Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13-rc2 1012 lines 27 kB view raw
1/* 2 * Note that prom_init() and anything called from prom_init() 3 * may be running at an address that is different from the address 4 * that it was linked at. References to static data items are 5 * handled by compiling this file with -mrelocatable-lib. 6 */ 7 8#include <linux/config.h> 9#include <linux/kernel.h> 10#include <linux/string.h> 11#include <linux/init.h> 12#include <linux/version.h> 13#include <linux/threads.h> 14#include <linux/spinlock.h> 15#include <linux/ioport.h> 16#include <linux/pci.h> 17#include <linux/slab.h> 18#include <linux/bitops.h> 19 20#include <asm/sections.h> 21#include <asm/prom.h> 22#include <asm/page.h> 23#include <asm/irq.h> 24#include <asm/io.h> 25#include <asm/smp.h> 26#include <asm/bootx.h> 27#include <asm/system.h> 28#include <asm/mmu.h> 29#include <asm/pgtable.h> 30#include <asm/bootinfo.h> 31#include <asm/btext.h> 32#include <asm/pci-bridge.h> 33#include <asm/open_pic.h> 34#include <asm/cacheflush.h> 35 36#ifdef CONFIG_LOGO_LINUX_CLUT224 37#include <linux/linux_logo.h> 38extern const struct linux_logo logo_linux_clut224; 39#endif 40 41/* 42 * Properties whose value is longer than this get excluded from our 43 * copy of the device tree. This way we don't waste space storing 44 * things like "driver,AAPL,MacOS,PowerPC" properties. But this value 45 * does need to be big enough to ensure that we don't lose things 46 * like the interrupt-map property on a PCI-PCI bridge. 47 */ 48#define MAX_PROPERTY_LENGTH 4096 49 50#ifndef FB_MAX /* avoid pulling in all of the fb stuff */ 51#define FB_MAX 8 52#endif 53 54#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long)) 55 56typedef u32 prom_arg_t; 57 58struct prom_args { 59 const char *service; 60 int nargs; 61 int nret; 62 prom_arg_t args[10]; 63}; 64 65struct pci_address { 66 unsigned a_hi; 67 unsigned a_mid; 68 unsigned a_lo; 69}; 70 71struct pci_reg_property { 72 struct pci_address addr; 73 unsigned size_hi; 74 unsigned size_lo; 75}; 76 77struct pci_range { 78 struct pci_address addr; 79 unsigned phys; 80 unsigned size_hi; 81 unsigned size_lo; 82}; 83 84struct isa_reg_property { 85 unsigned space; 86 unsigned address; 87 unsigned size; 88}; 89 90struct pci_intr_map { 91 struct pci_address addr; 92 unsigned dunno; 93 phandle int_ctrler; 94 unsigned intr; 95}; 96 97static void prom_exit(void); 98static int call_prom(const char *service, int nargs, int nret, ...); 99static int call_prom_ret(const char *service, int nargs, int nret, 100 prom_arg_t *rets, ...); 101static void prom_print_hex(unsigned int v); 102static int prom_set_color(ihandle ih, int i, int r, int g, int b); 103static int prom_next_node(phandle *nodep); 104static unsigned long check_display(unsigned long mem); 105static void setup_disp_fake_bi(ihandle dp); 106static unsigned long copy_device_tree(unsigned long mem_start, 107 unsigned long mem_end); 108static unsigned long inspect_node(phandle node, struct device_node *dad, 109 unsigned long mem_start, unsigned long mem_end, 110 struct device_node ***allnextpp); 111static void prom_hold_cpus(unsigned long mem); 112static void prom_instantiate_rtas(void); 113static void * early_get_property(unsigned long base, unsigned long node, 114 char *prop); 115 116prom_entry prom __initdata; 117ihandle prom_chosen __initdata; 118ihandle prom_stdout __initdata; 119 120static char *prom_display_paths[FB_MAX] __initdata; 121static phandle prom_display_nodes[FB_MAX] __initdata; 122static unsigned int prom_num_displays __initdata; 123static ihandle prom_disp_node __initdata; 124char *of_stdout_device __initdata; 125 126unsigned int rtas_data; /* physical pointer */ 127unsigned int rtas_entry; /* physical pointer */ 128unsigned int rtas_size; 129unsigned int old_rtas; 130 131boot_infos_t *boot_infos; 132char *bootpath; 133char *bootdevice; 134struct device_node *allnodes; 135 136extern char *klimit; 137 138static void __init 139prom_exit(void) 140{ 141 struct prom_args args; 142 143 args.service = "exit"; 144 args.nargs = 0; 145 args.nret = 0; 146 prom(&args); 147 for (;;) /* should never get here */ 148 ; 149} 150 151static int __init 152call_prom(const char *service, int nargs, int nret, ...) 153{ 154 va_list list; 155 int i; 156 struct prom_args prom_args; 157 158 prom_args.service = service; 159 prom_args.nargs = nargs; 160 prom_args.nret = nret; 161 va_start(list, nret); 162 for (i = 0; i < nargs; ++i) 163 prom_args.args[i] = va_arg(list, prom_arg_t); 164 va_end(list); 165 for (i = 0; i < nret; ++i) 166 prom_args.args[i + nargs] = 0; 167 prom(&prom_args); 168 return prom_args.args[nargs]; 169} 170 171static int __init 172call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...) 173{ 174 va_list list; 175 int i; 176 struct prom_args prom_args; 177 178 prom_args.service = service; 179 prom_args.nargs = nargs; 180 prom_args.nret = nret; 181 va_start(list, rets); 182 for (i = 0; i < nargs; ++i) 183 prom_args.args[i] = va_arg(list, int); 184 va_end(list); 185 for (i = 0; i < nret; ++i) 186 prom_args.args[i + nargs] = 0; 187 prom(&prom_args); 188 for (i = 1; i < nret; ++i) 189 rets[i-1] = prom_args.args[nargs + i]; 190 return prom_args.args[nargs]; 191} 192 193void __init 194prom_print(const char *msg) 195{ 196 const char *p, *q; 197 198 if (prom_stdout == 0) 199 return; 200 201 for (p = msg; *p != 0; p = q) { 202 for (q = p; *q != 0 && *q != '\n'; ++q) 203 ; 204 if (q > p) 205 call_prom("write", 3, 1, prom_stdout, p, q - p); 206 if (*q != 0) { 207 ++q; 208 call_prom("write", 3, 1, prom_stdout, "\r\n", 2); 209 } 210 } 211} 212 213static void __init 214prom_print_hex(unsigned int v) 215{ 216 char buf[16]; 217 int i, c; 218 219 for (i = 0; i < 8; ++i) { 220 c = (v >> ((7-i)*4)) & 0xf; 221 c += (c >= 10)? ('a' - 10): '0'; 222 buf[i] = c; 223 } 224 buf[i] = ' '; 225 buf[i+1] = 0; 226 prom_print(buf); 227} 228 229static int __init 230prom_set_color(ihandle ih, int i, int r, int g, int b) 231{ 232 return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r); 233} 234 235static int __init 236prom_next_node(phandle *nodep) 237{ 238 phandle node; 239 240 if ((node = *nodep) != 0 241 && (*nodep = call_prom("child", 1, 1, node)) != 0) 242 return 1; 243 if ((*nodep = call_prom("peer", 1, 1, node)) != 0) 244 return 1; 245 for (;;) { 246 if ((node = call_prom("parent", 1, 1, node)) == 0) 247 return 0; 248 if ((*nodep = call_prom("peer", 1, 1, node)) != 0) 249 return 1; 250 } 251} 252 253#ifdef CONFIG_POWER4 254/* 255 * Set up a hash table with a set of entries in it to map the 256 * first 64MB of RAM. This is used on 64-bit machines since 257 * some of them don't have BATs. 258 */ 259 260static inline void make_pte(unsigned long htab, unsigned int hsize, 261 unsigned int va, unsigned int pa, int mode) 262{ 263 unsigned int *pteg; 264 unsigned int hash, i, vsid; 265 266 vsid = ((va >> 28) * 0x111) << 12; 267 hash = ((va ^ vsid) >> 5) & 0x7fff80; 268 pteg = (unsigned int *)(htab + (hash & (hsize - 1))); 269 for (i = 0; i < 8; ++i, pteg += 4) { 270 if ((pteg[1] & 1) == 0) { 271 pteg[1] = vsid | ((va >> 16) & 0xf80) | 1; 272 pteg[3] = pa | mode; 273 break; 274 } 275 } 276} 277 278extern unsigned long _SDR1; 279extern PTE *Hash; 280extern unsigned long Hash_size; 281 282static void __init 283prom_alloc_htab(void) 284{ 285 unsigned int hsize; 286 unsigned long htab; 287 unsigned int addr; 288 289 /* 290 * Because of OF bugs we can't use the "claim" client 291 * interface to allocate memory for the hash table. 292 * This code is only used on 64-bit PPCs, and the only 293 * 64-bit PPCs at the moment are RS/6000s, and their 294 * OF is based at 0xc00000 (the 12M point), so we just 295 * arbitrarily use the 0x800000 - 0xc00000 region for the 296 * hash table. 297 * -- paulus. 298 */ 299 hsize = 4 << 20; /* POWER4 has no BATs */ 300 htab = (8 << 20); 301 call_prom("claim", 3, 1, htab, hsize, 0); 302 Hash = (void *)(htab + KERNELBASE); 303 Hash_size = hsize; 304 _SDR1 = htab + __ilog2(hsize) - 18; 305 306 /* 307 * Put in PTEs for the first 64MB of RAM 308 */ 309 memset((void *)htab, 0, hsize); 310 for (addr = 0; addr < 0x4000000; addr += 0x1000) 311 make_pte(htab, hsize, addr + KERNELBASE, addr, 312 _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX); 313#if 0 /* DEBUG stuff mapping the SCC */ 314 make_pte(htab, hsize, 0x80013000, 0x80013000, 315 _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX); 316#endif 317} 318#endif /* CONFIG_POWER4 */ 319 320 321/* 322 * If we have a display that we don't know how to drive, 323 * we will want to try to execute OF's open method for it 324 * later. However, OF will probably fall over if we do that 325 * we've taken over the MMU. 326 * So we check whether we will need to open the display, 327 * and if so, open it now. 328 */ 329static unsigned long __init 330check_display(unsigned long mem) 331{ 332 phandle node; 333 ihandle ih; 334 int i, j; 335 char type[16], *path; 336 static unsigned char default_colors[] = { 337 0x00, 0x00, 0x00, 338 0x00, 0x00, 0xaa, 339 0x00, 0xaa, 0x00, 340 0x00, 0xaa, 0xaa, 341 0xaa, 0x00, 0x00, 342 0xaa, 0x00, 0xaa, 343 0xaa, 0xaa, 0x00, 344 0xaa, 0xaa, 0xaa, 345 0x55, 0x55, 0x55, 346 0x55, 0x55, 0xff, 347 0x55, 0xff, 0x55, 348 0x55, 0xff, 0xff, 349 0xff, 0x55, 0x55, 350 0xff, 0x55, 0xff, 351 0xff, 0xff, 0x55, 352 0xff, 0xff, 0xff 353 }; 354 const unsigned char *clut; 355 356 prom_disp_node = 0; 357 358 for (node = 0; prom_next_node(&node); ) { 359 type[0] = 0; 360 call_prom("getprop", 4, 1, node, "device_type", 361 type, sizeof(type)); 362 if (strcmp(type, "display") != 0) 363 continue; 364 /* It seems OF doesn't null-terminate the path :-( */ 365 path = (char *) mem; 366 memset(path, 0, 256); 367 if (call_prom("package-to-path", 3, 1, node, path, 255) < 0) 368 continue; 369 370 /* 371 * If this display is the device that OF is using for stdout, 372 * move it to the front of the list. 373 */ 374 mem += strlen(path) + 1; 375 i = prom_num_displays++; 376 if (of_stdout_device != 0 && i > 0 377 && strcmp(of_stdout_device, path) == 0) { 378 for (; i > 0; --i) { 379 prom_display_paths[i] 380 = prom_display_paths[i-1]; 381 prom_display_nodes[i] 382 = prom_display_nodes[i-1]; 383 } 384 } 385 prom_display_paths[i] = path; 386 prom_display_nodes[i] = node; 387 if (i == 0) 388 prom_disp_node = node; 389 if (prom_num_displays >= FB_MAX) 390 break; 391 } 392 393 for (j=0; j<prom_num_displays; j++) { 394 path = prom_display_paths[j]; 395 node = prom_display_nodes[j]; 396 prom_print("opening display "); 397 prom_print(path); 398 ih = call_prom("open", 1, 1, path); 399 if (ih == 0 || ih == (ihandle) -1) { 400 prom_print("... failed\n"); 401 for (i=j+1; i<prom_num_displays; i++) { 402 prom_display_paths[i-1] = prom_display_paths[i]; 403 prom_display_nodes[i-1] = prom_display_nodes[i]; 404 } 405 if (--prom_num_displays > 0) { 406 prom_disp_node = prom_display_nodes[j]; 407 j--; 408 } else 409 prom_disp_node = 0; 410 continue; 411 } else { 412 prom_print("... ok\n"); 413 call_prom("setprop", 4, 1, node, "linux,opened", 0, 0); 414 415 /* 416 * Setup a usable color table when the appropriate 417 * method is available. 418 * Should update this to use set-colors. 419 */ 420 clut = default_colors; 421 for (i = 0; i < 32; i++, clut += 3) 422 if (prom_set_color(ih, i, clut[0], clut[1], 423 clut[2]) != 0) 424 break; 425 426#ifdef CONFIG_LOGO_LINUX_CLUT224 427 clut = PTRRELOC(logo_linux_clut224.clut); 428 for (i = 0; i < logo_linux_clut224.clutsize; 429 i++, clut += 3) 430 if (prom_set_color(ih, i + 32, clut[0], 431 clut[1], clut[2]) != 0) 432 break; 433#endif /* CONFIG_LOGO_LINUX_CLUT224 */ 434 } 435 } 436 437 if (prom_stdout) { 438 phandle p; 439 p = call_prom("instance-to-package", 1, 1, prom_stdout); 440 if (p && p != -1) { 441 type[0] = 0; 442 call_prom("getprop", 4, 1, p, "device_type", 443 type, sizeof(type)); 444 if (strcmp(type, "display") == 0) 445 call_prom("setprop", 4, 1, p, "linux,boot-display", 446 0, 0); 447 } 448 } 449 450 return ALIGNUL(mem); 451} 452 453/* This function will enable the early boot text when doing OF booting. This 454 * way, xmon output should work too 455 */ 456static void __init 457setup_disp_fake_bi(ihandle dp) 458{ 459#ifdef CONFIG_BOOTX_TEXT 460 int width = 640, height = 480, depth = 8, pitch; 461 unsigned address; 462 struct pci_reg_property addrs[8]; 463 int i, naddrs; 464 char name[32]; 465 char *getprop = "getprop"; 466 467 prom_print("Initializing fake screen: "); 468 469 memset(name, 0, sizeof(name)); 470 call_prom(getprop, 4, 1, dp, "name", name, sizeof(name)); 471 name[sizeof(name)-1] = 0; 472 prom_print(name); 473 prom_print("\n"); 474 call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width)); 475 call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height)); 476 call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth)); 477 pitch = width * ((depth + 7) / 8); 478 call_prom(getprop, 4, 1, dp, "linebytes", 479 &pitch, sizeof(pitch)); 480 if (pitch == 1) 481 pitch = 0x1000; /* for strange IBM display */ 482 address = 0; 483 call_prom(getprop, 4, 1, dp, "address", 484 &address, sizeof(address)); 485 if (address == 0) { 486 /* look for an assigned address with a size of >= 1MB */ 487 naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses", 488 addrs, sizeof(addrs)); 489 naddrs /= sizeof(struct pci_reg_property); 490 for (i = 0; i < naddrs; ++i) { 491 if (addrs[i].size_lo >= (1 << 20)) { 492 address = addrs[i].addr.a_lo; 493 /* use the BE aperture if possible */ 494 if (addrs[i].size_lo >= (16 << 20)) 495 address += (8 << 20); 496 break; 497 } 498 } 499 if (address == 0) { 500 prom_print("Failed to get address\n"); 501 return; 502 } 503 } 504 /* kludge for valkyrie */ 505 if (strcmp(name, "valkyrie") == 0) 506 address += 0x1000; 507 508#ifdef CONFIG_POWER4 509#if CONFIG_TASK_SIZE > 0x80000000 510#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5 511#endif 512 { 513 extern boot_infos_t disp_bi; 514 unsigned long va, pa, i, offset; 515 va = 0x90000000; 516 pa = address & 0xfffff000ul; 517 offset = address & 0x00000fff; 518 519 for (i=0; i<0x4000; i++) { 520 make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa, 521 _PAGE_ACCESSED | _PAGE_NO_CACHE | 522 _PAGE_GUARDED | PP_RWXX); 523 va += 0x1000; 524 pa += 0x1000; 525 } 526 btext_setup_display(width, height, depth, pitch, 0x90000000 | offset); 527 disp_bi.dispDeviceBase = (u8 *)address; 528 } 529#else /* CONFIG_POWER4 */ 530 btext_setup_display(width, height, depth, pitch, address); 531 btext_prepare_BAT(); 532#endif /* CONFIG_POWER4 */ 533#endif /* CONFIG_BOOTX_TEXT */ 534} 535 536/* 537 * Make a copy of the device tree from the PROM. 538 */ 539static unsigned long __init 540copy_device_tree(unsigned long mem_start, unsigned long mem_end) 541{ 542 phandle root; 543 unsigned long new_start; 544 struct device_node **allnextp; 545 546 root = call_prom("peer", 1, 1, (phandle)0); 547 if (root == (phandle)0) { 548 prom_print("couldn't get device tree root\n"); 549 prom_exit(); 550 } 551 allnextp = &allnodes; 552 mem_start = ALIGNUL(mem_start); 553 new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp); 554 *allnextp = NULL; 555 return new_start; 556} 557 558static unsigned long __init 559inspect_node(phandle node, struct device_node *dad, 560 unsigned long mem_start, unsigned long mem_end, 561 struct device_node ***allnextpp) 562{ 563 int l; 564 phandle child; 565 struct device_node *np; 566 struct property *pp, **prev_propp; 567 char *prev_name, *namep; 568 unsigned char *valp; 569 570 np = (struct device_node *) mem_start; 571 mem_start += sizeof(struct device_node); 572 memset(np, 0, sizeof(*np)); 573 np->node = node; 574 **allnextpp = PTRUNRELOC(np); 575 *allnextpp = &np->allnext; 576 if (dad != 0) { 577 np->parent = PTRUNRELOC(dad); 578 /* we temporarily use the `next' field as `last_child'. */ 579 if (dad->next == 0) 580 dad->child = PTRUNRELOC(np); 581 else 582 dad->next->sibling = PTRUNRELOC(np); 583 dad->next = np; 584 } 585 586 /* get and store all properties */ 587 prev_propp = &np->properties; 588 prev_name = ""; 589 for (;;) { 590 pp = (struct property *) mem_start; 591 namep = (char *) (pp + 1); 592 pp->name = PTRUNRELOC(namep); 593 if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) 594 break; 595 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1); 596 prev_name = namep; 597 valp = (unsigned char *) mem_start; 598 pp->value = PTRUNRELOC(valp); 599 pp->length = call_prom("getprop", 4, 1, node, namep, 600 valp, mem_end - mem_start); 601 if (pp->length < 0) 602 continue; 603#ifdef MAX_PROPERTY_LENGTH 604 if (pp->length > MAX_PROPERTY_LENGTH) 605 continue; /* ignore this property */ 606#endif 607 mem_start = ALIGNUL(mem_start + pp->length); 608 *prev_propp = PTRUNRELOC(pp); 609 prev_propp = &pp->next; 610 } 611 if (np->node != 0) { 612 /* Add a "linux,phandle" property" */ 613 pp = (struct property *) mem_start; 614 *prev_propp = PTRUNRELOC(pp); 615 prev_propp = &pp->next; 616 namep = (char *) (pp + 1); 617 pp->name = PTRUNRELOC(namep); 618 strcpy(namep, "linux,phandle"); 619 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1); 620 pp->value = (unsigned char *) PTRUNRELOC(&np->node); 621 pp->length = sizeof(np->node); 622 } 623 *prev_propp = NULL; 624 625 /* get the node's full name */ 626 l = call_prom("package-to-path", 3, 1, node, 627 mem_start, mem_end - mem_start); 628 if (l >= 0) { 629 char *p, *ep; 630 631 np->full_name = PTRUNRELOC((char *) mem_start); 632 *(char *)(mem_start + l) = 0; 633 /* Fixup an Apple bug where they have bogus \0 chars in the 634 * middle of the path in some properties 635 */ 636 for (p = (char *)mem_start, ep = p + l; p < ep; p++) 637 if ((*p) == '\0') { 638 memmove(p, p+1, ep - p); 639 ep--; 640 } 641 mem_start = ALIGNUL(mem_start + l + 1); 642 } 643 644 /* do all our children */ 645 child = call_prom("child", 1, 1, node); 646 while (child != 0) { 647 mem_start = inspect_node(child, np, mem_start, mem_end, 648 allnextpp); 649 child = call_prom("peer", 1, 1, child); 650 } 651 652 return mem_start; 653} 654 655unsigned long smp_chrp_cpu_nr __initdata = 0; 656 657/* 658 * With CHRP SMP we need to use the OF to start the other 659 * processors so we can't wait until smp_boot_cpus (the OF is 660 * trashed by then) so we have to put the processors into 661 * a holding pattern controlled by the kernel (not OF) before 662 * we destroy the OF. 663 * 664 * This uses a chunk of high memory, puts some holding pattern 665 * code there and sends the other processors off to there until 666 * smp_boot_cpus tells them to do something. We do that by using 667 * physical address 0x0. The holding pattern checks that address 668 * until its cpu # is there, when it is that cpu jumps to 669 * __secondary_start(). smp_boot_cpus() takes care of setting those 670 * values. 671 * 672 * We also use physical address 0x4 here to tell when a cpu 673 * is in its holding pattern code. 674 * 675 * -- Cort 676 * 677 * Note that we have to do this if we have more than one CPU, 678 * even if this is a UP kernel. Otherwise when we trash OF 679 * the other CPUs will start executing some random instructions 680 * and crash the system. -- paulus 681 */ 682static void __init 683prom_hold_cpus(unsigned long mem) 684{ 685 extern void __secondary_hold(void); 686 unsigned long i; 687 int cpu; 688 phandle node; 689 char type[16], *path; 690 unsigned int reg; 691 692 /* 693 * XXX: hack to make sure we're chrp, assume that if we're 694 * chrp we have a device_type property -- Cort 695 */ 696 node = call_prom("finddevice", 1, 1, "/"); 697 if (call_prom("getprop", 4, 1, node, 698 "device_type", type, sizeof(type)) <= 0) 699 return; 700 701 /* copy the holding pattern code to someplace safe (0) */ 702 /* the holding pattern is now within the first 0x100 703 bytes of the kernel image -- paulus */ 704 memcpy((void *)0, _stext, 0x100); 705 flush_icache_range(0, 0x100); 706 707 /* look for cpus */ 708 *(unsigned long *)(0x0) = 0; 709 asm volatile("dcbf 0,%0": : "r" (0) : "memory"); 710 for (node = 0; prom_next_node(&node); ) { 711 type[0] = 0; 712 call_prom("getprop", 4, 1, node, "device_type", 713 type, sizeof(type)); 714 if (strcmp(type, "cpu") != 0) 715 continue; 716 path = (char *) mem; 717 memset(path, 0, 256); 718 if (call_prom("package-to-path", 3, 1, node, path, 255) < 0) 719 continue; 720 reg = -1; 721 call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg)); 722 cpu = smp_chrp_cpu_nr++; 723#ifdef CONFIG_SMP 724 smp_hw_index[cpu] = reg; 725#endif /* CONFIG_SMP */ 726 /* XXX: hack - don't start cpu 0, this cpu -- Cort */ 727 if (cpu == 0) 728 continue; 729 prom_print("starting cpu "); 730 prom_print(path); 731 *(ulong *)(0x4) = 0; 732 call_prom("start-cpu", 3, 0, node, 733 (char *)__secondary_hold - _stext, cpu); 734 prom_print("..."); 735 for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ ) 736 ; 737 if (*(ulong *)(0x4) == cpu) 738 prom_print("ok\n"); 739 else { 740 prom_print("failed: "); 741 prom_print_hex(*(ulong *)0x4); 742 prom_print("\n"); 743 } 744 } 745} 746 747static void __init 748prom_instantiate_rtas(void) 749{ 750 ihandle prom_rtas; 751 prom_arg_t result; 752 753 prom_rtas = call_prom("finddevice", 1, 1, "/rtas"); 754 if (prom_rtas == -1) 755 return; 756 757 rtas_size = 0; 758 call_prom("getprop", 4, 1, prom_rtas, 759 "rtas-size", &rtas_size, sizeof(rtas_size)); 760 prom_print("instantiating rtas"); 761 if (rtas_size == 0) { 762 rtas_data = 0; 763 } else { 764 /* 765 * Ask OF for some space for RTAS. 766 * Actually OF has bugs so we just arbitrarily 767 * use memory at the 6MB point. 768 */ 769 rtas_data = 6 << 20; 770 prom_print(" at "); 771 prom_print_hex(rtas_data); 772 } 773 774 prom_rtas = call_prom("open", 1, 1, "/rtas"); 775 prom_print("..."); 776 rtas_entry = 0; 777 if (call_prom_ret("call-method", 3, 2, &result, 778 "instantiate-rtas", prom_rtas, rtas_data) == 0) 779 rtas_entry = result; 780 if ((rtas_entry == -1) || (rtas_entry == 0)) 781 prom_print(" failed\n"); 782 else 783 prom_print(" done\n"); 784} 785 786/* 787 * We enter here early on, when the Open Firmware prom is still 788 * handling exceptions and the MMU hash table for us. 789 */ 790unsigned long __init 791prom_init(int r3, int r4, prom_entry pp) 792{ 793 unsigned long mem; 794 ihandle prom_mmu; 795 unsigned long offset = reloc_offset(); 796 int i, l; 797 char *p, *d; 798 unsigned long phys; 799 prom_arg_t result[3]; 800 char model[32]; 801 phandle node; 802 int rc; 803 804 /* Default */ 805 phys = (unsigned long) &_stext; 806 807 /* First get a handle for the stdout device */ 808 prom = pp; 809 prom_chosen = call_prom("finddevice", 1, 1, "/chosen"); 810 if (prom_chosen == -1) 811 prom_exit(); 812 if (call_prom("getprop", 4, 1, prom_chosen, "stdout", 813 &prom_stdout, sizeof(prom_stdout)) <= 0) 814 prom_exit(); 815 816 /* Get the full OF pathname of the stdout device */ 817 mem = (unsigned long) klimit + offset; 818 p = (char *) mem; 819 memset(p, 0, 256); 820 call_prom("instance-to-path", 3, 1, prom_stdout, p, 255); 821 of_stdout_device = p; 822 mem += strlen(p) + 1; 823 824 /* Get the boot device and translate it to a full OF pathname. */ 825 p = (char *) mem; 826 l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20); 827 if (l > 0) { 828 p[l] = 0; /* should already be null-terminated */ 829 bootpath = PTRUNRELOC(p); 830 mem += l + 1; 831 d = (char *) mem; 832 *d = 0; 833 call_prom("canon", 3, 1, p, d, 1<<20); 834 bootdevice = PTRUNRELOC(d); 835 mem = ALIGNUL(mem + strlen(d) + 1); 836 } 837 838 prom_instantiate_rtas(); 839 840#ifdef CONFIG_POWER4 841 /* 842 * Find out how much memory we have and allocate a 843 * suitably-sized hash table. 844 */ 845 prom_alloc_htab(); 846#endif 847 mem = check_display(mem); 848 849 prom_print("copying OF device tree..."); 850 mem = copy_device_tree(mem, mem + (1<<20)); 851 prom_print("done\n"); 852 853 prom_hold_cpus(mem); 854 855 klimit = (char *) (mem - offset); 856 857 node = call_prom("finddevice", 1, 1, "/"); 858 rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model)); 859 if (rc > 0 && !strncmp (model, "Pegasos", 7) 860 && strncmp (model, "Pegasos2", 8)) { 861 /* Pegasos 1 has a broken translate method in the OF, 862 * and furthermore the BATs are mapped 1:1 so the phys 863 * address calculated above is correct, so let's use 864 * it directly. 865 */ 866 } else if (offset == 0) { 867 /* If we are already running at 0xc0000000, we assume we were 868 * loaded by an OF bootloader which did set a BAT for us. 869 * This breaks OF translate so we force phys to be 0. 870 */ 871 prom_print("(already at 0xc0000000) phys=0\n"); 872 phys = 0; 873 } else if (call_prom("getprop", 4, 1, prom_chosen, "mmu", 874 &prom_mmu, sizeof(prom_mmu)) <= 0) { 875 prom_print(" no MMU found\n"); 876 } else if (call_prom_ret("call-method", 4, 4, result, "translate", 877 prom_mmu, &_stext, 1) != 0) { 878 prom_print(" (translate failed)\n"); 879 } else { 880 /* We assume the phys. address size is 3 cells */ 881 phys = result[2]; 882 } 883 884 if (prom_disp_node != 0) 885 setup_disp_fake_bi(prom_disp_node); 886 887 /* Use quiesce call to get OF to shut down any devices it's using */ 888 prom_print("Calling quiesce ...\n"); 889 call_prom("quiesce", 0, 0); 890 891 /* Relocate various pointers which will be used once the 892 kernel is running at the address it was linked at. */ 893 for (i = 0; i < prom_num_displays; ++i) 894 prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]); 895 896#ifdef CONFIG_SERIAL_CORE_CONSOLE 897 /* Relocate the of stdout for console autodetection */ 898 of_stdout_device = PTRUNRELOC(of_stdout_device); 899#endif 900 901 prom_print("returning 0x"); 902 prom_print_hex(phys); 903 prom_print("from prom_init\n"); 904 prom_stdout = 0; 905 906 return phys; 907} 908 909/* 910 * early_get_property is used to access the device tree image prepared 911 * by BootX very early on, before the pointers in it have been relocated. 912 */ 913static void * __init 914early_get_property(unsigned long base, unsigned long node, char *prop) 915{ 916 struct device_node *np = (struct device_node *)(base + node); 917 struct property *pp; 918 919 for (pp = np->properties; pp != 0; pp = pp->next) { 920 pp = (struct property *) (base + (unsigned long)pp); 921 if (strcmp((char *)((unsigned long)pp->name + base), 922 prop) == 0) { 923 return (void *)((unsigned long)pp->value + base); 924 } 925 } 926 return NULL; 927} 928 929/* Is boot-info compatible ? */ 930#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION) 931#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2) 932#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4) 933 934void __init 935bootx_init(unsigned long r4, unsigned long phys) 936{ 937 boot_infos_t *bi = (boot_infos_t *) r4; 938 unsigned long space; 939 unsigned long ptr, x; 940 char *model; 941 942 boot_infos = PTRUNRELOC(bi); 943 if (!BOOT_INFO_IS_V2_COMPATIBLE(bi)) 944 bi->logicalDisplayBase = NULL; 945 946#ifdef CONFIG_BOOTX_TEXT 947 btext_init(bi); 948 949 /* 950 * Test if boot-info is compatible. Done only in config 951 * CONFIG_BOOTX_TEXT since there is nothing much we can do 952 * with an incompatible version, except display a message 953 * and eventually hang the processor... 954 * 955 * I'll try to keep enough of boot-info compatible in the 956 * future to always allow display of this message; 957 */ 958 if (!BOOT_INFO_IS_COMPATIBLE(bi)) { 959 btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n"); 960 btext_flushscreen(); 961 } 962#endif /* CONFIG_BOOTX_TEXT */ 963 964 /* New BootX enters kernel with MMU off, i/os are not allowed 965 here. This hack will have been done by the boostrap anyway. 966 */ 967 if (bi->version < 4) { 968 /* 969 * XXX If this is an iMac, turn off the USB controller. 970 */ 971 model = (char *) early_get_property 972 (r4 + bi->deviceTreeOffset, 4, "model"); 973 if (model 974 && (strcmp(model, "iMac,1") == 0 975 || strcmp(model, "PowerMac1,1") == 0)) { 976 out_le32((unsigned *)0x80880008, 1); /* XXX */ 977 } 978 } 979 980 /* Move klimit to enclose device tree, args, ramdisk, etc... */ 981 if (bi->version < 5) { 982 space = bi->deviceTreeOffset + bi->deviceTreeSize; 983 if (bi->ramDisk) 984 space = bi->ramDisk + bi->ramDiskSize; 985 } else 986 space = bi->totalParamsSize; 987 klimit = PTRUNRELOC((char *) bi + space); 988 989 /* New BootX will have flushed all TLBs and enters kernel with 990 MMU switched OFF, so this should not be useful anymore. 991 */ 992 if (bi->version < 4) { 993 /* 994 * Touch each page to make sure the PTEs for them 995 * are in the hash table - the aim is to try to avoid 996 * getting DSI exceptions while copying the kernel image. 997 */ 998 for (ptr = ((unsigned long) &_stext) & PAGE_MASK; 999 ptr < (unsigned long)bi + space; ptr += PAGE_SIZE) 1000 x = *(volatile unsigned long *)ptr; 1001 } 1002 1003#ifdef CONFIG_BOOTX_TEXT 1004 /* 1005 * Note that after we call btext_prepare_BAT, we can't do 1006 * prom_draw*, flushscreen or clearscreen until we turn the MMU 1007 * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase 1008 * to a virtual address. 1009 */ 1010 btext_prepare_BAT(); 1011#endif 1012}