Patchwork version 2, Generate multiboot tables after and from coreboot tables

login
register
about
Submitter Myles Watson
Date 2010-08-31 16:14:46
Message ID <AANLkTikZDtaYn9zLknYYUu-fQ+ui3Et3+ojEtpz7igLf@mail.gmail.com>
Download mbox | patch
Permalink /patch/1831/
State Accepted
Headers show

Comments

Myles Watson - 2010-08-31 16:14:46
On Tue, Aug 31, 2010 at 9:27 AM, Juhana Helovuo <juhe@iki.fi> 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 <juhe@iki.fi>
>> 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 <mylesgw@gmail.com>

Thanks,
Myles

Patch

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 <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)
 {
+        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;