xref: /netbsd-src/sys/arch/prep/stand/boot/boot.c (revision e5548b402ae4c44fb816de42c7bba9581ce23ef5)
1 /*	$NetBSD: boot.c,v 1.10 2005/12/11 12:18:48 christos 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 <lib/libsa/stand.h>
35 #include <lib/libsa/loadfile.h>
36 #include <lib/libkern/libkern.h>
37 #include <sys/reboot.h>
38 #include <sys/boot_flag.h>
39 #include <machine/bootinfo.h>
40 #include <machine/cpu.h>
41 #include <machine/residual.h>
42 #include <powerpc/spr.h>
43 
44 #include "boot.h"
45 
46 char *names[] = {
47 	"in()",
48 #if 0
49 	"fd(0,0,0)netbsd", "fd(0,0,0)netbsd.gz",
50 	"fd(0,0,0)netbsd.old", "fd(0,0,0)netbsd.old.gz",
51 	"fd(0,0,0)onetbsd", "fd(0,0,0)onetbsd.gz"
52 #endif
53 };
54 #define	NUMNAMES (sizeof (names) / sizeof (names[0]))
55 
56 #define	NAMELEN	128
57 char namebuf[NAMELEN];
58 char nametmp[NAMELEN];
59 
60 char bootinfo[BOOTINFO_MAXSIZE];
61 struct btinfo_residual btinfo_residual;
62 struct btinfo_console btinfo_console;
63 struct btinfo_clock btinfo_clock;
64 
65 RESIDUAL residual;
66 
67 extern u_long ns_per_tick;
68 extern char bootprog_name[], bootprog_rev[], bootprog_maker[], bootprog_date[];
69 
70 void boot __P((void *, u_long));
71 static void exec_kernel __P((char *));
72 
73 void
74 boot(resp, loadaddr)
75 	void *resp;
76 	u_long loadaddr;
77 {
78 	extern char _end[], _edata[];
79 	int n = 0;
80 	int addr, speed;
81 	unsigned int cpuvers;
82 	char *name, *cnname, *p;
83 
84 	/* Clear all of BSS */
85 	memset(_edata, 0, _end - _edata);
86 
87 	/*
88 	 * console init
89 	 */
90 	cnname = cninit(&addr, &speed);
91 
92 	/* make bootinfo */
93 	/*
94 	 * residual data
95 	 */
96 	btinfo_residual.common.next = sizeof(btinfo_residual);
97 	btinfo_residual.common.type = BTINFO_RESIDUAL;
98 	if (resp) {
99 		memcpy(&residual, resp, sizeof(residual));
100 		btinfo_residual.addr = (void *)&residual;
101 	} else {
102 		printf("Warning: no residual data.\n");
103 		btinfo_residual.addr = 0;
104 	}
105 
106 	/*
107 	 * console
108 	 */
109 	btinfo_console.common.next = sizeof(btinfo_console);
110 	btinfo_console.common.type = BTINFO_CONSOLE;
111 	strcpy(btinfo_console.devname, cnname);
112 	btinfo_console.addr = addr;
113 	btinfo_console.speed = speed;
114 
115 	/*
116 	 * clock
117 	 */
118 	__asm __volatile ("mfpvr %0" : "=r"(cpuvers));
119 	cpuvers >>= 16;
120 	btinfo_clock.common.next = 0;
121 	btinfo_clock.common.type = BTINFO_CLOCK;
122 	if (cpuvers == MPC601) {
123 		btinfo_clock.ticks_per_sec = 1000000000;
124 	} else {
125 		btinfo_clock.ticks_per_sec = resp ?
126 		    residual.VitalProductData.ProcessorBusHz/4 : TICKS_PER_SEC;
127 	}
128 	ns_per_tick = 1000000000 / btinfo_clock.ticks_per_sec;
129 
130 	p = bootinfo;
131         memcpy(p, (void *)&btinfo_residual, sizeof(btinfo_residual));
132         p += sizeof(btinfo_residual);
133         memcpy(p, (void *)&btinfo_console, sizeof(btinfo_console));
134         p += sizeof(btinfo_console);
135         memcpy(p, (void *)&btinfo_clock, sizeof(btinfo_clock));
136 
137 	/*
138 	 * load kernel if attached
139 	 */
140 	init_in(loadaddr);
141 
142 	printf("\n");
143 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
144 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
145 
146 	for (;;) {
147 		name = names[n++];
148 		if (n >= NUMNAMES)
149 			n = 0;
150 
151 		exec_kernel(name);
152 	}
153 }
154 
155 /*
156  * Exec kernel
157  */
158 static void
159 exec_kernel(name)
160 	char *name;
161 {
162 	int howto = 0;
163 	char c, *ptr;
164 	u_long marks[MARK_MAX];
165 #ifdef DBMONITOR
166 	int go_monitor;
167 	extern int db_monitor __P((void));
168 #endif /* DBMONITOR */
169 
170 ret:
171 	printf("\nBoot: ");
172 	memset(namebuf, 0, sizeof (namebuf));
173 	(void)tgets(namebuf);
174 
175 	ptr = namebuf;
176 #ifdef DBMONITOR
177 	go_monitor = 0;
178 	if (*ptr == '!') {
179 		if (*(++ptr) == NULL) {
180 			db_monitor();
181 			printf("\n");
182 			goto ret;
183 		} else {
184 			go_monitor++;
185 		}
186 	}
187 #endif /* DBMONITOR */
188 	while ((c = *ptr)) {
189 		while (c == ' ')
190 			c = *++ptr;
191 		if (!c)
192 			goto next;
193 		if (c == '-') {
194 			while ((c = *++ptr) && c != ' ')
195 				BOOT_FLAG(c, howto);
196 		} else {
197 			name = ptr;
198 			while ((c = *++ptr) && c != ' ');
199 			if (c)
200 				*ptr++ = 0;
201 		}
202 	}
203 
204 next:
205 	printf("Loading %s", name);
206 	if (howto)
207 		printf(" (howto 0x%x)", howto);
208 	printf("\n");
209 
210 	marks[MARK_START] = 0;
211 	if (loadfile(name, marks, LOAD_ALL) == 0) {
212 #ifdef DBMONITOR
213 		if (go_monitor) {
214 			db_monitor();
215 			printf("\n");
216 		}
217 #endif /* DBMONITOR */
218 
219 		printf("start=0x%lx\n\n", marks[MARK_ENTRY]);
220 		delay(1000);
221 		__syncicache((void *)marks[MARK_ENTRY],
222 			(u_int)marks[MARK_SYM] - (u_int)marks[MARK_ENTRY]);
223 
224 		run((void *)marks[MARK_SYM],
225 		    (void *)marks[MARK_END],
226 		    (void *)howto,
227 		    (void *)bootinfo,
228 		    (void *)marks[MARK_ENTRY]);
229 	}
230 }
231