From patchwork Tue Aug 31 16:14:46 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: version 2, Generate multiboot tables after and from coreboot tables Date: Tue, 31 Aug 2010 16:14:46 -0000 From: Myles Watson X-Patchwork-Id: 1831 Message-Id: To: Juhana Helovuo Cc: coreboot@coreboot.org On Tue, Aug 31, 2010 at 9:27 AM, Juhana Helovuo wrote: > On Mon, 2010-08-30 at 21:46 +0200, Patrick Georgi wrote: >> Am 30.08.2010 20:54, schrieb Juhana Helovuo: >> > Hello, >> > >> > The attached patch adds all the memory memory ranges in the coreboot >> > tables also to the multiboot tables. It is useful e.g. when booting >> > Linux with Grub2 payload, since then Linux gets the Coreboot memory map >> > via multiboot tables. >> > >> > This patch causes multiboot table to be located in memory before >> > coreboot tables, but it seemed to cause no harm for me. >> > >> > Signed-off-by: Juhana Helovuo >> I like the change, except for the #if 0 section. Could that code be >> removed entirely, or is there a reason for keeping it? >> Also, what's up with reserved_mem_count? Does that serve any purpose >> other than dumping the multiboot tables? I don't think we should keep the name reserved_mem_count if we increment it for all regions. > Ok, here is attached 2nd version of the patch. It is the simpler > alternative (#2) outlined in my previous mail. I simplified a little more. It would be even simpler if we dumped the table while it was being built. Signed-off-by: Myles Watson Thanks, Myles Index: svn/src/arch/i386/boot/multiboot.c =================================================================== --- svn.orig/src/arch/i386/boot/multiboot.c +++ svn/src/arch/i386/boot/multiboot.c @@ -22,63 +22,23 @@ #include #include #include +#include +#include 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) { + struct lb_memory* coreboot_table; + int entries; int i; + struct multiboot_mmap_entry *multiboot_mmap_table; + int entry_count; mbi = (struct multiboot_info *)rom_table_end; @@ -87,32 +47,64 @@ unsigned long write_multiboot_info( mbi->mmap_addr = (u32) rom_table_end; mb_mem = (struct multiboot_mmap_entry *)rom_table_end; + multiboot_mmap_table = mb_mem; // Save a copy for dumping table later - /* 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); - - 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++; + mb_mem->addr = low_table_start; + mb_mem->len = ROUND(low_table_end - low_table_start, 4096); + mb_mem->type = MULTIBOOT_MEMORY_RESERVED; + mb_mem->size = sizeof(*mb_mem) - sizeof(mb_mem->size); + mb_mem++; + + mb_mem->addr = rom_table_start; + mb_mem->len = ROUND(rom_table_end - rom_table_start, 4096); + mb_mem->type = MULTIBOOT_MEMORY_RESERVED; + mb_mem->size = sizeof(*mb_mem) - sizeof(mb_mem->size); + mb_mem++; + + entry_count = 2; /* just the reserved regions */ + + /* regions from coreboot tables */ + coreboot_table = get_lb_mem(); + entries = (coreboot_table->size - sizeof(*coreboot_table))/sizeof(coreboot_table->map[0]); + + 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++; + entry_count++; + } + + printk(BIOS_DEBUG, "Multiboot memory table dump, %d entries.\n", + entry_count); + for (i = 0; i < entry_count; i++) { + printk(BIOS_DEBUG, " %02d. %016llx %016llx : %s\n", i , + multiboot_mmap_table[i].addr, + multiboot_mmap_table[i].len, + (multiboot_mmap_table[i].type == 1 ? "RAM" : "RESERVED") + ); + } mbi->mmap_length = ((u32) mb_mem) - mbi->mmap_addr; mbi->flags |= MB_INFO_MEM_MAP; - printk(BIOS_INFO, "Multiboot Information structure has been written.\n"); + printk(BIOS_INFO, "Multiboot information structure written.\n"); return (unsigned long)mb_mem; } Index: svn/src/arch/i386/boot/tables.c =================================================================== --- svn.orig/src/arch/i386/boot/tables.c +++ svn/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,7 +202,7 @@ 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_end = write_coreboot_table(low_table_start, low_table_end, rom_table_start, rom_table_end); } @@ -224,6 +216,15 @@ 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 */ + rom_table_end = write_multiboot_info( + low_table_start, low_table_end, + rom_table_start, rom_table_end); +#endif + // Remove before sending upstream cbmem_list(); Index: svn/src/include/cpu/x86/multiboot.h =================================================================== --- svn.orig/src/include/cpu/x86/multiboot.h +++ svn/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;