xref: /openbsd/sys/arch/sparc64/stand/ofwboot/Locore.c (revision 4bdff4be)
1 /*	$OpenBSD: Locore.c,v 1.18 2023/06/01 17:24:56 krw 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 int 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 int
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 	} args;
456 
457 	args.name = ADR2CELL("call-method");
458 	args.nargs = 7;
459 	args.nreturns = 0;
460 	args.method = ADR2CELL("map");
461 	args.ihandle = HDL2CELL(mmuh);
462 	args.mode = mode;
463 	args.size = size;
464 	args.vaddr = ADR2CELL(vaddr);
465 	args.paddr_hi = HDQ2CELL_HI(paddr);
466 	args.paddr_lo = HDQ2CELL_LO(paddr);
467 	return openfirmware(&args);
468 }
469 
470 
471 /*
472  * Request some RAM from the prom
473  *
474  * Only works while the prom is actively mapping us.
475  */
476 static paddr_t
477 OF_alloc_phys(int len, int align)
478 {
479 	struct {
480 		cell_t name;
481 		cell_t nargs;
482 		cell_t nreturns;
483 		cell_t method;
484 		cell_t ihandle;
485 		cell_t align;
486 		cell_t len;
487 		cell_t status;
488 		cell_t phys_hi;
489 		cell_t phys_lo;
490 	} args;
491 
492 	args.name = ADR2CELL("call-method");
493 	args.nargs = 4;
494 	args.nreturns = 3;
495 	args.method = ADR2CELL("claim");
496 	args.ihandle = HDL2CELL(memh);
497 	args.align = align;
498 	args.len = len;
499 	if (openfirmware(&args) != 0)
500 		return -1LL;
501 	return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo);
502 }
503 
504 
505 /*
506  * Free some RAM to prom
507  *
508  * Only works while the prom is actively mapping us.
509  */
510 static int
511 OF_free_phys(paddr_t phys, int len)
512 {
513 	struct {
514 		cell_t name;
515 		cell_t nargs;
516 		cell_t nreturns;
517 		cell_t method;
518 		cell_t ihandle;
519 		cell_t len;
520 		cell_t phys_hi;
521 		cell_t phys_lo;
522 	} args;
523 
524 	args.name = ADR2CELL("call-method");
525 	args.nargs = 5;
526 	args.nreturns = 0;
527 	args.method = ADR2CELL("release");
528 	args.ihandle = HDL2CELL(memh);
529 	args.len = len;
530 	args.phys_hi = HDQ2CELL_HI(phys);
531 	args.phys_lo = HDQ2CELL_LO(phys);
532 	return openfirmware(&args);
533 }
534 
535 
536 /*
537  * Claim virtual memory -- does not map it in.
538  */
539 
540 void *
541 OF_claim(void *virt, u_int size, u_int align)
542 {
543 	/*
544 	 * Sun Ultra machines run the firmware with VM enabled,
545 	 * so you need to handle allocating and mapping both
546 	 * virtual and physical memory.  Ugh.
547 	 */
548 	paddr_t paddr;
549 	void * newvirt = NULL;
550 
551 	if (virt == NULL) {
552 		virt = (void *)OF_alloc_virt(size, align);
553 		if (virt == (void *)-1LL) {
554 			printf("OF_alloc_virt(%d,%d) failed w/%x\n",
555 			       size, align, virt);
556 			return virt;
557 		}
558 	} else {
559 		newvirt = (void *)OF_claim_virt((vaddr_t)virt, size);
560 		if (newvirt == (void *)-1LL) {
561 			printf("OF_claim_virt(%x,%d) failed w/%x\n",
562 			       virt, size, newvirt);
563 			return newvirt;
564 		}
565 		virt = newvirt;
566 	}
567 	if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) {
568 		printf("OF_alloc_phys(%d,%d) failed\n", size, align);
569 		OF_free_virt((vaddr_t)virt, size);
570 		return (void *)-1LL;
571 	}
572 	if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
573 		printf("OF_map_phys(%x,%d,%x,%d) failed\n",
574 		       paddr, size, virt, -1);
575 		OF_free_phys((paddr_t)paddr, size);
576 		OF_free_virt((vaddr_t)virt, size);
577 		return (void *)-1LL;
578 	}
579 	return virt;
580 }
581 
582 int
583 OF_peer(int phandle)
584 {
585 	struct {
586 		cell_t name;
587 		cell_t nargs;
588 		cell_t nreturns;
589 		cell_t phandle;
590 		cell_t sibling;
591 	} args;
592 
593 	args.name = ADR2CELL("peer");
594 	args.nargs = 1;
595 	args.nreturns = 1;
596 	args.phandle = HDL2CELL(phandle);
597 	if (openfirmware(&args) == -1)
598 		return 0;
599 	return args.sibling;
600 }
601 
602 int
603 OF_child(int phandle)
604 {
605 	struct {
606 		cell_t name;
607 		cell_t nargs;
608 		cell_t nreturns;
609 		cell_t phandle;
610 		cell_t child;
611 	} args;
612 
613 	args.name = ADR2CELL("child");
614 	args.nargs = 1;
615 	args.nreturns = 1;
616 	args.phandle = HDL2CELL(phandle);
617 	if (openfirmware(&args) == -1)
618 		return 0;
619 	return args.child;
620 }
621 
622 int
623 OF_parent(int phandle)
624 {
625 	struct {
626 		cell_t name;
627 		cell_t nargs;
628 		cell_t nreturns;
629 		cell_t phandle;
630 		cell_t parent;
631 	} args;
632 
633 	args.name = ADR2CELL("parent");
634 	args.nargs = 1;
635 	args.nreturns = 1;
636 	args.phandle = HDL2CELL(phandle);
637 	if (openfirmware(&args) == -1)
638 		return 0;
639 	return args.parent;
640 }
641 
642 int
643 OF_package_to_path(int phandle, char *buf, int buflen)
644 {
645 	struct {
646 		cell_t name;
647 		cell_t nargs;
648 		cell_t nreturns;
649 		cell_t phandle;
650 		cell_t buf;
651 		cell_t buflen;
652 		cell_t length;
653 	} args;
654 
655 	if (buflen > PAGE_SIZE)
656 		return -1;
657 	args.name = ADR2CELL("package-to-path");
658 	args.nargs = 3;
659 	args.nreturns = 1;
660 	args.phandle = HDL2CELL(phandle);
661 	args.buf = ADR2CELL(buf);
662 	args.buflen = buflen;
663 	if (openfirmware(&args) < 0)
664 		return -1;
665 	return args.length;
666 }
667 
668 void
669 putchar(int c)
670 {
671 	char ch = c;
672 
673 	if (c == '\n')
674 		putchar('\r');
675 	OF_write(stdout, &ch, 1);
676 }
677 
678 int
679 getchar(void)
680 {
681 	unsigned char ch = '\0';
682 	int l;
683 
684 	while ((l = OF_read(stdin, &ch, 1)) != 1)
685 		if (l != -2 && l != 0)
686 			return -1;
687 	return ch;
688 }
689 
690 int
691 cngetc(void)
692 {
693 	return getchar();
694 }
695