1 /* $NetBSD: Locore.c,v 1.23 2014/09/20 23:10:46 phx 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 40 static int (*openfirmware_entry)(void *); 41 static int openfirmware(void *); 42 43 void startup(void *, int, int (*)(void *), char *, int) 44 __attribute__((__used__)); 45 static void setup(void); 46 47 /* this pad gets the rodata laignment right, don't EVER fiddle it */ 48 char *pad __attribute__((__aligned__ (8))) = "pad"; 49 int stack[0x20000/4 + 4] __attribute__((__aligned__ (4), __used__)); 50 char *heapspace __attribute__((__aligned__ (4))); 51 char altheap[0x20000] __attribute__((__aligned__ (4))); 52 53 static int 54 openfirmware(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 65 void 66 startup(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 76 OF_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 93 OF_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 111 int 112 OF_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 132 int 133 OF_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 153 int 154 OF_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 */ 181 int 182 OF_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 209 int 210 OF_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 241 void 242 OF_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 262 int 263 OF_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 299 int 300 OF_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 336 int 337 OF_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 371 void * 372 OF_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 400 void * 401 OF_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 435 void 436 OF_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 458 int 459 OF_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__ 477 void 478 OF_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 503 void 504 OF_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 516 static int stdin; 517 static int stdout; 518 519 static void 520 setup(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 541 void 542 putchar(int c) 543 { 544 char ch = c; 545 546 if (c == '\n') 547 putchar('\r'); 548 OF_write(stdout, &ch, 1); 549 } 550 551 int 552 getchar(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 565 static int 566 OF_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 586 static int 587 OF_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 607 int 608 OF_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 632 static int 633 OF_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 661 void 662 dump_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