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