:: commit 038c0412085a66a286561ffa2e5fe8b9aedd74a7

mintsuki <mintsuki@protonmail.com> — 2020-11-01 20:25

parents: 28c1538f94

Add GUID resource type

diff --git a/CONFIG.md b/CONFIG.md
index 5a4e2fd7..8c7a1397 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -63,3 +63,4 @@ The format for `root` changes depending on the resource used.
 
 A resource can be one of the following:
 * `bios` - The `root` takes the form of `drive:partition`; for example: `bios://3:1/...` would use BIOS drive 3, partition 1. Partitions and BIOS drives are both 1-based. Omitting the drive is possible; for example: `bios://:2/...`. Omitting the drive makes Limine use the boot drive.
+* `guid` - The `root` takes the form of a GUID/UUID, such as `736b5698-5ae1-4dff-be2c-ef8f44a61c52`. It is a filesystem GUID and not a partition GUID.
diff --git a/Makefile b/Makefile
index 82c7b262..d921cbfe 100644
--- a/Makefile
+++ b/Makefile
@@ -43,9 +43,11 @@ test.img:
 
 echfs-test: limine-install test.img
 	$(MAKE) -C test
-	echfs-utils -m -p0 test.img quick-format 512
+	echfs-utils -m -p0 test.img quick-format 512 > part_guid
+	sed "s/@GUID@/`cat part_guid`/g" < test/limine.cfg > limine.cfg.tmp
+	echfs-utils -m -p0 test.img import limine.cfg.tmp limine.cfg
+	rm -f limine.cfg.tmp part_guid
 	echfs-utils -m -p0 test.img import test/test.elf boot/test.elf
-	echfs-utils -m -p0 test.img import test/limine.cfg limine.cfg
 	echfs-utils -m -p0 test.img import test/bg.bmp bg.bmp
 	./limine-install limine.bin test.img
 	qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.img -debugcon stdio
diff --git a/limine.bin b/limine.bin
index 5663b1ba..4ed50dc9 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/fs/echfs.c b/stage2/fs/echfs.c
index 258be885..806f6370 100644
--- a/stage2/fs/echfs.c
+++ b/stage2/fs/echfs.c
@@ -13,6 +13,8 @@ struct echfs_identity_table {
     uint64_t block_count;
     uint64_t dir_length;
     uint64_t block_size;
+    uint32_t reserved;
+    struct guid guid;
 } __attribute__((packed));
 
 #define ROOT_DIR_ID  (~((uint64_t)0))
@@ -40,14 +42,9 @@ int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t
     return 0;
 }
 
