aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/prom_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel/prom_init.c')
-rw-r--r--arch/ppc64/kernel/prom_init.c1838
1 files changed, 1838 insertions, 0 deletions
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
new file mode 100644
index 000000000000..8dffa9ae2623
--- /dev/null
+++ b/arch/ppc64/kernel/prom_init.c
@@ -0,0 +1,1838 @@
1/*
2 *
3 *
4 * Procedures for interfacing to Open Firmware.
5 *
6 * Paul Mackerras August 1996.
7 * Copyright (C) 1996 Paul Mackerras.
8 *
9 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
10 * {engebret|bergner}@us.ibm.com
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#undef DEBUG_PROM
19
20#include <stdarg.h>
21#include <linux/config.h>
22#include <linux/kernel.h>
23#include <linux/string.h>
24#include <linux/init.h>
25#include <linux/version.h>
26#include <linux/threads.h>
27#include <linux/spinlock.h>
28#include <linux/types.h>
29#include <linux/pci.h>
30#include <linux/proc_fs.h>
31#include <linux/stringify.h>
32#include <linux/delay.h>
33#include <linux/initrd.h>
34#include <linux/bitops.h>
35#include <asm/prom.h>
36#include <asm/rtas.h>
37#include <asm/abs_addr.h>
38#include <asm/page.h>
39#include <asm/processor.h>
40#include <asm/irq.h>
41#include <asm/io.h>
42#include <asm/smp.h>
43#include <asm/system.h>
44#include <asm/mmu.h>
45#include <asm/pgtable.h>
46#include <asm/pci.h>
47#include <asm/iommu.h>
48#include <asm/bootinfo.h>
49#include <asm/ppcdebug.h>
50#include <asm/btext.h>
51#include <asm/sections.h>
52#include <asm/machdep.h>
53
54#ifdef CONFIG_LOGO_LINUX_CLUT224
55#include <linux/linux_logo.h>
56extern const struct linux_logo logo_linux_clut224;
57#endif
58
59/*
60 * Properties whose value is longer than this get excluded from our
61 * copy of the device tree. This value does need to be big enough to
62 * ensure that we don't lose things like the interrupt-map property
63 * on a PCI-PCI bridge.
64 */
65#define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024)
66
67/*
68 * Eventually bump that one up
69 */
70#define DEVTREE_CHUNK_SIZE 0x100000
71
72/*
73 * This is the size of the local memory reserve map that gets copied
74 * into the boot params passed to the kernel. That size is totally
75 * flexible as the kernel just reads the list until it encounters an
76 * entry with size 0, so it can be changed without breaking binary
77 * compatibility
78 */
79#define MEM_RESERVE_MAP_SIZE 8
80
81/*
82 * prom_init() is called very early on, before the kernel text
83 * and data have been mapped to KERNELBASE. At this point the code
84 * is running at whatever address it has been loaded at, so
85 * references to extern and static variables must be relocated
86 * explicitly. The procedure reloc_offset() returns the address
87 * we're currently running at minus the address we were linked at.
88 * (Note that strings count as static variables.)
89 *
90 * Because OF may have mapped I/O devices into the area starting at
91 * KERNELBASE, particularly on CHRP machines, we can't safely call
92 * OF once the kernel has been mapped to KERNELBASE. Therefore all
93 * OF calls should be done within prom_init(), and prom_init()
94 * and all routines called within it must be careful to relocate
95 * references as necessary.
96 *
97 * Note that the bss is cleared *after* prom_init runs, so we have
98 * to make sure that any static or extern variables it accesses
99 * are put in the data segment.
100 */
101
102
103#define PROM_BUG() do { \
104 prom_printf("kernel BUG at %s line 0x%x!\n", \
105 RELOC(__FILE__), __LINE__); \
106 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
107} while (0)
108
109#ifdef DEBUG_PROM
110#define prom_debug(x...) prom_printf(x)
111#else
112#define prom_debug(x...)
113#endif
114
115
116typedef u32 prom_arg_t;
117
118struct prom_args {
119 u32 service;
120 u32 nargs;
121 u32 nret;
122 prom_arg_t args[10];
123 prom_arg_t *rets; /* Pointer to return values in args[16]. */
124};
125
126struct prom_t {
127 unsigned long entry;
128 ihandle root;
129 ihandle chosen;
130 int cpu;
131 ihandle stdout;
132 ihandle disp_node;
133 struct prom_args args;
134 unsigned long version;
135 unsigned long root_size_cells;
136 unsigned long root_addr_cells;
137};
138
139struct pci_reg_property {
140 struct pci_address addr;
141 u32 size_hi;
142 u32 size_lo;
143};
144
145struct mem_map_entry {
146 u64 base;
147 u64 size;
148};
149
150typedef u32 cell_t;
151
152extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
153
154extern void enter_prom(struct prom_args *args, unsigned long entry);
155extern void copy_and_flush(unsigned long dest, unsigned long src,
156 unsigned long size, unsigned long offset);
157
158extern unsigned long klimit;
159
160/* prom structure */
161static struct prom_t __initdata prom;
162
163#define PROM_SCRATCH_SIZE 256
164
165static char __initdata of_stdout_device[256];
166static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
167
168static unsigned long __initdata dt_header_start;
169static unsigned long __initdata dt_struct_start, dt_struct_end;
170static unsigned long __initdata dt_string_start, dt_string_end;
171
172static unsigned long __initdata prom_initrd_start, prom_initrd_end;
173
174static int __initdata iommu_force_on;
175static int __initdata ppc64_iommu_off;
176static int __initdata of_platform;
177
178static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
179
180static unsigned long __initdata prom_memory_limit;
181static unsigned long __initdata prom_tce_alloc_start;
182static unsigned long __initdata prom_tce_alloc_end;
183
184static unsigned long __initdata alloc_top;
185static unsigned long __initdata alloc_top_high;
186static unsigned long __initdata alloc_bottom;
187static unsigned long __initdata rmo_top;
188static unsigned long __initdata ram_top;
189
190static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
191static int __initdata mem_reserve_cnt;
192
193static cell_t __initdata regbuf[1024];
194
195
196#define MAX_CPU_THREADS 2
197
198/* TO GO */
199#ifdef CONFIG_HMT
200struct {
201 unsigned int pir;
202 unsigned int threadid;
203} hmt_thread_data[NR_CPUS];
204#endif /* CONFIG_HMT */
205
206/*
207 * This are used in calls to call_prom. The 4th and following
208 * arguments to call_prom should be 32-bit values. 64 bit values
209 * are truncated to 32 bits (and fortunately don't get interpreted
210 * as two arguments).
211 */
212#define ADDR(x) (u32) ((unsigned long)(x) - offset)
213
214/* 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
216 * mode when we do. We switch back to 64b mode upon return.
217 */
218
219#define PROM_ERROR (-1)
220
221static int __init call_prom(const char *service, int nargs, int nret, ...)
222{
223 int i;
224 unsigned long offset = reloc_offset();
225 struct prom_t *_prom = PTRRELOC(&prom);
226 va_list list;
227
228 _prom->args.service = ADDR(service);
229 _prom->args.nargs = nargs;
230 _prom->args.nret = nret;
231 _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
232
233 va_start(list, nret);
234 for (i=0; i < nargs; i++)
235 _prom->args.args[i] = va_arg(list, prom_arg_t);
236 va_end(list);
237
238 for (i=0; i < nret ;i++)
239 _prom->args.rets[i] = 0;
240
241 enter_prom(&_prom->args, _prom->entry);
242
243 return (nret > 0) ? _prom->args.rets[0] : 0;
244}
245
246
247static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
248 unsigned long align)
249{
250 return (unsigned int)call_prom("claim", 3, 1,
251 (prom_arg_t)virt, (prom_arg_t)size,
252 (prom_arg_t)align);
253}
254
255static void __init prom_print(const char *msg)
256{
257 const char *p, *q;
258 unsigned long offset = reloc_offset();
259 struct prom_t *_prom = PTRRELOC(&prom);
260
261 if (_prom->stdout == 0)
262 return;
263
264 for (p = msg; *p != 0; p = q) {
265 for (q = p; *q != 0 && *q != '\n'; ++q)
266 ;
267 if (q > p)
268 call_prom("write", 3, 1, _prom->stdout, p, q - p);
269 if (*q == 0)
270 break;
271 ++q;
272 call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);
273 }
274}
275
276
277static void __init prom_print_hex(unsigned long val)
278{
279 unsigned long offset = reloc_offset();
280 int i, nibbles = sizeof(val)*2;
281 char buf[sizeof(val)*2+1];
282 struct prom_t *_prom = PTRRELOC(&prom);
283
284 for (i = nibbles-1; i >= 0; i--) {
285 buf[i] = (val & 0xf) + '0';
286 if (buf[i] > '9')
287 buf[i] += ('a'-'0'-10);
288 val >>= 4;
289 }
290 buf[nibbles] = '\0';
291 call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
292}
293
294
295static void __init prom_printf(const char *format, ...)
296{
297 unsigned long offset = reloc_offset();
298 const char *p, *q, *s;
299 va_list args;
300 unsigned long v;
301 struct prom_t *_prom = PTRRELOC(&prom);
302
303 va_start(args, format);
304 for (p = PTRRELOC(format); *p != 0; p = q) {
305 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
306 ;
307 if (q > p)
308 call_prom("write", 3, 1, _prom->stdout, p, q - p);
309 if (*q == 0)
310 break;
311 if (*q == '\n') {
312 ++q;
313 call_prom("write", 3, 1, _prom->stdout,
314 ADDR("\r\n"), 2);
315 continue;
316 }
317 ++q;
318 if (*q == 0)
319 break;
320 switch (*q) {
321 case 's':
322 ++q;
323 s = va_arg(args, const char *);
324 prom_print(s);
325 break;
326 case 'x':
327 ++q;
328 v = va_arg(args, unsigned long);
329 prom_print_hex(v);
330 break;
331 }
332 }
333}
334
335
336static void __init __attribute__((noreturn)) prom_panic(const char *reason)
337{
338 unsigned long offset = reloc_offset();
339
340 prom_print(PTRRELOC(reason));
341 /* ToDo: should put up an SRC here */
342 call_prom("exit", 0, 0);
343
344 for (;;) /* should never get here */
345 ;
346}
347
348
349static int __init prom_next_node(phandle *nodep)
350{
351 phandle node;
352
353 if ((node = *nodep) != 0
354 && (*nodep = call_prom("child", 1, 1, node)) != 0)
355 return 1;
356 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
357 return 1;
358 for (;;) {
359 if ((node = call_prom("parent", 1, 1, node)) == 0)
360 return 0;
361 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
362 return 1;
363 }
364}
365
366static int __init prom_getprop(phandle node, const char *pname,
367 void *value, size_t valuelen)
368{
369 unsigned long offset = reloc_offset();
370
371 return call_prom("getprop", 4, 1, node, ADDR(pname),
372 (u32)(unsigned long) value, (u32) valuelen);
373}
374
375static int __init prom_getproplen(phandle node, const char *pname)
376{
377 unsigned long offset = reloc_offset();
378
379 return call_prom("getproplen", 2, 1, node, ADDR(pname));
380}
381
382static int __init prom_setprop(phandle node, const char *pname,
383 void *value, size_t valuelen)
384{
385 unsigned long offset = reloc_offset();
386
387 return call_prom("setprop", 4, 1, node, ADDR(pname),
388 (u32)(unsigned long) value, (u32) valuelen);
389}
390
391/* We can't use the standard versions because of RELOC headaches. */
392#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
393 || ('a' <= (c) && (c) <= 'f') \
394 || ('A' <= (c) && (c) <= 'F'))
395
396#define isdigit(c) ('0' <= (c) && (c) <= '9')
397#define islower(c) ('a' <= (c) && (c) <= 'z')
398#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
399
400unsigned long prom_strtoul(const char *cp, const char **endp)
401{
402 unsigned long result = 0, base = 10, value;
403
404 if (*cp == '0') {
405 base = 8;
406 cp++;
407 if (toupper(*cp) == 'X') {
408 cp++;
409 base = 16;
410 }
411 }
412
413 while (isxdigit(*cp) &&
414 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
415 result = result * base + value;
416 cp++;
417 }
418
419 if (endp)
420 *endp = cp;
421
422 return result;
423}
424
425unsigned long prom_memparse(const char *ptr, const char **retptr)
426{
427 unsigned long ret = prom_strtoul(ptr, retptr);
428 int shift = 0;
429
430 /*
431 * We can't use a switch here because GCC *may* generate a
432 * jump table which won't work, because we're not running at
433 * the address we're linked at.
434 */
435 if ('G' == **retptr || 'g' == **retptr)
436 shift = 30;
437
438 if ('M' == **retptr || 'm' == **retptr)
439 shift = 20;
440
441 if ('K' == **retptr || 'k' == **retptr)
442 shift = 10;
443
444 if (shift) {
445 ret <<= shift;
446 (*retptr)++;
447 }
448
449 return ret;
450}
451
452/*
453 * Early parsing of the command line passed to the kernel, used for
454 * "mem=x" and the options that affect the iommu
455 */
456static void __init early_cmdline_parse(void)
457{
458 unsigned long offset = reloc_offset();
459 struct prom_t *_prom = PTRRELOC(&prom);
460 char *opt, *p;
461 int l = 0;
462
463 RELOC(prom_cmd_line[0]) = 0;
464 p = RELOC(prom_cmd_line);
465 if ((long)_prom->chosen > 0)
466 l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
467#ifdef CONFIG_CMDLINE
468 if (l == 0) /* dbl check */
469 strlcpy(RELOC(prom_cmd_line),
470 RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
471#endif /* CONFIG_CMDLINE */
472 prom_printf("command line: %s\n", RELOC(prom_cmd_line));
473
474 opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));
475 if (opt) {
476 prom_printf("iommu opt is: %s\n", opt);
477 opt += 6;
478 while (*opt && *opt == ' ')
479 opt++;
480 if (!strncmp(opt, RELOC("off"), 3))
481 RELOC(ppc64_iommu_off) = 1;
482 else if (!strncmp(opt, RELOC("force"), 5))
483 RELOC(iommu_force_on) = 1;
484 }
485
486 opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
487 if (opt) {
488 opt += 4;
489 RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
490 /* Align to 16 MB == size of large page */
491 RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
492 }
493}
494
495/*
496 * Memory allocation strategy... our layout is normally:
497 *
498 * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd
499 * might end up beeing before the kernel though. We assume this won't override
500 * the final kernel at 0, we have no provision to handle that in this version,
501 * but it should hopefully never happen.
502 *
503 * alloc_top is set to the top of RMO, eventually shrink down if the TCEs overlap
504 * alloc_bottom is set to the top of kernel/initrd
505 *
506 * from there, allocations are done that way : rtas is allocated topmost, and
507 * the device-tree is allocated from the bottom. We try to grow the device-tree
508 * allocation as we progress. If we can't, then we fail, we don't currently have
509 * a facility to restart elsewhere, but that shouldn't be necessary neither
510 *
511 * Note that calls to reserve_mem have to be done explicitely, memory allocated
512 * with either alloc_up or alloc_down isn't automatically reserved.
513 */
514
515
516/*
517 * Allocates memory in the RMO upward from the kernel/initrd
518 *
519 * When align is 0, this is a special case, it means to allocate in place
520 * at the current location of alloc_bottom or fail (that is basically
521 * extending the previous allocation). Used for the device-tree flattening
522 */
523static unsigned long __init alloc_up(unsigned long size, unsigned long align)
524{
525 unsigned long offset = reloc_offset();
526 unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align);
527 unsigned long addr = 0;
528
529 prom_debug("alloc_up(%x, %x)\n", size, align);
530 if (RELOC(ram_top) == 0)
531 prom_panic("alloc_up() called with mem not initialized\n");
532
533 if (align)
534 base = _ALIGN_UP(RELOC(alloc_bottom), align);
535 else
536 base = RELOC(alloc_bottom);
537
538 for(; (base + size) <= RELOC(alloc_top);
539 base = _ALIGN_UP(base + 0x100000, align)) {
540 prom_debug(" trying: 0x%x\n\r", base);
541 addr = (unsigned long)prom_claim(base, size, 0);
542 if ((int)addr != PROM_ERROR)
543 break;
544 addr = 0;
545 if (align == 0)
546 break;
547 }
548 if (addr == 0)
549 return 0;
550 RELOC(alloc_bottom) = addr;
551
552 prom_debug(" -> %x\n", addr);
553 prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom));
554 prom_debug(" alloc_top : %x\n", RELOC(alloc_top));
555 prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
556 prom_debug(" rmo_top : %x\n", RELOC(rmo_top));
557 prom_debug(" ram_top : %x\n", RELOC(ram_top));
558
559 return addr;
560}
561
562/*
563 * Allocates memory downard, either from top of RMO, or if highmem
564 * is set, from the top of RAM. Note that this one doesn't handle
565 * failures. In does claim memory if highmem is not set.
566 */
567static unsigned long __init alloc_down(unsigned long size, unsigned long align,
568 int highmem)
569{
570 unsigned long offset = reloc_offset();
571 unsigned long base, addr = 0;
572
573 prom_debug("alloc_down(%x, %x, %s)\n", size, align,
574 highmem ? RELOC("(high)") : RELOC("(low)"));
575 if (RELOC(ram_top) == 0)
576 prom_panic("alloc_down() called with mem not initialized\n");
577
578 if (highmem) {
579 /* Carve out storage for the TCE table. */
580 addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align);
581 if (addr <= RELOC(alloc_bottom))
582 return 0;
583 else {
584 /* Will we bump into the RMO ? If yes, check out that we
585 * didn't overlap existing allocations there, if we did,
586 * we are dead, we must be the first in town !
587 */
588 if (addr < RELOC(rmo_top)) {
589 /* Good, we are first */
590 if (RELOC(alloc_top) == RELOC(rmo_top))
591 RELOC(alloc_top) = RELOC(rmo_top) = addr;
592 else
593 return 0;
594 }
595 RELOC(alloc_top_high) = addr;
596 }
597 goto bail;
598 }
599
600 base = _ALIGN_DOWN(RELOC(alloc_top) - size, align);
601 for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) {
602 prom_debug(" trying: 0x%x\n\r", base);
603 addr = (unsigned long)prom_claim(base, size, 0);
604 if ((int)addr != PROM_ERROR)
605 break;
606 addr = 0;
607 }
608 if (addr == 0)
609 return 0;
610 RELOC(alloc_top) = addr;
611
612 bail:
613 prom_debug(" -> %x\n", addr);
614 prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom));
615 prom_debug(" alloc_top : %x\n", RELOC(alloc_top));
616 prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
617 prom_debug(" rmo_top : %x\n", RELOC(rmo_top));
618 prom_debug(" ram_top : %x\n", RELOC(ram_top));
619
620 return addr;
621}
622
623/*
624 * Parse a "reg" cell
625 */
626static unsigned long __init prom_next_cell(int s, cell_t **cellp)
627{
628 cell_t *p = *cellp;
629 unsigned long r = 0;
630
631 /* Ignore more than 2 cells */
632 while (s > 2) {
633 p++;
634 s--;
635 }
636 while (s) {
637 r <<= 32;
638 r |= *(p++);
639 s--;
640 }
641
642 *cellp = p;
643 return r;
644}
645
646/*
647 * Very dumb function for adding to the memory reserve list, but
648 * we don't need anything smarter at this point
649 *
650 * XXX Eventually check for collisions. They should NEVER happen
651 * if problems seem to show up, it would be a good start to track
652 * them down.
653 */
654static void reserve_mem(unsigned long base, unsigned long size)
655{
656 unsigned long offset = reloc_offset();
657 unsigned long top = base + size;
658 unsigned long cnt = RELOC(mem_reserve_cnt);
659
660 if (size == 0)
661 return;
662
663 /* We need to always keep one empty entry so that we
664 * have our terminator with "size" set to 0 since we are
665 * dumb and just copy this entire array to the boot params
666 */
667 base = _ALIGN_DOWN(base, PAGE_SIZE);
668 top = _ALIGN_UP(top, PAGE_SIZE);
669 size = top - base;
670
671 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
672 prom_panic("Memory reserve map exhausted !\n");
673 RELOC(mem_reserve_map)[cnt].base = base;
674 RELOC(mem_reserve_map)[cnt].size = size;
675 RELOC(mem_reserve_cnt) = cnt + 1;
676}
677
678/*
679 * Initialize memory allocation mecanism, parse "memory" nodes and
680 * obtain that way the top of memory and RMO to setup out local allocator
681 */
682static void __init prom_init_mem(void)
683{
684 phandle node;
685 char *path, type[64];
686 unsigned int plen;
687 cell_t *p, *endp;
688 unsigned long offset = reloc_offset();
689 struct prom_t *_prom = PTRRELOC(&prom);
690
691 /*
692 * We iterate the memory nodes to find
693 * 1) top of RMO (first node)
694 * 2) top of memory
695 */
696 prom_debug("root_addr_cells: %x\n", (long)_prom->root_addr_cells);
697 prom_debug("root_size_cells: %x\n", (long)_prom->root_size_cells);
698
699 prom_debug("scanning memory:\n");
700 path = RELOC(prom_scratch);
701
702 for (node = 0; prom_next_node(&node); ) {
703 type[0] = 0;
704 prom_getprop(node, "device_type", type, sizeof(type));
705
706 if (strcmp(type, RELOC("memory")))
707 continue;
708
709 plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf));
710 if (plen > sizeof(regbuf)) {
711 prom_printf("memory node too large for buffer !\n");
712 plen = sizeof(regbuf);
713 }
714 p = RELOC(regbuf);
715 endp = p + (plen / sizeof(cell_t));
716
717#ifdef DEBUG_PROM
718 memset(path, 0, PROM_SCRATCH_SIZE);
719 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
720 prom_debug(" node %s :\n", path);
721#endif /* DEBUG_PROM */
722
723 while ((endp - p) >= (_prom->root_addr_cells + _prom->root_size_cells)) {
724 unsigned long base, size;
725
726 base = prom_next_cell(_prom->root_addr_cells, &p);
727 size = prom_next_cell(_prom->root_size_cells, &p);
728
729 if (size == 0)
730 continue;
731 prom_debug(" %x %x\n", base, size);
732 if (base == 0)
733 RELOC(rmo_top) = size;
734 if ((base + size) > RELOC(ram_top))
735 RELOC(ram_top) = base + size;
736 }
737 }
738
739 RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000);
740
741 /* Check if we have an initrd after the kernel, if we do move our bottom
742 * point to after it
743 */
744 if (RELOC(prom_initrd_start)) {
745 if (RELOC(prom_initrd_end) > RELOC(alloc_bottom))
746 RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
747 }
748
749 /*
750 * If prom_memory_limit is set we reduce the upper limits *except* for
751 * alloc_top_high. This must be the real top of RAM so we can put
752 * TCE's up there.
753 */
754
755 RELOC(alloc_top_high) = RELOC(ram_top);
756
757 if (RELOC(prom_memory_limit)) {
758 if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
759 prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
760 RELOC(prom_memory_limit));
761 RELOC(prom_memory_limit) = 0;
762 } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
763 prom_printf("Ignoring mem=%x >= ram_top.\n",
764 RELOC(prom_memory_limit));
765 RELOC(prom_memory_limit) = 0;
766 } else {
767 RELOC(ram_top) = RELOC(prom_memory_limit);
768 RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
769 }
770 }
771
772 /*
773 * Setup our top alloc point, that is top of RMO or top of
774 * segment 0 when running non-LPAR.
775 */
776 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
777 RELOC(alloc_top) = RELOC(rmo_top);
778 else
779 RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
780
781 prom_printf("memory layout at init:\n");
782 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
783 prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
784 prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
785 prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
786 prom_printf(" rmo_top : %x\n", RELOC(rmo_top));
787 prom_printf(" ram_top : %x\n", RELOC(ram_top));
788}
789
790
791/*
792 * Allocate room for and instanciate RTAS
793 */
794static void __init prom_instantiate_rtas(void)
795{
796 unsigned long offset = reloc_offset();
797 struct prom_t *_prom = PTRRELOC(&prom);
798 phandle prom_rtas, rtas_node;
799 u32 base, entry = 0;
800 u32 size = 0;
801
802 prom_debug("prom_instantiate_rtas: start...\n");
803
804 prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
805 prom_debug("prom_rtas: %x\n", prom_rtas);
806 if (prom_rtas == (phandle) -1)
807 return;
808
809 prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
810 if (size == 0)
811 return;
812
813 base = alloc_down(size, PAGE_SIZE, 0);
814 if (base == 0) {
815 prom_printf("RTAS allocation failed !\n");
816 return;
817 }
818 prom_printf("instantiating rtas at 0x%x", base);
819
820 rtas_node = call_prom("open", 1, 1, ADDR("/rtas"));
821 prom_printf("...");
822
823 if (call_prom("call-method", 3, 2,
824 ADDR("instantiate-rtas"),
825 rtas_node, base) != PROM_ERROR) {
826 entry = (long)_prom->args.rets[1];
827 }
828 if (entry == 0) {
829 prom_printf(" failed\n");
830 return;
831 }
832 prom_printf(" done\n");
833
834 reserve_mem(base, size);
835
836 prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base));
837 prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry));
838
839 prom_debug("rtas base = 0x%x\n", base);
840 prom_debug("rtas entry = 0x%x\n", entry);
841 prom_debug("rtas size = 0x%x\n", (long)size);
842
843 prom_debug("prom_instantiate_rtas: end...\n");
844}
845
846
847/*
848 * Allocate room for and initialize TCE tables
849 */
850static void __init prom_initialize_tce_table(void)
851{
852 phandle node;
853 ihandle phb_node;
854 unsigned long offset = reloc_offset();
855 char compatible[64], type[64], model[64];
856 char *path = RELOC(prom_scratch);
857 u64 base, align;
858 u32 minalign, minsize;
859 u64 tce_entry, *tce_entryp;
860 u64 local_alloc_top, local_alloc_bottom;
861 u64 i;
862
863 if (RELOC(ppc64_iommu_off))
864 return;
865
866 prom_debug("starting prom_initialize_tce_table\n");
867
868 /* Cache current top of allocs so we reserve a single block */
869 local_alloc_top = RELOC(alloc_top_high);
870 local_alloc_bottom = local_alloc_top;
871
872 /* Search all nodes looking for PHBs. */
873 for (node = 0; prom_next_node(&node); ) {
874 compatible[0] = 0;
875 type[0] = 0;
876 model[0] = 0;
877 prom_getprop(node, "compatible",
878 compatible, sizeof(compatible));
879 prom_getprop(node, "device_type", type, sizeof(type));
880 prom_getprop(node, "model", model, sizeof(model));
881
882 if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL))
883 continue;
884
885 /* Keep the old logic in tack to avoid regression. */
886 if (compatible[0] != 0) {
887 if ((strstr(compatible, RELOC("python")) == NULL) &&
888 (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
889 (strstr(compatible, RELOC("Winnipeg")) == NULL))
890 continue;
891 } else if (model[0] != 0) {
892 if ((strstr(model, RELOC("ython")) == NULL) &&
893 (strstr(model, RELOC("peedwagon")) == NULL) &&
894 (strstr(model, RELOC("innipeg")) == NULL))
895 continue;
896 }
897
898 if (prom_getprop(node, "tce-table-minalign", &minalign,
899 sizeof(minalign)) == PROM_ERROR)
900 minalign = 0;
901 if (prom_getprop(node, "tce-table-minsize", &minsize,
902 sizeof(minsize)) == PROM_ERROR)
903 minsize = 4UL << 20;
904
905 /*
906 * Even though we read what OF wants, we just set the table
907 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
908 * By doing this, we avoid the pitfalls of trying to DMA to
909 * MMIO space and the DMA alias hole.
910 *
911 * On POWER4, firmware sets the TCE region by assuming
912 * each TCE table is 8MB. Using this memory for anything
913 * else will impact performance, so we always allocate 8MB.
914 * Anton
915 */
916 if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
917 minsize = 8UL << 20;
918 else
919 minsize = 4UL << 20;
920
921 /* Align to the greater of the align or size */
922 align = max(minalign, minsize);
923 base = alloc_down(minsize, align, 1);
924 if (base == 0)
925 prom_panic("ERROR, cannot find space for TCE table.\n");
926 if (base < local_alloc_bottom)
927 local_alloc_bottom = base;
928
929 /* Save away the TCE table attributes for later use. */
930 prom_setprop(node, "linux,tce-base", &base, sizeof(base));
931 prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
932
933 /* It seems OF doesn't null-terminate the path :-( */
934 memset(path, 0, sizeof(path));
935 /* Call OF to setup the TCE hardware */
936 if (call_prom("package-to-path", 3, 1, node,
937 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
938 prom_printf("package-to-path failed\n");
939 }
940
941 prom_debug("TCE table: %s\n", path);
942 prom_debug("\tnode = 0x%x\n", node);
943 prom_debug("\tbase = 0x%x\n", base);
944 prom_debug("\tsize = 0x%x\n", minsize);
945
946 /* Initialize the table to have a one-to-one mapping
947 * over the allocated size.
948 */
949 tce_entryp = (unsigned long *)base;
950 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
951 tce_entry = (i << PAGE_SHIFT);
952 tce_entry |= 0x3;
953 *tce_entryp = tce_entry;
954 }
955
956 prom_printf("opening PHB %s", path);
957 phb_node = call_prom("open", 1, 1, path);
958 if ( (long)phb_node <= 0)
959 prom_printf("... failed\n");
960 else
961 prom_printf("... done\n");
962
963 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
964 phb_node, -1, minsize,
965 (u32) base, (u32) (base >> 32));
966 call_prom("close", 1, 0, phb_node);
967 }
968
969 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
970
971 if (RELOC(prom_memory_limit)) {
972 /*
973 * We align the start to a 16MB boundary so we can map the TCE area
974 * using large pages if possible. The end should be the top of RAM
975 * so no need to align it.
976 */
977 RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000);
978 RELOC(prom_tce_alloc_end) = local_alloc_top;
979 }
980
981 /* Flag the first invalid entry */
982 prom_debug("ending prom_initialize_tce_table\n");
983}
984
985/*
986 * With CHRP SMP we need to use the OF to start the other
987 * processors so we can't wait until smp_boot_cpus (the OF is
988 * trashed by then) so we have to put the processors into
989 * a holding pattern controlled by the kernel (not OF) before
990 * we destroy the OF.
991 *
992 * This uses a chunk of low memory, puts some holding pattern
993 * code there and sends the other processors off to there until
994 * smp_boot_cpus tells them to do something. The holding pattern
995 * checks that address until its cpu # is there, when it is that
996 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
997 * of setting those values.
998 *
999 * We also use physical address 0x4 here to tell when a cpu
1000 * is in its holding pattern code.
1001 *
1002 * Fixup comment... DRENG / PPPBBB - Peter
1003 *
1004 * -- Cort
1005 */
1006static void __init prom_hold_cpus(void)
1007{
1008 unsigned long i;
1009 unsigned int reg;
1010 phandle node;
1011 unsigned long offset = reloc_offset();
1012 char type[64];
1013 int cpuid = 0;
1014 unsigned int interrupt_server[MAX_CPU_THREADS];
1015 unsigned int cpu_threads, hw_cpu_num;
1016 int propsize;
1017 extern void __secondary_hold(void);
1018 extern unsigned long __secondary_hold_spinloop;
1019 extern unsigned long __secondary_hold_acknowledge;
1020 unsigned long *spinloop
1021 = (void *)virt_to_abs(&__secondary_hold_spinloop);
1022 unsigned long *acknowledge
1023 = (void *)virt_to_abs(&__secondary_hold_acknowledge);
1024 unsigned long secondary_hold
1025 = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
1026 struct prom_t *_prom = PTRRELOC(&prom);
1027
1028 prom_debug("prom_hold_cpus: start...\n");
1029 prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
1030 prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
1031 prom_debug(" 1) acknowledge = 0x%x\n",
1032 (unsigned long)acknowledge);
1033 prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge);
1034 prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold);
1035
1036 /* Set the common spinloop variable, so all of the secondary cpus
1037 * will block when they are awakened from their OF spinloop.
1038 * This must occur for both SMP and non SMP kernels, since OF will
1039 * be trashed when we move the kernel.
1040 */
1041 *spinloop = 0;
1042
1043#ifdef CONFIG_HMT
1044 for (i=0; i < NR_CPUS; i++) {
1045 RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
1046 }
1047#endif
1048 /* look for cpus */
1049 for (node = 0; prom_next_node(&node); ) {
1050 type[0] = 0;
1051 prom_getprop(node, "device_type", type, sizeof(type));
1052 if (strcmp(type, RELOC("cpu")) != 0)
1053 continue;
1054
1055 /* Skip non-configured cpus. */
1056 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
1057 if (strcmp(type, RELOC("okay")) != 0)
1058 continue;
1059
1060 reg = -1;
1061 prom_getprop(node, "reg", &reg, sizeof(reg));
1062
1063 prom_debug("\ncpuid = 0x%x\n", cpuid);
1064 prom_debug("cpu hw idx = 0x%x\n", reg);
1065
1066 /* Init the acknowledge var which will be reset by
1067 * the secondary cpu when it awakens from its OF
1068 * spinloop.
1069 */
1070 *acknowledge = (unsigned long)-1;
1071
1072 propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
1073 &interrupt_server,
1074 sizeof(interrupt_server));
1075 if (propsize < 0) {
1076 /* no property. old hardware has no SMT */
1077 cpu_threads = 1;
1078 interrupt_server[0] = reg; /* fake it with phys id */
1079 } else {
1080 /* We have a threaded processor */
1081 cpu_threads = propsize / sizeof(u32);
1082 if (cpu_threads > MAX_CPU_THREADS) {
1083 prom_printf("SMT: too many threads!\n"
1084 "SMT: found %x, max is %x\n",
1085 cpu_threads, MAX_CPU_THREADS);
1086 cpu_threads = 1; /* ToDo: panic? */
1087 }
1088 }
1089
1090 hw_cpu_num = interrupt_server[0];
1091 if (hw_cpu_num != _prom->cpu) {
1092 /* Primary Thread of non-boot cpu */
1093 prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);
1094 call_prom("start-cpu", 3, 0, node,
1095 secondary_hold, reg);
1096
1097 for ( i = 0 ; (i < 100000000) &&
1098 (*acknowledge == ((unsigned long)-1)); i++ )
1099 mb();
1100
1101 if (*acknowledge == reg) {
1102 prom_printf("done\n");
1103 /* We have to get every CPU out of OF,
1104 * even if we never start it. */
1105 if (cpuid >= NR_CPUS)
1106 goto next;
1107 } else {
1108 prom_printf("failed: %x\n", *acknowledge);
1109 }
1110 }
1111#ifdef CONFIG_SMP
1112 else
1113 prom_printf("%x : boot cpu %x\n", cpuid, reg);
1114#endif
1115next:
1116#ifdef CONFIG_SMP
1117 /* Init paca for secondary threads. They start later. */
1118 for (i=1; i < cpu_threads; i++) {
1119 cpuid++;
1120 if (cpuid >= NR_CPUS)
1121 continue;
1122 }
1123#endif /* CONFIG_SMP */
1124 cpuid++;
1125 }
1126#ifdef CONFIG_HMT
1127 /* Only enable HMT on processors that provide support. */
1128 if (__is_processor(PV_PULSAR) ||
1129 __is_processor(PV_ICESTAR) ||
1130 __is_processor(PV_SSTAR)) {
1131 prom_printf(" starting secondary threads\n");
1132
1133 for (i = 0; i < NR_CPUS; i += 2) {
1134 if (!cpu_online(i))
1135 continue;
1136
1137 if (i == 0) {
1138 unsigned long pir = mfspr(SPRN_PIR);
1139 if (__is_processor(PV_PULSAR)) {
1140 RELOC(hmt_thread_data)[i].pir =
1141 pir & 0x1f;
1142 } else {
1143 RELOC(hmt_thread_data)[i].pir =
1144 pir & 0x3ff;
1145 }
1146 }
1147 }
1148 } else {
1149 prom_printf("Processor is not HMT capable\n");
1150 }
1151#endif
1152
1153 if (cpuid > NR_CPUS)
1154 prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
1155 ") exceeded: ignoring extras\n");
1156
1157 prom_debug("prom_hold_cpus: end...\n");
1158}
1159
1160
1161static void __init prom_init_client_services(unsigned long pp)
1162{
1163 unsigned long offset = reloc_offset();
1164 struct prom_t *_prom = PTRRELOC(&prom);
1165
1166 /* Get a handle to the prom entry point before anything else */
1167 _prom->entry = pp;
1168
1169 /* Init default value for phys size */
1170 _prom->root_size_cells = 1;
1171 _prom->root_addr_cells = 2;
1172
1173 /* get a handle for the stdout device */
1174 _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1175 if ((long)_prom->chosen <= 0)
1176 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1177
1178 /* get device tree root */
1179 _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
1180 if ((long)_prom->root <= 0)
1181 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
1182}
1183
1184static void __init prom_init_stdout(void)
1185{
1186 unsigned long offset = reloc_offset();
1187 struct prom_t *_prom = PTRRELOC(&prom);
1188 char *path = RELOC(of_stdout_device);
1189 char type[16];
1190 u32 val;
1191
1192 if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)
1193 prom_panic("cannot find stdout");
1194
1195 _prom->stdout = val;
1196
1197 /* Get the full OF pathname of the stdout device */
1198 memset(path, 0, 256);
1199 call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
1200 val = call_prom("instance-to-package", 1, 1, _prom->stdout);
1201 prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));
1202 prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
1203 prom_setprop(_prom->chosen, "linux,stdout-path",
1204 RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);
1205
1206 /* If it's a display, note it */
1207 memset(type, 0, sizeof(type));
1208 prom_getprop(val, "device_type", type, sizeof(type));
1209 if (strcmp(type, RELOC("display")) == 0) {
1210 _prom->disp_node = val;
1211 prom_setprop(val, "linux,boot-display", NULL, 0);
1212 }
1213}
1214
1215static void __init prom_close_stdin(void)
1216{
1217 unsigned long offset = reloc_offset();
1218 struct prom_t *_prom = PTRRELOC(&prom);
1219 ihandle val;
1220
1221 if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
1222 call_prom("close", 1, 0, val);
1223}
1224
1225static int __init prom_find_machine_type(void)
1226{
1227 unsigned long offset = reloc_offset();
1228 struct prom_t *_prom = PTRRELOC(&prom);
1229 char compat[256];
1230 int len, i = 0;
1231 phandle rtas;
1232
1233 len = prom_getprop(_prom->root, "compatible",
1234 compat, sizeof(compat)-1);
1235 if (len > 0) {
1236 compat[len] = 0;
1237 while (i < len) {
1238 char *p = &compat[i];
1239 int sl = strlen(p);
1240 if (sl == 0)
1241 break;
1242 if (strstr(p, RELOC("Power Macintosh")) ||
1243 strstr(p, RELOC("MacRISC4")))
1244 return PLATFORM_POWERMAC;
1245 if (strstr(p, RELOC("Momentum,Maple")))
1246 return PLATFORM_MAPLE;
1247 i += sl + 1;
1248 }
1249 }
1250 /* Default to pSeries. We need to know if we are running LPAR */
1251 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1252 if (rtas != (phandle) -1) {
1253 unsigned long x;
1254 x = prom_getproplen(rtas, "ibm,hypertas-functions");
1255 if (x != PROM_ERROR) {
1256 prom_printf("Hypertas detected, assuming LPAR !\n");
1257 return PLATFORM_PSERIES_LPAR;
1258 }
1259 }
1260 return PLATFORM_PSERIES;
1261}
1262
1263static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
1264{
1265 unsigned long offset = reloc_offset();
1266
1267 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
1268}
1269
1270/*
1271 * If we have a display that we don't know how to drive,
1272 * we will want to try to execute OF's open method for it
1273 * later. However, OF will probably fall over if we do that
1274 * we've taken over the MMU.
1275 * So we check whether we will need to open the display,
1276 * and if so, open it now.
1277 */
1278static void __init prom_check_displays(void)
1279{
1280 unsigned long offset = reloc_offset();
1281 struct prom_t *_prom = PTRRELOC(&prom);
1282 char type[16], *path;
1283 phandle node;
1284 ihandle ih;
1285 int i;
1286
1287 static unsigned char default_colors[] = {
1288 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0xaa,
1290 0x00, 0xaa, 0x00,
1291 0x00, 0xaa, 0xaa,
1292 0xaa, 0x00, 0x00,
1293 0xaa, 0x00, 0xaa,
1294 0xaa, 0xaa, 0x00,
1295 0xaa, 0xaa, 0xaa,
1296 0x55, 0x55, 0x55,
1297 0x55, 0x55, 0xff,
1298 0x55, 0xff, 0x55,
1299 0x55, 0xff, 0xff,
1300 0xff, 0x55, 0x55,
1301 0xff, 0x55, 0xff,
1302 0xff, 0xff, 0x55,
1303 0xff, 0xff, 0xff
1304 };
1305 const unsigned char *clut;
1306
1307 prom_printf("Looking for displays\n");
1308 for (node = 0; prom_next_node(&node); ) {
1309 memset(type, 0, sizeof(type));
1310 prom_getprop(node, "device_type", type, sizeof(type));
1311 if (strcmp(type, RELOC("display")) != 0)
1312 continue;
1313
1314 /* It seems OF doesn't null-terminate the path :-( */
1315 path = RELOC(prom_scratch);
1316 memset(path, 0, PROM_SCRATCH_SIZE);
1317
1318 /*
1319 * leave some room at the end of the path for appending extra
1320 * arguments
1321 */
1322 if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)
1323 continue;
1324 prom_printf("found display : %s, opening ... ", path);
1325
1326 ih = call_prom("open", 1, 1, path);
1327 if (ih == (ihandle)0 || ih == (ihandle)-1) {
1328 prom_printf("failed\n");
1329 continue;
1330 }
1331
1332 /* Success */
1333 prom_printf("done\n");
1334 prom_setprop(node, "linux,opened", NULL, 0);
1335
1336 /*
1337 * stdout wasn't a display node, pick the first we can find
1338 * for btext
1339 */
1340 if (_prom->disp_node == 0)
1341 _prom->disp_node = node;
1342
1343 /* Setup a useable color table when the appropriate
1344 * method is available. Should update this to set-colors */
1345 clut = RELOC(default_colors);
1346 for (i = 0; i < 32; i++, clut += 3)
1347 if (prom_set_color(ih, i, clut[0], clut[1],
1348 clut[2]) != 0)
1349 break;
1350
1351#ifdef CONFIG_LOGO_LINUX_CLUT224
1352 clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
1353 for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
1354 if (prom_set_color(ih, i + 32, clut[0], clut[1],
1355 clut[2]) != 0)
1356 break;
1357#endif /* CONFIG_LOGO_LINUX_CLUT224 */
1358 }
1359}
1360
1361
1362/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
1363static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
1364 unsigned long needed, unsigned long align)
1365{
1366 unsigned long offset = reloc_offset();
1367 void *ret;
1368
1369 *mem_start = _ALIGN(*mem_start, align);
1370 while ((*mem_start + needed) > *mem_end) {
1371 unsigned long room, chunk;
1372
1373 prom_debug("Chunk exhausted, claiming more at %x...\n",
1374 RELOC(alloc_bottom));
1375 room = RELOC(alloc_top) - RELOC(alloc_bottom);
1376 if (room > DEVTREE_CHUNK_SIZE)
1377 room = DEVTREE_CHUNK_SIZE;
1378 if (room < PAGE_SIZE)
1379 prom_panic("No memory for flatten_device_tree (no room)");
1380 chunk = alloc_up(room, 0);
1381 if (chunk == 0)
1382 prom_panic("No memory for flatten_device_tree (claim failed)");
1383 *mem_end = RELOC(alloc_top);
1384 }
1385
1386 ret = (void *)*mem_start;
1387 *mem_start += needed;
1388
1389 return ret;
1390}
1391
1392#define dt_push_token(token, mem_start, mem_end) \
1393 do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0)
1394
1395static unsigned long __init dt_find_string(char *str)
1396{
1397 unsigned long offset = reloc_offset();
1398 char *s, *os;
1399
1400 s = os = (char *)RELOC(dt_string_start);
1401 s += 4;
1402 while (s < (char *)RELOC(dt_string_end)) {
1403 if (strcmp(s, str) == 0)
1404 return s - os;
1405 s += strlen(s) + 1;
1406 }
1407 return 0;
1408}
1409
1410static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1411 unsigned long *mem_end)
1412{
1413 unsigned long offset = reloc_offset();
1414 char *prev_name, *namep, *sstart;
1415 unsigned long soff;
1416 phandle child;
1417
1418 sstart = (char *)RELOC(dt_string_start);
1419
1420 /* get and store all property names */
1421 prev_name = RELOC("");
1422 for (;;) {
1423
1424 /* 32 is max len of name including nul. */
1425 namep = make_room(mem_start, mem_end, 32, 1);
1426 if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
1427 /* No more nodes: unwind alloc */
1428 *mem_start = (unsigned long)namep;
1429 break;
1430 }
1431 soff = dt_find_string(namep);
1432 if (soff != 0) {
1433 *mem_start = (unsigned long)namep;
1434 namep = sstart + soff;
1435 } else {
1436 /* Trim off some if we can */
1437 *mem_start = (unsigned long)namep + strlen(namep) + 1;
1438 RELOC(dt_string_end) = *mem_start;
1439 }
1440 prev_name = namep;
1441 }
1442
1443 /* do all our children */
1444 child = call_prom("child", 1, 1, node);
1445 while (child != (phandle)0) {
1446 scan_dt_build_strings(child, mem_start, mem_end);
1447 child = call_prom("peer", 1, 1, child);
1448 }
1449}
1450
1451static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1452 unsigned long *mem_end)
1453{
1454 int l, align;
1455 phandle child;
1456 char *namep, *prev_name, *sstart;
1457 unsigned long soff;
1458 unsigned char *valp;
1459 unsigned long offset = reloc_offset();
1460 char pname[32];
1461 char *path;
1462
1463 path = RELOC(prom_scratch);
1464
1465 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
1466
1467 /* get the node's full name */
1468 namep = (char *)*mem_start;
1469 l = call_prom("package-to-path", 3, 1, node,
1470 namep, *mem_end - *mem_start);
1471 if (l >= 0) {
1472 /* Didn't fit? Get more room. */
1473 if (l+1 > *mem_end - *mem_start) {
1474 namep = make_room(mem_start, mem_end, l+1, 1);
1475 call_prom("package-to-path", 3, 1, node, namep, l);
1476 }
1477 namep[l] = '\0';
1478 *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
1479 }
1480
1481 /* get it again for debugging */
1482 memset(path, 0, PROM_SCRATCH_SIZE);
1483 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1484
1485 /* get and store all properties */
1486 prev_name = RELOC("");
1487 sstart = (char *)RELOC(dt_string_start);
1488 for (;;) {
1489 if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0)
1490 break;
1491
1492 /* find string offset */
1493 soff = dt_find_string(pname);
1494 if (soff == 0) {
1495 prom_printf("WARNING: Can't find string index for <%s>, node %s\n",
1496 pname, path);
1497 break;
1498 }
1499 prev_name = sstart + soff;
1500
1501 /* get length */
1502 l = call_prom("getproplen", 2, 1, node, pname);
1503
1504 /* sanity checks */
1505 if (l < 0)
1506 continue;
1507 if (l > MAX_PROPERTY_LENGTH) {
1508 prom_printf("WARNING: ignoring large property ");
1509 /* It seems OF doesn't null-terminate the path :-( */
1510 prom_printf("[%s] ", path);
1511 prom_printf("%s length 0x%x\n", pname, l);
1512 continue;
1513 }
1514
1515 /* push property head */
1516 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1517 dt_push_token(l, mem_start, mem_end);
1518 dt_push_token(soff, mem_start, mem_end);
1519
1520 /* push property content */
1521 align = (l >= 8) ? 8 : 4;
1522 valp = make_room(mem_start, mem_end, l, align);
1523 call_prom("getprop", 4, 1, node, pname, valp, l);
1524 *mem_start = _ALIGN(*mem_start, 4);
1525 }
1526
1527 /* Add a "linux,phandle" property. */
1528 soff = dt_find_string(RELOC("linux,phandle"));
1529 if (soff == 0)
1530 prom_printf("WARNING: Can't find string index for <linux-phandle>"
1531 " node %s\n", path);
1532 else {
1533 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1534 dt_push_token(4, mem_start, mem_end);
1535 dt_push_token(soff, mem_start, mem_end);
1536 valp = make_room(mem_start, mem_end, 4, 4);
1537 *(u32 *)valp = node;
1538 }
1539
1540 /* do all our children */
1541 child = call_prom("child", 1, 1, node);
1542 while (child != (phandle)0) {
1543 scan_dt_build_struct(child, mem_start, mem_end);
1544 child = call_prom("peer", 1, 1, child);
1545 }
1546
1547 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
1548}
1549
1550static void __init flatten_device_tree(void)
1551{
1552 phandle root;
1553 unsigned long offset = reloc_offset();
1554 unsigned long mem_start, mem_end, room;
1555 struct boot_param_header *hdr;
1556 char *namep;
1557 u64 *rsvmap;
1558
1559 /*
1560 * Check how much room we have between alloc top & bottom (+/- a
1561 * few pages), crop to 4Mb, as this is our "chuck" size
1562 */
1563 room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;
1564 if (room > DEVTREE_CHUNK_SIZE)
1565 room = DEVTREE_CHUNK_SIZE;
1566 prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom));
1567
1568 /* Now try to claim that */
1569 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
1570 if (mem_start == 0)
1571 prom_panic("Can't allocate initial device-tree chunk\n");
1572 mem_end = RELOC(alloc_top);
1573
1574 /* Get root of tree */
1575 root = call_prom("peer", 1, 1, (phandle)0);
1576 if (root == (phandle)0)
1577 prom_panic ("couldn't get device tree root\n");
1578
1579 /* Build header and make room for mem rsv map */
1580 mem_start = _ALIGN(mem_start, 4);
1581 hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4);
1582 RELOC(dt_header_start) = (unsigned long)hdr;
1583 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
1584
1585 /* Start of strings */
1586 mem_start = PAGE_ALIGN(mem_start);
1587 RELOC(dt_string_start) = mem_start;
1588 mem_start += 4; /* hole */
1589
1590 /* Add "linux,phandle" in there, we'll need it */
1591 namep = make_room(&mem_start, &mem_end, 16, 1);
1592 strcpy(namep, RELOC("linux,phandle"));
1593 mem_start = (unsigned long)namep + strlen(namep) + 1;
1594 RELOC(dt_string_end) = mem_start;
1595
1596 /* Build string array */
1597 prom_printf("Building dt strings...\n");
1598 scan_dt_build_strings(root, &mem_start, &mem_end);
1599
1600 /* Build structure */
1601 mem_start = PAGE_ALIGN(mem_start);
1602 RELOC(dt_struct_start) = mem_start;
1603 prom_printf("Building dt structure...\n");
1604 scan_dt_build_struct(root, &mem_start, &mem_end);
1605 dt_push_token(OF_DT_END, &mem_start, &mem_end);
1606 RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
1607
1608 /* Finish header */
1609 hdr->magic = OF_DT_HEADER;
1610 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
1611 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
1612 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
1613 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
1614 hdr->version = OF_DT_VERSION;
1615 hdr->last_comp_version = 1;
1616
1617 /* Reserve the whole thing and copy the reserve map in, we
1618 * also bump mem_reserve_cnt to cause further reservations to
1619 * fail since it's too late.
1620 */
1621 reserve_mem(RELOC(dt_header_start), hdr->totalsize);
1622 memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
1623
1624#ifdef DEBUG_PROM
1625 {
1626 int i;
1627 prom_printf("reserved memory map:\n");
1628 for (i = 0; i < RELOC(mem_reserve_cnt); i++)
1629 prom_printf(" %x - %x\n", RELOC(mem_reserve_map)[i].base,
1630 RELOC(mem_reserve_map)[i].size);
1631 }
1632#endif
1633 RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
1634
1635 prom_printf("Device tree strings 0x%x -> 0x%x\n",
1636 RELOC(dt_string_start), RELOC(dt_string_end));
1637 prom_printf("Device tree struct 0x%x -> 0x%x\n",
1638 RELOC(dt_struct_start), RELOC(dt_struct_end));
1639
1640 }
1641
1642static void __init prom_find_boot_cpu(void)
1643{
1644 unsigned long offset = reloc_offset();
1645 struct prom_t *_prom = PTRRELOC(&prom);
1646 u32 getprop_rval;
1647 ihandle prom_cpu;
1648 phandle cpu_pkg;
1649
1650 if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
1651 prom_panic("cannot find boot cpu");
1652
1653 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
1654
1655 prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0);
1656 prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
1657 _prom->cpu = getprop_rval;
1658
1659 prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
1660}
1661
1662static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
1663{
1664#ifdef CONFIG_BLK_DEV_INITRD
1665 unsigned long offset = reloc_offset();
1666 struct prom_t *_prom = PTRRELOC(&prom);
1667
1668 if ( r3 && r4 && r4 != 0xdeadbeef) {
1669 u64 val;
1670
1671 RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
1672 RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
1673
1674 val = (u64)RELOC(prom_initrd_start);
1675 prom_setprop(_prom->chosen, "linux,initrd-start", &val, sizeof(val));
1676 val = (u64)RELOC(prom_initrd_end);
1677 prom_setprop(_prom->chosen, "linux,initrd-end", &val, sizeof(val));
1678
1679 reserve_mem(RELOC(prom_initrd_start),
1680 RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
1681
1682 prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start));
1683 prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end));
1684 }
1685#endif /* CONFIG_BLK_DEV_INITRD */
1686}
1687
1688/*
1689 * We enter here early on, when the Open Firmware prom is still
1690 * handling exceptions and the MMU hash table for us.
1691 */
1692
1693unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
1694 unsigned long r6, unsigned long r7)
1695{
1696 unsigned long offset = reloc_offset();
1697 struct prom_t *_prom = PTRRELOC(&prom);
1698 unsigned long phys = KERNELBASE - offset;
1699 u32 getprop_rval;
1700
1701 /*
1702 * First zero the BSS
1703 */
1704 memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);
1705
1706 /*
1707 * Init interface to Open Firmware, get some node references,
1708 * like /chosen
1709 */
1710 prom_init_client_services(pp);
1711
1712 /*
1713 * Init prom stdout device
1714 */
1715 prom_init_stdout();
1716 prom_debug("klimit=0x%x\n", RELOC(klimit));
1717 prom_debug("offset=0x%x\n", offset);
1718
1719 /*
1720 * Check for an initrd
1721 */
1722 prom_check_initrd(r3, r4);
1723
1724 /*
1725 * Get default machine type. At this point, we do not differenciate
1726 * between pSeries SMP and pSeries LPAR
1727 */
1728 RELOC(of_platform) = prom_find_machine_type();
1729 getprop_rval = RELOC(of_platform);
1730 prom_setprop(_prom->chosen, "linux,platform",
1731 &getprop_rval, sizeof(getprop_rval));
1732
1733 /*
1734 * On pSeries, copy the CPU hold code
1735 */
1736 if (RELOC(of_platform) & PLATFORM_PSERIES)
1737 copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
1738
1739 /*
1740 * Get memory cells format
1741 */
1742 getprop_rval = 1;
1743 prom_getprop(_prom->root, "#size-cells",
1744 &getprop_rval, sizeof(getprop_rval));
1745 _prom->root_size_cells = getprop_rval;
1746 getprop_rval = 2;
1747 prom_getprop(_prom->root, "#address-cells",
1748 &getprop_rval, sizeof(getprop_rval));
1749 _prom->root_addr_cells = getprop_rval;
1750
1751 /*
1752 * Do early parsing of command line
1753 */
1754 early_cmdline_parse();
1755
1756 /*
1757 * Initialize memory management within prom_init
1758 */
1759 prom_init_mem();
1760
1761 /*
1762 * Determine which cpu is actually running right _now_
1763 */
1764 prom_find_boot_cpu();
1765
1766 /*
1767 * Initialize display devices
1768 */
1769 prom_check_displays();
1770
1771 /*
1772 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
1773 * that uses the allocator, we need to make sure we get the top of memory
1774 * available for us here...
1775 */
1776 if (RELOC(of_platform) == PLATFORM_PSERIES)
1777 prom_initialize_tce_table();
1778
1779 /*
1780 * On non-powermacs, try to instantiate RTAS and puts all CPUs
1781 * in spin-loops. PowerMacs don't have a working RTAS and use
1782 * a different way to spin CPUs
1783 */
1784 if (RELOC(of_platform) != PLATFORM_POWERMAC) {
1785 prom_instantiate_rtas();
1786 prom_hold_cpus();
1787 }
1788
1789 /*
1790 * Fill in some infos for use by the kernel later on
1791 */
1792 if (RELOC(ppc64_iommu_off))
1793 prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
1794
1795 if (RELOC(iommu_force_on))
1796 prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
1797
1798 if (RELOC(prom_memory_limit))
1799 prom_setprop(_prom->chosen, "linux,memory-limit",
1800 PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit)));
1801
1802 if (RELOC(prom_tce_alloc_start)) {
1803 prom_setprop(_prom->chosen, "linux,tce-alloc-start",
1804 PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start)));
1805 prom_setprop(_prom->chosen, "linux,tce-alloc-end",
1806 PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end)));
1807 }
1808
1809 /*
1810 * Now finally create the flattened device-tree
1811 */
1812 prom_printf("copying OF device tree ...\n");
1813 flatten_device_tree();
1814
1815 /* in case stdin is USB and still active on IBM machines... */
1816 prom_close_stdin();
1817
1818 /*
1819 * Call OF "quiesce" method to shut down pending DMA's from
1820 * devices etc...
1821 */
1822 prom_printf("Calling quiesce ...\n");
1823 call_prom("quiesce", 0, 0);
1824
1825 /*
1826 * And finally, call the kernel passing it the flattened device
1827 * tree and NULL as r5, thus triggering the new entry point which
1828 * is common to us and kexec
1829 */
1830 prom_printf("returning from prom_init\n");
1831 prom_debug("->dt_header_start=0x%x\n", RELOC(dt_header_start));
1832 prom_debug("->phys=0x%x\n", phys);
1833
1834 __start(RELOC(dt_header_start), phys, 0);
1835
1836 return 0;
1837}
1838