:: commit dab65041021d5e1df38c977b8188fdbec0fdf48d

Andy-Python-Programmer <andypythonappdeveloper@gmail.com> — 2021-09-13 01:44

parents: 7ce2354c88

multiboot2: add kernel modules support

Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
diff --git a/stage23/protos/multiboot2.c b/stage23/protos/multiboot2.c
index 0d606b32..10e02994 100644
--- a/stage23/protos/multiboot2.c
+++ b/stage23/protos/multiboot2.c
@@ -50,6 +50,7 @@ static struct multiboot_header* load_multiboot2_header(uint8_t* kernel) {
 /// Returns the size required to store the multiboot2 info.
 static size_t get_multiboot2_info_size(
     char* cmdline, 
+    size_t modules_size,
     struct elf_section_hdr_info* section_hdr_info
 ) {
     return ALIGN_UP(sizeof(struct multiboot2_start_tag), MULTIBOOT_TAG_ALIGN) +                                         // start
@@ -58,6 +59,7 @@ static size_t get_multiboot2_info_size(
         ALIGN_UP(sizeof(struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN) +                                       // framebuffer
         ALIGN_UP(sizeof(struct multiboot_tag_new_acpi) + 36, MULTIBOOT_TAG_ALIGN) +                                     // new ACPI info
         ALIGN_UP(sizeof(struct multiboot_tag_elf_sections) + section_hdr_info->section_hdr_size, MULTIBOOT_TAG_ALIGN) + // ELF info
+        ALIGN_UP(modules_size, MULTIBOOT_TAG_ALIGN) +                                                                   // modules
         ALIGN_UP(sizeof(struct multiboot_tag_mmap) + sizeof(struct multiboot_mmap_entry) * 256, MULTIBOOT_TAG_ALIGN) +  // MMAP
 #if uefi == 1
         ALIGN_UP(sizeof(struct multiboot_tag_efi_mmap) + (efi_desc_size * 256), MULTIBOOT_TAG_ALIGN) +                  // EFI MMAP
@@ -119,7 +121,7 @@ void multiboot2_load(char *config, char* cmdline) {
     bool is_new_acpi_required = false;
 
     // Iterate through the entries...
-    for (struct multiboot_header_tag* tag = (struct multiboot_header_tag*)(header + 1);
+    for (struct multiboot_header_tag* tag = (struct multiboot_header_tag*)(header + 1); // header + 1 to skip the header struct.
          tag < (struct multiboot_header_tag*)((uintptr_t)header + header->header_length) && tag->type != MULTIBOOT_HEADER_TAG_END;
          tag = (struct multiboot_header_tag*)((uintptr_t)tag + ALIGN_UP(tag->size, MULTIBOOT_TAG_ALIGN))) {
   
@@ -159,17 +161,79 @@ void multiboot2_load(char *config, char* cmdline) {
                 fbtag = (struct multiboot_header_tag_framebuffer*)tag;
             } break;
 
+            // We always align the modules ;^)
+            case MULTIBOOT_HEADER_TAG_MODULE_ALIGN: break;
+
             default: panic("multiboot2: unknown tag type");
         }
     }
 
-    size_t mb2_info_size = get_multiboot2_info_size(cmdline, section_hdr_info);
+    size_t modules_size;
+    size_t n_modules = 0;
+
+    for (n_modules = 0;; n_modules++) {
+        if (config_get_value(config, modules_size, "MODULE_PATH") == NULL)
+            break;
+        
+        char* module_cmdline = config_get_value(config, modules_size, "MODULE_STRING");
+        modules_size += sizeof(struct multiboot_tag_module) + strlen(module_cmdline) + 1;
+    }
+
+    size_t mb2_info_size = get_multiboot2_info_size(cmdline, modules_size, section_hdr_info);
     size_t info_idx = 0;
     uint8_t* mb2_info = ext_mem_alloc(mb2_info_size);
 
     struct multiboot2_start_tag* mbi_start = (struct multiboot2_start_tag*)mb2_info;
     info_idx += sizeof(struct multiboot2_start_tag);
 
+    //////////////////////////////////////////////
+    // Create modules tag
+    //////////////////////////////////////////////
+    for (size_t i = 0; i < n_modules; i++) {
+        char* module_path = config_get_value(config, i, "MODULE_PATH");
+        if (module_path == NULL)
+            panic("multiboot2: Module disappeared unexpectedly");
+
+        print("multiboot2: Loading module `%s`...\n", module_path);
+
+        struct file_handle f;
+        if (!uri_open(&f, module_path))
+            panic("multiboot2: Failed to open module with path `%s`. Is the path correct?", module_path);
+        
+        char* module_cmdline = config_get_value(config, i, "MODULE_STRING");
+        void* module_addr = (void *)(uintptr_t)ALIGN_UP(kernel_top, 4096);
+
+        // Module commandline can be null, so we guard against that and make the 
+        // string "".
+        if (module_cmdline == NULL) {
+            module_cmdline = "";
+        }
+
+        memmap_alloc_range((uintptr_t)module_addr, f.size, MEMMAP_KERNEL_AND_MODULES,
+                            true, true, false, false);
+
+        kernel_top = (uintptr_t)module_addr + f.size;
+        fread(&f, module_addr, 0, f.size);
+    
+        struct multiboot_tag_module* module_tag = (struct multiboot_tag_module*)(mb2_info + info_idx);
+
+        module_tag->type = MULTIBOOT_TAG_TYPE_MODULE;
+        module_tag->size = sizeof(struct multiboot_tag_module) + strlen(module_cmdline) + 1;
+        module_tag->mod_start   = (uint32_t)(size_t)module_addr;
+        module_tag->mod_end     = module_tag->mod_start + f.size;
+        strcpy(module_tag->cmdline, module_cmdline); // Copy over the command line
+
+        if (verbose) {
+            print("multiboot2: Requested module %u:\n", i);
+            print("            Path:   %s\n", module_path);
+            print("            String: \"%s\"\n", module_cmdline ?: "");
+            print("            Begin:  %x\n", module_tag->mod_start);
+            print("            End:    %x\n", module_tag->mod_end);
+        }
+
+        append_tag(mb2_info, module_tag);
+    }
+
     //////////////////////////////////////////////
     // Create command line tag
     //////////////////////////////////////////////
tab: 248 wrap: offon