1/* $NetBSD: Locore.c,v 1.21 2008/02/12 04:27:46 garbled Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include "openfirm.h" 35#include <sys/param.h> 36#include <lib/libsa/stand.h> 37 38#include <machine/cpu.h> 39 40static int (*openfirmware_entry)(void *); 41static int openfirmware(void *); 42 43void startup(void *, int, int (*)(void *), char *, int) 44 __attribute__((__used__)); 45static void setup(void); 46 47/* this pad gets the rodata laignment right, don't EVER fiddle it */ 48char *pad __attribute__((__aligned__ (8))) = "pad"; 49int stack[8192/4 + 4] __attribute__((__aligned__ (4), __used__)); 50char *heapspace __attribute__((__aligned__ (4))); 51char altheap[0x20000] __attribute__((__aligned__ (4))); 52 53static int 54openfirmware(void *arg) 55{ 56 int r; 57 58 __asm volatile ("sync; isync"); 59 r = openfirmware_entry(arg); 60 __asm volatile ("sync; isync"); 61 62 return r; 63} 64 65void 66startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) 67{ 68 69 openfirmware_entry = openfirm; 70 setup(); 71 main(); 72 OF_exit(); 73} 74 75__dead void 76OF_exit(void) 77{ 78 static struct { 79 char *name; 80 int nargs; 81 int nreturns; 82 } args = { 83 "exit", 84 0, 85 0 86 }; 87 88 openfirmware(&args); 89 for (;;); /* just in case */ 90} 91 92__dead void 93OF_boot(char *bootspec) 94{ 95 static struct { 96 char *name; 97 int nargs; 98 int nreturns; 99 char *bootspec; 100 } args = { 101 "boot", 102 1, 103 0, 104 }; 105 106 args.bootspec = bootspec; 107 openfirmware(&args); 108 for (;;); /* just in case */ 109} 110 111int 112OF_finddevice(char *name) 113{ 114 static struct { 115 char *name; 116 int nargs; 117 int nreturns; 118 char *device; 119 int phandle; 120 } args = { 121 "finddevice", 122 1, 123 1, 124 }; 125 126 args.device = name; 127 if (openfirmware(&args) == -1) 128 return -1; 129 return args.phandle; 130} 131 132int 133OF_instance_to_package(int ihandle) 134{ 135 static struct { 136 char *name; 137 int nargs; 138 int nreturns; 139 int ihandle; 140 int phandle; 141 } args = { 142 "instance-to-package", 143 1, 144 1, 145 }; 146 147 args.ihandle = ihandle; 148 if (openfirmware(&args) == -1) 149 return -1; 150 return args.phandle; 151} 152 153int 154OF_getprop(int handle, char *prop, void *buf, int buflen) 155{ 156 static struct { 157 char *name; 158 int nargs; 159 int nreturns; 160 int phandle; 161 char *prop; 162 void *buf; 163 int buflen; 164 int size; 165 } args = { 166 "getprop", 167 4, 168 1, 169 }; 170 171 args.phandle = handle; 172 args.prop = prop; 173 args.buf = buf; 174 args.buflen = buflen; 175 if (openfirmware(&args) == -1) 176 return -1; 177 return args.size; 178} 179 180#ifdef __notyet__ /* Has a bug on FirePower */ 181int 182OF_setprop(int handle, char *prop, void *buf, int len) 183{ 184 static struct { 185 char *name; 186 int nargs; 187 int nreturns; 188 int phandle; 189 char *prop; 190 void *buf; 191 int len; 192 int size; 193 } args = { 194 "setprop", 195 4, 196 1, 197 }; 198 199 args.phandle = handle; 200 args.prop = prop; 201 args.buf = buf; 202 args.len = len; 203 if (openfirmware(&args) == -1) 204 return -1; 205 return args.size; 206} 207#endif 208 209int 210OF_open(char *dname) 211{ 212 static struct { 213 char *name; 214 int nargs; 215 int nreturns; 216 char *dname; 217 int handle; 218 } args = { 219 "open", 220 1, 221 1, 222 }; 223 224#ifdef OFW_DEBUG 225 printf("OF_open(%s) -> ", dname); 226#endif 227 args.dname = dname; 228 if (openfirmware(&args) == -1 || 229 args.handle == 0) { 230#ifdef OFW_DEBUG 231 printf("lose\n"); 232#endif 233 return -1; 234 } 235#ifdef OFW_DEBUG 236 printf("%d\n", args.handle); 237#endif 238 return args.handle; 239} 240 241void 242OF_close(int handle) 243{ 244 static struct { 245 char *name; 246 int nargs; 247 int nreturns; 248 int handle; 249 } args = { 250 "close", 251 1, 252 0, 253 }; 254 255#ifdef OFW_DEBUG 256 printf("OF_close(%d)\n", handle); 257#endif 258 args.handle = handle; 259 openfirmware(&args); 260} 261 262int 263OF_write(int handle, void *addr, int len) 264{ 265 static struct { 266 char *name; 267 int nargs; 268 int nreturns; 269 int ihandle; 270 void *addr; 271 int len; 272 int actual; 273 } args = { 274 "write", 275 3, 276 1, 277 }; 278 279#ifdef OFW_DEBUG 280 if (len != 1) 281 printf("OF_write(%d, %p, %x) -> ", handle, addr, len); 282#endif 283 args.ihandle = handle; 284 args.addr = addr; 285 args.len = len; 286 if (openfirmware(&args) == -1) { 287#ifdef OFW_DEBUG 288 printf("lose\n"); 289#endif 290 return -1; 291 } 292#ifdef OFW_DEBUG 293 if (len != 1) 294 printf("%x\n", args.actual); 295#endif 296 return args.actual; 297} 298 299int 300OF_read(int handle, void *addr, int len) 301{ 302 static struct { 303 char *name; 304 int nargs; 305 int nreturns; 306 int ihandle; 307 void *addr; 308 int len; 309 int actual; 310 } args = { 311 "read", 312 3, 313 1, 314 }; 315 316#ifdef OFW_DEBUG 317 if (len != 1) 318 printf("OF_read(%d, %p, %x) -> ", handle, addr, len); 319#endif 320 args.ihandle = handle; 321 args.addr = addr; 322 args.len = len; 323 if (openfirmware(&args) == -1) { 324#ifdef OFW_DEBUG 325 printf("lose\n"); 326#endif 327 return -1; 328 } 329#ifdef OFW_DEBUG 330 if (len != 1) 331 printf("%x\n", args.actual); 332#endif 333 return args.actual; 334} 335 336int 337OF_seek(int handle, u_quad_t pos) 338{ 339 static struct { 340 char *name; 341 int nargs; 342 int nreturns; 343 int handle; 344 int poshi; 345 int poslo; 346 int status; 347 } args = { 348 "seek", 349 3, 350 1, 351 }; 352 353#ifdef OFW_DEBUG 354 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos); 355#endif 356 args.handle = handle; 357 args.poshi = (int)(pos >> 32); 358 args.poslo = (int)pos; 359 if (openfirmware(&args) == -1) { 360#ifdef OFW_DEBUG 361 printf("lose\n"); 362#endif 363 return -1; 364 } 365#ifdef OFW_DEBUG 366 printf("%d\n", args.status); 367#endif 368 return args.status; 369} 370 371void * 372OF_alloc_mem(u_int size) 373{ 374 static struct { 375 char *name; 376 int nargs; 377 int nreturns; 378 u_int size; 379 void *baseaddr; 380 } args = { 381 "alloc-mem", 382 1, 383 1, 384 }; 385#ifdef OFW_DEBUG 386 printf("alloc-mem %x -> ", size); 387#endif 388 if (openfirmware(&args) == -1) { 389#ifdef OFW_DEBUG 390 printf("lose\n"); 391#endif 392 return (void *)-1; 393 } 394#ifdef OFW_DEBUG 395 printf("%p\n", args.baseaddr); 396#endif 397 return args.baseaddr; 398} 399 400void * 401OF_claim(void *virt, u_int size, u_int align) 402{ 403 static struct { 404 char *name; 405 int nargs; 406 int nreturns; 407 void *virt; 408 u_int size; 409 u_int align; 410 void *baseaddr; 411 } args = { 412 "claim", 413 3, 414 1, 415 }; 416 417#ifdef OFW_DEBUG 418 printf("OF_claim(%p, %x, %x) -> ", virt, size, align); 419#endif 420 args.virt = virt; 421 args.size = size; 422 args.align = align; 423 if (openfirmware(&args) == -1) { 424#ifdef OFW_DEBUG 425 printf("lose\n"); 426#endif 427 return (void *)-1; 428 } 429#ifdef OFW_DEBUG 430 printf("%p\n", args.baseaddr); 431#endif 432 return args.baseaddr; 433} 434 435void 436OF_release(void *virt, u_int size) 437{ 438 static struct { 439 char *name; 440 int nargs; 441 int nreturns; 442 void *virt; 443 u_int size; 444 } args = { 445 "release", 446 2, 447 0, 448 }; 449 450#ifdef OFW_DEBUG 451 printf("OF_release(%p, %x)\n", virt, size); 452#endif 453 args.virt = virt; 454 args.size = size; 455 openfirmware(&args); 456} 457 458int 459OF_milliseconds(void) 460{ 461 static struct { 462 char *name; 463 int nargs; 464 int nreturns; 465 int ms; 466 } args = { 467 "milliseconds", 468 0, 469 1, 470 }; 471 472 openfirmware(&args); 473 return args.ms; 474} 475 476#ifdef __notyet__ 477void 478OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 479{ 480 static struct { 481 char *name; 482 int nargs; 483 int nreturns; 484 void *virt; 485 u_int size; 486 void (*entry)(); 487 void *arg; 488 u_int len; 489 } args = { 490 "chain", 491 5, 492 0, 493 }; 494 495 args.virt = virt; 496 args.size = size; 497 args.entry = entry; 498 args.arg = arg; 499 args.len = len; 500 openfirmware(&args); 501} 502#else 503void 504OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len) 505{ 506 /* 507 * This is a REALLY dirty hack till the firmware gets this going 508 */ 509#if 0 510 OF_release(virt, size); 511#endif 512 entry(0, 0, openfirmware_entry, arg, len); 513} 514#endif 515 516static int stdin; 517static int stdout; 518 519static void 520setup(void) 521{ 522 int chosen; 523 524 if ((chosen = OF_finddevice("/chosen")) == -1) 525 OF_exit(); 526 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != 527 sizeof(stdin) || 528 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != 529 sizeof(stdout)) 530 OF_exit(); 531 532 //printf("Allocating 0x20000 bytes of ram for boot\n"); 533 heapspace = OF_claim(0, 0x20000, NBPG); 534 if (heapspace == (char *)-1) { 535 printf("WARNING: Failed to alloc ram, using bss\n"); 536 setheap(&altheap, &altheap[0x20000]); 537 } else 538 setheap(heapspace, heapspace+0x20000); 539} 540 541void 542putchar(int c) 543{ 544 char ch = c; 545 546 if (c == '\n') 547 putchar('\r'); 548 OF_write(stdout, &ch, 1); 549} 550 551int 552getchar(void) 553{ 554 unsigned char ch = '\0'; 555 int l; 556 557 while ((l = OF_read(stdin, &ch, 1)) != 1) 558 if (l != -2 && l != 0) 559 return -1; 560 return ch; 561} 562 563#ifdef OFWDUMP 564 565static int 566OF_peer(int phandle) 567{ 568 static struct { 569 const char *name; 570 int nargs; 571 int nreturns; 572 int phandle; 573 int sibling; 574 } args = { 575 "peer", 576 1, 577 1, 578 }; 579 580 args.phandle = phandle; 581 if (openfirmware(&args) == -1) 582 return 0; 583 return args.sibling; 584} 585 586static int 587OF_child(int phandle) 588{ 589 static struct { 590 const char *name; 591 int nargs; 592 int nreturns; 593 int phandle; 594 int child; 595 } args = { 596 "child", 597 1, 598 1, 599 }; 600 601 args.phandle = phandle; 602 if (openfirmware(&args) == -1) 603 return 0; 604 return args.child; 605} 606 607int 608OF_nextprop(int handle, const char *prop, void *nextprop) 609{ 610 static struct { 611 const char *name; 612 int nargs; 613 int nreturns; 614 int phandle; 615 const char *prop; 616 char *buf; 617 int flag; 618 } args = { 619 "nextprop", 620 3, 621 1, 622 }; 623 624 args.phandle = handle; 625 args.prop = prop; 626 args.buf = nextprop; 627 if (openfirmware(&args) == -1) 628 return -1; 629 return args.flag; 630} 631 632static int 633OF_package_to_path(int phandle, char *buf, int buflen) 634{ 635 static struct { 636 const char *name; 637 int nargs; 638 int nreturns; 639 int phandle; 640 char *buf; 641 int buflen; 642 int length; 643 } args = { 644 "package-to-path", 645 3, 646 1, 647 }; 648 649 if (buflen > 4096) 650 return -1; 651 args.phandle = phandle; 652 args.buf = buf; 653 args.buflen = buflen; 654 if (openfirmware(&args) < 0) 655 return -1; 656 if (args.length > buflen) 657 args.length = buflen; 658 return args.length; 659} 660 661void 662dump_ofwtree(int node) 663{ 664 int peer, child, namelen, dlen, i; 665 char namebuf[33], newnamebuf[33]; 666 char path[256], data[256]; 667 668 for (peer = node; peer; peer = OF_peer(peer)) { 669 printf("\nnode: 0x%x ", peer); 670 if (OF_package_to_path(peer, path, 512) >= 0) 671 printf("path=%s", path); 672 printf("\n"); 673 namebuf[0] = '\0'; 674 namelen = OF_nextprop(peer, namebuf, &newnamebuf); 675 while (namelen >= 0) { 676 /*printf("namelen == %d namebuf=%s new=%s\n", namelen, 677 namebuf, newnamebuf);*/ 678 //newnamebuf[namelen] = '\0'; 679 strcpy(namebuf, newnamebuf); 680 printf(" %s :", newnamebuf); 681 dlen = OF_getprop(peer, newnamebuf, data, 256); 682 if (dlen > 0) { 683 if (data[0] < 0177) 684 printf(" %s\n", data); 685 else 686 printf("\n"); 687 printf(" "); 688 for (i=0; i < dlen && i < 256; i++) { 689 if (data[i] < 0x10) 690 printf("0"); 691 printf("%x", data[i]); 692 if ((i+1)%4 == 0) 693 printf(" "); 694 if ((i+1)%32 == 0) 695 printf("\n "); 696 } 697 } 698 printf("\n"); 699 namelen = OF_nextprop(peer, namebuf, &newnamebuf); 700 if (newnamebuf[0] == '\0' || 701 strcmp(namebuf, newnamebuf) == 0) 702 break; 703 } 704 child = OF_child(peer); 705 if (child > 0) 706 dump_ofwtree(child); 707 } 708} 709 710#endif /* OFWDUMP */ 711