1 /* $NetBSD: Locore.c,v 1.31 2018/06/06 23:50:29 uwe 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 <sys/param.h> 35 #include <lib/libsa/stand.h> 36 37 #include <machine/cpu.h> 38 39 #include "openfirm.h" 40 41 static int (*openfirmware)(void *); 42 43 static void startup(void *, int, int (*)(void *), char *, int) 44 __attribute__((__used__)); 45 static void setup(void); 46 47 #ifdef HEAP_VARIABLE 48 #ifndef HEAP_SIZE 49 #define HEAP_SIZE 0x20000 50 #endif 51 char *heapspace; 52 #endif 53 54 static int stack[8192/4 + 4] __attribute__((__used__)); 55 56 #ifdef XCOFF_GLUE 57 __asm( 58 " .text \n" 59 " .globl _entry \n" 60 "_entry: \n" 61 " .long _start,0,0 \n" 62 ); 63 #endif /* XCOFF_GLUE */ 64 65 __asm( 66 " .text \n" 67 " .globl _start \n" 68 "_start: \n" 69 " sync \n" 70 " isync \n" 71 " lis %r1,stack@ha \n" 72 " addi %r1,%r1,stack@l \n" 73 " addi %r1,%r1,8192 \n" 74 " \n" 75 " mfmsr %r8 \n" 76 " li %r0,0 \n" 77 " mtmsr %r0 \n" 78 " isync \n" 79 " \n" 80 " \n" /* test for 601 */ 81 " mfspr %r0,287 \n" /* mfpvbr %r0 PVR = 287 */ 82 " srwi %r0,%r0,0x10 \n" 83 " cmpi 0,1,%r0,0x02 \n" /* 601 CPU = 0x0001 */ 84 " blt 1f \n" /* skip over non-601 BAT setup */ 85 /* non PPC 601 BATs */ 86 " li %r0,0 \n" 87 " mtibatu 0,%r0 \n" 88 " mtibatu 1,%r0 \n" 89 " mtibatu 2,%r0 \n" 90 " mtibatu 3,%r0 \n" 91 " mtdbatu 0,%r0 \n" 92 " mtdbatu 1,%r0 \n" 93 " mtdbatu 2,%r0 \n" 94 " mtdbatu 3,%r0 \n" 95 " \n" 96 " li %r9,0x12 \n" /* BATL(0, BAT_M, BAT_PP_RW) */ 97 " mtibatl 0,%r9 \n" 98 " mtdbatl 0,%r9 \n" 99 " li %r9,0x1ffe \n" /* BATU(0, BAT_BL_256M, BAT_Vs) */ 100 " mtibatu 0,%r9 \n" 101 " mtdbatu 0,%r9 \n" 102 " b 2f \n" 103 104 /* PPC 601 BATs */ 105 "1: li %r0,0 \n" 106 " mtibatu 0,%r0 \n" 107 " mtibatu 1,%r0 \n" 108 " mtibatu 2,%r0 \n" 109 " mtibatu 3,%r0 \n" 110 " \n" 111 " li %r9,0x7f \n" 112 " mtibatl 0,%r9 \n" 113 " li %r9,0x1a \n" 114 " mtibatu 0,%r9 \n" 115 " \n" 116 " lis %r9,0x80 \n" 117 " addi %r9,%r9,0x7f \n" 118 " mtibatl 1,%r9 \n" 119 " lis %r9,0x80 \n" 120 " addi %r9,%r9,0x1a \n" 121 " mtibatu 1,%r9 \n" 122 " \n" 123 " lis %r9,0x100 \n" 124 " addi %r9,%r9,0x7f \n" 125 " mtibatl 2,%r9 \n" 126 " lis %r9,0x100 \n" 127 " addi %r9,%r9,0x1a \n" 128 " mtibatu 2,%r9 \n" 129 " \n" 130 " lis %r9,0x180 \n" 131 " addi %r9,%r9,0x7f \n" 132 " mtibatl 3,%r9 \n" 133 " lis %r9,0x180 \n" 134 " addi %r9,%r9,0x1a \n" 135 " mtibatu 3,%r9 \n" 136 " \n" 137 "2: isync \n" 138 " \n" 139 " mtmsr %r8 \n" 140 " isync \n" 141 " \n" 142 /* 143 * Make sure that .bss is zeroed 144 */ 145 " \n" 146 " li %r0,0 \n" 147 " lis %r8,_edata@ha \n" 148 " addi %r8,%r8,_edata@l\n" 149 " lis %r9,_end@ha \n" 150 " addi %r9,%r9,_end@l \n" 151 " \n" 152 "5: cmpw 0,%r8,%r9 \n" 153 " bge 6f \n" 154 " stw %r0,0(%r8) \n" 155 " addi %r8,%r8,4 \n" 156 " b 5b \n" 157 " \n" 158 "6: b startup \n" 159 ); 160 161 #if 0 162 static int 163 openfirmware(void *arg) 164 { 165 166 __asm volatile ("sync; isync"); 167 openfirmware_entry(arg); 168 __asm volatile ("sync; isync"); 169 } 170 #endif 171 172 static void 173 startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) 174 { 175 176 openfirmware = openfirm; 177 setup(); 178 main(); 179 OF_exit(); 180 } 181 182 #if 0 183 void 184 OF_enter(void) 185 { 186 static struct { 187 const char *name; 188 int nargs; 189 int nreturns; 190 } args = { 191 "enter", 192 0, 193 0 194 }; 195 196 openfirmware(&args); 197 } 198 #endif /* OF_enter */ 199 200 __dead void 201 OF_exit(void) 202 { 203 static struct { 204 const char *name; 205 int nargs; 206 int nreturns; 207 } args = { 208 "exit", 209 0, 210 0 211 }; 212 213 openfirmware(&args); 214 for (;;); /* just in case */ 215 } 216 217 int 218 OF_finddevice(const char *name) 219 { 220 static struct { 221 const char *name; 222 int nargs; 223 int nreturns; 224 const char *device; 225 int phandle; 226 } args = { 227 "finddevice", 228 1, 229 1, 230 }; 231 232 args.device = name; 233 if (openfirmware(&args) == -1) 234 return -1; 235 return args.phandle; 236 } 237 238 int 239 OF_instance_to_package(int ihandle) 240 { 241 static struct { 242 const char *name; 243 int nargs; 244 int nreturns; 245 int ihandle; 246 int phandle; 247 } args = { 248 "instance-to-package", 249 1, 250 1, 251 }; 252 253 args.ihandle = ihandle; 254 if (openfirmware(&args) == -1) 255 return -1; 256 return args.phandle; 257 } 258 259 int 260 OF_getprop(int handle, const char *prop, void *buf, int buflen) 261 { 262 static struct { 263 const char *name; 264 int nargs; 265 int nreturns; 266 int phandle; 267 const char *prop; 268 void *buf; 269 int buflen; 270 int size; 271 } args = { 272 "getprop", 273 4, 274 1, 275 }; 276 277 args.phandle = handle; 278 args.prop = prop; 279 args.buf = buf; 280 args.buflen = buflen; 281 if (openfirmware(&args) == -1) 282 return -1; 283 return args.size; 284 } 285 286 #ifdef __notyet__ /* Has a bug on FirePower */ 287 int 288 OF_setprop(int handle, const char *prop, void *buf, int len) 289 { 290 static struct { 291 const char *name; 292 int nargs; 293 int nreturns; 294 int phandle; 295 const char *prop; 296 void *buf; 297 int len; 298 int size; 299 } args = { 300 "setprop", 301 4, 302 1, 303 }; 304 305 args.phandle = handle; 306 args.prop = prop; 307 args.buf = buf; 308 args.len = len; 309 if (openfirmware(&args) == -1) 310 return -1; 311 return args.size; 312 } 313 #endif 314 315 int 316 OF_open(const char *dname) 317 { 318 static struct { 319 const char *name; 320 int nargs; 321 int nreturns; 322 const char *dname; 323 int handle; 324 } args = { 325 "open", 326 1, 327 1, 328 }; 329 330 #ifdef OFW_DEBUG 331 printf("OF_open(%s) -> ", dname); 332 #endif 333 args.dname = dname; 334 if (openfirmware(&args) == -1 || 335 args.handle == 0) { 336 #ifdef OFW_DEBUG 337 printf("lose\n"); 338 #endif 339 return -1; 340 } 341 #ifdef OFW_DEBUG 342 printf("%d\n", args.handle); 343 #endif 344 return args.handle; 345 } 346 347 void 348 OF_close(int handle) 349 { 350 static struct { 351 const char *name; 352 int nargs; 353 int nreturns; 354 int handle; 355 } args = { 356 "close", 357 1, 358 0, 359 }; 360 361 #ifdef OFW_DEBUG 362 printf("OF_close(%d)\n", handle); 363 #endif 364 args.handle = handle; 365 openfirmware(&args); 366 } 367 368 int 369 OF_write(int handle, void *addr, int len) 370 { 371 static struct { 372 const char *name; 373 int nargs; 374 int nreturns; 375 int ihandle; 376 void *addr; 377 int len; 378 int actual; 379 } args = { 380 "write", 381 3, 382 1, 383 }; 384 385 #ifdef OFW_DEBUG 386 if (len != 1) 387 printf("OF_write(%d, %p, %x) -> ", handle, addr, len); 388 #endif 389 args.ihandle = handle; 390 args.addr = addr; 391 args.len = len; 392 if (openfirmware(&args) == -1) { 393 #ifdef OFW_DEBUG 394 printf("lose\n"); 395 #endif 396 return -1; 397 } 398 #ifdef OFW_DEBUG 399 if (len != 1) 400 printf("%x\n", args.actual); 401 #endif 402 return args.actual; 403 } 404 405 int 406 OF_read(int handle, void *addr, int len) 407 { 408 static struct { 409 const char *name; 410 int nargs; 411 int nreturns; 412 int ihandle; 413 void *addr; 414 int len; 415 int actual; 416 } args = { 417 "read", 418 3, 419 1, 420 }; 421 422 #ifdef OFW_DEBUG 423 if (len != 1) 424 printf("OF_read(%d, %p, %x) -> ", handle, addr, len); 425 #endif 426 args.ihandle = handle; 427 args.addr = addr; 428 args.len = len; 429 if (openfirmware(&args) == -1) { 430 #ifdef OFW_DEBUG 431 printf("lose\n"); 432 #endif 433 return -1; 434 } 435 #ifdef OFW_DEBUG 436 if (len != 1) 437 printf("%x\n", args.actual); 438 #endif 439 return args.actual; 440 } 441 442 int 443 OF_seek(int handle, u_quad_t pos) 444 { 445 static struct { 446 const char *name; 447 int nargs; 448 int nreturns; 449 int handle; 450 int poshi; 451 int poslo; 452 int status; 453 } args = { 454 "seek", 455 3, 456 1, 457 }; 458 459 #ifdef OFW_DEBUG 460 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos); 461 #endif 462 args.handle = handle; 463 args.poshi = (int)(pos >> 32); 464 args.poslo = (int)pos; 465 if (openfirmware(&args) == -1) { 466 #ifdef OFW_DEBUG 467 printf("lose\n"); 468 #endif 469 return -1; 470 } 471 #ifdef OFW_DEBUG 472 printf("%d\n", args.status); 473 #endif 474 return args.status; 475 } 476 477 void * 478 OF_claim(void *virt, u_int size, u_int align) 479 { 480 static struct { 481 const char *name; 482 int nargs; 483 int nreturns; 484 void *virt; 485 u_int size; 486 u_int align; 487 void *baseaddr; 488 } args = { 489 "claim", 490 3, 491 1, 492 }; 493 494 #ifdef OFW_DEBUG 495 printf("OF_claim(%p, %x, %x) -> ", virt, size, align); 496 #endif 497 args.virt = virt; 498 args.size = size; 499 args.align = align; 500 if (openfirmware(&args) == -1) { 501 #ifdef OFW_DEBUG 502 printf("lose\n"); 503 #endif 504 return (void *)-1; 505 } 506 #ifdef OFW_DEBUG 507 printf("%p\n", args.baseaddr); 508 #endif 509 return args.baseaddr; 510 } 511 512 void 513 OF_release(void *virt, u_int size) 514 { 515 static struct { 516 const char *name; 517 int nargs; 518 int nreturns; 519 void *virt; 520 u_int size; 521 } args = { 522 "release", 523 2, 524 0, 525 }; 526 527 #ifdef OFW_DEBUG 528 printf("OF_release(%p, %x)\n", virt, size); 529 #endif 530 args.virt = virt; 531 args.size = size; 532 openfirmware(&args); 533 } 534 535 int 536 OF_milliseconds(void) 537 { 538 static struct { 539 const char *name; 540 int nargs; 541 int nreturns; 542 int ms; 543 } args = { 544 "milliseconds", 545 0, 546 1, 547 }; 548 549 openfirmware(&args); 550 return args.ms; 551 } 552 553 #ifdef __notyet__ 554 void 555 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 556 { 557 static struct { 558 const char *name; 559 int nargs; 560 int nreturns; 561 void *virt; 562 u_int size; 563 void (*entry)(); 564 void *arg; 565 u_int len; 566 } args = { 567 "chain", 568 5, 569 0, 570 }; 571 572 args.virt = virt; 573 args.size = size; 574 args.entry = entry; 575 args.arg = arg; 576 args.len = len; 577 openfirmware(&args); 578 } 579 #else 580 void 581 OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len) 582 { 583 /* 584 * This is a REALLY dirty hack till the firmware gets this going 585 */ 586 #if 0 587 OF_release(virt, size); 588 #endif 589 entry(0, 0, openfirmware, arg, len); 590 } 591 #endif 592 593 int 594 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...) 595 { 596 va_list ap; 597 static struct { 598 const char *name; 599 int nargs; 600 int nreturns; 601 const char *method; 602 int ihandle; 603 int args_n_results[12]; 604 } args = { 605 "call-method", 606 2, 607 1, 608 }; 609 int *ip, n; 610 611 if (nargs > 6) 612 return -1; 613 args.nargs = nargs + 2; 614 args.nreturns = nreturns + 1; 615 args.method = method; 616 args.ihandle = ihandle; 617 va_start(ap, nreturns); 618 for (ip = args.args_n_results + (n = nargs); --n >= 0;) 619 *--ip = va_arg(ap, int); 620 621 if (openfirmware(&args) == -1) { 622 va_end(ap); 623 return -1; 624 } 625 if (args.args_n_results[nargs]) { 626 va_end(ap); 627 return args.args_n_results[nargs]; 628 } 629 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 630 *va_arg(ap, int *) = *--ip; 631 va_end(ap); 632 return 0; 633 } 634 635 static int stdin; 636 static int stdout; 637 638 static void 639 setup(void) 640 { 641 int chosen; 642 643 if ((chosen = OF_finddevice("/chosen")) == -1) 644 OF_exit(); 645 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != 646 sizeof(stdin) || 647 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != 648 sizeof(stdout)) 649 OF_exit(); 650 651 #ifdef HEAP_VARIABLE 652 heapspace = OF_claim(0, HEAP_SIZE, NBPG); 653 if (heapspace == (char *)-1) { 654 panic("Failed to allocate heap"); 655 } 656 657 setheap(heapspace, heapspace + HEAP_SIZE); 658 #endif /* HEAP_VARIABLE */ 659 } 660 661 void 662 putchar(int c) 663 { 664 char ch = c; 665 666 if (c == '\n') 667 putchar('\r'); 668 OF_write(stdout, &ch, 1); 669 } 670 671 int 672 getchar(void) 673 { 674 unsigned char ch = '\0'; 675 int l; 676 677 while ((l = OF_read(stdin, &ch, 1)) != 1) 678 if (l != -2 && l != 0) 679 return -1; 680 return ch; 681 } 682