xref: /freebsd/stand/powerpc/boot1.chrp/boot1.c (revision 56e53cb8ef000c3ef72337a4095987a932cdedef)
1ca987d46SWarner Losh /*-
2ca987d46SWarner Losh  * Copyright (c) 1998 Robert Nordier
3ca987d46SWarner Losh  * All rights reserved.
4ca987d46SWarner Losh  * Copyright (c) 2001 Robert Drehmel
5ca987d46SWarner Losh  * All rights reserved.
6ca987d46SWarner Losh  *
7ca987d46SWarner Losh  * Redistribution and use in source and binary forms are freely
8ca987d46SWarner Losh  * permitted provided that the above copyright notice and this
9ca987d46SWarner Losh  * paragraph and the following disclaimer are duplicated in all
10ca987d46SWarner Losh  * such forms.
11ca987d46SWarner Losh  *
12ca987d46SWarner Losh  * This software is provided "AS IS" and without any express or
13ca987d46SWarner Losh  * implied warranties, including, without limitation, the implied
14ca987d46SWarner Losh  * warranties of merchantability and fitness for a particular
15ca987d46SWarner Losh  * purpose.
16ca987d46SWarner Losh  */
17ca987d46SWarner Losh 
18ca987d46SWarner Losh #include <sys/cdefs.h>
19ca987d46SWarner Losh __FBSDID("$FreeBSD$");
20ca987d46SWarner Losh 
21ca987d46SWarner Losh #include <sys/param.h>
22ca987d46SWarner Losh #include <sys/dirent.h>
23ca987d46SWarner Losh #include <machine/elf.h>
24ca987d46SWarner Losh #include <machine/stdarg.h>
25a76b2d3dSWarner Losh #include <machine/md_var.h>
26ca987d46SWarner Losh 
27ca987d46SWarner Losh #include "paths.h"
28ca987d46SWarner Losh 
29ca987d46SWarner Losh #define BSIZEMAX	16384
30ca987d46SWarner Losh 
31ca987d46SWarner Losh typedef int putc_func_t(char c, void *arg);
32ca987d46SWarner Losh typedef int32_t ofwh_t;
33ca987d46SWarner Losh 
34ca987d46SWarner Losh struct sp_data {
35ca987d46SWarner Losh 	char	*sp_buf;
36ca987d46SWarner Losh 	u_int	sp_len;
37ca987d46SWarner Losh 	u_int	sp_size;
38ca987d46SWarner Losh };
39ca987d46SWarner Losh 
40ca987d46SWarner Losh static const char digits[] = "0123456789abcdef";
41ca987d46SWarner Losh 
42ca987d46SWarner Losh static char bootpath[128];
43ca987d46SWarner Losh static char bootargs[128];
44ca987d46SWarner Losh 
45ca987d46SWarner Losh static ofwh_t bootdev;
46ca987d46SWarner Losh 
47ca987d46SWarner Losh static struct fs fs;
48ca987d46SWarner Losh static char blkbuf[BSIZEMAX];
49ca987d46SWarner Losh static unsigned int fsblks;
50ca987d46SWarner Losh 
51ca987d46SWarner Losh static uint32_t fs_off;
52ca987d46SWarner Losh 
53ca987d46SWarner Losh int main(int ac, char **av);
54ca987d46SWarner Losh 
55ca987d46SWarner Losh static void exit(int) __dead2;
56ca987d46SWarner Losh static void load(const char *);
57*56e53cb8SWarner Losh static int dskread(void *, uint64_t, int);
58ca987d46SWarner Losh 
59ca987d46SWarner Losh static void usage(void);
60ca987d46SWarner Losh 
61ca987d46SWarner Losh static void bcopy(const void *src, void *dst, size_t len);
62ca987d46SWarner Losh static void bzero(void *b, size_t len);
63ca987d46SWarner Losh 
64ca987d46SWarner Losh static int domount(const char *device, int quiet);
65ca987d46SWarner Losh 
66ca987d46SWarner Losh static void panic(const char *fmt, ...) __dead2;
67ca987d46SWarner Losh static int printf(const char *fmt, ...);
68ca987d46SWarner Losh static int putchar(char c, void *arg);
69ca987d46SWarner Losh static int vprintf(const char *fmt, va_list ap);
70ca987d46SWarner Losh static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
71ca987d46SWarner Losh 
72ca987d46SWarner Losh static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
73ca987d46SWarner Losh static int __putc(char c, void *arg);
74ca987d46SWarner Losh static int __puts(const char *s, putc_func_t *putc, void *arg);
75ca987d46SWarner Losh static int __sputc(char c, void *arg);
76ca987d46SWarner Losh static char *__uitoa(char *buf, u_int val, int base);
77ca987d46SWarner Losh static char *__ultoa(char *buf, u_long val, int base);
78ca987d46SWarner Losh 
79ca987d46SWarner Losh /*
80ca987d46SWarner Losh  * Open Firmware interface functions
81ca987d46SWarner Losh  */
82*56e53cb8SWarner Losh typedef uint32_t	ofwcell_t;
83*56e53cb8SWarner Losh typedef uint32_t	u_ofwh_t;
84ca987d46SWarner Losh typedef int (*ofwfp_t)(void *);
85ca987d46SWarner Losh ofwfp_t ofw;			/* the prom Open Firmware entry */
86ca987d46SWarner Losh ofwh_t chosenh;
87ca987d46SWarner Losh 
88ca987d46SWarner Losh void ofw_init(void *, int, int (*)(void *), char *, int);
89ca987d46SWarner Losh static ofwh_t ofw_finddevice(const char *);
90ca987d46SWarner Losh static ofwh_t ofw_open(const char *);
91ca987d46SWarner Losh static int ofw_close(ofwh_t);
92ca987d46SWarner Losh static int ofw_getprop(ofwh_t, const char *, void *, size_t);
93ca987d46SWarner Losh static int ofw_setprop(ofwh_t, const char *, void *, size_t);
94ca987d46SWarner Losh static int ofw_read(ofwh_t, void *, size_t);
95ca987d46SWarner Losh static int ofw_write(ofwh_t, const void *, size_t);
96ca987d46SWarner Losh static int ofw_claim(void *virt, size_t len, u_int align);
97*56e53cb8SWarner Losh static int ofw_seek(ofwh_t, uint64_t);
98ca987d46SWarner Losh static void ofw_exit(void) __dead2;
99ca987d46SWarner Losh 
100ca987d46SWarner Losh ofwh_t bootdevh;
101ca987d46SWarner Losh ofwh_t stdinh, stdouth;
102ca987d46SWarner Losh 
103ca987d46SWarner Losh __asm("                         \n\
104ca987d46SWarner Losh         .data                   \n\
105ca987d46SWarner Losh 	.align 4		\n\
106ca987d46SWarner Losh stack:                          \n\
107ca987d46SWarner Losh         .space  16384           \n\
108ca987d46SWarner Losh                                 \n\
109ca987d46SWarner Losh         .text                   \n\
110ca987d46SWarner Losh         .globl  _start          \n\
111ca987d46SWarner Losh _start:                         \n\
112ca987d46SWarner Losh         lis     %r1,stack@ha    \n\
113ca987d46SWarner Losh         addi    %r1,%r1,stack@l \n\
114ca987d46SWarner Losh         addi    %r1,%r1,8192    \n\
115ca987d46SWarner Losh                                 \n\
116ca987d46SWarner Losh         b       ofw_init        \n\
117ca987d46SWarner Losh ");
118ca987d46SWarner Losh 
119ca987d46SWarner Losh void
120ca987d46SWarner Losh ofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
121ca987d46SWarner Losh {
122ca987d46SWarner Losh 	char *av[16];
123ca987d46SWarner Losh 	char *p;
124ca987d46SWarner Losh 	int ac;
125ca987d46SWarner Losh 
126ca987d46SWarner Losh 	ofw = openfirm;
127ca987d46SWarner Losh 
128ca987d46SWarner Losh 	chosenh = ofw_finddevice("/chosen");
129ca987d46SWarner Losh 	ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh));
130ca987d46SWarner Losh 	ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth));
131ca987d46SWarner Losh 	ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs));
132ca987d46SWarner Losh 	ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
133ca987d46SWarner Losh 
134ca987d46SWarner Losh 	bootargs[sizeof(bootargs) - 1] = '\0';
135ca987d46SWarner Losh 	bootpath[sizeof(bootpath) - 1] = '\0';
136ca987d46SWarner Losh 
137ca987d46SWarner Losh 	p = bootpath;
138ca987d46SWarner Losh 	while (*p != '\0') {
139ca987d46SWarner Losh 		/* Truncate partition ID */
140ca987d46SWarner Losh 		if (*p == ':') {
141ca987d46SWarner Losh 			ofw_close(bootdev);
142ca987d46SWarner Losh 			*(++p) = '\0';
143ca987d46SWarner Losh 			break;
144ca987d46SWarner Losh 		}
145ca987d46SWarner Losh 		p++;
146ca987d46SWarner Losh 	}
147ca987d46SWarner Losh 
148ca987d46SWarner Losh 	ac = 0;
149ca987d46SWarner Losh 	p = bootargs;
150ca987d46SWarner Losh 	for (;;) {
151ca987d46SWarner Losh 		while (*p == ' ' && *p != '\0')
152ca987d46SWarner Losh 			p++;
153ca987d46SWarner Losh 		if (*p == '\0' || ac >= 16)
154ca987d46SWarner Losh 			break;
155ca987d46SWarner Losh 		av[ac++] = p;
156ca987d46SWarner Losh 		while (*p != ' ' && *p != '\0')
157ca987d46SWarner Losh 			p++;
158ca987d46SWarner Losh 		if (*p != '\0')
159ca987d46SWarner Losh 			*p++ = '\0';
160ca987d46SWarner Losh 	}
161ca987d46SWarner Losh 
162ca987d46SWarner Losh 	exit(main(ac, av));
163ca987d46SWarner Losh }
164ca987d46SWarner Losh 
165ca987d46SWarner Losh static ofwh_t
166ca987d46SWarner Losh ofw_finddevice(const char *name)
167ca987d46SWarner Losh {
168ca987d46SWarner Losh 	ofwcell_t args[] = {
169ca987d46SWarner Losh 		(ofwcell_t)"finddevice",
170ca987d46SWarner Losh 		1,
171ca987d46SWarner Losh 		1,
172ca987d46SWarner Losh 		(ofwcell_t)name,
173ca987d46SWarner Losh 		0
174ca987d46SWarner Losh 	};
175ca987d46SWarner Losh 
176ca987d46SWarner Losh 	if ((*ofw)(args)) {
177ca987d46SWarner Losh 		printf("ofw_finddevice: name=\"%s\"\n", name);
178ca987d46SWarner Losh 		return (1);
179ca987d46SWarner Losh 	}
180ca987d46SWarner Losh 	return (args[4]);
181ca987d46SWarner Losh }
182ca987d46SWarner Losh 
183ca987d46SWarner Losh static int
184ca987d46SWarner Losh ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
185ca987d46SWarner Losh {
186ca987d46SWarner Losh 	ofwcell_t args[] = {
187ca987d46SWarner Losh 		(ofwcell_t)"getprop",
188ca987d46SWarner Losh 		4,
189ca987d46SWarner Losh 		1,
190ca987d46SWarner Losh 		(u_ofwh_t)ofwh,
191ca987d46SWarner Losh 		(ofwcell_t)name,
192ca987d46SWarner Losh 		(ofwcell_t)buf,
193ca987d46SWarner Losh 		len,
194ca987d46SWarner Losh 	0
195ca987d46SWarner Losh 	};
196ca987d46SWarner Losh 
197ca987d46SWarner Losh 	if ((*ofw)(args)) {
198ca987d46SWarner Losh 		printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n",
199ca987d46SWarner Losh 			ofwh, buf, len);
200ca987d46SWarner Losh 		return (1);
201ca987d46SWarner Losh 	}
202ca987d46SWarner Losh 	return (0);
203ca987d46SWarner Losh }
204ca987d46SWarner Losh 
205ca987d46SWarner Losh static int
206ca987d46SWarner Losh ofw_setprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
207ca987d46SWarner Losh {
208ca987d46SWarner Losh 	ofwcell_t args[] = {
209ca987d46SWarner Losh 		(ofwcell_t)"setprop",
210ca987d46SWarner Losh 		4,
211ca987d46SWarner Losh 		1,
212ca987d46SWarner Losh 		(u_ofwh_t)ofwh,
213ca987d46SWarner Losh 		(ofwcell_t)name,
214ca987d46SWarner Losh 		(ofwcell_t)buf,
215ca987d46SWarner Losh 		len,
216ca987d46SWarner Losh 	0
217ca987d46SWarner Losh 	};
218ca987d46SWarner Losh 
219ca987d46SWarner Losh 	if ((*ofw)(args)) {
220ca987d46SWarner Losh 		printf("ofw_setprop: ofwh=0x%x buf=%p len=%u\n",
221ca987d46SWarner Losh 			ofwh, buf, len);
222ca987d46SWarner Losh 		return (1);
223ca987d46SWarner Losh 	}
224ca987d46SWarner Losh 	return (0);
225ca987d46SWarner Losh }
226ca987d46SWarner Losh 
227ca987d46SWarner Losh static ofwh_t
228ca987d46SWarner Losh ofw_open(const char *path)
229ca987d46SWarner Losh {
230ca987d46SWarner Losh 	ofwcell_t args[] = {
231ca987d46SWarner Losh 		(ofwcell_t)"open",
232ca987d46SWarner Losh 		1,
233ca987d46SWarner Losh 		1,
234ca987d46SWarner Losh 		(ofwcell_t)path,
235ca987d46SWarner Losh 		0
236ca987d46SWarner Losh 	};
237ca987d46SWarner Losh 
238ca987d46SWarner Losh 	if ((*ofw)(args)) {
239ca987d46SWarner Losh 		printf("ofw_open: path=\"%s\"\n", path);
240ca987d46SWarner Losh 		return (-1);
241ca987d46SWarner Losh 	}
242ca987d46SWarner Losh 	return (args[4]);
243ca987d46SWarner Losh }
244ca987d46SWarner Losh 
245ca987d46SWarner Losh static int
246ca987d46SWarner Losh ofw_close(ofwh_t devh)
247ca987d46SWarner Losh {
248ca987d46SWarner Losh 	ofwcell_t args[] = {
249ca987d46SWarner Losh 		(ofwcell_t)"close",
250ca987d46SWarner Losh 		1,
251ca987d46SWarner Losh 		0,
252ca987d46SWarner Losh 		(u_ofwh_t)devh
253ca987d46SWarner Losh 	};
254ca987d46SWarner Losh 
255ca987d46SWarner Losh 	if ((*ofw)(args)) {
256ca987d46SWarner Losh 		printf("ofw_close: devh=0x%x\n", devh);
257ca987d46SWarner Losh 		return (1);
258ca987d46SWarner Losh 	}
259ca987d46SWarner Losh 	return (0);
260ca987d46SWarner Losh }
261ca987d46SWarner Losh 
262ca987d46SWarner Losh static int
263ca987d46SWarner Losh ofw_claim(void *virt, size_t len, u_int align)
264ca987d46SWarner Losh {
265ca987d46SWarner Losh 	ofwcell_t args[] = {
266ca987d46SWarner Losh 		(ofwcell_t)"claim",
267ca987d46SWarner Losh 		3,
268ca987d46SWarner Losh 		1,
269ca987d46SWarner Losh 		(ofwcell_t)virt,
270ca987d46SWarner Losh 		len,
271ca987d46SWarner Losh 		align,
272ca987d46SWarner Losh 		0,
273ca987d46SWarner Losh 		0
274ca987d46SWarner Losh 	};
275ca987d46SWarner Losh 
276ca987d46SWarner Losh 	if ((*ofw)(args)) {
277ca987d46SWarner Losh 		printf("ofw_claim: virt=%p len=%u\n", virt, len);
278ca987d46SWarner Losh 		return (1);
279ca987d46SWarner Losh 	}
280ca987d46SWarner Losh 
281ca987d46SWarner Losh 	return (0);
282ca987d46SWarner Losh }
283ca987d46SWarner Losh 
284ca987d46SWarner Losh static int
285ca987d46SWarner Losh ofw_read(ofwh_t devh, void *buf, size_t len)
286ca987d46SWarner Losh {
287ca987d46SWarner Losh 	ofwcell_t args[] = {
288ca987d46SWarner Losh 		(ofwcell_t)"read",
289ca987d46SWarner Losh 		3,
290ca987d46SWarner Losh 		1,
291ca987d46SWarner Losh 		(u_ofwh_t)devh,
292ca987d46SWarner Losh 		(ofwcell_t)buf,
293ca987d46SWarner Losh 		len,
294ca987d46SWarner Losh 		0
295ca987d46SWarner Losh 	};
296ca987d46SWarner Losh 
297ca987d46SWarner Losh 	if ((*ofw)(args)) {
298ca987d46SWarner Losh 		printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len);
299ca987d46SWarner Losh 		return (1);
300ca987d46SWarner Losh 	}
301ca987d46SWarner Losh 	return (0);
302ca987d46SWarner Losh }
303ca987d46SWarner Losh 
304ca987d46SWarner Losh static int
305ca987d46SWarner Losh ofw_write(ofwh_t devh, const void *buf, size_t len)
306ca987d46SWarner Losh {
307ca987d46SWarner Losh 	ofwcell_t args[] = {
308ca987d46SWarner Losh 		(ofwcell_t)"write",
309ca987d46SWarner Losh 		3,
310ca987d46SWarner Losh 		1,
311ca987d46SWarner Losh 		(u_ofwh_t)devh,
312ca987d46SWarner Losh 		(ofwcell_t)buf,
313ca987d46SWarner Losh 		len,
314ca987d46SWarner Losh 		0
315ca987d46SWarner Losh 	};
316ca987d46SWarner Losh 
317ca987d46SWarner Losh 	if ((*ofw)(args)) {
318ca987d46SWarner Losh 		printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len);
319ca987d46SWarner Losh 		return (1);
320ca987d46SWarner Losh 	}
321ca987d46SWarner Losh 	return (0);
322ca987d46SWarner Losh }
323ca987d46SWarner Losh 
324ca987d46SWarner Losh static int
325*56e53cb8SWarner Losh ofw_seek(ofwh_t devh, uint64_t off)
326ca987d46SWarner Losh {
327ca987d46SWarner Losh 	ofwcell_t args[] = {
328ca987d46SWarner Losh 		(ofwcell_t)"seek",
329ca987d46SWarner Losh 		3,
330ca987d46SWarner Losh 		1,
331ca987d46SWarner Losh 		(u_ofwh_t)devh,
332ca987d46SWarner Losh 		off >> 32,
333ca987d46SWarner Losh 		off,
334ca987d46SWarner Losh 		0
335ca987d46SWarner Losh 	};
336ca987d46SWarner Losh 
337ca987d46SWarner Losh 	if ((*ofw)(args)) {
338ca987d46SWarner Losh 		printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off);
339ca987d46SWarner Losh 		return (1);
340ca987d46SWarner Losh 	}
341ca987d46SWarner Losh 	return (0);
342ca987d46SWarner Losh }
343ca987d46SWarner Losh 
344ca987d46SWarner Losh static void
345ca987d46SWarner Losh ofw_exit(void)
346ca987d46SWarner Losh {
347ca987d46SWarner Losh 	ofwcell_t args[3];
348ca987d46SWarner Losh 
349ca987d46SWarner Losh 	args[0] = (ofwcell_t)"exit";
350ca987d46SWarner Losh 	args[1] = 0;
351ca987d46SWarner Losh 	args[2] = 0;
352ca987d46SWarner Losh 
353ca987d46SWarner Losh 	for (;;)
354ca987d46SWarner Losh 		(*ofw)(args);
355ca987d46SWarner Losh }
356ca987d46SWarner Losh 
357ca987d46SWarner Losh static void
358ca987d46SWarner Losh bcopy(const void *src, void *dst, size_t len)
359ca987d46SWarner Losh {
360ca987d46SWarner Losh 	const char *s = src;
361ca987d46SWarner Losh 	char *d = dst;
362ca987d46SWarner Losh 
363ca987d46SWarner Losh 	while (len-- != 0)
364ca987d46SWarner Losh 		*d++ = *s++;
365ca987d46SWarner Losh }
366ca987d46SWarner Losh 
367ca987d46SWarner Losh static void
368ca987d46SWarner Losh memcpy(void *dst, const void *src, size_t len)
369ca987d46SWarner Losh {
370ca987d46SWarner Losh 	bcopy(src, dst, len);
371ca987d46SWarner Losh }
372ca987d46SWarner Losh 
373ca987d46SWarner Losh static void
374ca987d46SWarner Losh bzero(void *b, size_t len)
375ca987d46SWarner Losh {
376ca987d46SWarner Losh 	char *p = b;
377ca987d46SWarner Losh 
378ca987d46SWarner Losh 	while (len-- != 0)
379ca987d46SWarner Losh 		*p++ = 0;
380ca987d46SWarner Losh }
381ca987d46SWarner Losh 
382ca987d46SWarner Losh static int
383ca987d46SWarner Losh strcmp(const char *s1, const char *s2)
384ca987d46SWarner Losh {
385ca987d46SWarner Losh 	for (; *s1 == *s2 && *s1; s1++, s2++)
386ca987d46SWarner Losh 		;
387ca987d46SWarner Losh 	return ((u_char)*s1 - (u_char)*s2);
388ca987d46SWarner Losh }
389ca987d46SWarner Losh 
390ca987d46SWarner Losh #include "ufsread.c"
391ca987d46SWarner Losh 
392ca987d46SWarner Losh int
393ca987d46SWarner Losh main(int ac, char **av)
394ca987d46SWarner Losh {
395ca987d46SWarner Losh 	const char *path;
396ca987d46SWarner Losh 	char bootpath_full[255];
397ca987d46SWarner Losh 	int i, len;
398ca987d46SWarner Losh 
399ca987d46SWarner Losh 	path = PATH_LOADER;
400ca987d46SWarner Losh 	for (i = 0; i < ac; i++) {
401ca987d46SWarner Losh 		switch (av[i][0]) {
402ca987d46SWarner Losh 		case '-':
403ca987d46SWarner Losh 			switch (av[i][1]) {
404ca987d46SWarner Losh 			default:
405ca987d46SWarner Losh 				usage();
406ca987d46SWarner Losh 			}
407ca987d46SWarner Losh 			break;
408ca987d46SWarner Losh 		default:
409ca987d46SWarner Losh 			path = av[i];
410ca987d46SWarner Losh 			break;
411ca987d46SWarner Losh 		}
412ca987d46SWarner Losh 	}
413ca987d46SWarner Losh 
414ca987d46SWarner Losh 	printf(" \n>> FreeBSD/powerpc Open Firmware boot block\n"
415ca987d46SWarner Losh 	"   Boot path:   %s\n"
416ca987d46SWarner Losh 	"   Boot loader: %s\n", bootpath, path);
417ca987d46SWarner Losh 
418ca987d46SWarner Losh 	len = 0;
419ca987d46SWarner Losh 	while (bootpath[len] != '\0') len++;
420ca987d46SWarner Losh 
421ca987d46SWarner Losh 	memcpy(bootpath_full,bootpath,len+1);
422ca987d46SWarner Losh 
423ca987d46SWarner Losh 	if (bootpath_full[len-1] != ':') {
424ca987d46SWarner Losh 		/* First try full volume */
425ca987d46SWarner Losh 		if (domount(bootpath_full,1) == 0)
426ca987d46SWarner Losh 			goto out;
427ca987d46SWarner Losh 
428ca987d46SWarner Losh 		/* Add a : so that we try partitions if that fails */
429ca987d46SWarner Losh 		if (bootdev > 0)
430ca987d46SWarner Losh 			ofw_close(bootdev);
431ca987d46SWarner Losh 		bootpath_full[len] = ':';
432ca987d46SWarner Losh 		len += 1;
433ca987d46SWarner Losh 	}
434ca987d46SWarner Losh 
435ca987d46SWarner Losh 	/* Loop through first 16 partitions to find a UFS one */
436ca987d46SWarner Losh 	for (i = 0; i < 16; i++) {
437ca987d46SWarner Losh 		if (i < 10) {
438ca987d46SWarner Losh 			bootpath_full[len] = i + '0';
439ca987d46SWarner Losh 			bootpath_full[len+1] = '\0';
440ca987d46SWarner Losh 		} else {
441ca987d46SWarner Losh 			bootpath_full[len] = '1';
442ca987d46SWarner Losh 			bootpath_full[len+1] = i - 10 + '0';
443ca987d46SWarner Losh 			bootpath_full[len+2] = '\0';
444ca987d46SWarner Losh 		}
445ca987d46SWarner Losh 
446ca987d46SWarner Losh 		if (domount(bootpath_full,1) >= 0)
447ca987d46SWarner Losh 			break;
448ca987d46SWarner Losh 
449ca987d46SWarner Losh 		if (bootdev > 0)
450ca987d46SWarner Losh 			ofw_close(bootdev);
451ca987d46SWarner Losh 	}
452ca987d46SWarner Losh 
453ca987d46SWarner Losh 	if (i >= 16)
454ca987d46SWarner Losh 		panic("domount");
455ca987d46SWarner Losh 
456ca987d46SWarner Losh out:
457ca987d46SWarner Losh 	printf("   Boot volume:   %s\n",bootpath_full);
458ca987d46SWarner Losh 	ofw_setprop(chosenh, "bootargs", bootpath_full, len+2);
459ca987d46SWarner Losh 	load(path);
460ca987d46SWarner Losh 	return (1);
461ca987d46SWarner Losh }
462ca987d46SWarner Losh 
463ca987d46SWarner Losh static void
464ca987d46SWarner Losh usage(void)
465ca987d46SWarner Losh {
466ca987d46SWarner Losh 
467ca987d46SWarner Losh 	printf("usage: boot device [/path/to/loader]\n");
468ca987d46SWarner Losh 	exit(1);
469ca987d46SWarner Losh }
470ca987d46SWarner Losh 
471ca987d46SWarner Losh static void
472ca987d46SWarner Losh exit(int code)
473ca987d46SWarner Losh {
474ca987d46SWarner Losh 
475ca987d46SWarner Losh 	ofw_exit();
476ca987d46SWarner Losh }
477ca987d46SWarner Losh 
478ca987d46SWarner Losh static struct dmadat __dmadat;
479ca987d46SWarner Losh 
480ca987d46SWarner Losh static int
481ca987d46SWarner Losh domount(const char *device, int quiet)
482ca987d46SWarner Losh {
483ca987d46SWarner Losh 
484ca987d46SWarner Losh 	dmadat = &__dmadat;
485ca987d46SWarner Losh 	if ((bootdev = ofw_open(device)) == -1) {
486ca987d46SWarner Losh 		printf("domount: can't open device\n");
487ca987d46SWarner Losh 		return (-1);
488ca987d46SWarner Losh 	}
489ca987d46SWarner Losh 	if (fsread(0, NULL, 0)) {
490ca987d46SWarner Losh 		if (!quiet)
491ca987d46SWarner Losh 			printf("domount: can't read superblock\n");
492ca987d46SWarner Losh 		return (-1);
493ca987d46SWarner Losh 	}
494ca987d46SWarner Losh 	return (0);
495ca987d46SWarner Losh }
496ca987d46SWarner Losh 
497ca987d46SWarner Losh static void
498ca987d46SWarner Losh load(const char *fname)
499ca987d46SWarner Losh {
500ca987d46SWarner Losh 	Elf32_Ehdr eh;
501ca987d46SWarner Losh 	Elf32_Phdr ph;
502ca987d46SWarner Losh 	caddr_t p;
503ca987d46SWarner Losh 	ufs_ino_t ino;
504ca987d46SWarner Losh 	int i;
505ca987d46SWarner Losh 
506ca987d46SWarner Losh 	if ((ino = lookup(fname)) == 0) {
507ca987d46SWarner Losh 		printf("File %s not found\n", fname);
508ca987d46SWarner Losh 		return;
509ca987d46SWarner Losh 	}
510ca987d46SWarner Losh 	if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) {
511ca987d46SWarner Losh 		printf("Can't read elf header\n");
512ca987d46SWarner Losh 		return;
513ca987d46SWarner Losh 	}
514ca987d46SWarner Losh 	if (!IS_ELF(eh)) {
515ca987d46SWarner Losh 		printf("Not an ELF file\n");
516ca987d46SWarner Losh 		return;
517ca987d46SWarner Losh 	}
518ca987d46SWarner Losh 	for (i = 0; i < eh.e_phnum; i++) {
519ca987d46SWarner Losh 		fs_off = eh.e_phoff + i * eh.e_phentsize;
520ca987d46SWarner Losh 		if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) {
521ca987d46SWarner Losh 			printf("Can't read program header %d\n", i);
522ca987d46SWarner Losh 			return;
523ca987d46SWarner Losh 		}
524ca987d46SWarner Losh 		if (ph.p_type != PT_LOAD)
525ca987d46SWarner Losh 			continue;
526ca987d46SWarner Losh 		fs_off = ph.p_offset;
527ca987d46SWarner Losh 		p = (caddr_t)ph.p_vaddr;
528ca987d46SWarner Losh 		ofw_claim(p,(ph.p_filesz > ph.p_memsz) ?
529ca987d46SWarner Losh 		    ph.p_filesz : ph.p_memsz,0);
530ca987d46SWarner Losh 		if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) {
531ca987d46SWarner Losh 			printf("Can't read content of section %d\n", i);
532ca987d46SWarner Losh 			return;
533ca987d46SWarner Losh 		}
534ca987d46SWarner Losh 		if (ph.p_filesz != ph.p_memsz)
535ca987d46SWarner Losh 			bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
536ca987d46SWarner Losh 		__syncicache(p, ph.p_memsz);
537ca987d46SWarner Losh 	}
538ca987d46SWarner Losh 	ofw_close(bootdev);
539ca987d46SWarner Losh 	(*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0,
540ca987d46SWarner Losh 	    ofw,NULL,0);
541ca987d46SWarner Losh }
542ca987d46SWarner Losh 
543ca987d46SWarner Losh static int
544*56e53cb8SWarner Losh dskread(void *buf, uint64_t lba, int nblk)
545ca987d46SWarner Losh {
546ca987d46SWarner Losh 	/*
547ca987d46SWarner Losh 	 * The Open Firmware should open the correct partition for us.
548ca987d46SWarner Losh 	 * That means, if we read from offset zero on an open instance handle,
549ca987d46SWarner Losh 	 * we should read from offset zero of that partition.
550ca987d46SWarner Losh 	 */
551ca987d46SWarner Losh 	ofw_seek(bootdev, lba * DEV_BSIZE);
552ca987d46SWarner Losh 	ofw_read(bootdev, buf, nblk * DEV_BSIZE);
553ca987d46SWarner Losh 	return (0);
554ca987d46SWarner Losh }
555ca987d46SWarner Losh 
556ca987d46SWarner Losh static void
557ca987d46SWarner Losh panic(const char *fmt, ...)
558ca987d46SWarner Losh {
559ca987d46SWarner Losh 	char buf[128];
560ca987d46SWarner Losh 	va_list ap;
561ca987d46SWarner Losh 
562ca987d46SWarner Losh 	va_start(ap, fmt);
563ca987d46SWarner Losh 	vsnprintf(buf, sizeof buf, fmt, ap);
564ca987d46SWarner Losh 	printf("panic: %s\n", buf);
565ca987d46SWarner Losh 	va_end(ap);
566ca987d46SWarner Losh 
567ca987d46SWarner Losh 	exit(1);
568ca987d46SWarner Losh }
569ca987d46SWarner Losh 
570ca987d46SWarner Losh static int
571ca987d46SWarner Losh printf(const char *fmt, ...)
572ca987d46SWarner Losh {
573ca987d46SWarner Losh 	va_list ap;
574ca987d46SWarner Losh 	int ret;
575ca987d46SWarner Losh 
576ca987d46SWarner Losh 	va_start(ap, fmt);
577ca987d46SWarner Losh 	ret = vprintf(fmt, ap);
578ca987d46SWarner Losh 	va_end(ap);
579ca987d46SWarner Losh 	return (ret);
580ca987d46SWarner Losh }
581ca987d46SWarner Losh 
582ca987d46SWarner Losh static int
583ca987d46SWarner Losh putchar(char c, void *arg)
584ca987d46SWarner Losh {
585ca987d46SWarner Losh 	char buf;
586ca987d46SWarner Losh 
587ca987d46SWarner Losh 	if (c == '\n') {
588ca987d46SWarner Losh 		buf = '\r';
589ca987d46SWarner Losh 		ofw_write(stdouth, &buf, 1);
590ca987d46SWarner Losh 	}
591ca987d46SWarner Losh 	buf = c;
592ca987d46SWarner Losh 	ofw_write(stdouth, &buf, 1);
593ca987d46SWarner Losh 	return (1);
594ca987d46SWarner Losh }
595ca987d46SWarner Losh 
596ca987d46SWarner Losh static int
597ca987d46SWarner Losh vprintf(const char *fmt, va_list ap)
598ca987d46SWarner Losh {
599ca987d46SWarner Losh 	int ret;
600ca987d46SWarner Losh 
601ca987d46SWarner Losh 	ret = __printf(fmt, putchar, 0, ap);
602ca987d46SWarner Losh 	return (ret);
603ca987d46SWarner Losh }
604ca987d46SWarner Losh 
605ca987d46SWarner Losh static int
606ca987d46SWarner Losh vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
607ca987d46SWarner Losh {
608ca987d46SWarner Losh 	struct sp_data sp;
609ca987d46SWarner Losh 	int ret;
610ca987d46SWarner Losh 
611ca987d46SWarner Losh 	sp.sp_buf = str;
612ca987d46SWarner Losh 	sp.sp_len = 0;
613ca987d46SWarner Losh 	sp.sp_size = sz;
614ca987d46SWarner Losh 	ret = __printf(fmt, __sputc, &sp, ap);
615ca987d46SWarner Losh 	return (ret);
616ca987d46SWarner Losh }
617ca987d46SWarner Losh 
618ca987d46SWarner Losh static int
619ca987d46SWarner Losh __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
620ca987d46SWarner Losh {
621ca987d46SWarner Losh 	char buf[(sizeof(long) * 8) + 1];
622ca987d46SWarner Losh 	char *nbuf;
623ca987d46SWarner Losh 	u_long ul;
624ca987d46SWarner Losh 	u_int ui;
625ca987d46SWarner Losh 	int lflag;
626ca987d46SWarner Losh 	int sflag;
627ca987d46SWarner Losh 	char *s;
628ca987d46SWarner Losh 	int pad;
629ca987d46SWarner Losh 	int ret;
630ca987d46SWarner Losh 	int c;
631ca987d46SWarner Losh 
632ca987d46SWarner Losh 	nbuf = &buf[sizeof buf - 1];
633ca987d46SWarner Losh 	ret = 0;
634ca987d46SWarner Losh 	while ((c = *fmt++) != 0) {
635ca987d46SWarner Losh 		if (c != '%') {
636ca987d46SWarner Losh 			ret += putc(c, arg);
637ca987d46SWarner Losh 			continue;
638ca987d46SWarner Losh 		}
639ca987d46SWarner Losh 		lflag = 0;
640ca987d46SWarner Losh 		sflag = 0;
641ca987d46SWarner Losh 		pad = 0;
642ca987d46SWarner Losh reswitch:	c = *fmt++;
643ca987d46SWarner Losh 		switch (c) {
644ca987d46SWarner Losh 		case '#':
645ca987d46SWarner Losh 			sflag = 1;
646ca987d46SWarner Losh 			goto reswitch;
647ca987d46SWarner Losh 		case '%':
648ca987d46SWarner Losh 			ret += putc('%', arg);
649ca987d46SWarner Losh 			break;
650ca987d46SWarner Losh 		case 'c':
651ca987d46SWarner Losh 			c = va_arg(ap, int);
652ca987d46SWarner Losh 			ret += putc(c, arg);
653ca987d46SWarner Losh 			break;
654ca987d46SWarner Losh 		case 'd':
655ca987d46SWarner Losh 			if (lflag == 0) {
656ca987d46SWarner Losh 				ui = (u_int)va_arg(ap, int);
657ca987d46SWarner Losh 				if (ui < (int)ui) {
658ca987d46SWarner Losh 					ui = -ui;
659ca987d46SWarner Losh 					ret += putc('-', arg);
660ca987d46SWarner Losh 				}
661ca987d46SWarner Losh 				s = __uitoa(nbuf, ui, 10);
662ca987d46SWarner Losh 			} else {
663ca987d46SWarner Losh 				ul = (u_long)va_arg(ap, long);
664ca987d46SWarner Losh 				if (ul < (long)ul) {
665ca987d46SWarner Losh 					ul = -ul;
666ca987d46SWarner Losh 					ret += putc('-', arg);
667ca987d46SWarner Losh 				}
668ca987d46SWarner Losh 				s = __ultoa(nbuf, ul, 10);
669ca987d46SWarner Losh 			}
670ca987d46SWarner Losh 			ret += __puts(s, putc, arg);
671ca987d46SWarner Losh 			break;
672ca987d46SWarner Losh 		case 'l':
673ca987d46SWarner Losh 			lflag = 1;
674ca987d46SWarner Losh 			goto reswitch;
675ca987d46SWarner Losh 		case 'o':
676ca987d46SWarner Losh 			if (lflag == 0) {
677ca987d46SWarner Losh 				ui = (u_int)va_arg(ap, u_int);
678ca987d46SWarner Losh 				s = __uitoa(nbuf, ui, 8);
679ca987d46SWarner Losh 			} else {
680ca987d46SWarner Losh 				ul = (u_long)va_arg(ap, u_long);
681ca987d46SWarner Losh 				s = __ultoa(nbuf, ul, 8);
682ca987d46SWarner Losh 			}
683ca987d46SWarner Losh 			ret += __puts(s, putc, arg);
684ca987d46SWarner Losh 			break;
685ca987d46SWarner Losh 		case 'p':
686ca987d46SWarner Losh 			ul = (u_long)va_arg(ap, void *);
687ca987d46SWarner Losh 			s = __ultoa(nbuf, ul, 16);
688ca987d46SWarner Losh 			ret += __puts("0x", putc, arg);
689ca987d46SWarner Losh 			ret += __puts(s, putc, arg);
690ca987d46SWarner Losh 			break;
691ca987d46SWarner Losh 		case 's':
692ca987d46SWarner Losh 			s = va_arg(ap, char *);
693ca987d46SWarner Losh 			ret += __puts(s, putc, arg);
694ca987d46SWarner Losh 			break;
695ca987d46SWarner Losh 		case 'u':
696ca987d46SWarner Losh 			if (lflag == 0) {
697ca987d46SWarner Losh 				ui = va_arg(ap, u_int);
698ca987d46SWarner Losh 				s = __uitoa(nbuf, ui, 10);
699ca987d46SWarner Losh 			} else {
700ca987d46SWarner Losh 				ul = va_arg(ap, u_long);
701ca987d46SWarner Losh 				s = __ultoa(nbuf, ul, 10);
702ca987d46SWarner Losh 			}
703ca987d46SWarner Losh 			ret += __puts(s, putc, arg);
704ca987d46SWarner Losh 			break;
705ca987d46SWarner Losh 		case 'x':
706ca987d46SWarner Losh 			if (lflag == 0) {
707ca987d46SWarner Losh 				ui = va_arg(ap, u_int);
708ca987d46SWarner Losh 				s = __uitoa(nbuf, ui, 16);
709ca987d46SWarner Losh 			} else {
710ca987d46SWarner Losh 				ul = va_arg(ap, u_long);
711ca987d46SWarner Losh 				s = __ultoa(nbuf, ul, 16);
712ca987d46SWarner Losh 			}
713ca987d46SWarner Losh 			if (sflag)
714ca987d46SWarner Losh 				ret += __puts("0x", putc, arg);
715ca987d46SWarner Losh 			ret += __puts(s, putc, arg);
716ca987d46SWarner Losh 			break;
717ca987d46SWarner Losh 		case '0': case '1': case '2': case '3': case '4':
718ca987d46SWarner Losh 		case '5': case '6': case '7': case '8': case '9':
719ca987d46SWarner Losh 			pad = pad * 10 + c - '0';
720ca987d46SWarner Losh 			goto reswitch;
721ca987d46SWarner Losh 		default:
722ca987d46SWarner Losh 			break;
723ca987d46SWarner Losh 		}
724ca987d46SWarner Losh 	}
725ca987d46SWarner Losh 	return (ret);
726ca987d46SWarner Losh }
727ca987d46SWarner Losh 
728ca987d46SWarner Losh static int
729ca987d46SWarner Losh __sputc(char c, void *arg)
730ca987d46SWarner Losh {
731ca987d46SWarner Losh 	struct sp_data *sp;
732ca987d46SWarner Losh 
733ca987d46SWarner Losh 	sp = arg;
734ca987d46SWarner Losh 	if (sp->sp_len < sp->sp_size)
735ca987d46SWarner Losh 		sp->sp_buf[sp->sp_len++] = c;
736ca987d46SWarner Losh 	sp->sp_buf[sp->sp_len] = '\0';
737ca987d46SWarner Losh 	return (1);
738ca987d46SWarner Losh }
739ca987d46SWarner Losh 
740ca987d46SWarner Losh static int
741ca987d46SWarner Losh __puts(const char *s, putc_func_t *putc, void *arg)
742ca987d46SWarner Losh {
743ca987d46SWarner Losh 	const char *p;
744ca987d46SWarner Losh 	int ret;
745ca987d46SWarner Losh 
746ca987d46SWarner Losh 	ret = 0;
747ca987d46SWarner Losh 	for (p = s; *p != '\0'; p++)
748ca987d46SWarner Losh 		ret += putc(*p, arg);
749ca987d46SWarner Losh 	return (ret);
750ca987d46SWarner Losh }
751ca987d46SWarner Losh 
752ca987d46SWarner Losh static char *
753ca987d46SWarner Losh __uitoa(char *buf, u_int ui, int base)
754ca987d46SWarner Losh {
755ca987d46SWarner Losh 	char *p;
756ca987d46SWarner Losh 
757ca987d46SWarner Losh 	p = buf;
758ca987d46SWarner Losh 	*p = '\0';
759ca987d46SWarner Losh 	do
760ca987d46SWarner Losh 		*--p = digits[ui % base];
761ca987d46SWarner Losh 	while ((ui /= base) != 0);
762ca987d46SWarner Losh 	return (p);
763ca987d46SWarner Losh }
764ca987d46SWarner Losh 
765ca987d46SWarner Losh static char *
766ca987d46SWarner Losh __ultoa(char *buf, u_long ul, int base)
767ca987d46SWarner Losh {
768ca987d46SWarner Losh 	char *p;
769ca987d46SWarner Losh 
770ca987d46SWarner Losh 	p = buf;
771ca987d46SWarner Losh 	*p = '\0';
772ca987d46SWarner Losh 	do
773ca987d46SWarner Losh 		*--p = digits[ul % base];
774ca987d46SWarner Losh 	while ((ul /= base) != 0);
775ca987d46SWarner Losh 	return (p);
776ca987d46SWarner Losh }
777