9ns: ensure the parent of a rename target is a directory
[akaros.git] / kern / src / multiboot.c
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). */
22 static 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
35 bool 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. */
42 void 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
80 void 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
104 void 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. */
119 bool 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 }