1 /* $NetBSD: Locore.c,v 1.35 2021/02/28 20:27:40 thorpej 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 #include <powerpc/oea/spr.h>
39
40 #include "openfirm.h"
41
42 static int (*openfirmware)(void *);
43
44 static void startup(void *, int, int (*)(void *), char *, int)
45 __attribute__((__used__));
46 static void setup(void);
47
48 #ifdef HEAP_VARIABLE
49 #ifndef HEAP_SIZE
50 #define HEAP_SIZE 0x20000
51 #endif
52 char *heapspace;
53 #endif
54
55 static int stack[8192/4 + 4] __attribute__((__used__));
56
57 #ifdef XCOFF_GLUE
58 __asm(
59 " .text \n"
60 " .globl _entry \n"
61 "_entry: \n"
62 " .long _start,0,0 \n"
63 );
64 #endif /* XCOFF_GLUE */
65
66 __asm(
67 " .text \n"
68 " .globl _start \n"
69 "_start: \n"
70 " sync \n"
71 " isync \n"
72 " lis %r1,stack@ha \n"
73 " addi %r1,%r1,stack@l \n"
74 " addi %r1,%r1,8192 \n"
75 " \n"
76 " mfmsr %r8 \n"
77 " li %r0,0 \n"
78 " mtmsr %r0 \n"
79 " isync \n"
80 " \n"
81 " \n" /* test for 601 */
82 " mfspr %r0,287 \n" /* mfpvbr %r0 PVR = 287 */
83 " srwi %r0,%r0,0x10 \n"
84 " cmplwi %r0,0x02 \n" /* 601 CPU = 0x0001 */
85 " blt 2f \n" /* skip over non-601 BAT setup */
86 " cmplwi %r0,0x39 \n" /* PPC970 */
87 " blt 0f \n"
88 " cmplwi %r0,0x45 \n" /* PPC970GX */
89 " ble 1f \n"
90 /* non PPC 601 BATs */
91 "0: li %r0,0 \n"
92 " mtibatu 0,%r0 \n"
93 " mtibatu 1,%r0 \n"
94 " mtibatu 2,%r0 \n"
95 " mtibatu 3,%r0 \n"
96 " mtdbatu 0,%r0 \n"
97 " mtdbatu 1,%r0 \n"
98 " mtdbatu 2,%r0 \n"
99 " mtdbatu 3,%r0 \n"
100 " \n"
101 " li %r9,0x12 \n" /* BATL(0, BAT_M, BAT_PP_RW) */
102 " mtibatl 0,%r9 \n"
103 " mtdbatl 0,%r9 \n"
104 " li %r9,0x1ffe \n" /* BATU(0, BAT_BL_256M, BAT_Vs) */
105 " mtibatu 0,%r9 \n"
106 " mtdbatu 0,%r9 \n"
107 " b 3f \n"
108 /* 970 initialization stuff */
109 "1: \n"
110 /* make sure we're in bridge mode */
111 " clrldi %r8,%r8,3 \n"
112 " mtmsrd %r8 \n"
113 " isync \n"
114 /* clear HID5 DCBZ bits (56/57), need to do this early */
115 " mfspr %r9,0x3f6 \n"
116 " rldimi %r9,0,6,56 \n"
117 " sync \n"
118 " mtspr 0x3f6,%r9 \n"
119 " isync \n"
120 " sync \n"
121 /* Setup HID1 features, prefetch + i-cacheability controlled by PTE */
122 " mfspr %r9,0x3f1 \n"
123 " li %r11,0x1200 \n"
124 " sldi %r11,%r11,44 \n"
125 " or %r9,%r9,%r11 \n"
126 " mtspr 0x3f1,%r9 \n"
127 " isync \n"
128 " sync \n"
129 " b 3f \n"
130 /* PPC 601 BATs */
131 "2: li %r0,0 \n"
132 " mtibatu 0,%r0 \n"
133 " mtibatu 1,%r0 \n"
134 " mtibatu 2,%r0 \n"
135 " mtibatu 3,%r0 \n"
136 " \n"
137 " li %r9,0x7f \n"
138 " mtibatl 0,%r9 \n"
139 " li %r9,0x1a \n"
140 " mtibatu 0,%r9 \n"
141 " \n"
142 " lis %r9,0x80 \n"
143 " addi %r9,%r9,0x7f \n"
144 " mtibatl 1,%r9 \n"
145 " lis %r9,0x80 \n"
146 " addi %r9,%r9,0x1a \n"
147 " mtibatu 1,%r9 \n"
148 " \n"
149 " lis %r9,0x100 \n"
150 " addi %r9,%r9,0x7f \n"
151 " mtibatl 2,%r9 \n"
152 " lis %r9,0x100 \n"
153 " addi %r9,%r9,0x1a \n"
154 " mtibatu 2,%r9 \n"
155 " \n"
156 " lis %r9,0x180 \n"
157 " addi %r9,%r9,0x7f \n"
158 " mtibatl 3,%r9 \n"
159 " lis %r9,0x180 \n"
160 " addi %r9,%r9,0x1a \n"
161 " mtibatu 3,%r9 \n"
162 " \n"
163 "3: isync \n"
164 " \n"
165 " mtmsr %r8 \n"
166 " isync \n"
167 " \n"
168 /*
169 * Make sure that .bss is zeroed
170 */
171 " \n"
172 " li %r0,0 \n"
173 " lis %r8,_edata@ha \n"
174 " addi %r8,%r8,_edata@l\n"
175 " lis %r9,_end@ha \n"
176 " addi %r9,%r9,_end@l \n"
177 " \n"
178 "5: cmpw 0,%r8,%r9 \n"
179 " bge 6f \n"
180 /*
181 * clear by bytes to avoid ppc601 alignment exceptions
182 */
183 " stb %r0,0(%r8) \n"
184 " stb %r0,1(%r8) \n"
185 " stb %r0,2(%r8) \n"
186 " stb %r0,3(%r8) \n"
187 " addi %r8,%r8,4 \n"
188 " b 5b \n"
189 " \n"
190 "6: b startup \n"
191 );
192
193 #if 0
194 static int
195 openfirmware(void *arg)
196 {
197
198 __asm volatile ("sync; isync");
199 openfirmware_entry(arg);
200 __asm volatile ("sync; isync");
201 }
202 #endif
203
204 int ofw_real_mode;
205 int ofw_address_cells;
206 int ofw_size_cells;
207
208 int ofw_root; /* / */
209 int ofw_options; /* /options */
210 int ofw_openprom; /* /openprom */
211 int ofw_chosen; /* /chosen (package) */
212 int ofw_stdin; /* /chosen/stdin */
213 int ofw_stdout; /* /chosen/stdout */
214 int ofw_memory_ihandle; /* /chosen/memory */
215 int ofw_mmu_ihandle; /* /chosen/mmu */
216
217 bool
218 ofw_option_truefalse(const char *prop, int proplen)
219 {
220 /* These are all supposed to be strings. */
221 switch (prop[0]) {
222 case 'y':
223 case 'Y':
224 case 't':
225 case 'T':
226 case '1':
227 return true;
228 }
229 return false;
230 }
231
232 static void
233 startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
234 {
235
236 openfirmware = openfirm;
237 setup();
238 main();
239 OF_exit();
240 }
241
242 #if 0
243 void
244 OF_enter(void)
245 {
246 static struct {
247 const char *name;
248 int nargs;
249 int nreturns;
250 } args = {
251 "enter",
252 0,
253 0
254 };
255
256 openfirmware(&args);
257 }
258 #endif /* OF_enter */
259
260 __dead void
261 OF_exit(void)
262 {
263 static struct {
264 const char *name;
265 int nargs;
266 int nreturns;
267 } args = {
268 "exit",
269 0,
270 0
271 };
272
273 openfirmware(&args);
274 for (;;); /* just in case */
275 }
276
277 int
278 OF_finddevice(const char *name)
279 {
280 static struct {
281 const char *name;
282 int nargs;
283 int nreturns;
284 const char *device;
285 int phandle;
286 } args = {
287 "finddevice",
288 1,
289 1,
290 };
291
292 args.device = name;
293 if (openfirmware(&args) == -1)
294 return -1;
295 return args.phandle;
296 }
297
298 int
299 OF_instance_to_package(int ihandle)
300 {
301 static struct {
302 const char *name;
303 int nargs;
304 int nreturns;
305 int ihandle;
306 int phandle;
307 } args = {
308 "instance-to-package",
309 1,
310 1,
311 };
312
313 args.ihandle = ihandle;
314 if (openfirmware(&args) == -1)
315 return -1;
316 return args.phandle;
317 }
318
319 int
320 OF_getprop(int handle, const char *prop, void *buf, int buflen)
321 {
322 static struct {
323 const char *name;
324 int nargs;
325 int nreturns;
326 int phandle;
327 const char *prop;
328 void *buf;
329 int buflen;
330 int size;
331 } args = {
332 "getprop",
333 4,
334 1,
335 };
336
337 args.phandle = handle;
338 args.prop = prop;
339 args.buf = buf;
340 args.buflen = buflen;
341 if (openfirmware(&args) == -1)
342 return -1;
343 return args.size;
344 }
345
346 #ifdef __notyet__ /* Has a bug on FirePower */
347 int
348 OF_setprop(int handle, const char *prop, void *buf, int len)
349 {
350 static struct {
351 const char *name;
352 int nargs;
353 int nreturns;
354 int phandle;
355 const char *prop;
356 void *buf;
357 int len;
358 int size;
359 } args = {
360 "setprop",
361 4,
362 1,
363 };
364
365 args.phandle = handle;
366 args.prop = prop;
367 args.buf = buf;
368 args.len = len;
369 if (openfirmware(&args) == -1)
370 return -1;
371 return args.size;
372 }
373 #endif
374
375 int
376 OF_open(const char *dname)
377 {
378 static struct {
379 const char *name;
380 int nargs;
381 int nreturns;
382 const char *dname;
383 int handle;
384 } args = {
385 "open",
386 1,
387 1,
388 };
389
390 #ifdef OFW_DEBUG
391 printf("OF_open(%s) -> ", dname);
392 #endif
393 args.dname = dname;
394 if (openfirmware(&args) == -1 ||
395 args.handle == 0) {
396 #ifdef OFW_DEBUG
397 printf("lose\n");
398 #endif
399 return -1;
400 }
401 #ifdef OFW_DEBUG
402 printf("%d\n", args.handle);
403 #endif
404 return args.handle;
405 }
406
407 void
408 OF_close(int handle)
409 {
410 static struct {
411 const char *name;
412 int nargs;
413 int nreturns;
414 int handle;
415 } args = {
416 "close",
417 1,
418 0,
419 };
420
421 #ifdef OFW_DEBUG
422 printf("OF_close(%d)\n", handle);
423 #endif
424 args.handle = handle;
425 openfirmware(&args);
426 }
427
428 int
429 OF_write(int handle, void *addr, int len)
430 {
431 static struct {
432 const char *name;
433 int nargs;
434 int nreturns;
435 int ihandle;
436 void *addr;
437 int len;
438 int actual;
439 } args = {
440 "write",
441 3,
442 1,
443 };
444
445 #ifdef OFW_DEBUG
446 if (len != 1)
447 printf("OF_write(%d, %p, %x) -> ", handle, addr, len);
448 #endif
449 args.ihandle = handle;
450 args.addr = addr;
451 args.len = len;
452 if (openfirmware(&args) == -1) {
453 #ifdef OFW_DEBUG
454 printf("lose\n");
455 #endif
456 return -1;
457 }
458 #ifdef OFW_DEBUG
459 if (len != 1)
460 printf("%x\n", args.actual);
461 #endif
462 return args.actual;
463 }
464
465 int
466 OF_read(int handle, void *addr, int len)
467 {
468 static struct {
469 const char *name;
470 int nargs;
471 int nreturns;
472 int ihandle;
473 void *addr;
474 int len;
475 int actual;
476 } args = {
477 "read",
478 3,
479 1,
480 };
481
482 #ifdef OFW_DEBUG
483 if (len != 1)
484 printf("OF_read(%d, %p, %x) -> ", handle, addr, len);
485 #endif
486 args.ihandle = handle;
487 args.addr = addr;
488 args.len = len;
489 if (openfirmware(&args) == -1) {
490 #ifdef OFW_DEBUG
491 printf("lose\n");
492 #endif
493 return -1;
494 }
495 #ifdef OFW_DEBUG
496 if (len != 1)
497 printf("%x\n", args.actual);
498 #endif
499 return args.actual;
500 }
501
502 int
503 OF_seek(int handle, u_quad_t pos)
504 {
505 static struct {
506 const char *name;
507 int nargs;
508 int nreturns;
509 int handle;
510 int poshi;
511 int poslo;
512 int status;
513 } args = {
514 "seek",
515 3,
516 1,
517 };
518
519 #ifdef OFW_DEBUG
520 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
521 #endif
522 args.handle = handle;
523 args.poshi = (int)(pos >> 32);
524 args.poslo = (int)pos;
525 if (openfirmware(&args) == -1) {
526 #ifdef OFW_DEBUG
527 printf("lose\n");
528 #endif
529 return -1;
530 }
531 #ifdef OFW_DEBUG
532 printf("%d\n", args.status);
533 #endif
534 return args.status;
535 }
536
537 void *
538 OF_claim(void *virt, u_int size, u_int align)
539 {
540 static struct {
541 const char *name;
542 int nargs;
543 int nreturns;
544 void *virt;
545 u_int size;
546 u_int align;
547 void *baseaddr;
548 } args = {
549 "claim",
550 3,
551 1,
552 };
553
554 #ifdef OFW_DEBUG
555 printf("OF_claim(%p, %x, %x) -> ", virt, size, align);
556 #endif
557 args.virt = virt;
558 args.size = size;
559 args.align = align;
560 if (openfirmware(&args) == -1) {
561 #ifdef OFW_DEBUG
562 printf("lose\n");
563 #endif
564 return (void *)-1;
565 }
566 #ifdef OFW_DEBUG
567 printf("%p\n", args.baseaddr);
568 #endif
569 return args.baseaddr;
570 }
571
572 void
573 OF_release(void *virt, u_int size)
574 {
575 static struct {
576 const char *name;
577 int nargs;
578 int nreturns;
579 void *virt;
580 u_int size;
581 } args = {
582 "release",
583 2,
584 0,
585 };
586
587 #ifdef OFW_DEBUG
588 printf("OF_release(%p, %x)\n", virt, size);
589 #endif
590 args.virt = virt;
591 args.size = size;
592 openfirmware(&args);
593 }
594
595 int
596 OF_milliseconds(void)
597 {
598 static struct {
599 const char *name;
600 int nargs;
601 int nreturns;
602 int ms;
603 } args = {
604 "milliseconds",
605 0,
606 1,
607 };
608
609 openfirmware(&args);
610 return args.ms;
611 }
612
613 #ifdef __notyet__
614 void
615 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
616 {
617 static struct {
618 const char *name;
619 int nargs;
620 int nreturns;
621 void *virt;
622 u_int size;
623 void (*entry)();
624 void *arg;
625 u_int len;
626 } args = {
627 "chain",
628 5,
629 0,
630 };
631
632 args.virt = virt;
633 args.size = size;
634 args.entry = entry;
635 args.arg = arg;
636 args.len = len;
637 openfirmware(&args);
638 }
639 #else
640 void
641 OF_chain(void *virt, u_int size, boot_entry_t entry, void *arg, u_int len)
642 {
643 /*
644 * This is a REALLY dirty hack till the firmware gets this going
645 */
646 #if 0
647 OF_release(virt, size);
648 #endif
649 entry(0, 0, openfirmware, arg, len);
650 }
651 #endif
652
653 int
654 OF_call_method(const char *method, int ihandle, int nargs, int nreturns,
655 int *cells)
656 {
657 static struct {
658 const char *name;
659 int nargs;
660 int nreturns;
661 const char *method;
662 int ihandle;
663 int args_n_results[12];
664 } args = {
665 "call-method",
666 2,
667 1,
668 };
669 int *ip, n;
670
671 if (nargs > 6)
672 return -1;
673
674 args.nargs = nargs + 2;
675 args.nreturns = nreturns + 1;
676 args.method = method;
677 args.ihandle = ihandle;
678
679 for (ip = args.args_n_results + (n = nargs); --n >= 0;)
680 *--ip = *cells++;
681
682 if (openfirmware(&args) == -1) {
683 return -1;
684 }
685
686 if (args.args_n_results[nargs]) {
687 return args.args_n_results[nargs];
688 }
689
690 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
691 *cells++ = *--ip;
692
693 return 0;
694 }
695
696 static void
697 setup(void)
698 {
699 char prop[32];
700 int proplen;
701 const char *reason = NULL;
702
703 if ((ofw_chosen = OF_finddevice("/chosen")) == -1)
704 OF_exit();
705 if (OF_getprop(ofw_chosen, "stdin", &ofw_stdin, sizeof(ofw_stdin)) !=
706 sizeof(ofw_stdin) ||
707 OF_getprop(ofw_chosen, "stdout", &ofw_stdout, sizeof(ofw_stdout)) !=
708 sizeof(ofw_stdout))
709 OF_exit();
710
711 if (ofw_stdout == 0) {
712 /* screen should be console, but it is not open */
713 ofw_stdout = OF_open("screen");
714 }
715
716 #ifdef HEAP_VARIABLE
717 uint32_t pvr, vers, hsize = HEAP_SIZE;
718
719 __asm volatile ("mfpvr %0" : "=r"(pvr));
720 vers = pvr >> 16;
721 if (vers >= IBM970 && vers <= IBM970GX) hsize = 0x800000;
722
723 heapspace = OF_claim(0, hsize, NBPG);
724 if (heapspace == (char *)-1) {
725 panic("Failed to allocate heap");
726 }
727
728 setheap(heapspace, heapspace + HEAP_SIZE);
729 #endif /* HEAP_VARIABLE */
730
731 ofw_root = OF_finddevice("/");
732 ofw_options = OF_finddevice("/options");
733 ofw_openprom = OF_finddevice("/openprom");
734 ofw_chosen = OF_finddevice("/chosen");
735
736 if (ofw_root == -1) {
737 reason = "No root node";
738 goto bad_environment;
739 }
740 if (ofw_chosen == -1) {
741 reason = "No chosen node";
742 goto bad_environment;
743 }
744
745 if (ofw_options != -1) {
746 proplen = OF_getprop(ofw_options, "real-mode?", prop,
747 sizeof(prop));
748 if (proplen > 0) {
749 ofw_real_mode = ofw_option_truefalse(prop, proplen);
750 }
751 }
752
753 /*
754 * Get #address-cells and #size-cells.
755 */
756 ofw_address_cells = 1;
757 ofw_size_cells = 1;
758 OF_getprop(ofw_root, "#address-cells", &ofw_address_cells,
759 sizeof(ofw_address_cells));
760 OF_getprop(ofw_root, "#size-cells", &ofw_size_cells,
761 sizeof(ofw_size_cells));
762
763 /* See loadfile_machdep.c */
764 if (ofw_size_cells != 1) {
765 printf("#size-cells = %d not yet supported\n", ofw_size_cells);
766 reason = "unsupported #size-cells";
767 goto bad_environment;
768 }
769
770 /*
771 * Get the ihandle on /chosen/memory and /chosen/mmu.
772 */
773 ofw_memory_ihandle = -1;
774 ofw_mmu_ihandle = -1;
775 OF_getprop(ofw_chosen, "memory", &ofw_memory_ihandle,
776 sizeof(ofw_memory_ihandle));
777 OF_getprop(ofw_chosen, "mmu", &ofw_mmu_ihandle,
778 sizeof(ofw_mmu_ihandle));
779 if (ofw_memory_ihandle == -1) {
780 reason = "no /chosen/memory";
781 goto bad_environment;
782 }
783 if (ofw_mmu_ihandle == -1) {
784 reason = "no /chosen/mmu";
785 goto bad_environment;
786 }
787
788 return;
789
790 bad_environment:
791 if (reason == NULL) {
792 reason = "unknown reason";
793 }
794 printf("Invalid Openfirmware environment: %s\n", reason);
795 OF_exit();
796 }
797
798 void
799 putchar(int c)
800 {
801 char ch = c;
802
803 if (c == '\n')
804 putchar('\r');
805 OF_write(ofw_stdout, &ch, 1);
806 }
807
808 int
809 getchar(void)
810 {
811 unsigned char ch = '\0';
812 int l;
813
814 while ((l = OF_read(ofw_stdin, &ch, 1)) != 1)
815 if (l != -2 && l != 0)
816 return -1;
817 return ch;
818 }
Cache object: 5cb393a5dbe33f3847e84c7a3c108a25
|