From: "Nicholas Piggin" <npiggin@gmail.com>
To: "BALATON Zoltan" <balaton@eik.bme.hu>, <qemu-devel@nongnu.org>,
<qemu-ppc@nongnu.org>
Subject: Re: [PATCH 2/4] ppc/amigaone: Implement NVRAM emulation
Date: Thu, 27 Feb 2025 11:10:45 +1000 [thread overview]
Message-ID: <D82TTAPY9JXE.3P3A8B5Y1GAB1@gmail.com> (raw)
In-Reply-To: <7fac3d50347adbb00bfcd1d1d0bfdf9e73515ebb.1740243918.git.balaton@eik.bme.hu>
On Sun Feb 23, 2025 at 3:52 AM AEST, BALATON Zoltan wrote:
> The board has a battery backed NVRAM where U-Boot environment is
> stored which is also accessed by AmigaOS and e.g. C:NVGetVar command
> crashes without it having at least a valid checksum.
>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
> hw/ppc/amigaone.c | 116 ++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 113 insertions(+), 3 deletions(-)
>
> diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c
> index 4290d58613..5273543460 100644
> --- a/hw/ppc/amigaone.c
> +++ b/hw/ppc/amigaone.c
> @@ -21,10 +21,13 @@
> #include "hw/ide/pci.h"
> #include "hw/i2c/smbus_eeprom.h"
> #include "hw/ppc/ppc.h"
> +#include "system/block-backend.h"
> #include "system/qtest.h"
> #include "system/reset.h"
> #include "kvm_ppc.h"
>
> +#include <zlib.h> /* for crc32 */
> +
> #define BUS_FREQ_HZ 100000000
>
> /*
> @@ -46,6 +49,103 @@ static const char dummy_fw[] = {
> 0x4e, 0x80, 0x00, 0x20, /* blr */
> };
>
> +#define NVRAM_ADDR 0xfd0e0000
> +#define NVRAM_SIZE (4 * KiB)
> +
> +#define TYPE_A1_NVRAM "a1-nvram"
> +OBJECT_DECLARE_SIMPLE_TYPE(A1NVRAMState, A1_NVRAM)
> +
> +struct A1NVRAMState {
> + SysBusDevice parent_obj;
> +
> + MemoryRegion mr;
> + BlockBackend *blk;
> +};
> +
> +/* read callback not used because of romd mode, only here just in case */
Better make it g_assert_not_reached() then.
> +static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> + A1NVRAMState *s = opaque;
> + uint8_t *p = memory_region_get_ram_ptr(&s->mr);
> +
> + return p[addr];
> +}
> +
> +static void nvram_write(void *opaque, hwaddr addr, uint64_t val,
> + unsigned int size)
> +{
> + A1NVRAMState *s = opaque;
> + uint8_t *p = memory_region_get_ram_ptr(&s->mr);
> +
> + p[addr] = val;
> + if (s->blk) {
> + blk_pwrite(s->blk, addr, 1, &val, 0);
> + }
> +}
> +
> +static const MemoryRegionOps nvram_ops = {
> + .read = nvram_read,
> + .write = nvram_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> + .impl = {
> + .min_access_size = 1,
> + .max_access_size = 1,
> + },
> +};
> +
> +static void nvram_realize(DeviceState *dev, Error **errp)
> +{
> + A1NVRAMState *s = A1_NVRAM(dev);
> + void *p;
> + uint32_t *c;
> +
> + memory_region_init_rom_device(&s->mr, NULL, &nvram_ops, s, "nvram",
> + NVRAM_SIZE, &error_fatal);
> + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr);
> + c = p = memory_region_get_ram_ptr(&s->mr);
> + if (s->blk) {
> + if (blk_getlength(s->blk) != NVRAM_SIZE) {
> + error_setg(errp, "NVRAM backing file size must be %ld bytes",
> + NVRAM_SIZE);
> + return;
> + }
> + blk_set_perm(s->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
> + BLK_PERM_ALL, &error_fatal);
> + if (blk_pread(s->blk, 0, NVRAM_SIZE, p, 0) < 0) {
> + error_setg(errp, "Cannot read NVRAM contents from backing file");
> + return;
> + }
> + }
> + if (*c == 0) {
> + *c = cpu_to_be32(crc32(0, p + 4, NVRAM_SIZE - 4));
> + if (s->blk) {
> + blk_pwrite(s->blk, 0, 4, p, 0);
> + }
> + }
> +}
So, no need for a reset because it's persistent?
> +
> +static const Property nvram_properties[] = {
> + DEFINE_PROP_DRIVE("drive", A1NVRAMState, blk),
> +};
> +
> +static void nvram_class_init(ObjectClass *oc, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(oc);
> +
> + dc->realize = nvram_realize;
> + device_class_set_props(dc, nvram_properties);
> +}
> +
> +static const TypeInfo nvram_types[] = {
> + {
> + .name = TYPE_A1_NVRAM,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(A1NVRAMState),
> + .class_init = nvram_class_init,
> + },
> +};
> +DEFINE_TYPES(nvram_types)
> +
> static void amigaone_cpu_reset(void *opaque)
> {
> PowerPCCPU *cpu = opaque;
> @@ -72,7 +172,7 @@ static void amigaone_init(MachineState *machine)
> DeviceState *dev;
> I2CBus *i2c_bus;
> uint8_t *spd_data;
> - int i;
> + DriveInfo *di;
>
> /* init CPU */
> cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
> @@ -97,6 +197,16 @@ static void amigaone_init(MachineState *machine)
> memory_region_add_subregion(get_system_memory(), 0x40000000, mr);
> }
>
> + /* nvram */
> + dev = qdev_new(TYPE_A1_NVRAM);
> + di = drive_get(IF_MTD, 0, 0);
> + if (di) {
> + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(di));
> + }
> + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> + memory_region_add_subregion(get_system_memory(), NVRAM_ADDR,
> + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
> +
> /* allocate and load firmware */
> rom = g_new(MemoryRegion, 1);
> memory_region_init_rom(rom, NULL, "rom", PROM_SIZE, &error_fatal);
> @@ -136,7 +246,7 @@ static void amigaone_init(MachineState *machine)
> pci_mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
> mr = g_new(MemoryRegion, 1);
> memory_region_init_alias(mr, OBJECT(dev), "pci-mem-low", pci_mem,
> - 0, 0x1000000);
> + 0, 0xe0000);
> memory_region_add_subregion(get_system_memory(), 0xfd000000, mr);
Better make these addresses #defines at the top of the file with
the NVRAM_ADDR?
Thanks,
Nick
> mr = g_new(MemoryRegion, 1);
> memory_region_init_alias(mr, OBJECT(dev), "pci-mem-high", pci_mem,
> @@ -153,7 +263,7 @@ static void amigaone_init(MachineState *machine)
> qdev_connect_gpio_out_named(DEVICE(via), "intr", 0,
> qdev_get_gpio_in(DEVICE(cpu),
> PPC6xx_INPUT_INT));
> - for (i = 0; i < PCI_NUM_PINS; i++) {
> + for (int i = 0; i < PCI_NUM_PINS; i++) {
> qdev_connect_gpio_out(dev, i, qdev_get_gpio_in_named(DEVICE(via),
> "pirq", i));
> }
next prev parent reply other threads:[~2025-02-27 1:11 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-22 17:52 [PATCH 0/4] ppc/amigaone patches BALATON Zoltan
2025-02-22 17:52 ` [PATCH 1/4] ppc/amigaone: Simplify replacement dummy_fw BALATON Zoltan
2025-02-27 0:50 ` Nicholas Piggin
2025-02-22 17:52 ` [PATCH 2/4] ppc/amigaone: Implement NVRAM emulation BALATON Zoltan
2025-02-27 1:10 ` Nicholas Piggin [this message]
2025-02-27 1:48 ` BALATON Zoltan
2025-02-27 8:08 ` Nicholas Piggin
2025-02-27 16:40 ` BALATON Zoltan
2025-02-22 17:52 ` [PATCH 3/4] ppc/amigaone: Add default environment BALATON Zoltan
2025-02-27 1:21 ` Nicholas Piggin
2025-02-27 2:18 ` BALATON Zoltan
2025-02-27 8:31 ` Nicholas Piggin
2025-02-27 17:07 ` BALATON Zoltan
2025-02-22 17:52 ` [PATCH 4/4] ppc/amigaone: Add kernel and initrd support BALATON Zoltan
2025-02-27 1:24 ` Nicholas Piggin
2025-02-24 19:04 ` [PATCH 0/4] ppc/amigaone patches Bernhard Beschow
2025-02-24 20:48 ` BALATON Zoltan
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=D82TTAPY9JXE.3P3A8B5Y1GAB1@gmail.com \
--to=npiggin@gmail.com \
--cc=balaton@eik.bme.hu \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@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.