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