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.1 2005/08/29 14:46:34 debug Exp $ |
* $Id: arcbios.c,v 1.9 2006/06/30 20:22:54 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 |
699 |
uint64_t eparent, echild, epeer, tmp; |
uint64_t eparent, echild, epeer, tmp; |
700 |
unsigned char buf[8]; |
unsigned char buf[8]; |
701 |
|
|
702 |
/* debug("[ addchild: peeraddr = 0x%016llx ]\n", |
/* debug("[ addchild: peeraddr = 0x%016"PRIx64" ]\n", |
703 |
(long long)peeraddr); */ |
(uint64_t) peeraddr); */ |
704 |
|
|
705 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
706 |
peeraddr + 0 * machine->md.arc.wordlen, &buf[0], |
peeraddr + 0 * machine->md.arc.wordlen, &buf[0], |
744 |
+ ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40) |
+ ((uint64_t)buf[4] << 32) + ((uint64_t)buf[5] << 40) |
745 |
+ ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56); |
+ ((uint64_t)buf[6] << 48) + ((uint64_t)buf[7] << 56); |
746 |
|
|
747 |
/* debug(" epeer=%llx echild=%llx eparent=%llx\n", |
/* debug(" epeer=%"PRIx64" echild=%"PRIx64" eparent=%"PRIx64 |
748 |
(long long)epeer, (long long)echild, |
"\n", (uint64_t) epeer, (uint64_t) echild, |
749 |
(long long)eparent); */ |
(uint64_t) eparent); */ |
750 |
|
|
751 |
if (eparent == parent && epeer == 0) { |
if (eparent == parent && epeer == 0) { |
752 |
epeer = a; |
epeer = a; |
753 |
store_64bit_word(cpu, peeraddr + 0 * |
store_64bit_word(cpu, peeraddr + 0 * |
754 |
machine->md.arc.wordlen, epeer); |
machine->md.arc.wordlen, epeer); |
755 |
/* debug("[ addchild: adding 0x%016llx as peer " |
/* debug("[ addchild: adding 0x%016"PRIx64" as peer " |
756 |
"to 0x%016llx ]\n", (long long)a, |
"to 0x%016"PRIx64" ]\n", (uint64_t) a, |
757 |
(long long)peeraddr); */ |
(uint64_t) peeraddr); */ |
758 |
} |
} |
759 |
if (peeraddr == parent && echild == 0) { |
if (peeraddr == parent && echild == 0) { |
760 |
echild = a; |
echild = a; |
761 |
store_64bit_word(cpu, peeraddr + 1 * |
store_64bit_word(cpu, peeraddr + 1 * |
762 |
machine->md.arc.wordlen, echild); |
machine->md.arc.wordlen, echild); |
763 |
/* debug("[ addchild: adding 0x%016llx as child " |
/* debug("[ addchild: adding 0x%016"PRIx64" as child " |
764 |
"to 0x%016llx ]\n", (long long)a, |
"to 0x%016"PRIx64" ]\n", (uint64_t) a, |
765 |
(long long)peeraddr); */ |
(uint64_t) peeraddr); */ |
766 |
} |
} |
767 |
|
|
768 |
/* Go to the next component: */ |
/* Go to the next component: */ |
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 " |
869 |
machine->md.arc.next_component_address + |
machine->md.arc.next_component_address + |
870 |
(cpu->machine->md.arc.arc_64bit? 0x18 : 0x0c); |
(cpu->machine->md.arc.arc_64bit? 0x18 : 0x0c); |
871 |
|
|
872 |
/* printf("& ADDING %i: configdata=0x%016llx " |
/* printf("& ADDING %i: configdata=0x%016"PRIx64" " |
873 |
"component=0x%016llx\n", |
"component=0x%016"PRIx64"\n", |
874 |
machine->md.arc.n_configuration_data, |
machine->md.arc.n_configuration_data, |
875 |
(long long)machine->md.arc.configuration_data_configdata[ |
(uint64_t) machine->md.arc.configuration_data_configdata[ |
876 |
machine->md.arc.n_configuration_data], |
machine->md.arc.n_configuration_data], |
877 |
(long long)machine->md.arc.configuration_data_component[ |
(uint64_t) machine->md.arc.configuration_data_component[ |
878 |
machine->md.arc.n_configuration_data]); */ |
machine->md.arc.n_configuration_data]); */ |
879 |
|
|
880 |
machine->md.arc.n_configuration_data ++; |
machine->md.arc.n_configuration_data ++; |
947 |
ugly_goto: |
ugly_goto: |
948 |
*start = 0; *size = 0; |
*start = 0; *size = 0; |
949 |
|
|
950 |
/* printf("reading MSDOS partition from offset 0x%llx\n", |
/* printf("reading MSDOS partition from offset 0x%"PRIx64"\n", |
951 |
(long long)offset); */ |
(uint64_t) offset); */ |
952 |
|
|
953 |
res = diskimage_access(machine, disk_id, disk_type, 0, offset, |
res = diskimage_access(machine, disk_id, disk_type, 0, offset, |
954 |
sector, sizeof(sector)); |
sector, sizeof(sector)); |
955 |
if (!res) { |
if (!res) { |
956 |
fatal("[ arcbios_get_msdos_partition_size(): couldn't " |
fatal("[ arcbios_get_msdos_partition_size(): couldn't " |
957 |
"read the disk image, id %i, offset 0x%llx ]\n", |
"read the disk image, id %i, offset 0x%"PRIx64" ]\n", |
958 |
disk_id, (long long)offset); |
disk_id, (uint64_t) offset); |
959 |
return; |
return; |
960 |
} |
} |
961 |
|
|
1239 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
1240 |
(int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0]; |
(int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0]; |
1241 |
} |
} |
1242 |
debug("[ ARCBIOS GetPeer(node 0x%016llx): 0x%016llx ]\n", |
debug("[ ARCBIOS GetPeer(node 0x%016"PRIx64"): 0x%016"PRIx64 |
1243 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
" ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0], |
1244 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_V0]); |
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]); |
1245 |
break; |
break; |
1246 |
case 0x28: /* GetChild(node) */ |
case 0x28: /* GetChild(node) */ |
1247 |
/* 0 for the root, non-0 for children: */ |
/* 0 for the root, non-0 for children: */ |
1290 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
1291 |
(int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0]; |
(int32_t)cpu->cd.mips.gpr[MIPS_GPR_V0]; |
1292 |
} |
} |
1293 |
debug("[ ARCBIOS GetChild(node 0x%016llx): 0x%016llx ]\n", |
debug("[ ARCBIOS GetChild(node 0x%016"PRIx64"): 0x%016" |
1294 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
PRIx64" ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0], |
1295 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_V0]); |
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]); |
1296 |
break; |
break; |
1297 |
case 0x2c: /* GetParent(node) */ |
case 0x2c: /* GetParent(node) */ |
1298 |
{ |
{ |
1339 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
cpu->cd.mips.gpr[MIPS_GPR_V0] = (int64_t) |
1340 |
(int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0]; |
(int32_t) cpu->cd.mips.gpr[MIPS_GPR_V0]; |
1341 |
} |
} |
1342 |
debug("[ ARCBIOS GetParent(node 0x%016llx): 0x%016llx ]\n", |
debug("[ ARCBIOS GetParent(node 0x%016"PRIx64"): 0x%016" |
1343 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
PRIx64" ]\n", (uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0], |
1344 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_V0]); |
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_V0]); |
1345 |
break; |
break; |
1346 |
case 0x30: /* GetConfigurationData(void *configdata, void *node) */ |
case 0x30: /* GetConfigurationData(void *configdata, void *node) */ |
1347 |
/* fatal("[ ARCBIOS GetConfigurationData(0x%016llx," |
/* fatal("[ ARCBIOS GetConfigurationData(0x%016"PRIx64"," |
1348 |
"0x%016llx) ]\n", (long long)cpu->cd.mips.gpr[MIPS_GPR_A0], |
"0x%016"PRIx64") ]\n", |
1349 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1]); */ |
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A0], |
1350 |
|
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1]); */ |
1351 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL; |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EINVAL; |
1352 |
for (i=0; i<machine->md.arc.n_configuration_data; i++) { |
for (i=0; i<machine->md.arc.n_configuration_data; i++) { |
1353 |
/* fatal("configuration_data_component[%i] = " |
/* fatal("configuration_data_component[%i] = " |
1354 |
"0x%016llx\n", i, (long long)machine-> |
"0x%016"PRIx64"\n", i, (uint64_t) machine-> |
1355 |
md.arc.configuration_data_component[i]); */ |
md.arc.configuration_data_component[i]); */ |
1356 |
if (cpu->cd.mips.gpr[MIPS_GPR_A1] == |
if (cpu->cd.mips.gpr[MIPS_GPR_A1] == |
1357 |
machine->md.arc.configuration_data_component[i]) { |
machine->md.arc.configuration_data_component[i]) { |
1384 |
int match_len = 0; |
int match_len = 0; |
1385 |
|
|
1386 |
memset(buf, 0, sizeof(buf)); |
memset(buf, 0, sizeof(buf)); |
1387 |
for (i=0; i<sizeof(buf); i++) { |
for (i=0; i<(ssize_t)sizeof(buf); i++) { |
1388 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1389 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
1390 |
&buf[i], 1, MEM_READ, CACHE_NONE); |
&buf[i], 1, MEM_READ, CACHE_NONE); |
1552 |
machine->tick_func[i](cpu, |
machine->tick_func[i](cpu, |
1553 |
machine->tick_extra[i]); |
machine->tick_extra[i]); |
1554 |
|
|
1555 |
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]; |
1556 |
|
i++) { |
1557 |
int x; |
int x; |
1558 |
unsigned char ch; |
unsigned char ch; |
1559 |
|
|
1594 |
nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN; |
nread? ARCBIOS_ESUCCESS: ARCBIOS_EAGAIN; |
1595 |
} else { |
} else { |
1596 |
int handle = cpu->cd.mips.gpr[MIPS_GPR_A0]; |
int handle = cpu->cd.mips.gpr[MIPS_GPR_A0]; |
1597 |
int disk_type; |
int disk_type = 0; |
1598 |
int disk_id = arcbios_handle_to_disk_id_and_type( |
int disk_id = arcbios_handle_to_disk_id_and_type( |
1599 |
machine, handle, &disk_type); |
machine, handle, &disk_type); |
1600 |
uint64_t partition_offset = 0; |
uint64_t partition_offset = 0; |
1666 |
* TODO: this is just a test |
* TODO: this is just a test |
1667 |
*/ |
*/ |
1668 |
int handle = cpu->cd.mips.gpr[MIPS_GPR_A0]; |
int handle = cpu->cd.mips.gpr[MIPS_GPR_A0]; |
1669 |
int disk_type; |
int disk_type = 0; |
1670 |
int disk_id = arcbios_handle_to_disk_id_and_type( |
int disk_id = arcbios_handle_to_disk_id_and_type( |
1671 |
machine, handle, &disk_type); |
machine, handle, &disk_type); |
1672 |
uint64_t partition_offset = 0; |
uint64_t partition_offset = 0; |
1677 |
arcbios_handle_to_start_and_size(machine, |
arcbios_handle_to_start_and_size(machine, |
1678 |
handle, &partition_offset, &size); |
handle, &partition_offset, &size); |
1679 |
|
|
1680 |
debug("[ ARCBIOS Write(%i,0x%08llx,%i,0x%08llx) ]\n", |
debug("[ ARCBIOS Write(%i,0x%08"PRIx64",%i,0x%08" |
1681 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
PRIx64") ]\n", (int) cpu->cd.mips.gpr[MIPS_GPR_A0], |
1682 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1], |
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1], |
1683 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2], |
(int) cpu->cd.mips.gpr[MIPS_GPR_A2], |
1684 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A3]); |
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A3]); |
1685 |
|
|
1686 |
tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]); |
tmp_buf = malloc(cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1687 |
if (tmp_buf == NULL) { |
if (tmp_buf == NULL) { |
1691 |
break; |
break; |
1692 |
} |
} |
1693 |
|
|
1694 |
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++) |
1695 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1696 |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
1697 |
&tmp_buf[i], sizeof(char), MEM_READ, |
&tmp_buf[i], sizeof(char), MEM_READ, |
1713 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO; |
cpu->cd.mips.gpr[MIPS_GPR_V0] = ARCBIOS_EIO; |
1714 |
free(tmp_buf); |
free(tmp_buf); |
1715 |
} else { |
} else { |
1716 |
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]; |
1717 |
|
i++) { |
1718 |
unsigned char ch = '\0'; |
unsigned char ch = '\0'; |
1719 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1720 |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A1] + i, |
1729 |
break; |
break; |
1730 |
case 0x70: /* Seek(uint32_t handle, int64_t *ofs, |
case 0x70: /* Seek(uint32_t handle, int64_t *ofs, |
1731 |
uint32_t whence): uint32_t */ |
uint32_t whence): uint32_t */ |
1732 |
debug("[ ARCBIOS Seek(%i,0x%08llx,%i): ", |
debug("[ ARCBIOS Seek(%i,0x%08"PRIx64",%i): ", |
1733 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
(int) cpu->cd.mips.gpr[MIPS_GPR_A0], |
1734 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1], |
(uint64_t)cpu->cd.mips.gpr[MIPS_GPR_A1], |
1735 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2]); |
(int) cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1736 |
|
|
1737 |
if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) { |
if (cpu->cd.mips.gpr[MIPS_GPR_A2] != 0) { |
1738 |
fatal("[ ARCBIOS Seek(%i,0x%08llx,%i): " |
fatal("[ ARCBIOS Seek(%i,0x%08"PRIx64",%i): " |
1739 |
"UNIMPLEMENTED whence=%i ]\n", |
"UNIMPLEMENTED whence=%i ]\n", |
1740 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A0], |
(int) cpu->cd.mips.gpr[MIPS_GPR_A0], |
1741 |
(long long)cpu->cd.mips.gpr[MIPS_GPR_A1], |
(uint64_t) cpu->cd.mips.gpr[MIPS_GPR_A1], |
1742 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2], |
(int) cpu->cd.mips.gpr[MIPS_GPR_A2], |
1743 |
(int)cpu->cd.mips.gpr[MIPS_GPR_A2]); |
(int) cpu->cd.mips.gpr[MIPS_GPR_A2]); |
1744 |
} |
} |
1745 |
|
|
1746 |
{ |
{ |
1762 |
+ ((uint64_t)buf[7] << 56); |
+ ((uint64_t)buf[7] << 56); |
1763 |
machine->md.arc.current_seek_offset[ |
machine->md.arc.current_seek_offset[ |
1764 |
cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs; |
cpu->cd.mips.gpr[MIPS_GPR_A0]] = ofs; |
1765 |
debug("%016llx ]\n", (long long)ofs); |
debug("%016"PRIx64" ]\n", (uint64_t) ofs); |
1766 |
} |
} |
1767 |
|
|
1768 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */ |
cpu->cd.mips.gpr[MIPS_GPR_V0] = 0; /* Success. */ |
1770 |
break; |
break; |
1771 |
case 0x78: /* GetEnvironmentVariable(char *) */ |
case 0x78: /* GetEnvironmentVariable(char *) */ |
1772 |
/* Find the environment variable given by a0: */ |
/* Find the environment variable given by a0: */ |
1773 |
for (i=0; i<sizeof(buf); i++) |
for (i=0; i<(ssize_t)sizeof(buf); i++) |
1774 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1775 |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
cpu->cd.mips.gpr[MIPS_GPR_A0] + i, |
1776 |
&buf[i], sizeof(char), MEM_READ, CACHE_NONE); |
&buf[i], sizeof(char), MEM_READ, CACHE_NONE); |
1779 |
for (i=0; i<0x1000; i++) { |
for (i=0; i<0x1000; i++) { |
1780 |
/* Matching string at offset i? */ |
/* Matching string at offset i? */ |
1781 |
int nmatches = 0; |
int nmatches = 0; |
1782 |
for (j=0; j<strlen((char *)buf); j++) { |
for (j=0; j<(ssize_t)strlen((char *)buf); j++) { |
1783 |
cpu->memory_rw(cpu, cpu->mem, |
cpu->memory_rw(cpu, cpu->mem, |
1784 |
(uint64_t)(ARC_ENV_STRINGS + i + j), |
(uint64_t)(ARC_ENV_STRINGS + i + j), |
1785 |
&ch2, sizeof(char), MEM_READ, CACHE_NONE); |
&ch2, sizeof(char), MEM_READ, CACHE_NONE); |
1790 |
(uint64_t)(ARC_ENV_STRINGS + i + |
(uint64_t)(ARC_ENV_STRINGS + i + |
1791 |
strlen((char *)buf)), &ch2, sizeof(char), |
strlen((char *)buf)), &ch2, sizeof(char), |
1792 |
MEM_READ, CACHE_NONE); |
MEM_READ, CACHE_NONE); |
1793 |
if (nmatches == strlen((char *)buf) && ch2 == '=') { |
if (nmatches == (int)strlen((char *)buf) && ch2=='=') { |
1794 |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
cpu->cd.mips.gpr[MIPS_GPR_V0] = |
1795 |
ARC_ENV_STRINGS + i + |
ARC_ENV_STRINGS + i + |
1796 |
strlen((char *)buf) + 1; |
strlen((char *)buf) + 1; |
2235 |
|
|
2236 |
|
|
2237 |
/* |
/* |
2238 |
|
* arc_environment_setup(): |
2239 |
|
* |
2240 |
|
* Initialize the emulated environment variables. |
2241 |
|
*/ |
2242 |
|
static void arc_environment_setup(struct machine *machine, int is64bit, |
2243 |
|
char *primary_ether_addr) |
2244 |
|
{ |
2245 |
|
size_t bootpath_len = 500; |
2246 |
|
char *init_bootpath; |
2247 |
|
uint64_t addr, addr2; |
2248 |
|
struct cpu *cpu = machine->cpus[0]; |
2249 |
|
|
2250 |
|
/* |
2251 |
|
* Boot string in ARC format: |
2252 |
|
* |
2253 |
|
* TODO: How about floppies? multi()disk()fdisk() |
2254 |
|
* Is tftp() good for netbooting? |
2255 |
|
*/ |
2256 |
|
init_bootpath = malloc(bootpath_len); |
2257 |
|
if (init_bootpath == NULL) { |
2258 |
|
fprintf(stderr, "out of mem, bootpath\n"); |
2259 |
|
exit(1); |
2260 |
|
} |
2261 |
|
init_bootpath[0] = '\0'; |
2262 |
|
|
2263 |
|
if (machine->bootdev_id < 0 || machine->force_netboot) { |
2264 |
|
snprintf(init_bootpath, bootpath_len, "tftp()"); |
2265 |
|
} else { |
2266 |
|
/* TODO: Make this nicer. */ |
2267 |
|
if (machine->machine_type == MACHINE_SGI) { |
2268 |
|
if (machine->machine_subtype == 30) |
2269 |
|
strlcat(init_bootpath, "xio(0)pci(15)", |
2270 |
|
bootpath_len); |
2271 |
|
if (machine->machine_subtype == 32) |
2272 |
|
strlcat(init_bootpath, "pci(0)", |
2273 |
|
bootpath_len); |
2274 |
|
} |
2275 |
|
|
2276 |
|
if (diskimage_is_a_cdrom(machine, machine->bootdev_id, |
2277 |
|
machine->bootdev_type)) |
2278 |
|
snprintf(init_bootpath + strlen(init_bootpath), |
2279 |
|
bootpath_len - strlen(init_bootpath), |
2280 |
|
"scsi(0)cdrom(%i)fdisk(0)", machine->bootdev_id); |
2281 |
|
else |
2282 |
|
snprintf(init_bootpath + strlen(init_bootpath), |
2283 |
|
bootpath_len - strlen(init_bootpath), |
2284 |
|
"scsi(0)disk(%i)rdisk(0)partition(1)", |
2285 |
|
machine->bootdev_id); |
2286 |
|
} |
2287 |
|
|
2288 |
|
if (machine->machine_type == MACHINE_ARC) |
2289 |
|
strlcat(init_bootpath, "\\", bootpath_len); |
2290 |
|
|
2291 |
|
machine->bootstr = malloc(ARC_BOOTSTR_BUFLEN); |
2292 |
|
if (machine->bootstr == NULL) { |
2293 |
|
fprintf(stderr, "out of memory\n"); |
2294 |
|
exit(1); |
2295 |
|
} |
2296 |
|
|
2297 |
|
strlcpy(machine->bootstr, init_bootpath, ARC_BOOTSTR_BUFLEN); |
2298 |
|
if (strlcat(machine->bootstr, machine->boot_kernel_filename, |
2299 |
|
ARC_BOOTSTR_BUFLEN) >= ARC_BOOTSTR_BUFLEN) { |
2300 |
|
fprintf(stderr, "boot string too long?\n"); |
2301 |
|
exit(1); |
2302 |
|
} |
2303 |
|
|
2304 |
|
/* Boot args., eg "-a" */ |
2305 |
|
machine->bootarg = machine->boot_string_argument; |
2306 |
|
|
2307 |
|
/* argc, argv, envp in a0, a1, a2: */ |
2308 |
|
cpu->cd.mips.gpr[MIPS_GPR_A0] = 0; /* note: argc is increased later */ |
2309 |
|
|
2310 |
|
/* TODO: not needed? */ |
2311 |
|
cpu->cd.mips.gpr[MIPS_GPR_SP] = (int64_t)(int32_t) |
2312 |
|
(machine->physical_ram_in_mb * 1048576 + 0x80000000 - 0x2080); |
2313 |
|
|
2314 |
|
/* Set up argc/argv: */ |
2315 |
|
addr = ARC_ENV_STRINGS; |
2316 |
|
addr2 = ARC_ARGV_START; |
2317 |
|
cpu->cd.mips.gpr[MIPS_GPR_A1] = addr2; |
2318 |
|
|
2319 |
|
/* bootstr: */ |
2320 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2321 |
|
add_environment_string(cpu, machine->bootstr, &addr); |
2322 |
|
cpu->cd.mips.gpr[MIPS_GPR_A0] ++; |
2323 |
|
|
2324 |
|
/* bootarg: */ |
2325 |
|
if (machine->bootarg[0] != '\0') { |
2326 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2327 |
|
add_environment_string(cpu, machine->bootarg, &addr); |
2328 |
|
cpu->cd.mips.gpr[MIPS_GPR_A0] ++; |
2329 |
|
} |
2330 |
|
|
2331 |
|
cpu->cd.mips.gpr[MIPS_GPR_A2] = addr2; |
2332 |
|
|
2333 |
|
/* |
2334 |
|
* Add environment variables. For each variable, add it |
2335 |
|
* as a string using add_environment_string(), and add a |
2336 |
|
* pointer to it to the ARC_ENV_POINTERS array. |
2337 |
|
*/ |
2338 |
|
if (machine->use_x11) { |
2339 |
|
if (machine->machine_type == MACHINE_ARC) { |
2340 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2341 |
|
add_environment_string(cpu, |
2342 |
|
"CONSOLEIN=multi()key()keyboard()console()", &addr); |
2343 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2344 |
|
add_environment_string(cpu, |
2345 |
|
"CONSOLEOUT=multi()video()monitor()console()", |
2346 |
|
&addr); |
2347 |
|
} else { |
2348 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2349 |
|
add_environment_string(cpu, "ConsoleIn=keyboard()", |
2350 |
|
&addr); |
2351 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2352 |
|
add_environment_string(cpu, "ConsoleOut=video()", |
2353 |
|
&addr); |
2354 |
|
|
2355 |
|
/* g for graphical mode. G for graphical mode |
2356 |
|
with SGI logo visible on Irix? */ |
2357 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2358 |
|
add_environment_string(cpu, "console=g", &addr); |
2359 |
|
} |
2360 |
|
} else { |
2361 |
|
if (machine->machine_type == MACHINE_ARC) { |
2362 |
|
/* TODO: serial console for ARC? */ |
2363 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2364 |
|
add_environment_string(cpu, |
2365 |
|
"CONSOLEIN=multi()serial(0)", &addr); |
2366 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2367 |
|
add_environment_string(cpu, |
2368 |
|
"CONSOLEOUT=multi()serial(0)", &addr); |
2369 |
|
} else { |
2370 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2371 |
|
add_environment_string(cpu, "ConsoleIn=serial(0)", |
2372 |
|
&addr); |
2373 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2374 |
|
add_environment_string(cpu, "ConsoleOut=serial(0)", |
2375 |
|
&addr); |
2376 |
|
|
2377 |
|
/* 'd' or 'd2' in Irix, 'ttyS0' in Linux? */ |
2378 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2379 |
|
add_environment_string(cpu, "console=d", &addr); |
2380 |
|
} |
2381 |
|
} |
2382 |
|
|
2383 |
|
if (machine->machine_type == MACHINE_SGI) { |
2384 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2385 |
|
add_environment_string(cpu, "AutoLoad=No", &addr); |
2386 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2387 |
|
add_environment_string(cpu, "diskless=0", &addr); |
2388 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2389 |
|
add_environment_string(cpu, "volume=80", &addr); |
2390 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2391 |
|
add_environment_string(cpu, "sgilogo=y", &addr); |
2392 |
|
|
2393 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2394 |
|
add_environment_string(cpu, "monitor=h", &addr); |
2395 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2396 |
|
add_environment_string(cpu, "TimeZone=GMT", &addr); |
2397 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2398 |
|
add_environment_string(cpu, "nogfxkbd=1", &addr); |
2399 |
|
|
2400 |
|
/* TODO: 'xio(0)pci(15)scsi(0)disk(1)rdisk(0)partition(0)' |
2401 |
|
on IP30 at least */ |
2402 |
|
|
2403 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2404 |
|
add_environment_string(cpu, |
2405 |
|
"SystemPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(8)", |
2406 |
|
&addr); |
2407 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2408 |
|
add_environment_string(cpu, |
2409 |
|
"OSLoadPartition=pci(0)scsi(0)disk(2)rdisk(0)partition(0)", |
2410 |
|
&addr); |
2411 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2412 |
|
add_environment_string(cpu, "OSLoadFilename=/unix", &addr); |
2413 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2414 |
|
add_environment_string(cpu, "OSLoader=sash", &addr); |
2415 |
|
|
2416 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2417 |
|
add_environment_string(cpu, "rbaud=9600", &addr); |
2418 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2419 |
|
add_environment_string(cpu, "rebound=y", &addr); |
2420 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2421 |
|
add_environment_string(cpu, "crt_option=1", &addr); |
2422 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2423 |
|
add_environment_string(cpu, "netaddr=10.0.0.1", &addr); |
2424 |
|
|
2425 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2426 |
|
add_environment_string(cpu, "keybd=US", &addr); |
2427 |
|
|
2428 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2429 |
|
add_environment_string(cpu, "cpufreq=3", &addr); |
2430 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2431 |
|
add_environment_string(cpu, "dbaud=9600", &addr); |
2432 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2433 |
|
add_environment_string(cpu, primary_ether_addr, &addr); |
2434 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2435 |
|
add_environment_string(cpu, "verbose=istrue", &addr); |
2436 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2437 |
|
add_environment_string(cpu, "showconfig=istrue", &addr); |
2438 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2439 |
|
add_environment_string(cpu, "diagmode=v", &addr); |
2440 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2441 |
|
add_environment_string(cpu, "kernname=unix", &addr); |
2442 |
|
} else { |
2443 |
|
char *tmp; |
2444 |
|
size_t mlen = strlen(machine->bootarg) + |
2445 |
|
strlen("OSLOADOPTIONS=") + 2; |
2446 |
|
tmp = malloc(mlen); |
2447 |
|
snprintf(tmp, mlen, "OSLOADOPTIONS=%s", machine->bootarg); |
2448 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2449 |
|
add_environment_string(cpu, tmp, &addr); |
2450 |
|
|
2451 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2452 |
|
add_environment_string(cpu, "OSLOADPARTITION=scsi(0)cdrom(6)" |
2453 |
|
"fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr); |
2454 |
|
|
2455 |
|
store_pointer_and_advance(cpu, &addr2, addr, is64bit); |
2456 |
|
add_environment_string(cpu, "SYSTEMPARTITION=scsi(0)cdrom(6)" |
2457 |
|
"fdisk(0);scsi(0)disk(0)rdisk(0)partition(1)", &addr); |
2458 |
|
} |
2459 |
|
|
2460 |
|
/* End the environment strings with an empty zero-terminated |
2461 |
|
string, and the envp array with a NULL pointer. */ |
2462 |
|
add_environment_string(cpu, "", &addr); /* the end */ |
2463 |
|
store_pointer_and_advance(cpu, &addr2, 0, is64bit); |
2464 |
|
|
2465 |
|
/* Return address: (0x20 = ReturnFromMain()) */ |
2466 |
|
cpu->cd.mips.gpr[MIPS_GPR_RA] = ARC_FIRMWARE_ENTRIES + 0x20; |
2467 |
|
} |
2468 |
|
|
2469 |
|
|
2470 |
|
/* |
2471 |
* arcbios_init(): |
* arcbios_init(): |
2472 |
* |
* |
2473 |
* Should be called before any other arcbios function is used. An exception |
* Should be called before any other arcbios function is used. An exception |
2474 |
* is arcbios_console_init(), which may be called before this function. |
* is arcbios_console_init(), which may be called before this function. |
2475 |
|
* |
2476 |
|
* TODO: Refactor; this is too long. |
2477 |
*/ |
*/ |
2478 |
void arcbios_init(struct machine *machine, int is64bit, |
void arcbios_init(struct machine *machine, int is64bit, uint64_t sgi_ram_offset, |
2479 |
uint64_t sgi_ram_offset) |
char *primary_ether_addr, uint8_t *primary_ether_macaddr) |
2480 |
{ |
{ |
2481 |
int i, alloclen = 20; |
int i, alloclen = 20; |
2482 |
char *name; |
char *name; |
2723 |
|
|
2724 |
system = arcbios_addchild_manual(cpu, COMPONENT_CLASS_SystemClass, |
system = arcbios_addchild_manual(cpu, COMPONENT_CLASS_SystemClass, |
2725 |
COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0); |
COMPONENT_TYPE_ARC, 0,1,2,0, 0xffffffff, name, 0/*ROOT*/, NULL, 0); |
2726 |
debug("ARC system @ 0x%llx (\"%s\")\n", (long long)system, name); |
debug("ARC system @ 0x%"PRIx64" (\"%s\")\n", (uint64_t) system, name); |
2727 |
|
|
2728 |
|
|
2729 |
/* |
/* |
2839 |
0xffffffff, NULL, cpuaddr, NULL, 0); |
0xffffffff, NULL, cpuaddr, NULL, 0); |
2840 |
} |
} |
2841 |
|
|
2842 |
debug("ARC cpu%i @ 0x%llx", i, (long long)cpuaddr); |
debug("ARC cpu%i @ 0x%"PRIx64, i, (uint64_t) cpuaddr); |
2843 |
|
|
2844 |
if (fpu != 0) |
if (fpu != 0) |
2845 |
debug(" (fpu @ 0x%llx)\n", (long long)fpu); |
debug(" (fpu @ 0x%"PRIx64")\n", (uint64_t) fpu); |
2846 |
else |
else |
2847 |
debug("\n"); |
debug("\n"); |
2848 |
|
|
2849 |
debug(" picache @ 0x%llx, pdcache @ 0x%llx\n", |
debug(" picache @ 0x%"PRIx64", pdcache @ 0x%"PRIx64"\n", |
2850 |
(long long)picache, (long long)pdcache); |
(uint64_t) picache, (uint64_t) pdcache); |
2851 |
|
|
2852 |
if (machine->cache_secondary >= 12) |
if (machine->cache_secondary >= 12) |
2853 |
debug(" sdcache @ 0x%llx\n", |
debug(" sdcache @ 0x%"PRIx64"\n", |
2854 |
(long long)sdcache); |
(uint64_t) sdcache); |
2855 |
|
|
2856 |
if (machine->machine_type == MACHINE_SGI) { |
if (machine->machine_type == MACHINE_SGI) { |
2857 |
/* TODO: Memory amount (and base address?)! */ |
/* TODO: Memory amount (and base address?)! */ |
2859 |
COMPONENT_CLASS_MemoryClass, |
COMPONENT_CLASS_MemoryClass, |
2860 |
COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0, |
COMPONENT_TYPE_MemoryUnit, 0, 1, 2, 0, |
2861 |
0xffffffff, "memory", cpuaddr, NULL, 0); |
0xffffffff, "memory", cpuaddr, NULL, 0); |
2862 |
debug("ARC memory @ 0x%llx\n", (long long)memory); |
debug("ARC memory @ 0x%"PRIx64"\n", (uint64_t) memory); |
2863 |
} |
} |
2864 |
} |
} |
2865 |
|
|
2897 |
ARC_FIRMWARE_ENTRIES + i*8); |
ARC_FIRMWARE_ENTRIES + i*8); |
2898 |
store_64bit_word(cpu, ARC_PRIVATE_VECTORS + i*8, |
store_64bit_word(cpu, ARC_PRIVATE_VECTORS + i*8, |
2899 |
ARC_PRIVATE_ENTRIES + i*8); |
ARC_PRIVATE_ENTRIES + i*8); |
2900 |
|
|
2901 |
|
/* "Magic trap" instruction: */ |
2902 |
|
store_32bit_word(cpu, ARC_FIRMWARE_ENTRIES + i*8, |
2903 |
|
0x00c0de0c); |
2904 |
|
store_32bit_word(cpu, ARC_PRIVATE_ENTRIES + i*8, |
2905 |
|
0x00c0de0c); |
2906 |
} else { |
} else { |
2907 |
store_32bit_word(cpu, ARC_FIRMWARE_VECTORS + i*4, |
store_32bit_word(cpu, ARC_FIRMWARE_VECTORS + i*4, |
2908 |
ARC_FIRMWARE_ENTRIES + i*4); |
ARC_FIRMWARE_ENTRIES + i*4); |
2909 |
store_32bit_word(cpu, ARC_PRIVATE_VECTORS + i*4, |
store_32bit_word(cpu, ARC_PRIVATE_VECTORS + i*4, |
2910 |
ARC_PRIVATE_ENTRIES + i*4); |
ARC_PRIVATE_ENTRIES + i*4); |
2911 |
|
|
2912 |
|
/* "Magic trap" instruction: */ |
2913 |
|
store_32bit_word(cpu, ARC_FIRMWARE_ENTRIES + i*4, |
2914 |
|
0x00c0de0c); |
2915 |
|
store_32bit_word(cpu, ARC_PRIVATE_ENTRIES + i*4, |
2916 |
|
0x00c0de0c); |
2917 |
} |
} |
2918 |
} |
} |
2919 |
|
|
2957 |
store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb, |
store_buf(cpu, SGI_SPB_ADDR, (char *)&arcbios_spb, |
2958 |
sizeof(arcbios_spb)); |
sizeof(arcbios_spb)); |
2959 |
} |
} |
2960 |
|
|
2961 |
|
|
2962 |
|
/* |
2963 |
|
* TODO: How to build the component tree intermixed with |
2964 |
|
* the rest of device initialization? |
2965 |
|
*/ |
2966 |
|
|
2967 |
|
arc_environment_setup(machine, is64bit, primary_ether_addr); |
2968 |
} |
} |
2969 |
|
|