1 // arch/x86/multiboot.cc -- Code to interpret multiboot data and initialize
2 // free memory regions based thereupon.
4 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 // this software and associated documentation files (the "Software"), to deal with
8 // the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 // of the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following conditions:
13 // * Redistributions of source code must retain the above copyright notice,
14 // this list of conditions and the following disclaimers.
16 // * Redistributions in binary form must reproduce the above copyright notice,
17 // this list of conditions and the following disclaimers in the
18 // documentation and/or other materials provided with the distribution.
20 // * The names of the Software's authors and/or contributors
21 // may not be used to endorse or promote products derived from
22 // this Software without specific prior written permission.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
26 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
32 #include <kern/libc.h>
33 #include <kern/pagealloc.h>
35 #include <arch/multiboot.h>
36 #include <arch/addrs.h>
37 #include <arch/paging.h>
40 #include <util/misc.h>
43 u32 x86_boot_info_phys;
56 using Util::round_down;
58 void make_mem_avail(u64 start, u64 end)
65 for (int i = 0; i < num_zones; i++) {
66 u64 rstart = mem_zone_regions[i].start;
67 u64 rend = mem_zone_regions[i].end;
69 if (start <= rend && end >= rstart) {
75 ulong page_len = (rend - rstart + 1) / page_size;
76 pagezones[i].free(Mem::phys_to_page(rstart), page_len);
83 if (x86_boot_info_phys > max_ktext_map) {
84 printf("Cannot access boot info at %#.8x\n", x86_boot_info_phys);
88 boot_info = (BootInfo *)phys_to_kvirt(x86_boot_info_phys);
91 if (!(boot_info->flags & (1 << BootInfo::flag_mmap))) {
92 // FIXME: use mem_lower and mem_upper in this case.
93 printf("MultiBoot info does not contain a memory map.\n");
97 printf("BIOS Memory Map:\n");
100 while (off < boot_info->mmap_length) {
101 u32 phys = boot_info->mmap_addr + off;
103 if (phys > max_ktext_map) {
104 printf("Cannot access BIOS memory map entry at %#.8x\n", phys);
108 MemMap *mmap = (MemMap *)phys_to_kvirt(phys);
110 printf("0x%016llx - 0x%016llx, type %d\n",
111 mmap->base, mmap->base + mmap->len - 1, mmap->type);
113 off += mmap->size + 4;
115 if (mmap->type == MemMap::Available) {
116 u64 end = mmap->base + mmap->len;
125 // Don't make available any pages that overlap the
126 // kernel text/data or bootmem allocations.
128 u64 kernelstart = round_down(kvirt_to_phys(&_start), page_shift);
129 u64 kernelend = round_up(kvirt_to_phys((void *)next_free_bootmem),
133 while (off < boot_info->mmap_length) {
134 u32 phys = boot_info->mmap_addr + off;
135 MemMap *mmap = (MemMap *)phys_to_kvirt(phys);
136 off += mmap->size + 4;
138 if (mmap->type == MemMap::Available) {
139 // Don't use any page that isn't fully in this entry.
141 u64 start = round_up(mmap->base, page_shift);
142 u64 end = round_down(mmap->base + mmap->len, page_shift) - 1;
144 // Don't overwrite page 1; the BIOS will need it for later calls in
145 // emulation, and at least the BIOS I'm testing on doesn't mark
148 if (start < page_size)
151 if (start <= kernelend && end >= kernelstart) {
152 if (start < kernelstart)
153 make_mem_avail(start, kernelstart - 1);
156 make_mem_avail(kernelend + 1, end);
158 make_mem_avail(start, end);