00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/init.h>
00016 #include <asm/bios_parametrs.h>
00017 #include <agnix/memory.h>
00018 #include <asm/memtests.h>
00019 #include <agnix/console.h>
00020
00021 #define MOD_NAME "BOOTM: "
00022
00023 struct main_memory_s main_memory;
00024 struct memory_block_s main_block;
00025 extern struct bin_allocator_s bin_alloc;
00026 extern u32 swapper_pg_dir[1024];
00027 extern int page_tables_init(struct main_memory_s *mem);
00028
00029 extern char __init_begin, __init_end;
00030
00031 void __init modify_memory_entry(struct memory_block_s *mem_block, unsigned long long start, unsigned long long size,
00032 unsigned long type, int block_nr)
00033 {
00034 mem_block->entries[block_nr].start = start;
00035 mem_block->entries[block_nr].size = size;
00036 mem_block->entries[block_nr].type = type;
00037 }
00038
00039 void __init add_memory_entry(struct memory_block_s *mem_block, struct e820_entry_s *entry)
00040 {
00041 int block_nr = mem_block->mem_nr;
00042
00043 memcpy(&mem_block->entries[block_nr], entry, sizeof(struct e820_entry_s));
00044 mem_block->mem_nr++;
00045 }
00046
00047 #define mem_block_size(mem_block, i) \
00048 mem_block->entries[i].size
00049
00050 #define mem_block_start(mem_block, i) \
00051 mem_block->entries[i].start
00052
00053 #define mem_block_end(mem_block, i) \
00054 mem_block->entries[i].start + mem_block->entries[i].size
00055
00056 #define mem_block_type(mem_block, i) \
00057 mem_block->entries[i].type
00058
00059 unsigned long __init parse_biosmap(struct e820_entry_s *biosentry, char map_nr)
00060 {
00061 struct e820_entry_s *bios_entry = biosentry;
00062 struct e820_entry_s bios_entry_tmp;
00063 struct memory_block_s *mem_block = &main_block;
00064 unsigned long max_ram_addr = 0;
00065 int max_entry;
00066 unsigned long max_addr;
00067 unsigned long prev_max_addr = -1;
00068 int i;
00069 int map_count = (int)map_nr;
00070
00071 do {
00072 max_entry = -1;
00073 max_addr = -1;
00074 for (i = 0; i < map_nr; i++) {
00075 if (((prev_max_addr == -1) || (bios_entry[i].start > prev_max_addr)) && (bios_entry[i].start < max_addr)) {
00076 max_entry = i;
00077 max_addr = bios_entry[i].start;
00078 }
00079 }
00080 if (max_entry == -1) break;
00081
00082 prev_max_addr = max_addr;
00083
00084 memcpy(&bios_entry_tmp, &bios_entry[max_entry], sizeof(bios_entry_tmp));
00085
00086 for (i = 0; i < mem_block->mem_nr; i++) {
00087 if (bios_entry_tmp.start < mem_block_end(mem_block, i)) {
00088 if (bios_entry_tmp.type > mem_block_type(mem_block, i)) {
00089 mem_block_size(mem_block, i) = mem_block_start(mem_block, i) -
00090 bios_entry_tmp.start;
00091 } else {
00092 bios_entry_tmp.start = mem_block_end(mem_block, i);
00093 }
00094 }
00095 }
00096
00097 add_memory_entry(mem_block, &bios_entry_tmp);
00098 if (bios_entry_tmp.type == E820_RAM) {
00099 if (max_ram_addr < bios_entry_tmp.start + bios_entry_tmp.size)
00100 max_ram_addr = bios_entry_tmp.start + bios_entry_tmp.size;
00101 }
00102
00103 map_count--;
00104 } while(map_count);
00105
00106 return max_ram_addr;
00107 }
00108
00109 void print_memory_map(struct main_memory_s *memory, int broadcast)
00110 {
00111 int i;
00112 char *e820_name;
00113
00114 if (broadcast) {
00115 printk("\n");
00116 printk(MOD_NAME "Memory size = %dKB\n", (unsigned long)(memory->mem_size));
00117 printk(MOD_NAME "Memory map (BIOS):\n");
00118 } else {
00119 printf("\n");
00120 printf(MOD_NAME "Memory size = %dKB\n", (unsigned long)(memory->mem_size));
00121 printf(MOD_NAME "Memory map (BIOS):\n");
00122 }
00123
00124 for (i = 0; i < main_block.mem_nr; i++) {
00125
00126 if (main_block.entries[i].size == 0)
00127 continue;
00128
00129 switch (main_block.entries[i].type) {
00130
00131 case E820_RAM:
00132 e820_name = "(RAM) ";
00133 break;
00134 case E820_RESERVED:
00135 e820_name = "(RESERVED)";
00136 break;
00137 case E820_ACPI:
00138 e820_name = "(ACPI) ";
00139 break;
00140 case E820_NVS:
00141 e820_name = "(NVS) ";
00142 break;
00143 default:
00144 e820_name = "(UNKNOWN) ";
00145 }
00146
00147 if (broadcast) {
00148 printk("\t%s %08x-%08x\n", e820_name, (unsigned long)main_block.entries[i].start,
00149 (unsigned long)(main_block.entries[i].start + main_block.entries[i].size));
00150 } else {
00151 printf("\t%s %08x-%08x\n", e820_name, (unsigned long)main_block.entries[i].start,
00152 (unsigned long)(main_block.entries[i].start + main_block.entries[i].size));
00153 }
00154 }
00155
00156 if (broadcast)
00157 printk("\n");
00158 else
00159 printf("\n");
00160 }
00161
00162 void bootmem_free_ram(void)
00163 {
00164 int i;
00165
00166 for (i = 0; i < main_block.mem_nr; i++) {
00167
00168 if (main_block.entries[i].size == 0)
00169 continue;
00170
00171 if (main_block.entries[i].type == E820_RAM) {
00172 bin_free_pages(&bin_alloc, (unsigned long)(main_block.entries[i].start) >> PAGE_SHIFT, (unsigned long)(main_block.entries[i].size) >> PAGE_SHIFT);
00173 }
00174 }
00175 }
00176
00177 int __init bootmem_init_bh(void)
00178 {
00179 memset(&main_memory, 0, sizeof(main_memory));
00180 memset(&main_block, 0, sizeof(main_block));
00181 INIT_LIST_HEAD(&main_memory.list);
00182 INIT_LIST_HEAD(&main_block.list);
00183 list_add(&main_block.list, &main_memory.list);
00184
00185 main_memory.mem_size = parse_biosmap(E820_MAP, E820_MAP_NR) >> 10;
00186 main_memory.pdbr = (u32)swapper_pg_dir;
00187
00188 return 0;
00189 }
00190
00191 int __init bootmem_init_dh(void)
00192 {
00193 bootmem_free_ram();
00194 bin_reserve_system_pages();
00195 print_memory_map(&main_memory, 1);
00196
00197 page_tables_init(&main_memory);
00198
00199 #if CONFIG_MEMTESTS
00200 if (do_memtests() < 0) {
00201 return -1;
00202 }
00203 #endif
00204
00205 return 0;
00206 }
00207
00208 int bootmem_free_init(void)
00209 {
00210 u32 init_start = (u32)&__init_begin;
00211 u32 init_end = (u32)&__init_end;
00212
00213 printk("Freeing __init segment (%d kb)\n", (init_end - init_start) >> 10);
00214
00215 return 0;
00216 }
00217
00218 void bootmem_print_memory(void)
00219 {
00220 print_memory_map(&main_memory, 0);
00221 }