Commit 66a93e0f47fa9869178008c7bc38d66a7c5e45f4

Authored by bellard
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 */