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,6 +5,8 @@ | ||
| 5 | #define KERNEL_LOAD_ADDR 0x80010000 | 5 | #define KERNEL_LOAD_ADDR 0x80010000 |
| 6 | #define INITRD_LOAD_ADDR 0x80800000 | 6 | #define INITRD_LOAD_ADDR 0x80800000 |
| 7 | 7 | ||
| 8 | +#define VIRT_TO_PHYS_ADDEND (-0x80000000LL) | ||
| 9 | + | ||
| 8 | extern FILE *logfile; | 10 | extern FILE *logfile; |
| 9 | 11 | ||
| 10 | static PITState *pit; | 12 | static PITState *pit; |
| @@ -101,6 +103,7 @@ void cpu_mips_clock_init (CPUState *env) | @@ -101,6 +103,7 @@ void cpu_mips_clock_init (CPUState *env) | ||
| 101 | cpu_mips_update_count(env, 1, 0); | 103 | cpu_mips_update_count(env, 1, 0); |
| 102 | } | 104 | } |
| 103 | 105 | ||
| 106 | + | ||
| 104 | static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | 107 | static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 105 | { | 108 | { |
| 106 | #if 0 | 109 | #if 0 |
| @@ -189,72 +192,71 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, | @@ -189,72 +192,71 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, | ||
| 189 | const char *initrd_filename) | 192 | const char *initrd_filename) |
| 190 | { | 193 | { |
| 191 | char buf[1024]; | 194 | char buf[1024]; |
| 192 | - target_ulong kernel_base, kernel_size, initrd_base, initrd_size; | 195 | + int64_t entry = 0; |
| 193 | unsigned long bios_offset; | 196 | unsigned long bios_offset; |
| 194 | int io_memory; | 197 | int io_memory; |
| 195 | - int linux_boot; | ||
| 196 | int ret; | 198 | int ret; |
| 197 | CPUState *env; | 199 | CPUState *env; |
| 198 | - | ||
| 199 | - printf("%s: start\n", __func__); | ||
| 200 | - linux_boot = (kernel_filename != NULL); | 200 | + long kernel_size; |
| 201 | 201 | ||
| 202 | env = cpu_init(); | 202 | env = cpu_init(); |
| 203 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); | 203 | register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); |
| 204 | 204 | ||
| 205 | /* allocate RAM */ | 205 | /* allocate RAM */ |
| 206 | cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); | 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 | bios_offset = ram_size + vga_ram_size; | 212 | bios_offset = ram_size + vga_ram_size; |
| 208 | snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); | 213 | snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); |
| 209 | printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE); | 214 | printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE); |
| 210 | ret = load_image(buf, phys_ram_base + bios_offset); | 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 | /* load initrd */ | 244 | /* load initrd */ |
| 234 | if (initrd_filename) { | 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 | fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", | 249 | fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", |
| 240 | initrd_filename); | 250 | initrd_filename); |
| 241 | exit(1); | 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 | /* Store command line. */ | 255 | /* Store command line. */ |
| 249 | strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline); | 256 | strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline); |
| 250 | /* FIXME: little endian support */ | 257 | /* FIXME: little endian support */ |
| 251 | *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678); | 258 | *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678); |
| 252 | *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size); | 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 | /* Init internal devices */ | 262 | /* Init internal devices */ |