aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/fby35.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c
index 5c5224d..e7405f6 100644
--- a/hw/arm/fby35.c
+++ b/hw/arm/fby35.c
@@ -9,6 +9,7 @@
#include "qemu/units.h"
#include "qapi/error.h"
#include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
#include "hw/boards.h"
#include "hw/arm/aspeed_soc.h"
@@ -23,12 +24,49 @@ struct Fby35State {
MemoryRegion bmc_boot_rom;
AspeedSoCState bmc;
+
+ bool mmio_exec;
};
#define FBY35_BMC_RAM_SIZE (2 * GiB)
+#define FBY35_BMC_FIRMWARE_ADDR 0x0
+
+static void fby35_bmc_write_boot_rom(DriveInfo *dinfo, MemoryRegion *mr,
+ hwaddr offset, size_t rom_size,
+ Error **errp)
+{
+ BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
+ g_autofree void *storage = NULL;
+ int64_t size;
+
+ /*
+ * The block backend size should have already been 'validated' by
+ * the creation of the m25p80 object.
+ */
+ size = blk_getlength(blk);
+ if (size <= 0) {
+ error_setg(errp, "failed to get flash size");
+ return;
+ }
+
+ if (rom_size > size) {
+ rom_size = size;
+ }
+
+ storage = g_malloc0(rom_size);
+ if (blk_pread(blk, 0, rom_size, storage, 0) < 0) {
+ error_setg(errp, "failed to read the initial flash content");
+ return;
+ }
+
+ /* TODO: find a better way to install the ROM */
+ memcpy(memory_region_get_ram_ptr(mr) + offset, storage, rom_size);
+}
static void fby35_bmc_init(Fby35State *s)
{
+ DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
+
memory_region_init(&s->bmc_memory, OBJECT(s), "bmc-memory", UINT64_MAX);
memory_region_init_ram(&s->bmc_dram, OBJECT(s), "bmc-dram",
FBY35_BMC_RAM_SIZE, &error_abort);
@@ -48,6 +86,28 @@ static void fby35_bmc_init(Fby35State *s)
qdev_realize(DEVICE(&s->bmc), NULL, &error_abort);
aspeed_board_init_flashes(&s->bmc.fmc, "n25q00", 2, 0);
+
+ /* Install first FMC flash content as a boot rom. */
+ if (drive0) {
+ AspeedSMCFlash *fl = &s->bmc.fmc.flashes[0];
+ MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+ uint64_t size = memory_region_size(&fl->mmio);
+
+ if (s->mmio_exec) {
+ memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
+ &fl->mmio, 0, size);
+ memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
+ boot_rom);
+ } else {
+
+ memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
+ size, &error_abort);
+ memory_region_add_subregion(&s->bmc_memory, FBY35_BMC_FIRMWARE_ADDR,
+ boot_rom);
+ fby35_bmc_write_boot_rom(drive0, boot_rom, FBY35_BMC_FIRMWARE_ADDR,
+ size, &error_abort);
+ }
+ }
}
static void fby35_init(MachineState *machine)
@@ -57,6 +117,22 @@ static void fby35_init(MachineState *machine)
fby35_bmc_init(s);
}
+
+static bool fby35_get_mmio_exec(Object *obj, Error **errp)
+{
+ return FBY35(obj)->mmio_exec;
+}
+
+static void fby35_set_mmio_exec(Object *obj, bool value, Error **errp)
+{
+ FBY35(obj)->mmio_exec = value;
+}
+
+static void fby35_instance_init(Object *obj)
+{
+ FBY35(obj)->mmio_exec = false;
+}
+
static void fby35_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -66,6 +142,12 @@ static void fby35_class_init(ObjectClass *oc, void *data)
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->min_cpus = mc->max_cpus = mc->default_cpus = 2;
+
+ object_class_property_add_bool(oc, "execute-in-place",
+ fby35_get_mmio_exec,
+ fby35_set_mmio_exec);
+ object_class_property_set_description(oc, "execute-in-place",
+ "boot directly from CE0 flash device");
}
static const TypeInfo fby35_types[] = {
@@ -74,6 +156,7 @@ static const TypeInfo fby35_types[] = {
.parent = TYPE_MACHINE,
.class_init = fby35_class_init,
.instance_size = sizeof(Fby35State),
+ .instance_init = fby35_instance_init,
},
};