Skip to content

Commit 34f053d

Browse files
zbalatonnpiggin
authored andcommitted
ppc/amigaone: Add kernel and initrd support
Add support for -kernel, -initrd and -append command line options. Signed-off-by: BALATON Zoltan <[email protected]> Reviewed-by: Nicholas Piggin <[email protected]> Message-ID: <489b1be5d95d5153e924c95b0691b8b53f9ffb9e.1740673173.git.balaton@eik.bme.hu> Signed-off-by: Nicholas Piggin <[email protected]>
1 parent c2bed99 commit 34f053d

File tree

1 file changed

+112
-1
lines changed

1 file changed

+112
-1
lines changed

hw/ppc/amigaone.c

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@
2525
#include "system/qtest.h"
2626
#include "system/reset.h"
2727
#include "kvm_ppc.h"
28+
#include "elf.h"
2829

2930
#include <zlib.h> /* for crc32 */
3031

3132
#define BUS_FREQ_HZ 100000000
3233

34+
#define INITRD_MIN_ADDR 0x600000
35+
3336
/*
3437
* Firmware binary available at
3538
* https://www.hyperion-entertainment.com/index.php/downloads?view=files&parent=28
@@ -178,12 +181,68 @@ static const TypeInfo nvram_types[] = {
178181
};
179182
DEFINE_TYPES(nvram_types)
180183

184+
struct boot_info {
185+
hwaddr entry;
186+
hwaddr stack;
187+
hwaddr bd_info;
188+
hwaddr initrd_start;
189+
hwaddr initrd_end;
190+
hwaddr cmdline_start;
191+
hwaddr cmdline_end;
192+
};
193+
194+
/* Board info struct from U-Boot */
195+
struct bd_info {
196+
uint32_t bi_memstart;
197+
uint32_t bi_memsize;
198+
uint32_t bi_flashstart;
199+
uint32_t bi_flashsize;
200+
uint32_t bi_flashoffset;
201+
uint32_t bi_sramstart;
202+
uint32_t bi_sramsize;
203+
uint32_t bi_bootflags;
204+
uint32_t bi_ip_addr;
205+
uint8_t bi_enetaddr[6];
206+
uint16_t bi_ethspeed;
207+
uint32_t bi_intfreq;
208+
uint32_t bi_busfreq;
209+
uint32_t bi_baudrate;
210+
} QEMU_PACKED;
211+
212+
static void create_bd_info(hwaddr addr, ram_addr_t ram_size)
213+
{
214+
struct bd_info *bd = g_new0(struct bd_info, 1);
215+
216+
bd->bi_memsize = cpu_to_be32(ram_size);
217+
bd->bi_flashstart = cpu_to_be32(PROM_ADDR);
218+
bd->bi_flashsize = cpu_to_be32(1); /* match what U-Boot detects */
219+
bd->bi_bootflags = cpu_to_be32(1);
220+
bd->bi_intfreq = cpu_to_be32(11.5 * BUS_FREQ_HZ);
221+
bd->bi_busfreq = cpu_to_be32(BUS_FREQ_HZ);
222+
bd->bi_baudrate = cpu_to_be32(115200);
223+
224+
cpu_physical_memory_write(addr, bd, sizeof(*bd));
225+
}
226+
181227
static void amigaone_cpu_reset(void *opaque)
182228
{
183229
PowerPCCPU *cpu = opaque;
230+
CPUPPCState *env = &cpu->env;
184231

185232
cpu_reset(CPU(cpu));
186-
cpu_ppc_tb_reset(&cpu->env);
233+
if (env->load_info) {
234+
struct boot_info *bi = env->load_info;
235+
236+
env->gpr[1] = bi->stack;
237+
env->gpr[2] = 1024;
238+
env->gpr[3] = bi->bd_info;
239+
env->gpr[4] = bi->initrd_start;
240+
env->gpr[5] = bi->initrd_end;
241+
env->gpr[6] = bi->cmdline_start;
242+
env->gpr[7] = bi->cmdline_end;
243+
env->nip = bi->entry;
244+
}
245+
cpu_ppc_tb_reset(env);
187246
}
188247

189248
static void fix_spd_data(uint8_t *spd)
@@ -205,6 +264,8 @@ static void amigaone_init(MachineState *machine)
205264
I2CBus *i2c_bus;
206265
uint8_t *spd_data;
207266
DriveInfo *di;
267+
hwaddr loadaddr;
268+
struct boot_info *bi = NULL;
208269

209270
/* init CPU */
210271
cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
@@ -301,6 +362,56 @@ static void amigaone_init(MachineState *machine)
301362
}
302363
pci_ide_create_devs(PCI_DEVICE(object_resolve_path_component(via, "ide")));
303364
pci_vga_init(pci_bus);
365+
366+
if (!machine->kernel_filename) {
367+
return;
368+
}
369+
370+
/* handle -kernel, -initrd, -append options and emulate U-Boot */
371+
bi = g_new0(struct boot_info, 1);
372+
cpu->env.load_info = bi;
373+
374+
loadaddr = MIN(machine->ram_size, 256 * MiB);
375+
bi->bd_info = loadaddr - 8 * MiB;
376+
create_bd_info(bi->bd_info, machine->ram_size);
377+
bi->stack = bi->bd_info - 64 * KiB - 8;
378+
379+
if (machine->kernel_cmdline && machine->kernel_cmdline[0]) {
380+
size_t len = strlen(machine->kernel_cmdline);
381+
382+
loadaddr = bi->bd_info + 1 * MiB;
383+
cpu_physical_memory_write(loadaddr, machine->kernel_cmdline, len + 1);
384+
bi->cmdline_start = loadaddr;
385+
bi->cmdline_end = loadaddr + len + 1; /* including terminating '\0' */
386+
}
387+
388+
sz = load_elf(machine->kernel_filename, NULL, NULL, NULL,
389+
&bi->entry, &loadaddr, NULL, NULL,
390+
ELFDATA2MSB, PPC_ELF_MACHINE, 0, 0);
391+
if (sz <= 0) {
392+
sz = load_uimage(machine->kernel_filename, &bi->entry, &loadaddr,
393+
NULL, NULL, NULL);
394+
}
395+
if (sz <= 0) {
396+
error_report("Could not load kernel '%s'",
397+
machine->kernel_filename);
398+
exit(1);
399+
}
400+
loadaddr += sz;
401+
402+
if (machine->initrd_filename) {
403+
loadaddr = ROUND_UP(loadaddr + 4 * MiB, 4 * KiB);
404+
loadaddr = MAX(loadaddr, INITRD_MIN_ADDR);
405+
sz = load_image_targphys(machine->initrd_filename, loadaddr,
406+
bi->bd_info - loadaddr);
407+
if (sz <= 0) {
408+
error_report("Could not load initrd '%s'",
409+
machine->initrd_filename);
410+
exit(1);
411+
}
412+
bi->initrd_start = loadaddr;
413+
bi->initrd_end = loadaddr + sz;
414+
}
304415
}
305416

306417
static void amigaone_machine_init(MachineClass *mc)

0 commit comments

Comments
 (0)