Luna/kernel/src/fs/GPT.cpp

75 lines
2.4 KiB
C++

#include "fs/GPT.h"
#include <luna/CRC32.h>
static const u8 null_guid[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
namespace GPT
{
Result<bool> identify(SharedPtr<Device> device)
{
if (!device->is_block_device()) return false;
Header header;
// The header is at LBA 1.
usize nread = TRY(device->read((u8*)&header, 1 * GPT_SECTOR_SIZE, sizeof(header)));
check(nread == sizeof(header));
if (memcmp(header.signature, GPT_SIGNATURE, GPT_SIGNATURE_LENGTH)) return false;
kinfoln("gpt: Found GUID partition table on device %s, revision %#.8x, with space for %d partition entries!",
device->device_path().chars(), header.revision, header.num_partitions);
if (header.revision != GPT_REVISION)
{
kwarnln("gpt: GUID partition table revision not supported!");
return false;
}
check(header.hdr_size == 0x5c);
check(header.reserved == 0);
check(header.this_lba == 1);
const u32 chksum = checksum_gpt(header);
if (chksum != header.checksum)
{
kwarnln("gpt: Header checksum does not match, %#.8x != %#.8x!", chksum, header.checksum);
return false;
}
u64 partition_table_start = header.partition_table_lba * GPT_SECTOR_SIZE;
u32 partition_index = 1;
auto* table = (PartitionEntry*)TRY(calloc_impl(header.num_partitions, sizeof(PartitionEntry)));
auto guard = make_scope_guard([table] { free_impl(table); });
nread = TRY(device->read((u8*)table, partition_table_start, sizeof(PartitionEntry) * header.num_partitions));
check(nread == sizeof(PartitionEntry) * header.num_partitions);
for (u32 i = 0; i < header.num_partitions; i++)
{
PartitionEntry& entry = table[i];
if (!memcmp(entry.type_guid, null_guid, 16)) continue;
kinfoln("gpt: Partition entry #%u is active: start=%lu, end=%lu", i, entry.start_lba, entry.end_lba);
TRY(MBR::PartitionDevice::create(device, entry.start_lba, entry.end_lba - entry.start_lba,
partition_index++));
}
return true;
}
u32 checksum_gpt(Header header)
{
header.checksum = 0;
CRC32 crc;
crc.append((u8*)&header, 0x5c);
return crc.digest();
}
}