xref: /openbsd/sys/arch/sparc64/stand/ofwboot/Locore.c (revision e5dd7070)
1 /*	$OpenBSD: Locore.c,v 1.16 2018/12/31 11:44:57 claudio Exp $	*/
2 /*	$NetBSD: Locore.c,v 1.1 2000/08/20 14:58:36 mrg Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6  * Copyright (C) 1995, 1996 TooLs GmbH.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by TooLs GmbH.
20  * 4. The name of TooLs GmbH may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <lib/libsa/stand.h>
36 
37 #include "openfirm.h"
38 
39 #include <machine/cpu.h>
40 
41 #ifdef SOFTRAID
42 #include <dev/softraidvar.h>
43 #include <lib/libsa/softraid.h>
44 #endif
45 
46 static vaddr_t OF_claim_virt(vaddr_t vaddr, int len);
47 static vaddr_t OF_alloc_virt(int len, int align);
48 static int OF_free_virt(vaddr_t vaddr, int len);
49 static vaddr_t OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode);
50 static paddr_t OF_alloc_phys(int len, int align);
51 static int OF_free_phys(paddr_t paddr, int len);
52 
53 extern int openfirmware(void *);
54 
55 void setup(void);
56 
57 __dead void
58 _rtt(void)
59 {
60 	struct {
61 		cell_t name;
62 		cell_t nargs;
63 		cell_t nreturns;
64 	} args;
65 
66 #ifdef SOFTRAID
67 	sr_clear_keys();
68 #endif
69 
70 	args.name = ADR2CELL("exit");
71 	args.nargs = 0;
72 	args.nreturns = 0;
73 	openfirmware(&args);
74 	while (1);			/* just in case */
75 }
76 
77 void
78 OF_enter(void)
79 {
80 	struct {
81 		cell_t name;
82 		cell_t nargs;
83 		cell_t nreturns;
84 	} args;
85 
86 	args.name = ADR2CELL("enter");
87 	args.nargs = 0;
88 	args.nreturns = 0;
89 	openfirmware(&args);
90 }
91 
92 int
93 OF_finddevice(char *name)
94 {
95 	struct {
96 		cell_t name;
97 		cell_t nargs;
98 		cell_t nreturns;
99 		cell_t device;
100 		cell_t phandle;
101 	} args;
102 
103 	args.name = ADR2CELL("finddevice");
104 	args.nargs = 1;
105 	args.nreturns = 1;
106 	args.device = ADR2CELL(name);
107 	if (openfirmware(&args) == -1)
108 		return -1;
109 	return args.phandle;
110 }
111 
112 int
113 OF_instance_to_package(int ihandle)
114 {
115 	struct {
116 		cell_t name;
117 		cell_t nargs;
118 		cell_t nreturns;
119 		cell_t ihandle;
120 		cell_t phandle;
121 	} args;
122 
123 	args.name = ADR2CELL("instance-to-package");
124 	args.nargs = 1;
125 	args.nreturns = 1;
126 	args.ihandle = HDL2CELL(ihandle);
127 	if (openfirmware(&args) == -1)
128 		return -1;
129 	return args.phandle;
130 }
131 
132 int
133 OF_getprop(int handle, char *prop, void *buf, int buflen)
134 {
135 	struct {
136 		cell_t name;
137 		cell_t nargs;
138 		cell_t nreturns;
139 		cell_t phandle;
140 		cell_t prop;
141 		cell_t buf;
142 		cell_t buflen;
143 		cell_t size;
144 	} args;
145 
146 	args.name = ADR2CELL("getprop");
147 	args.nargs = 4;
148 	args.nreturns = 1;
149 	args.phandle = HDL2CELL(handle);
150 	args.prop = ADR2CELL(prop);
151 	args.buf = ADR2CELL(buf);
152 	args.buflen = buflen;
153 	if (openfirmware(&args) == -1)
154 		return -1;
155 	return args.size;
156 }
157 
158 int
159 OF_open(char *dname)
160 {
161 	struct {
162 		cell_t name;
163 		cell_t nargs;
164 		cell_t nreturns;
165 		cell_t dname;
166 		cell_t handle;
167 	} args;
168 
169 	args.name = ADR2CELL("open");
170 	args.nargs = 1;
171 	args.nreturns = 1;
172 	args.dname = ADR2CELL(dname);
173 	if (openfirmware(&args) == -1 ||
174 	    args.handle == 0)
175 		return -1;
176 	return args.handle;
177 }
178 
179 void
180 OF_close(int handle)
181 {
182 	struct {
183 		cell_t name;
184 		cell_t nargs;
185 		cell_t nreturns;
186 		cell_t handle;
187 	} args;
188 
189 	args.name = ADR2CELL("close");
190 	args.nargs = 1;
191 	args.nreturns = 0;
192 	args.handle = HDL2CELL(handle);
193 	openfirmware(&args);
194 }
195 
196 int
197 OF_write(int handle, void *addr, int len)
198 {
199 	struct {
200 		cell_t name;
201 		cell_t nargs;
202 		cell_t nreturns;
203 		cell_t ihandle;
204 		cell_t addr;
205 		cell_t len;
206 		cell_t actual;
207 	} args;
208 
209 	args.name = ADR2CELL("write");
210 	args.nargs = 3;
211 	args.nreturns = 1;
212 	args.ihandle = HDL2CELL(handle);
213 	args.addr = ADR2CELL(addr);
214 	args.len = len;
215 	if (openfirmware(&args) == -1)
216 		return -1;
217 	return args.actual;
218 }
219 
220 int
221 OF_read(int handle, void *addr, int len)
222 {
223 	struct {
224 		cell_t name;
225 		cell_t nargs;
226 		cell_t nreturns;
227 		cell_t ihandle;
228 		cell_t addr;
229 		cell_t len;
230 		cell_t actual;
231 	} args;
232 
233 	args.name = ADR2CELL("read");
234 	args.nargs = 3;
235 	args.nreturns = 1;
236 	args.ihandle = HDL2CELL(handle);
237 	args.addr = ADR2CELL(addr);
238 	args.len = len;
239 	if (openfirmware(&args) == -1) {
240 		return -1;
241 	}
242 	return args.actual;
243 }
244 
245 int
246 OF_seek(int handle, u_quad_t pos)
247 {
248 	struct {
249 		cell_t name;
250 		cell_t nargs;
251 		cell_t nreturns;
252 		cell_t handle;
253 		cell_t poshi;
254 		cell_t poslo;
255 		cell_t status;
256 	} args;
257 
258 	args.name = ADR2CELL("seek");
259 	args.nargs = 3;
260 	args.nreturns = 1;
261 	args.handle = HDL2CELL(handle);
262 	args.poshi = HDQ2CELL_HI(pos);
263 	args.poslo = HDQ2CELL_LO(pos);
264 	if (openfirmware(&args) == -1) {
265 		return -1;
266 	}
267 	return args.status;
268 }
269 
270 void
271 OF_release(void *virt, u_int size)
272 {
273 	struct {
274 		cell_t name;
275 		cell_t nargs;
276 		cell_t nreturns;
277 		cell_t virt;
278 		cell_t size;
279 	} args;
280 
281 	args.name = ADR2CELL("release");
282 	args.nargs = 2;
283 	args.nreturns = 0;
284 	args.virt = ADR2CELL(virt);
285 	args.size = size;
286 	openfirmware(&args);
287 }
288 
289 int
290 OF_milliseconds(void)
291 {
292 	struct {
293 		cell_t name;
294 		cell_t nargs;
295 		cell_t nreturns;
296 		cell_t ms;
297 	} args;
298 
299 	args.name = ADR2CELL("milliseconds");
300 	args.nargs = 0;
301 	args.nreturns = 1;
302 	openfirmware(&args);
303 	return args.ms;
304 }
305 
306 void
307 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
308 {
309 	extern int64_t romp;
310 
311 	entry(0, arg, len, (unsigned long)romp, (unsigned long)romp);
312 	panic("OF_chain: kernel returned!");
313 	__asm("ta 2" : :);
314 }
315 
316 static u_int stdin;
317 static u_int stdout;
318 static u_int mmuh = -1;
319 static u_int memh = -1;
320 
321 void
322 setup(void)
323 {
324 	u_int chosen;
325 
326 	if ((chosen = OF_finddevice("/chosen")) == -1)
327 		_rtt();
328 	if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin)
329 	    || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout)
330 	    || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh)
331 	    || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh))
332 		_rtt();
333 }
334 
335 /*
336  * The following need either the handle to memory or the handle to the MMU.
337  */
338 
339 /*
340  * Grab some address space from the prom
341  *
342  * Only works while the prom is actively mapping us.
343  */
344 static vaddr_t
345 OF_claim_virt(vaddr_t vaddr, int len)
346 {
347 	struct {
348 		cell_t name;
349 		cell_t nargs;
350 		cell_t nreturns;
351 		cell_t method;
352 		cell_t ihandle;
353 		cell_t align;
354 		cell_t len;
355 		cell_t vaddr;
356 		cell_t status;
357 		cell_t retaddr;
358 	} args;
359 
360 	args.name = ADR2CELL("call-method");
361 	args.nargs = 5;
362 	args.nreturns = 2;
363 	args.method = ADR2CELL("claim");
364 	args.ihandle = HDL2CELL(mmuh);
365 	args.align = 0;
366 	args.len = len;
367 	args.vaddr = ADR2CELL(vaddr);
368 	if (openfirmware(&args) != 0)
369 		return -1LL;
370 	return (vaddr_t)args.retaddr;
371 }
372 
373 /*
374  * Request some address space from the prom
375  *
376  * Only works while the prom is actively mapping us.
377  */
378 static vaddr_t
379 OF_alloc_virt(int len, int align)
380 {
381 	int retaddr=-1;
382 	struct {
383 		cell_t name;
384 		cell_t nargs;
385 		cell_t nreturns;
386 		cell_t method;
387 		cell_t ihandle;
388 		cell_t align;
389 		cell_t len;
390 		cell_t status;
391 		cell_t retaddr;
392 	} args;
393 
394 	args.name = ADR2CELL("call-method");
395 	args.nargs = 4;
396 	args.nreturns = 2;
397 	args.method = ADR2CELL("claim");
398 	args.ihandle = HDL2CELL(mmuh);
399 	args.align = align;
400 	args.len = len;
401 	args.retaddr = ADR2CELL(&retaddr);
402 	if (openfirmware(&args) != 0)
403 		return -1LL;
404 	return (vaddr_t)args.retaddr;
405 }
406 
407 /*
408  * Release some address space to the prom
409  *
410  * Only works while the prom is actively mapping us.
411  */
412 static int
413 OF_free_virt(vaddr_t vaddr, int len)
414 {
415 	struct {
416 		cell_t name;
417 		cell_t nargs;
418 		cell_t nreturns;
419 		cell_t method;
420 		cell_t ihandle;
421 		cell_t len;
422 		cell_t vaddr;
423 	} args;
424 
425 	args.name = ADR2CELL("call-method");
426 	args.nargs = 4;
427 	args.nreturns = 0;
428 	args.method = ADR2CELL("release");
429 	args.ihandle = HDL2CELL(mmuh);
430 	args.vaddr = ADR2CELL(vaddr);
431 	args.len = len;
432 	return openfirmware(&args);
433 }
434 
435 
436 /*
437  * Have prom map in some memory
438  *
439  * Only works while the prom is actively mapping us.
440  */
441 static vaddr_t
442 OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode)
443 {
444 	struct {
445 		cell_t name;
446 		cell_t nargs;
447 		cell_t nreturns;
448 		cell_t method;
449 		cell_t ihandle;
450 		cell_t mode;
451 		cell_t size;
452 		cell_t vaddr;
453 		cell_t paddr_hi;
454 		cell_t paddr_lo;
455 		cell_t status;
456 		cell_t retaddr;
457 	} args;
458 
459 	args.name = ADR2CELL("call-method");
460 	args.nargs = 7;
461 	args.nreturns = 1;
462 	args.method = ADR2CELL("map");
463 	args.ihandle = HDL2CELL(mmuh);
464 	args.mode = mode;
465 	args.size = size;
466 	args.vaddr = ADR2CELL(vaddr);
467 	args.paddr_hi = HDQ2CELL_HI(paddr);
468 	args.paddr_lo = HDQ2CELL_LO(paddr);
469 
470 	if (openfirmware(&args) == -1)
471 		return -1;
472 	if (args.status)
473 		return -1;
474 	return (vaddr_t)args.retaddr;
475 }
476 
477 
478 /*
479  * Request some RAM from the prom
480  *
481  * Only works while the prom is actively mapping us.
482  */
483 static paddr_t
484 OF_alloc_phys(int len, int align)
485 {
486 	struct {
487 		cell_t name;
488 		cell_t nargs;
489 		cell_t nreturns;
490 		cell_t method;
491 		cell_t ihandle;
492 		cell_t align;
493 		cell_t len;
494 		cell_t status;
495 		cell_t phys_hi;
496 		cell_t phys_lo;
497 	} args;
498 
499 	args.name = ADR2CELL("call-method");
500 	args.nargs = 4;
501 	args.nreturns = 3;
502 	args.method = ADR2CELL("claim");
503 	args.ihandle = HDL2CELL(memh);
504 	args.align = align;
505 	args.len = len;
506 	if (openfirmware(&args) != 0)
507 		return -1LL;
508 	return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo);
509 }
510 
511 
512 /*
513  * Free some RAM to prom
514  *
515  * Only works while the prom is actively mapping us.
516  */
517 static int
518 OF_free_phys(paddr_t phys, int len)
519 {
520 	struct {
521 		cell_t name;
522 		cell_t nargs;
523 		cell_t nreturns;
524 		cell_t method;
525 		cell_t ihandle;
526 		cell_t len;
527 		cell_t phys_hi;
528 		cell_t phys_lo;
529 	} args;
530 
531 	args.name = ADR2CELL("call-method");
532 	args.nargs = 5;
533 	args.nreturns = 0;
534 	args.method = ADR2CELL("release");
535 	args.ihandle = HDL2CELL(memh);
536 	args.len = len;
537 	args.phys_hi = HDQ2CELL_HI(phys);
538 	args.phys_lo = HDQ2CELL_LO(phys);
539 	return openfirmware(&args);
540 }
541 
542 
543 /*
544  * Claim virtual memory -- does not map it in.
545  */
546 
547 void *
548 OF_claim(void *virt, u_int size, u_int align)
549 {
550 	/*
551 	 * Sun Ultra machines run the firmware with VM enabled,
552 	 * so you need to handle allocating and mapping both
553 	 * virtual and physical memory.  Ugh.
554 	 */
555 	paddr_t paddr;
556 	void * newvirt = NULL;
557 
558 	if (virt == NULL) {
559 		virt = (void *)OF_alloc_virt(size, align);
560 		if (virt == (void *)-1LL) {
561 			printf("OF_alloc_virt(%d,%d) failed w/%x\n",
562 			       size, align, virt);
563 			return virt;
564 		}
565 	} else {
566 		newvirt = (void *)OF_claim_virt((vaddr_t)virt, size);
567 		if (newvirt == (void *)-1LL) {
568 			printf("OF_claim_virt(%x,%d) failed w/%x\n",
569 			       virt, size, newvirt);
570 			return newvirt;
571 		}
572 		virt = newvirt;
573 	}
574 	if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) {
575 		printf("OF_alloc_phys(%d,%d) failed\n", size, align);
576 		OF_free_virt((vaddr_t)virt, size);
577 		return (void *)-1LL;
578 	}
579 	if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
580 		printf("OF_map_phys(%x,%d,%x,%d) failed\n",
581 		       paddr, size, virt, -1);
582 		OF_free_phys((paddr_t)paddr, size);
583 		OF_free_virt((vaddr_t)virt, size);
584 		return (void *)-1LL;
585 	}
586 	return virt;
587 }
588 
589 int
590 OF_peer(int phandle)
591 {
592 	struct {
593 		cell_t name;
594 		cell_t nargs;
595 		cell_t nreturns;
596 		cell_t phandle;
597 		cell_t sibling;
598 	} args;
599 
600 	args.name = ADR2CELL("peer");
601 	args.nargs = 1;
602 	args.nreturns = 1;
603 	args.phandle = HDL2CELL(phandle);
604 	if (openfirmware(&args) == -1)
605 		return 0;
606 	return args.sibling;
607 }
608 
609 int
610 OF_child(int phandle)
611 {
612 	struct {
613 		cell_t name;
614 		cell_t nargs;
615 		cell_t nreturns;
616 		cell_t phandle;
617 		cell_t child;
618 	} args;
619 
620 	args.name = ADR2CELL("child");
621 	args.nargs = 1;
622 	args.nreturns = 1;
623 	args.phandle = HDL2CELL(phandle);
624 	if (openfirmware(&args) == -1)
625 		return 0;
626 	return args.child;
627 }
628 
629 int
630 OF_parent(int phandle)
631 {
632 	struct {
633 		cell_t name;
634 		cell_t nargs;
635 		cell_t nreturns;
636 		cell_t phandle;
637 		cell_t parent;
638 	} args;
639 
640 	args.name = ADR2CELL("parent");
641 	args.nargs = 1;
642 	args.nreturns = 1;
643 	args.phandle = HDL2CELL(phandle);
644 	if (openfirmware(&args) == -1)
645 		return 0;
646 	return args.parent;
647 }
648 
649 int
650 OF_package_to_path(int phandle, char *buf, int buflen)
651 {
652 	struct {
653 		cell_t name;
654 		cell_t nargs;
655 		cell_t nreturns;
656 		cell_t phandle;
657 		cell_t buf;
658 		cell_t buflen;
659 		cell_t length;
660 	} args;
661 
662 	if (buflen > PAGE_SIZE)
663 		return -1;
664 	args.name = ADR2CELL("package-to-path");
665 	args.nargs = 3;
666 	args.nreturns = 1;
667 	args.phandle = HDL2CELL(phandle);
668 	args.buf = ADR2CELL(buf);
669 	args.buflen = buflen;
670 	if (openfirmware(&args) < 0)
671 		return -1;
672 	return args.length;
673 }
674 
675 void
676 putchar(int c)
677 {
678 	char ch = c;
679 
680 	if (c == '\n')
681 		putchar('\r');
682 	OF_write(stdout, &ch, 1);
683 }
684 
685 int
686 getchar(void)
687 {
688 	unsigned char ch = '\0';
689 	int l;
690 
691 	while ((l = OF_read(stdin, &ch, 1)) != 1)
692 		if (l != -2 && l != 0)
693 			return -1;
694 	return ch;
695 }
696 
697 int
698 cngetc(void)
699 {
700 	return getchar();
701 }
702