Kernel: Use Vector instead of raw poiters in Disk stuff

We now don't have to manually free allocated data
This commit is contained in:
Bananymous 2023-02-16 20:48:41 +02:00
parent 7f12a7050a
commit 8f1b6da2af
4 changed files with 47 additions and 38 deletions

View File

@ -38,7 +38,9 @@ namespace Kernel
: ATADevice(io_base, ctl_base, slave_bit)
{}
virtual uint32_t sector_size() const override { return m_sector_words * 2; }
virtual const char* type() const override { return "PATA"; }
virtual bool read(uint32_t lba, uint32_t sector_count, uint8_t* buffer) override;
protected:
@ -52,6 +54,7 @@ namespace Kernel
private:
bool m_lba_48 = false;
uint32_t m_sector_words = 256;
};

View File

@ -25,6 +25,7 @@ namespace Kernel
bool initialize_partitions();
virtual bool read(uint32_t lba, uint32_t sector_count, uint8_t* buffer) = 0;
virtual uint32_t sector_size() const = 0;
private:
BAN::Vector<Partition> m_partitions;

View File

@ -125,8 +125,20 @@ namespace Kernel
uint16_t response[256];
for (int i = 0; i < 256; i++)
response[i] = IO::inw(io_base() + ATA_IO_PORT_DATA);
m_lba_48 = response[83] & (1 << 10);
if (!(response[106] & (1 << 15))
&& (response[106] & (1 << 14))
&& (response[106] & (1 << 12)))
{
m_sector_words = ((uint32_t)response[117] << 16) | response[118];
dprintln("using {} sector size", m_sector_words * 2);
}
return true;
}
@ -158,7 +170,7 @@ namespace Kernel
// 7. Send the "READ SECTORS" command (0x20) to port 0x1F7: outb(0x1F7, 0x20)
IO::outb(io_base() + ATA_IO_PORT_COMMAND, ATA_COMMAND_READ_SECTORS);
memset(buffer, 0, sector_count * 256 * sizeof(uint16_t));
memset(buffer, 0, sector_count * m_sector_words * sizeof(uint16_t));
for (int i = 0; i < sector_count; i++)
{
// 8. Wait for an IRQ or poll.
@ -167,11 +179,11 @@ namespace Kernel
// 9. Transfer 256 16-bit values, a uint16_t at a time, into your buffer from I/O port 0x1F0.
// (In assembler, REP INSW works well for this.)
for (int j = 0; j < 256; j++)
for (size_t j = 0; j < m_sector_words; j++)
{
uint16_t word = IO::inw(io_base() + ATA_IO_PORT_DATA);
buffer[i * 512 + j * 2 + 0] = word & 0xFF;
buffer[i * 512 + j * 2 + 1] = word >> 8;
buffer[(i * m_sector_words + j) * 2 + 0] = word & 0xFF;
buffer[(i * m_sector_words + j) * 2 + 1] = word >> 8;
}
// 10. Then loop back to waiting for the next IRQ (or poll again -- see next note) for each successive sector.

View File

@ -114,76 +114,69 @@ namespace Kernel
return result;
}
static bool is_valid_gpt_header(const GPTHeader& header)
static bool is_valid_gpt_header(const GPTHeader& header, uint32_t sector_size)
{
if (memcmp(header.signature, "EFI PART", 8) != 0)
return false;
if (header.revision != 0x00010000)
return false;
if (header.size < 92 || header.size > 512)
if (header.size < 92 || header.size > sector_size)
return false;
if (header.my_lba != 1)
return false;
return true;
}
static bool is_valid_gpt_crc32(const GPTHeader& header, const uint8_t* lba1, const uint8_t* entry_array)
static bool is_valid_gpt_crc32(const GPTHeader& header, BAN::Vector<uint8_t> lba1, const BAN::Vector<uint8_t>& entry_array)
{
uint8_t lba1_copy[512];
memcpy(lba1_copy, lba1, 512);
memset(lba1_copy + 16, 0, 4);
if (header.crc32 != crc32_checksum(lba1_copy, header.size))
memset(lba1.data() + 16, 0, 4);
if (header.crc32 != crc32_checksum(lba1.data(), header.size))
return false;
if (header.partition_entry_array_crc32 != crc32_checksum(entry_array, header.partition_entry_count * header.partition_entry_size))
if (header.partition_entry_array_crc32 != crc32_checksum(entry_array.data(), header.partition_entry_count * header.partition_entry_size))
return false;
return true;
}
static GPTHeader parse_gpt_header(const uint8_t* lba1)
static GPTHeader parse_gpt_header(const BAN::Vector<uint8_t> lba1)
{
GPTHeader header;
memset(&header, 0, sizeof(header));
memcpy(header.signature, lba1, 8);
memcpy(header.guid, lba1 + 56, 16);
header.revision = little_endian_to_host<uint32_t>(lba1 + 8);
header.size = little_endian_to_host<uint32_t>(lba1 + 12);
header.crc32 = little_endian_to_host<uint32_t>(lba1 + 16);
header.my_lba = little_endian_to_host<uint64_t>(lba1 + 24);
header.first_lba = little_endian_to_host<uint64_t>(lba1 + 40);
header.last_lba = little_endian_to_host<uint64_t>(lba1 + 48);
header.partition_entry_lba = little_endian_to_host<uint64_t>(lba1 + 72);
header.partition_entry_count = little_endian_to_host<uint32_t>(lba1 + 80);
header.partition_entry_size = little_endian_to_host<uint32_t>(lba1 + 84);
header.partition_entry_array_crc32 = little_endian_to_host<uint32_t>(lba1 + 88);
memcpy(header.signature, lba1.data(), 8);
memcpy(header.guid, lba1.data() + 56, 16);
header.revision = little_endian_to_host<uint32_t>(lba1.data() + 8);
header.size = little_endian_to_host<uint32_t>(lba1.data() + 12);
header.crc32 = little_endian_to_host<uint32_t>(lba1.data() + 16);
header.my_lba = little_endian_to_host<uint64_t>(lba1.data() + 24);
header.first_lba = little_endian_to_host<uint64_t>(lba1.data() + 40);
header.last_lba = little_endian_to_host<uint64_t>(lba1.data() + 48);
header.partition_entry_lba = little_endian_to_host<uint64_t>(lba1.data() + 72);
header.partition_entry_count = little_endian_to_host<uint32_t>(lba1.data() + 80);
header.partition_entry_size = little_endian_to_host<uint32_t>(lba1.data() + 84);
header.partition_entry_array_crc32 = little_endian_to_host<uint32_t>(lba1.data() + 88);
return header;
}
bool DiskDevice::initialize_partitions()
{
uint8_t lba1[512];
if (!read(1, 1, lba1))
BAN::Vector<uint8_t> lba1(sector_size());
if (!read(1, 1, lba1.data()))
return false;
GPTHeader header = parse_gpt_header(lba1);
if (!is_valid_gpt_header(header))
if (!is_valid_gpt_header(header, sector_size()))
{
dprintln("invalid gpt header");
return false;
}
uint8_t* entry_array = nullptr;
BAN::Vector<uint8_t> entry_array;
{
uint32_t bytes = header.partition_entry_count * header.partition_entry_size;
uint32_t sectors = (bytes + 511) / 512;
entry_array = (uint8_t*)kmalloc(sectors * 512);
if (entry_array == nullptr)
uint32_t sectors = (bytes + sector_size() - 1) / sector_size();
MUST(entry_array.resize(sectors * sector_size()));
if (!read(header.partition_entry_lba, sectors, entry_array.data()))
return false;
if (!read(header.partition_entry_lba, sectors, entry_array))
{
kfree(entry_array);
return false;
}
}
if (!is_valid_gpt_crc32(header, lba1, entry_array))
@ -194,7 +187,7 @@ namespace Kernel
for (uint32_t i = 0; i < header.partition_entry_count; i++)
{
uint8_t* partition_data = entry_array + header.partition_entry_size * i;
uint8_t* partition_data = entry_array.data() + header.partition_entry_size * i;
Partition partition;
memcpy(partition.type_guid, partition_data, 16);