xref: /netbsd-src/sys/arch/bebox/stand/boot/boot.c (revision 7c7c171d130af9949261bc7dce2150a03c3d239c)
1 /*	$Id: boot.c,v 1.2 1998/01/19 03:00:57 sakamoto 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 #include <stand.h>
34 
35 #include <sys/exec_elf.h>
36 #include <sys/reboot.h>
37 #include <machine/param.h>
38 #include <bebox/include/bootinfo.h>
39 #ifdef CONS_SERIAL
40 #include "ns16550.h"
41 #endif /* CONS_SERIAL */
42 
43 #define NAMELEN	128
44 
45 char *name;
46 char *names[] = {
47 	"in()",
48 	"fd(0,1,0)netbsd", "fd(0,1,0)netbsd.gz",
49 	"fd(0,1,0)netbsd.old", "fd(0,1,0)netbsd.old.gz",
50 	"fd(0,1,0)onetbsd", "fd(0,1,0)onetbsd.gz"
51 };
52 #define NUMNAMES (sizeof (names) / sizeof (names[0]))
53 
54 char namebuf[NAMELEN];
55 char nametmp[NAMELEN];
56 int args;
57 void *startsym, *endsym, *bootinfo;
58 struct btinfo_memory btinfo_memory;
59 struct btinfo_console btinfo_console;
60 struct btinfo_clock btinfo_clock;
61 extern int errno;
62 
63 void
64 main()
65 {
66 	int fd, n = 0;
67 	void *p;
68 	void start_CPU1();
69 	extern int CPU1_alive;
70 	extern char bootprog_name[], bootprog_rev[],
71 		bootprog_maker[], bootprog_date[];
72 
73 	if (whichCPU() == 1)
74 		cpu1();
75 	resetCPU1();
76 
77 	/*
78 	 * make bootinfo
79 	 */
80 	bootinfo = (void *)0x3030;
81 
82 	btinfo_memory.common.next = sizeof (btinfo_memory);
83 	btinfo_memory.common.type = BTINFO_MEMORY;
84 	btinfo_memory.memsize = *(int *)0x3010;
85 
86 	btinfo_console.common.next = sizeof (btinfo_console);
87 	btinfo_console.common.type = BTINFO_CONSOLE;
88 #ifdef CONS_VGA
89 	strcpy(btinfo_console.devname, "vga");
90 #endif /* CONS_VGA */
91 #ifdef CONS_SERIAL
92 	strcpy(btinfo_console.devname, "com");
93 # ifdef COMPORT
94 	btinfo_console.addr = COMPORT;
95 # else /* COMPORT */
96 	btinfo_console.addr = COM1;
97 # endif /* COMPORT */
98 # ifdef COMSPEED
99 	btinfo_console.speed = COMSPEED;
100 # else /* COMSPEED */
101 	btinfo_console.speed = 9600;
102 # endif /* COMSPEED */
103 #endif /* CONS_SERIAL */
104 
105 	btinfo_clock.common.next = 0;
106 	btinfo_clock.common.type = BTINFO_CLOCK;
107 	btinfo_clock.ticks_per_sec = findcpuspeed();
108 
109 	p = bootinfo;
110 	bcopy((void *)&btinfo_memory, p, sizeof (btinfo_memory));
111 	p += sizeof (btinfo_memory);
112 	bcopy((void *)&btinfo_console, p, sizeof (btinfo_console));
113 	p += sizeof (btinfo_console);
114 	bcopy((void *)&btinfo_clock, p, sizeof (btinfo_clock));
115 
116 	/*
117 	 * console init
118 	 */
119 	cninit();
120 
121 	/*
122 	 * attached kernel check
123 	 */
124 	init_in();
125 
126 	runCPU1(start_CPU1);
127 	wait_for(&CPU1_alive);
128 
129 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
130 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
131 	printf(">> Memory: %d k\n", btinfo_memory.memsize / 1024);
132 
133 	for (;;) {
134 		args = 0;
135 		name = names[n++];
136 		if (n >= NUMNAMES)
137 			n = 0;
138 
139 		getbootdev(&args);
140 		fd = open(name, 0);
141 		if (fd >= 0) {
142 			exec_kernel(fd, &args);
143 			close(fd);	/* exec failed */
144 		} else {
145 			printf("open error:%s\n",  strerror(errno));
146 		}
147 	}
148 }
149 
150 /*
151  * Get boot device, file name, flag
152  */
153 getbootdev(howto)
154 	int *howto;
155 {
156 	char c, *ptr;
157 #ifdef DBMONITOR
158 	extern int load_flag;
159 #endif /* DBMONITOR */
160 
161 #ifdef DBMONITOR
162 ret:
163 	if (load_flag)
164 		printf("Load: ");
165 	else
166 #endif /* DBMONITOR */
167 		printf("Boot: ");
168 
169 	bzero(namebuf, sizeof (namebuf));
170 	if (tgets(namebuf) != -1) {
171 		ptr = namebuf;
172 #ifdef DBMONITOR
173 		if (*ptr == '!') {
174 			db_monitor();
175 			printf("\n");
176 			goto ret;
177 		}
178 #endif /* DBMONITOR */
179 		while (c = *ptr) {
180 			while (c == ' ')
181 				c = *++ptr;
182 			if (!c)
183 				return;
184 			if (c == '-')
185 				while ((c = *++ptr) && c != ' ') {
186 					if (c == 'a')
187 						*howto |= RB_ASKNAME;
188 					else if (c == 'b')
189 						*howto |= RB_HALT;
190 					else if (c == 'd')
191 						*howto |= RB_KDB;
192 					else if (c == 'r')
193 						*howto |= RB_DFLTROOT;
194 					else if (c == 's')
195 						*howto |= RB_SINGLE;
196 				}
197 			else {
198 				name = ptr;
199 				while ((c = *++ptr) && c != ' ');
200 				if (c)
201 					*ptr++ = 0;
202 			}
203 		}
204 	} else {
205 		putchar('\n');
206 	}
207 }
208 
209 exec_kernel(fd, howto)
210 	int fd;
211 	int *howto;
212 {
213 	int i, first = 1;
214 	Elf32_Ehdr hdr;
215 	Elf32_Phdr phdr;
216 	Elf32_Shdr shdr;
217 	void *sp, *ssp;
218 #ifdef DBMONITOR
219 	extern int load_flag;
220 #endif /* DBMONITOR */
221 
222 #ifdef DBMONITOR
223 	printf("%s %s ", (load_flag ? "Loading" : "Booting"), name);
224 #else /* DBMONITOR */
225 	printf("Booting %s ", name);
226 #endif /* DBMONITOR */
227 
228 	if (read(fd, &hdr, ELF32_HDR_SIZE) != ELF32_HDR_SIZE) {
229 		printf("\nread error: %s\n", strerror(errno));
230 		return;
231 	}
232 	if (bcmp(hdr.e_ident, Elf32_e_ident, Elf32_e_siz)) {
233 		printf("\nnot ELF32 format\n");
234 		return;
235 	}
236 	if (hdr.e_machine != Elf_em_ppc) {
237 		printf("\nnot PowerPC exec binary\n");
238 		return;
239 	}
240 #if 0
241 	printf("e_entry= 0x%x\n", hdr.e_entry);
242 	printf("e_phoff= 0x%x\n", hdr.e_phoff);
243 	printf("e_shoff= 0x%x\n", hdr.e_shoff);
244 	printf("e_flags= 0x%x\n", hdr.e_flags);
245 	printf("e_ehsize= 0x%x\n", hdr.e_ehsize);
246 	printf("e_phentsize= 0x%x\n", hdr.e_phentsize);
247 	printf("e_phnum= 0x%x\n", hdr.e_phnum);
248 	printf("e_shentsize= 0x%x\n", hdr.e_shentsize);
249 	printf("e_shnum= 0x%x\n", hdr.e_shnum);
250 	printf("e_shstrndx= 0x%x\n", hdr.e_shstrndx);
251 #endif
252 	printf("@ 0x%x\n", hdr.e_entry);
253 
254 	for (i = 0; i < hdr.e_phnum; i++) {
255 		lseek(fd, hdr.e_phoff + sizeof(phdr) * i, SEEK_SET);
256 		if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) {
257 			printf("\nread phdr error: %s\n", strerror(errno));
258 			return;
259 		}
260 		if (phdr.p_type != Elf_pt_load ||
261 		    (phdr.p_flags & (Elf_pf_w|Elf_pf_x)) == 0)
262 			continue;
263 
264 		/* Read in segment. */
265 		printf("%s%d", first ? "" : "+", phdr.p_filesz);
266 		lseek(fd, phdr.p_offset, SEEK_SET);
267 		if (read(fd, (void *)phdr.p_vaddr, phdr.p_filesz)
268 		    != phdr.p_filesz) {
269 			printf("read text error: %s\n", strerror(errno));
270 			return;
271 		}
272 
273 		/* Zero out bss. */
274 		if (phdr.p_filesz < phdr.p_memsz) {
275 			printf("+%d", phdr.p_memsz - phdr.p_filesz);
276 			bzero(phdr.p_vaddr + phdr.p_filesz,
277 			    phdr.p_memsz - phdr.p_filesz);
278 			sp = (void *)(phdr.p_vaddr + phdr.p_memsz);
279 			startsym = sp = (void *)ALIGN(sp);
280 		}
281 		first = 0;
282 	}
283 
284 	bcopy(&hdr, startsym, ELF32_HDR_SIZE);
285 	((Elf32_Ehdr *)startsym)->e_shoff = ELF32_HDR_SIZE;
286 	sp += ELF32_HDR_SIZE;
287 	ssp = sp + sizeof(shdr) * hdr.e_shnum;
288 	first = 1;
289 	printf("+[");
290 
291 	for (i = 0; i < hdr.e_shnum; i++) {
292 		lseek(fd, hdr.e_shoff + sizeof(shdr) * i, SEEK_SET);
293 		if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) {
294 			printf("\nread shdr error: %s\n", strerror(errno));
295 			return;
296 		}
297 		bcopy(&shdr, sp, sizeof(shdr));
298 		((Elf32_Shdr *)sp)->sh_offset = ssp - startsym;
299 		sp += sizeof(shdr);
300 
301 		if (shdr.sh_type != Elf_sht_strtab &&
302 		    shdr.sh_type != Elf_sht_symtab)
303 			continue;
304 
305 		/* Read in segment. */
306 		printf("%s%d", first ? "" : "+", shdr.sh_size);
307 		lseek(fd, shdr.sh_offset, SEEK_SET);
308 		if (read(fd, ssp, shdr.sh_size) != shdr.sh_size) {
309 			printf("read symbol error: %s\n", strerror(errno));
310 			return;
311 		}
312 		ssp += shdr.sh_size;
313 		ssp = (void *)ALIGN(ssp);
314 		first = 0;
315 	}
316 	endsym = ssp;
317 	printf("]\n");
318 	close(fd);
319 
320 #ifdef DBMONITOR
321 	if (!load_flag) {
322 		*(volatile long *)0x0080 = (long)hdr.e_entry;
323 		run((void *)hdr.e_entry);
324 	}
325 #else /* DBMONITOR */
326 	*(volatile long *)0x0080 = (long)hdr.e_entry;
327 	run((void *)hdr.e_entry);
328 #endif /* DBMONITOR */
329 }
330