Patchwork [v2,20/20] arm: add generic ROM model for Faraday SoC platforms

login
register
mail settings
Submitter Kuo-Jung Su
Date Jan. 25, 2013, 8:19 a.m.
Message ID <1359101996-11667-21-git-send-email-dantesu@gmail.com>
Download mbox | patch
Permalink /patch/215580/
State New
Headers show

Comments

Kuo-Jung Su - Jan. 25, 2013, 8:19 a.m.
From: Kuo-Jung Su <dantesu@faraday-tech.com>

Since the NAND and SPI flash memories do not support random access,
so most of the systems which use such memory as main storages
usually has some bootstrap code stored inside the embedded ROM of
its SoC, and the bootstrap code is responsible for SDRAM initialization
and then load the specific software(i.e. u-boot/linux) into SDRAM,
and finally jumps into the loaded primary software.

This QEMU model simply emulates the behavior of the embedded ROM
for bootstrap code execution.

Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
---
 hw/rom.c |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)
 create mode 100644 hw/rom.c
Paul Brook - Jan. 25, 2013, 9:08 p.m.
> Since the NAND and SPI flash memories do not support random access,
> so most of the systems which use such memory as main storages
> usually has some bootstrap code stored inside the embedded ROM of
> its SoC, and the bootstrap code is responsible for SDRAM initialization
> and then load the specific software(i.e. u-boot/linux) into SDRAM,
> and finally jumps into the loaded primary software.

No.

For a start the block device you're using is for parallel plash devices, which 
are directly mapped.  This contradicts your desciption which talks about 
serial flash.

Please look at how other boards work.  There are already mechanisms for 
creating rom areas, or preloading images into ram.

Paul
Kuo-Jung Su - Jan. 28, 2013, 6:28 a.m.
Thanks for response.
The reason why I initialized the QEMU-A36x project a month ago,
was to create a embedded ROM code development environment.

And there are fews issues at the qemu-1.3.0 which I was working on.

1. The ARM ELF loader failed to correctly handle the image with sparse
memory model.
    For exmaple, A369 ROM code is configured as
    TEXT/RO-DATA @ 0x00000000 (ROM)
    BSS/RW-DATA/STACK @ 0xA0000000 (SRAM)
    And the RW-DATA section is never correctly initialized (all zero)
    if I use arm_load_kernel().

    => RAM emulation(Preloading images into ram) simply doesn't work,
         I'll check if the issue still exists in the current master branch.

2. I've seen some platform using pflash as ROM emulation,
    and because some of our customer/colleague love arguing,
    so I just wanted to try another way more precisely emulate the model.
    And it now seems not a good idea here, I'll switch into pflash
emulation later

Best Wishes
Dante Su



2013/1/26 Paul Brook <paul@codesourcery.com>

> > Since the NAND and SPI flash memories do not support random access,
> > so most of the systems which use such memory as main storages
> > usually has some bootstrap code stored inside the embedded ROM of
> > its SoC, and the bootstrap code is responsible for SDRAM initialization
> > and then load the specific software(i.e. u-boot/linux) into SDRAM,
> > and finally jumps into the loaded primary software.
>
> No.
>
> For a start the block device you're using is for parallel plash devices,
> which
> are directly mapped.  This contradicts your desciption which talks about
> serial flash.
>
> Please look at how other boards work.  There are already mechanisms for
> creating rom areas, or preloading images into ram.
>
> Paul
>

Patch

diff --git a/hw/rom.c b/hw/rom.c
new file mode 100644
index 0000000..aff2666
--- /dev/null
+++ b/hw/rom.c
@@ -0,0 +1,119 @@ 
+/*
+ * QEMU model of ROM
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is licensed under GNU GPL v2.
+ */
+
+#include "sysbus.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/blockdev.h"
+
+#define TYPE_ROM    "rom"
+
+typedef struct ROMState {
+    SysBusDevice busdev;
+    MemoryRegion mem;
+    MemoryRegion *mem_mappings;    /* array; one per mapping */
+    MemoryRegion orig_mem;
+    BlockDriverState *bdrv;
+    uint8_t *storage;
+    uint32_t size;
+} rom_state;
+
+#define ROM(obj) \
+    OBJECT_CHECK(rom_state, obj, TYPE_ROM)
+
+static uint64_t
+rom_mem_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    return 0;
+}
+
+static void
+rom_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+}
+
+static const MemoryRegionOps rom_ops = {
+    .read  = rom_mem_read,
+    .write = rom_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 8
+    }
+};
+
+static int rom_init(SysBusDevice *dev)
+{
+    rom_state *s = ROM(FROM_SYSBUS(rom_state, dev));
+    DriveInfo *dinfo;
+
+    memory_region_init_rom_device(&s->orig_mem, &rom_ops, s, "rom", s->size);
+    vmstate_register_ram(&s->orig_mem, DEVICE(s));
+    s->storage = memory_region_get_ram_ptr(&s->orig_mem);
+
+    dinfo = drive_get_next(IF_PFLASH);
+    if (dinfo && dinfo->bdrv) {
+        s->bdrv = dinfo->bdrv;
+        /* read the initial flash content */
+        bdrv_read(s->bdrv, 0, s->storage,
+                    DIV_ROUND_UP(s->size, BDRV_SECTOR_SIZE));
+    } else {
+        memset(s->storage, 0x00, s->size);
+    }
+
+    memory_region_init(&s->mem, "rom", s->size);
+    s->mem_mappings = g_new(MemoryRegion, 1);
+    memory_region_init_alias(&s->mem_mappings[0],
+                             "rom-alias",
+                             &s->orig_mem,
+                             0,
+                             s->size);
+    memory_region_add_subregion(&s->mem, 0, &s->mem_mappings[0]);
+
+    sysbus_init_mmio(dev, &s->mem);
+    return 0;
+}
+
+static Property rom_properties[] = {
+    DEFINE_PROP_UINT32("size", rom_state, size, 16384),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription vmstate_rom = {
+    .name = "rom",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void rom_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init   = rom_init;
+    dc->props = rom_properties;
+    dc->vmsd  = &vmstate_rom;
+}
+
+static const TypeInfo rom_info = {
+    .name           = TYPE_ROM,
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(rom_state),
+    .class_init     = rom_class_init,
+};
+
+static void rom_register_types(void)
+{
+    type_register_static(&rom_info);
+}
+
+type_init(rom_register_types)