akaros/kern/src/multiboot.c
<<
>>
Prefs
   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.
   5 *
   6 * Multiboot parsing and helper functions. */
   7
   8#include <multiboot.h>
   9#include <ros/common.h>
  10#include <arch/mmu.h>
  11#include <arch/arch.h>
  12#include <ros/memlayout.h>
  13#include <stdio.h>
  14#include <pmap.h>
  15
  16#ifdef CONFIG_X86
  17#include <arch/apic.h>
  18#endif
  19
  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). */
  22static void mboot_parsing(struct multiboot_info *mbi)
  23{
  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,
  31                       mbi->mods_addr);
  32        }
  33}
  34
  35bool mboot_has_mmaps(struct multiboot_info *mbi)
  36{
  37        return mbi->flags & MULTIBOOT_INFO_MEM_MAP;
  38}
  39
  40/* This only notices bios detectable memory - there's a lot more in the higher
  41 * paddrs. */
  42void mboot_detect_memory(struct multiboot_info *mbi)
  43{
  44        physaddr_t max_bios_mem;
  45        physaddr_t max_bios_addr;
  46        size_t basemem;
  47        size_t extmem;
  48        if (!(mbi->flags & MULTIBOOT_INFO_MEMORY)) {
  49                printk("No BIOS memory info from multiboot, crash impending\n");
  50                return;
  51        }
  52        /* mem_lower and upper are measured in KB.  They are 32 bit values, so
  53         * we're 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
  56         * we 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
  59         * is any extended memory. */
  60        if (extmem) {
  61                max_bios_mem = EXTPHYSMEM + extmem;
  62                /* On 32 bit, if we had enough RAM that adding a little wrapped
  63                 * us around, we'll back off a little and run with just extmem
  64                 * amount (in essence, subtracing 1MB). */
  65                if (max_bios_mem < extmem)
  66                        max_bios_mem = extmem;
  67        } else {
  68                max_bios_mem = basemem;
  69        }
  70        max_bios_addr = MIN(max_bios_mem, KERN_VMAP_TOP - KERNBASE);
  71        printk("Base memory: %luK, Extended memory: %luK\n", basemem / 1024,
  72               extmem / 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
  76         * mappings (like in riscv) */
  77        max_pmem = max_bios_mem;
  78}
  79
  80void mboot_foreach_mmap(struct multiboot_info *mbi, mboot_foreach_t func,
  81                        void *data)
  82{
  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");
  86                return;
  87        }
  88        mmap_b = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr +
  89                                                KERNBASE);
  90        mmap_e = (struct multiboot_mmap_entry*)((size_t)mbi->mmap_addr +
  91                                                KERNBASE + mbi->mmap_length);
  92        printd("mmap_addr = %p, mmap_length = %p\n", mbi->mmap_addr,
  93               mbi->mmap_length);
  94        /* Note when we incremement mmap_i, we add in the value of size... */
  95        for (mmap_i = mmap_b;
  96             mmap_i < mmap_e;
  97             mmap_i = (struct multiboot_mmap_entry*)((void*)mmap_i +
  98                                                     mmap_i->size +
  99                                                     sizeof(mmap_i->size))) {
 100                func(mmap_i, data);
 101        }
 102}
 103
 104void mboot_print_mmap(struct multiboot_info *mbi)
 105{
 106        void print_entry(struct multiboot_mmap_entry *entry, void *data)
 107        {
 108                printk("Base = 0x%016llx, Length = 0x%016llx : %s\n",
 109                       entry->addr, entry->len,
 110                       entry->type == MULTIBOOT_MEMORY_AVAILABLE ? "FREE" :
 111                                                                   "RESERVED");
 112        }
 113        mboot_foreach_mmap(mbi, print_entry, 0);
 114}
 115
 116/* Given a range of memory, will tell us if multiboot is using anything we care
 117 * about in that range.  It usually uses memory below 1MB, so boot_alloc is
 118 * fine.  This is pre, so MBI is still a paddr. */
 119bool mboot_region_collides(struct multiboot_info *mbi, uintptr_t base,
 120                           uintptr_t end)
 121{
 122        if (regions_collide_unsafe((uintptr_t)mbi, (uintptr_t)mbi +
 123                                   sizeof(struct multiboot_info), base, end))
 124                return TRUE;
 125        if (mboot_has_mmaps(mbi)) {
 126                if (regions_collide_unsafe((uintptr_t)mbi->mmap_addr + KERNBASE,
 127                                           (uintptr_t)mbi->mmap_addr + KERNBASE
 128                                           + mbi->mmap_length, base, end))
 129                        return TRUE;
 130        }
 131        return FALSE;
 132}
 133