-int echfs_check_signature(int disk, int partition) {
-    struct part part;
-    if (get_part(&part, disk, partition)) {
-        panic("Invalid partition");
-    }
-
+int echfs_check_signature(struct part *part) {
     struct echfs_identity_table id_table;
-    read_partition(disk, &part, &id_table, 0, sizeof(struct echfs_identity_table));
+    read_partition(part->drive, part, &id_table, 0, sizeof(struct echfs_identity_table));
 
     if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
         return 0;
@@ -56,6 +53,19 @@ int echfs_check_signature(int disk, int partition) {
     return 1;
 }
 
+bool echfs_get_guid(struct guid *guid, struct part *part) {
+    struct echfs_identity_table id_table;
+    read_partition(part->drive, part, &id_table, 0, sizeof(struct echfs_identity_table));
+
+    if (strncmp(id_table.signature, "_ECH_FS_", 8)) {
+        return false;
+    }
+
+    *guid = id_table.guid;
+
+    return true;
+}
+
 int echfs_open(struct echfs_file_handle *ret, int disk, int partition, const char *path) {
     const char *fullpath = path;
 
diff --git a/stage2/fs/echfs.h b/stage2/fs/echfs.h
index 5899afd7..a3eb7b3e 100644
--- a/stage2/fs/echfs.h
+++ b/stage2/fs/echfs.h
@@ -2,7 +2,9 @@
 #define __FS__ECHFS_H__
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <lib/part.h>
+#include <lib/blib.h>
 
 struct echfs_dir_entry {
     uint64_t parent_id;
@@ -31,7 +33,8 @@ struct echfs_file_handle {
     struct echfs_dir_entry dir_entry;
 };
 
-int echfs_check_signature(int disk, int partition);
+int echfs_check_signature(struct part *part);
+bool echfs_get_guid(struct guid *guid, struct part *part);
 
 int echfs_open(struct echfs_file_handle *ret, int disk, int partition, const char *filename);
 int echfs_read(struct echfs_file_handle *file, void *buf, uint64_t loc, uint64_t count);
diff --git a/stage2/fs/ext2.c b/stage2/fs/ext2.c
index 87885fd7..ef29d1da 100644
--- a/stage2/fs/ext2.c
+++ b/stage2/fs/ext2.c
@@ -411,13 +411,9 @@ static int inode_read(void *buf, uint64_t loc, uint64_t count,
 

 // attempts to initialize the ext2 filesystem

 // and checks if all features are supported

-int ext2_check_signature(int drive, int partition) {

-    struct part part;

-    if (get_part(&part, drive, partition))

-        panic("Invalid partition");

-

+int ext2_check_signature(struct part *part) {

     struct ext2_superblock sb;

-    read_partition(drive, &part, &sb, 1024, sizeof(struct ext2_superblock));

+    read_partition(part->drive, part, &sb, 1024, sizeof(struct ext2_superblock));

 

     if (sb.s_magic != EXT2_S_MAGIC)

         return 0;

@@ -434,3 +430,16 @@ int ext2_check_signature(int drive, int partition) {
 

     return 1;

 }

+

+bool ext2_get_guid(struct guid *guid, struct part *part) {

+    struct ext2_superblock sb;

+    read_partition(part->drive, part, &sb, 1024, sizeof(struct ext2_superblock));

+

+    if (sb.s_magic != EXT2_S_MAGIC)

+        return false;

+

+    ((uint64_t *)guid)[0] = sb.s_uuid[0];

+    ((uint64_t *)guid)[1] = sb.s_uuid[1];

+

+    return true;

+}

diff --git a/stage2/fs/ext2.h b/stage2/fs/ext2.h
index 0fbc1f8f..c59b8c10 100644
--- a/stage2/fs/ext2.h
+++ b/stage2/fs/ext2.h
@@ -3,7 +3,9 @@
 

 #include <stdint.h>

 #include <stddef.h>

+#include <stdbool.h>

 #include <lib/part.h>

+#include <lib/blib.h>

 

 struct ext2_linux {

     uint8_t  frag_num;

@@ -54,7 +56,8 @@ struct ext2_file_handle {
     uint64_t block_size;

 };

 

-int ext2_check_signature(int drive, int partition);

+int ext2_check_signature(struct part *part);

+bool ext2_get_guid(struct guid *guid, struct part *part);

 

 int ext2_open(struct ext2_file_handle *ret, int drive, int partition, const char *path);

 int ext2_read(struct ext2_file_handle *file, void *buf, uint64_t loc, uint64_t count);

diff --git a/stage2/fs/fat32.c b/stage2/fs/fat32.c
index 1f3c3690..7361d50e 100644
--- a/stage2/fs/fat32.c
+++ b/stage2/fs/fat32.c
@@ -66,14 +66,12 @@ struct fat32_lfn_entry {
     char name3[4];
 } __attribute__((packed));
 
-static int fat32_init_context(struct fat32_context* context, int disk, int partition) {
-    context->drive = disk;
-    if (get_part(&context->part, disk, partition)) {
-        panic("Invalid partition");
-    }
+static int fat32_init_context(struct fat32_context* context, struct part *part) {
+    context->part  = *part;
+    context->drive = part->drive;
 
     struct fat32_bpb bpb;
-    read_partition(disk, &context->part, &bpb, 0, sizeof(struct fat32_bpb));
+    read_partition(part->drive, &context->part, &bpb, 0, sizeof(struct fat32_bpb));
 
     if (bpb.signature != FAT32_VALID_SIGNATURE_1 && bpb.signature != FAT32_VALID_SIGNATURE_2) {
         return 1;
@@ -223,14 +221,19 @@ static int fat32_open_in(struct fat32_context* context, struct fat32_directory_e
     return -1;
 }
 
-int fat32_check_signature(int disk, int partition) {
+int fat32_check_signature(struct part *part) {
     struct fat32_context context;
-    return fat32_init_context(&context, disk, partition) == 0;
+    return fat32_init_context(&context, part) == 0;
 }
 
 int fat32_open(struct fat32_file_handle* ret, int disk, int partition, const char* path) {
+    struct part part;
+    if (get_part(&part, disk, partition)) {
+        panic("Invalid partition");
+    }
+
     struct fat32_context context;
-    int r = fat32_init_context(&context, disk, partition);
+    int r = fat32_init_context(&context, &part);
 
     if (r) {
         print("fat32: context init failure (%d)\n", r);
diff --git a/stage2/fs/fat32.h b/stage2/fs/fat32.h
index 145a1728..8697a40f 100644
--- a/stage2/fs/fat32.h
+++ b/stage2/fs/fat32.h
@@ -24,7 +24,7 @@ struct fat32_file_handle {
     uint32_t size_clusters;
 };
 
-int fat32_check_signature(int disk, int partition);
+int fat32_check_signature(struct part *part);
 
 int fat32_open(struct fat32_file_handle *ret, int disk, int partition, const char *path);
 int fat32_read(struct fat32_file_handle *file, void *buf, uint64_t loc, uint64_t count);
diff --git a/stage2/fs/file.c b/stage2/fs/file.c
index a125cf50..4dec2d9e 100644
--- a/stage2/fs/file.c
+++ b/stage2/fs/file.c
@@ -6,9 +6,26 @@
 #include <fs/fat32.h>
 #include <lib/blib.h>
 #include <mm/pmm.h>
+#include <lib/part.h>
+
+bool fs_get_guid(struct guid *guid, struct part *part) {
+    if (echfs_check_signature(part)) {
+        return echfs_get_guid(guid, part);
+    }
+    if (ext2_check_signature(part)) {
+        return ext2_get_guid(guid, part);
+    }
+
+    return false;
+}
 
 int fopen(struct file_handle *ret, int disk, int partition, const char *filename) {
-    if (echfs_check_signature(disk, partition)) {
+    struct part part;
+    if (get_part(&part, disk, partition)) {
+        panic("Invalid partition");
+    }
+
+    if (echfs_check_signature(&part)) {
         struct echfs_file_handle *fd = conv_mem_alloc(sizeof(struct echfs_file_handle));
 
         int r = echfs_open(fd, disk, partition, filename);
@@ -24,7 +41,7 @@ int fopen(struct file_handle *ret, int disk, int partition, const char *filename
         return 0;
     }
 
-    if (ext2_check_signature(disk, partition)) {
+    if (ext2_check_signature(&part)) {
         struct ext2_file_handle *fd = conv_mem_alloc(sizeof(struct ext2_file_handle));
 
         int r = ext2_open(fd, disk, partition, filename);
@@ -40,7 +57,7 @@ int fopen(struct file_handle *ret, int disk, int partition, const char *filename
         return 0;
     }
 
-    if (fat32_check_signature(disk, partition)) {
+    if (fat32_check_signature(&part)) {
         struct fat32_file_handle *fd = conv_mem_alloc(sizeof(struct fat32_file_handle));
 
         int r = fat32_open(fd, disk, partition, filename);
diff --git a/stage2/fs/file.h b/stage2/fs/file.h
index d39ec2a9..dfea68b3 100644
--- a/stage2/fs/file.h
+++ b/stage2/fs/file.h
@@ -2,6 +2,12 @@
 #define __FS__FILE_H__
 
 #include <stdint.h>
+#include <stdbool.h>
+
+struct part;
+struct guid;
+
+bool fs_get_guid(struct guid *guid, struct part *part);
 
 struct file_handle {
     int        disk;
diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c
index 3f48c23d..ea4b0eef 100644
--- a/stage2/lib/blib.c
+++ b/stage2/lib/blib.c
@@ -10,6 +10,7 @@
 #include <sys/e820.h>
 #include <lib/print.h>
 #include <lib/config.h>
+#include <lib/part.h>
 #include <mm/pmm.h>
 
 uint8_t boot_drive;
@@ -59,14 +60,32 @@ static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) {
     return true;
 }
 
+static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path) {
+    struct guid guid;
+
+    if (!string_to_guid(&guid, guid_str))
+        panic("Invalid GUID format");
+
+    int drive, partition;
+    if (!part_get_by_guid(&drive, &partition, &guid))
+        panic("No partition found for GUID: %s", guid_str);
+
+    if (fopen(fd, drive, partition, path))
+        return false;
+
+    return true;
+}
+
 bool uri_open(struct file_handle *fd, char *uri) {
     char *resource, *root, *path;
     config_resolve_uri(uri, &resource, &root, &path);
 
     if (!strcmp(resource, "bios")) {
         return uri_bios_dispatch(fd, root, path);
+    } else if (!strcmp(resource, "guid")) {
+        return uri_guid_dispatch(fd, root, path);
     } else {
-        panic("Resource `%s` not valid.");
+        panic("Resource `%s` not valid.", resource);
     }
 }
 
@@ -148,7 +167,7 @@ static bool is_valid_guid(const char *s) {
         }
     }
 }
-
+/*
 static void guid_convert_le_cluster(uint8_t *dest, const char *s, int len) {
     size_t p = 0;
     for (int i = len - 1; i >= 0; i--) {
@@ -157,7 +176,7 @@ static void guid_convert_le_cluster(uint8_t *dest, const char *s, int len) {
         i % 2 ? (dest[p] = val) : (dest[p++] |= val << 4);
     }
 }
-
+*/
 static void guid_convert_be_cluster(uint8_t *dest, const char *s, int len) {
     size_t p = 0;
     for (int i = 0; i < len; i++) {
@@ -171,9 +190,9 @@ bool string_to_guid(struct guid *guid, const char *s) {
     if (!is_valid_guid(s))
         return false;
 
-    guid_convert_le_cluster((uint8_t *)guid + 0,  s + 0,  8);
-    guid_convert_le_cluster((uint8_t *)guid + 4,  s + 9,  4);
-    guid_convert_le_cluster((uint8_t *)guid + 6,  s + 14, 4);
+    guid_convert_be_cluster((uint8_t *)guid + 0,  s + 0,  8);
+    guid_convert_be_cluster((uint8_t *)guid + 4,  s + 9,  4);
+    guid_convert_be_cluster((uint8_t *)guid + 6,  s + 14, 4);
     guid_convert_be_cluster((uint8_t *)guid + 8,  s + 19, 4);
     guid_convert_be_cluster((uint8_t *)guid + 10, s + 24, 12);
 
diff --git a/stage2/lib/config.c b/stage2/lib/config.c
index 8f07660a..d81b4633 100644
--- a/stage2/lib/config.c
+++ b/stage2/lib/config.c
@@ -140,6 +140,7 @@ bool config_resolve_uri(char *uri, char **resource, char **root, char **path) {
         }
     }
 
+    // Get root
     for (size_t i = 0; ; i++) {
         if (uri[i] == 0)
             return false;
@@ -152,9 +153,9 @@ bool config_resolve_uri(char *uri, char **resource, char **root, char **path) {
         }
     }
 
+    // Get path
     if (*uri == 0)
         return false;
-
     *path = uri;
 
     return true;
diff --git a/stage2/lib/part.c b/stage2/lib/part.c
index da7dccdf..12070ee4 100644
--- a/stage2/lib/part.c
+++ b/stage2/lib/part.c
@@ -75,9 +75,18 @@ static int gpt_get_part(struct part *ret, int drive, int partition) {
     if (!memcmp(&entry.unique_partition_guid, &empty_guid, sizeof(struct guid)))
         return NO_PARTITION;
 
+    ret->drive      = drive;
+    ret->partition  = partition;
     ret->first_sect = entry.starting_lba;
     ret->sect_count = (entry.ending_lba - entry.starting_lba) + 1;
-    ret->guid       = entry.unique_partition_guid;
+
+    struct guid guid;
+    if (!fs_get_guid(&guid, ret)) {
+        ret->guid_valid = false;
+    } else {
+        ret->guid_valid = true;
+        ret->guid = guid;
+    }
 
     return 0;
 }
@@ -114,14 +123,18 @@ static int mbr_get_part(struct part *ret, int drive, int partition) {
     if (entry.type == 0)
         return NO_PARTITION;
 
+    ret->drive      = drive;
+    ret->partition  = partition;
     ret->first_sect = entry.first_sect;
     ret->sect_count = entry.sect_count;
 
-    // We use the same method of generating GUIDs for MBR partitions as Linux
-    struct guid empty_guid = {0};
-    ret->guid   = empty_guid;
-    ret->guid.a = disk_signature;
-    ret->guid.b = (partition + 1) << 8;
+    struct guid guid;
+    if (!fs_get_guid(&guid, ret)) {
+        ret->guid_valid = false;
+    } else {
+        ret->guid_valid = true;
+        ret->guid = guid;
+    }
 
     return 0;
 }
@@ -189,3 +202,22 @@ load_up:
         goto load_up;
     }
 }
+
+bool part_get_by_guid(int *drive, int *part, struct guid *guid) {
+    for (size_t i = 0; i < part_index_i; i++) {
+        if (!part_index[i].guid_valid)
+            continue;
+        print("%X %X\n",
+            ((uint64_t*)&part_index[i].guid)[0],
+            ((uint64_t*)&part_index[i].guid)[1]);
+        print("%X %X\n",
+            ((uint64_t*)guid)[0],
+            ((uint64_t*)guid)[1]);
+        if (!memcmp(&part_index[i].guid, guid, 16)) {
+            *drive = part_index[i].drive;
+            *part  = part_index[i].partition;
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/stage2/lib/part.h b/stage2/lib/part.h
index 135c32f5..e7304b10 100644
--- a/stage2/lib/part.h
+++ b/stage2/lib/part.h
@@ -6,12 +6,16 @@
 #include <lib/blib.h>
 
 struct part {
+    int drive;
+    int partition;
     uint64_t first_sect;
     uint64_t sect_count;
+    bool guid_valid;
     struct guid guid;
 };
 
 int get_part(struct part *part, int drive, int partition);
+bool part_get_by_guid(int *drive, int *part, struct guid *guid);
 
 void part_create_index(void);
 
diff --git a/test/limine.cfg b/test/limine.cfg
index e1d7cf7a..05ed74c4 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -20,7 +20,7 @@ BACKGROUND_PATH=bg.bmp
 :Stivale Test
 
 PROTOCOL=stivale
-KERNEL_PATH=bios://:1/boot/test.elf
+KERNEL_PATH=guid://@GUID@/boot/test.elf
 KERNEL_CMDLINE=Hi! This is an example!
 
 :Stivale2 Test
tab: 248 wrap: offon