From ddb15c409290ac5473ee36d5dc621a92f161cdfb Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Thu, 6 Jun 2024 15:05:45 +0200 Subject: basic gpt support Signed-off-by: Anna (navi) Figueiredo Gomes --- include/fs/gpt.h | 40 +++++++++++++++++++++++++++++++ meson.build | 1 + src/fs/gpt.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nrvn.c | 47 +++++++++++++++++++++++++++++++++---- 4 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 include/fs/gpt.h create mode 100644 src/fs/gpt.c diff --git a/include/fs/gpt.h b/include/fs/gpt.h new file mode 100644 index 0000000..a1a8356 --- /dev/null +++ b/include/fs/gpt.h @@ -0,0 +1,40 @@ +#ifndef _GPT_H_ +#define _GPT_H_ + +#include +#include + +struct gpt_header { + char sig[8]; + uint32_t revision; + uint32_t size; + uint32_t crc32; + uint32_t res; + uint64_t lba; + uint64_t lba_mirror; + uint64_t first_block; + uint64_t last_block; + uint8_t guid[16]; + uint64_t first_lba; + uint32_t number_partitions; + uint32_t size_partitions; + uint32_t crc32_entry; +}; + +struct gpt_entry { + uint8_t type[16]; + uint8_t guid[16]; + struct { + uint64_t start; + uint64_t end; + } lba; + uint64_t attrs; + char name[72]; +}; + +struct disk; +struct gpt_header *read_gpt_disk(struct disk *disk); +struct gpt_entry *get_gpt_entry(struct disk *disk, struct gpt_header *header, size_t num); +char *read_gpt_entry(struct disk *disk, struct gpt_entry *entry); + +#endif diff --git a/meson.build b/meson.build index 6393037..94f7334 100644 --- a/meson.build +++ b/meson.build @@ -26,6 +26,7 @@ files = [ 'src/ps2.c', 'src/ahci.c', 'src/vga.c', + 'src/fs/gpt.c', linker_script ] diff --git a/src/fs/gpt.c b/src/fs/gpt.c new file mode 100644 index 0000000..f9ff055 --- /dev/null +++ b/src/fs/gpt.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include + +struct gpt_header *read_gpt_disk(struct disk *disk) { + uint16_t *gpt = kmalloc(512); + if (!read(disk->port, 1, 1, gpt)) + return NULL; + struct gpt_header *part = (void*) gpt; + if (memcmp(part->sig, "EFI PART", 8) != 0) { + vga_puts("not gpt"); + return NULL; + } + vga_puts("found gpt table on disk 0\n"); + + vga_puts("number of partitions: "); + vga_putn(part->number_partitions); + vga_putc('\n'); + + vga_puts("starting lba: "); + vga_putn(part->first_lba); + vga_putc('\n'); + + vga_puts("size per entry: "); + vga_putn(part->size_partitions); + vga_putc('\n'); + + return part; +} + +struct gpt_entry *get_gpt_entry(struct disk *disk, struct gpt_header *header, size_t num) { + if (num >= header->number_partitions) + return NULL; + uint16_t *data = kmalloc(512); + if (!read(disk->port, header->first_lba + num, 1, data)) + return NULL; + struct gpt_entry *entry = (void *) data; + + /* + vga_puts("unique guid for first partition: "); + vga_putx(entry->guid); + vga_putc('\n'); + */ + + vga_puts("starting partition lba: "); + vga_putn(entry->lba.start); + vga_putc('\n'); + + vga_puts("ending partition lba: "); + vga_putn(entry->lba.end); + vga_putc('\n'); + + return entry; +} + +char *read_gpt_entry(struct disk *disk, struct gpt_entry *entry) { + uint16_t *data = kmalloc(512 * (entry->lba.end - entry->lba.start)); + uint16_t *ptr = data; + for (size_t lba = entry->lba.start; lba < entry->lba.end; lba += 1024) { + if (!read(disk->port, lba, entry->lba.end - lba < 1024 ? entry->lba.end - lba : 1024, ptr)) { + vga_puts("failed to read disk"); + kfree(data); + return NULL; + } + ptr += 1024 * 256; + } + + return (char *)data; +} diff --git a/src/nrvn.c b/src/nrvn.c index 66a59df..3fcbc41 100644 --- a/src/nrvn.c +++ b/src/nrvn.c @@ -8,20 +8,33 @@ #include #include #include +#include #include #include #include +#include + +#include /* Check if the compiler thinks you are targeting the wrong operating system. */ #if defined(__linux__) # error "You are not using a cross-compiler, you will most certainly run into trouble" #endif -/* This tutorial will only work for the 32-bit ix86 targets. */ #if !defined(__x86_64__) -# error "This tutorial needs to be compiled with a ix86-elf compiler" +# error "nrvn needs to be compiled with a x86_64 compiler" #endif +int oct2bin(char *str, int size) { + int n = 0; + while (size--) { + n *= 8; + n += *str - '0'; + str++; + } + return n; +} + void kernel_main(void) { vga_init(); vga_puts("hello world\n"); @@ -31,7 +44,6 @@ void kernel_main(void) { idt_init(); vga_puts("interrupt tables initialized\n"); - vga_puts("initializing the pic..."); pic_init(); vga_puts("pic initialized\n"); @@ -41,8 +53,6 @@ void kernel_main(void) { vga_puts("memory pages allocated\n"); } else { vga_puts("failed to allocate memory pages\n"); - asm volatile ("cli"); - asm volatile ("hlt"); } vga_puts("initializing ps/2...\n"); @@ -56,5 +66,32 @@ void kernel_main(void) { vga_puts("pci initialized.\n"); else vga_puts("pci initialization failed.\n"); + + struct disk *disk = get_disk(0); + + struct gpt_header *gpt = read_gpt_disk(disk); + if (!gpt) + while (1); + + struct gpt_entry *entry = get_gpt_entry(disk, gpt, 0); + if (!entry) + while (1); + + char *archive = read_gpt_entry(disk, entry); + while (!memcmp(archive + 257, "ustar", 5)) { + int size = oct2bin(archive + 0x7c, 11); + vga_puts(archive[156] == '0' ? "filename: " : "directory: "); + vga_puts(archive); + vga_puts(", size: "); + vga_putn(size); + vga_putc('\n'); + if (size > 0) { + vga_puts("contents: "); + vga_puts(archive + 512); + vga_putc('\n'); + } + archive += 512 + (size > 0 ? 512 : 0); + } + while (1); } -- cgit v1.2.3