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