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