All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <laurent@vivier.eu>
To: qemu-devel@nongnu.org
Cc: Laurent Vivier <laurent@vivier.eu>
Subject: [PATCH 3/3] m68k: virt: add a firmware (petitboot)
Date: Wed,  2 Feb 2022 23:35:28 +0100	[thread overview]
Message-ID: <20220202223528.1260154-4-laurent@vivier.eu> (raw)
In-Reply-To: <20220202223528.1260154-1-laurent@vivier.eu>

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



      parent reply	other threads:[~2022-02-02 22:39 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-02 22:35 [PATCH 0/3] m68k: virt: add a firmware to the virt machine (petit boot) Laurent Vivier
2022-02-02 22:35 ` [PATCH 1/3] m68k: bootinfo entry size must be aligned on 4 bytes Laurent Vivier
2022-02-02 22:35 ` [PATCH 2/3] m68k: virt: add a bootstrap ROM Laurent Vivier
2022-02-02 23:27   ` Philippe Mathieu-Daudé via
2022-02-02 22:35 ` Laurent Vivier [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220202223528.1260154-4-laurent@vivier.eu \
    --to=laurent@vivier.eu \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.