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
