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