xref: /netbsd/sys/arch/macppc/stand/ofwboot/Locore.c (revision 9112fc8a)
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
ofw_option_truefalse(const char * prop,int proplen)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
startup(void * vpd,int res,int (* openfirm)(void *),char * arg,int argl)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
OF_exit(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
OF_finddevice(const char * name)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
OF_instance_to_package(int ihandle)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
OF_getprop(int handle,const char * prop,void * buf,int buflen)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
OF_setprop(int handle,const char * prop,void * buf,int len)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
OF_open(const char * dname)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
OF_close(int handle)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
OF_write(int handle,void * addr,int len)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
OF_read(int handle,void * addr,int len)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
OF_seek(int handle,u_quad_t pos)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 *
OF_claim(void * virt,u_int size,u_int align)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
OF_release(void * virt,u_int size)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
OF_milliseconds(void)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
OF_chain(void * virt,u_int size,void (* entry)(),void * arg,u_int len)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
OF_chain(void * virt,u_int size,boot_entry_t entry,void * arg,u_int len)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
OF_call_method(const char * method,int ihandle,int nargs,int nreturns,int * cells)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
setup(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
putchar(int c)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
getchar(void)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 }
819