ia64/xen-unstable

view xen/arch/powerpc/boot_of.c @ 11060:00a41d1daf89

[POWERPC] add support for builtin command line
Support expressing Xen command line arguments at make invocation. Use
same section name as Linux's zImage and reserve a certain amount of
space so that arguments can be manipulated by external tools.

Signed-off-by: Amos Waterland <apw@us.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Amos Waterland <apw@us.ibm.com>
date Mon Aug 07 17:16:18 2006 -0500 (2006-08-07)
parents b786bfb058eb
children cdb24f869a56
line source
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
21 #include <xen/config.h>
22 #include <xen/init.h>
23 #include <xen/lib.h>
24 #include <xen/multiboot.h>
25 #include <xen/version.h>
26 #include <xen/spinlock.h>
27 #include <xen/serial.h>
28 #include <xen/time.h>
29 #include <asm/page.h>
30 #include <asm/io.h>
31 #include "exceptions.h"
32 #include "of-devtree.h"
34 static ulong of_vec;
35 static ulong of_msr;
36 static int of_out;
37 static ofdn_t boot_cpu;
38 static char bootargs[256];
40 #define COMMAND_LINE_SIZE 512
41 static char builtin_cmdline[COMMAND_LINE_SIZE]
42 __attribute__((section("__builtin_cmdline"))) = CMDLINE;
44 extern struct ns16550_defaults ns16550;
46 #undef OF_DEBUG
48 #ifdef OF_DEBUG
49 #define DBG(args...) of_printf(args)
50 #else
51 #define DBG(args...)
52 #endif
54 #define of_panic(MSG...) \
55 do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)
57 struct of_service {
58 u32 ofs_service;
59 u32 ofs_nargs;
60 u32 ofs_nrets;
61 u32 ofs_args[10];
62 };
64 static int bof_chosen;
66 static struct of_service s;
67 extern s32 prom_call(void *arg, ulong rtas_base, ulong func, ulong msr);
69 static int __init of_call(
70 const char *service, u32 nargs, u32 nrets, s32 rets[], ...)
71 {
72 int rc;
74 if (of_vec != 0) {
75 va_list args;
76 int i;
78 memset(&s, 0, sizeof (s));
79 s.ofs_service = (ulong)service;
80 s.ofs_nargs = nargs;
81 s.ofs_nrets = nrets;
82 s.ofs_nargs = nargs;
84 /* copy all the params into the args array */
85 va_start(args, rets);
87 for (i = 0; i < nargs; i++) {
88 s.ofs_args[i] = va_arg(args, u32);
89 }
91 va_end(args);
93 rc = prom_call(&s, 0, of_vec, of_msr);
95 /* yes always to the copy, just in case */
96 for (i = 0; i < nrets; i++) {
97 rets[i] = s.ofs_args[i + nargs];
98 }
99 } else {
100 rc = OF_FAILURE;
101 }
102 return rc;
103 }
105 /* popular OF methods */
106 static int __init _of_write(int ih, const char *addr, u32 len)
107 {
108 int rets[1] = { OF_FAILURE };
109 if (of_call("write", 3, 1, rets, ih, addr, len) == OF_FAILURE) {
110 return OF_FAILURE;
111 }
112 return rets[0];
113 }
115 /* popular OF methods */
116 static int __init of_write(int ih, const char *addr, u32 len)
117 {
118 int rc;
119 int i = 0;
120 int sum = 0;
122 while (i < len) {
123 if (addr[i] == '\n') {
124 if (i > 0) {
125 rc = _of_write(ih, addr, i);
126 if (rc == OF_FAILURE)
127 return rc;
128 sum += rc;
129 }
130 rc = _of_write(ih, "\r\n", 2);
131 if (rc == OF_FAILURE)
132 return rc;
133 sum += rc;
134 i++;
135 addr += i;
136 len -= i;
137 i = 0;
138 continue;
139 }
140 i++;
141 }
142 if (len > 0) {
143 rc = _of_write(ih, addr, len);
144 if (rc == OF_FAILURE)
145 return rc;
146 sum += rc;
147 }
149 return sum;
150 }
152 static int of_printf(const char *fmt, ...)
153 __attribute__ ((format (printf, 1, 2)));
154 static int __init of_printf(const char *fmt, ...)
155 {
156 static char buf[1024];
157 va_list args;
158 int sz;
160 if (of_out == 0) {
161 return OF_FAILURE;
162 }
164 va_start(args, fmt);
166 sz = vsnprintf(buf, sizeof (buf), fmt, args);
167 if (sz <= sizeof (buf)) {
168 of_write(of_out, buf, sz);
169 } else {
170 static const char trunc[] = "\n(TRUNCATED)\n";
172 sz = sizeof (buf);
173 of_write(of_out, buf, sz);
174 of_write(of_out, trunc, sizeof (trunc));
175 }
176 return sz;
177 }
179 static int __init of_finddevice(const char *devspec)
180 {
181 int rets[1] = { OF_FAILURE };
183 of_call("finddevice", 1, 1, rets, devspec);
184 if (rets[0] == OF_FAILURE) {
185 DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]);
186 return OF_FAILURE;
187 }
188 DBG("finddevice %s -> %d\n",devspec, rets[0]);
189 return rets[0];
190 }
192 static int __init of_getprop(int ph, const char *name, void *buf, u32 buflen)
193 {
194 int rets[1] = { OF_FAILURE };
196 of_call("getprop", 4, 1, rets, ph, name, buf, buflen);
198 if (rets[0] == OF_FAILURE) {
199 DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
200 return OF_FAILURE;
201 }
203 DBG("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf);
204 return rets[0];
205 }
207 static int __init of_setprop(
208 int ph, const char *name, const void *buf, u32 buflen)
209 {
210 int rets[1] = { OF_FAILURE };
212 of_call("setprop", 4, 1, rets, ph, name, buf, buflen);
214 if (rets[0] == OF_FAILURE) {
215 DBG("setprop 0x%x %s -> FAILURE\n", ph, name);
216 return OF_FAILURE;
217 }
219 DBG("setprop 0x%x %s -> %s\n", ph, name, (char *)buf);
220 return rets[0];
221 }
223 /*
224 * returns 0 if there are no children (of spec)
225 */
226 static int __init of_getchild(int ph)
227 {
228 int rets[1] = { OF_FAILURE };
230 of_call("child", 1, 1, rets, ph);
231 DBG("getchild 0x%x -> 0x%x\n", ph, rets[0]);
233 return rets[0];
234 }
236 /*
237 * returns 0 is there are no peers
238 */
239 static int __init of_getpeer(int ph)
240 {
241 int rets[1] = { OF_FAILURE };
243 of_call("peer", 1, 1, rets, ph);
244 DBG("getpeer 0x%x -> 0x%x\n", ph, rets[0]);
246 return rets[0];
247 }
249 static int __init of_getproplen(int ph, const char *name)
250 {
251 int rets[1] = { OF_FAILURE };
253 of_call("getproplen", 2, 1, rets, ph, name);
254 if (rets[0] == OF_FAILURE) {
255 DBG("getproplen 0x%x %s -> FAILURE\n", ph, name);
256 return OF_FAILURE;
257 }
258 DBG("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]);
259 return rets[0];
260 }
262 static int __init of_package_to_path(int ph, char *buffer, u32 buflen)
263 {
264 int rets[1] = { OF_FAILURE };
266 of_call("package-to-path", 3, 1, rets, ph, buffer, buflen);
267 if (rets[0] == OF_FAILURE) {
268 DBG("%s 0x%x -> FAILURE\n", __func__, ph);
269 return OF_FAILURE;
270 }
271 DBG("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]);
272 if (rets[0] <= buflen)
273 buffer[rets[0]] = '\0';
274 return rets[0];
275 }
277 static int __init of_nextprop(int ph, const char *name, void *buf)
278 {
279 int rets[1] = { OF_FAILURE };
281 of_call("nextprop", 3, 1, rets, ph, name, buf);
283 if (rets[0] == OF_FAILURE) {
284 DBG("nextprop 0x%x %s -> FAILURE\n", ph, name);
285 return OF_FAILURE;
286 }
288 DBG("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf);
289 return rets[0];
290 }
292 static int __init of_instance_to_path(int ih, char *buffer, u32 buflen)
293 {
294 int rets[1] = { OF_FAILURE };
296 if (of_call("instance-to-path", 3, 1, rets, ih, buffer, buflen)
297 == OF_FAILURE)
298 return OF_FAILURE;
300 if (rets[0] <= buflen)
301 buffer[rets[0]] = '\0';
302 return rets[0];
303 }
305 static int __init of_start_cpu(int cpu, u32 pc, u32 reg)
306 {
307 int rets[1] = { OF_FAILURE };
309 if ( of_call("start-cpu", 3, 0, rets, cpu, pc, reg) == OF_FAILURE )
310 return OF_FAILURE;
312 return rets[0];
313 }
315 static void __init of_test(const char *of_method_name)
316 {
317 int rets[1] = { OF_FAILURE };
319 of_call("test", 1, 1, rets, of_method_name);
320 if (rets[0] == OF_FAILURE ) {
321 of_printf("Warning: possibly no OF method %s.\n"
322 "(Ignore this warning on PIBS.)\n", of_method_name);
323 }
324 }
326 static int __init of_claim(void * virt, u32 size)
327 {
328 int rets[1] = { OF_FAILURE };
330 of_call("claim", 3, 1, rets, virt, size, 0/*align*/);
331 if (rets[0] == OF_FAILURE) {
332 DBG("%s 0x%p 0x%08x -> FAIL\n", __func__, virt, size);
333 return OF_FAILURE;
334 }
336 DBG("%s 0x%p 0x%08x -> 0x%x\n", __func__, virt, size, rets[0]);
337 return rets[0];
338 }
340 static int __init of_instance_to_package(int ih)
341 {
342 int rets[1] = { OF_FAILURE };
344 of_call("instance-to-package", 1, 1, rets, ih);
345 if (rets[0] == OF_FAILURE)
346 return OF_FAILURE;
348 return rets[0];
349 }
351 static int __init of_getparent(int ph)
352 {
353 int rets[1] = { OF_FAILURE };
355 of_call("parent", 1, 1, rets, ph);
357 DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
358 return rets[0];
359 }
361 static void boot_of_probemem(multiboot_info_t *mbi)
362 {
363 int root;
364 int p;
365 u32 addr_cells = 1;
366 u32 size_cells = 1;
367 int rc;
368 int mcount = 0;
369 static memory_map_t mmap[16];
371 root = of_finddevice("/");
372 p = of_getchild(root);
374 /* code is writen to assume sizes of 1 */
375 of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
376 of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
377 DBG("%s: address_cells=%d size_cells=%d\n",
378 __func__, addr_cells, size_cells);
380 do {
381 const char memory[] = "memory";
382 char type[32];
384 type[0] = '\0';
386 of_getprop(p, "device_type", type, sizeof (type));
387 if (strncmp(type, memory, sizeof (memory)) == 0) {
388 u32 reg[48];
389 u32 al, ah, ll, lh;
390 int r;
392 rc = of_getprop(p, "reg", reg, sizeof (reg));
393 if (rc == OF_FAILURE) {
394 of_panic("no reg property for memory node: 0x%x.\n", p);
395 }
396 int l = rc/sizeof(u32); /* number reg element */
397 DBG("%s: number of bytes in property 'reg' %d\n",
398 __func__, rc);
400 r = 0;
401 while (r < l) {
402 al = ah = ll = lh = 0;
403 if (addr_cells == 2) {
404 ah = reg[r++];
405 if (r >= l)
406 break; /* partial line. Skip */
407 al = reg[r++];
408 if (r >= l)
409 break; /* partial line. Skip */
410 } else {
411 al = reg[r++];
412 if (r >= l)
413 break; /* partial line. Skip */
414 }
415 if (size_cells == 2) {
416 lh = reg[r++];
417 if (r >= l)
418 break; /* partial line. Skip */
419 ll = reg[r++];
420 } else {
421 ll = reg[r++];
422 }
424 if ((ll != 0) || (lh != 0)) {
425 mmap[mcount].size = 20; /* - size field */
426 mmap[mcount].type = 1; /* Regular ram */
427 mmap[mcount].length_high = lh;
428 mmap[mcount].length_low = ll;
429 mmap[mcount].base_addr_high = ah;
430 mmap[mcount].base_addr_low = al;
431 of_printf("%s: memory 0x%016lx[0x%08lx]\n",
432 __func__,
433 (u64)(((u64)mmap[mcount].base_addr_high << 32)
434 | mmap[mcount].base_addr_low),
435 (u64)(((u64)mmap[mcount].length_high << 32)
436 | mmap[mcount].length_low));
437 ++mcount;
438 }
439 }
440 }
441 p = of_getpeer(p);
442 } while (p != OF_FAILURE && p != 0);
444 if (mcount > 0) {
445 mbi->flags |= MBI_MEMMAP;
446 mbi->mmap_length = sizeof (mmap[0]) * mcount;
447 mbi->mmap_addr = (ulong)mmap;
448 }
449 }
451 static void boot_of_bootargs(multiboot_info_t *mbi)
452 {
453 int rc;
455 rc = of_getprop(bof_chosen, "bootargs", &bootargs, sizeof (bootargs));
456 if (rc == OF_FAILURE || bootargs[0] == '\0') {
457 strlcpy(bootargs, builtin_cmdline, sizeof(bootargs));
458 }
460 mbi->flags |= MBI_CMDLINE;
461 mbi->cmdline = (u32)bootargs;
463 of_printf("bootargs = %s\n", bootargs);
464 }
466 static int save_props(void *m, ofdn_t n, int pkg)
467 {
468 int ret;
469 char name[128];
470 int result = 1;
471 int found_name = 0;
472 int found_device_type = 0;
473 const char name_str[] = "name";
474 const char devtype_str[] = "device_type";
476 /* get first */
477 result = of_nextprop(pkg, 0, name);
479 while (result > 0) {
480 int sz;
481 u64 obj[1024];
483 sz = of_getproplen(pkg, name);
484 if (sz >= 0) {
485 ret = OF_SUCCESS;
486 } else {
487 ret = OF_FAILURE;
488 }
490 if (ret == OF_SUCCESS) {
491 int actual = 0;
492 ofdn_t pos;
494 if (sz > 0) {
495 if (sz > sizeof (obj)) {
496 of_panic("obj array not big enough for 0x%x\n", sz);
497 }
498 actual = of_getprop(pkg, name, obj, sz);
499 if (actual > sz) of_panic("obj too small");
500 }
502 if (strncmp(name, name_str, sizeof(name_str)) == 0) {
503 found_name = 1;
504 }
506 if (strncmp(name, devtype_str, sizeof(devtype_str)) == 0) {
507 found_device_type = 1;
508 }
510 pos = ofd_prop_add(m, n, name, obj, actual);
511 if (pos == 0) of_panic("prop_create");
512 }
514 result = of_nextprop(pkg, name, name);
515 }
517 return 1;
518 }
521 static void do_pkg(void *m, ofdn_t n, int p, char *path, size_t psz)
522 {
523 int pnext;
524 ofdn_t nnext;
525 int sz;
527 retry:
528 save_props(m, n, p);
530 /* do children first */
531 pnext = of_getchild(p);
533 if (pnext != 0) {
534 sz = of_package_to_path(pnext, path, psz);
535 if (sz == OF_FAILURE) of_panic("bad path\n");
537 nnext = ofd_node_child_create(m, n, path, sz);
538 if (nnext == 0) of_panic("out of mem\n");
540 do_pkg(m, nnext, pnext, path, psz);
541 }
543 /* do peer */
544 pnext = of_getpeer(p);
546 if (pnext != 0) {
547 sz = of_package_to_path(pnext, path, psz);
549 nnext = ofd_node_peer_create(m, n, path, sz);
550 if (nnext <= 0) of_panic("out of space in OFD tree.\n");
552 n = nnext;
553 p = pnext;
554 goto retry;
555 }
556 }
558 static int pkg_save(void *mem)
559 {
560 int root;
561 char path[256];
562 int r;
564 path[0]='/';
565 path[1]='\0';
567 /* get root */
568 root = of_getpeer(0);
569 if (root == OF_FAILURE) of_panic("no root package\n");
571 do_pkg(mem, OFD_ROOT, root, path, sizeof(path));
573 r = (((ofdn_t *)mem)[1] + 1) * sizeof (u64);
575 of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r);
577 return r;
578 }
580 static int boot_of_fixup_refs(void *mem)
581 {
582 static const char *fixup_props[] = {
583 "interrupt-parent",
584 };
585 int i;
586 int count = 0;
588 for (i = 0; i < ARRAY_SIZE(fixup_props); i++) {
589 ofdn_t c;
590 const char *name = fixup_props[i];
592 c = ofd_node_find_by_prop(mem, OFD_ROOT, name, NULL, 0);
593 while (c > 0) {
594 const char *path;
595 int rp;
596 int ref;
597 ofdn_t dp;
598 int rc;
599 ofdn_t upd;
600 char ofpath[256];
602 path = ofd_node_path(mem, c);
603 if (path == NULL) of_panic("no path to found prop: %s\n", name);
605 rp = of_finddevice(path);
606 if (rp == OF_FAILURE)
607 of_panic("no real device for: name %s, path %s\n",
608 name, path);
609 /* Note: In theory 0 is a valid node handle but it is highly
610 * unlikely.
611 */
612 if (rp == 0) {
613 of_panic("%s: of_finddevice returns 0 for path %s\n",
614 __func__, path);
615 }
617 rc = of_getprop(rp, name, &ref, sizeof(ref));
618 if ((rc == OF_FAILURE) || (rc == 0))
619 of_panic("no prop: name %s, path %s, device 0x%x\n",
620 name, path, rp);
622 rc = of_package_to_path(ref, ofpath, sizeof (ofpath));
623 if (rc == OF_FAILURE)
624 of_panic("no package: name %s, path %s, device 0x%x,\n"
625 "ref 0x%x\n", name, path, rp, ref);
627 dp = ofd_node_find(mem, ofpath);
628 if (dp <= 0) of_panic("no ofd node for OF node[0x%x]: %s\n",
629 ref, ofpath);
631 ref = dp;
633 upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref));
634 if (upd <= 0) of_panic("update failed: %s\n", name);
636 #ifdef DEBUG
637 of_printf("%s: %s/%s -> %s\n", __func__,
638 path, name, ofpath);
639 #endif
640 ++count;
641 c = ofd_node_find_next(mem, c);
642 }
643 }
644 return count;
645 }
647 static int boot_of_fixup_chosen(void *mem)
648 {
649 int ch;
650 ofdn_t dn;
651 ofdn_t dc;
652 int val;
653 int rc;
654 char ofpath[256];
656 ch = of_finddevice("/chosen");
657 if (ch == OF_FAILURE) of_panic("/chosen not found\n");
659 rc = of_getprop(ch, "cpu", &val, sizeof (val));
661 if (rc != OF_FAILURE) {
662 rc = of_instance_to_path(val, ofpath, sizeof (ofpath));
664 if (rc > 0) {
665 dn = ofd_node_find(mem, ofpath);
666 if (dn <= 0) of_panic("no node for: %s\n", ofpath);
668 boot_cpu = dn;
669 val = dn;
671 dn = ofd_node_find(mem, "/chosen");
672 if (dn <= 0) of_panic("no /chosen node\n");
674 dc = ofd_prop_add(mem, dn, "cpu", &val, sizeof (val));
675 if (dc <= 0) of_panic("could not fix /chosen/cpu\n");
676 rc = 1;
677 } else {
678 of_printf("*** can't find path to booting cpu, "
679 "SMP is disabled\n");
680 boot_cpu = -1;
681 }
682 }
683 return rc;
684 }
686 static ulong space_base;
687 static ulong find_space(u32 size, ulong align, multiboot_info_t *mbi)
688 {
689 memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr);
690 ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
691 ulong base;
693 of_printf("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%lx\n",
694 __func__, space_base, eomem, size, align);
695 base = ALIGN_UP(space_base, PAGE_SIZE);
696 if ((base + size) >= 0x4000000) return 0;
697 if (base + size > eomem) of_panic("not enough RAM\n");
699 if (size == 0) return base;
700 if (of_claim((void*)base, size) != OF_FAILURE) {
701 space_base = base + size;
702 return base;
703 } else {
704 for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) {
705 of_printf("Trying 0x%016lx\n", base);
706 if (of_claim((void*)base, size) != OF_FAILURE) {
707 space_base = base + size;
708 return base;
709 }
710 }
711 return 0;
712 }
713 }
715 /* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges
716 * property. The values are bad, and it doesn't even have the
717 * right number of cells. */
719 static void __init boot_of_fix_maple(void)
720 {
721 int isa;
722 const char *ranges = "ranges";
723 u32 isa_ranges[3];
724 const u32 isa_test[] = { 0x00000001, 0xf4000000, 0x00010000 };
725 const u32 isa_fixed[] = {
726 0x00000001,
727 0x00000000,
728 0x00000000, /* 0xf4000000, matt says this */
729 0x00000000,
730 0x00000000,
731 0x00010000
732 };
734 isa = of_finddevice("/ht@0/isa@4");
735 if (isa != OF_FAILURE) {
736 if (of_getproplen(isa, ranges) == sizeof (isa_test)) {
737 of_getprop(isa, ranges, isa_ranges, sizeof (isa_ranges));
738 if (memcmp(isa_ranges, isa_test, sizeof (isa_test)) == 0) {
739 int rc;
741 of_printf("OF: fixing bogus ISA range on maple\n");
742 rc = of_setprop(isa, ranges, isa_fixed, sizeof (isa_fixed));
743 if (rc == OF_FAILURE) {
744 of_panic("of_setprop() failed\n");
745 }
746 }
747 }
748 }
749 }
751 static int __init boot_of_serial(void *oftree)
752 {
753 int n;
754 int p;
755 int rc;
756 u32 val[3];
757 char buf[128];
759 n = of_instance_to_package(of_out);
760 if (n == OF_FAILURE) {
761 of_panic("instance-to-package of /chosen/stdout: failed\n");
762 }
764 /* prune this from the oftree */
765 rc = of_package_to_path(n, buf, sizeof(buf));
766 if (rc == OF_FAILURE) {
767 of_panic("package-to-path of /chosen/stdout: failed\n");
768 }
769 of_printf("Pruning from devtree: %s\n"
770 " since Xen will be using it for console\n", buf);
771 rc = ofd_prune_path(oftree, buf);
772 if (rc < 0) {
773 of_panic("prune path \"%s\" failed\n", buf);
774 }
777 p = of_getparent(n);
778 if (p == OF_FAILURE) {
779 of_panic("no parent for: 0x%x\n", n);
780 }
782 buf[0] = '\0';
783 of_getprop(p, "device_type", buf, sizeof (buf));
784 if (strstr(buf, "isa") == NULL) {
785 of_panic("only ISA UARTS supported\n");
786 }
788 /* should get this from devtree */
789 isa_io_base = 0xf4000000;
790 of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base);
792 buf[0] = '\0';
793 of_getprop(n, "device_type", buf, sizeof (buf));
794 if (strstr(buf, "serial") == NULL) {
795 of_panic("only UARTS supported\n");
796 }
798 rc = of_getprop(n, "reg", val, sizeof (val));
799 if (rc == OF_FAILURE) {
800 of_panic("%s: no location for serial port\n", __func__);
801 }
802 ns16550.io_base = val[1];
804 ns16550.baud = BAUD_AUTO;
805 ns16550.data_bits = 8;
806 ns16550.parity = 'n';
807 ns16550.stop_bits = 1;
809 rc = of_getprop(n, "interrupts", val, sizeof (val));
810 if (rc == OF_FAILURE) {
811 of_printf("%s: no ISRC, forcing poll mode\n", __func__);
812 ns16550.irq = 0;
813 } else {
814 ns16550.irq = val[0];
815 of_printf("%s: ISRC=0x%x, but forcing poll mode\n",
816 __func__, ns16550.irq);
817 ns16550.irq = 0;
818 }
820 return 1;
821 }
823 static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
824 {
825 static module_t mods[3];
826 void *oftree;
827 ulong oftree_sz = 48 * PAGE_SIZE;
828 char *mod0_start;
829 ulong mod0_size;
830 ulong mod0;
831 static const char sepr[] = " -- ";
832 extern char dom0_start[] __attribute__ ((weak));
833 extern char dom0_size[] __attribute__ ((weak));
834 const char *p;
836 if ((r3 > 0) && (r4 > 0)) {
837 /* was it handed to us in registers ? */
838 mod0_start = (void *)r3;
839 mod0_size = r4;
840 } else {
841 /* see if it is in the boot params */
842 p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
843 if ( p != NULL) {
844 p += 11;
845 mod0_start = (char *)simple_strtoul(p, NULL, 0);
847 p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
848 p += 10;
849 mod0_size = simple_strtoul(p, NULL, 0);
851 of_printf("mod0: %o %c %c %c\n",
852 mod0_start[0],
853 mod0_start[1],
854 mod0_start[2],
855 mod0_start[3]);
857 } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
858 /* was it linked in ? */
860 mod0_start = dom0_start;
861 mod0_size = (ulong)dom0_size;
862 of_printf("%s: linked in module copied after _end "
863 "(start 0x%p size 0x%lx)\n",
864 __func__, mod0_start, mod0_size);
865 } else {
866 mod0_start = _end;
867 mod0_size = 0;
868 }
869 }
871 space_base = (ulong)_end;
872 mod0 = find_space(mod0_size, PAGE_SIZE, mbi);
874 /* three cases
875 * 1) mod0_size is not 0 and the image can be copied
876 * 2) mod0_size is not 0 and the image cannot be copied
877 * 3) mod0_size is 0
878 */
879 if (mod0_size > 0) {
880 if (mod0 != 0) {
881 memcpy((void *)mod0, mod0_start, mod0_size);
882 mods[0].mod_start = mod0;
883 mods[0].mod_end = mod0 + mod0_size;
884 } else {
885 of_panic("No space to copy mod0\n");
886 }
887 } else {
888 mods[0].mod_start = mod0;
889 mods[0].mod_end = mod0;
890 }
892 of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__,
893 mods[0].mod_start, mods[0].mod_end);
894 p = strstr((char *)(ulong)mbi->cmdline, sepr);
895 if (p != NULL) {
896 p += sizeof (sepr) - 1;
897 mods[0].string = (u32)(ulong)p;
898 of_printf("%s: mod[0].string: %s\n", __func__, p);
899 }
901 /* snapshot the tree */
902 oftree = (void*)find_space(oftree_sz, PAGE_SIZE, mbi);
903 if (oftree == 0) of_panic("Could not allocate OFD tree\n");
905 of_printf("creating oftree\n");
906 of_test("package-to-path");
907 ofd_create(oftree, oftree_sz);
908 pkg_save(oftree);
910 boot_of_fixup_refs(oftree);
911 boot_of_fixup_chosen(oftree);
913 ofd_walk(oftree, OFD_ROOT, /* add_hype_props */ NULL, 2);
915 mods[1].mod_start = (ulong)oftree;
916 mods[1].mod_end = mods[1].mod_start + oftree_sz;
917 of_printf("%s: mod[1] @ 0x%016x[0x%x]\n", __func__,
918 mods[1].mod_start, mods[1].mod_end);
921 mbi->flags |= MBI_MODULES;
922 mbi->mods_count = 2;
923 mbi->mods_addr = (u32)mods;
925 boot_of_serial(oftree);
926 }
928 static int __init boot_of_cpus(void)
929 {
930 int cpus;
931 int cpu;
932 int result;
933 u32 cpu_clock[2];
935 cpus = of_finddevice("/cpus");
936 cpu = of_getchild(cpus);
937 result = of_getprop(cpu, "timebase-frequency", &timebase_freq,
938 sizeof(timebase_freq));
939 if (result == OF_FAILURE) {
940 of_panic("Couldn't get timebase frequency!\n");
941 }
942 of_printf("OF: timebase-frequency = %d Hz\n", timebase_freq);
944 result = of_getprop(cpu, "clock-frequency", &cpu_clock, sizeof(cpu_clock));
945 if (result == OF_FAILURE || (result !=4 && result != 8)) {
946 of_panic("Couldn't get clock frequency!\n");
947 }
948 cpu_khz = cpu_clock[0];
949 if (result == 8) {
950 cpu_khz <<= 32;
951 cpu_khz |= cpu_clock[1];
952 }
953 cpu_khz /= 1000;
954 of_printf("OF: clock-frequency = %ld KHz\n", cpu_khz);
956 /* FIXME: should not depend on the boot CPU bring the first child */
957 cpu = of_getpeer(cpu);
958 while (cpu > 0) {
959 of_start_cpu(cpu, (ulong)spin_start, 0);
960 cpu = of_getpeer(cpu);
961 }
962 return 1;
963 }
965 static int __init boot_of_rtas(void)
966 {
967 return 1;
968 }
970 multiboot_info_t __init *boot_of_init(
971 ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
972 {
973 static multiboot_info_t mbi;
975 of_vec = vec;
976 of_msr = orig_msr;
978 bof_chosen = of_finddevice("/chosen");
979 of_getprop(bof_chosen, "stdout", &of_out, sizeof (of_out));
981 of_printf("%s\n", "---------------------------------------------------");
982 of_printf("OF: Xen/PPC version %d.%d%s (%s@%s) (%s) %s\n",
983 xen_major_version(), xen_minor_version(), xen_extra_version(),
984 xen_compile_by(), xen_compile_domain(),
985 xen_compiler(), xen_compile_date());
987 of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n"
988 "boot msr: 0x%lx\n",
989 __func__,
990 r3, r4, vec, r6, r7, orig_msr);
992 if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) {
993 of_printf("Hmm.. OF[0x%lx] seems to have stepped on our image "
994 "that ranges: %p .. %p.\n HANG!\n",
995 vec, _start, _end);
996 }
997 of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6);
999 boot_of_fix_maple();
1000 boot_of_probemem(&mbi);
1001 boot_of_bootargs(&mbi);
1002 boot_of_module(r3, r4, &mbi);
1003 boot_of_cpus();
1004 boot_of_rtas();
1006 /* end of OF */
1007 of_call("quiesce", 0, 0, NULL);
1009 return &mbi;
1012 /*
1013 * Local variables:
1014 * mode: C
1015 * c-set-style: "BSD"
1016 * c-basic-offset: 4
1017 * tab-width: 4
1018 * indent-tabs-mode: nil
1019 * End:
1020 */