00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cpu/x86/multiboot.h>
00022 #include <string.h>
00023 #include <device/resource.h>
00024 #include <console/console.h>
00025
00026 typedef unsigned long long u64;
00027
00028 static struct multiboot_mmap_entry *mb_mem;
00029 struct multiboot_info *mbi;
00030
00031 static struct {
00032 u64 addr;
00033 u64 len;
00034 } reserved_mem[2];
00035
00036 static void build_mb_mem_range_nooverlap(u64 addr, u64 len)
00037 {
00038 int i;
00039 for (i = 0; i < sizeof(reserved_mem) / sizeof(reserved_mem[0]); i++) {
00040
00041 if (addr >= reserved_mem[i].addr && addr + len <= reserved_mem[i].addr + reserved_mem[i].len)
00042 return;
00043
00044 if (addr < reserved_mem[i].addr && addr + len > reserved_mem[i].addr + reserved_mem[i].len) {
00045 build_mb_mem_range_nooverlap(addr, reserved_mem[i].addr - addr);
00046 build_mb_mem_range_nooverlap(reserved_mem[i].addr + reserved_mem[i].len, (addr + len) - (reserved_mem[i].addr + reserved_mem[i].len));
00047 return;
00048 }
00049
00050 if (addr < reserved_mem[i].addr + reserved_mem[i].len && addr + len > reserved_mem[i].addr + reserved_mem[i].len) {
00051 len += addr;
00052 addr = reserved_mem[i].addr + reserved_mem[i].len;
00053 len -= addr;
00054
00055 continue;
00056 }
00057
00058 if (addr < reserved_mem[i].addr && addr + len > reserved_mem[i].addr) {
00059 len = reserved_mem[i].addr - addr;
00060 continue;
00061 }
00062
00063 }
00064
00065 mb_mem->addr = addr;
00066 mb_mem->len = len;
00067 mb_mem->type = 1;
00068 mb_mem->size = sizeof(*mb_mem) - sizeof(mb_mem->size);
00069 mb_mem++;
00070 }
00071
00072 static void build_mb_mem_range(void *gp, struct device *dev, struct resource *res)
00073 {
00074 build_mb_mem_range_nooverlap(res->base, res->size);
00075 }
00076
00077 #define ROUND(_r,_a) ((_r) + (((_a) - 1)) & ~((_a) - 1))
00078
00079 unsigned long write_multiboot_info(
00080 unsigned long low_table_start, unsigned long low_table_end,
00081 unsigned long rom_table_start, unsigned long rom_table_end)
00082 {
00083 struct multiboot_info *mbi;
00084 int i;
00085
00086 mbi = rom_table_end;
00087 memset(mbi, 0, sizeof(*mbi));
00088 rom_table_end += sizeof(*mbi);
00089
00090 mbi->mmap_addr = (u32) rom_table_end;
00091 mb_mem = rom_table_end;
00092
00093
00094 reserved_mem[0].addr = low_table_start;
00095 reserved_mem[0].len = ROUND(low_table_end - low_table_start, 4096);
00096 reserved_mem[1].addr = rom_table_start;
00097 reserved_mem[1].len = ROUND(rom_table_end - rom_table_start, 4096);
00098
00099 for (i = 0; i < sizeof(reserved_mem) / sizeof(reserved_mem[0]); i++) {
00100 mb_mem->addr = reserved_mem[i].addr;
00101 mb_mem->len = reserved_mem[i].len;
00102 mb_mem->type = 2;
00103 mb_mem->size = sizeof(*mb_mem) - sizeof(mb_mem->size);
00104 mb_mem++;
00105 }
00106
00107
00108 search_global_resources( IORESOURCE_MEM | IORESOURCE_CACHEABLE,
00109 IORESOURCE_MEM | IORESOURCE_CACHEABLE, build_mb_mem_range, NULL);
00110
00111 mbi->mmap_length = ((u32) mb_mem) - mbi->mmap_addr;
00112 mbi->flags |= MB_INFO_MEM_MAP;
00113
00114 printk_info("Multiboot Information structure has been written.\n");
00115
00116 return mb_mem;
00117 }