boot1.c revision 133862
111126Sjulian/*
2103722Sphk * Copyright (c) 1998 Robert Nordier
311126Sjulian * All rights reserved.
411126Sjulian * Copyright (c) 2001 Robert Drehmel
511126Sjulian * All rights reserved.
611126Sjulian *
711126Sjulian * Redistribution and use in source and binary forms are freely
811126Sjulian * permitted provided that the above copyright notice and this
911126Sjulian * paragraph and the following disclaimer are duplicated in all
1011126Sjulian * such forms.
1111126Sjulian *
1211126Sjulian * This software is provided "AS IS" and without any express or
1311126Sjulian * implied warranties, including, without limitation, the implied
14103722Sphk * warranties of merchantability and fitness for a particular
15103722Sphk * purpose.
1611126Sjulian */
17103722Sphk
1811126Sjulian#include <sys/cdefs.h>
1911126Sjulian__FBSDID("$FreeBSD: head/sys/boot/sparc64/boot1/boot1.c 133862 2004-08-16 15:45:27Z marius $");
2011126Sjulian
2111126Sjulian#include <sys/param.h>
2211126Sjulian#include <sys/dirent.h>
2311126Sjulian#include <machine/elf.h>
2411126Sjulian#include <machine/stdarg.h>
2511126Sjulian
2611126Sjulian#define _PATH_LOADER	"/boot/loader"
27116182Sobrien#define _PATH_KERNEL	"/boot/kernel/kernel"
28116182Sobrien
29116182Sobrien#define BSIZEMAX	16384
3011126Sjulian
3148936Sphktypedef int putc_func_t(int c, void *arg);
3283366Sjuliantypedef int32_t ofwh_t;
33111179Sphk
3490737Sgreenstruct sp_data {
3590737Sgreen	char	*sp_buf;
3636735Sdfr	u_int	sp_len;
3748936Sphk	u_int	sp_size;
3811126Sjulian};
3912954Sjulian
4048936Sphkstatic const char digits[] = "0123456789abcdef";
41120514Sphk
42171181Skibstatic char bootpath[128];
4365374Sphkstatic char bootargs[128];
44126078Sphk
45147982Srwatsonstatic ofwh_t bootdev;
46171181Skib
4749535Sphkstatic struct fs fs;
4811126Sjulianstatic ino_t inomap;
49149144Sphkstatic char blkbuf[BSIZEMAX];
50149144Sphkstatic unsigned int fsblks;
51131996Sphk
5248936Sphkstatic uint32_t fs_off;
53150342Sphk
54142242Sphkint main(int ac, char **av);
55171188Skib
56171188Skibstatic void exit(int) __dead2;
57171181Skibstatic void load(const char *);
58171181Skibstatic int dskread(void *, u_int64_t, int);
59171181Skib
60171181Skibstatic void usage(void);
61171181Skib
62170950Skibstatic void bcopy(const void *src, void *dst, size_t len);
63170950Skibstatic void bzero(void *b, size_t len);
64177301Skib
65177301Skibstatic int mount(const char *device);
66170950Skib
67135600Sphkstatic void panic(const char *fmt, ...) __dead2;
68135600Sphkstatic int printf(const char *fmt, ...);
69126082Sphkstatic int putchar(int c, void *arg);
70151450Sjhbstatic int vprintf(const char *fmt, va_list ap);
71126082Sphkstatic int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
72126082Sphk
73126082Sphkstatic int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
74177301Skibstatic int __putc(int c, void *arg);
75177301Skibstatic int __puts(const char *s, putc_func_t *putc, void *arg);
76177301Skibstatic int __sputc(int c, void *arg);
77177301Skibstatic char *__uitoa(char *buf, u_int val, int base);
78177301Skibstatic char *__ultoa(char *buf, u_long val, int base);
79177301Skib
80170950Skib/*
81170950Skib * Open Firmware interface functions
82170950Skib */
83177301Skibtypedef u_int64_t	ofwcell_t;
84177301Skibtypedef u_int32_t	u_ofwh_t;
85170950Skibtypedef int (*ofwfp_t)(ofwcell_t []);
86177301Skibofwfp_t ofw;			/* the prom Open Firmware entry */
87170950Skib
88170950Skibvoid ofw_init(int, int, int, int, ofwfp_t);
89177301Skibofwh_t ofw_finddevice(const char *);
90177301Skibofwh_t ofw_open(const char *);
91177301Skibint ofw_getprop(ofwh_t, const char *, void *, size_t);
92177301Skibint ofw_read(ofwh_t, void *, size_t);
93177301Skibint ofw_write(ofwh_t, const void *, size_t);
94177301Skibint ofw_seek(ofwh_t, u_int64_t);
95177301Skibvoid ofw_exit(void) __dead2;
96177301Skib
97177301Skibofwh_t bootdevh;
98177301Skibofwh_t stdinh, stdouth;
99177301Skib
100177301Skib/*
101177301Skib * This has to stay here, as the PROM seems to ignore the
102177301Skib * entry point specified in the a.out header.  (or elftoaout is broken)
103170950Skib */
104170950Skib
105177301Skibvoid
106177301Skibofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr)
107177301Skib{
108177301Skib	ofwh_t chosenh;
109170950Skib	char *av[16];
110170950Skib	char *p;
111170950Skib	int ac;
112170950Skib
113170950Skib	ofw = ofwaddr;
114170950Skib
115170950Skib	chosenh = ofw_finddevice("/chosen");
116170950Skib	ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh));
117170950Skib	ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth));
118170950Skib	ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs));
119170950Skib	ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
120170950Skib
121177301Skib	bootargs[sizeof(bootargs) - 1] = '\0';
122177301Skib	bootpath[sizeof(bootpath) - 1] = '\0';
123177301Skib
124177301Skib	ac = 0;
125177301Skib	p = bootargs;
126177301Skib	for (;;) {
127177301Skib		while (*p == ' ' && *p != '\0')
128177301Skib			p++;
129135600Sphk		if (*p == '\0' || ac >= 16)
130135600Sphk			break;
131126082Sphk		av[ac++] = p;
132135704Sphk		while (*p != ' ' && *p != '\0')
133126082Sphk			p++;
134126082Sphk		if (*p != '\0')
135126082Sphk			*p++ = '\0';
136126082Sphk	}
137144385Sphk
138144385Sphk	exit(main(ac, av));
139144385Sphk}
140144385Sphk
141144385Sphkofwh_t
142144385Sphkofw_finddevice(const char *name)
143144385Sphk{
144144385Sphk	ofwcell_t args[] = {
145144385Sphk		(ofwcell_t)"finddevice",
146144385Sphk		1,
147144384Sphk		1,
148126082Sphk		(ofwcell_t)name,
149135704Sphk		0
150142232Sphk	};
151126082Sphk
152126082Sphk	if ((*ofw)(args)) {
153126082Sphk		printf("ofw_finddevice: name=\"%s\"\n", name);
154126082Sphk		return (1);
155142242Sphk	}
156126082Sphk	return (args[4]);
157142242Sphk}
158135600Sphk
159136014Sphkint
160136014Sphkofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
161126082Sphk{
162126082Sphk	ofwcell_t args[] = {
163126082Sphk		(ofwcell_t)"getprop",
164150342Sphk		4,
165142242Sphk		1,
166142242Sphk		(u_ofwh_t)ofwh,
167150342Sphk		(ofwcell_t)name,
168150342Sphk		(ofwcell_t)buf,
169150342Sphk		len,
170154029Sbz	0
171126082Sphk	};
172136014Sphk
173136014Sphk	if ((*ofw)(args)) {
174136014Sphk		printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n",
175136014Sphk			ofwh, buf, len);
176150342Sphk		return (1);
177126082Sphk	}
178136014Sphk	return (0);
179135704Sphk}
180135704Sphk
181135704Sphkofwh_t
182135704Sphkofw_open(const char *path)
183171181Skib{
184126082Sphk	ofwcell_t args[] = {
185135704Sphk		(ofwcell_t)"open",
186135704Sphk		1,
187135704Sphk		1,
188171181Skib		(ofwcell_t)path,
189171181Skib		0
190171181Skib	};
191171181Skib
192171181Skib	if ((*ofw)(args)) {
193171181Skib		printf("ofw_open: path=\"%s\"\n", path);
194171181Skib		return (-1);
195135704Sphk	}
196135704Sphk	return (args[4]);
197135704Sphk}
198135704Sphk
199163529Skibint
200163529Skibofw_close(ofwh_t devh)
201163529Skib{
202163529Skib	ofwcell_t args[] = {
203171181Skib		(ofwcell_t)"close",
204163529Skib		1,
205163529Skib		0,
206163529Skib		(u_ofwh_t)devh
207163529Skib	};
208163529Skib
209163529Skib	if ((*ofw)(args)) {
210171181Skib		printf("ofw_close: devh=0x%x\n", devh);
211171181Skib		return (1);
212171181Skib	}
213171181Skib	return (0);
214171181Skib}
215171181Skib
216163529Skibint
217163529Skibofw_read(ofwh_t devh, void *buf, size_t len)
218163529Skib{
219163529Skib	ofwcell_t args[] = {
220163529Skib		(ofwcell_t)"read",
221135704Sphk		4,
222135704Sphk		1,
223135704Sphk		(u_ofwh_t)devh,
224135704Sphk		(ofwcell_t)buf,
225135704Sphk		len,
226135704Sphk		0
227135704Sphk	};
228135704Sphk
229135704Sphk	if ((*ofw)(args)) {
230135704Sphk		printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len);
231120514Sphk		return (1);
232120514Sphk	}
233120514Sphk	return (0);
23485603Sphk}
235120514Sphk
236120514Sphkint
237120514Sphkofw_write(ofwh_t devh, const void *buf, size_t len)
238120514Sphk{
239120514Sphk	ofwcell_t args[] = {
240120514Sphk		(ofwcell_t)"write",
241120514Sphk		3,
242120514Sphk		1,
243120514Sphk		(u_ofwh_t)devh,
244120514Sphk		(ofwcell_t)buf,
245111179Sphk		len,
246111179Sphk		0
247111179Sphk	};
248111179Sphk
249111179Sphk	if ((*ofw)(args)) {
250111179Sphk		printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len);
251120514Sphk		return (1);
252120514Sphk	}
253120514Sphk	return (0);
254120514Sphk}
255120514Sphk
256120514Sphkint
257120514Sphkofw_seek(ofwh_t devh, u_int64_t off)
258120514Sphk{
259111179Sphk	ofwcell_t args[] = {
260111179Sphk		(ofwcell_t)"seek",
261111179Sphk		4,
262111179Sphk		1,
263111179Sphk		(u_ofwh_t)devh,
264120514Sphk		off >> 32,
265120514Sphk		off,
266111179Sphk		0
267111179Sphk	};
268111179Sphk
269111179Sphk	if ((*ofw)(args)) {
270111179Sphk		printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off);
271111179Sphk		return (1);
272111179Sphk	}
273111179Sphk	return (0);
274111220Sphk}
275111179Sphk
276111179Sphkvoid
277111179Sphkofw_exit(void)
278126080Sphk{
279126080Sphk	ofwcell_t args[3];
280111815Sphk
281111815Sphk	args[0] = (ofwcell_t)"exit";
282111815Sphk	args[1] = 0;
283111815Sphk	args[2] = 0;
284111815Sphk
285111815Sphk	for (;;)
286111815Sphk		(*ofw)(args);
287111815Sphk}
288111815Sphk
289111815Sphkstatic void
290111815Sphkbcopy(const void *src, void *dst, size_t len)
291111179Sphk{
292111179Sphk	const char *s = src;
293120514Sphk	char *d = dst;
294111179Sphk
295120514Sphk	while (len-- != 0)
296120514Sphk		*d++ = *s++;
297120514Sphk}
298120514Sphk
299120514Sphkstatic void
300120514Sphkmemcpy(void *dst, const void *src, size_t len)
301133741Sjmg{
302120514Sphk	bcopy(src, dst, len);
303120514Sphk}
304120514Sphk
305120514Sphkstatic void
306120514Sphkbzero(void *b, size_t len)
307120514Sphk{
308120514Sphk	char *p = b;
309120514Sphk
310120514Sphk	while (len-- != 0)
311130585Sphk		*p++ = 0;
312120514Sphk}
313120514Sphk
314120514Sphkstatic int
315120514Sphkstrcmp(const char *s1, const char *s2)
316120514Sphk{
317120514Sphk	for (; *s1 == *s2 && *s1; s1++, s2++)
318120514Sphk		;
319120514Sphk	return ((u_char)*s1 - (u_char)*s2);
320120514Sphk}
321120514Sphk
322120514Sphk#include "ufsread.c"
323120514Sphk
324120514Sphkint
325120514Sphkmain(int ac, char **av)
326120514Sphk{
327120514Sphk	const char *path;
328120514Sphk	int i;
329149177Sphk
330149177Sphk	path = _PATH_LOADER;
331149177Sphk	for (i = 0; i < ac; i++) {
332177301Skib		switch (av[i][0]) {
333149177Sphk		case '-':
334149177Sphk			switch (av[i][1]) {
335177301Skib			default:
336177301Skib				usage();
337177301Skib			}
338149177Sphk			break;
339177301Skib		default:
340149177Sphk			path = av[i];
341177301Skib			break;
342149177Sphk		}
343149177Sphk	}
344149177Sphk
345149177Sphk	printf(" \n>> FreeBSD/sparc64 boot block\n"
346170152Skib	"   Boot path:   %s\n"
347149177Sphk	"   Boot loader: %s\n", bootpath, path);
348177301Skib
349149177Sphk	if (mount(bootpath) == -1)
350149177Sphk		panic("mount");
351177301Skib
352177301Skib	load(path);
353177301Skib	return (1);
354149177Sphk}
355177301Skib
356149177Sphkstatic void
357177301Skibusage(void)
358149177Sphk{
359149177Sphk
360149177Sphk	printf("usage: boot device [/path/to/loader]\n");
361149177Sphk	exit(1);
362149177Sphk}
363149177Sphk
364177301Skibstatic void
365149177Sphkexit(int code)
366149177Sphk{
367177301Skib
368177301Skib	ofw_exit();
369177301Skib}
370149177Sphk
371177301Skibstatic struct dmadat __dmadat;
372149177Sphk
373177301Skibstatic int
374149177Sphkmount(const char *device)
375149177Sphk{
376149177Sphk
377149177Sphk	dmadat = &__dmadat;
378149177Sphk	if ((bootdev = ofw_open(device)) == -1) {
379149177Sphk		printf("mount: can't open device\n");
380177301Skib		return (-1);
381177301Skib	}
382149177Sphk	if (fsread(0, NULL, 0)) {
383177301Skib		printf("mount: can't read superblock\n");
384177301Skib		return (-1);
385177301Skib	}
386177301Skib	return (0);
387177301Skib}
388177301Skib
389149177Sphkstatic void
390177301Skibload(const char *fname)
391149177Sphk{
392177301Skib	Elf64_Ehdr eh;
393149177Sphk	Elf64_Phdr ph;
394149177Sphk	caddr_t p;
395149177Sphk	ino_t ino;
396149177Sphk	int i;
397149177Sphk
398177301Skib	if ((ino = lookup(fname)) == 0) {
399149177Sphk		printf("File %s not found\n", fname);
400149177Sphk		return;
401177301Skib	}
402177301Skib	if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) {
403177301Skib		printf("Can't read elf header\n");
404149177Sphk		return;
405177858Skib	}
406149177Sphk	if (!IS_ELF(eh)) {
407177301Skib		printf("Not an ELF file\n");
408149177Sphk		return;
409149177Sphk	}
410149177Sphk	for (i = 0; i < eh.e_phnum; i++) {
411149177Sphk		fs_off = eh.e_phoff + i * eh.e_phentsize;
412149177Sphk		if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) {
413149177Sphk			printf("Can't read program header %d\n", i);
414177301Skib			return;
415149177Sphk		}
416149177Sphk		if (ph.p_type != PT_LOAD)
417177301Skib			continue;
418177301Skib		fs_off = ph.p_offset;
419177301Skib		p = (caddr_t)ph.p_vaddr;
420149177Sphk		if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) {
421177858Skib			printf("Can't read content of section %d\n", i);
422149177Sphk			return;
423177301Skib		}
424149177Sphk		if (ph.p_filesz != ph.p_memsz)
425149177Sphk			bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
426149177Sphk	}
427149177Sphk	ofw_close(bootdev);
428149177Sphk	(*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
429149177Sphk}
430177301Skib
431149177Sphkstatic int
432149177Sphkdskread(void *buf, u_int64_t lba, int nblk)
433177301Skib{
434177301Skib	/*
435177301Skib	 * The Open Firmware should open the correct partition for us.
436149177Sphk	 * That means, if we read from offset zero on an open instance handle,
437177301Skib	 * we should read from offset zero of that partition.
438149177Sphk	 */
439177301Skib	ofw_seek(bootdev, lba * DEV_BSIZE);
440149177Sphk	ofw_read(bootdev, buf, nblk * DEV_BSIZE);
441149177Sphk	return (0);
442149177Sphk}
443149177Sphk
444149177Sphkstatic void
445149177Sphkpanic(const char *fmt, ...)
446177301Skib{
447149177Sphk	char buf[128];
448149177Sphk	va_list ap;
449177301Skib
450177301Skib	va_start(ap, fmt);
451177301Skib	vsnprintf(buf, sizeof buf, fmt, ap);
452149177Sphk	printf("panic: %s\n", buf);
453177301Skib	va_end(ap);
454149177Sphk
455177301Skib	exit(1);
456149177Sphk}
457149177Sphk
458149177Sphkstatic int
459149177Sphkprintf(const char *fmt, ...)
460149177Sphk{
461149177Sphk	va_list ap;
462177301Skib	int ret;
463149177Sphk
464149177Sphk	va_start(ap, fmt);
465177301Skib	ret = vprintf(fmt, ap);
466177301Skib	va_end(ap);
467177301Skib	return (ret);
468149177Sphk}
469177301Skib
470149177Sphkstatic int
471177301Skibputchar(int c, void *arg)
472149177Sphk{
473149177Sphk	char buf;
474149177Sphk
475149177Sphk	if (c == '\n') {
476149177Sphk		buf = '\r';
477149177Sphk		ofw_write(stdouth, &buf, 1);
478177301Skib	}
479149177Sphk	buf = c;
480149177Sphk	ofw_write(stdouth, &buf, 1);
481177301Skib	return (1);
482177301Skib}
483177301Skib
484149177Sphkstatic int
485177301Skibvprintf(const char *fmt, va_list ap)
486149177Sphk{
487177301Skib	int ret;
488149177Sphk
489149177Sphk	ret = __printf(fmt, putchar, 0, ap);
490149177Sphk	return (ret);
491149177Sphk}
49247640Sphk
493130936Slestatic int
49447028Sphkvsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
49547028Sphk{
49647028Sphk	struct sp_data sp;
497130585Sphk	int ret;
49847028Sphk
499130640Sphk	sp.sp_buf = str;
500130640Sphk	sp.sp_len = 0;
501143631Sphk	sp.sp_size = sz;
50247028Sphk	ret = __printf(fmt, __sputc, &sp, ap);
50347028Sphk	return (ret);
50449826Sphk}
505130585Sphk
50649826Sphkstatic int
50749826Sphk__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
508130640Sphk{
509130640Sphk	char buf[(sizeof(long) * 8) + 1];
510140964Sphk	char *nbuf;
51149826Sphk	u_long ul;
51249826Sphk	u_int ui;
513143282Sphk	int lflag;
514143282Sphk	int sflag;
515140963Sphk	char *s;
516140963Sphk	int pad;
517140969Sphk	int ret;
518143282Sphk	int c;
519140963Sphk
520140963Sphk	nbuf = &buf[sizeof buf - 1];
521140963Sphk	ret = 0;
52266067Sphk	while ((c = *fmt++) != 0) {
52366067Sphk		if (c != '%') {
52466067Sphk			ret += putc(c, arg);
52574522Sphk			continue;
52666067Sphk		}
52766067Sphk		lflag = 0;
52866067Sphk		sflag = 0;
529130585Sphk		pad = 0;
530144281Sphkreswitch:	c = *fmt++;
53147028Sphk		switch (c) {
532140733Sphk		case '#':
533130640Sphk			sflag = 1;
53448936Sphk			goto reswitch;
535140733Sphk		case '%':
536144292Sphk			ret += putc('%', arg);
537144281Sphk			break;
538143631Sphk		case 'c':
539170950Skib			c = va_arg(ap, int);
540140733Sphk			ret += putc(c, arg);
541140733Sphk			break;
54248936Sphk		case 'd':
543143631Sphk			if (lflag == 0) {
544150342Sphk				ui = (u_int)va_arg(ap, int);
545144281Sphk				if (ui < (int)ui) {
546125850Sbde					ui = -ui;
54747028Sphk					ret += putc('-', arg);
54847028Sphk				}
54947028Sphk				s = __uitoa(nbuf, ui, 10);
550130640Sphk			} else {
55147028Sphk				ul = (u_long)va_arg(ap, long);
552140969Sphk				if (ul < (long)ul) {
55347028Sphk					ul = -ul;
55447028Sphk					ret += putc('-', arg);
55547028Sphk				}
556130640Sphk				s = __ultoa(nbuf, ul, 10);
55747028Sphk			}
558140969Sphk			ret += __puts(s, putc, arg);
55947028Sphk			break;
56047028Sphk		case 'l':
561125846Sphk			lflag = 1;
562144292Sphk			goto reswitch;
56349535Sphk		case 'o':
564149324Sphk			if (lflag == 0) {
56549535Sphk				ui = (u_int)va_arg(ap, u_int);
566149324Sphk				s = __uitoa(nbuf, ui, 8);
567149324Sphk			} else {
568149324Sphk				ul = (u_long)va_arg(ap, u_long);
569177301Skib				s = __ultoa(nbuf, ul, 8);
570149324Sphk			}
571149324Sphk			ret += __puts(s, putc, arg);
572126156Sphk			break;
573126082Sphk		case 'p':
574126082Sphk			ul = (u_long)va_arg(ap, void *);
575126082Sphk			s = __ultoa(nbuf, ul, 16);
576126077Sphk			ret += __puts("0x", putc, arg);
577126077Sphk			ret += __puts(s, putc, arg);
578149177Sphk			break;
579126077Sphk		case 's':
580177301Skib			s = va_arg(ap, char *);
581177301Skib			ret += __puts(s, putc, arg);
582177301Skib			break;
583177301Skib		case 'u':
584177301Skib			if (lflag == 0) {
585149177Sphk				ui = va_arg(ap, u_int);
586177301Skib				s = __uitoa(nbuf, ui, 10);
587177301Skib			} else {
588149177Sphk				ul = va_arg(ap, u_long);
589177301Skib				s = __ultoa(nbuf, ul, 10);
590177301Skib			}
591177301Skib			ret += __puts(s, putc, arg);
592177301Skib			break;
593177301Skib		case 'x':
594126082Sphk			if (lflag == 0) {
595143746Sphk				ui = va_arg(ap, u_int);
596126082Sphk				s = __uitoa(nbuf, ui, 16);
597126082Sphk			} else {
598154266Salfred				ul = va_arg(ap, u_long);
599154266Salfred				s = __ultoa(nbuf, ul, 16);
600126082Sphk			}
601126082Sphk			if (sflag)
602126082Sphk				ret += __puts("0x", putc, arg);
603126082Sphk			ret += __puts(s, putc, arg);
604126082Sphk			break;
605126082Sphk		case '0': case '1': case '2': case '3': case '4':
606126082Sphk		case '5': case '6': case '7': case '8': case '9':
607126082Sphk			pad = pad * 10 + c - '0';
608126082Sphk			goto reswitch;
609126082Sphk		default:
610126082Sphk			break;
611126082Sphk		}
612126078Sphk	}
613129943Sphk	return (ret);
614126078Sphk}
615126078Sphk
616126078Sphkstatic int
617126078Sphk__sputc(int c, void *arg)
618126078Sphk{
619126078Sphk	struct sp_data *sp;
620149177Sphk
621149177Sphk	sp = arg;
622149177Sphk	if (sp->sp_len < sp->sp_size)
623149177Sphk		sp->sp_buf[sp->sp_len++] = c;
624177301Skib	sp->sp_buf[sp->sp_len] = '\0';
625177301Skib	return (1);
626149177Sphk}
627149177Sphk
628149177Sphkstatic int
629149177Sphk__puts(const char *s, putc_func_t *putc, void *arg)
630149177Sphk{
631149177Sphk	const char *p;
632149177Sphk	int ret;
633149177Sphk
634149177Sphk	ret = 0;
635149177Sphk	for (p = s; *p != '\0'; p++)
636149177Sphk		ret += putc(*p, arg);
637149177Sphk	return (ret);
638149177Sphk}
639149177Sphk
640149177Sphkstatic char *
641149177Sphk__uitoa(char *buf, u_int ui, int base)
642149177Sphk{
643149177Sphk	char *p;
644149177Sphk
645149177Sphk	p = buf;
646149177Sphk	*p = '\0';
647149177Sphk	do
648120514Sphk		*--p = digits[ui % base];
649126082Sphk	while ((ui /= base) != 0);
650126082Sphk	return (p);
651126082Sphk}
652126082Sphk
653126082Sphkstatic char *
654177301Skib__ultoa(char *buf, u_long ul, int base)
655177301Skib{
656125846Sphk	char *p;
657111622Sphk
658171181Skib	p = buf;
659171181Skib	*p = '\0';
660171181Skib	do
661147982Srwatson		*--p = digits[ul % base];
662125846Sphk	while ((ul /= base) != 0);
663130585Sphk	return (p);
664125846Sphk}
665125846Sphk