Home | History | Annotate | Line # | Download | only in ofwboot
      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 }
    819