diff options
| -rw-r--r-- | arch/ppc64/kernel/prom_init.c | 102 |
1 files changed, 61 insertions, 41 deletions
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 3de950de3671..1ac531ba7056 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
| @@ -211,13 +211,23 @@ struct { | |||
| 211 | */ | 211 | */ |
| 212 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) | 212 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) |
| 213 | 213 | ||
| 214 | /* | ||
| 215 | * Error results ... some OF calls will return "-1" on error, some | ||
| 216 | * will return 0, some will return either. To simplify, here are | ||
| 217 | * macros to use with any ihandle or phandle return value to check if | ||
| 218 | * it is valid | ||
| 219 | */ | ||
| 220 | |||
| 221 | #define PROM_ERROR (-1u) | ||
| 222 | #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) | ||
| 223 | #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) | ||
| 224 | |||
| 225 | |||
| 214 | /* This is the one and *ONLY* place where we actually call open | 226 | /* This is the one and *ONLY* place where we actually call open |
| 215 | * firmware from, since we need to make sure we're running in 32b | 227 | * firmware from, since we need to make sure we're running in 32b |
| 216 | * mode when we do. We switch back to 64b mode upon return. | 228 | * mode when we do. We switch back to 64b mode upon return. |
| 217 | */ | 229 | */ |
| 218 | 230 | ||
| 219 | #define PROM_ERROR (-1) | ||
| 220 | |||
| 221 | static int __init call_prom(const char *service, int nargs, int nret, ...) | 231 | static int __init call_prom(const char *service, int nargs, int nret, ...) |
| 222 | { | 232 | { |
| 223 | int i; | 233 | int i; |
| @@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void) | |||
| 587 | { | 597 | { |
| 588 | unsigned long offset = reloc_offset(); | 598 | unsigned long offset = reloc_offset(); |
| 589 | ihandle elfloader; | 599 | ihandle elfloader; |
| 590 | int ret; | ||
| 591 | 600 | ||
| 592 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); | 601 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); |
| 593 | if (elfloader == 0) { | 602 | if (elfloader == 0) { |
| 594 | prom_printf("couldn't open /packages/elf-loader\n"); | 603 | prom_printf("couldn't open /packages/elf-loader\n"); |
| 595 | return; | 604 | return; |
| 596 | } | 605 | } |
| 597 | ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"), | 606 | call_prom("call-method", 3, 1, ADDR("process-elf-header"), |
| 598 | elfloader, ADDR(&fake_elf)); | 607 | elfloader, ADDR(&fake_elf)); |
| 599 | call_prom("close", 1, 0, elfloader); | 608 | call_prom("close", 1, 0, elfloader); |
| 600 | } | 609 | } |
| @@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) | |||
| 646 | base = _ALIGN_UP(base + 0x100000, align)) { | 655 | base = _ALIGN_UP(base + 0x100000, align)) { |
| 647 | prom_debug(" trying: 0x%x\n\r", base); | 656 | prom_debug(" trying: 0x%x\n\r", base); |
| 648 | addr = (unsigned long)prom_claim(base, size, 0); | 657 | addr = (unsigned long)prom_claim(base, size, 0); |
| 649 | if ((int)addr != PROM_ERROR) | 658 | if (addr != PROM_ERROR) |
| 650 | break; | 659 | break; |
| 651 | addr = 0; | 660 | addr = 0; |
| 652 | if (align == 0) | 661 | if (align == 0) |
| @@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, | |||
| 708 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { | 717 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { |
| 709 | prom_debug(" trying: 0x%x\n\r", base); | 718 | prom_debug(" trying: 0x%x\n\r", base); |
| 710 | addr = (unsigned long)prom_claim(base, size, 0); | 719 | addr = (unsigned long)prom_claim(base, size, 0); |
| 711 | if ((int)addr != PROM_ERROR) | 720 | if (addr != PROM_ERROR) |
| 712 | break; | 721 | break; |
| 713 | addr = 0; | 722 | addr = 0; |
| 714 | } | 723 | } |
| @@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void) | |||
| 902 | { | 911 | { |
| 903 | unsigned long offset = reloc_offset(); | 912 | unsigned long offset = reloc_offset(); |
| 904 | struct prom_t *_prom = PTRRELOC(&prom); | 913 | struct prom_t *_prom = PTRRELOC(&prom); |
| 905 | phandle prom_rtas, rtas_node; | 914 | phandle rtas_node; |
| 915 | ihandle rtas_inst; | ||
| 906 | u32 base, entry = 0; | 916 | u32 base, entry = 0; |
| 907 | u32 size = 0; | 917 | u32 size = 0; |
| 908 | 918 | ||
| 909 | prom_debug("prom_instantiate_rtas: start...\n"); | 919 | prom_debug("prom_instantiate_rtas: start...\n"); |
| 910 | 920 | ||
| 911 | prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | 921 | rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
| 912 | prom_debug("prom_rtas: %x\n", prom_rtas); | 922 | prom_debug("rtas_node: %x\n", rtas_node); |
| 913 | if (prom_rtas == (phandle) -1) | 923 | if (!PHANDLE_VALID(rtas_node)) |
| 914 | return; | 924 | return; |
| 915 | 925 | ||
| 916 | prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size)); | 926 | prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); |
| 917 | if (size == 0) | 927 | if (size == 0) |
| 918 | return; | 928 | return; |
| 919 | 929 | ||
| @@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void) | |||
| 922 | prom_printf("RTAS allocation failed !\n"); | 932 | prom_printf("RTAS allocation failed !\n"); |
| 923 | return; | 933 | return; |
| 924 | } | 934 | } |
| 925 | prom_printf("instantiating rtas at 0x%x", base); | ||
| 926 | 935 | ||
| 927 | rtas_node = call_prom("open", 1, 1, ADDR("/rtas")); | 936 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); |
| 928 | prom_printf("..."); | 937 | if (!IHANDLE_VALID(rtas_inst)) { |
| 938 | prom_printf("opening rtas package failed"); | ||
| 939 | return; | ||
| 940 | } | ||
| 941 | |||
| 942 | prom_printf("instantiating rtas at 0x%x ...", base); | ||
| 929 | 943 | ||
| 930 | if (call_prom("call-method", 3, 2, | 944 | if (call_prom("call-method", 3, 2, |
| 931 | ADDR("instantiate-rtas"), | 945 | ADDR("instantiate-rtas"), |
| 932 | rtas_node, base) != PROM_ERROR) { | 946 | rtas_inst, base) != PROM_ERROR) { |
| 933 | entry = (long)_prom->args.rets[1]; | 947 | entry = (long)_prom->args.rets[1]; |
| 934 | } | 948 | } |
| 935 | if (entry == 0) { | 949 | if (entry == 0) { |
| @@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void) | |||
| 940 | 954 | ||
| 941 | reserve_mem(base, size); | 955 | reserve_mem(base, size); |
| 942 | 956 | ||
| 943 | prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base)); | 957 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); |
| 944 | prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry)); | 958 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); |
| 945 | 959 | ||
| 946 | prom_debug("rtas base = 0x%x\n", base); | 960 | prom_debug("rtas base = 0x%x\n", base); |
| 947 | prom_debug("rtas entry = 0x%x\n", entry); | 961 | prom_debug("rtas entry = 0x%x\n", entry); |
| @@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void) | |||
| 1062 | 1076 | ||
| 1063 | prom_printf("opening PHB %s", path); | 1077 | prom_printf("opening PHB %s", path); |
| 1064 | phb_node = call_prom("open", 1, 1, path); | 1078 | phb_node = call_prom("open", 1, 1, path); |
| 1065 | if ( (long)phb_node <= 0) | 1079 | if (phb_node == 0) |
| 1066 | prom_printf("... failed\n"); | 1080 | prom_printf("... failed\n"); |
| 1067 | else | 1081 | else |
| 1068 | prom_printf("... done\n"); | 1082 | prom_printf("... done\n"); |
| @@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp) | |||
| 1279 | 1293 | ||
| 1280 | /* get a handle for the stdout device */ | 1294 | /* get a handle for the stdout device */ |
| 1281 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); | 1295 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); |
| 1282 | if ((long)_prom->chosen <= 0) | 1296 | if (!PHANDLE_VALID(_prom->chosen)) |
| 1283 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ | 1297 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ |
| 1284 | 1298 | ||
| 1285 | /* get device tree root */ | 1299 | /* get device tree root */ |
| 1286 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); | 1300 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); |
| 1287 | if ((long)_prom->root <= 0) | 1301 | if (!PHANDLE_VALID(_prom->root)) |
| 1288 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ | 1302 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ |
| 1289 | } | 1303 | } |
| 1290 | 1304 | ||
| @@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void) | |||
| 1356 | } | 1370 | } |
| 1357 | /* Default to pSeries. We need to know if we are running LPAR */ | 1371 | /* Default to pSeries. We need to know if we are running LPAR */ |
| 1358 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | 1372 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
| 1359 | if (rtas != (phandle) -1) { | 1373 | if (!PHANDLE_VALID(rtas)) { |
| 1360 | unsigned long x; | 1374 | int x = prom_getproplen(rtas, "ibm,hypertas-functions"); |
| 1361 | x = prom_getproplen(rtas, "ibm,hypertas-functions"); | ||
| 1362 | if (x != PROM_ERROR) { | 1375 | if (x != PROM_ERROR) { |
| 1363 | prom_printf("Hypertas detected, assuming LPAR !\n"); | 1376 | prom_printf("Hypertas detected, assuming LPAR !\n"); |
| 1364 | return PLATFORM_PSERIES_LPAR; | 1377 | return PLATFORM_PSERIES_LPAR; |
| @@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void) | |||
| 1426 | * leave some room at the end of the path for appending extra | 1439 | * leave some room at the end of the path for appending extra |
| 1427 | * arguments | 1440 | * arguments |
| 1428 | */ | 1441 | */ |
| 1429 | if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0) | 1442 | if (call_prom("package-to-path", 3, 1, node, path, |
| 1443 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) | ||
| 1430 | continue; | 1444 | continue; |
| 1431 | prom_printf("found display : %s, opening ... ", path); | 1445 | prom_printf("found display : %s, opening ... ", path); |
| 1432 | 1446 | ||
| 1433 | ih = call_prom("open", 1, 1, path); | 1447 | ih = call_prom("open", 1, 1, path); |
| 1434 | if (ih == (ihandle)0 || ih == (ihandle)-1) { | 1448 | if (ih == 0) { |
| 1435 | prom_printf("failed\n"); | 1449 | prom_printf("failed\n"); |
| 1436 | continue; | 1450 | continue; |
| 1437 | } | 1451 | } |
| @@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str) | |||
| 1514 | return 0; | 1528 | return 0; |
| 1515 | } | 1529 | } |
| 1516 | 1530 | ||
| 1531 | /* | ||
| 1532 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
| 1533 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
| 1534 | */ | ||
| 1535 | #define MAX_PROPERTY_NAME 64 | ||
| 1536 | |||
| 1517 | static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | 1537 | static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, |
| 1518 | unsigned long *mem_end) | 1538 | unsigned long *mem_end) |
| 1519 | { | 1539 | { |
| @@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | |||
| 1527 | /* get and store all property names */ | 1547 | /* get and store all property names */ |
| 1528 | prev_name = RELOC(""); | 1548 | prev_name = RELOC(""); |
| 1529 | for (;;) { | 1549 | for (;;) { |
| 1530 | 1550 | int rc; | |
| 1531 | /* 32 is max len of name including nul. */ | 1551 | |
| 1532 | namep = make_room(mem_start, mem_end, 32, 1); | 1552 | /* 64 is max len of name including nul. */ |
| 1533 | if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) { | 1553 | namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); |
| 1554 | rc = call_prom("nextprop", 3, 1, node, prev_name, namep); | ||
| 1555 | if (rc != 1) { | ||
| 1534 | /* No more nodes: unwind alloc */ | 1556 | /* No more nodes: unwind alloc */ |
| 1535 | *mem_start = (unsigned long)namep; | 1557 | *mem_start = (unsigned long)namep; |
| 1536 | break; | 1558 | break; |
| @@ -1555,12 +1577,6 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | |||
| 1555 | } | 1577 | } |
| 1556 | } | 1578 | } |
| 1557 | 1579 | ||
| 1558 | /* | ||
| 1559 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
| 1560 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
| 1561 | */ | ||
| 1562 | #define MAX_PROPERTY_NAME 64 | ||
| 1563 | |||
| 1564 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | 1580 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, |
| 1565 | unsigned long *mem_end) | 1581 | unsigned long *mem_end) |
| 1566 | { | 1582 | { |
| @@ -1607,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
| 1607 | prev_name = RELOC(""); | 1623 | prev_name = RELOC(""); |
| 1608 | sstart = (char *)RELOC(dt_string_start); | 1624 | sstart = (char *)RELOC(dt_string_start); |
| 1609 | for (;;) { | 1625 | for (;;) { |
| 1610 | if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0) | 1626 | int rc; |
| 1627 | |||
| 1628 | rc = call_prom("nextprop", 3, 1, node, prev_name, pname); | ||
| 1629 | if (rc != 1) | ||
| 1611 | break; | 1630 | break; |
| 1612 | 1631 | ||
| 1613 | /* find string offset */ | 1632 | /* find string offset */ |
| @@ -1623,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
| 1623 | l = call_prom("getproplen", 2, 1, node, pname); | 1642 | l = call_prom("getproplen", 2, 1, node, pname); |
| 1624 | 1643 | ||
| 1625 | /* sanity checks */ | 1644 | /* sanity checks */ |
| 1626 | if (l < 0) | 1645 | if (l == PROM_ERROR) |
| 1627 | continue; | 1646 | continue; |
| 1628 | if (l > MAX_PROPERTY_LENGTH) { | 1647 | if (l > MAX_PROPERTY_LENGTH) { |
| 1629 | prom_printf("WARNING: ignoring large property "); | 1648 | prom_printf("WARNING: ignoring large property "); |
| @@ -1771,17 +1790,18 @@ static void __init fixup_device_tree(void) | |||
| 1771 | 1790 | ||
| 1772 | /* Some G5s have a missing interrupt definition, fix it up here */ | 1791 | /* Some G5s have a missing interrupt definition, fix it up here */ |
| 1773 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); | 1792 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); |
| 1774 | if ((long)u3 <= 0) | 1793 | if (!PHANDLE_VALID(u3)) |
| 1775 | return; | 1794 | return; |
| 1776 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); | 1795 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); |
| 1777 | if ((long)i2c <= 0) | 1796 | if (!PHANDLE_VALID(i2c)) |
| 1778 | return; | 1797 | return; |
| 1779 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); | 1798 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); |
| 1780 | if ((long)mpic <= 0) | 1799 | if (!PHANDLE_VALID(mpic)) |
| 1781 | return; | 1800 | return; |
| 1782 | 1801 | ||
| 1783 | /* check if proper rev of u3 */ | 1802 | /* check if proper rev of u3 */ |
| 1784 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) | 1803 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) |
| 1804 | == PROM_ERROR) | ||
| 1785 | return; | 1805 | return; |
| 1786 | if (u3_rev != 0x35) | 1806 | if (u3_rev != 0x35) |
| 1787 | return; | 1807 | return; |
