On Sun Feb 23, 2025 at 3:52 AM AEST, BALATON Zoltan wrote: > Add support for -kernel, -initrd and -append command line options.
Looks okay. Any test case could be added to test_ppc_amiga.py? Reviewed-by: Nicholas Piggin <npig...@gmail.com> > > Signed-off-by: BALATON Zoltan <bala...@eik.bme.hu> > --- > 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 35e4075cc3..94682de1c7 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 > @@ -181,12 +184,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) > @@ -208,6 +267,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)); > @@ -304,6 +365,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)