qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/3] m68k: virt: add a firmware (petitboot)


From: Laurent Vivier
Subject: [PATCH 3/3] m68k: virt: add a firmware (petitboot)
Date: Wed, 2 Feb 2022 23:35:28 +0100

Add a firmware for the m68k virt machine

The firmware is based on petit boot (also used in bare metal POWER
systems)

Petit boot is embedded in a buildroot filesystem.

This patch define the buildroot repository, add make targets to
build and install the kernel and filesystem produced by buildroot.

To build the firmware:

$ git submodule init roms/buildroot
$ git submodule update roms/buildroot
$ make -C roms m68k-virt-firmware

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 configure                   |   3 +-
 include/hw/misc/virt_ctrl.h |   6 ++
 hw/m68k/virt.c              |  12 +++-
 hw/misc/virt_ctrl.c         | 111 +++++++++++++++++++++++++++++++++++-
 .gitmodules                 |   3 +
 pc-bios/meson.build         |   2 +
 roms/Makefile               |   8 +++
 roms/buildroot              |   1 +
 8 files changed, 140 insertions(+), 6 deletions(-)
 create mode 160000 roms/buildroot

diff --git a/configure b/configure
index e6cfc0e4be6c..5cc3d7029455 100755
--- a/configure
+++ b/configure
@@ -3685,7 +3685,8 @@ for bios_file in \
     $source_path/pc-bios/openbios-* \
     $source_path/pc-bios/u-boot.* \
     $source_path/pc-bios/palcode-* \
-    $source_path/pc-bios/qemu_vga.ndrv
+    $source_path/pc-bios/qemu_vga.ndrv \
+    $source_path/pc-bios/m68k-virt.*
 
 do
     LINKS="$LINKS pc-bios/$(basename $bios_file)"
diff --git a/include/hw/misc/virt_ctrl.h b/include/hw/misc/virt_ctrl.h
index 25a237e51874..e1a3f027ab03 100644
--- a/include/hw/misc/virt_ctrl.h
+++ b/include/hw/misc/virt_ctrl.h
@@ -17,6 +17,12 @@ struct VirtCtrlState {
     qemu_irq irq;
 
     uint32_t irq_enabled;
+
+    MachineState *machine;
+    char *fw_elf;
+    char *fw_ramfs;
+    uint32_t fw_bootinfo_size;
+    uint8_t *fw_bootinfo;
 };
 
 #endif
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 11aff6d93865..d6af84d1a3f6 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -89,9 +89,11 @@
 /*
  * At the end of the memory address space we have a 1 MB ROM
  */
