/* Copyright (c) 2009,13 The Regents of the University of California
* Barret Rhoden <brho@cs.berkeley.edu>
* Kevin Klues <klueska@cs.berkeley.edu>
- * See LICENSE for details.
+ * See LICENSE for details.
*
- * Multiboot parsing. */
+ * Multiboot parsing and helper functions. */
#include <multiboot.h>
#include <ros/common.h>
#include <arch/arch.h>
#include <ros/memlayout.h>
#include <stdio.h>
+#include <pmap.h>
#ifdef CONFIG_X86
#include <arch/apic.h>
#endif
-physaddr_t maxpa; /* Maximum physical address in the system */
-physaddr_t maxaddrpa; /* Maximum addressable physical address */
-size_t npages; /* Total number of physical memory pages */
-size_t naddrpages; /* num of addressable physical memory pages */
+/* Misc dead code to read from mboot. We'll need to do this to run a legit
+ * initrd from grub (module /initramfs.cpio, or whatever). */
+static void mboot_parsing(struct multiboot_info *mbi)
+{
+ if (mbi->flags & MULTIBOOT_INFO_BOOTDEV)
+ printk("MBI: boot_device = 0x%08x\n", mbi->boot_device);
+ if (mbi->flags & MULTIBOOT_INFO_CMDLINE)
+ printk("MBI: command line: %s\n",
+ (char*)((physaddr_t)mbi->cmdline + KERNBASE));
+ if (mbi->flags & MULTIBOOT_INFO_MODS) {
+ printk("MBI: nr mods, %d: mods addr %p\n", mbi->mods_count,
+ mbi->mods_addr);
+ }
+}
-static size_t basemem; /* Amount of base memory (in bytes) */
-static size_t extmem; /* Amount of extended memory (in bytes) */
+bool mboot_has_mmaps(struct multiboot_info *mbi)
+{
+ return mbi->flags & MULTIBOOT_INFO_MEM_MAP;
+}
/* This only notices bios detectable memory - there's a lot more in the higher
* paddrs. */
-void mboot_detect_memory(multiboot_info_t *mbi)
+void mboot_detect_memory(struct multiboot_info *mbi)
{
+ physaddr_t max_bios_mem;
+ physaddr_t max_bios_addr;
+ size_t basemem;
+ size_t extmem;
if (!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
printk("No BIOS memory info from multiboot, crash impending!\n");
return;
}
/* mem_lower and upper are measured in KB. They are 32 bit values, so we're
* limited to 4TB total. */
- size_t basemem = ROUNDDOWN((size_t)mbi->mem_lower * 1024, PGSIZE);
- size_t extmem = ROUNDDOWN((size_t)mbi->mem_upper * 1024, PGSIZE);
+ basemem = ROUNDDOWN((size_t)mbi->mem_lower * 1024, PGSIZE);
+ /* On 32 bit, This shift << 10 could cause us to lose some memory, but we
+ * weren't going to access it anyways (won't go beyond ~1GB) */
+ extmem = ROUNDDOWN((size_t)mbi->mem_upper * 1024, PGSIZE);
/* Calculate the maximum physical address based on whether or not there is
* any extended memory. */
- if (extmem)
- maxpa = EXTPHYSMEM + extmem;
- else
- maxpa = basemem;
- npages = maxpa / PGSIZE;
- /* KERN_VMAP_TOP - KERNBASE is the max amount of virtual addresses we can
- * use for the physical memory mapping (aka - the KERNBASE mapping) */
- maxaddrpa = MIN(maxpa, KERN_VMAP_TOP - KERNBASE);
- naddrpages = maxaddrpa / PGSIZE;
- printk("Physical memory: %luK available, ", maxpa / 1024);
- printk("base = %luK, extended = %luK\n", basemem / 1024, extmem / 1024);
- printk("Maximum directly addressable physical memory: %luK\n",
- maxaddrpa / 1024);
+ if (extmem) {
+ max_bios_mem = EXTPHYSMEM + extmem;
+ /* On 32 bit, if we had enough RAM that adding a little wrapped us
+ * around, we'll back off a little and run with just extmem amount (in
+ * essence, subtracing 1MB). */
+ if (max_bios_mem < extmem)
+ max_bios_mem = extmem;
+ } else {
+ max_bios_mem = basemem;
+ }
+ max_bios_addr = MIN(max_bios_mem, KERN_VMAP_TOP - KERNBASE);
+ printk("Base memory: %luK, Extended memory: %luK\n", basemem / 1024,
+ extmem / 1024);
+ printk("Maximum directly addressable base and extended memory: %luK\n",
+ max_bios_addr / 1024);
+ /* Take a first stab at the max pmem, in case there are no memory mappings
+ * (like in riscv) */
+ max_pmem = max_bios_mem;
}
-/* TODO: Use the info from this for our free pages, instead of just using
- * the extended memory */
-void mboot_print_mmap(multiboot_info_t *mbi)
+void mboot_foreach_mmap(struct multiboot_info *mbi, mboot_foreach_t func,
+ void *data)
{
- multiboot_memory_map_t *mmap_b, *mmap_e, *mmap_i;
- if (!(mbi->flags & MULTIBOOT_INFO_ELF_SHDR)) {
- printk("No memory mapping info from multiboot\n");
+ struct multiboot_mmap_entry *mmap_b, *mmap_e, *mmap_i;
+ if (!mboot_has_mmaps(mbi)) {
+ printd("No memory mapping info from multiboot\n");
return;
}
- mmap_b = (multiboot_memory_map_t*)((size_t)mbi->mmap_addr + KERNBASE);
- mmap_e = (multiboot_memory_map_t*)((size_t)mbi->mmap_addr + KERNBASE
+ mmap_b = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE);
+ mmap_e = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr + KERNBASE
+ mbi->mmap_length);
printd("mmap_addr = %p, mmap_length = %p\n", mbi->mmap_addr,
mbi->mmap_length);
- printd("mmap_b %p, mmap_e %p\n", mmap_b, mmap_e);
/* Note when we incremement mmap_i, we add in the value of size... */
for (mmap_i = mmap_b;
mmap_i < mmap_e;
- mmap_i = (multiboot_memory_map_t*)((void*)mmap_i + mmap_i->size
- + sizeof(mmap_i->size))) {
- printk("base = 0x%016llx, length = 0x%016llx : %s\n",
- mmap_i->addr, mmap_i->len,
- mmap_i->type == MULTIBOOT_MEMORY_AVAILABLE ? "FREE" :
- "RESERVED");
+ mmap_i = (struct multiboot_mmap_entry*)((void*)mmap_i + mmap_i->size
+ + sizeof(mmap_i->size))) {
+ func(mmap_i, data);
}
}
+void mboot_print_mmap(struct multiboot_info *mbi)
+{
+ void print_entry(struct multiboot_mmap_entry *entry, void *data)
+ {
+ printk("Base = 0x%016llx, Length = 0x%016llx : %s\n",
+ entry->addr, entry->len,
+ entry->type == MULTIBOOT_MEMORY_AVAILABLE ? "FREE" :
+ "RESERVED");
+ }
+ mboot_foreach_mmap(mbi, print_entry, 0);
+}
+
+/* Given a range of memory, will tell us if multiboot is using anything we care
+ * about in that range. It usually uses memory below 1MB, so boot_alloc is
+ * fine. This is pre, so MBI is still a paddr. */
+bool mboot_region_collides(struct multiboot_info *mbi, uintptr_t base,
+ uintptr_t end)
+{
+ if (regions_collide_unsafe((uintptr_t)mbi,
+ (uintptr_t)mbi + sizeof(struct multiboot_info),
+ base, end))
+ return TRUE;
+ if (mboot_has_mmaps(mbi)) {
+ if (regions_collide_unsafe((uintptr_t)mbi->mmap_addr + KERNBASE,
+ (uintptr_t)mbi->mmap_addr + KERNBASE
+ + mbi->mmap_length,
+ base, end))
+ return TRUE;
+ }
+ return FALSE;
+}