Generate multiboot tables from coreboot tables.
[coreboot.git] / src / arch / i386 / boot / multiboot.c
index a47c0b4af4a5090c6a4f1900f6bbcdc61ee19d66..4059f2736b830b51e4b6c5f34f5cb6abd8216dad 100644 (file)
 #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;