Commit 66a93e0f47fa9869178008c7bc38d66a7c5e45f4
1 parent
9ee3c029
ELF loader (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1860 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
41 additions
and
39 deletions
hw/mips_r4k.c
... | ... | @@ -5,6 +5,8 @@ |
5 | 5 | #define KERNEL_LOAD_ADDR 0x80010000 |
6 | 6 | #define INITRD_LOAD_ADDR 0x80800000 |
7 | 7 | |
8 | +#define VIRT_TO_PHYS_ADDEND (-0x80000000LL) | |
9 | + | |
8 | 10 | extern FILE *logfile; |
9 | 11 | |
10 | 12 | static PITState *pit; |
... | ... | @@ -101,6 +103,7 @@ void cpu_mips_clock_init (CPUState *env) |
101 | 103 | cpu_mips_update_count(env, 1, 0); |
102 | 104 | } |
103 | 105 | |
106 | + | |
104 | 107 | static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
105 | 108 | { |
106 | 109 | #if 0 |
... | ... | @@ -189,72 +192,71 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, |
189 | 192 | const char *initrd_filename) |
190 | 193 | { |
191 | 194 | char buf[1024]; |
192 | - target_ulong kernel_base, kernel_size, initrd_base, initrd_size; | |
195 | + int64_t entry = 0; | |
193 | 196 | unsigned long bios_offset; |
194 | 197 | int io_memory; |
195 | - int linux_boot; | |
196 | 198 | int ret; |
197 | 199 | CPUState *env; |
198 | - | |
199 | - printf("%s: start\n", __func__); | |
200 | - linux_boot = (kernel_filename != NULL); | |
200 | + long kernel_size; | |
201 | 201 | |
202 | 202 | env = cpu_init(); |
203 | 203 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); |
204 | 204 | |
205 | 205 | /* allocate RAM */ |
206 | 206 | cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); |
207 | + | |
208 | + /* Try to load a BIOS image. If this fails, we continue regardless, | |
209 | + but initialize the hardware ourselves. When a kernel gets | |
210 | + preloaded we also initialize the hardware, since the BIOS wasn't | |
211 | + run. */ | |
207 | 212 | bios_offset = ram_size + vga_ram_size; |
208 | 213 | snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); |
209 | 214 | printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE); |
210 | 215 | ret = load_image(buf, phys_ram_base + bios_offset); |
211 | - if (ret != BIOS_SIZE) { | |
212 | - fprintf(stderr, "qemu: could not load MIPS bios '%s'\n", buf); | |
213 | - exit(1); | |
216 | + if (ret == BIOS_SIZE) { | |
217 | + cpu_register_physical_memory((uint32_t)(0x1fc00000), | |
218 | + BIOS_SIZE, bios_offset | IO_MEM_ROM); | |
219 | + env->PC = 0xBFC00000; | |
220 | + if (!kernel_filename) | |
221 | + return; | |
222 | + } else { | |
223 | + /* not fatal */ | |
224 | + fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", | |
225 | + buf); | |
214 | 226 | } |
215 | - cpu_register_physical_memory((uint32_t)(0x1fc00000), | |
216 | - BIOS_SIZE, bios_offset | IO_MEM_ROM); | |
217 | -#if 0 | |
218 | - memcpy(phys_ram_base + 0x10000, phys_ram_base + bios_offset, BIOS_SIZE); | |
219 | - env->PC = 0x80010004; | |
220 | -#else | |
221 | - env->PC = 0xBFC00004; | |
222 | -#endif | |
223 | - if (linux_boot) { | |
224 | - kernel_base = KERNEL_LOAD_ADDR; | |
225 | - /* now we can load the kernel */ | |
226 | - kernel_size = load_image(kernel_filename, | |
227 | - phys_ram_base + (kernel_base - 0x80000000)); | |
228 | - if (kernel_size == (target_ulong) -1) { | |
229 | - fprintf(stderr, "qemu: could not load kernel '%s'\n", | |
230 | - kernel_filename); | |
231 | - exit(1); | |
232 | - } | |
227 | + | |
228 | + kernel_size = 0; | |
229 | + if (kernel_filename) { | |
230 | + kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry); | |
231 | + if (kernel_size >= 0) | |
232 | + env->PC = entry; | |
233 | + else { | |
234 | + kernel_size = load_image(kernel_filename, | |
235 | + phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND); | |
236 | + if (kernel_size < 0) { | |
237 | + fprintf(stderr, "qemu: could not load kernel '%s'\n", | |
238 | + kernel_filename); | |
239 | + exit(1); | |
240 | + } | |
241 | + env->PC = KERNEL_LOAD_ADDR; | |
242 | + } | |
243 | + | |
233 | 244 | /* load initrd */ |
234 | 245 | if (initrd_filename) { |
235 | - initrd_base = INITRD_LOAD_ADDR; | |
236 | - initrd_size = load_image(initrd_filename, | |
237 | - phys_ram_base + initrd_base); | |
238 | - if (initrd_size == (target_ulong) -1) { | |
246 | + if (load_image(initrd_filename, | |
247 | + phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND) | |
248 | + == (target_ulong) -1) { | |
239 | 249 | fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", |
240 | 250 | initrd_filename); |
241 | 251 | exit(1); |
242 | 252 | } |
243 | - } else { | |
244 | - initrd_base = 0; | |
245 | - initrd_size = 0; | |
246 | 253 | } |
247 | - env->PC = KERNEL_LOAD_ADDR; | |
254 | + | |
248 | 255 | /* Store command line. */ |
249 | 256 | strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline); |
250 | 257 | /* FIXME: little endian support */ |
251 | 258 | *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678); |
252 | 259 | *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size); |
253 | - } else { | |
254 | - kernel_base = 0; | |
255 | - kernel_size = 0; | |
256 | - initrd_base = 0; | |
257 | - initrd_size = 0; | |
258 | 260 | } |
259 | 261 | |
260 | 262 | /* Init internal devices */ | ... | ... |