linux: Add possibility to load multiple modules
diff --git a/CONFIG.md b/CONFIG.md
index 760bea51..c86909b2 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -39,7 +39,10 @@ Some keys take *URIs* as values; these are described in the next section.
*Locally assignable (protocol specific)* keys are:
* Linux protocol:
* `KERNEL_PATH` - The URI path of the kernel.
- * `INITRD_PATH` - The URI path to the initial ramdisk.
+ * `MODULE_PATH` - The URI path to a module (such as initramfs).
+
+ Note that one can define this last variable multiple times to specify multiple
+ modules.
* stivale and stivale2 protocols:
* `KERNEL_PATH` - The URI path of the kernel.
* `MODULE_PATH` - The URI path to a module.
diff --git a/limine-pxe.bin b/limine-pxe.bin
index 66287d00..40301f0b 100644
Binary files a/limine-pxe.bin and b/limine-pxe.bin differ
diff --git a/limine.bin b/limine.bin
index 94aa765e..8dbce093 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/protos/linux.c b/stage2/protos/linux.c
index be91c436..dedb4777 100644
--- a/stage2/protos/linux.c
+++ b/stage2/protos/linux.c
@@ -127,20 +127,28 @@ void linux_load(char *cmdline) {
memmap_alloc_range(KERNEL_LOAD_ADDR, kernel->size - real_mode_code_size, 0);
fread(kernel, (void *)KERNEL_LOAD_ADDR, real_mode_code_size, kernel->size - real_mode_code_size);
- char initrd_path[64];
- if (!config_get_value(initrd_path, 0, 64, "INITRD_PATH"))
- panic("INITRD_PATH not specified");
+ size_t modules_mem_base = INITRD_LOAD_ADDR;
+ for (size_t i = 0; ; i++) {
+ char module_path[64];
+ if (!config_get_value(module_path, i, 64, "MODULE_PATH"))
+ break;
- struct file_handle initrd;
- if (!uri_open(&initrd, initrd_path))
- panic("Could not open initrd");
+ struct file_handle module;
+ if (!uri_open(&module, module_path))
+ panic("Could not open `%s`", module_path);
- print("Loading initrd...\n");
- memmap_alloc_range(INITRD_LOAD_ADDR, initrd.size, 0);
- fread(&initrd, (void *)INITRD_LOAD_ADDR, 0, initrd.size);
+ print("Loading module `%s`...\n", module_path);
- *((uint32_t *)(real_mode_code + 0x218)) = (uint32_t)INITRD_LOAD_ADDR;
- *((uint32_t *)(real_mode_code + 0x21c)) = (uint32_t)initrd.size;
+ memmap_alloc_range(modules_mem_base, module.size, 0);
+ fread(&module, (void *)modules_mem_base, 0, module.size);
+
+ modules_mem_base += module.size;
+ }
+
+ if (modules_mem_base != INITRD_LOAD_ADDR) {
+ *((uint32_t *)(real_mode_code + 0x218)) = (uint32_t)INITRD_LOAD_ADDR;
+ *((uint32_t *)(real_mode_code + 0x21c)) = (uint32_t)(modules_mem_base - INITRD_LOAD_ADDR);
+ }
uint16_t real_mode_code_seg = rm_seg(real_mode_code);
uint16_t kernel_entry_seg = real_mode_code_seg + 0x20;
