#include "fs/GPT.h" #include static const u8 null_guid[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; namespace GPT { Result identify(SharedPtr 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); #if 0 const u32 chksum = checksum_gpt(header); if (chksum != header.checksum) { kwarnln("gpt: Header checksum does not match, %#.8x != %#.8x!", chksum, header.checksum); return false; } #endif u64 partition_table_start = header.partition_table_lba * GPT_SECTOR_SIZE; u32 partition_index = 1; auto* table = TRY(make_array(header.num_partitions)); auto guard = make_scope_guard([table] { delete[] 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; return CRC32::checksum((u8*)&header, 0x5c); } }