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:
parent
7f12a7050a
commit
8f1b6da2af
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue