[PULL 70/72] ppc/amigaone: Add kernel and initrd support

Nicholas Piggin posted 72 patches 11 months ago
[PULL 70/72] ppc/amigaone: Add kernel and initrd support
Posted by Nicholas Piggin 11 months ago
From: BALATON Zoltan <balaton@eik.bme.hu>

Add support for -kernel, -initrd and -append command line options.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Message-ID: <489b1be5d95d5153e924c95b0691b8b53f9ffb9e.1740673173.git.balaton@eik.bme.hu>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 hw/ppc/amigaone.c | 113 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 112 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c
index 1c6f2a944d..359f5fa125 100644
--- a/hw/ppc/amigaone.c
+++ b/hw/ppc/amigaone.c
@@ -25,11 +25,14 @@
 #include "system/qtest.h"
 #include "system/reset.h"
 #include "kvm_ppc.h"
+#include "elf.h"
 
 #include <zlib.h> /* for crc32 */
 
 #define BUS_FREQ_HZ 100000000
 
+#define INITRD_MIN_ADDR 0x600000
+
 /*
  * Firmware binary available at
  * https://www.hyperion-entertainment.com/index.php/downloads?view=files&parent=28
@@ -178,12 +181,68 @@ static const TypeInfo nvram_types[] = {
 };
 DEFINE_TYPES(nvram_types)
 
+struct boot_info {
+    hwaddr entry;
+    hwaddr stack;
+    hwaddr bd_info;
+    hwaddr initrd_start;
+    hwaddr initrd_end;
+    hwaddr cmdline_start;
+    hwaddr cmdline_end;
+};
+
+/* Board info struct from U-Boot */
+struct bd_info {
+    uint32_t bi_memstart;
+    uint32_t bi_memsize;
+    uint32_t bi_flashstart;
+    uint32_t bi_flashsize;
+    uint32_t bi_flashoffset;
+    uint32_t bi_sramstart;
+    uint32_t bi_sramsize;
+    uint32_t bi_bootflags;
+    uint32_t bi_ip_addr;
+    uint8_t  bi_enetaddr[6];
+    uint16_t bi_ethspeed;
+    uint32_t bi_intfreq;
+    uint32_t bi_busfreq;
+    uint32_t bi_baudrate;
+} QEMU_PACKED;
+
+static void create_bd_info(hwaddr addr, ram_addr_t ram_size)
+{
+    struct bd_info *bd = g_new0(struct bd_info, 1);
+
+    bd->bi_memsize =    cpu_to_be32(ram_size);
+    bd->bi_flashstart = cpu_to_be32(PROM_ADDR);
+    bd->bi_flashsize =  cpu_to_be32(1); /* match what U-Boot detects */
+    bd->bi_bootflags =  cpu_to_be32(1);
+    bd->bi_intfreq =    cpu_to_be32(11.5 * BUS_FREQ_HZ);
+    bd->bi_busfreq =    cpu_to_be32(BUS_FREQ_HZ);
+    bd->bi_baudrate =   cpu_to_be32(115200);
+
+    cpu_physical_memory_write(addr, bd, sizeof(*bd));
+}
+
 static void amigaone_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
 
     cpu_reset(CPU(cpu));
-    cpu_ppc_tb_reset(&cpu->env);
+    if (env->load_info) {
+        struct boot_info *bi = env->load_info;
+
+        env->gpr[1] = bi->stack;
+        env->gpr[2] = 1024;
+        env->gpr[3] = bi->bd_info;
+        env->gpr[4] = bi->initrd_start;
+        env->gpr[5] = bi->initrd_end;
+        env->gpr[6] = bi->cmdline_start;
+        env->gpr[7] = bi->cmdline_end;
+        env->nip = bi->entry;
+    }
+    cpu_ppc_tb_reset(env);
 }
 
 static void fix_spd_data(uint8_t *spd)
@@ -205,6 +264,8 @@ static void amigaone_init(MachineState *machine)
     I2CBus *i2c_bus;
     uint8_t *spd_data;
     DriveInfo *di;
+    hwaddr loadaddr;
+    struct boot_info *bi = NULL;
 
     /* init CPU */
     cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
@@ -301,6 +362,56 @@ static void amigaone_init(MachineState *machine)
     }
     pci_ide_create_devs(PCI_DEVICE(object_resolve_path_component(via, "ide")));
     pci_vga_init(pci_bus);
+
+    if (!machine->kernel_filename) {
+        return;
+    }
+
+    /* handle -kernel, -initrd, -append options and emulate U-Boot */
+    bi = g_new0(struct boot_info, 1);
+    cpu->env.load_info = bi;
+
+    loadaddr = MIN(machine->ram_size, 256 * MiB);
+    bi->bd_info = loadaddr - 8 * MiB;
+    create_bd_info(bi->bd_info, machine->ram_size);
+    bi->stack = bi->bd_info - 64 * KiB - 8;
+
+    if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
+        size_t len = strlen(machine->kernel_cmdline);
+
+        loadaddr = bi->bd_info + 1 * MiB;
+        cpu_physical_memory_write(loadaddr, machine->kernel_cmdline, len + 1);
+        bi->cmdline_start = loadaddr;
+        bi->cmdline_end = loadaddr + len + 1; /* including terminating '\0' */
+    }
+
+    sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
+                  &bi->entry, &loadaddr, NULL, NULL,
+                  ELFDATA2MSB, PPC_ELF_MACHINE, 0, 0);
+    if (sz <= 0) {
+        sz = load_uimage(machine->kernel_filename, &bi->entry, &loadaddr,
+                         NULL, NULL, NULL);
+    }
+    if (sz <= 0) {
+        error_report("Could not load kernel '%s'",
+                     machine->kernel_filename);
+        exit(1);
+    }
+    loadaddr += sz;
+
+    if (machine->initrd_filename) {
+        loadaddr = ROUND_UP(loadaddr + 4 * MiB, 4 * KiB);
+        loadaddr = MAX(loadaddr, INITRD_MIN_ADDR);
+        sz = load_image_targphys(machine->initrd_filename, loadaddr,
+                                 bi->bd_info - loadaddr);
+        if (sz <= 0) {
+            error_report("Could not load initrd '%s'",
+                         machine->initrd_filename);
+            exit(1);
+        }
+        bi->initrd_start = loadaddr;
+        bi->initrd_end = loadaddr + sz;
+    }
 }
 
 static void amigaone_machine_init(MachineClass *mc)
-- 
2.47.1
Re: [PULL 70/72] ppc/amigaone: Add kernel and initrd support
Posted by Peter Maydell 3 months, 2 weeks ago
On Tue, 11 Mar 2025 at 13:24, Nicholas Piggin <npiggin@gmail.com> wrote:
>
> From: BALATON Zoltan <balaton@eik.bme.hu>
>
> Add support for -kernel, -initrd and -append command line options.
>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
> Message-ID: <489b1be5d95d5153e924c95b0691b8b53f9ffb9e.1740673173.git.balaton@eik.bme.hu>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---

Hi; Coverity reports a memory leak in this function
(CID 1641398):

> +static void create_bd_info(hwaddr addr, ram_addr_t ram_size)
> +{
> +    struct bd_info *bd = g_new0(struct bd_info, 1);

We allocate the bd_info struct here...

> +
> +    bd->bi_memsize =    cpu_to_be32(ram_size);
> +    bd->bi_flashstart = cpu_to_be32(PROM_ADDR);
> +    bd->bi_flashsize =  cpu_to_be32(1); /* match what U-Boot detects */
> +    bd->bi_bootflags =  cpu_to_be32(1);
> +    bd->bi_intfreq =    cpu_to_be32(11.5 * BUS_FREQ_HZ);
> +    bd->bi_busfreq =    cpu_to_be32(BUS_FREQ_HZ);
> +    bd->bi_baudrate =   cpu_to_be32(115200);
> +
> +    cpu_physical_memory_write(addr, bd, sizeof(*bd));

...but we never free it or keep a pointer to it.

I guess we can mark it g_autofree ?

> +}

thanks
-- PMM
Re: [PULL 70/72] ppc/amigaone: Add kernel and initrd support
Posted by Philippe Mathieu-Daudé 7 months, 3 weeks ago
Hi,

On 11/3/25 13:58, Nicholas Piggin wrote:
> From: BALATON Zoltan <balaton@eik.bme.hu>
> 
> Add support for -kernel, -initrd and -append command line options.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
> Message-ID: <489b1be5d95d5153e924c95b0691b8b53f9ffb9e.1740673173.git.balaton@eik.bme.hu>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>   hw/ppc/amigaone.c | 113 +++++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 112 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c
> index 1c6f2a944d..359f5fa125 100644
> --- a/hw/ppc/amigaone.c
> +++ b/hw/ppc/amigaone.c


> @@ -301,6 +362,56 @@ static void amigaone_init(MachineState *machine)
>       }
>       pci_ide_create_devs(PCI_DEVICE(object_resolve_path_component(via, "ide")));
>       pci_vga_init(pci_bus);
> +
> +    if (!machine->kernel_filename) {
> +        return;
> +    }
> +
> +    /* handle -kernel, -initrd, -append options and emulate U-Boot */
> +    bi = g_new0(struct boot_info, 1);
> +    cpu->env.load_info = bi;
> +
> +    loadaddr = MIN(machine->ram_size, 256 * MiB);
> +    bi->bd_info = loadaddr - 8 * MiB;
> +    create_bd_info(bi->bd_info, machine->ram_size);
> +    bi->stack = bi->bd_info - 64 * KiB - 8;
> +
> +    if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
> +        size_t len = strlen(machine->kernel_cmdline);
> +
> +        loadaddr = bi->bd_info + 1 * MiB;
> +        cpu_physical_memory_write(loadaddr, machine->kernel_cmdline, len + 1);

This patch introduces a call to a legacy API (documented since at least
2017 in commit b7ecba0f6f6: "docs/devel/loads-stores.rst: Document our
various load and store APIs"). Can we load via &address_space_memory
instead?

> +        bi->cmdline_start = loadaddr;
> +        bi->cmdline_end = loadaddr + len + 1; /* including terminating '\0' */
> +    }
> +
> +    sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
> +                  &bi->entry, &loadaddr, NULL, NULL,
> +                  ELFDATA2MSB, PPC_ELF_MACHINE, 0, 0);
> +    if (sz <= 0) {
> +        sz = load_uimage(machine->kernel_filename, &bi->entry, &loadaddr,
> +                         NULL, NULL, NULL);
> +    }
> +    if (sz <= 0) {
> +        error_report("Could not load kernel '%s'",
> +                     machine->kernel_filename);
> +        exit(1);
> +    }
> +    loadaddr += sz;
> +
> +    if (machine->initrd_filename) {
> +        loadaddr = ROUND_UP(loadaddr + 4 * MiB, 4 * KiB);
> +        loadaddr = MAX(loadaddr, INITRD_MIN_ADDR);
> +        sz = load_image_targphys(machine->initrd_filename, loadaddr,
> +                                 bi->bd_info - loadaddr);
> +        if (sz <= 0) {
> +            error_report("Could not load initrd '%s'",
> +                         machine->initrd_filename);
> +            exit(1);
> +        }
> +        bi->initrd_start = loadaddr;
> +        bi->initrd_end = loadaddr + sz;
> +    }
>   }
>   
>   static void amigaone_machine_init(MachineClass *mc)
Re: [PULL 70/72] ppc/amigaone: Add kernel and initrd support
Posted by BALATON Zoltan 7 months, 3 weeks ago
On Mon, 16 Jun 2025, Philippe Mathieu-Daudé wrote:
> On 11/3/25 13:58, Nicholas Piggin wrote:
>> From: BALATON Zoltan <balaton@eik.bme.hu>
>> 
>> Add support for -kernel, -initrd and -append command line options.
>> 
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
>> Message-ID: 
>> <489b1be5d95d5153e924c95b0691b8b53f9ffb9e.1740673173.git.balaton@eik.bme.hu>
>> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
>> ---
>>   hw/ppc/amigaone.c | 113 +++++++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 112 insertions(+), 1 deletion(-)
>> 
>> diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c
>> index 1c6f2a944d..359f5fa125 100644
>> --- a/hw/ppc/amigaone.c
>> +++ b/hw/ppc/amigaone.c
>
>
>> @@ -301,6 +362,56 @@ static void amigaone_init(MachineState *machine)
>>       }
>>       pci_ide_create_devs(PCI_DEVICE(object_resolve_path_component(via, 
>> "ide")));
>>       pci_vga_init(pci_bus);
>> +
>> +    if (!machine->kernel_filename) {
>> +        return;
>> +    }
>> +
>> +    /* handle -kernel, -initrd, -append options and emulate U-Boot */
>> +    bi = g_new0(struct boot_info, 1);
>> +    cpu->env.load_info = bi;
>> +
>> +    loadaddr = MIN(machine->ram_size, 256 * MiB);
>> +    bi->bd_info = loadaddr - 8 * MiB;
>> +    create_bd_info(bi->bd_info, machine->ram_size);
>> +    bi->stack = bi->bd_info - 64 * KiB - 8;
>> +
>> +    if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
>> +        size_t len = strlen(machine->kernel_cmdline);
>> +
>> +        loadaddr = bi->bd_info + 1 * MiB;
>> +        cpu_physical_memory_write(loadaddr, machine->kernel_cmdline, len + 
>> 1);
>
> This patch introduces a call to a legacy API (documented since at least
> 2017 in commit b7ecba0f6f6: "docs/devel/loads-stores.rst: Document our
> various load and store APIs").

It does not say deprecated but only if you're in a device you probably 
need something else as this implicitly operates on system address space 
and does not report errors. But we're in a machine here and there's 
nothing to be done for a failure which is not expected at this point.

> Can we load via &address_space_memory instead?

I guess we could but that would just make this line much longer and less 
readable. There are plenty of places using this still so unless it's about 
to be removed I'd leave it as it is. Get back to this when it's the last 
instance.

Regards,
BALATON Zoltan