12 #include <linux/kernel.h>
13 #include <linux/string.h>
15 #include <generated/utsrelease.h>
16 #include <asm/sections.h>
19 #include <asm/bootx.h>
20 #include <asm/btext.h>
22 #include <asm/setup.h>
28 #define DBG(fmt...) do { bootx_printf(fmt); } while(0)
30 #define DBG(fmt...) do { } while(0)
33 extern void __start(
unsigned long r3,
unsigned long r4,
unsigned long r5);
35 static unsigned long __initdata bootx_dt_strbase;
36 static unsigned long __initdata bootx_dt_strend;
37 static unsigned long __initdata bootx_node_chosen;
42 #define BOOT_INFO_IS_COMPATIBLE(bi) \
43 ((bi)->compatible_version <= BOOT_INFO_VERSION)
44 #define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
45 #define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
47 #ifdef CONFIG_BOOTX_TEXT
50 const char *
p, *
q, *
s;
55 for (p = format; *p != 0; p =
q) {
56 for (q = p; *q != 0 && *q !=
'\n' && *q !=
'%'; ++
q)
75 s =
va_arg(args,
const char *);
82 v =
va_arg(args,
unsigned long);
89 static void __init bootx_printf(
const char *
format, ...) {}
92 static void *
__init bootx_early_getprop(
unsigned long base,
105 return (
void *)((
unsigned long)pp->
value + base);
112 #define dt_push_token(token, mem) \
114 *(mem) = _ALIGN_UP(*(mem),4); \
115 *((u32 *)*(mem)) = token; \
119 static unsigned long __init bootx_dt_find_string(
char *
str)
123 s = os = (
char *)bootx_dt_strbase;
125 while (s < (
char *)bootx_dt_strend) {
136 unsigned long soff = bootx_dt_find_string(name);
140 bootx_printf(
"WARNING: Can't find string index for <%s>\n",
144 if (size > 0x20000) {
145 bootx_printf(
"WARNING: ignoring large property ");
146 bootx_printf(
"%s length 0x%x\n", name, size);
155 memcpy((
void *)*mem_end, data, size);
156 *mem_end =
_ALIGN_UP(*mem_end + size, 4);
160 static void __init bootx_add_chosen_props(
unsigned long base,
161 unsigned long *mem_end)
165 bootx_dt_add_prop(
"linux,bootx",
NULL, 0, mem_end);
168 char *
args = (
char *)((
unsigned long)bootx_info) +
170 bootx_dt_add_prop(
"bootargs", args,
strlen(args) + 1,
mem_end);
173 val = ((
unsigned long)bootx_info) + bootx_info->
ramDisk;
174 bootx_dt_add_prop(
"linux,initrd-start", &val, 4, mem_end);
176 bootx_dt_add_prop(
"linux,initrd-end", &val, 4, mem_end);
178 if (
strlen(bootx_disp_path))
179 bootx_dt_add_prop(
"linux,stdout-path", bootx_disp_path,
180 strlen(bootx_disp_path) + 1, mem_end);
183 static void __init bootx_add_display_props(
unsigned long base,
184 unsigned long *mem_end,
191 bootx_dt_add_prop(
"linux,boot-display",
NULL, 0, mem_end);
192 bootx_dt_add_prop(
"linux,opened",
NULL, 0, mem_end);
194 bootx_dt_add_prop(
"linux,bootx-noscreen",
NULL, 0, mem_end);
197 bootx_dt_add_prop(
"linux,bootx-depth", &tmp, 4, mem_end);
199 bootx_dt_add_prop(
"linux,bootx-width", &tmp, 4, mem_end);
201 bootx_dt_add_prop(
"linux,bootx-height", &tmp, 4, mem_end);
203 bootx_dt_add_prop(
"linux,bootx-linebytes", &tmp, 4, mem_end);
209 bootx_dt_add_prop(
"linux,bootx-addr", &tmp, 4, mem_end);
212 static void __init bootx_dt_add_string(
char *
s,
unsigned long *mem_end)
214 unsigned int l =
strlen(s) + 1;
215 memcpy((
void *)*mem_end, s, l);
216 bootx_dt_strend = *mem_end = *mem_end +
l;
219 static void __init bootx_scan_dt_build_strings(
unsigned long base,
221 unsigned long *mem_end)
231 bootx_printf(
"Node without a full name !\n");
234 DBG(
"* strings: %s\n", namep);
236 if (!
strcmp(namep,
"/chosen")) {
237 DBG(
" detected /chosen ! adding properties names !\n");
238 bootx_dt_add_string(
"linux,bootx", mem_end);
239 bootx_dt_add_string(
"linux,stdout-path", mem_end);
240 bootx_dt_add_string(
"linux,initrd-start", mem_end);
241 bootx_dt_add_string(
"linux,initrd-end", mem_end);
242 bootx_dt_add_string(
"bootargs", mem_end);
243 bootx_node_chosen =
node;
246 DBG(
" detected display ! adding properties names !\n");
247 bootx_dt_add_string(
"linux,boot-display", mem_end);
248 bootx_dt_add_string(
"linux,opened", mem_end);
249 strncpy(bootx_disp_path, namep, 255);
258 if (namep ==
NULL ||
strcmp(namep,
"name") == 0)
261 soff = bootx_dt_find_string(namep);
263 bootx_dt_add_string(namep, mem_end);
272 bootx_scan_dt_build_strings(base, *cpp, mem_end);
277 static void __init bootx_scan_dt_build_struct(
unsigned long base,
279 unsigned long *mem_end)
283 char *namep, *
p, *ep, *
lp;
294 DBG(
"* struct: %s\n", namep);
300 memcpy((
void *)*mem_end, namep, l + 1);
301 namep = (
char *)*mem_end;
302 for (lp = p = namep, ep = namep + l; p < ep; p++) {
309 *mem_end =
_ALIGN_UP((
unsigned long)lp + 1, 4);
321 if (node == bootx_node_chosen && !
strcmp(namep,
"bootargs"))
325 bootx_dt_add_prop(namep,
332 if (node == bootx_node_chosen) {
333 bootx_add_chosen_props(base, mem_end);
335 bootx_add_display_props(base, mem_end, 0);
338 bootx_add_display_props(base, mem_end, 1);
344 bootx_scan_dt_build_struct(base, *cpp, mem_end);
351 static unsigned long __init bootx_flatten_dt(
unsigned long start)
362 mem_start = mem_end =
_ALIGN_UP(((
unsigned long)bi) + start, 4);
363 DBG(
"Boot params header at: %x\n", mem_start);
368 mem_end = ((
unsigned long)rsvmap) + 8 *
sizeof(
u64);
374 DBG(
"Building string array at: %x\n", mem_end);
375 DBG(
"Device Tree Base=%x\n", base);
379 bootx_scan_dt_build_strings(base, 4, &mem_end);
381 bootx_dt_add_string(
"linux,bootx-noscreen", &mem_end);
382 bootx_dt_add_string(
"linux,bootx-depth", &mem_end);
383 bootx_dt_add_string(
"linux,bootx-width", &mem_end);
384 bootx_dt_add_string(
"linux,bootx-height", &mem_end);
385 bootx_dt_add_string(
"linux,bootx-linebytes", &mem_end);
386 bootx_dt_add_string(
"linux,bootx-addr", &mem_end);
392 mem_end =
_ALIGN(mem_end, 16);
393 DBG(
"Building device tree structure at: %x\n", mem_end);
395 bootx_scan_dt_build_struct(base, 4, &mem_end);
411 DBG(
"End of boot params: %x\n", mem_end);
415 rsvmap[2] = ((
unsigned long)bootx_info) + bootx_info->
ramDisk;
424 return (
unsigned long)
hdr;
428 #ifdef CONFIG_BOOTX_TEXT
434 bootx_printf(
"Welcome to Linux, kernel " UTS_RELEASE
"\n");
435 bootx_printf(
"\nlinked at : 0x%x",
KERNELBASE);
438 bootx_printf(
" (log)");
439 bootx_printf(
"\nklimit : 0x%x",(
unsigned long)
klimit);
440 bootx_printf(
"\nboot_info at : 0x%x", bi);
441 __asm__ __volatile__ (
"mfmsr %0" :
"=r" (flags));
442 bootx_printf(
"\nMSR : 0x%x", flags);
443 __asm__ __volatile__ (
"mfspr %0, 287" :
"=r" (pvr));
444 bootx_printf(
"\nPVR : 0x%x", pvr);
447 __asm__ __volatile__ (
"mfspr %0, 1008" :
"=r" (flags));
448 bootx_printf(
"\nHID0 : 0x%x", flags);
450 if (pvr == 8 || pvr == 12 || pvr == 0x800c) {
451 __asm__ __volatile__ (
"mfspr %0, 1019" :
"=r" (flags));
452 bootx_printf(
"\nICTC : 0x%x", flags);
455 bootx_printf(
"\n\n");
456 bootx_printf(
"bi->deviceTreeOffset : 0x%x\n",
458 bootx_printf(
"bi->deviceTreeSize : 0x%x\n",
461 bootx_printf(
"\n\n");
470 unsigned long ptr,
x;
481 bootx_dt_strbase = bootx_dt_strend = 0;
482 bootx_node_chosen = 0;
483 bootx_disp_path[0] = 0;
493 #ifdef CONFIG_BOOTX_TEXT
515 bootx_printf(
" !!! WARNING - Incompatible version"
516 " of BootX !!!\n\n\n");
521 bootx_printf(
" !!! WARNING - Usupported machine"
522 " architecture !\n");
527 #ifdef CONFIG_BOOTX_TEXT
541 && (
strcmp(model,
"iMac,1") == 0
542 ||
strcmp(model,
"PowerMac1,1") == 0)) {
543 bootx_printf(
"iMac,1 detected, shutting down USB\n");
558 bootx_printf(
"Total space used by parameters & ramdisk: 0x%x\n", space);
564 bootx_printf(
"Touching pages...\n");
573 x = *(
volatile unsigned long *)
ptr;
579 bootx_printf(
"Preparing boot params...\n");
581 hdr = bootx_flatten_dt(space);
583 #ifdef CONFIG_BOOTX_TEXT
585 bootx_printf(
"Preparing BAT...\n");