From 74949401bd294ebe3ee7bf9cf5b58a45a3db1375 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 23 Mar 2023 11:13:14 +0200 Subject: [PATCH] Kernel: Cleanup GPT parsing code --- BAN/include/BAN/UTF8.h | 51 ++++++-- kernel/include/kernel/Storage/StorageDevice.h | 2 +- kernel/kernel/Font.cpp | 4 +- kernel/kernel/Storage/StorageDevice.cpp | 117 ++++++------------ 4 files changed, 84 insertions(+), 90 deletions(-) diff --git a/BAN/include/BAN/UTF8.h b/BAN/include/BAN/UTF8.h index d712a39546..f2a127a055 100644 --- a/BAN/include/BAN/UTF8.h +++ b/BAN/include/BAN/UTF8.h @@ -3,15 +3,12 @@ #include #include -namespace BAN +namespace BAN::UTF8 { - namespace UTF8 - { - static constexpr uint32_t invalid = 0xFFFFFFFF; - } + static constexpr uint32_t invalid = 0xFFFFFFFF; - static constexpr uint32_t utf8_byte_length(uint8_t first_byte) + constexpr uint32_t byte_length(uint8_t first_byte) { if ((first_byte & 0x80) == 0x00) return 1; @@ -24,9 +21,9 @@ namespace BAN return 0; } - static constexpr uint32_t utf8_to_codepoint(uint8_t* bytes) + constexpr uint32_t to_codepoint(uint8_t* bytes) { - uint32_t length = utf8_byte_length(bytes[0]); + uint32_t length = byte_length(bytes[0]); for (uint32_t i = 1; i < length; i++) if ((bytes[i] & 0xC0) != 0x80) @@ -43,4 +40,42 @@ namespace BAN return UTF8::invalid; } + template + constexpr bool from_codepoints(const T* codepoints, size_t count, char* out) + { + uint8_t* ptr = (uint8_t*)out; + + for (size_t i = 0; i < count; i++) + { + if (codepoints[i] < 0x80) + { + *ptr++ = codepoints[i]; + } + else if (codepoints[i] < 0x800) + { + *ptr++ = 0xC0 | ((codepoints[i] >> 6) & 0x1F); + *ptr++ = 0x80 | ((codepoints[i] >> 0) & 0x3F); + } + else if (codepoints[i] < 0x10000) + { + *ptr++ = 0xE0 | ((codepoints[i] >> 12) & 0x0F); + *ptr++ = 0x80 | ((codepoints[i] >> 6) & 0x3F); + *ptr++ = 0x80 | ((codepoints[i] >> 0) & 0x3F); + } + else if (codepoints[i] < 0x110000) + { + *ptr++ = 0xF0 | ((codepoints[i] >> 18) & 0x07); + *ptr++ = 0x80 | ((codepoints[i] >> 12) & 0x3F); + *ptr++ = 0x80 | ((codepoints[i] >> 6) & 0x3F); + *ptr++ = 0x80 | ((codepoints[i] >> 0) & 0x3F); + } + else + { + return false; + } + } + + return true; + } + } \ No newline at end of file diff --git a/kernel/include/kernel/Storage/StorageDevice.h b/kernel/include/kernel/Storage/StorageDevice.h index f333d21c94..769e0e4346 100644 --- a/kernel/include/kernel/Storage/StorageDevice.h +++ b/kernel/include/kernel/Storage/StorageDevice.h @@ -38,7 +38,7 @@ namespace Kernel const uint64_t m_lba_start; const uint64_t m_lba_end; const uint64_t m_attributes; - char m_name[36 * 3 + 1]; + char m_name[36 * 4 + 1]; }; public: diff --git a/kernel/kernel/Font.cpp b/kernel/kernel/Font.cpp index 4bf8c7937d..ef1e3c99ed 100644 --- a/kernel/kernel/Font.cpp +++ b/kernel/kernel/Font.cpp @@ -202,7 +202,7 @@ namespace Kernel ASSERT(byte_index < 4); bytes[byte_index++] = byte; - uint32_t len = BAN::utf8_byte_length(bytes[0]); + uint32_t len = BAN::UTF8::byte_length(bytes[0]); if (len == 0) { @@ -211,7 +211,7 @@ namespace Kernel } else if (len == byte_index) { - uint32_t codepoint = BAN::utf8_to_codepoint(bytes); + uint32_t codepoint = BAN::UTF8::to_codepoint(bytes); if (codepoint == BAN::UTF8::invalid) invalid_utf = true; else if (glyph_offsets.contains(codepoint)) diff --git a/kernel/kernel/Storage/StorageDevice.cpp b/kernel/kernel/Storage/StorageDevice.cpp index feb94746ed..c63b62566b 100644 --- a/kernel/kernel/Storage/StorageDevice.cpp +++ b/kernel/kernel/Storage/StorageDevice.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include #include @@ -14,21 +16,33 @@ namespace Kernel struct GPTHeader { - char signature[8]; - uint32_t revision; - uint32_t size; - uint32_t crc32; - uint64_t my_lba; - uint64_t first_lba; - uint64_t last_lba; - GUID guid; - uint64_t partition_entry_lba; - uint32_t partition_entry_count; - uint32_t partition_entry_size; - uint32_t partition_entry_array_crc32; + char signature[8]; + BAN::LittleEndian revision; + BAN::LittleEndian size; + BAN::LittleEndian crc32; + BAN::LittleEndian reserved; + BAN::LittleEndian my_lba; + BAN::LittleEndian alternate_lba; + BAN::LittleEndian first_usable_lba; + BAN::LittleEndian last_usable_lba; + GUID disk_guid; + BAN::LittleEndian partition_entry_lba; + BAN::LittleEndian partition_entry_count; + BAN::LittleEndian partition_entry_size; + BAN::LittleEndian partition_entry_array_crc32; }; - uint32_t crc32_table[256] = + struct PartitionEntry + { + GUID partition_type_guid; + GUID unique_partition_guid; + BAN::LittleEndian starting_lba; + BAN::LittleEndian ending_lba; + BAN::LittleEndian attributes; + BAN::LittleEndian partition_name[36]; + } __attribute__((packed)); + + static uint32_t crc32_table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, @@ -107,16 +121,6 @@ namespace Kernel return crc32 ^ 0xFFFFFFFF; } - static GUID parse_guid(const uint8_t* guid) - { - GUID result; - result.data1 = BAN::Math::big_endian_to_host(guid + 0); - result.data2 = BAN::Math::big_endian_to_host(guid + 4); - result.data3 = BAN::Math::big_endian_to_host(guid + 6); - memcpy(result.data4, guid + 8, 8); - return result; - } - static bool is_valid_gpt_header(const GPTHeader& header, uint32_t sector_size) { if (memcmp(header.signature, "EFI PART", 8) != 0) @@ -140,58 +144,12 @@ namespace Kernel return true; } - static GPTHeader parse_gpt_header(const BAN::Vector& lba1) - { - GPTHeader header; - memset(&header, 0, sizeof(header)); - - memcpy(header.signature, lba1.data(), 8); - header.revision = BAN::Math::little_endian_to_host(lba1.data() + 8); - header.size = BAN::Math::little_endian_to_host(lba1.data() + 12); - header.crc32 = BAN::Math::little_endian_to_host(lba1.data() + 16); - header.my_lba = BAN::Math::little_endian_to_host(lba1.data() + 24); - header.first_lba = BAN::Math::little_endian_to_host(lba1.data() + 40); - header.last_lba = BAN::Math::little_endian_to_host(lba1.data() + 48); - header.guid = parse_guid(lba1.data() + 56); - header.partition_entry_lba = BAN::Math::little_endian_to_host(lba1.data() + 72); - header.partition_entry_count = BAN::Math::little_endian_to_host(lba1.data() + 80); - header.partition_entry_size = BAN::Math::little_endian_to_host(lba1.data() + 84); - header.partition_entry_array_crc32 = BAN::Math::little_endian_to_host(lba1.data() + 88); - return header; - } - - static void utf8_encode(const uint16_t* codepoints, size_t count, char* out) - { - uint32_t len = 0; - while (*codepoints && count--) - { - uint16_t cp = *codepoints; - if (cp < 128) - { - out[len++] = cp & 0x7F; - } - else if (cp < 2048) - { - out[len++] = 0xC0 | ((cp >> 0x6) & 0x1F); - out[len++] = 0x80 | (cp & 0x3F); - } - else - { - out[len++] = 0xE0 | ((cp >> 0xC) & 0x0F); - out[len++] = 0x80 | ((cp >> 0x6) & 0x3F); - out[len++] = 0x80 | (cp & 0x3F); - } - codepoints++; - } - out[len] = 0; - } - BAN::ErrorOr StorageDevice::initialize_partitions() { BAN::Vector lba1(sector_size()); TRY(read_sectors(1, 1, lba1.data())); - GPTHeader header = parse_gpt_header(lba1); + const GPTHeader& header = *(const GPTHeader*)lba1.data(); if (!is_valid_gpt_header(header, sector_size())) return BAN::Error::from_c_string("Invalid GPT header"); @@ -199,7 +157,8 @@ namespace Kernel if (uint32_t remainder = size % sector_size()) size += sector_size() - remainder; - BAN::Vector entry_array(size); + BAN::Vector entry_array; + TRY(entry_array.resize(size)); TRY(read_sectors(header.partition_entry_lba, size / sector_size(), entry_array.data())); if (!is_valid_gpt_crc32(header, lba1, entry_array)) @@ -207,18 +166,18 @@ namespace Kernel for (uint32_t i = 0; i < header.partition_entry_count; i++) { - uint8_t* partition_data = entry_array.data() + header.partition_entry_size * i; + const PartitionEntry& entry = *(const PartitionEntry*)(entry_array.data() + header.partition_entry_size * i); - char utf8_name[36 * 3 + 1]; // 36 16-bit codepoints + nullbyte - utf8_encode((uint16_t*)(partition_data + 56), header.partition_entry_size - 56, utf8_name); + char utf8_name[36 * 4 + 1]; + BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name); MUST(m_partitions.emplace_back( *this, - parse_guid(partition_data + 0), - parse_guid(partition_data + 16), - BAN::Math::little_endian_to_host(partition_data + 32), - BAN::Math::little_endian_to_host(partition_data + 40), - BAN::Math::little_endian_to_host(partition_data + 48), + entry.partition_type_guid, + entry.unique_partition_guid, + entry.starting_lba, + entry.ending_lba, + entry.attributes, utf8_name )); }