diff mbox

[1/2] hw/arm/virt: Provide flash devices for boot ROMs

Message ID 1402411908-25821-2-git-send-email-peter.maydell@linaro.org
State New
Headers show

Commit Message

Peter Maydell June 10, 2014, 2:51 p.m. UTC
Add two flash devices to the virt board, so that it can be used for
running guests which want a bootrom image such as UEFI. We provide
two flash devices to make it more convenient to provide both a
read-only UEFI image and a read-write place to store guest-set
UEFI config variables. The '-bios' command line option is set up
to provide an image for the first of the two flash devices.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/virt.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

Comments

Paolo Bonzini June 10, 2014, 4:15 p.m. UTC | #1
Il 10/06/2014 16:51, Peter Maydell ha scritto:
> +    /* Create two flash devices to fill the VIRT_FLASH space in the memmap.
> +     * Any file passed via -bios goes in the first of these.
> +     */
> +    hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2;
> +    hwaddr flashbase = vbi->memmap[VIRT_FLASH].base;
> +    char *nodename;
> +
> +    if (bios_name) {
> +        const char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
> +        if (!fn || load_image_targphys(fn, flashbase, flashsize) < 0) {
> +            error_report("Could not load ROM image '%s'", bios_name);
> +            exit(1);
> +        }
> +    }
> +
> +    create_one_flash("virt.flash0", flashbase, flashsize);
> +    create_one_flash("virt.flash1", flashbase + flashsize, flashsize);

What happens if you specify both -bios and -drive if=pflash?  Can you 
check that the user does not specify both?

Paolo
Peter Maydell June 10, 2014, 4:17 p.m. UTC | #2
On 10 June 2014 17:15, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 10/06/2014 16:51, Peter Maydell ha scritto:
>
>> +    /* Create two flash devices to fill the VIRT_FLASH space in the
>> memmap.
>> +     * Any file passed via -bios goes in the first of these.
>> +     */
>> +    hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2;
>> +    hwaddr flashbase = vbi->memmap[VIRT_FLASH].base;
>> +    char *nodename;
>> +
>> +    if (bios_name) {
>> +        const char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
>> +        if (!fn || load_image_targphys(fn, flashbase, flashsize) < 0) {
>> +            error_report("Could not load ROM image '%s'", bios_name);
>> +            exit(1);
>> +        }
>> +    }
>> +
>> +    create_one_flash("virt.flash0", flashbase, flashsize);
>> +    create_one_flash("virt.flash1", flashbase + flashsize, flashsize);
>
>
> What happens if you specify both -bios and -drive if=pflash?  Can you check
> that the user does not specify both?

We'll create the device and then overlay it with the "ROM"
image, same as for vexpress. (If the bios image is short
then the underlying pflash contents will be visible.)

thanks
-- PMM
Paolo Bonzini June 10, 2014, 4:23 p.m. UTC | #3
Il 10/06/2014 18:17, Peter Maydell ha scritto:
>>> >> +    create_one_flash("virt.flash0", flashbase, flashsize);
>>> >> +    create_one_flash("virt.flash1", flashbase + flashsize, flashsize);
>> >
>> >
>> > What happens if you specify both -bios and -drive if=pflash?  Can you check
>> > that the user does not specify both?
> We'll create the device and then overlay it with the "ROM"
> image, same as for vexpress. (If the bios image is short
> then the underlying pflash contents will be visible.)

Could you provide slightly saner semantics for -M virt? :)

Paolo
Peter Maydell June 10, 2014, 4:38 p.m. UTC | #4
On 10 June 2014 17:23, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 10/06/2014 18:17, Peter Maydell ha scritto:
>
>>>> >> +    create_one_flash("virt.flash0", flashbase, flashsize);
>>>> >> +    create_one_flash("virt.flash1", flashbase + flashsize,
>>>> >> flashsize);
>>>
>>> >
>>> >
>>> > What happens if you specify both -bios and -drive if=pflash?  Can you
>>> > check
>>> > that the user does not specify both?
>>
>> We'll create the device and then overlay it with the "ROM"
>> image, same as for vexpress. (If the bios image is short
>> then the underlying pflash contents will be visible.)
>
>
> Could you provide slightly saner semantics for -M virt? :)

Heh. How about:
 * if both bios_name and pflash drive 0 specified, this is an error
 * otherwise use whichever we have
 * (NB that bios_name + pflash drive 1 is a reasonable combination)

vexpress should do this too, for consistency.

(Actually ideally I'd just make bios_name be a convenient
shortcut for specifying a block backend for pflash that's
readonly and permits undersized backing files, but I don't
think we can easily do that right now.)

