/* * mem_init - initializes memory * * Frees up bootmem * Calculates and displays memory available/used */ void __init mem_init(void) { int codesize, datasize, initsize, reserved_pages, free_pages; int tmp; high_memory = (void *)(CONFIG_LINUX_LINK_BASE + arc_mem_sz); free_all_bootmem(); /* count all reserved pages [kernel code/data/mem_map..] */ reserved_pages = 0; for (tmp = 0; tmp < max_mapnr; tmp++) if (PageReserved(mem_map + tmp)) reserved_pages++; /* XXX: nr_free_pages() is equivalent */ free_pages = max_mapnr - reserved_pages; /* * For the purpose of display below, split the "reserve mem" * kernel code/data is already shown explicitly, * Show any other reservations (mem_map[ ] et al) */ reserved_pages -= (((unsigned int)_end - CONFIG_LINUX_LINK_BASE) >> PAGE_SHIFT); codesize = _etext - _text; datasize = _end - _etext; initsize = __init_end - __init_begin; pr_info("Memory Available: %dM / %ldM (%dK code, %dK data, %dK init, %dK reserv)\n", PAGES_TO_MB(free_pages), TO_MB(arc_mem_sz), TO_KB(codesize), TO_KB(datasize), TO_KB(initsize), PAGES_TO_KB(reserved_pages)); }
int init_boot_information ( uint32_t magic, mbootinfo_t *mbi, sysinfo_t *sys_info ) { int i = 0; memset((void *) sys_info, 0x00, sizeof(sysinfo_t)); /* Integrity check */ if(magic != MULTIBOOT_INFO_MAGIC) { printk("[INFO] Invalid magic number (%x)\n", magic); return -1; } if (!CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_MEMORY)) { printk ( "[FATAL] There is no memory information " "on multiboot structure\n" ); return -1; } sys_info->sys_kern_start = (vaddr_t) &KERN_TEXT_BEGIN; sys_info->sys_kern_end = (vaddr_t) &KERN_TOP; sys_info->sys_lomem = mbi->mi_mem_lower*1024; sys_info->sys_himem = mbi->mi_mem_upper*1024; sys_info->sys_page_size = PAGE_SIZE; /** HiMem empieza desde el mega a contar asi que le tenemos que sumar */ sys_info->sys_memory = sys_info->sys_lomem + sys_info->sys_himem + 1024*1024; paddr_t seg_start = 0, seg_end = 0; if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_MMAP)) { struct multiboot_mmap *mmap; #ifdef DEBUG printk("[mboot] Memory maps:\n"); #endif for(mmap = (struct multiboot_mmap *) mbi->mi_mmap_addr; (unsigned long) mmap < mbi->mi_mmap_addr + mbi->mi_mmap_length; mmap = (struct multiboot_mmap *) ((unsigned long) mmap + mmap->mm_size + sizeof (mmap->mm_size))) { /* Tenemos un limite maximo estatico de # de segmentos */ if (i == VM_MAX_SEGMENTS) { printk("[NOTICE] Too many segments increase VM_MAX_SEGMENTS\n"); break; } /* Si el tipo no es AVAILABLE RAM skipeamos */ if(mmap->mm_type != AVL_RAM) { continue; } /* Por ahora usamos la parte baja del puntero que nos da GRUB */ seg_start = mmap->mm_base_addr_low; seg_end = mmap->mm_base_addr_low + mmap->mm_length_low; if(seg_start < 0x100000 && seg_end > 0xa0000) { printk("[NOTICE] segment overlaps with ``Compatibility Holes''\n"); sys_info->sys_addr_space.segments[i].seg_start = seg_start; sys_info->sys_addr_space.segments[i].seg_end = 0xa0000; sys_info->sys_addr_space.segments[i].seg_type = mmap->mm_type; sys_info->sys_addr_space.segments_number++; i++; sys_info->sys_addr_space.segments[i].seg_start = 0x100000; sys_info->sys_addr_space.segments[i].seg_end = seg_end; sys_info->sys_addr_space.segments[i].seg_type = mmap->mm_type; sys_info->sys_addr_space.segments_number++; i++; } else { sys_info->sys_addr_space.segments[i].seg_start = seg_start; sys_info->sys_addr_space.segments[i].seg_end = seg_end; sys_info->sys_addr_space.segments[i].seg_type = mmap->mm_type; sys_info->sys_addr_space.segments_number++; i++; } } } /* Inicializamos en el maximo PFN */ sys_info->sys_minpfn = PFN_UP(0xffffffff); /* Inicializamos en el mninimo PFN */ sys_info->sys_maxpfn = PFN_DOWN(0); /* Buscamos el Minimum page frame number y el Maximun Page Frame number */ for(i = 0; i < sys_info->sys_addr_space.segments_number; i++) { sys_info->sys_minpfn = min(sys_info->sys_minpfn, PFN_UP(sys_info->sys_addr_space.segments[i].seg_start)); sys_info->sys_maxpfn = max(sys_info->sys_maxpfn, PFN_DOWN(sys_info->sys_addr_space.segments[i].seg_end)); } sys_info->sys_pages = sys_info->sys_maxpfn+1; /* * FIXME: Aca hay un error, el maxpfn esta mal calculado * por que lo estoy tomando con respecto a seg_end y si seg_end * termina al medio de una pagina, el max_pfn tendira que ser * el numero de pagina al que corresponde seg_end menos 1. No lo arreglo * por que cuando hago los cambios no se por que carajo crashea. Si * te das cuenta por que pasa Gaston, arreglalo. * Sino, mas adelante loveo. */ #define PAGES_TO_MB(x) ((x) >> (20-PAGE_SHIFT)) printk("[INFO] %ldMB LOWMEM available.\n", PAGES_TO_MB(sys_info->sys_maxpfn)); if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_VBE)) { printk("[mboot] VBE Information present\n"); DUMP(mbi->mi_vbe_control_info, "%p\n"); DUMP(mbi->mi_vbe_mode_info, "%p\n"); DUMP(mbi->mi_vbe_interface_seg, "%d\n"); DUMP(mbi->mi_vbe_interface_off, "%d\n"); DUMP(mbi->mi_vbe_interface_len, "%d\n"); } if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_DRIVES)) { #ifdef DEBUG int i, count; struct multiboot_drive *mbd = (struct multiboot_drive *) mbi->mi_drives_addr; count = mbi->mi_drives_length / sizeof(struct multiboot_drive); printk("[mboot] Drives information:\n"); for(i = 0; i < count; i++, mbd++) { printk ( " | Bios drive number: %d\n" " | Drive Mode: %s\n" " | C = %d | H = %d | S = %d | BLOCKS = %d | Size = %d\n", mbd->md_number, (mbd->md_mode ? "LBA" : "CHS"), mbd->md_cylinders, mbd->md_heads, mbd->md_sectors, mbd->md_cylinders * mbd->md_heads * mbd->md_sectors, mbd->md_cylinders * mbd->md_heads * mbd->md_sectors * 512 ); } #endif /* DEBUG */ } #ifdef DEBUG if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_BOOT_DEVICE)) { printk ("[mboot] Device drive: 0x%x\n", mbi->mi_boot_device_drive); } if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_CMDLINE)) { printk ("[mboot] Command line: %s\n", mbi->mi_cmdline); } if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_MODS)) { struct multiboot_module *mod; int i; printk ( "[mboot] Number of loaded modules: %d\n", (int) mbi->mi_mods_count ); mod = (void *) mbi->mi_mods_addr; for (i = 0; i < mbi->mi_mods_count; i++, mod++) { printk ( "\t[%u] mod_start = 0x%x, mod_end = 0x%x, string = %s\n", (unsigned) i, (unsigned) mod->mm_mod_start, (unsigned) mod->mm_mod_end, (char *) mod->mm_string ); } } if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_AOUT_SYMS) && CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_ELF_SYMS)) { printk("[Error] Cannot have both, ELF header and aout header\n"); return -1; } /* Is the symbol table of a.out valid? */ if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_AOUT_SYMS)) { struct multiboot_aout_symtab *aout_sym = &(mbi->u.aout_sym); printk ( "aout_symbol_table: tabsize = 0x%0x, " "strsize = 0x%x, addr = 0x%x\n", aout_sym->ma_tabsize, aout_sym->ma_strsize, aout_sym->ma_addr ); } /* Is the section header table of ELF valid? */ if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_ELF_SYMS)) { struct multiboot_elf_sh_table *elf_sec = &(mbi->u.elf_sec); printk ( "[mboot] elf_sec: num = %u, size = 0x%x," " addr = 0x%x, shndx = 0x%x\n", elf_sec->me_num, elf_sec->me_size, elf_sec->me_addr, elf_sec->me_shndx ); } if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_CONFIG_TABLE)) { } if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_LOADER_NAME)) { printk("[mboot] Loaded by: %s\n", mbi->mi_loader_name); } if (CHECK_BIT (mbi->mi_flags, MULTIBOOT_INFO_HAS_APM_TABLE)) { printk("[mboot] APM Information present\n"); struct multiboot_apm *apm_info = (struct multiboot_apm *) mbi->mi_apm_table; printk( " version : %x\n", apm_info->ma_version ); printk( " cseg : %x\n", apm_info->ma_cseg ); printk( " offset : %x\n", apm_info->ma_offset ); printk( " cseg_16 : %x\n", apm_info->ma_cseg_16 ); printk( " dseg : %x\n", apm_info->ma_dseg ); printk( " flags : %x\n", apm_info->ma_flags ); printk( " cseg_len : %x\n", apm_info->ma_cseg_len ); printk( " cseg_16_len : %x\n", apm_info->ma_cseg_16_len ); printk( " dseg_len : %x\n", apm_info->ma_dseg_len ); } #endif /* DEBUG */ return 0; }