75 lines
2.4 KiB
C++
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();
|
|
}
|
|
}
|