diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2013-11-06 14:36:17 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2013-11-11 12:14:42 +0100 |
commit | baa782020e9d2d0ce7b6fd1c7c43411c9aa2b900 (patch) | |
tree | cef0d18a74e078b76e18100dd25001497ccc196c | |
parent | 289b45fdffa42db85fa4ad63338677ab8f15e9a2 (diff) | |
download | coreboot-baa782020e9d2d0ce7b6fd1c7c43411c9aa2b900.tar.xz |
qemu: load e820 from fw_cfg
qemu 1.7+ provides a fw_cfg file named "etc/e820" with e820-like entries
for reservations and ram regions. Use it for ram detection if present,
otherwise fallback to the traditional cmos method.
Change-Id: Icac6c99d2a053e59dfdd28e48d1ceb3d56a61bdc
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-on: http://review.coreboot.org/4030
Tested-by: build bot (Jenkins)
-rw-r--r-- | src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h | 6 | ||||
-rw-r--r-- | src/mainboard/emulation/qemu-i440fx/northbridge.c | 65 |
2 files changed, 60 insertions, 11 deletions
diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h b/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h index d159f12d09..80e628032b 100644 --- a/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h +++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h @@ -51,3 +51,9 @@ typedef struct FWCfgFiles { uint32_t count; FWCfgFile f[]; } FWCfgFiles; + +typedef struct FwCfgE820Entry { + uint64_t address; + uint64_t length; + uint32_t type; +} FwCfgE820Entry __attribute((__aligned__(4))); diff --git a/src/mainboard/emulation/qemu-i440fx/northbridge.c b/src/mainboard/emulation/qemu-i440fx/northbridge.c index c87868925c..0f8c0c23f3 100644 --- a/src/mainboard/emulation/qemu-i440fx/northbridge.c +++ b/src/mainboard/emulation/qemu-i440fx/northbridge.c @@ -13,6 +13,7 @@ #include <cbmem.h> #include "fw_cfg.h" +#include "fw_cfg_if.h" #include "memory.c" @@ -58,20 +59,62 @@ static void cpu_pci_domain_read_resources(struct device *dev) struct resource *res; unsigned long tomk = 0, high; int idx = 10; + int size; pci_domain_read_resources(dev); - tomk = qemu_get_memory_size(); - high = qemu_get_high_memory_size(); - printk(BIOS_DEBUG, "Detected %lu MiB RAM below 4G.\n", tomk / 1024); - printk(BIOS_DEBUG, "Detected %lu MiB RAM above 4G.\n", high / 1024); - - /* Report the memory regions. */ - idx = 10; - ram_resource(dev, idx++, 0, 640); - ram_resource(dev, idx++, 768, tomk - 768); - if (high) - ram_resource(dev, idx++, 4 * 1024 * 1024, high); + size = fw_cfg_check_file("etc/e820"); + if (size > 0) { + /* supported by qemu 1.7+ */ + FwCfgE820Entry *list = malloc(size); + int i; + fw_cfg_load_file("etc/e820", list); + for (i = 0; i < size/sizeof(*list); i++) { + switch (list[i].type) { + case 1: /* ram */ + printk(BIOS_DEBUG, "QEMU: e820/ram: 0x%08llx +0x%08llx\n", + list[i].address, list[i].length); + if (list[i].address == 0) { + tomk = list[i].length / 1024; + ram_resource(dev, idx++, 0, 640); + ram_resource(dev, idx++, 768, tomk - 768); + } else { + ram_resource(dev, idx++, + list[i].address / 1024, + list[i].length / 1024); + } + break; + case 2: /* reserved */ + printk(BIOS_DEBUG, "QEMU: e820/res: 0x%08llx +0x%08llx\n", + list[i].address, list[i].length); + res = new_resource(dev, idx++); + res->base = list[i].address; + res->size = list[i].length; + res->limit = 0xffffffff; + res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | + IORESOURCE_STORED | IORESOURCE_ASSIGNED; + break; + default: + /* skip unknown */ + break; + } + } + free(list); + } + + if (!tomk) { + /* qemu older than 1.7, or reading etc/e820 failed. Fallback to cmos. */ + tomk = qemu_get_memory_size(); + high = qemu_get_high_memory_size(); + printk(BIOS_DEBUG, "QEMU: cmos: %lu MiB RAM below 4G.\n", tomk / 1024); + printk(BIOS_DEBUG, "QEMU: cmos: %lu MiB RAM above 4G.\n", high / 1024); + + /* Report the memory regions. */ + ram_resource(dev, idx++, 0, 640); + ram_resource(dev, idx++, 768, tomk - 768); + if (high) + ram_resource(dev, idx++, 4 * 1024 * 1024, high); + } /* Reserve I/O ports used by QEMU */ qemu_reserve_ports(dev, idx++, 0x0510, 0x02, "firmware-config"); |