[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Lost] [Patch] kernel2: Multiboot-Module an init uebergeben



+ kernel: Multiboot-Module an init uebergeben
Index: trunk/src/include/arch/i386/page.h
===================================================================
--- trunk.orig/src/include/arch/i386/page.h
+++ trunk/src/include/arch/i386/page.h
@@ -57,7 +57,7 @@
 #define USER_MEM_START 0x40000000
 #define USER_MEM_END   0xffffffff
 
-#define USER_STACK_START USER_MEM_END
+#define USER_STACK_START 0
 #define USER_STACK_SIZE 0x1000
 
 
Index: trunk/src/kernel2/include/arch/i386/mm_arch.h
===================================================================
--- trunk.orig/src/kernel2/include/arch/i386/mm_arch.h
+++ trunk/src/kernel2/include/arch/i386/mm_arch.h
@@ -78,4 +78,7 @@ typedef enum { page_4K, page_4M } page_s
 #define MM_FLAGS_NO_CACHE (PTE_PCT)
 
 
+#define MM_USER_START 0x40000000
+#define MM_USER_END   0xFFFFFFFF
+
 #endif
Index: trunk/src/kernel2/src/tasks/modules.c
===================================================================
--- trunk.orig/src/kernel2/src/tasks/modules.c
+++ trunk/src/kernel2/src/tasks/modules.c
@@ -48,6 +48,8 @@
 
 static void load_module(struct multiboot_module* multiboot_module);
 
