Boot framework rework (#45)
[lunaix-os.git] / lunaix-os / arch / x86 / boot / i386 / kremap32.c
index c73c2a3c482a7836831d707516baf74629db4d57..e7ff12252c2f84aefe2af89b5fe3e42067d98ac9 100644 (file)
@@ -2,14 +2,19 @@
 
 #include <lunaix/mm/pagetable.h>
 #include <lunaix/compiler.h>
+#include <lunaix/sections.h>
 
 #include <sys/boot/bstage.h>
 #include <sys/mm/mm_defs.h>
 
-bridge_farsym(__kexec_start);
-bridge_farsym(__kexec_end);
+#define PF_X 0x1
+#define PF_W 0x2
+#define ksection_maps autogen_name(ksecmap)
+
+extern_autogen(ksecmap);
+
 bridge_farsym(__kexec_text_start);
-bridge_farsym(__kexec_text_end);
+bridge_farsym(ksection_maps);
 
 // define the initial page table layout
 struct kernel_map;
@@ -17,7 +22,8 @@ struct kernel_map;
 static struct kernel_map kernel_pt __section(".kpg");
 export_symbol(debug, boot, kernel_pt);
 
-struct kernel_map {
+struct kernel_map 
+{
     pte_t l0t[_PAGE_LEVEL_SIZE];
     pte_t pg_mnt[_PAGE_LEVEL_SIZE];
 
@@ -36,12 +42,12 @@ do_remap()
     pte_t* ktep         = (pte_t*)  kpt_pa->kernel_lfts;    
     pte_t* boot_l0tep   = (pte_t*)  kpt_pa;
 
-    set_pte(boot_l0tep, pte_mkhuge(mkpte_prot(KERNEL_DATA)));
+    set_pte(boot_l0tep, pte_mkhuge(mkpte_prot(KERNEL_PGTAB)));
 
     // --- 将内核重映射至高半区 ---
 
     // Hook the kernel reserved LFTs onto L0T
-    pte_t pte = mkpte((ptr_t)ktep, KERNEL_DATA);
+    pte_t pte = mkpte((ptr_t)ktep, KERNEL_PGTAB);
     
     for (u32_t i = 0; i < KEXEC_RSVD; i++) {
         pte = pte_setpaddr(pte, (ptr_t)&kpt_pa->kernel_lfts[i]);
@@ -50,50 +56,58 @@ do_remap()
         klptep++;
     }
 
+    struct ksecmap* maps;
+    struct ksection* section;
+    pfn_t pgs;
+    pte_t *kmntep;
+
+    maps = (struct ksecmap*)to_kphysical(__far(ksection_maps));
+    ktep += pfn(to_kphysical(__far(__kexec_text_start)));
+
     // Ensure the size of kernel is within the reservation
-    pfn_t kimg_pagecount = 
-        pfn(__far(__kexec_end) - __far(__kexec_start));
-    if (kimg_pagecount > KEXEC_RSVD * _PAGE_LEVEL_SIZE) {
+    if (leaf_count(maps->ksize) > KEXEC_RSVD * _PAGE_LEVEL_SIZE) 
+    {
         // ERROR: require more pages
         //  here should do something else other than head into blocking
         asm("ud2");
     }
 
-    // Now, map the kernel
+    // Now, map the sections
 
-    pfn_t kimg_end = pfn(to_kphysical(__far(__kexec_end)));
-    pfn_t i = pfn(to_kphysical(__far(__kexec_text_start)));
-    ktep += i;
+    for (unsigned int i = 0; i < maps->num; i++)
+    {
+        section = &maps->secs[i];
 
-    // kernel .text
-    pte = pte_setprot(pte, KERNEL_EXEC);
-    pfn_t ktext_end = pfn(to_kphysical(__far(__kexec_text_end)));
-    for (; i < ktext_end; i++) {
-        pte = pte_setpaddr(pte, page_addr(i));
-        set_pte(ktep, pte);
+        if (section->va < KERNEL_RESIDENT) {
+            continue;
+        }
 
-        ktep++;
-    }
+        pte = mkpte_prot(KERNEL_RDONLY);
+        if ((section->flags & PF_X)) {
+            pte = pte_mkexec(pte);
+        }
+        if ((section->flags & PF_W)) {
+            pte = pte_mkwritable(pte);
+        }
 
-    // all remaining kernel sections
-    pte = pte_setprot(pte, KERNEL_DATA);
-    for (; i < kimg_end; i++) {
-        pte = pte_setpaddr(pte, page_addr(i));
-        set_pte(ktep, pte);
+        pgs = leaf_count(section->size);
+        for (pfn_t j = 0; j < pgs; j++)
+        {
+            pte = pte_setpaddr(pte, section->pa + page_addr(j));
+            set_pte(ktep, pte);
 
-        ktep++;
+            ktep++;
+        }
     }
 
-    // XXX: Mapping the kernel .rodata section?
-
     // set mount point
-    pte_t* kmntep = (pte_t*) &kpt_pa->l0t[pfn_at(PG_MOUNT_1, L0T_SIZE)];
-    set_pte(kmntep, mkpte((ptr_t)kpt_pa->pg_mnt, KERNEL_DATA));
+    kmntep = (pte_t*) &kpt_pa->l0t[pfn_at(PG_MOUNT_1, L0T_SIZE)];
+    set_pte(kmntep, mkpte((ptr_t)kpt_pa->pg_mnt, KERNEL_PGTAB));
 
     // Build up self-reference
     int level = (VMS_SELF / L0T_SIZE) & _PAGE_LEVEL_MASK;
     
-    pte = mkpte_root((ptr_t)kpt_pa, KERNEL_DATA);
+    pte = mkpte_root((ptr_t)kpt_pa, KERNEL_PGTAB);
     set_pte(&boot_l0tep[level], pte);
 }