Commit 1640695026373034f9740ad1bcb69f27e584218c
1 parent
008a8818
Add nominal ARM Versatil/AB board emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1864 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
153 additions
and
173 deletions
Makefile.target
... | ... | @@ -346,7 +346,7 @@ endif |
346 | 346 | endif |
347 | 347 | ifeq ($(TARGET_BASE_ARCH), arm) |
348 | 348 | VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o |
349 | -VL_OBJS+= pl011.o pl050.o pl080.o pl110.o pl190.o | |
349 | +VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o | |
350 | 350 | endif |
351 | 351 | ifeq ($(TARGET_BASE_ARCH), sh4) |
352 | 352 | VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o | ... | ... |
hw/arm_boot.c
0 → 100644
1 | +/* | |
2 | + * ARM kernel loader. | |
3 | + * | |
4 | + * Copyright (c) 2006 CodeSourcery. | |
5 | + * Written by Paul Brook | |
6 | + * | |
7 | + * This code is licenced under the GPL. | |
8 | + */ | |
9 | + | |
10 | +#include "vl.h" | |
11 | + | |
12 | +#define KERNEL_ARGS_ADDR 0x100 | |
13 | +#define KERNEL_LOAD_ADDR 0x00010000 | |
14 | +#define INITRD_LOAD_ADDR 0x00800000 | |
15 | + | |
16 | +/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ | |
17 | +static uint32_t bootloader[] = { | |
18 | + 0xe3a00000, /* mov r0, #0 */ | |
19 | + 0xe3a01000, /* mov r1, #0x?? */ | |
20 | + 0xe3811c00, /* orr r1, r1, #0x??00 */ | |
21 | + 0xe59f2000, /* ldr r2, [pc, #0] */ | |
22 | + 0xe59ff000, /* ldr pc, [pc, #0] */ | |
23 | + 0, /* Address of kernel args. Set by integratorcp_init. */ | |
24 | + 0 /* Kernel entry point. Set by integratorcp_init. */ | |
25 | +}; | |
26 | + | |
27 | +static void set_kernel_args(uint32_t ram_size, int initrd_size, | |
28 | + const char *kernel_cmdline) | |
29 | +{ | |
30 | + uint32_t *p; | |
31 | + | |
32 | + p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); | |
33 | + /* ATAG_CORE */ | |
34 | + stl_raw(p++, 5); | |
35 | + stl_raw(p++, 0x54410001); | |
36 | + stl_raw(p++, 1); | |
37 | + stl_raw(p++, 0x1000); | |
38 | + stl_raw(p++, 0); | |
39 | + /* ATAG_MEM */ | |
40 | + stl_raw(p++, 4); | |
41 | + stl_raw(p++, 0x54410002); | |
42 | + stl_raw(p++, ram_size); | |
43 | + stl_raw(p++, 0); | |
44 | + if (initrd_size) { | |
45 | + /* ATAG_INITRD2 */ | |
46 | + stl_raw(p++, 4); | |
47 | + stl_raw(p++, 0x54420005); | |
48 | + stl_raw(p++, INITRD_LOAD_ADDR); | |
49 | + stl_raw(p++, initrd_size); | |
50 | + } | |
51 | + if (kernel_cmdline && *kernel_cmdline) { | |
52 | + /* ATAG_CMDLINE */ | |
53 | + int cmdline_size; | |
54 | + | |
55 | + cmdline_size = strlen(kernel_cmdline); | |
56 | + memcpy (p + 2, kernel_cmdline, cmdline_size + 1); | |
57 | + cmdline_size = (cmdline_size >> 2) + 1; | |
58 | + stl_raw(p++, cmdline_size + 2); | |
59 | + stl_raw(p++, 0x54410009); | |
60 | + p += cmdline_size; | |
61 | + } | |
62 | + /* ATAG_END */ | |
63 | + stl_raw(p++, 0); | |
64 | + stl_raw(p++, 0); | |
65 | +} | |
66 | + | |
67 | +void arm_load_kernel(int ram_size, const char *kernel_filename, | |
68 | + const char *kernel_cmdline, const char *initrd_filename, | |
69 | + int board_id) | |
70 | +{ | |
71 | + int kernel_size; | |
72 | + int initrd_size; | |
73 | + int n; | |
74 | + | |
75 | + /* Load the kernel. */ | |
76 | + if (!kernel_filename) { | |
77 | + fprintf(stderr, "Kernel image must be specified\n"); | |
78 | + exit(1); | |
79 | + } | |
80 | + kernel_size = load_image(kernel_filename, | |
81 | + phys_ram_base + KERNEL_LOAD_ADDR); | |
82 | + if (kernel_size < 0) { | |
83 | + fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); | |
84 | + exit(1); | |
85 | + } | |
86 | + if (initrd_filename) { | |
87 | + initrd_size = load_image(initrd_filename, | |
88 | + phys_ram_base + INITRD_LOAD_ADDR); | |
89 | + if (initrd_size < 0) { | |
90 | + fprintf(stderr, "qemu: could not load initrd '%s'\n", | |
91 | + initrd_filename); | |
92 | + exit(1); | |
93 | + } | |
94 | + } else { | |
95 | + initrd_size = 0; | |
96 | + } | |
97 | + bootloader[1] |= board_id & 0xff; | |
98 | + bootloader[2] |= (board_id >> 8) & 0xff; | |
99 | + bootloader[5] = KERNEL_ARGS_ADDR; | |
100 | + bootloader[6] = KERNEL_LOAD_ADDR; | |
101 | + for (n = 0; n < sizeof(bootloader) / 4; n++) | |
102 | + stl_raw(phys_ram_base + (n * 4), bootloader[n]); | |
103 | + set_kernel_args(ram_size, initrd_size, kernel_cmdline); | |
104 | +} | |
105 | + | ... | ... |
hw/integratorcp.c
... | ... | @@ -10,10 +10,6 @@ |
10 | 10 | #include "vl.h" |
11 | 11 | #include "arm_pic.h" |
12 | 12 | |
13 | -#define KERNEL_ARGS_ADDR 0x100 | |
14 | -#define KERNEL_LOAD_ADDR 0x00010000 | |
15 | -#define INITRD_LOAD_ADDR 0x00800000 | |
16 | - | |
17 | 13 | void DMA_run (void) |
18 | 14 | { |
19 | 15 | } |
... | ... | @@ -470,57 +466,6 @@ static void icp_control_init(uint32_t base) |
470 | 466 | } |
471 | 467 | |
472 | 468 | |
473 | -/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ | |
474 | -static uint32_t bootloader[] = { | |
475 | - 0xe3a00000, /* mov r0, #0 */ | |
476 | - 0xe3a01013, /* mov r1, #0x13 */ | |
477 | - 0xe3811c01, /* orr r1, r1, #0x100 */ | |
478 | - 0xe59f2000, /* ldr r2, [pc, #0] */ | |
479 | - 0xe59ff000, /* ldr pc, [pc, #0] */ | |
480 | - 0, /* Address of kernel args. Set by integratorcp_init. */ | |
481 | - 0 /* Kernel entry point. Set by integratorcp_init. */ | |
482 | -}; | |
483 | - | |
484 | -static void set_kernel_args(uint32_t ram_size, int initrd_size, | |
485 | - const char *kernel_cmdline) | |
486 | -{ | |
487 | - uint32_t *p; | |
488 | - | |
489 | - p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); | |
490 | - /* ATAG_CORE */ | |
491 | - stl_raw(p++, 5); | |
492 | - stl_raw(p++, 0x54410001); | |
493 | - stl_raw(p++, 1); | |
494 | - stl_raw(p++, 0x1000); | |
495 | - stl_raw(p++, 0); | |
496 | - /* ATAG_MEM */ | |
497 | - stl_raw(p++, 4); | |
498 | - stl_raw(p++, 0x54410002); | |
499 | - stl_raw(p++, ram_size); | |
500 | - stl_raw(p++, 0); | |
501 | - if (initrd_size) { | |
502 | - /* ATAG_INITRD2 */ | |
503 | - stl_raw(p++, 4); | |
504 | - stl_raw(p++, 0x54420005); | |
505 | - stl_raw(p++, INITRD_LOAD_ADDR); | |
506 | - stl_raw(p++, initrd_size); | |
507 | - } | |
508 | - if (kernel_cmdline && *kernel_cmdline) { | |
509 | - /* ATAG_CMDLINE */ | |
510 | - int cmdline_size; | |
511 | - | |
512 | - cmdline_size = strlen(kernel_cmdline); | |
513 | - memcpy (p + 2, kernel_cmdline, cmdline_size + 1); | |
514 | - cmdline_size = (cmdline_size >> 2) + 1; | |
515 | - stl_raw(p++, cmdline_size + 2); | |
516 | - stl_raw(p++, 0x54410009); | |
517 | - p += cmdline_size; | |
518 | - } | |
519 | - /* ATAG_END */ | |
520 | - stl_raw(p++, 0); | |
521 | - stl_raw(p++, 0); | |
522 | -} | |
523 | - | |
524 | 469 | /* Board init. */ |
525 | 470 | |
526 | 471 | static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device, |
... | ... | @@ -532,9 +477,6 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device, |
532 | 477 | uint32_t bios_offset; |
533 | 478 | icp_pic_state *pic; |
534 | 479 | void *cpu_pic; |
535 | - int kernel_size; | |
536 | - int initrd_size; | |
537 | - int n; | |
538 | 480 | |
539 | 481 | env = cpu_init(); |
540 | 482 | cpu_arm_set_model(env, cpuid); |
... | ... | @@ -567,33 +509,8 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device, |
567 | 509 | } |
568 | 510 | pl110_init(ds, 0xc0000000, pic, 22, 0); |
569 | 511 | |
570 | - /* Load the kernel. */ | |
571 | - if (!kernel_filename) { | |
572 | - fprintf(stderr, "Kernel image must be specified\n"); | |
573 | - exit(1); | |
574 | - } | |
575 | - kernel_size = load_image(kernel_filename, | |
576 | - phys_ram_base + KERNEL_LOAD_ADDR); | |
577 | - if (kernel_size < 0) { | |
578 | - fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); | |
579 | - exit(1); | |
580 | - } | |
581 | - if (initrd_filename) { | |
582 | - initrd_size = load_image(initrd_filename, | |
583 | - phys_ram_base + INITRD_LOAD_ADDR); | |
584 | - if (initrd_size < 0) { | |
585 | - fprintf(stderr, "qemu: could not load initrd '%s'\n", | |
586 | - initrd_filename); | |
587 | - exit(1); | |
588 | - } | |
589 | - } else { | |
590 | - initrd_size = 0; | |
591 | - } | |
592 | - bootloader[5] = KERNEL_ARGS_ADDR; | |
593 | - bootloader[6] = KERNEL_LOAD_ADDR; | |
594 | - for (n = 0; n < sizeof(bootloader) / 4; n++) | |
595 | - stl_raw(phys_ram_base + (n * 4), bootloader[n]); | |
596 | - set_kernel_args(ram_size, initrd_size, kernel_cmdline); | |
512 | + arm_load_kernel(ram_size, kernel_filename, kernel_cmdline, | |
513 | + initrd_filename, 0x113); | |
597 | 514 | } |
598 | 515 | |
599 | 516 | static void integratorcp926_init(int ram_size, int vga_ram_size, | ... | ... |
hw/versatilepb.c
1 | 1 | /* |
2 | - * ARM Versatile Platform Baseboard System emulation. | |
2 | + * ARM Versatile Platform/Application Baseboard System emulation. | |
3 | 3 | * |
4 | 4 | * Copyright (c) 2005-2006 CodeSourcery. |
5 | 5 | * Written by Paul Brook |
... | ... | @@ -10,10 +10,6 @@ |
10 | 10 | #include "vl.h" |
11 | 11 | #include "arm_pic.h" |
12 | 12 | |
13 | -#define KERNEL_ARGS_ADDR 0x100 | |
14 | -#define KERNEL_LOAD_ADDR 0x00010000 | |
15 | -#define INITRD_LOAD_ADDR 0x00800000 | |
16 | - | |
17 | 13 | /* Primary interrupt controller. */ |
18 | 14 | |
19 | 15 | typedef struct vpb_sic_state |
... | ... | @@ -151,66 +147,16 @@ static vpb_sic_state *vpb_sic_init(uint32_t base, void *parent, int irq) |
151 | 147 | |
152 | 148 | /* Board init. */ |
153 | 149 | |
154 | -/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ | |
155 | -static uint32_t bootloader[] = { | |
156 | - 0xe3a00000, /* mov r0, #0 */ | |
157 | - 0xe3a01083, /* mov r1, #0x83 */ | |
158 | - 0xe3811c01, /* orr r1, r1, #0x100 */ | |
159 | - 0xe59f2000, /* ldr r2, [pc, #0] */ | |
160 | - 0xe59ff000, /* ldr pc, [pc, #0] */ | |
161 | - 0, /* Address of kernel args. Set by integratorcp_init. */ | |
162 | - 0 /* Kernel entry point. Set by integratorcp_init. */ | |
163 | -}; | |
164 | - | |
165 | -static void set_kernel_args(uint32_t ram_size, int initrd_size, | |
166 | - const char *kernel_cmdline) | |
167 | -{ | |
168 | - uint32_t *p; | |
169 | - | |
170 | - p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR); | |
171 | - /* ATAG_CORE */ | |
172 | - stl_raw(p++, 5); | |
173 | - stl_raw(p++, 0x54410001); | |
174 | - stl_raw(p++, 1); | |
175 | - stl_raw(p++, 0x1000); | |
176 | - stl_raw(p++, 0); | |
177 | - /* ATAG_MEM */ | |
178 | - stl_raw(p++, 4); | |
179 | - stl_raw(p++, 0x54410002); | |
180 | - stl_raw(p++, ram_size); | |
181 | - stl_raw(p++, 0); | |
182 | - if (initrd_size) { | |
183 | - /* ATAG_INITRD2 */ | |
184 | - stl_raw(p++, 4); | |
185 | - stl_raw(p++, 0x54420005); | |
186 | - stl_raw(p++, INITRD_LOAD_ADDR); | |
187 | - stl_raw(p++, initrd_size); | |
188 | - } | |
189 | - if (kernel_cmdline && *kernel_cmdline) { | |
190 | - /* ATAG_CMDLINE */ | |
191 | - int cmdline_size; | |
150 | +/* The AB and PB boards both use the same core, just with different | |
151 | + peripherans and expansion busses. For now we emulate a subset of the | |
152 | + PB peripherals and just change the board ID. */ | |
192 | 153 | |
193 | - cmdline_size = strlen(kernel_cmdline); | |
194 | - memcpy (p + 2, kernel_cmdline, cmdline_size + 1); | |
195 | - cmdline_size = (cmdline_size >> 2) + 1; | |
196 | - stl_raw(p++, cmdline_size + 2); | |
197 | - stl_raw(p++, 0x54410009); | |
198 | - p += cmdline_size; | |
199 | - } | |
200 | - /* ATAG_END */ | |
201 | - stl_raw(p++, 0); | |
202 | - stl_raw(p++, 0); | |
203 | -} | |
204 | - | |
205 | -static void vpb_init(int ram_size, int vga_ram_size, int boot_device, | |
154 | +static void versatile_init(int ram_size, int vga_ram_size, int boot_device, | |
206 | 155 | DisplayState *ds, const char **fd_filename, int snapshot, |
207 | 156 | const char *kernel_filename, const char *kernel_cmdline, |
208 | - const char *initrd_filename) | |
157 | + const char *initrd_filename, int board_id) | |
209 | 158 | { |
210 | 159 | CPUState *env; |
211 | - int kernel_size; | |
212 | - int initrd_size; | |
213 | - int n; | |
214 | 160 | void *pic; |
215 | 161 | void *sic; |
216 | 162 | |
... | ... | @@ -250,6 +196,7 @@ static void vpb_init(int ram_size, int vga_ram_size, int boot_device, |
250 | 196 | that includes hardware cursor support from the PL111. */ |
251 | 197 | pl110_init(ds, 0x10120000, pic, 16, 1); |
252 | 198 | |
199 | + /* Memory map for Versatile/PB: */ | |
253 | 200 | /* 0x10000000 System registers. */ |
254 | 201 | /* 0x10001000 PCI controller config registers. */ |
255 | 202 | /* 0x10002000 Serial bus interface. */ |
... | ... | @@ -285,33 +232,30 @@ static void vpb_init(int ram_size, int vga_ram_size, int boot_device, |
285 | 232 | /* 0x101f3000 UART2. */ |
286 | 233 | /* 0x101f4000 SSPI. */ |
287 | 234 | |
288 | - /* Load the kernel. */ | |
289 | - if (!kernel_filename) { | |
290 | - fprintf(stderr, "Kernel image must be specified\n"); | |
291 | - exit(1); | |
292 | - } | |
293 | - kernel_size = load_image(kernel_filename, | |
294 | - phys_ram_base + KERNEL_LOAD_ADDR); | |
295 | - if (kernel_size < 0) { | |
296 | - fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); | |
297 | - exit(1); | |
298 | - } | |
299 | - if (initrd_filename) { | |
300 | - initrd_size = load_image(initrd_filename, | |
301 | - phys_ram_base + INITRD_LOAD_ADDR); | |
302 | - if (initrd_size < 0) { | |
303 | - fprintf(stderr, "qemu: could not load initrd '%s'\n", | |
304 | - initrd_filename); | |
305 | - exit(1); | |
306 | - } | |
307 | - } else { | |
308 | - initrd_size = 0; | |
309 | - } | |
310 | - bootloader[5] = KERNEL_ARGS_ADDR; | |
311 | - bootloader[6] = KERNEL_LOAD_ADDR; | |
312 | - for (n = 0; n < sizeof(bootloader) / 4; n++) | |
313 | - stl_raw(phys_ram_base + (n * 4), bootloader[n]); | |
314 | - set_kernel_args(ram_size, initrd_size, kernel_cmdline); | |
235 | + arm_load_kernel(ram_size, kernel_filename, kernel_cmdline, | |
236 | + initrd_filename, board_id); | |
237 | +} | |
238 | + | |
239 | +static void vpb_init(int ram_size, int vga_ram_size, int boot_device, | |
240 | + DisplayState *ds, const char **fd_filename, int snapshot, | |
241 | + const char *kernel_filename, const char *kernel_cmdline, | |
242 | + const char *initrd_filename) | |
243 | +{ | |
244 | + versatile_init(ram_size, vga_ram_size, boot_device, | |
245 | + ds, fd_filename, snapshot, | |
246 | + kernel_filename, kernel_cmdline, | |
247 | + initrd_filename, 0x183); | |
248 | +} | |
249 | + | |
250 | +static void vab_init(int ram_size, int vga_ram_size, int boot_device, | |
251 | + DisplayState *ds, const char **fd_filename, int snapshot, | |
252 | + const char *kernel_filename, const char *kernel_cmdline, | |
253 | + const char *initrd_filename) | |
254 | +{ | |
255 | + versatile_init(ram_size, vga_ram_size, boot_device, | |
256 | + ds, fd_filename, snapshot, | |
257 | + kernel_filename, kernel_cmdline, | |
258 | + initrd_filename, 0x25e); | |
315 | 259 | } |
316 | 260 | |
317 | 261 | QEMUMachine versatilepb_machine = { |
... | ... | @@ -319,3 +263,9 @@ QEMUMachine versatilepb_machine = { |
319 | 263 | "ARM Versatile/PB (ARM926EJ-S)", |
320 | 264 | vpb_init, |
321 | 265 | }; |
266 | + | |
267 | +QEMUMachine versatileab_machine = { | |
268 | + "versatileab", | |
269 | + "ARM Versatile/AB (ARM926EJ-S)", | |
270 | + vab_init, | |
271 | +}; | ... | ... |
vl.c
... | ... | @@ -4863,6 +4863,7 @@ void register_machines(void) |
4863 | 4863 | qemu_register_machine(&integratorcp926_machine); |
4864 | 4864 | qemu_register_machine(&integratorcp1026_machine); |
4865 | 4865 | qemu_register_machine(&versatilepb_machine); |
4866 | + qemu_register_machine(&versatileab_machine); | |
4866 | 4867 | #elif defined(TARGET_SH4) |
4867 | 4868 | qemu_register_machine(&shix_machine); |
4868 | 4869 | #else | ... | ... |
vl.h
... | ... | @@ -987,6 +987,7 @@ extern QEMUMachine integratorcp1026_machine; |
987 | 987 | |
988 | 988 | /* versatilepb.c */ |
989 | 989 | extern QEMUMachine versatilepb_machine; |
990 | +extern QEMUMachine versatileab_machine; | |
990 | 991 | |
991 | 992 | /* ps2.c */ |
992 | 993 | void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg); |
... | ... | @@ -1019,6 +1020,12 @@ void *pl190_init(uint32_t base, void *parent, int irq, int fiq); |
1019 | 1020 | void sp804_init(uint32_t base, void *pic, int irq); |
1020 | 1021 | void icp_pit_init(uint32_t base, void *pic, int irq); |
1021 | 1022 | |
1023 | +/* arm_boot.c */ | |
1024 | + | |
1025 | +void arm_load_kernel(int ram_size, const char *kernel_filename, | |
1026 | + const char *kernel_cmdline, const char *initrd_filename, | |
1027 | + int board_id); | |
1028 | + | |
1022 | 1029 | /* sh7750.c */ |
1023 | 1030 | struct SH7750State; |
1024 | 1031 | ... | ... |