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.
