From 4ed4fc9e5100c88c7f2c74af764c2dde0f1179ce Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Fri, 23 Feb 2018 22:31:26 +0100 Subject: [PATCH] Add GUID Partition Table support And enable it on dragon-nx32. Signed-off-by: Tormod Volden --- Kernel/dev/gpt.c | 105 +++++++++++++++++++++++++++ Kernel/dev/gpt.h | 48 ++++++++++++ Kernel/dev/mbr.c | 25 +++---- Kernel/dev/mbr.h | 20 ++++- Kernel/platform-dragon-nx32/config.h | 2 + 5 files changed, 183 insertions(+), 17 deletions(-) create mode 100644 Kernel/dev/gpt.c create mode 100644 Kernel/dev/gpt.h diff --git a/Kernel/dev/gpt.c b/Kernel/dev/gpt.c new file mode 100644 index 00000000..d3475103 --- /dev/null +++ b/Kernel/dev/gpt.c @@ -0,0 +1,105 @@ +/* + * Copyright 2018 Tormod Volden + * + */ + +#include +#include +#include +#include +#include "mbr.h" +#include "gpt.h" + +#ifdef CONFIG_GPT + +void kputs_utf16le(uint8_t *s) +{ + int i; + for (i = 0; s[i] || s[i+1]; i += 2) { + if (s[i+1]) + kputchar('!'); + else + kputchar(s[i] & 0x7f); + } +} + +int parse_gpt_part_entry(gpt_partition_entry_t *entry, uint8_t next) +{ + int i; + uint8_t zero_check = 0; + for (i = 0; i < 16; i++) + zero_check |= entry->type_guid[i]; + if (zero_check == 0) + return 0; + if (entry->last_lba_msb != 0) { + kputs("Partition out of reach\n"); + return 0; + } + + blk_op.blkdev->lba_first[next] = le32_to_cpu(entry->first_lba_lsb); + blk_op.blkdev->lba_count[next] = le32_to_cpu(entry->last_lba_lsb) - le32_to_cpu(entry->first_lba_lsb); + + kprintf("%d ", next + 1); + + /* on the verbose side */ + /* kprintf("(%lx-%lx) ", le32_to_cpu(entry->first_lba_lsb), le32_to_cpu(entry->last_lba_lsb)); */ + + /* only print first bits of type guid, in conventional order */ + for (i = 3; i >= 0; i--) + kprintf("%2x", entry->type_guid[i]); + kputchar(' '); + kputs_utf16le(entry->part_name); + kputchar('\n'); + + return 1; /* count me */ +} + +void parse_gpt(uint8_t *buf, uint8_t i_mbr) +{ + int i; + uint32_t entry_block; + int num_part; + gpt_header_t *gpt_header = (gpt_header_t*) buf; + uint8_t next = 0; + uint8_t counted; + + kputs("GPT:\n"); + + /* read block 1 into buffer, mbr.c has set it all up */ + blk_op.lba = 1; + blk_op.blkdev->transfer(); + + if (strcmp((const char *) gpt_header->signature, "EFI PART")) { + kputs("No valid GPT header in block 1\n"); + /* TODO look for backup header */ + return; + } + + if (gpt_header->table_starting_lba_msb != 0) { + kputs("GPT out of reach\n"); + return; + } + + entry_block = le32_to_cpu(gpt_header->table_starting_lba_lsb); + + if (le32_to_cpu(gpt_header->size_part_entry) != 128) { + kputs("Unsupported GPT entry size\n"); + return; + } + + num_part = (int) le32_to_cpu(gpt_header->num_part_entries); + + for (i = 0; i < num_part && next < MAX_PARTITIONS; i++) { + gpt_partition_entry_t *entry; + /* each block has 4 partition entries */ + if (i % 4 == 0) { + blk_op.lba = entry_block++; + blk_op.blkdev->transfer(); + } + entry = (gpt_partition_entry_t *) buf + (i % 4); + counted = parse_gpt_part_entry(entry, next); + next += counted; + } +} + +#endif /* CONFIG_GPT */ diff --git a/Kernel/dev/gpt.h b/Kernel/dev/gpt.h new file mode 100644 index 00000000..4e633cbc --- /dev/null +++ b/Kernel/dev/gpt.h @@ -0,0 +1,48 @@ +#ifndef __GPT_DOT_H__ +#define __GPT_DOT_H__ + +/* Copyright 2018 Tormod Volden */ + +#define MBR_GPT_PROTECTED_TYPE 0xEE + +/* FUZIX root partition type */ +#define GPT_FUZIX_ROOT_UUID 63ce1ba5-46ab-49bd-abf4-2859975849e1 +#define GPT_FUZIX_ROOT_UUID_16BIT 1ba5 + +typedef struct __attribute((packed)) { + uint8_t signature[8]; + uint32_t revision; + uint32_t header_size; + uint32_t header_crc; + uint8_t reserved[4]; + uint32_t current_lba_lsb; /* 64 bit LSB */ + uint32_t current_lba_msb; + uint32_t backup_lba_lsb; + uint32_t backup_lba_msb; + uint32_t first_usable_lba_lsb; + uint32_t first_usable_lba_msb; + uint32_t last_usable_lba_lsb; + uint32_t last_usable_lba_msb; + uint8_t disk_guid[16]; + uint32_t table_starting_lba_lsb; + uint32_t table_starting_lba_msb; + uint32_t num_part_entries; + uint32_t size_part_entry; + uint32_t crc_part_array; + /* reserved to end of block */ +} gpt_header_t; + +typedef struct __attribute((packed)) { + uint8_t type_guid[16]; + uint8_t uniq_part_guid[16]; + uint32_t first_lba_lsb; + uint32_t first_lba_msb; + uint32_t last_lba_lsb; + uint32_t last_lba_msb; + uint8_t attr_flags[8]; + uint8_t part_name[72]; /* 36 UTF_16LE */ +} gpt_partition_entry_t; + +void parse_gpt(uint8_t *buf, uint8_t i_mbr); + +#endif /* __GPT_DOT_H__ */ diff --git a/Kernel/dev/mbr.c b/Kernel/dev/mbr.c index bef5aef2..38f51872 100644 --- a/Kernel/dev/mbr.c +++ b/Kernel/dev/mbr.c @@ -5,22 +5,8 @@ #include #include #include - -typedef struct { - /* Described this way so that it packs */ - uint8_t status_chs_first[4]; - uint8_t type_chs_last[4]; - uint32_t lba_first; - uint32_t lba_count; -} partition_table_entry_t; - -#define MBR_ENTRY_COUNT 4 -#define MBR_SIGNATURE 0xAA55 -typedef struct { - uint8_t bootcode[446]; - partition_table_entry_t partition[MBR_ENTRY_COUNT]; - uint16_t signature; -} boot_record_t; +#include "mbr.h" +#include "gpt.h" void mbr_parse(char letter) { @@ -70,6 +56,12 @@ void mbr_parse(char letter) for(i=0; ipartition[i].type_chs_last[0]){ +#ifdef CONFIG_GPT + case MBR_GPT_PROTECTED_TYPE: + // TODO assert next is zero (unless hybrid...) + parse_gpt((uint8_t *) br, i); + goto out; +#endif case 0: break; case 0x05: @@ -100,6 +92,7 @@ void mbr_parse(char letter) if(ep_offset && next >= 4) kputs("> "); +out: /* release temporary memory */ tmpfree(br); } diff --git a/Kernel/dev/mbr.h b/Kernel/dev/mbr.h index e728803e..06cbe17a 100644 --- a/Kernel/dev/mbr.h +++ b/Kernel/dev/mbr.h @@ -1,6 +1,24 @@ #ifndef __MBR_DOT_H__ #define __MBR_DOT_H__ +/* 2015-01-04 Will Sowerbutts */ + +typedef struct __attribute((packed)) { + /* Described this way so that it packs */ + uint8_t status_chs_first[4]; + uint8_t type_chs_last[4]; + uint32_t lba_first; + uint32_t lba_count; +} partition_table_entry_t; + +#define MBR_ENTRY_COUNT 4 +#define MBR_SIGNATURE 0xAA55 +typedef struct __attribute((packed)) { + uint8_t bootcode[446]; + partition_table_entry_t partition[MBR_ENTRY_COUNT]; + uint16_t signature; +} boot_record_t; + void mbr_parse(char letter); -#endif +#endif /* __MBR_DOT_H__ */ diff --git a/Kernel/platform-dragon-nx32/config.h b/Kernel/platform-dragon-nx32/config.h index 2bf53a73..2003cc2e 100644 --- a/Kernel/platform-dragon-nx32/config.h +++ b/Kernel/platform-dragon-nx32/config.h @@ -33,6 +33,8 @@ #define CONFIG_SD /* enable if SD interface present */ #define CONFIG_IDE /* enable if IDE interface present */ +#define CONFIG_GPT + /* Video terminal, not a serial tty */ #define CONFIG_VT #define CONFIG_FONT8X8 -- 2.34.1