thanks
-- PMM
Paolo Bonzini June 10, 2014, 4:48 p.m. UTC | #5
Il 10/06/2014 18:38, Peter Maydell ha scritto:
> On 10 June 2014 17:23, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Il 10/06/2014 18:17, Peter Maydell ha scritto:
>>
>>>>>>> +    create_one_flash("virt.flash0", flashbase, flashsize);
>>>>>>> +    create_one_flash("virt.flash1", flashbase + flashsize,
>>>>>>> flashsize);
>>>>
>>>>>
>>>>>
>>>>> What happens if you specify both -bios and -drive if=pflash?  Can you
>>>>> check
>>>>> that the user does not specify both?
>>>
>>> We'll create the device and then overlay it with the "ROM"
>>> image, same as for vexpress. (If the bios image is short
>>> then the underlying pflash contents will be visible.)
>>
>>
>> Could you provide slightly saner semantics for -M virt? :)
>
> Heh. How about:
>  * if both bios_name and pflash drive 0 specified, this is an error
>  * otherwise use whichever we have
>  * (NB that bios_name + pflash drive 1 is a reasonable combination)

Yes, it is.

> vexpress should do this too, for consistency.

If it's okay for you, why not.

Paolo

> (Actually ideally I'd just make bios_name be a convenient
> shortcut for specifying a block backend for pflash that's
> readonly and permits undersized backing files, but I don't
> think we can easily do that right now.)
>
> thanks
> -- PMM
>
Peter Maydell June 10, 2014, 4:50 p.m. UTC | #6
On 10 June 2014 17:48, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 10/06/2014 18:38, Peter Maydell ha scritto:
>> Heh. How about:
>>  * if both bios_name and pflash drive 0 specified, this is an error
>>  * otherwise use whichever we have
>>  * (NB that bios_name + pflash drive 1 is a reasonable combination)
>
>
> Yes, it is.
>
>
>> vexpress should do this too, for consistency.
>
>
> If it's okay for you, why not.

We haven't released anything where vexpress supports -bios
yet, so it's still fine to change.

thanks
-- PMM
diff mbox

Patch

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 3b55a4b..10f8fcb 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -37,6 +37,7 @@ 
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
 #include "hw/boards.h"
+#include "hw/loader.h"
 #include "exec/address-spaces.h"
 #include "qemu/bitops.h"
 #include "qemu/error-report.h"
@@ -94,7 +95,6 @@  typedef struct VirtBoardInfo {
  * a 32 bit VM and leaving space for expansion and in particular for PCI.
  */
 static const MemMapEntry a15memmap[] = {
-    /* Space up to 0x8000000 is reserved for a boot ROM */
     [VIRT_FLASH] = { 0, 0x8000000 },
     [VIRT_CPUPERIPHS] = { 0x8000000, 0x20000 },
     /* GIC distributor and CPU interfaces sit inside the CPU peripheral space */
@@ -375,6 +375,65 @@  static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
     }
 }
 
+static void create_one_flash(const char *name, hwaddr flashbase,
+                             hwaddr flashsize)
+{
+    /* Create and map a single flash device. We use the same
+     * parameters as the flash devices on the Versatile Express board.
+     */
+    DriveInfo *dinfo = drive_get_next(IF_PFLASH);
+    DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
+    const uint64_t sectorlength = 256 * 1024;
+
+    if (dinfo && qdev_prop_set_drive(dev, "drive", dinfo->bdrv)) {
+        abort();
+    }
+
+    qdev_prop_set_uint32(dev, "num-blocks", flashsize / sectorlength);
+    qdev_prop_set_uint64(dev, "sector-length", sectorlength);
+    qdev_prop_set_uint8(dev, "width", 4);
+    qdev_prop_set_uint8(dev, "device-width", 2);
+    qdev_prop_set_uint8(dev, "big-endian", 0);
+    qdev_prop_set_uint16(dev, "id0", 0x89);
+    qdev_prop_set_uint16(dev, "id1", 0x18);
+    qdev_prop_set_uint16(dev, "id2", 0x00);
+    qdev_prop_set_uint16(dev, "id3", 0x00);
+    qdev_prop_set_string(dev, "name", name);
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, flashbase);
+}
+
+static void create_flash(const VirtBoardInfo *vbi)
+{
+    /* Create two flash devices to fill the VIRT_FLASH space in the memmap.
+     * Any file passed via -bios goes in the first of these.
+     */
+    hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2;
+    hwaddr flashbase = vbi->memmap[VIRT_FLASH].base;
+    char *nodename;
+
+    if (bios_name) {
+        const char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (!fn || load_image_targphys(fn, flashbase, flashsize) < 0) {
+            error_report("Could not load ROM image '%s'", bios_name);
+            exit(1);
+        }
+    }
+
+    create_one_flash("virt.flash0", flashbase, flashsize);
+    create_one_flash("virt.flash1", flashbase + flashsize, flashsize);
+
+    nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
+    qemu_fdt_add_subnode(vbi->fdt, nodename);
+    qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");
+    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
+                                 2, flashbase, 2, flashsize,
+                                 2, flashbase + flashsize, 2, flashsize);
+    qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);
+    g_free(nodename);
+}
+
 static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
 {
     const VirtBoardInfo *board = (const VirtBoardInfo *)binfo;
@@ -451,6 +510,8 @@  static void machvirt_init(MachineState *machine)
     vmstate_register_ram_global(ram);
     memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram);
 
+    create_flash(vbi);
+
     create_gic(vbi, pic);
 
     create_uart(vbi, pic);