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