1:
2:
3:
4:
5:
6:
7:
8:
9:
10: #include "hw.h"
11: #include "arm-misc.h"
12: #include "sysemu.h"
13:
14: #define KERNEL_ARGS_ADDR 0x100
15: #define KERNEL_LOAD_ADDR 0x00010000
16: #define INITRD_LOAD_ADDR 0x00800000
17:
18:
19: static uint32_t bootloader[] = {
20: 0xe3a00000,
21: 0xe3a01000,
22: 0xe3811c00,
23: 0xe59f2000,
24: 0xe59ff000,
25: 0,
26: 0
27: };
28:
29:
30:
31: static uint32_t smpboot[] = {
32: 0xe3a00201,
33: 0xe3800601,
34: 0xe3a01001,
35: 0xe5801100,
36: 0xe3a00201,
37: 0xe3800030,
38: 0xe320f003,
39: 0xe5901000,
40: 0xe3110003,
41: 0x1afffffb,
42: 0xe12fff11
43: };
44:
45: static void main_cpu_reset(void *opaque)
46: {
47: CPUState *env = opaque;
48:
49: cpu_reset(env);
50: if (env->kernel_filename)
51: arm_load_kernel(env, env->ram_size, env->kernel_filename,
52: env->kernel_cmdline, env->initrd_filename,
53: env->board_id, env->loader_start);
54:
55:
56: }
57:
58: static void set_kernel_args(uint32_t ram_size, int initrd_size,
59: const char *kernel_cmdline,
60: target_phys_addr_t loader_start)
61: {
62: uint32_t *p;
63:
64: p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
65:
66: stl_raw(p++, 5);
67: stl_raw(p++, 0x54410001);
68: stl_raw(p++, 1);
69: stl_raw(p++, 0x1000);
70: stl_raw(p++, 0);
71:
72: stl_raw(p++, 4);
73: stl_raw(p++, 0x54410002);
74: stl_raw(p++, ram_size);
75: stl_raw(p++, loader_start);
76: if (initrd_size) {
77:
78: stl_raw(p++, 4);
79: stl_raw(p++, 0x54420005);
80: stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
81: stl_raw(p++, initrd_size);
82: }
83: if (kernel_cmdline && *kernel_cmdline) {
84:
85: int cmdline_size;
86:
87: cmdline_size = strlen(kernel_cmdline);
88: memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
89: cmdline_size = (cmdline_size >> 2) + 1;
90: stl_raw(p++, cmdline_size + 2);
91: stl_raw(p++, 0x54410009);
92: p += cmdline_size;
93: }
94:
95: stl_raw(p++, 0);
96: stl_raw(p++, 0);
97: }
98:
99: static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
100: const char *kernel_cmdline,
101: target_phys_addr_t loader_start)
102: {
103: uint32_t *p;
104: unsigned char *s;
105:
106:
107: p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
108:
109: stl_raw(p++, 4096);
110:
111: stl_raw(p++, ram_size / 4096);
112:
113: stl_raw(p++, 0);
114: #define FLAG_READONLY 1
115: #define FLAG_RDLOAD 4
116: #define FLAG_RDPROMPT 8
117:
118: stl_raw(p++, FLAG_READONLY | FLAG_RDLOAD | FLAG_RDPROMPT);
119:
120: stl_raw(p++, (31 << 8) | 0);
121:
122: stl_raw(p++, 0);
123:
124: stl_raw(p++, 0);
125:
126: stl_raw(p++, 0);
127:
128: stl_raw(p++, 0);
129:
130: stl_raw(p++, 0);
131:
132:
133:
134:
135: stl_raw(p++, 0);
136:
137: stl_raw(p++, 0);
138: stl_raw(p++, 0);
139: stl_raw(p++, 0);
140: stl_raw(p++, 0);
141:
142: stl_raw(p++, 0);
143:
144: if (initrd_size)
145: stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
146: else
147: stl_raw(p++, 0);
148:
149: stl_raw(p++, initrd_size);
150:
151: stl_raw(p++, 0);
152:
153: stl_raw(p++, 0);
154:
155: stl_raw(p++, 0);
156:
157: stl_raw(p++, 0);
158:
159: stl_raw(p++, 0);
160:
161: memset(p, 0, 256 + 1024 -
162: (p - ((uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR))));
163: s = phys_ram_base + KERNEL_ARGS_ADDR + 256 + 1024;
164: if (kernel_cmdline)
165: strcpy (s, kernel_cmdline);
166: else
167: stb_raw(s, 0);
168: }
169:
170: void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
171: const char *kernel_cmdline, const char *initrd_filename,
172: int board_id, target_phys_addr_t loader_start)
173: {
174: int kernel_size;
175: int initrd_size;
176: int n;
177: int is_linux = 0;
178: uint64_t elf_entry;
179: target_ulong entry;
180:
181:
182: if (!kernel_filename) {
183: fprintf(stderr, "Kernel image must be specified\n");
184: exit(1);
185: }
186:
187: if (!env->kernel_filename) {
188: env->ram_size = ram_size;
189: env->kernel_filename = kernel_filename;
190: env->kernel_cmdline = kernel_cmdline;
191: env->initrd_filename = initrd_filename;
192: env->board_id = board_id;
193: env->loader_start = loader_start;
194: qemu_register_reset(main_cpu_reset, env);
195: }
196:
197: kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
198: entry = elf_entry;
199: if (kernel_size < 0) {
200: kernel_size = load_uboot(kernel_filename, &entry, &is_linux);
201: }
202: if (kernel_size < 0) {
203: kernel_size = load_image(kernel_filename,
204: phys_ram_base + KERNEL_LOAD_ADDR);
205: entry = loader_start + KERNEL_LOAD_ADDR;
206: is_linux = 1;
207: }
208: if (kernel_size < 0) {
209: fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
210: exit(1);
211: }
212: if (!is_linux) {
213:
214: env->regs[15] = entry & 0xfffffffe;
215: env->thumb = entry & 1;
216: } else {
217: if (initrd_filename) {
218: initrd_size = load_image(initrd_filename,
219: phys_ram_base + INITRD_LOAD_ADDR);
220: if (initrd_size < 0) {
221: fprintf(stderr, "qemu: could not load initrd '%s'\n",
222: initrd_filename);
223: exit(1);
224: }
225: } else {
226: initrd_size = 0;
227: }
228: bootloader[1] |= board_id & 0xff;
229: bootloader[2] |= (board_id >> 8) & 0xff;
230: bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
231: bootloader[6] = entry;
232: for (n = 0; n < sizeof(bootloader) / 4; n++)
233: stl_raw(phys_ram_base + (n * 4), bootloader[n]);
234: for (n = 0; n < sizeof(smpboot) / 4; n++)
235: stl_raw(phys_ram_base + ram_size + (n * 4), smpboot[n]);
236: if (old_param)
237: set_kernel_args_old(ram_size, initrd_size,
238: kernel_cmdline, loader_start);
239: else
240: set_kernel_args(ram_size, initrd_size,
241: kernel_cmdline, loader_start);
242: }
243: }