00001 /*********************************************************** 00002 *PANALIX 0.06, (c) Adrian Panasiuk 2002-4 * 00003 *adek336[at]o2.pl, panalix.prv.pl * 00004 *under GPLv3 license * 00005 * * 00006 *panalix - small osdev project * 00007 ************************************************************ 00008 * mboot.cpp, version 1.1 * 00009 ************************************************************ 00010 * * 00011 *get config from the multiboot compliant bootloader * 00012 * * 00013 *27'04'04- fork from o.05 branch's mboot.cpp(1.1) * 00014 * * 00015 ***********************************************************/ 00016 00017 #include "src/common/shared.hpp" 00018 #include "src/module/elf.hpp" 00019 #include "src/memory/align.hpp" 00020 #include "src/memory/alloc4k.hpp" 00021 #include "src/mboot.hpp" 00022 00023 namespace Mboot { 00024 00025 00026 /*we copy the struct to save it from overwriting*/ 00027 mboot_struct multiboot_info = *mb_info; 00028 00029 //preserve the syms data by changing the first_free_page var 00030 void init() 00031 { 00032 uint32 i; 00033 /* Get the highest adress of a section of the kernel's helping data, and then 00034 adjust first_free_page to a page above it. This way it won't get overwritten */ 00035 mboot_sht *sht= mboot_syms(); 00036 uint32 max_addr=0, n; 00037 Elf32_shdr *sect; 00038 00039 if (sht != NULL) 00040 { 00041 max_addr=sht->addr+(sht->num*sht->entry_size); 00042 for (i=0;i<sht->num;i++) 00043 { 00044 sect= (Elf32_shdr*) LMA2VIRT(sht->addr + sht->entry_size*i); 00045 00046 n=sect->sh_addr+sect->sh_size; 00047 if (n>mem_kernel_start) 00048 n-=mem_kernel_start-mem_physical; 00049 max_addr= MAX(n, max_addr); 00050 } 00051 Memory::Physical::first_free_page= 00052 align_up(max_addr, PAGE_ALIGN)/PAGE_SIZE; 00053 // sysfail(max_addr); 00054 // Memory::Physical::first_free_page= 00055 // align_up(sht->addr+(sht->num*sht->entry_size), PAGE_ALIGN)/PAGE_SIZE; 00056 } 00057 00058 /* Get the highest address of a kernel module, adjust first_free_page. Then it won't get overwritten by 00059 system tables */ 00060 int mcnt=mods_count(); 00061 if (mcnt == 0) return ; 00062 00063 struct mod_info *m; 00064 m= mods_info(mcnt-1); //the last module- the highest address (is this always true?) 00065 Memory::Physical::first_free_page=MAX(Memory::Physical::first_free_page, align_up(m->mod_end, PAGE_ALIGN)/PAGE_ALIGN); 00066 } 00067 00068 /*returns the number of modules*/ 00069 uint32 mods_count() 00070 { 00071 /*check if module info is provided in multiboot_info*/ 00072 if (multiboot_info.flags && DEF_MBOOT_MODS == DEF_MBOOT_MODS) 00073 /*if yes, return it*/ 00074 return multiboot_info.mods_count; 00075 00076 /*if not, return no modules availlable*/ 00077 return 0; 00078 } 00079 00080 /*returns a pointer to modinfo no. n*/ 00081 /*n = 0, first module, etc.*/ 00082 //will return physical adresses below 1 Mib 00083 mod_info *mods_info(uint32 n) 00084 { 00085 /*check if module info is provided in multiboot_info*/ 00086 if (multiboot_info.flags && DEF_MBOOT_MODS != DEF_MBOOT_MODS) 00087 /*if not, return 0*/ 00088 return (mod_info*) NULL; 00089 00090 /*check if there is a module no. n*/ 00091 if (n + 1 > mods_count()) return 0; 00092 00093 return (mod_info*) ((uint32) multiboot_info.mods_addr + sizeof(mod_info) * n); 00094 } 00095 00096 /*checks if syms info is availlable. if yes, return the struct*/ 00097 mboot_sht *mboot_syms() 00098 { 00099 /*check if syms info's availlable*/ 00100 if (multiboot_info.flags && DEF_MBOOT_ELF_SH != DEF_MBOOT_ELF_SH) 00101 return 0; 00102 00103 /*return the data*/ 00104 return (struct mboot_sht*)(&multiboot_info.syms); 00105 } 00106 00107 }; /*namespace Mboot*/ 00108 00109 /*********************************************************** 00110 * * 00111 *panalix 0.06 (c) Adrian Panasiuk 2002-4 * 00112 *adek336[at]o2.pl, panalix.prv.pl * 00113 * * 00114 ************************************************************/