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