xref: /netbsd/sys/arch/sun2/sun2/promlib.c (revision 974f92f1)
1*974f92f1Srin /*	$NetBSD: promlib.c,v 1.19 2020/09/10 02:03:44 rin Exp $	*/
2ec984a04Sfredette 
3ec984a04Sfredette /*-
4ec984a04Sfredette  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5ec984a04Sfredette  * All rights reserved.
6ec984a04Sfredette  *
7ec984a04Sfredette  * This code is derived from software contributed to The NetBSD Foundation
8ec984a04Sfredette  * by Adam Glass, Gordon W. Ross, and Matthew Fredette.
9ec984a04Sfredette  *
10ec984a04Sfredette  * Redistribution and use in source and binary forms, with or without
11ec984a04Sfredette  * modification, are permitted provided that the following conditions
12ec984a04Sfredette  * are met:
13ec984a04Sfredette  * 1. Redistributions of source code must retain the above copyright
14ec984a04Sfredette  *    notice, this list of conditions and the following disclaimer.
15ec984a04Sfredette  * 2. Redistributions in binary form must reproduce the above copyright
16ec984a04Sfredette  *    notice, this list of conditions and the following disclaimer in the
17ec984a04Sfredette  *    documentation and/or other materials provided with the distribution.
18ec984a04Sfredette  *
19ec984a04Sfredette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20ec984a04Sfredette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21ec984a04Sfredette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22ec984a04Sfredette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23ec984a04Sfredette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ec984a04Sfredette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ec984a04Sfredette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ec984a04Sfredette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ec984a04Sfredette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ec984a04Sfredette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ec984a04Sfredette  * POSSIBILITY OF SUCH DAMAGE.
30ec984a04Sfredette  */
31ec984a04Sfredette 
32ed517291Slukem #include <sys/cdefs.h>
33*974f92f1Srin __KERNEL_RCSID(0, "$NetBSD: promlib.c,v 1.19 2020/09/10 02:03:44 rin Exp $");
34ed517291Slukem 
35ec984a04Sfredette #include <sys/param.h>
36ec984a04Sfredette #include <sys/systm.h>
37ec984a04Sfredette #include <sys/reboot.h>
38ec984a04Sfredette #include <sys/boot_flag.h>
39ec984a04Sfredette 
4043e759e5Sthorpej #include <uvm/uvm_extern.h>
4143e759e5Sthorpej 
42ec984a04Sfredette #define _SUN2_PROMLIB_PRIVATE
43ec984a04Sfredette #include <machine/promlib.h>
44ec984a04Sfredette 
45ec984a04Sfredette #include <sun2/sun2/machdep.h>
46ec984a04Sfredette #include <sun2/sun2/control.h>
4715b02e5bSfredette #include <sun68k/sun68k/vector.h>
489ec520c4Sfredette #include <machine/pte.h>
49ec984a04Sfredette 
50ec984a04Sfredette /*
51ec984a04Sfredette  * The state we save when we get ready to disappear into the PROM.
52ec984a04Sfredette  */
53ec984a04Sfredette struct kernel_state {
54ec984a04Sfredette 	int saved_spl;
55ec984a04Sfredette 	int saved_ctx;
569ec520c4Sfredette 	u_int saved_ptes[4];
57ec984a04Sfredette };
58ec984a04Sfredette 
59ec984a04Sfredette static void **sunmon_vbr;
60ec984a04Sfredette static struct kernel_state sunmon_kernel_state;
61ec984a04Sfredette static struct bootparam sunmon_bootparam;
629ec520c4Sfredette static u_int sunmon_ptes[4];
63ec984a04Sfredette 
6410b1a7beSchs static void tracedump(int);
65ec984a04Sfredette 
66ec984a04Sfredette /*
67ec984a04Sfredette  * The PROM keeps its data is in the first four physical pages, and
689ec520c4Sfredette  * assumes that they're mapped to the first four virtual pages.
699ec520c4Sfredette  * Normally we keep the first four virtual pages unmapped, so before
709ec520c4Sfredette  * we can dereference pointers in romVectorPtr or call the PROM, we
719ec520c4Sfredette  * have to restore its mappings.
72ec984a04Sfredette  */
73ec984a04Sfredette 
74ec984a04Sfredette /*
759ec520c4Sfredette  * This swaps out one set of PTEs for the first
769ec520c4Sfredette  * four virtual pages, and swaps another set in.
779ec520c4Sfredette  */
7810b1a7beSchs static inline void _prom_swap_ptes(u_int *, u_int *);
799ec520c4Sfredette static inline void
_prom_swap_ptes(u_int * swapout,u_int * swapin)8010b1a7beSchs _prom_swap_ptes(u_int *swapout, u_int *swapin)
819ec520c4Sfredette {
829ec520c4Sfredette 	int pte_number;
83bbb634caSfredette 	vaddr_t va;
849ec520c4Sfredette 
8543e759e5Sthorpej 	for (pte_number = 0, va = 0; pte_number < 4;
8643e759e5Sthorpej 	     pte_number++, va += PAGE_SIZE) {
879ec520c4Sfredette 		swapout[pte_number] = get_pte(va);
889ec520c4Sfredette 		set_pte(va, swapin[pte_number]);
899ec520c4Sfredette 	}
909ec520c4Sfredette }
919ec520c4Sfredette 
929ec520c4Sfredette /*
93ec984a04Sfredette  * Prepare for running the PROM monitor.
94ec984a04Sfredette  */
9510b1a7beSchs static inline void _mode_monitor(struct kernel_state *, int);
96ec984a04Sfredette static inline void
_mode_monitor(struct kernel_state * state,int full)9710b1a7beSchs _mode_monitor(struct kernel_state *state, int full)
98ec984a04Sfredette {
99ec984a04Sfredette 	/*
1009ec520c4Sfredette 	 * Save the current context, and the PTEs for pages
1019ec520c4Sfredette 	 * zero through three, and reset them to what the PROM
1029ec520c4Sfredette 	 * expects.
103ec984a04Sfredette 	 */
104ec984a04Sfredette 	state->saved_ctx = get_context();
105ec984a04Sfredette 	set_context(0);
1069ec520c4Sfredette 	_prom_swap_ptes(state->saved_ptes, sunmon_ptes);
107ec984a04Sfredette 
108ec984a04Sfredette 	/*
109ec984a04Sfredette 	 * If we're going to enter the PROM fully, raise the interrupt
110ec984a04Sfredette 	 * level, disable our level 5 clock, restore the PROM vector
111ec984a04Sfredette 	 * table, and enable the PROM NMI clock.
112ec984a04Sfredette 	 */
113ec984a04Sfredette 	if (full) {
114ec984a04Sfredette 		state->saved_spl = splhigh();
115ec984a04Sfredette 		set_clk_mode(0, 0);
116ec984a04Sfredette 		setvbr(sunmon_vbr);
117ec984a04Sfredette 		set_clk_mode(1, 1);
118ec984a04Sfredette 	}
119ec984a04Sfredette }
120ec984a04Sfredette 
121ec984a04Sfredette /*
122ec984a04Sfredette  * Prepare for running the kernel.
123ec984a04Sfredette  */
12410b1a7beSchs static inline void _mode_kernel(struct kernel_state *, int);
125ec984a04Sfredette static inline void
_mode_kernel(struct kernel_state * state,int full)12610b1a7beSchs _mode_kernel(struct kernel_state *state, int full)
127ec984a04Sfredette {
128ec984a04Sfredette 	/*
129ec984a04Sfredette 	 * If we were in the PROM fully, disable the PROM NMI clock,
130ec984a04Sfredette 	 * restore our own vector table, and enable our level 5 clock.
131ec984a04Sfredette 	 */
132ec984a04Sfredette 	if (full) {
133ec984a04Sfredette 		set_clk_mode(1, 0);
134ec984a04Sfredette 		setvbr(vector_table);
135ec984a04Sfredette 		set_clk_mode(0, 1);
136ec984a04Sfredette 		splx(state->saved_spl);
137ec984a04Sfredette 	}
138ec984a04Sfredette 
139ec984a04Sfredette 	/*
1409ec520c4Sfredette 	 * Restore our PTEs for pages zero through three,
1419ec520c4Sfredette 	 * and restore the current context.
142ec984a04Sfredette 	 */
1439ec520c4Sfredette 	_prom_swap_ptes(sunmon_ptes, state->saved_ptes);
144ec984a04Sfredette 	set_context(state->saved_ctx);
145ec984a04Sfredette }
146ec984a04Sfredette 
147ec984a04Sfredette /* We define many prom_ functions using this macro. */
148ec984a04Sfredette #define PROMLIB_FUNC(type, new, proto, old, args, ret)			\
149ec984a04Sfredette type new proto								\
150ec984a04Sfredette {									\
151ec984a04Sfredette 	struct kernel_state state;					\
152ec984a04Sfredette 	int rc;								\
153ec984a04Sfredette 	_mode_monitor(&state, 0);					\
154ec984a04Sfredette 	rc = (*(romVectorPtr->old)) args;				\
155b539fa61Schristos 	__USE(rc);							\
156ec984a04Sfredette 	_mode_kernel(&state, 0);					\
157ec984a04Sfredette 	ret ;								\
158ec984a04Sfredette }
159ec984a04Sfredette PROMLIB_FUNC(int, prom_memsize, (void), memorySize, + 0, return(rc))
160ec984a04Sfredette PROMLIB_FUNC(int, prom_stdin, (void), inSource, + 0, return(rc))
161ec984a04Sfredette PROMLIB_FUNC(int, prom_stdout, (void), outSink, + 0, return(rc))
16265df8b69Sfredette PROMLIB_FUNC(int, prom_kbdid, (void), keyBid, + 0, return(rc))
163ec984a04Sfredette PROMLIB_FUNC(int, prom_getchar, (void), getChar, (), return(rc))
164ec984a04Sfredette PROMLIB_FUNC(int, prom_peekchar, (void), mayGet, (), return(rc))
165aeb5917fSfredette PROMLIB_FUNC(void, prom_putchar, (int c), putChar, (c), return)
166aeb5917fSfredette 
16710b1a7beSchs void
prom_putstr(char * buf,int len)16810b1a7beSchs prom_putstr(char *buf, int len)
169aeb5917fSfredette {
170aeb5917fSfredette 	struct kernel_state state;
171aeb5917fSfredette 	_mode_monitor(&state, 0);
172aeb5917fSfredette 	for(; len > 0; buf++, len--) {
173aeb5917fSfredette 		(*(romVectorPtr->putChar))((int) (*buf));
174aeb5917fSfredette 	}
175aeb5917fSfredette 	_mode_kernel(&state, 0);
176aeb5917fSfredette }
177ec984a04Sfredette 
178ec984a04Sfredette /*
179ec984a04Sfredette  * printf is difficult, because it's a varargs function.
180ec984a04Sfredette  * This is very ugly.  Please fix me!
181ec984a04Sfredette  */
182ec984a04Sfredette void
prom_printf(const char * fmt,...)183ec984a04Sfredette prom_printf(const char *fmt, ...)
184ec984a04Sfredette {
185ec984a04Sfredette 	struct kernel_state state;
186ec984a04Sfredette 	int rc;
187ec984a04Sfredette 	va_list ap;
188ec984a04Sfredette 	const char *p1;
189ec984a04Sfredette 	char c1;
190ec984a04Sfredette 	struct printf_args {
191ec984a04Sfredette 		int arg[15];
192ec984a04Sfredette 	} varargs;
193ec984a04Sfredette 	int i;
194ec984a04Sfredette 
195ec984a04Sfredette 	/*
196ec984a04Sfredette 	 * Since the PROM obviously doesn't take a va_list, we conjure
197ec984a04Sfredette 	 * up a structure of ints to hold the arguments, and pass it
198ec984a04Sfredette 	 * the structure (*not* a pointer to the structure!) to get
199ec984a04Sfredette 	 * the same effect.  This means there is a limit on the number
200ec984a04Sfredette 	 * of arguments you can use with prom_printf.  Ugly indeed.
201ec984a04Sfredette 	 */
202ec984a04Sfredette 	va_start(ap, fmt);
203ec984a04Sfredette 	i = 0;
204ec984a04Sfredette 	for(p1 = fmt; (c1 = *(p1++)) != '\0'; ) {
205ec984a04Sfredette 		if (c1 == '%') {
20610b1a7beSchs 			if (i == (sizeof(varargs.arg) /
20710b1a7beSchs 				  sizeof(varargs.arg[0]))) {
20810b1a7beSchs 				prom_printf("too many args to prom_printf, "
20910b1a7beSchs 					    "format %s", fmt);
210ec984a04Sfredette 				prom_abort();
211ec984a04Sfredette 			}
212ec984a04Sfredette 			varargs.arg[i++] = va_arg(ap, int);
213ec984a04Sfredette 		}
214ec984a04Sfredette 	}
215ec984a04Sfredette 	va_end(ap);
216ec984a04Sfredette 
217ec984a04Sfredette 	/* now call the monitor's printf: */
218ec984a04Sfredette 	_mode_monitor(&state, 0);
219ec984a04Sfredette 	rc = (*
220ec984a04Sfredette 	    /* the ghastly type we cast the PROM printf vector to: */
22110b1a7beSchs 	    ( (int (*)(const char *, struct printf_args))
222ec984a04Sfredette 	    /* the PROM printf vector: */
223ec984a04Sfredette 		(romVectorPtr->printf))
224ec984a04Sfredette 		)(fmt, varargs);
225b539fa61Schristos 	__USE(rc);
226ec984a04Sfredette 	_mode_kernel(&state, 0);
227ec984a04Sfredette }
228ec984a04Sfredette 
229ec984a04Sfredette /* Return the boot path. */
230ec984a04Sfredette char *
prom_getbootpath(void)23110b1a7beSchs prom_getbootpath(void)
232ec984a04Sfredette {
233ec984a04Sfredette 	/*
234ec984a04Sfredette 	 * The first bootparam argument is the device string.
235ec984a04Sfredette 	 */
236ec984a04Sfredette 	return (sunmon_bootparam.argPtr[0]);
237ec984a04Sfredette }
238ec984a04Sfredette 
239ec984a04Sfredette /* Return the boot args. */
240ec984a04Sfredette char *
prom_getbootargs(void)24110b1a7beSchs prom_getbootargs(void)
242ec984a04Sfredette {
243ec984a04Sfredette 	/*
244ec984a04Sfredette 	 * The second bootparam argument is any options.
245ec984a04Sfredette 	 */
246ec984a04Sfredette 	return (sunmon_bootparam.argPtr[1]);
247ec984a04Sfredette }
248ec984a04Sfredette 
249ec984a04Sfredette /* Return the boot file. */
250ec984a04Sfredette char *
prom_getbootfile(void)25110b1a7beSchs prom_getbootfile(void)
252ec984a04Sfredette {
253ec984a04Sfredette 	return (sunmon_bootparam.fileName);
254ec984a04Sfredette }
255ec984a04Sfredette 
25615b02e5bSfredette /* This maps a PROM `sd' unit number into a SCSI target. */
25715b02e5bSfredette int
prom_sd_target(int unit)25810b1a7beSchs prom_sd_target(int unit)
25915b02e5bSfredette {
26015b02e5bSfredette 	switch(unit) {
26115b02e5bSfredette 	case 2:	return (4);
26215b02e5bSfredette 	}
26315b02e5bSfredette 	return (unit);
26415b02e5bSfredette }
26515b02e5bSfredette 
266ec984a04Sfredette /*
267ec984a04Sfredette  * This aborts to the PROM, but should allow the user
268ec984a04Sfredette  * to "c" continue back into the kernel.
269ec984a04Sfredette  */
270ec984a04Sfredette void
prom_abort(void)27110b1a7beSchs prom_abort(void)
272ec984a04Sfredette {
27310b1a7beSchs 	uint16_t old_g0_g4_vectors[4], *vec, *store;
274ec984a04Sfredette 
275ec984a04Sfredette 	_mode_monitor(&sunmon_kernel_state, 1);
27615b02e5bSfredette 
27715b02e5bSfredette 	/*
27815b02e5bSfredette 	 * Set up our g0 and g4 handlers, by writing into
27915b02e5bSfredette 	 * the PROM's vector table directly.  Note that
28015b02e5bSfredette 	 * the braw instruction displacement is PC-relative.
28115b02e5bSfredette 	 */
28215b02e5bSfredette #define	BRAW	0x6000
28310b1a7beSchs 	vec = (uint16_t *) sunmon_vbr;
28415b02e5bSfredette 	store = old_g0_g4_vectors;
28515b02e5bSfredette 	*(store++) = *vec;
28615b02e5bSfredette 	*(vec++) = BRAW;
28715b02e5bSfredette 	*(store++) = *vec;
288002ed08eSthorpej 	*vec = ((u_long) g0_entry) - ((u_long) vec);
289002ed08eSthorpej 	vec++;
29015b02e5bSfredette 	*(store++) = *vec;
29115b02e5bSfredette 	*(vec++) = BRAW;
29215b02e5bSfredette 	*(store++) = *vec;
293002ed08eSthorpej 	*vec = ((u_long) g4_entry) - ((u_long) vec);
294002ed08eSthorpej 	vec++;
29515b02e5bSfredette #undef	BRAW
29615b02e5bSfredette 
297ec984a04Sfredette 	delay(100000);
298ec984a04Sfredette 
299ec984a04Sfredette 	/*
300ec984a04Sfredette 	 * Drop into the PROM in a way that allows a continue.
301ec984a04Sfredette 	 * Already setup "trap #14" in prom_init().
302ec984a04Sfredette 	 */
303ec984a04Sfredette 
3042d65de24Sperry 	__asm(" trap #14 ; _sunmon_continued: nop");
305ec984a04Sfredette 
306ec984a04Sfredette 	/* We have continued from a PROM abort! */
30715b02e5bSfredette 
30815b02e5bSfredette 	/* Put back the old g0 and g4 handlers. */
30910b1a7beSchs 	vec = (uint16_t *) sunmon_vbr;
31015b02e5bSfredette 	store = old_g0_g4_vectors;
31115b02e5bSfredette 	*(vec++) = *(store++);
31215b02e5bSfredette 	*(vec++) = *(store++);
31315b02e5bSfredette 	*(vec++) = *(store++);
31415b02e5bSfredette 	*(vec++) = *(store++);
31515b02e5bSfredette 
316ec984a04Sfredette 	_mode_kernel(&sunmon_kernel_state, 1);
317ec984a04Sfredette }
318ec984a04Sfredette 
319ec984a04Sfredette void
prom_halt(void)32010b1a7beSchs prom_halt(void)
321ec984a04Sfredette {
322ec984a04Sfredette 	_mode_monitor(&sunmon_kernel_state, 1);
323ec984a04Sfredette 	(*romVectorPtr->exitToMon)();
324ec984a04Sfredette 	for(;;);
325ec984a04Sfredette 	/*NOTREACHED*/
326ec984a04Sfredette }
327ec984a04Sfredette 
328ec984a04Sfredette /*
329ec984a04Sfredette  * Caller must pass a string that is in our data segment.
330ec984a04Sfredette  */
331ec984a04Sfredette void
prom_boot(const char * bs)3326df30aa4Stsutsui prom_boot(const char *bs)
333ec984a04Sfredette {
334ec984a04Sfredette 	_mode_monitor(&sunmon_kernel_state, 1);
335ec984a04Sfredette 	(*romVectorPtr->reBoot)(bs);
336ec984a04Sfredette 	(*romVectorPtr->exitToMon)();
337ec984a04Sfredette 	for(;;);
338ec984a04Sfredette 	/*NOTREACHED*/
339ec984a04Sfredette }
340ec984a04Sfredette 
341ec984a04Sfredette 
342ec984a04Sfredette /*
343ec984a04Sfredette  * Print out a traceback for the caller - can be called anywhere
344ec984a04Sfredette  * within the kernel or from the monitor by typing "g4".
345ec984a04Sfredette  */
346ec984a04Sfredette struct funcall_frame {
347ec984a04Sfredette 	struct funcall_frame *fr_savfp;
348ec984a04Sfredette 	int fr_savpc;
349ec984a04Sfredette 	int fr_arg[1];
350ec984a04Sfredette };
351ec984a04Sfredette /*VARARGS0*/
352*974f92f1Srin static void __noinline
tracedump(int x1)35310b1a7beSchs tracedump(int x1)
354ec984a04Sfredette {
355ec984a04Sfredette 	struct funcall_frame *fp = (struct funcall_frame *)(&x1 - 2);
356ec984a04Sfredette 	u_int stackpage = ((u_int)fp) & ~PGOFSET;
357ec984a04Sfredette 
358ec984a04Sfredette 	prom_printf("Begin traceback...fp = 0x%x\n", fp);
359ec984a04Sfredette 	do {
360ec984a04Sfredette 		if (fp == fp->fr_savfp) {
361ec984a04Sfredette 			prom_printf("FP loop at 0x%x", fp);
362ec984a04Sfredette 			break;
363ec984a04Sfredette 		}
364ec984a04Sfredette 		prom_printf("Called from 0x%x, fp=0x%x, args=0x%x 0x%x 0x%x 0x%x\n",
365ec984a04Sfredette 				   fp->fr_savpc, fp->fr_savfp,
366ec984a04Sfredette 				   fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
367ec984a04Sfredette 		fp = fp->fr_savfp;
368ec984a04Sfredette 	} while ( (((u_int)fp) & ~PGOFSET) == stackpage);
369ec984a04Sfredette 	prom_printf("End traceback...\n");
370ec984a04Sfredette }
371ec984a04Sfredette 
372ec984a04Sfredette /* Handlers for the old-school "g0" and "g4" */
37310b1a7beSchs void g0_handler(void);
374ec984a04Sfredette void
g0_handler(void)37510b1a7beSchs g0_handler(void)
376ec984a04Sfredette {
377ec984a04Sfredette 	_mode_kernel(&sunmon_kernel_state, 1);
378ec984a04Sfredette 	panic("zero");
379ec984a04Sfredette }
38010b1a7beSchs void g4_handler(int);
381ec984a04Sfredette void
g4_handler(int addr)38210b1a7beSchs g4_handler(int addr)
383ec984a04Sfredette {
384ec984a04Sfredette 	_mode_kernel(&sunmon_kernel_state, 1);
385ec984a04Sfredette 	tracedump(addr);
386ec984a04Sfredette }
387ec984a04Sfredette 
388ec984a04Sfredette /*
389ec984a04Sfredette  * Set the PROM vector handler (for g0, g4, etc.)
390ec984a04Sfredette  * and set boothowto from the PROM arg strings.
391ec984a04Sfredette  *
392ec984a04Sfredette  * Note, args are always:
393ec984a04Sfredette  * argv[0] = boot_device	(i.e. "sd(0,0,0)")
394ec984a04Sfredette  * argv[1] = options	(i.e. "-ds" or NULL)
395ec984a04Sfredette  * argv[2] = NULL
396ec984a04Sfredette  */
397ec984a04Sfredette void
prom_init(void)39810b1a7beSchs prom_init(void)
399ec984a04Sfredette {
400ec984a04Sfredette 	struct bootparam *old_bp;
401ec984a04Sfredette 	struct bootparam *new_bp;
402ec984a04Sfredette 	int bp_shift;
403ec984a04Sfredette 	int i;
404ec984a04Sfredette 	char *p;
405ec984a04Sfredette 	int fl;
406ec984a04Sfredette 
407ec984a04Sfredette 	/*
408ec984a04Sfredette 	 * Any second the pointers in the PROM vector are going to
4099ec520c4Sfredette 	 * break (since they point into pages zero through three,
4109ec520c4Sfredette 	 * which we like to keep unmapped), so we grab a complete
4119ec520c4Sfredette 	 * copy of the bootparams, taking care to adjust the pointers
4129ec520c4Sfredette 	 * in the copy to also point to the copy.
413ec984a04Sfredette 	 */
414ec984a04Sfredette 	old_bp = *romVectorPtr->bootParam;
415ec984a04Sfredette 	new_bp = &sunmon_bootparam;
416ec984a04Sfredette 	*new_bp = *old_bp;
417ca414a50Sfredette 	bp_shift = ((char *) new_bp) - ((char *) old_bp);
418ca414a50Sfredette 	for(i = 0; i < 8 && new_bp->argPtr[i] != NULL; i++) {
419ec984a04Sfredette 		new_bp->argPtr[i] += bp_shift;
420ec984a04Sfredette 	}
421ec984a04Sfredette 	new_bp->fileName += bp_shift;
422ec984a04Sfredette 
4239ec520c4Sfredette 	/* Save the PROM's mappings for pages zero through three. */
4249ec520c4Sfredette 	_prom_swap_ptes(sunmon_ptes, sunmon_ptes);
4259ec520c4Sfredette 
426ec984a04Sfredette 	/* Save the PROM monitor Vector Base Register (VBR). */
427ec984a04Sfredette 	sunmon_vbr = getvbr();
428ec984a04Sfredette 
429ec984a04Sfredette 	/* Arrange for "trap #14" to cause a PROM abort. */
430ec984a04Sfredette 	sunmon_vbr[32+14] = romVectorPtr->abortEntry;
431ec984a04Sfredette 
432ec984a04Sfredette 	/* Try to find some options. */
433ec984a04Sfredette 	p = prom_getbootargs();
434ec984a04Sfredette 	if (p != NULL) {
435ec984a04Sfredette 
436ec984a04Sfredette 		/* Skip any whitespace */
437ec984a04Sfredette 		for(; *p != '-'; )
438ec984a04Sfredette 			if (*(p++) == '\0') {
439ec984a04Sfredette 				p = NULL;
440ec984a04Sfredette 				break;
441ec984a04Sfredette 			}
442ec984a04Sfredette 	}
443ec984a04Sfredette 
444ec984a04Sfredette 	/* If we have options. */
445ec984a04Sfredette 	if (p != NULL) {
446ec984a04Sfredette #ifdef	DEBUG
447ec984a04Sfredette 		prom_printf("boot options: %s\n", p);
448ec984a04Sfredette #endif
449ec984a04Sfredette 		for(; *(++p); ) {
450d77c828cSfredette 			fl = 0;
451ec984a04Sfredette 			BOOT_FLAG(*p, fl);
452ec984a04Sfredette 			if (fl)
453ec984a04Sfredette 				boothowto |= fl;
454ec984a04Sfredette 			else
455ec984a04Sfredette 				prom_printf("unknown option `%c'\n", *p);
456ec984a04Sfredette 		}
457ec984a04Sfredette 	}
458ec984a04Sfredette }
459