-#define VIRT_ROM_ADDR 0xfff00000
-#define VIRT_ROM_SIZE 0x00100000
-#define VIRT_ROM_NAME "m68k-virt.rom"
+#define VIRT_ROM_ADDR      0xfff00000
+#define VIRT_ROM_SIZE      0x00100000
+#define VIRT_ROM_NAME      "m68k-virt.rom"
+#define VIRT_FW_ELF_NAME   "m68k-virt.vmlinux"
+#define VIRT_FW_RAMFS_NAME "m68k-virt.petitboot"
 
 typedef struct {
     M68kCPU *cpu;
@@ -202,6 +204,10 @@ static void virt_init(MachineState *machine)
 
     /* virt controller */
     dev = qdev_new(TYPE_VIRT_CTRL);
+    object_property_set_link(OBJECT(dev), "machine", OBJECT(machine),
+                             &error_abort);
+    qdev_prop_set_string(dev, "fw.elf", VIRT_FW_ELF_NAME);
+    qdev_prop_set_string(dev, "fw.ramfs", VIRT_FW_RAMFS_NAME);
     sysbus = SYS_BUS_DEVICE(dev);
     sysbus_realize_and_unref(sysbus, &error_fatal);
     sysbus_mmio_map(sysbus, 0, VIRT_CTRL_MMIO_BASE);
diff --git a/hw/misc/virt_ctrl.c b/hw/misc/virt_ctrl.c
index e75d1e7e17b3..2ac725f1570b 100644
--- a/hw/misc/virt_ctrl.c
+++ b/hw/misc/virt_ctrl.c
@@ -5,28 +5,98 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/datadir.h"
 #include "hw/qdev-properties.h"
 #include "hw/sysbus.h"
+#include "hw/loader.h"
+#include "hw/boards.h"
 #include "migration/vmstate.h"
 #include "qemu/log.h"
 #include "trace.h"
+#include "elf.h"
 #include "sysemu/runstate.h"
 #include "hw/misc/virt_ctrl.h"
 
 enum {
     REG_FEATURES = 0x00,
     REG_CMD      = 0x04,
+    REG_PARAM    = 0x08,
 };
 
 #define FEAT_POWER_CTRL 0x00000001
+#define FEAT_FW_CTRL    0x00000002
+
+#define FEAT_SUPPORTED (FEAT_POWER_CTRL | FEAT_FW_CTRL)
 
 enum {
+    /* Power Control */
     CMD_NOOP,
     CMD_RESET,
     CMD_HALT,
     CMD_PANIC,
+    /* Firmware Control */
+    CMD_FW_MACHINE_ID,
+    CMD_FW_LOAD,
+    CMD_FW_RAMSIZE,
+    CMD_FW_QEMU_VERSION
+};
+
+enum {
+   FW_M68K,
 };
 
+static uint32_t param;
+
+#define RESULT_ERROR (-1)
+
+static uint32_t fw_load_m68k(VirtCtrlState *s)
+{
+    char *elf_filename, *ramfs_filename;
+    int32_t kernel_size;
+    uint64_t elf_entry, high;
+    int32_t ramfs_size;
+    ram_addr_t ramfs_base;
+    void *ram_ptr;
+
+    elf_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->fw_elf);
+    if (elf_filename == NULL) {
+        error_report("Cannot find %s", s->fw_elf);
+        return RESULT_ERROR;
+    }
+    ramfs_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, s->fw_ramfs);
+    if (ramfs_filename == NULL) {
+        error_report("Cannot find %s", s->fw_ramfs);
+        return RESULT_ERROR;
+    }
+
+    kernel_size = load_elf_ram(elf_filename, NULL, NULL, NULL,
+                               &elf_entry, NULL, &high, NULL, 1,
+                               EM_68K, 0, 0, NULL, false);
+    if (kernel_size < 0) {
+        error_report("could not load kernel '%s'", elf_filename);
+        return RESULT_ERROR;
+    }
+
+    ramfs_size = get_image_size(ramfs_filename);
+    if (ramfs_size < 0) {
+        error_report("could not load initial ram disk '%s'",
+                     ramfs_filename);
+        return RESULT_ERROR;
+    }
+
+    ram_ptr = memory_region_get_ram_ptr(s->machine->ram);
+
+    ramfs_base = (s->machine->ram_size - ramfs_size) & ~0xfff;
+    load_image_size(ramfs_filename, ram_ptr + ramfs_base, ramfs_size);
+
+    high = (high + 1) & ~1;
+    *(uint32_t *)(ram_ptr + high) = cpu_to_be32(elf_entry);
+    *(uint32_t *)(ram_ptr + high + 4) = cpu_to_be32(ramfs_base);
+    *(uint32_t *)(ram_ptr + high + 8) = cpu_to_be32(ramfs_size);
+
+    return high;
+}
+
 static uint64_t virt_ctrl_read(void *opaque, hwaddr addr, unsigned size)
 {
     VirtCtrlState *s = opaque;
@@ -34,7 +104,10 @@ static uint64_t virt_ctrl_read(void *opaque, hwaddr addr, 
unsigned size)
 
     switch (addr) {
     case REG_FEATURES:
-        value = FEAT_POWER_CTRL;
+        value = FEAT_SUPPORTED;
+        break;
+    case REG_PARAM:
+        value = param;
         break;
     default:
         qemu_log_mask(LOG_UNIMP,
@@ -43,7 +116,7 @@ static uint64_t virt_ctrl_read(void *opaque, hwaddr addr, 
unsigned size)
         break;
     }
 
-    trace_virt_ctrl_write(s, addr, size, value);
+    trace_virt_ctrl_read(s, addr, size, value);
 
     return value;
 }
@@ -69,8 +142,32 @@ static void virt_ctrl_write(void *opaque, hwaddr addr, 
uint64_t value,
         case CMD_PANIC:
             qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
             break;
+        case CMD_FW_LOAD:
+            switch (param) {
+            case FW_M68K:
+                param = fw_load_m68k(s);
+                break;
+            default:
+                qemu_log_mask(LOG_UNIMP, "%s: unimplemented FW type %d\n",
+                              __func__, param);
+                break;
+            }
+            break;
+        case CMD_FW_RAMSIZE:
+            param = s->machine->ram_size;
+            break;
+        case CMD_FW_QEMU_VERSION:
+            param = (QEMU_VERSION_MAJOR << 24) | (QEMU_VERSION_MINOR << 16) |
+                    (QEMU_VERSION_MICRO << 8);
+            break;
+        case CMD_FW_MACHINE_ID:
+            param = 0;
+            break;
         }
         break;
+    case REG_PARAM:
+        param = value;
+        break;
     default:
         qemu_log_mask(LOG_UNIMP,
                       "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
@@ -114,6 +211,14 @@ static const VMStateDescription vmstate_virt_ctrl = {
     }
 };
 
+static Property virt_ctl_properties[] = {
+    DEFINE_PROP_LINK("machine", VirtCtrlState, machine,
+                     TYPE_MACHINE, MachineState *),
+    DEFINE_PROP_STRING("fw.elf", VirtCtrlState, fw_elf),
+    DEFINE_PROP_STRING("fw.ramfs", VirtCtrlState, fw_ramfs),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void virt_ctrl_instance_init(Object *obj)
 {
     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
@@ -132,6 +237,8 @@ static void virt_ctrl_class_init(ObjectClass *oc, void 
*data)
     dc->reset = virt_ctrl_reset;
     dc->realize = virt_ctrl_realize;
     dc->vmsd = &vmstate_virt_ctrl;
+
+    device_class_set_props(dc, virt_ctl_properties);
 }
 
 static const TypeInfo virt_ctrl_info = {
diff --git a/.gitmodules b/.gitmodules
index 315d597d057a..b45269f896cf 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -70,3 +70,6 @@
 [submodule "roms/m68k-virt"]
        path = roms/m68k-virt
        url = https://github.com/vivier/m68k-virt-bootstrap.git
+[submodule "roms/buildroot"]
+       path = roms/buildroot
+       url = https://github.com/vivier/buildroot.git
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
index ffec6decdc4c..c94b63d17d7b 100644
--- a/pc-bios/meson.build
+++ b/pc-bios/meson.build
@@ -82,6 +82,8 @@ blobs = files(
   'opensbi-riscv64-generic-fw_dynamic.bin',
   'npcm7xx_bootrom.bin',
   'm68k-virt.rom',
+  'm68k-virt.vmlinux',
+  'm68k-virt.petitboot',
 )
 
 if get_option('install_blobs')
diff --git a/roms/Makefile b/roms/Makefile
index f9f84e8efb1b..8275083444ef 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -71,6 +71,7 @@ default help:
        @echo "  opensbi64-generic  -- update OpenSBI for 64-bit generic 
machine"
        @echo "  qboot              -- update qboot"
        @echo "  m68k-virt-bootrom  -- update m68k-virt bootrom"
+       @echo "  m68k-virt-firmware -- update m68k-virt firmware (petitboot)"
        @echo "  clean              -- delete the files generated by the 
previous" \
                                      "build targets"
 
@@ -203,6 +204,12 @@ m68k-virt-bootrom:
        $(MAKE) -C m68k-virt CROSS_COMPILE=$(m68k_cross_prefix)
        cp m68k-virt/rom.bin ../pc-bios/m68k-virt.rom
 
+m68k-virt-firmware:
+       $(MAKE) -C buildroot qemu_m68k_virt_petitboot_defconfig
+       $(MAKE) -C buildroot -j $$(( $$(getconf _NPROCESSORS_ONLN) * 2 + 1))
+       cp buildroot/output/images/vmlinux ../pc-bios/m68k-virt.vmlinux
+       cp buildroot/output/images/rootfs.cpio.xz ../pc-bios/m68k-virt.petitboot
+
 clean:
        rm -rf seabios/.config seabios/out seabios/builds
        $(MAKE) -C sgabios clean
@@ -218,3 +225,4 @@ clean:
        $(MAKE) -C qboot clean
        $(MAKE) -C vbootrom clean
        $(MAKE) -C m68k-virt clean
+       $(MAKE) -C buildroot clean
diff --git a/roms/buildroot b/roms/buildroot
new file mode 160000
index 000000000000..5590654699e4
--- /dev/null
+++ b/roms/buildroot
@@ -0,0 +1 @@
+Subproject commit 5590654699e4926bee834ae99f90c8062bc418eb
-- 
2.34.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]