1 |
/* |
/* |
2 |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: file.c,v 1.131 2006/03/30 19:36:03 debug Exp $ |
* $Id: file.c,v 1.140 2007/02/10 14:29:54 debug Exp $ |
29 |
* |
* |
30 |
* This file contains functions which load executable images into (emulated) |
* This file contains functions which load executable images into (emulated) |
31 |
* memory. File formats recognized so far are: |
* memory. File formats recognized so far are: |
1163 |
char *filename, uint64_t *entrypointp) |
char *filename, uint64_t *entrypointp) |
1164 |
{ |
{ |
1165 |
FILE *f; |
FILE *f; |
1166 |
int len; |
int len, sign3264; |
1167 |
unsigned char buf[4096]; |
unsigned char buf[16384]; |
1168 |
uint64_t entry, loadaddr, vaddr, skip = 0; |
uint64_t entry, loadaddr, vaddr, skip = 0; |
1169 |
char *p, *p2; |
char *p, *p2; |
1170 |
|
|
1171 |
|
/* Special case for 32-bit MIPS: */ |
1172 |
|
sign3264 = 0; |
1173 |
|
if (m->arch == ARCH_MIPS && m->cpus[0]->is_32bit) |
1174 |
|
sign3264 = 1; |
1175 |
|
|
1176 |
p = strchr(filename, ':'); |
p = strchr(filename, ':'); |
1177 |
if (p == NULL) { |
if (p == NULL) { |
1178 |
fprintf(stderr, "\n"); |
fprintf(stderr, "\n"); |
1196 |
} else |
} else |
1197 |
p = p2; |
p = p2; |
1198 |
|
|
1199 |
|
if (sign3264) { |
1200 |
|
loadaddr = (int64_t)(int32_t)loadaddr; |
1201 |
|
entry = (int64_t)(int32_t)entry; |
1202 |
|
vaddr = (int64_t)(int32_t)vaddr; |
1203 |
|
skip = (int64_t)(int32_t)skip; |
1204 |
|
} |
1205 |
|
|
1206 |
f = fopen(strrchr(filename, ':')+1, "r"); |
f = fopen(strrchr(filename, ':')+1, "r"); |
1207 |
if (f == NULL) { |
if (f == NULL) { |
1208 |
perror(p); |
perror(p); |
1213 |
|
|
1214 |
/* Load file contents: */ |
/* Load file contents: */ |
1215 |
while (!feof(f)) { |
while (!feof(f)) { |
1216 |
len = fread(buf, 1, sizeof(buf), f); |
size_t to_read = sizeof(buf); |
1217 |
|
|
1218 |
|
/* If vaddr isn't buf-size aligned, then start with a |
1219 |
|
smaller buffer: */ |
1220 |
|
if (vaddr & (sizeof(buf) - 1)) |
1221 |
|
to_read = sizeof(buf) - (vaddr & (sizeof(buf)-1)); |
1222 |
|
|
1223 |
|
len = fread(buf, 1, to_read, f); |
1224 |
|
|
1225 |
if (len > 0) |
if (len > 0) |
1226 |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], |
m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], |
1405 |
ok = 1; |
ok = 1; |
1406 |
} |
} |
1407 |
break; |
break; |
1408 |
|
/* case ARCH_AVR32: |
1409 |
|
switch (emachine) { |
1410 |
|
case 6317: |
1411 |
|
ok = 1; |
1412 |
|
} |
1413 |
|
break; |
1414 |
case ARCH_HPPA: |
case ARCH_HPPA: |
1415 |
switch (emachine) { |
switch (emachine) { |
1416 |
case EM_PARISC: |
case EM_PARISC: |
1428 |
case EM_IA_64: |
case EM_IA_64: |
1429 |
ok = 1; |
ok = 1; |
1430 |
} |
} |
1431 |
break; |
break; */ |
1432 |
case ARCH_M68K: |
case ARCH_M68K: |
1433 |
switch (emachine) { |
switch (emachine) { |
1434 |
case EM_68K: |
case EM_68K: |
1462 |
ok = 1; |
ok = 1; |
1463 |
} |
} |
1464 |
break; |
break; |
1465 |
case ARCH_X86: |
/* case ARCH_X86: |
1466 |
switch (emachine) { |
switch (emachine) { |
1467 |
case EM_386: |
case EM_386: |
1468 |
case EM_486: |
case EM_486: |
1474 |
ok = 1; |
ok = 1; |
1475 |
break; |
break; |
1476 |
} |
} |
1477 |
break; |
break; */ |
1478 |
default: |
default: |
1479 |
fatal("file.c: INTERNAL ERROR: Unimplemented arch!\n"); |
fatal("file.c: INTERNAL ERROR: Unimplemented arch!\n"); |
1480 |
} |
} |
1501 |
debug("%08"PRIx32"\n", (uint32_t) eentry); |
debug("%08"PRIx32"\n", (uint32_t) eentry); |
1502 |
|
|
1503 |
/* |
/* |
1504 |
* SH64: 32-bit instruction encoding? TODO |
* SH64: 32-bit instruction encoding? |
1505 |
*/ |
*/ |
1506 |
if (arch == ARCH_SH && (eentry & 1)) { |
if (arch == ARCH_SH && (eentry & 1)) { |
1507 |
debug("SH64: 32-bit instruction encoding\n"); |
debug("SH64: 32-bit instruction encoding\n"); |
1508 |
m->cpus[0]->cd.sh.compact = 0; |
m->cpus[0]->cd.sh.compact = 0; |
1509 |
m->cpus[0]->cd.sh.bits = 64; |
m->cpus[0]->cd.sh.cpu_type.bits = 64; |
1510 |
} |
} |
1511 |
|
|
1512 |
/* Read the program headers: */ |
/* Read the program headers: */ |
2086 |
"floppy image. Maybe you forgot the\n-d switch?\n"); |
"floppy image. Maybe you forgot the\n-d switch?\n"); |
2087 |
|
|
2088 |
/* |
/* |
2089 |
|
* Ugly hack for Dreamcast: When booting from a Dreamcast CDROM |
2090 |
|
* image, a temporary file is extracted into /tmp/gxemul.*, but this |
2091 |
|
* is a "scrambled" raw binary. This code unscrambles it, and loads |
2092 |
|
* it as a raw binary. |
2093 |
|
*/ |
2094 |
|
if (machine->machine_type == MACHINE_DREAMCAST && |
2095 |
|
strncmp(filename, "/tmp/gxemul.", 12) == 0) { |
2096 |
|
char *tmp_filename = malloc(strlen(filename) + 100); |
2097 |
|
snprintf(tmp_filename, strlen(filename) + 100, |
2098 |
|
"%s.descrambled", filename); |
2099 |
|
debug("descrambling into %s\n", tmp_filename); |
2100 |
|
dreamcast_descramble(filename, tmp_filename); |
2101 |
|
|
2102 |
|
snprintf(tmp_filename, strlen(filename) + 100, |
2103 |
|
"0x8c010000:%s.descrambled", filename); |
2104 |
|
debug("loading descrambled Dreamcast binary\n"); |
2105 |
|
file_load_raw(machine, mem, tmp_filename, entrypointp); |
2106 |
|
free(tmp_filename); |
2107 |
|
|
2108 |
|
/* Hack: Start a "boot from CDROM" sequence: */ |
2109 |
|
*entrypointp = 0x8c000080; |
2110 |
|
goto ret; |
2111 |
|
} |
2112 |
|
|
2113 |
|
/* |
2114 |
* Last resort: symbol definitions from nm (or nm -S): |
* Last resort: symbol definitions from nm (or nm -S): |
2115 |
* |
* |
2116 |
* If the buf contains typical 'binary' characters, then print |
* If the buf contains typical 'binary' characters, then print |