diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/i386/boot/multiboot.c | 97 | ||||
-rw-r--r-- | src/arch/i386/boot/tables.c | 20 | ||||
-rw-r--r-- | src/include/cpu/x86/multiboot.h | 5 |
3 files changed, 42 insertions, 80 deletions
diff --git a/src/arch/i386/boot/multiboot.c b/src/arch/i386/boot/multiboot.c index a47c0b4af4..4059f2736b 100644 --- a/src/arch/i386/boot/multiboot.c +++ b/src/arch/i386/boot/multiboot.c @@ -22,62 +22,16 @@ #include <string.h> #include <device/resource.h> #include <console/console.h> +#include <boot/coreboot_tables.h> +#include <arch/coreboot_tables.h> -static struct multiboot_mmap_entry *mb_mem; struct multiboot_info *mbi = NULL; -static struct { - u64 addr; - u64 len; -} reserved_mem[2]; - -static void build_mb_mem_range_nooverlap(u64 addr, u64 len) -{ - int i; - for (i = 0; i < sizeof(reserved_mem) / sizeof(reserved_mem[0]); i++) { - /* free region fully contained in reserved region, abort */ - if (addr >= reserved_mem[i].addr && addr + len <= reserved_mem[i].addr + reserved_mem[i].len) - return; - /* reserved region splits free region */ - if (addr < reserved_mem[i].addr && addr + len > reserved_mem[i].addr + reserved_mem[i].len) { - build_mb_mem_range_nooverlap(addr, reserved_mem[i].addr - addr); - build_mb_mem_range_nooverlap(reserved_mem[i].addr + reserved_mem[i].len, (addr + len) - (reserved_mem[i].addr + reserved_mem[i].len)); - return; - } - /* left overlap */ - if (addr < reserved_mem[i].addr + reserved_mem[i].len && addr + len > reserved_mem[i].addr + reserved_mem[i].len) { - len += addr; - addr = reserved_mem[i].addr + reserved_mem[i].len; - len -= addr; - /* len += addr - old_addr */ - continue; - } - /* right overlap */ - if (addr < reserved_mem[i].addr && addr + len > reserved_mem[i].addr) { - len = reserved_mem[i].addr - addr; - continue; - } - /* none of the above, just add it */ - } - - mb_mem->addr = addr; - mb_mem->len = len; - mb_mem->type = 1; - mb_mem->size = sizeof(*mb_mem) - sizeof(mb_mem->size); - mb_mem++; -} - -static void build_mb_mem_range(void *gp, struct device *dev, struct resource *res) -{ - build_mb_mem_range_nooverlap(res->base, res->size); -} - -#define ROUND(_r,_a) (((_r) + (((_a) - 1))) & ~((_a) - 1)) - -unsigned long write_multiboot_info( - unsigned long low_table_start, unsigned long low_table_end, - unsigned long rom_table_start, unsigned long rom_table_end) +unsigned long write_multiboot_info(unsigned long rom_table_end) { + static struct multiboot_mmap_entry *mb_mem; + struct lb_memory* coreboot_table; + int entries; int i; mbi = (struct multiboot_info *)rom_table_end; @@ -88,26 +42,31 @@ unsigned long write_multiboot_info( mbi->mmap_addr = (u32) rom_table_end; mb_mem = (struct multiboot_mmap_entry *)rom_table_end; - /* FIXME This code is broken, it does not know about high memory - * tables, nor does it reserve the coreboot table area. - */ - /* reserved regions */ - reserved_mem[0].addr = low_table_start; - reserved_mem[0].len = ROUND(low_table_end - low_table_start, 4096); - reserved_mem[1].addr = rom_table_start; - reserved_mem[1].len = ROUND(rom_table_end - rom_table_start, 4096); + /* copy regions from coreboot tables */ + coreboot_table = get_lb_mem(); + entries = (coreboot_table->size - sizeof(*coreboot_table))/sizeof(coreboot_table->map[0]); - for (i = 0; i < sizeof(reserved_mem) / sizeof(reserved_mem[0]); i++) { - mb_mem->addr = reserved_mem[i].addr; - mb_mem->len = reserved_mem[i].len; - mb_mem->type = 2; - mb_mem->size = sizeof(*mb_mem) - sizeof(mb_mem->size); - mb_mem++; + if (coreboot_table == NULL || entries < 1) { + printk(BIOS_INFO, "%s: Cannot find coreboot table.\n", __func__); + return (unsigned long) mb_mem; } - /* free regions */ - search_global_resources( IORESOURCE_MEM | IORESOURCE_CACHEABLE, - IORESOURCE_MEM | IORESOURCE_CACHEABLE, build_mb_mem_range, NULL); + for (i = 0; i < entries; i++) { + uint64_t entry_start = unpack_lb64(coreboot_table->map[i].start); + uint64_t entry_size = unpack_lb64(coreboot_table->map[i].size); + mb_mem->addr = entry_start; + mb_mem->len = entry_size; + switch (coreboot_table->map[i].type) { + case LB_MEM_RAM: + mb_mem->type = MULTIBOOT_MEMORY_AVAILABLE; + break; + default: // anything other than usable RAM + mb_mem->type = MULTIBOOT_MEMORY_RESERVED; + break; + } + mb_mem->size = sizeof(*mb_mem) - sizeof(mb_mem->size); + mb_mem++; + } mbi->mmap_length = ((u32) mb_mem) - mbi->mmap_addr; mbi->flags |= MB_INFO_MEM_MAP; diff --git a/src/arch/i386/boot/tables.c b/src/arch/i386/boot/tables.c index 6ee7c2c876..69e0539126 100644 --- a/src/arch/i386/boot/tables.c +++ b/src/arch/i386/boot/tables.c @@ -179,14 +179,6 @@ struct lb_memory *write_tables(void) #endif -#if CONFIG_MULTIBOOT - post_code(0x9d); - - /* The Multiboot information structure */ - rom_table_end = write_multiboot_info( - low_table_start, low_table_end, - rom_table_start, rom_table_end); -#endif #define MAX_COREBOOT_TABLE_SIZE (8 * 1024) post_code(0x9d); @@ -210,8 +202,9 @@ struct lb_memory *write_tables(void) new_high_table_pointer - high_table_pointer); } else { /* The coreboot table must be in 0-4K or 960K-1M */ - write_coreboot_table(low_table_start, low_table_end, - rom_table_start, rom_table_end); + rom_table_end = write_coreboot_table( + low_table_start, low_table_end, + rom_table_start, rom_table_end); } post_code(0x9e); @@ -224,6 +217,13 @@ struct lb_memory *write_tables(void) cbmem_add(CBMEM_ID_RESUME, 1024 * (1024-64)); #endif +#if CONFIG_MULTIBOOT + post_code(0x9d); + + /* The Multiboot information structure */ + write_multiboot_info(rom_table_end); +#endif + // Remove before sending upstream cbmem_list(); diff --git a/src/include/cpu/x86/multiboot.h b/src/include/cpu/x86/multiboot.h index c027fd7b55..70d839d6ae 100644 --- a/src/include/cpu/x86/multiboot.h +++ b/src/include/cpu/x86/multiboot.h @@ -167,6 +167,9 @@ struct multiboot_info { uint16_t vbe_interface_len; }; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 + struct multiboot_mmap_entry { uint32_t size; uint64_t addr; @@ -176,6 +179,6 @@ struct multiboot_mmap_entry { extern struct multiboot_info *mbi; -unsigned long write_multiboot_info(unsigned long, unsigned long, unsigned long, unsigned long); +unsigned long write_multiboot_info(unsigned long rom_table_end); #endif |