+static pm_process_t* init_process;
+
 /**
  * Das Init-Modul laden. Dieses Modul ist dafuer verantwortlich, die restlichen
  * Module zu laden.
@@ -104,7 +106,7 @@ static void load_module(struct multiboot
         multiboot_module_mapped->start, image_size);
 
     //load_module_bin(multiboot_module_mapped, cmdline);
-    pm_process_t* init_process = pm_create(cmdline);
+    init_process = pm_create(cmdline);
     if (loader_load_image(init_process->pid, (vaddr_t) image_start, image_size)
         == FALSE)
     {
@@ -116,6 +118,120 @@ static void load_module(struct multiboot
     pmm_free((vaddr_t) multiboot_module_mapped->start, NUM_PAGES(image_size));
 }
 
+/**
+ * Hier werden die anderen Module an init weitergeleitet
+  *
+ * @param elf_header Pointer auf den ELF-Header
+ */
+void load_multiboot_modules(struct multiboot_info* multiboot_info)
+{
+    int i;
+    struct multiboot_module* multiboot_module_phys;
+    struct multiboot_module* multiboot_module;
+
+    if (multiboot_info->mi_mods_count == 0)
+    {
+        panic("Keine Multiboot-Module zu laden.");
+    }
+    else
+    {
+        multiboot_module_phys = (void*) multiboot_info->mi_mods_addr;
+
+        // Speicher für die Modulparameter
+        char* mod_cmdline_page = pmm_alloc(1);
+        void* mod_cmdline_task = mmc_automap(
+            &init_process->context, mod_cmdline_page, 1,
+            MM_USER_START, MM_USER_END, MM_FLAGS_USER_DATA);
+
+        mod_cmdline_page = vmm_kernel_automap(mod_cmdline_page, PAGE_SIZE);
+        char* mod_cmdline = mod_cmdline_page;
+        size_t mod_cmdline_free = PAGE_SIZE;
+
+        // Speicher für die Modulliste
+        void* mod_list_phys = pmm_alloc(1);
+        void* mod_list_task = mmc_automap(
+            &init_process->context, mod_list_phys, 1,
+            MM_USER_START, MM_USER_END, MM_FLAGS_USER_DATA);
+
+        dword* modulelist = vmm_kernel_automap(mod_list_phys, PAGE_SIZE);
+
+        // Stack von init mappen und Pointer auf die Modulliste uebergeben
+        dword* stack = vmm_kernel_automap(
+            mmc_resolve(&init_process->context,
+                (vaddr_t) USER_STACK_START - PAGE_SIZE),
+            PAGE_SIZE);
+
+        stack[1023] = (dword) mod_list_task;
+        vmm_kernel_unmap(stack, PAGE_SIZE);
+
+        // esp von init entsprechend anpassen
+        pm_thread_t* init_thread = (pm_thread_t*)
+            list_get_element_at(init_process->threads, 0);
+
+        interrupt_stack_frame_t* init_isf = (interrupt_stack_frame_t*)
+            init_thread->kernel_stack;
+
+        init_isf->esp -= 8;
+
+        // Das unterste dword auf der Page mit der Liste beinhaltet die
+        // Anzahl der Module
+        modulelist[0] = multiboot_info->mi_mods_count;
+
+        // Module in den Adressraum von init mappen
+        for (i = 0; i < multiboot_info->mi_mods_count; i++)
+        {
+            //Die multiboot_module struct des aktuellen Moduls mappen
+            multiboot_module = vmm_kernel_automap(
+                (paddr_t)multiboot_module_phys,
+                sizeof(multiboot_module));
+
+            // Anzahl der benoetigten Pages berechnen
+            size_t pages = NUM_PAGES(
+                  PAGE_ALIGN_ROUND_UP((dword) multiboot_module->end)
+                - PAGE_ALIGN_ROUND_DOWN((dword) multiboot_module->start));
+
+            // Freie virtuelle Adresse suchen um das Modul dort hin zu mappen.
+            void* dest = mmc_automap(
+                &init_process->context,
+                (paddr_t) multiboot_module->start, pages,
+                MM_USER_START, MM_USER_END, MM_FLAGS_USER_DATA);
+
+            //first_task->memory_used += pages * 0x1000;
+
+            // TODO: Den Speicher aus dem Kerneladressraum unmappen
+
+            // Die Adresse in die Modulliste von Init schreiben
+            modulelist[1 + (3*i)] = (dword) dest;
+            modulelist[2 + (3*i)] = multiboot_module->end - multiboot_module->start;
+            modulelist[3 + (3*i)] = (dword) mod_cmdline_task + (mod_cmdline - mod_cmdline_page);
+
+            // Modulbefehlszeile kopieren
+            char* cmdline = vmm_kernel_automap(
+                (paddr_t) multiboot_module->cmdline, PAGE_SIZE);
+
+            size_t length = strlen(cmdline);
+            if (mod_cmdline_free > length) {
+                strncpy(mod_cmdline, cmdline, length);
+                mod_cmdline[length] = '\0';
+                mod_cmdline += (length + 1);
+                mod_cmdline_free -= (length + 1);
+            }
+            vmm_kernel_unmap(cmdline, PAGE_SIZE);
+
+            // multiboot_module struct wieder freigeben
+            vmm_kernel_unmap(multiboot_module, sizeof(multiboot_module));
+
+            // Physikalische Adresse der multiboot_module struct auf die naechste setzen
+            multiboot_module_phys++;
+        }
+
+        // Die temporaer gemapte Modulliste wieder freigeben (nur hier im Kernel freigeben)
+        vmm_kernel_unmap(modulelist, PAGE_SIZE);
+        vmm_kernel_unmap(mod_cmdline_page, PAGE_SIZE);
+    }
+
+    //TODO: Muessen noch irgendwelche Multiboot-Structs physikalisch freigegeben werden?
+}
 
 /*##############################
  * Hilfsfunktionen => loader.h #
Index: trunk/src/kernel2/include/tasks.h
===================================================================
--- trunk.orig/src/kernel2/include/tasks.h
+++ trunk/src/kernel2/include/tasks.h
@@ -167,5 +167,8 @@ void pm_scheduler_push(pm_thread_t* thre
 /// Das Init-Modul laden
 void load_init_module(struct multiboot_info* multiboot_info);
 
+/// Alle weiteren Module an init uebergeben
+void load_multiboot_modules(struct multiboot_info* multiboot_info);
+
 #endif //ifndef _TASKS_H_
 
Index: trunk/src/kernel2/src/init.c
===================================================================
--- trunk.orig/src/kernel2/src/init.c
+++ trunk/src/kernel2/src/init.c
@@ -199,6 +199,9 @@ void init(int multiboot_magic, struct mu
         // Init-Modul laden
         load_init_module(&multiboot_info);
 
+        // Alle weiteren Module an init uebergeben
+        load_multiboot_modules(&multiboot_info);
+
         // Sobald alle CPUs angekommen sind, gehts los!
         // TODO: Timeout?
         while (final_cpus_arrived < cpu_count) asm("nop");
Index: trunk/src/kernel2/src/tasks/thread.c
===================================================================
--- trunk.orig/src/kernel2/src/tasks/thread.c
+++ trunk/src/kernel2/src/tasks/thread.c
@@ -106,9 +106,9 @@ pm_thread_t* pm_thread_create(pm_process
     
     // Page fuer den Userspace-Stack allozieren
     paddr_t stack_phys = pmm_alloc(NUM_PAGES(USER_STACK_SIZE));
-    mmc_map(&process->context, (vaddr_t) (isf->esp - USER_STACK_SIZE + 
-        1), stack_phys, MM_FLAGS_USER_DATA, NUM_PAGES(USER_STACK_SIZE));
-    
+    mmc_map(&process->context, (vaddr_t) (isf->esp - USER_STACK_SIZE),
+        stack_phys, MM_FLAGS_USER_DATA, NUM_PAGES(USER_STACK_SIZE));
+
     // Thread in die Liste aufnehmen, und beim Scheduler regisrieren
     list_push(process->threads, thread);