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