:: commit a51f8a39c03de9754a7796bf2a282909a853e1aa

mintsuki <mintsuki@protonmail.com> — 2022-03-16 05:49

parents: 1e62d99374

limine: Add modules request

diff --git a/common/lib/part.h b/common/lib/part.h
index fc8849a0..8b14590f 100644
--- a/common/lib/part.h
+++ b/common/lib/part.h
@@ -56,6 +56,7 @@ extern struct volume **volume_index;
 extern size_t volume_index_i;
 
 bool gpt_get_guid(struct guid *guid, struct volume *volume);
+uint32_t mbr_get_id(struct volume *volume);
 
 int part_get(struct volume *part, struct volume *volume, int partition);
 
diff --git a/common/lib/part.s2.c b/common/lib/part.s2.c
index ed3e51bb..77113e6f 100644
--- a/common/lib/part.s2.c
+++ b/common/lib/part.s2.c
@@ -208,6 +208,59 @@ struct mbr_entry {
 	uint32_t sect_count;
 } __attribute__((packed));
 
+static bool is_valid_mbr(struct volume *volume) {
+    // Check if actually valid mbr
+    uint16_t hint = 0;
+    volume_read(volume, &hint, 218, sizeof(uint16_t));
+    if (hint != 0)
+        return false;
+
+    volume_read(volume, &hint, 444, sizeof(uint16_t));
+    if (hint != 0 && hint != 0x5a5a)
+        return false;
+
+    volume_read(volume, &hint, 510, sizeof(uint16_t));
+    if (hint != 0xaa55)
+        return false;
+
+    volume_read(volume, &hint, 446, sizeof(uint8_t));
+    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
+        return false;
+    volume_read(volume, &hint, 462, sizeof(uint8_t));
+    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
+        return false;
+    volume_read(volume, &hint, 478, sizeof(uint8_t));
+    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
+        return false;
+    volume_read(volume, &hint, 494, sizeof(uint8_t));
+    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
+        return false;
+
+    char hintc[64];
+    volume_read(volume, hintc, 4, 8);
+    if (memcmp(hintc, "_ECH_FS_", 8) == 0)
+        return false;
+    volume_read(volume, hintc, 54, 3);
+    if (memcmp(hintc, "FAT", 3) == 0)
+        return false;
+    volume_read(volume, &hint, 1080, sizeof(uint16_t));
+    if (hint == 0xef53)
+        return false;
+
+    return true;
+}
+
+uint32_t mbr_get_id(struct volume *volume) {
+    if (!is_valid_mbr(volume)) {
+        return 0;
+    }
+
+    uint32_t ret;
+    volume_read(volume, &ret, 0x1b8, sizeof(uint32_t));
+
+    return ret;
+}
+
 static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part,
                                 int partition) {
     struct mbr_entry entry;
@@ -261,43 +314,9 @@ static int mbr_get_logical_part(struct volume *ret, struct volume *extended_part
 }
 
 static int mbr_get_part(struct volume *ret, struct volume *volume, int partition) {
-    // Check if actually valid mbr
-    uint16_t hint = 0;
-    volume_read(volume, &hint, 218, sizeof(uint16_t));
-    if (hint != 0)
-        return INVALID_TABLE;
-
-    volume_read(volume, &hint, 444, sizeof(uint16_t));
-    if (hint != 0 && hint != 0x5a5a)
-        return INVALID_TABLE;
-
-    volume_read(volume, &hint, 510, sizeof(uint16_t));
-    if (hint != 0xaa55)
-        return INVALID_TABLE;
-
-    volume_read(volume, &hint, 446, sizeof(uint8_t));
-    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
-        return INVALID_TABLE;
-    volume_read(volume, &hint, 462, sizeof(uint8_t));
-    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
-        return INVALID_TABLE;
-    volume_read(volume, &hint, 478, sizeof(uint8_t));
-    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
-        return INVALID_TABLE;
-    volume_read(volume, &hint, 494, sizeof(uint8_t));
-    if ((uint8_t)hint != 0x00 && (uint8_t)hint != 0x80)
-        return INVALID_TABLE;
-
-    char hintc[64];
-    volume_read(volume, hintc, 4, 8);
-    if (memcmp(hintc, "_ECH_FS_", 8) == 0)
-        return INVALID_TABLE;
-    volume_read(volume, hintc, 54, 3);
-    if (memcmp(hintc, "FAT", 3) == 0)
-        return INVALID_TABLE;
-    volume_read(volume, &hint, 1080, sizeof(uint16_t));
-    if (hint == 0xef53)
+    if (!is_valid_mbr(volume)) {
         return INVALID_TABLE;
+    }
 
     struct mbr_entry entry;
 
diff --git a/common/limine.h b/common/limine.h
index e8aa1f8e..a8425566 100644
--- a/common/limine.h
+++ b/common/limine.h
@@ -3,6 +3,8 @@
 
 #include <stdint.h>
 
+// Misc
+
 #ifdef LIMINE_NO_POINTERS
 #  define LIMINE_PTR(TYPE) uint64_t
 #else
@@ -11,6 +13,21 @@
 
 #define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b
 
+struct limine_uuid {
+    uint32_t a;
+    uint16_t b;
+    uint16_t c;
+    uint8_t d[8];
+};
+
+struct limine_file_location {
+    uint64_t partition_index;
+    uint32_t mbr_disk_id;
+    struct limine_uuid gpt_disk_uuid;
+    struct limine_uuid gpt_part_uuid;
+    struct limine_uuid part_uuid;
+};
+
 // Boot info
 
 #define LIMINE_BOOT_INFO_REQUEST { LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740 }
@@ -140,4 +157,30 @@ struct limine_entry_point_request {
     LIMINE_PTR(void *) entry;
 };
 
+// Module
+
+#define LIMINE_MODULE_REQUEST { LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee }
+
+struct limine_module {
+    uint64_t base;
+    uint64_t length;
+    LIMINE_PTR(char *) path;
+    LIMINE_PTR(char *) cmdline;
+    LIMINE_PTR(struct limine_file_location *) file_location;
+    uint8_t reserved[256];
+};
+
+struct limine_module_response {
+    uint64_t flags;
+
+    uint64_t modules_count;
+    LIMINE_PTR(struct limine_module *) modules;
+};
+
+struct limine_module_request {
+    uint64_t id[4];
+    uint64_t flags;
+    LIMINE_PTR(struct limine_module_response *) response;
+};
+
 #endif
diff --git a/common/menu.c b/common/menu.c
index 4be1b45a..18b11079 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -127,6 +127,7 @@ static const char *VALID_KEYS[] = {
     "INITRD_PATH",
     "MODULE_PATH",
     "MODULE_STRING",
+    "MODULE_CMDLINE",
     "RESOLUTION",
     "TEXTMODE",
     "KASLR",
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 8e1911fc..2e82c961 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -39,6 +39,29 @@ static uint64_t physical_base, virtual_base, slide, direct_map_offset;
 static size_t requests_count;
 static void *requests[MAX_REQUESTS];
 
+static struct limine_file_location get_file_loc(struct volume *vol) {
+    struct limine_file_location ret = {0};
+
+    ret.partition_index = vol->partition;
+
+    ret.mbr_disk_id = mbr_get_id(vol);
+
+    if (vol->guid_valid) {
+        memcpy(&ret.part_uuid, &vol->guid, sizeof(struct limine_uuid));
+    }
+
+    if (vol->part_guid_valid) {
+        memcpy(&ret.gpt_part_uuid, &vol->part_guid, sizeof(struct limine_uuid));
+    }
+
+    struct guid gpt_disk_uuid;
+    if (gpt_get_guid(&gpt_disk_uuid, vol->backing_dev ?: vol) == true) {
+        memcpy(&ret.gpt_disk_uuid, &gpt_disk_uuid, sizeof(struct limine_uuid));
+    }
+
+    return ret;
+}
+
 static uint64_t reported_addr(void *addr) {
     return (uint64_t)(uintptr_t)addr + direct_map_offset;
 }
@@ -230,6 +253,63 @@ FEAT_START
     cmdline_request->response = reported_addr(cmdline_response);
 FEAT_END
 
+    // Modules
+FEAT_START
+    struct limine_module_request *module_request = get_request(LIMINE_MODULE_REQUEST);
+    if (module_request == NULL) {
+        break; // next feature
+    }
+
+    size_t module_count;
+    for (module_count = 0; ; module_count++) {
+        char *module_file = config_get_value(config, module_count, "MODULE_PATH");
+        if (module_file == NULL)
+            break;
+    }
+
+    struct limine_module_response *module_response =
+        ext_mem_alloc(sizeof(struct limine_module_response));
+
+    struct limine_module *modules = ext_mem_alloc(module_count * sizeof(struct limine_module));
+
+    for (size_t i = 0; i < module_count; i++) {
+        struct conf_tuple conf_tuple =
+                config_get_tuple(config, i, "MODULE_PATH", "MODULE_CMDLINE");
+
+        char *module_path = conf_tuple.value1;
+        char *module_cmdline = conf_tuple.value2;
+
+        struct limine_module *m = &modules[i];
+
+        if (module_cmdline == NULL) {
+            module_cmdline = "";
+        }
+
+        print("limine: Loading module `%s`...\n", module_path);
+
+        struct file_handle *f;
+        if ((f = uri_open(module_path)) == NULL)
+            panic(true, "limine: Failed to open module with path `%s`. Is the path correct?", module_path);
+
+        m->base = reported_addr(freadall(f, MEMMAP_KERNEL_AND_MODULES));
+        m->length = f->size;
+        m->path = reported_addr(module_path);
+        m->cmdline = reported_addr(module_cmdline);
+
+        struct limine_file_location *l = ext_mem_alloc(sizeof(struct limine_file_location));
+        *l = get_file_loc(f->vol);
+
+        m->file_location = reported_addr(l);
+
+        fclose(f);
+    }
+
+    module_response->modules_count = module_count;
+    module_response->modules = reported_addr(modules);
+
+    module_request->response = reported_addr(module_response);
+FEAT_END
+
     // Framebuffer feature
 FEAT_START
     term_deinit();
diff --git a/test/limine.c b/test/limine.c
index 78ac704f..677adc39 100644
--- a/test/limine.c
+++ b/test/limine.c
@@ -37,6 +37,12 @@ static struct limine_memmap_request memmap_request = {
     .flags = 0, .response = NULL
 };
 
+__attribute__((used))
+static struct limine_module_request module_request = {
+    .id = LIMINE_MODULE_REQUEST,
+    .flags = 0, .response = NULL
+};
+
 static char *get_memmap_type(uint64_t type) {
     switch (type) {
         case LIMINE_MEMMAP_USABLE:
@@ -60,6 +66,26 @@ static char *get_memmap_type(uint64_t type) {
     }
 }
 
+static void print_file_loc(struct limine_file_location *file_location) {
+    e9_printf("Loc->PartIndex: %d", file_location->partition_index);
+    e9_printf("Loc->MBRDiskId: %x", file_location->mbr_disk_id);
+    e9_printf("Loc->GPTDiskUUID: %x-%x-%x-%x",
+              file_location->gpt_disk_uuid.a,
+              file_location->gpt_disk_uuid.b,
+              file_location->gpt_disk_uuid.c,
+              *(uint64_t *)file_location->gpt_disk_uuid.d);
+    e9_printf("Loc->GPTPartUUID: %x-%x-%x-%x",
+              file_location->gpt_part_uuid.a,
+              file_location->gpt_part_uuid.b,
+              file_location->gpt_part_uuid.c,
+              *(uint64_t *)file_location->gpt_part_uuid.d);
+    e9_printf("Loc->PartUUID: %x-%x-%x-%x",
+              file_location->part_uuid.a,
+              file_location->part_uuid.b,
+              file_location->part_uuid.c,
+              *(uint64_t *)file_location->part_uuid.d);
+}
+
 #define FEAT_START do {
 #define FEAT_END } while (0);
 
@@ -122,5 +148,24 @@ FEAT_START
     }
 FEAT_END
 
+FEAT_START
+    if (module_request.response == NULL) {
+        e9_printf("Modules not passed");
+        break;
+    }
+    struct limine_module_response *module_response = module_request.response;
+    e9_printf("%d module(s)", module_response->modules_count);
+    for (size_t i = 0; i < module_response->modules_count; i++) {
+        struct limine_module *m = &module_response->modules[i];
+
+        e9_printf("Base: %x", m->base);
+        e9_printf("Length: %x", m->length);
+        e9_printf("Path: %s", m->path);
+        e9_printf("Cmdline: %s", m->cmdline);
+
+        print_file_loc(m->file_location);
+    }
+FEAT_END
+
     for (;;);
 }
diff --git a/test/limine.cfg b/test/limine.cfg
index 828a9b5f..f8a1f4f5 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -20,7 +20,7 @@ KERNEL_PATH=${STIVALE_KERNEL}
 KERNEL_CMDLINE=Woah! Another example!
 
 MODULE_PATH=${BACKGROUND_PATH}
-MODULE_STRING=yooooo
+MODULE_CMDLINE=yooooo
 
 # Test that the module string provided to the kernel will be
 # the module path since a module string is not specified.
tab: 248 wrap: offon