25
25
#include "system/qtest.h"
26
26
#include "system/reset.h"
27
27
#include "kvm_ppc.h"
28
+ #include "elf.h"
28
29
29
30
#include <zlib.h> /* for crc32 */
30
31
31
32
#define BUS_FREQ_HZ 100000000
32
33
34
+ #define INITRD_MIN_ADDR 0x600000
35
+
33
36
/*
34
37
* Firmware binary available at
35
38
* https://www.hyperion-entertainment.com/index.php/downloads?view=files&parent=28
@@ -178,12 +181,68 @@ static const TypeInfo nvram_types[] = {
178
181
};
179
182
DEFINE_TYPES (nvram_types )
180
183
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
+
181
227
static void amigaone_cpu_reset (void * opaque )
182
228
{
183
229
PowerPCCPU * cpu = opaque ;
230
+ CPUPPCState * env = & cpu -> env ;
184
231
185
232
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 );
187
246
}
188
247
189
248
static void fix_spd_data (uint8_t * spd )
@@ -205,6 +264,8 @@ static void amigaone_init(MachineState *machine)
205
264
I2CBus * i2c_bus ;
206
265
uint8_t * spd_data ;
207
266
DriveInfo * di ;
267
+ hwaddr loadaddr ;
268
+ struct boot_info * bi = NULL ;
208
269
209
270
/* init CPU */
210
271
cpu = POWERPC_CPU (cpu_create (machine -> cpu_type ));
@@ -301,6 +362,56 @@ static void amigaone_init(MachineState *machine)
301
362
}
302
363
pci_ide_create_devs (PCI_DEVICE (object_resolve_path_component (via , "ide" )));
303
364
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
+ }
304
415
}
305
416
306
417
static void amigaone_machine_init (MachineClass * mc )
0 commit comments