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