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