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 */ | ... | ... |