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.
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>
20 #include <asm/sections.h>
26 #include <asm/bootx.h>
27 #include <asm/system.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>
36 #ifdef CONFIG_LOGO_LINUX_CLUT224
37 #include <linux/linux_logo.h>
38 extern const struct linux_logo logo_linux_clut224;
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.
48 #define MAX_PROPERTY_LENGTH 4096
50 #ifndef FB_MAX /* avoid pulling in all of the fb stuff */
54 #define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
69 struct pci_reg_property {
70 struct pci_address addr;
76 struct pci_address addr;
82 struct isa_reg_property {
89 struct pci_address addr;
95 static void prom_exit(void);
96 static void *call_prom(const char *service, int nargs, int nret, ...);
97 static void *call_prom_ret(const char *service, int nargs, int nret,
99 static void prom_print_hex(unsigned int v);
100 static int prom_set_color(ihandle ih, int i, int r, int g, int b);
101 static int prom_next_node(phandle *nodep);
102 static unsigned long check_display(unsigned long mem);
103 static void setup_disp_fake_bi(ihandle dp);
104 static unsigned long copy_device_tree(unsigned long mem_start,
105 unsigned long mem_end);
106 static unsigned long inspect_node(phandle node, struct device_node *dad,
107 unsigned long mem_start, unsigned long mem_end,
108 struct device_node ***allnextpp);
109 static void prom_hold_cpus(unsigned long mem);
110 static void prom_instantiate_rtas(void);
111 static void * early_get_property(unsigned long base, unsigned long node,
114 prom_entry prom __initdata;
115 ihandle prom_chosen __initdata;
116 ihandle prom_stdout __initdata;
118 static char *prom_display_paths[FB_MAX] __initdata;
119 static phandle prom_display_nodes[FB_MAX] __initdata;
120 static unsigned int prom_num_displays __initdata;
121 static ihandle prom_disp_node __initdata;
122 char *of_stdout_device __initdata;
124 unsigned int rtas_data; /* physical pointer */
125 unsigned int rtas_entry; /* physical pointer */
126 unsigned int rtas_size;
127 unsigned int old_rtas;
129 boot_infos_t *boot_infos;
132 struct device_node *allnodes;
139 struct prom_args args;
141 args.service = "exit";
145 for (;;) /* should never get here */
150 call_prom(const char *service, int nargs, int nret, ...)
154 struct prom_args prom_args;
156 prom_args.service = service;
157 prom_args.nargs = nargs;
158 prom_args.nret = nret;
159 va_start(list, nret);
160 for (i = 0; i < nargs; ++i)
161 prom_args.args[i] = va_arg(list, void *);
163 for (i = 0; i < nret; ++i)
164 prom_args.args[i + nargs] = NULL;
166 return prom_args.args[nargs];
170 call_prom_ret(const char *service, int nargs, int nret, void **rets, ...)
174 struct prom_args prom_args;
176 prom_args.service = service;
177 prom_args.nargs = nargs;
178 prom_args.nret = nret;
179 va_start(list, rets);
180 for (i = 0; i < nargs; ++i)
181 prom_args.args[i] = va_arg(list, void *);
183 for (i = 0; i < nret; ++i)
184 prom_args.args[i + nargs] = NULL;
186 for (i = 1; i < nret; ++i)
187 rets[i-1] = prom_args.args[nargs + i];
188 return prom_args.args[nargs];
192 prom_print(const char *msg)
196 if (prom_stdout == 0)
199 for (p = msg; *p != 0; p = q) {
200 for (q = p; *q != 0 && *q != '\n'; ++q)
203 call_prom("write", 3, 1, prom_stdout, p, q - p);
206 call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
212 prom_print_hex(unsigned int v)
217 for (i = 0; i < 8; ++i) {
218 c = (v >> ((7-i)*4)) & 0xf;
219 c += (c >= 10)? ('a' - 10): '0';
228 prom_set_color(ihandle ih, int i, int r, int g, int b)
230 struct prom_args prom_args;
232 prom_args.service = "call-method";
235 prom_args.args[0] = "color!";
236 prom_args.args[1] = ih;
237 prom_args.args[2] = (void *) i;
238 prom_args.args[3] = (void *) b;
239 prom_args.args[4] = (void *) g;
240 prom_args.args[5] = (void *) r;
242 return (int) prom_args.args[6];
246 prom_next_node(phandle *nodep)
250 if ((node = *nodep) != 0
251 && (*nodep = call_prom("child", 1, 1, node)) != 0)
253 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
256 if ((node = call_prom("parent", 1, 1, node)) == 0)
258 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
265 * Set up a hash table with a set of entries in it to map the
266 * first 64MB of RAM. This is used on 64-bit machines since
267 * some of them don't have BATs.
270 static inline void make_pte(unsigned long htab, unsigned int hsize,
271 unsigned int va, unsigned int pa, int mode)
274 unsigned int hash, i, vsid;
276 vsid = ((va >> 28) * 0x111) << 12;
277 hash = ((va ^ vsid) >> 5) & 0x7fff80;
278 pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
279 for (i = 0; i < 8; ++i, pteg += 4) {
280 if ((pteg[1] & 1) == 0) {
281 pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
288 extern unsigned long _SDR1;
290 extern unsigned long Hash_size;
293 prom_alloc_htab(void)
300 * Because of OF bugs we can't use the "claim" client
301 * interface to allocate memory for the hash table.
302 * This code is only used on 64-bit PPCs, and the only
303 * 64-bit PPCs at the moment are RS/6000s, and their
304 * OF is based at 0xc00000 (the 12M point), so we just
305 * arbitrarily use the 0x800000 - 0xc00000 region for the
309 hsize = 4 << 20; /* POWER4 has no BATs */
311 call_prom("claim", 3, 1, htab, hsize, 0);
312 Hash = (void *)(htab + KERNELBASE);
314 _SDR1 = htab + __ilog2(hsize) - 18;
317 * Put in PTEs for the first 64MB of RAM
319 memset((void *)htab, 0, hsize);
320 for (addr = 0; addr < 0x4000000; addr += 0x1000)
321 make_pte(htab, hsize, addr + KERNELBASE, addr,
322 _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
323 #if 0 /* DEBUG stuff mapping the SCC */
324 make_pte(htab, hsize, 0x80013000, 0x80013000,
325 _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
328 #endif /* CONFIG_POWER4 */
332 * If we have a display that we don't know how to drive,
333 * we will want to try to execute OF's open method for it
334 * later. However, OF will probably fall over if we do that
335 * we've taken over the MMU.
336 * So we check whether we will need to open the display,
337 * and if so, open it now.
339 static unsigned long __init
340 check_display(unsigned long mem)
345 char type[16], *path;
346 static unsigned char default_colors[] = {
364 const unsigned char *clut;
366 prom_disp_node = NULL;
368 for (node = NULL; prom_next_node(&node); ) {
370 call_prom("getprop", 4, 1, node, "device_type",
372 if (strcmp(type, "display") != 0)
374 /* It seems OF doesn't null-terminate the path :-( */
376 memset(path, 0, 256);
377 if ((int) call_prom("package-to-path", 3, 1,
378 node, path, 255) < 0)
382 * If this display is the device that OF is using for stdout,
383 * move it to the front of the list.
385 mem += strlen(path) + 1;
386 i = prom_num_displays++;
387 if (of_stdout_device != 0 && i > 0
388 && strcmp(of_stdout_device, path) == 0) {
390 prom_display_paths[i]
391 = prom_display_paths[i-1];
392 prom_display_nodes[i]
393 = prom_display_nodes[i-1];
396 prom_display_paths[i] = path;
397 prom_display_nodes[i] = node;
399 prom_disp_node = node;
400 if (prom_num_displays >= FB_MAX)
404 for (j=0; j<prom_num_displays; j++) {
405 path = prom_display_paths[j];
406 node = prom_display_nodes[j];
407 prom_print("opening display ");
409 ih = call_prom("open", 1, 1, path);
410 if (ih == 0 || ih == (ihandle) -1) {
411 prom_print("... failed\n");
412 for (i=j+1; i<prom_num_displays; i++) {
413 prom_display_paths[i-1] = prom_display_paths[i];
414 prom_display_nodes[i-1] = prom_display_nodes[i];
416 if (--prom_num_displays > 0) {
417 prom_disp_node = prom_display_nodes[j];
420 prom_disp_node = NULL;
423 prom_print("... ok\n");
424 call_prom("setprop", 4, 1, node, "linux,opened", 0, NULL);
427 * Setup a usable color table when the appropriate
428 * method is available.
429 * Should update this to use set-colors.
431 clut = default_colors;
432 for (i = 0; i < 32; i++, clut += 3)
433 if (prom_set_color(ih, i, clut[0], clut[1],
437 #ifdef CONFIG_LOGO_LINUX_CLUT224
438 clut = PTRRELOC(logo_linux_clut224.clut);
439 for (i = 0; i < logo_linux_clut224.clutsize;
441 if (prom_set_color(ih, i + 32, clut[0],
442 clut[1], clut[2]) != 0)
444 #endif /* CONFIG_LOGO_LINUX_CLUT224 */
450 p = call_prom("instance-to-package", 1, 1, prom_stdout);
451 if (p && (int)p != -1) {
453 call_prom("getprop", 4, 1, p, "device_type",
455 if (strcmp(type, "display") == 0)
456 call_prom("setprop", 4, 1, p, "linux,boot-display",
464 /* This function will enable the early boot text when doing OF booting. This
465 * way, xmon output should work too
468 setup_disp_fake_bi(ihandle dp)
470 #ifdef CONFIG_BOOTX_TEXT
471 int width = 640, height = 480, depth = 8, pitch;
473 struct pci_reg_property addrs[8];
476 char *getprop = "getprop";
478 prom_print("Initializing fake screen: ");
480 memset(name, 0, sizeof(name));
481 call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
482 name[sizeof(name)-1] = 0;
485 call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
486 call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
487 call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
488 pitch = width * ((depth + 7) / 8);
489 call_prom(getprop, 4, 1, dp, "linebytes",
490 &pitch, sizeof(pitch));
492 pitch = 0x1000; /* for strange IBM display */
494 call_prom(getprop, 4, 1, dp, "address",
495 &address, sizeof(address));
497 /* look for an assigned address with a size of >= 1MB */
498 naddrs = (int) call_prom(getprop, 4, 1, dp,
499 "assigned-addresses",
500 addrs, sizeof(addrs));
501 naddrs /= sizeof(struct pci_reg_property);
502 for (i = 0; i < naddrs; ++i) {
503 if (addrs[i].size_lo >= (1 << 20)) {
504 address = addrs[i].addr.a_lo;
505 /* use the BE aperture if possible */
506 if (addrs[i].size_lo >= (16 << 20))
507 address += (8 << 20);
512 prom_print("Failed to get address\n");
516 /* kludge for valkyrie */
517 if (strcmp(name, "valkyrie") == 0)
521 #if CONFIG_TASK_SIZE > 0x80000000
522 #error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
525 extern boot_infos_t disp_bi;
526 unsigned long va, pa, i, offset;
528 pa = address & 0xfffff000ul;
529 offset = address & 0x00000fff;
531 for (i=0; i<0x4000; i++) {
532 make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa,
533 _PAGE_ACCESSED | _PAGE_NO_CACHE |
534 _PAGE_GUARDED | PP_RWXX);
538 btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
539 disp_bi.dispDeviceBase = (u8 *)address;
541 #else /* CONFIG_POWER4 */
542 btext_setup_display(width, height, depth, pitch, address);
544 #endif /* CONFIG_POWER4 */
545 #endif /* CONFIG_BOOTX_TEXT */
549 * Make a copy of the device tree from the PROM.
551 static unsigned long __init
552 copy_device_tree(unsigned long mem_start, unsigned long mem_end)
555 unsigned long new_start;
556 struct device_node **allnextp;
558 root = call_prom("peer", 1, 1, (phandle)0);
559 if (root == (phandle)0) {
560 prom_print("couldn't get device tree root\n");
563 allnextp = &allnodes;
564 mem_start = ALIGNUL(mem_start);
565 new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
570 static unsigned long __init
571 inspect_node(phandle node, struct device_node *dad,
572 unsigned long mem_start, unsigned long mem_end,
573 struct device_node ***allnextpp)
577 struct device_node *np;
578 struct property *pp, **prev_propp;
579 char *prev_name, *namep;
582 np = (struct device_node *) mem_start;
583 mem_start += sizeof(struct device_node);
584 memset(np, 0, sizeof(*np));
586 **allnextpp = PTRUNRELOC(np);
587 *allnextpp = &np->allnext;
589 np->parent = PTRUNRELOC(dad);
590 /* we temporarily use the `next' field as `last_child'. */
592 dad->child = PTRUNRELOC(np);
594 dad->next->sibling = PTRUNRELOC(np);
598 /* get and store all properties */
599 prev_propp = &np->properties;
602 pp = (struct property *) mem_start;
603 namep = (char *) (pp + 1);
604 pp->name = PTRUNRELOC(namep);
605 if ((int) call_prom("nextprop", 3, 1, node, prev_name,
608 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
610 valp = (unsigned char *) mem_start;
611 pp->value = PTRUNRELOC(valp);
613 call_prom("getprop", 4, 1, node, namep,
614 valp, mem_end - mem_start);
617 #ifdef MAX_PROPERTY_LENGTH
618 if (pp->length > MAX_PROPERTY_LENGTH)
619 continue; /* ignore this property */
621 mem_start = ALIGNUL(mem_start + pp->length);
622 *prev_propp = PTRUNRELOC(pp);
623 prev_propp = &pp->next;
625 if (np->node != NULL) {
626 /* Add a "linux,phandle" property" */
627 pp = (struct property *) mem_start;
628 *prev_propp = PTRUNRELOC(pp);
629 prev_propp = &pp->next;
630 namep = (char *) (pp + 1);
631 pp->name = PTRUNRELOC(namep);
632 strcpy(namep, "linux,phandle");
633 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
634 pp->value = (unsigned char *) PTRUNRELOC(&np->node);
635 pp->length = sizeof(np->node);
639 /* get the node's full name */
640 l = (int) call_prom("package-to-path", 3, 1, node,
641 (char *) mem_start, mem_end - mem_start);
643 np->full_name = PTRUNRELOC((char *) mem_start);
644 *(char *)(mem_start + l) = 0;
645 mem_start = ALIGNUL(mem_start + l + 1);
648 /* do all our children */
649 child = call_prom("child", 1, 1, node);
650 while (child != (void *)0) {
651 mem_start = inspect_node(child, np, mem_start, mem_end,
653 child = call_prom("peer", 1, 1, child);
659 unsigned long smp_chrp_cpu_nr __initdata = 0;
662 * With CHRP SMP we need to use the OF to start the other
663 * processors so we can't wait until smp_boot_cpus (the OF is
664 * trashed by then) so we have to put the processors into
665 * a holding pattern controlled by the kernel (not OF) before
668 * This uses a chunk of high memory, puts some holding pattern
669 * code there and sends the other processors off to there until
670 * smp_boot_cpus tells them to do something. We do that by using
671 * physical address 0x0. The holding pattern checks that address
672 * until its cpu # is there, when it is that cpu jumps to
673 * __secondary_start(). smp_boot_cpus() takes care of setting those
676 * We also use physical address 0x4 here to tell when a cpu
677 * is in its holding pattern code.
681 * Note that we have to do this if we have more than one CPU,
682 * even if this is a UP kernel. Otherwise when we trash OF
683 * the other CPUs will start executing some random instructions
684 * and crash the system. -- paulus
687 prom_hold_cpus(unsigned long mem)
689 extern void __secondary_hold(void);
693 char type[16], *path;
697 * XXX: hack to make sure we're chrp, assume that if we're
698 * chrp we have a device_type property -- Cort
700 node = call_prom("finddevice", 1, 1, "/");
701 if ((int)call_prom("getprop", 4, 1, node,
702 "device_type",type, sizeof(type)) <= 0)
705 /* copy the holding pattern code to someplace safe (0) */
706 /* the holding pattern is now within the first 0x100
707 bytes of the kernel image -- paulus */
708 memcpy((void *)0, _stext, 0x100);
709 flush_icache_range(0, 0x100);
712 *(unsigned long *)(0x0) = 0;
713 asm volatile("dcbf 0,%0": : "r" (0) : "memory");
714 for (node = NULL; prom_next_node(&node); ) {
716 call_prom("getprop", 4, 1, node, "device_type",
718 if (strcmp(type, "cpu") != 0)
721 memset(path, 0, 256);
722 if ((int) call_prom("package-to-path", 3, 1,
723 node, path, 255) < 0)
726 call_prom("getprop", 4, 1, node, "reg", ®, sizeof(reg));
727 cpu = smp_chrp_cpu_nr++;
729 smp_hw_index[cpu] = reg;
730 #endif /* CONFIG_SMP */
731 /* XXX: hack - don't start cpu 0, this cpu -- Cort */
734 prom_print("starting cpu ");
737 call_prom("start-cpu", 3, 0, node,
738 (char *)__secondary_hold - _stext, cpu);
740 for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
742 if (*(ulong *)(0x4) == cpu)
745 prom_print("failed: ");
746 prom_print_hex(*(ulong *)0x4);
753 prom_instantiate_rtas(void)
757 struct prom_args prom_args;
759 prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
760 if (prom_rtas == (void *) -1)
764 call_prom("getprop", 4, 1, prom_rtas,
765 "rtas-size", &rtas_size, sizeof(rtas_size));
766 prom_print("instantiating rtas");
767 if (rtas_size == 0) {
771 * Ask OF for some space for RTAS.
772 * Actually OF has bugs so we just arbitrarily
773 * use memory at the 6MB point.
777 prom_print_hex(rtas_data);
780 prom_rtas = call_prom("open", 1, 1, "/rtas");
782 prom_args.service = "call-method";
785 prom_args.args[0] = "instantiate-rtas";
786 prom_args.args[1] = prom_rtas;
787 prom_args.args[2] = (void *) rtas_data;
790 if (prom_args.args[3] == 0)
791 i = (unsigned int)prom_args.args[4];
793 if ((rtas_entry == -1) || (rtas_entry == 0))
794 prom_print(" failed\n");
796 prom_print(" done\n");
800 * We enter here early on, when the Open Firmware prom is still
801 * handling exceptions and the MMU hash table for us.
804 prom_init(int r3, int r4, prom_entry pp)
808 unsigned long offset = reloc_offset();
818 phys = (unsigned long) &_stext;
820 /* First get a handle for the stdout device */
822 prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
823 if (prom_chosen == (void *)-1)
825 if ((int) call_prom("getprop", 4, 1, prom_chosen,
826 "stdout", &prom_stdout,
827 sizeof(prom_stdout)) <= 0)
830 /* Get the full OF pathname of the stdout device */
831 mem = (unsigned long) klimit + offset;
834 call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
835 of_stdout_device = p;
836 mem += strlen(p) + 1;
838 /* Get the boot device and translate it to a full OF pathname. */
840 l = (int) call_prom("getprop", 4, 1, prom_chosen,
841 "bootpath", p, 1<<20);
843 p[l] = 0; /* should already be null-terminated */
844 bootpath = PTRUNRELOC(p);
848 call_prom("canon", 3, 1, p, d, 1<<20);
849 bootdevice = PTRUNRELOC(d);
850 mem = ALIGNUL(mem + strlen(d) + 1);
853 prom_instantiate_rtas();
857 * Find out how much memory we have and allocate a
858 * suitably-sized hash table.
862 mem = check_display(mem);
864 prom_print("copying OF device tree...");
865 mem = copy_device_tree(mem, mem + (1<<20));
866 prom_print("done\n");
870 klimit = (char *) (mem - offset);
872 node = call_prom("finddevice", 1, 1, "/");
873 rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
874 if (rc > 0 && !strncmp (model, "Pegasos", 7)
875 && strncmp (model, "Pegasos2", 8)) {
876 /* Pegasos 1 has a broken translate method in the OF,
877 * and furthermore the BATs are mapped 1:1 so the phys
878 * address calculated above is correct, so let's use
881 } else if (offset == 0) {
882 /* If we are already running at 0xc0000000, we assume we were
883 * loaded by an OF bootloader which did set a BAT for us.
884 * This breaks OF translate so we force phys to be 0.
886 prom_print("(already at 0xc0000000) phys=0\n");
888 } else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu",
889 &prom_mmu, sizeof(prom_mmu)) <= 0) {
890 prom_print(" no MMU found\n");
891 } else if ((int)call_prom_ret("call-method", 4, 4, result, "translate",
892 prom_mmu, &_stext, 1) != 0) {
893 prom_print(" (translate failed)\n");
895 /* We assume the phys. address size is 3 cells */
896 phys = (unsigned long)result[2];
899 if (prom_disp_node != 0)
900 setup_disp_fake_bi(prom_disp_node);
902 /* Use quiesce call to get OF to shut down any devices it's using */
903 prom_print("Calling quiesce ...\n");
904 call_prom("quiesce", 0, 0);
906 /* Relocate various pointers which will be used once the
907 kernel is running at the address it was linked at. */
908 for (i = 0; i < prom_num_displays; ++i)
909 prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
911 #ifdef CONFIG_SERIAL_CORE_CONSOLE
912 /* Relocate the of stdout for console autodetection */
913 of_stdout_device = PTRUNRELOC(of_stdout_device);
916 prom_print("returning 0x");
917 prom_print_hex(phys);
918 prom_print("from prom_init\n");
925 * early_get_property is used to access the device tree image prepared
926 * by BootX very early on, before the pointers in it have been relocated.
929 early_get_property(unsigned long base, unsigned long node, char *prop)
931 struct device_node *np = (struct device_node *)(base + node);
934 for (pp = np->properties; pp != 0; pp = pp->next) {
935 pp = (struct property *) (base + (unsigned long)pp);
936 if (strcmp((char *)((unsigned long)pp->name + base),
938 return (void *)((unsigned long)pp->value + base);
944 /* Is boot-info compatible ? */
945 #define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
946 #define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
947 #define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
950 bootx_init(unsigned long r4, unsigned long phys)
952 boot_infos_t *bi = (boot_infos_t *) r4;
954 unsigned long ptr, x;
957 boot_infos = PTRUNRELOC(bi);
958 if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
959 bi->logicalDisplayBase = NULL;
961 #ifdef CONFIG_BOOTX_TEXT
965 * Test if boot-info is compatible. Done only in config
966 * CONFIG_BOOTX_TEXT since there is nothing much we can do
967 * with an incompatible version, except display a message
968 * and eventually hang the processor...
970 * I'll try to keep enough of boot-info compatible in the
971 * future to always allow display of this message;
973 if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
974 btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
977 #endif /* CONFIG_BOOTX_TEXT */
979 /* New BootX enters kernel with MMU off, i/os are not allowed
980 here. This hack will have been done by the boostrap anyway.
982 if (bi->version < 4) {
984 * XXX If this is an iMac, turn off the USB controller.
986 model = (char *) early_get_property
987 (r4 + bi->deviceTreeOffset, 4, "model");
989 && (strcmp(model, "iMac,1") == 0
990 || strcmp(model, "PowerMac1,1") == 0)) {
991 out_le32((unsigned *)0x80880008, 1); /* XXX */
995 /* Move klimit to enclose device tree, args, ramdisk, etc... */
996 if (bi->version < 5) {
997 space = bi->deviceTreeOffset + bi->deviceTreeSize;
999 space = bi->ramDisk + bi->ramDiskSize;
1001 space = bi->totalParamsSize;
1002 klimit = PTRUNRELOC((char *) bi + space);
1004 /* New BootX will have flushed all TLBs and enters kernel with
1005 MMU switched OFF, so this should not be useful anymore.
1007 if (bi->version < 4) {
1009 * Touch each page to make sure the PTEs for them
1010 * are in the hash table - the aim is to try to avoid
1011 * getting DSI exceptions while copying the kernel image.
1013 for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
1014 ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
1015 x = *(volatile unsigned long *)ptr;
1018 #ifdef CONFIG_BOOTX_TEXT
1020 * Note that after we call btext_prepare_BAT, we can't do
1021 * prom_draw*, flushscreen or clearscreen until we turn the MMU
1022 * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
1023 * to a virtual address.
1025 btext_prepare_BAT();