1 |
/* |
/* |
2 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2006 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: arcbios.c,v 1.2 2005/11/16 21:15:20 debug Exp $ |
* $Id: arcbios.c,v 1.5 2006/02/09 22:40:27 debug Exp $ |
29 |
* |
* |
30 |
* ARCBIOS emulation. |
* ARCBIOS emulation. |
31 |
*/ |
*/ |
451 |
/* |
/* |
452 |
* TODO: Huh? Why isn't it necessary to convert from arc to sgi types? |
* TODO: Huh? Why isn't it necessary to convert from arc to sgi types? |
453 |
* |
* |
454 |
* TODO 2: It seems that it _is_ neccessary, but NetBSD's arcdiag |
* TODO 2: It seems that it _is_ necessary, but NetBSD's arcdiag |
455 |
* doesn't handle the sgi case separately. |
* doesn't handle the sgi case separately. |
456 |
*/ |
*/ |
457 |
#if 1 |
#if 1 |
843 |
|
|
844 |
if (config_data != NULL) { |
if (config_data != NULL) { |
845 |
unsigned char *p = config_data; |
unsigned char *p = config_data; |
846 |
int i; |
size_t i; |
847 |
|
|
848 |
if (machine->md.arc.n_configuration_data >= MAX_CONFIG_DATA) { |
if (machine->md.arc.n_configuration_data >= MAX_CONFIG_DATA) { |
849 |
printf("fatal error: you need to increase " |
printf("fatal error: you need to increase " |
1383 |
int match_len = 0; |
int match_len = 0; |
1384 |
|
|
1385 |
memset(buf, 0, sizeof(buf)); |
memset(buf, 0, sizeof(buf)); |
1386 |
for (i=0; i<sizeof(buf); i++) { |
for (i=0; i<(ssize_t)sizeof(buf); i++) { |
1387 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1388 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
1389 |
&buf[i], 1, MEM_READ, CACHE_NONE); |
&buf[i], 1, MEM_READ, CACHE_NONE); |
1551 |
machine->tick_func[i](cpu, |
machine->tick_func[i](cpu, |
1552 |
machine->tick_extra[i]); |
machine->tick_extra[i]); |
1553 |
|
|
1554 |
for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) { |
for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2]; |
1555 |
|
i++) { |
1556 |
int x; |
int x; |
1557 |
unsigned char ch; |
unsigned char ch; |
1558 |
|
|
1690 |
break; |
break; |
1691 |
} |
} |
1692 |
|
|
1693 |
for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) |
for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) |
1694 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1695 |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
1696 |
&tmp_buf[i], sizeof(char), MEM_READ, |
&tmp_buf[i], sizeof(char), MEM_READ, |
1712 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO; |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO; |
1713 |
free(tmp_buf); |
free(tmp_buf); |
1714 |
} else { |
} else { |
1715 |
for (i=0; i<cpu->cd.mips.gpr[MIPS_GPR_A2]; i++) { |
for (i=0; i<(int32_t)cpu->cd.mips.gpr[MIPS_GPR_A2]; |
1716 |
|
i++) { |
1717 |
unsigned char ch = '\0'; |
unsigned char ch = '\0'; |
1718 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1719 |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
1769 |
break; |
break; |
1770 |
case 0x78: /* GetEnvironmentVariable(char *) */ |
case 0x78: /* GetEnvironmentVariable(char *) */ |
1771 |
/* Find the environment variable given by a0: */ |
/* Find the environment variable given by a0: */ |
1772 |
for (i=0; i<sizeof(buf); i++) |
for (i=0; i<(ssize_t)sizeof(buf); i++) |
1773 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1774 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
1775 |
&buf[i], sizeof(char), MEM_READ, CACHE_NONE); |
&buf[i], sizeof(char), MEM_READ, CACHE_NONE); |
1778 |
for (i=0; i<0x1000; i++) { |
for (i=0; i<0x1000; i++) { |
1779 |
/* Matching string at offset i? */ |
/* Matching string at offset i? */ |
1780 |
int nmatches = 0; |
int nmatches = 0; |
1781 |
for (j=0; j<strlen((char *)buf); j++) { |
for (j=0; j<(ssize_t)strlen((char *)buf); j++) { |
1782 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1783 |
(uint64_t)(ARC_ENV_STRINGS + i + j), |
(uint64_t)(ARC_ENV_STRINGS + i + j), |
1784 |
&ch2, sizeof(char), MEM_READ, CACHE_NONE); |
&ch2, sizeof(char), MEM_READ, CACHE_NONE); |
1789 |
(uint64_t)(ARC_ENV_STRINGS + i + |
(uint64_t)(ARC_ENV_STRINGS + i + |
1790 |
strlen((char *)buf)), &ch2, sizeof(char), |
strlen((char *)buf)), &ch2, sizeof(char), |
1791 |
MEM_READ, CACHE_NONE); |
MEM_READ, CACHE_NONE); |
1792 |
if (nmatches == strlen((char *)buf) && ch2 == '=') { |
if (nmatches == (int)strlen((char *)buf) && ch2=='=') { |
1793 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1794 |
ARC_ENV_STRINGS + i + |
ARC_ENV_STRINGS + i + |
1795 |
strlen((char *)buf) + 1; |
strlen((char *)buf) + 1; |
2234 |
|
|
2235 |
|
|
2236 |
/* |
/* |
2237 |
|
* arc_environment_setup(): |
2238 |
|
* |
2239 |
|
* Initialize the emulated environment variables. |
2240 |
|
*/ |
2241 |
|
static void arc_environment_setup(struct machine *machine, int is64bit, |
2242 |
|
char *primary_ether_addr) |
2243 |
|
{ |
2244 |
|
size_t bootpath_len = 500; |
2245 |
|
char *init_bootpath; |
2246 |
|
uint64_t addr, addr2; |
2247 |
|
struct cpu *cpu = machine->cpus[0]; |
2248 |
|
|
2249 |
|
/* |
2250 |
|
* Boot string in ARC format: |
2251 |
|
* |
2252 |
|
* TODO: How about floppies? multi()disk()fdisk() |
2253 |
|
* Is tftp() good for netbooting? |
2254 |
|
*/ |
2255 |
|
init_bootpath = malloc(bootpath_len); |
2256 |
|
if (init_bootpath == NULL) { |
2257 |
|
fprintf(stderr, "out of mem, bootpath\n"); |
2258 |
|
exit(1); |
2259 |
|
} |
2260 |
|
init_bootpath[0] = '\0'; |
2261 |
|
|
2262 |
|
if (machine->bootdev_id < 0 || machine->force_netboot) { |
2263 |
|
snprintf(init_bootpath, bootpath_len, "tftp()"); |
2264 |
|
} else { |
2265 |
|
/* TODO: Make this nicer. */ |
2266 |
|
if (machine->machine_type == MACHINE_SGI) { |
2267 |
|
if (machine->machine_subtype == 30) |
2268 |
|
strlcat(init_bootpath, "xio(0)pci(15)", |
2269 |
|
MACHINE_NAME_MAXBUF); |
2270 |
|
if (machine->machine_subtype == 32) |
2271 |
|
strlcat(init_bootpath, "pci(0)", |
2272 |
|
MACHINE_NAME_MAXBUF); |
2273 |
|
} |
2274 |
|
|
2275 |
|
if (diskimage_is_a_cdrom(machine, machine->bootdev_id, |
2276 |
|
machine->bootdev_type)) |
2277 |
|
snprintf(init_bootpath + strlen(init_bootpath), |
2278 |
|
bootpath_len - strlen(init_bootpath), |
2279 |
|
"scsi(0)cdrom(%i)fdisk(0)", machine->bootdev_id); |
2280 |
|
else |
2281 |
|
snprintf(init_bootpath + strlen(init_bootpath), |
2282 |
|
bootpath_len - strlen(init_bootpath), |
2283 |
|
"scsi(0)disk(%i)rdisk(0)partition(1)", |
2284 |
|
machine->bootdev_id); |
2285 |
|
} |
2286 |
|
|
2287 |
|
if (machine->machine_type == MACHINE_ARC) |
2288 |
|
strlcat(init_bootpath, "\\", MACHINE_NAME_MAXBUF); |
2289 |
|
|
2290 |
|
machine->bootstr = malloc(ARC_BOOTSTR_BUFLEN); |
2291 |
|
if (machine->bootstr == NULL) { |
2292 |
|
fprintf(stderr, "out of memory\n"); |
2293 |
|
exit(1); |
2294 |
|
} |
2295 |
|
|
2296 |
|
strlcpy(machine->bootstr, init_bootpath, ARC_BOOTSTR_BUFLEN); |
2297 |
|
if (strlcat(machine->bootstr, machine->boot_kernel_filename, |
2298 |
|
ARC_BOOTSTR_BUFLEN) >= ARC_BOOTSTR_BUFLEN) { |
2299 |
|
fprintf(stderr, "boot string too long?\n"); |
2300 |
|
exit(1); |
2301 |
|
} |
2302 |
|
|
2303 |
|
/* Boot args., eg "-a" */ |
2304 |
|
machine->bootarg = machine->boot_string_argument; |
2305 |
|
|
2306 |
|
/* argc, argv, envp in a0, a1, a2: */ |
2307 |
|
cpu->cd.mips.gpr[MIPS_GPR_A0] = 0; /* note: argc is increased later */ |
2308 |
|
|
2309 |
|
/* TODO: not needed? */ |
2310 |
|
cpu->cd.mips.gpr[MIPS_GPR_SP] = (int64_t)(int32_t) |
2311 |
|
(machine->physical_ram_in_mb * 1048576 + 0x80000000 - 0x2080); |
2312 |
|
|
2313 |
|
/* Set up argc/argv: */ |
2314 |
|
addr = ARC_ENV_STRINGS; |
2315 |
|
addr2 = ARC_ARGV_START; |
2316 |
|
cpu->cd.mips.gpr[MIPS_GPR_A1] = addr2; |
2317 |
|
|
2318 |
|
/* bootstr: */ |
2319 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2320 |
|
add_environment_string(cpu, machine->bootstr, &addr); |
2321 |
|
cpu->cd.mips.gpr[MIPS_GPR_A0] ++; |
2322 |
|
|
2323 |
|
/* bootarg: */ |
2324 |
|
if (machine->bootarg[0] != '\0') { |
2325 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2326 |
|
add_environment_string(cpu, machine->bootarg, &addr); |
2327 |
|
cpu->cd.mips.gpr[MIPS_GPR_A0] ++; |
2328 |
|
} |
2329 |
|
|
2330 |
|
cpu->cd.mips.gpr[MIPS_GPR_A2] = addr2; |
2331 |
|
|
2332 |
|
/* |
2333 |
|
* Add environment variables. For each variable, add it |
2334 |
|
* as a string using add_environment_string(), and add a |
2335 |
|
* pointer to it to the ARC_ENV_POINTERS array. |
2336 |
|
*/ |
2337 |
|
if (machine->use_x11) { |
2338 |
|
if (machine->machine_type == MACHINE_ARC) { |
2339 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2340 |
|
add_environment_string(cpu, |
2341 |
|
"CONSOLEIN=multi()key()keyboard()console()", &addr); |
2342 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2343 |
|
add_environment_string(cpu, |
2344 |
|
"CONSOLEOUT=multi()video()monitor()console()", |
2345 |
|
&addr); |
2346 |
|
} else { |
2347 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2348 |
|
add_environment_string(cpu, "ConsoleIn=keyboard()", |
2349 |
|
&addr); |
2350 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2351 |
|
add_environment_string(cpu, "ConsoleOut=video()", |
2352 |
|
&addr); |
2353 |
|
|
2354 |
|
/* g for graphical mode. G for graphical mode |
2355 |
|
with SGI logo visible on Irix? */ |
2356 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2357 |
|
add_environment_string(cpu, "console=g", &addr); |
2358 |
|
} |
2359 |
|
} else { |
2360 |
|
if (machine->machine_type == MACHINE_ARC) { |
2361 |
|
/* TODO: serial console for ARC? */ |
2362 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2363 |
|
add_environment_string(cpu, |
2364 |
|
"CONSOLEIN=multi()serial(0)", &addr); |
2365 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2366 |
|
add_environment_string(cpu, |
2367 |
|
"CONSOLEOUT=multi()serial(0)", &addr); |
2368 |
|
} else { |
2369 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2370 |
|
add_environment_string(cpu, "ConsoleIn=serial(0)", |
2371 |
|
&addr); |
2372 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2373 |
|
add_environment_string(cpu, "ConsoleOut=serial(0)", |
2374 |
|
&addr); |
2375 |
|
|
2376 |
|
/* 'd' or 'd2' in Irix, 'ttyS0' in Linux? */ |
2377 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2378 |
|
add_environment_string(cpu, "console=d", &addr); |
2379 |
|
} |
2380 |
|
} |
2381 |
|
|
2382 |
|
if (machine->machine_type == MACHINE_SGI) { |
2383 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2384 |
|
add_environment_string(cpu, "AutoLoad=No", &addr); |
2385 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2386 |
|
add_environment_string(cpu, "diskless=0", &addr); |
2387 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2388 |
|
add_environment_string(cpu, "volume=80", &addr); |
2389 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2390 |
|
add_environment_string(cpu, "sgilogo=y", &addr); |
2391 |
|
|
2392 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2393 |
|
add_environment_string(cpu, "monitor=h", &addr); |
2394 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2395 |
|
add_environment_string(cpu, "TimeZone=GMT", &addr); |
2396 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2397 |
|
add_environment_string(cpu, "nogfxkbd=1", &addr); |
2398 |
|
|
2399 |
|
/* TODO: 'xio(0)pci(15)scsi(0)disk(1)rdisk(0)partition(0)' |
2400 |
|
on IP30 at least */ |
2401 |
|
|
2402 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2403 |
|
add_environment_string(cpu, |
2404 |
|
"SystemPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(8)", |
2405 |
|
&addr); |
2406 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2407 |
|
add_environment_string(cpu, |
2408 |
|
"OSLoadPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(0)", |
2409 |
|
&addr); |
2410 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2411 |
|
add_environment_string(cpu, "OSLoadFilename=/unix", &addr); |
2412 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2413 |
|
add_environment_string(cpu, "OSLoader=sash", &addr); |
2414 |
|
|
2415 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2416 |
|
add_environment_string(cpu, "rbaud=9600", &addr); |
2417 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2418 |
|
add_environment_string(cpu, "rebound=y", &addr); |
2419 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2420 |
|
add_environment_string(cpu, "crt_option=1", &addr); |
2421 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2422 |
|
add_environment_string(cpu, "netaddr=10.0.0.1", &addr); |
2423 |
|
|
2424 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2425 |
|
add_environment_string(cpu, "keybd=US", &addr); |
2426 |
|
|
2427 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2428 |
|
add_environment_string(cpu, "cpufreq=3", &addr); |
2429 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2430 |
|
add_environment_string(cpu, "dbaud=9600", &addr); |
2431 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2432 |
|
add_environment_string(cpu, primary_ether_addr, &addr); |
2433 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2434 |
|
add_environment_string(cpu, "verbose=istrue", &addr); |
2435 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2436 |
|
add_environment_string(cpu, "showconfig=istrue", &addr); |
2437 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2438 |
|
add_environment_string(cpu, "diagmode=v", &addr); |
2439 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2440 |
|
add_environment_string(cpu, "kernname=unix", &addr); |
2441 |
|
} else { |
2442 |
|
char *tmp; |
2443 |
|
size_t mlen = strlen(machine->bootarg) + |
2444 |
|
strlen("OSLOADOPTIONS=") + 2; |
2445 |
|
tmp = malloc(mlen); |
2446 |
|
snprintf(tmp, mlen, "OSLOADOPTIONS=%s", machine->bootarg); |
2447 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2448 |
|
add_environment_string(cpu, tmp, &addr); |
2449 |
|
|
2450 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2451 |
|
add_environment_string(cpu, "OSLOADPARTITION=scsi(0)cdrom(6)" |
2452 |
|
"fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr); |
2453 |
|
|
2454 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2455 |
|
add_environment_string(cpu, "SYSTEMPARTITION=scsi(0)cdrom(6)" |
2456 |
|
"fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr); |
2457 |
|
} |
2458 |
|
|
2459 |
|
/* End the environment strings with an empty zero-terminated |
2460 |
|
string, and the envp array with a NULL pointer. */ |
2461 |
|
add_environment_string(cpu, "", &addr); /* the end */ |
2462 |
|
store_pointer_and_advance(cpu, &addr2, 0, is64bit); |
2463 |
|
|
2464 |
|
/* Return address: (0x20 = ReturnFromMain()) */ |
2465 |
|
cpu->cd.mips.gpr[MIPS_GPR_RA] = ARC_FIRMWARE_ENTRIES + 0x20; |
2466 |
|
} |
2467 |
|
|
2468 |
|
|
2469 |
|
/* |
2470 |
* arcbios_init(): |
* arcbios_init(): |
2471 |
* |
* |
2472 |
* Should be called before any other arcbios function is used. An exception |
* Should be called before any other arcbios function is used. An exception |
2473 |
* is arcbios_console_init(), which may be called before this function. |
* is arcbios_console_init(), which may be called before this function. |
2474 |
|
* |
2475 |
|
* TODO: Refactor; this is too long. |
2476 |
*/ |
*/ |
2477 |
void arcbios_init(struct machine *machine, int is64bit, |
void arcbios_init(struct machine *machine, int is64bit, uint64_t sgi_ram_offset, |
2478 |
uint64_t sgi_ram_offset) |
char *primary_ether_addr, uint8_t *primary_ether_macaddr) |
2479 |
{ |
{ |
2480 |
int i, alloclen = 20; |
int i, alloclen = 20; |
2481 |
char *name; |
char *name; |
2944 |
store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb, |
store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb, |
2945 |
sizeof(arcbios_spb)); |
sizeof(arcbios_spb)); |
2946 |
} |
} |
2947 |
|
|
2948 |
|
|
2949 |
|
/* |
2950 |
|
* TODO: How to build the component tree intermixed with |
2951 |
|
* the rest of device initialization? |
2952 |
|
*/ |
2953 |
|
|
2954 |
|
arc_environment_setup(machine, is64bit, primary_ether_addr); |
2955 |
} |
} |
2956 |
|
|