summaryrefslogtreecommitdiff
path: root/src/mainboard/emulation
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2013-11-06 14:36:17 +0100
committerGerd Hoffmann <kraxel@redhat.com>2013-11-11 12:14:42 +0100
commitbaa782020e9d2d0ce7b6fd1c7c43411c9aa2b900 (patch)
treecef0d18a74e078b76e18100dd25001497ccc196c /src/mainboard/emulation
parent289b45fdffa42db85fa4ad63338677ab8f15e9a2 (diff)
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)
Diffstat (limited to 'src/mainboard/emulation')
-rw-r--r--src/mainboard/emulation/qemu-i440fx/fw_cfg_if.h6
-rw-r--r--src/mainboard/emulation/qemu-i440fx/northbridge.c65
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");