1 /* Copyright (c) 2009,13 The Regents of the University of California
2 * Barret Rhoden <brho@cs.berkeley.edu>
3 * Kevin Klues <klueska@cs.berkeley.edu>
4 * See LICENSE for details.
6 * Multiboot parsing and helper functions. */
9 #include <ros/common.h>
11 #include <arch/arch.h>
12 #include <ros/memlayout.h>
17 #include <arch/apic.h>
20 /* Misc dead code to read from mboot. We'll need to do this to run a legit
21 * initrd from grub (module /initramfs.cpio, or whatever). */
22 static void mboot_parsing(struct multiboot_info *mbi)
24 if (mbi->flags & MULTIBOOT_INFO_BOOTDEV)
25 printk("MBI: boot_device = 0x%08x\n", mbi->boot_device);
26 if (mbi->flags & MULTIBOOT_INFO_CMDLINE)
27 printk("MBI: command line: %s\n",
28 (char*)((physaddr_t)mbi->cmdline + KERNBASE));
29 if (mbi->flags & MULTIBOOT_INFO_MODS) {
30 printk("MBI: nr mods, %d: mods addr %p\n", mbi->mods_count,
35 bool mboot_has_mmaps(struct multiboot_info *mbi)
37 return mbi->flags & MULTIBOOT_INFO_MEM_MAP;
40 /* This only notices bios detectable memory - there's a lot more in the higher
42 void mboot_detect_memory(struct multiboot_info *mbi)
44 physaddr_t max_bios_mem;
45 physaddr_t max_bios_addr;
48 if (!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
49 printk("No BIOS memory info from multiboot, crash impending!\n");
52 /* mem_lower and upper are measured in KB. They are 32 bit values, so we're
53 * limited to 4TB total. */
54 basemem = ROUNDDOWN((size_t)mbi->mem_lower * 1024, PGSIZE);
55 /* On 32 bit, This shift << 10 could cause us to lose some memory, but we
56 * weren't going to access it anyways (won't go beyond ~1GB) */
57 extmem = ROUNDDOWN((size_t)mbi->mem_upper * 1024, PGSIZE);
58 /* Calculate the maximum physical address based on whether or not there is
59 * any extended memory. */
61 max_bios_mem = EXTPHYSMEM + extmem;
62 /* On 32 bit, if we had enough RAM that adding a little wrapped us
63 * around, we'll back off a little and run with just extmem amount (in
64 * essence, subtracing 1MB). */
65 if (max_bios_mem < extmem)
66 max_bios_mem = extmem;
68 max_bios_mem = basemem;
70 max_bios_addr = MIN(max_bios_mem, KERN_VMAP_TOP - KERNBASE);
71 printk("Base memory: %luK, Extended memory: %luK\n", basemem / 1024,
73 printk("Maximum directly addressable base and extended memory: %luK\n",
74 max_bios_addr / 1024);
75 /* Take a first stab at the max pmem, in case there are no memory mappings
77 max_pmem = max_bios_mem;
80 void mboot_foreach_mmap(struct multiboot_info *mbi, mboot_foreach_t func,
83 struct multiboot_mmap_entry *mmap_b, *mmap_e, *mmap_i;
84 if (!mboot_has_mmaps(mbi)) {
85 printd("No memory mapping info from multiboot\n");
88 mmap_b = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE);
89 mmap_e = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE
91 printd("mmap_addr = %p, mmap_length = %p\n", mbi->mmap_addr,
93 /* Note when we incremement mmap_i, we add in the value of size... */
96 mmap_i = (struct multiboot_mmap_entry*)((void*)mmap_i + mmap_i->size
97 + sizeof(mmap_i->size))) {
102 void mboot_print_mmap(struct multiboot_info *mbi)
104 void print_entry(struct multiboot_mmap_entry *entry, void *data)
106 printk("Base = 0x%016llx, Length = 0x%016llx : %s\n",
107 entry->addr, entry->len,
108 entry->type == MULTIBOOT_MEMORY_AVAILABLE ? "FREE" :
111 mboot_foreach_mmap(mbi, print_entry, 0);
114 /* Given a range of memory, will tell us if multiboot is using anything we care
115 * about in that range. It usually uses memory below 1MB, so boot_alloc is
116 * fine. This is pre, so MBI is still a paddr. */
117 bool mboot_region_collides(struct multiboot_info *mbi, uintptr_t base,
120 if (regions_collide_unsafe((uintptr_t)mbi,
121 (uintptr_t)mbi + sizeof(struct multiboot_info),
124 if (mboot_has_mmaps(mbi)) {
125 if (regions_collide_unsafe((uintptr_t)mbi->mmap_addr + KERNBASE,
126 (uintptr_t)mbi->mmap_addr + KERNBASE