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) : 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 const char* type() const override { return "PATA"; }
virtual bool read(uint32_t lba, uint32_t sector_count, uint8_t* buffer) override; virtual bool read(uint32_t lba, uint32_t sector_count, uint8_t* buffer) override;
protected: protected:
@ -52,6 +54,7 @@ namespace Kernel
private: private:
bool m_lba_48 = false; bool m_lba_48 = false;
uint32_t m_sector_words = 256;
}; };

View File

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

View File

@ -125,8 +125,20 @@ namespace Kernel
uint16_t response[256]; uint16_t response[256];
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
response[i] = IO::inw(io_base() + ATA_IO_PORT_DATA); response[i] = IO::inw(io_base() + ATA_IO_PORT_DATA);
m_lba_48 = response[83] & (1 << 10); 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; return true;
} }
@ -158,7 +170,7 @@ namespace Kernel
// 7. Send the "READ SECTORS" command (0x20) to port 0x1F7: outb(0x1F7, 0x20) // 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); 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++) for (int i = 0; i < sector_count; i++)
{ {
// 8. Wait for an IRQ or poll. // 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. // 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.) // (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); uint16_t word = IO::inw(io_base() + ATA_IO_PORT_DATA);
buffer[i * 512 + j * 2 + 0] = word & 0xFF; buffer[(i * m_sector_words + j) * 2 + 0] = word & 0xFF;
buffer[i * 512 + j * 2 + 1] = word >> 8; 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. // 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; 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) if (memcmp(header.signature, "EFI PART", 8) != 0)
return false; return false;
if (header.revision != 0x00010000) if (header.revision != 0x00010000)
return false; return false;
if (header.size < 92 || header.size > 512) if (header.size < 92 || header.size > sector_size)
return false; return false;
if (header.my_lba != 1) if (header.my_lba != 1)
return false; return false;
return true; 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]; memset(lba1.data() + 16, 0, 4);
memcpy(lba1_copy, lba1, 512); if (header.crc32 != crc32_checksum(lba1.data(), header.size))
memset(lba1_copy + 16, 0, 4);
if (header.crc32 != crc32_checksum(lba1_copy, header.size))
return false; 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 false;
return true; return true;
} }
static GPTHeader parse_gpt_header(const uint8_t* lba1) static GPTHeader parse_gpt_header(const BAN::Vector<uint8_t> lba1)
{ {
GPTHeader header; GPTHeader header;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
memcpy(header.signature, lba1, 8); memcpy(header.signature, lba1.data(), 8);
memcpy(header.guid, lba1 + 56, 16); memcpy(header.guid, lba1.data() + 56, 16);
header.revision = little_endian_to_host<uint32_t>(lba1 + 8); header.revision = little_endian_to_host<uint32_t>(lba1.data() + 8);
header.size = little_endian_to_host<uint32_t>(lba1 + 12); header.size = little_endian_to_host<uint32_t>(lba1.data() + 12);
header.crc32 = little_endian_to_host<uint32_t>(lba1 + 16); header.crc32 = little_endian_to_host<uint32_t>(lba1.data() + 16);
header.my_lba = little_endian_to_host<uint64_t>(lba1 + 24); header.my_lba = little_endian_to_host<uint64_t>(lba1.data() + 24);
header.first_lba = little_endian_to_host<uint64_t>(lba1 + 40); header.first_lba = little_endian_to_host<uint64_t>(lba1.data() + 40);
header.last_lba = little_endian_to_host<uint64_t>(lba1 + 48); header.last_lba = little_endian_to_host<uint64_t>(lba1.data() + 48);
header.partition_entry_lba = little_endian_to_host<uint64_t>(lba1 + 72); header.partition_entry_lba = little_endian_to_host<uint64_t>(lba1.data() + 72);
header.partition_entry_count = little_endian_to_host<uint32_t>(lba1 + 80); header.partition_entry_count = little_endian_to_host<uint32_t>(lba1.data() + 80);
header.partition_entry_size = little_endian_to_host<uint32_t>(lba1 + 84); 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 + 88); header.partition_entry_array_crc32 = little_endian_to_host<uint32_t>(lba1.data() + 88);
return header; return header;
} }
bool DiskDevice::initialize_partitions() bool DiskDevice::initialize_partitions()
{ {
uint8_t lba1[512]; BAN::Vector<uint8_t> lba1(sector_size());
if (!read(1, 1, lba1)) if (!read(1, 1, lba1.data()))
return false; return false;
GPTHeader header = parse_gpt_header(lba1); GPTHeader header = parse_gpt_header(lba1);
if (!is_valid_gpt_header(header)) if (!is_valid_gpt_header(header, sector_size()))
{ {
dprintln("invalid gpt header"); dprintln("invalid gpt header");
return false; 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 bytes = header.partition_entry_count * header.partition_entry_size;
uint32_t sectors = (bytes + 511) / 512; uint32_t sectors = (bytes + sector_size() - 1) / sector_size();
entry_array = (uint8_t*)kmalloc(sectors * 512); MUST(entry_array.resize(sectors * sector_size()));
if (entry_array == nullptr) if (!read(header.partition_entry_lba, sectors, entry_array.data()))
return false; 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)) 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++) 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; Partition partition;
memcpy(partition.type_guid, partition_data, 16); memcpy(partition.type_guid, partition_data, 16);