boot1.c revision 97864
190699Srobert/*
290699Srobert * Copyright (c) 1998 Robert Nordier
390699Srobert * All rights reserved.
490699Srobert * Copyright (c) 2001 Robert Drehmel
590699Srobert * All rights reserved.
690699Srobert *
790699Srobert * Redistribution and use in source and binary forms are freely
890699Srobert * permitted provided that the above copyright notice and this
990699Srobert * paragraph and the following disclaimer are duplicated in all
1090699Srobert * such forms.
1190699Srobert *
1290699Srobert * This software is provided "AS IS" and without any express or
1390699Srobert * implied warranties, including, without limitation, the implied
1490699Srobert * warranties of merchantability and fitness for a particular
1590699Srobert * purpose.
1690699Srobert *
1790699Srobert */
1891295Srobert
1991295Srobert#include <sys/cdefs.h>
2091295Srobert__FBSDID("$FreeBSD: head/sys/boot/sparc64/boot1/boot1.c 97864 2002-06-05 12:00:53Z phk $");
2191295Srobert
2290699Srobert#include <sys/param.h>
2390699Srobert#include <sys/reboot.h>
2490699Srobert#include <sys/diskslice.h>
2590699Srobert#include <sys/disklabel.h>
2690699Srobert#include <sys/dirent.h>
2790699Srobert#include <machine/elf.h>
2890699Srobert#include <machine/stdarg.h>
2990699Srobert
3090699Srobert#include <ufs/ffs/fs.h>
3190699Srobert#include <ufs/ufs/dinode.h>
3290699Srobert
3395337Sjake#define _PATH_LOADER	"/boot/loader"
3495337Sjake#define _PATH_KERNEL	"/boot/kernel/kernel"
3590699Srobert
3696497Sobrien#define BSIZEMAX	16384
3790699Srobert
3895351Sjaketypedef int putc_func_t(int c, void *arg);
3995351Sjaketypedef int32_t ofwh_t;
4095351Sjake
4195351Sjakestruct sp_data {
4295351Sjake	char	*sp_buf;
4395351Sjake	u_int	sp_len;
4495351Sjake	u_int	sp_size;
4590699Srobert};
4690699Srobert
4795346Sjakestatic const char digits[] = "0123456789abcdef";
4890699Srobert
4995346Sjakestatic char bootpath[128];
5095346Sjakestatic char bootargs[128];
5195346Sjake
5295351Sjakestatic ofwh_t bootdev;
5395346Sjake
5495351Sjakestatic struct fs fs;
5595351Sjakestatic ino_t inomap;
5695351Sjakestatic char blkbuf[BSIZEMAX];
5795351Sjakestatic unsigned int fsblks;
5895351Sjake
5990699Srobertstatic uint32_t fs_off;
6090699Srobert
6195346Sjakeint main(int ac, char **av);
6295346Sjake
6395351Sjakestatic void exit(int) __dead2;
6490699Srobertstatic void load(const char *);
6590699Srobertstatic int dskread(void *, u_int64_t, int);
6690699Srobert
6795351Sjakestatic void usage(void);
6895351Sjake
6995340Sjakestatic void bcopy(const void *src, void *dst, size_t len);
7095340Sjakestatic void bzero(void *b, size_t len);
7190699Srobert
7295351Sjakestatic int mount(const char *device);
7395351Sjake
7495351Sjakestatic void panic(const char *fmt, ...) __dead2;
7595346Sjakestatic int printf(const char *fmt, ...);
7695351Sjakestatic int putchar(int c, void *arg);
7795346Sjakestatic int vprintf(const char *fmt, va_list ap);
7895351Sjakestatic int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
7995346Sjake
8095346Sjakestatic int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
8195346Sjakestatic int __putc(int c, void *arg);
8295346Sjakestatic int __puts(const char *s, putc_func_t *putc, void *arg);
8395351Sjakestatic int __sputc(int c, void *arg);
8495346Sjakestatic char *__uitoa(char *buf, u_int val, int base);
8595346Sjakestatic char *__ultoa(char *buf, u_long val, int base);
8695346Sjake
8790699Srobert/*
8890699Srobert * Open Firmware interface functions
8990699Srobert */
9090699Sroberttypedef u_int64_t	ofwcell_t;
9190699Sroberttypedef u_int32_t	u_ofwh_t;
9290699Sroberttypedef int (*ofwfp_t)(ofwcell_t []);
9390699Srobertofwfp_t ofw;			/* the prom Open Firmware entry */
9490699Srobert
9590699Srobertvoid ofw_init(int, int, int, int, ofwfp_t);
9690699Srobertofwh_t ofw_finddevice(const char *);
9790699Srobertofwh_t ofw_open(const char *);
9890699Srobertint ofw_getprop(ofwh_t, const char *, void *, size_t);
9990699Srobertint ofw_read(ofwh_t, void *, size_t);
10090699Srobertint ofw_write(ofwh_t, const void *, size_t);
10190699Srobertint ofw_seek(ofwh_t, u_int64_t);
10295351Sjakevoid ofw_exit(void) __dead2;
10390699Srobert
10490699Srobertofwh_t bootdevh;
10590699Srobertofwh_t stdinh, stdouth;
10690699Srobert
10790699Srobert/*
10890699Srobert * This has to stay here, as the PROM seems to ignore the
10990699Srobert * entry point specified in the a.out header.  (or elftoaout is broken)
11090699Srobert */
11190699Srobert
11290699Srobertvoid
11390699Srobertofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr)
11490699Srobert{
11590699Srobert	ofwh_t chosenh;
11695346Sjake	char *av[16];
11795346Sjake	char *p;
11895346Sjake	int ac;
11990699Srobert
12090699Srobert	ofw = ofwaddr;
12190699Srobert
12290699Srobert	chosenh = ofw_finddevice("/chosen");
12390699Srobert	ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh));
12490699Srobert	ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth));
12595346Sjake	ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs));
12690699Srobert	ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
12790699Srobert
12895346Sjake	bootargs[sizeof(bootargs) - 1] = '\0';
12995346Sjake	bootpath[sizeof(bootpath) - 1] = '\0';
13095346Sjake
13195346Sjake	ac = 0;
13295346Sjake	p = bootargs;
13395346Sjake	for (;;) {
13495346Sjake		while (*p == ' ' && *p != '\0')
13595346Sjake			p++;
13695346Sjake		if (*p == '\0' || ac >= 16)
13795346Sjake			break;
13895346Sjake		av[ac++] = p;
13995346Sjake		while (*p != ' ' && *p != '\0')
14095346Sjake			p++;
14195346Sjake		if (*p != '\0')
14295346Sjake			*p++ = '\0';
14395346Sjake	}
14495346Sjake
14595346Sjake	exit(main(ac, av));
14690699Srobert}
14790699Srobert
14890699Srobertofwh_t
14990699Srobertofw_finddevice(const char *name)
15090699Srobert{
15191295Srobert	ofwcell_t args[] = {
15291295Srobert		(ofwcell_t)"finddevice",
15391295Srobert		1,
15491295Srobert		1,
15591295Srobert		(ofwcell_t)name,
15691295Srobert		0
15791295Srobert	};
15891295Srobert
15991295Srobert	if ((*ofw)(args)) {
16091295Srobert		printf("ofw_finddevice: name=\"%s\"\n", name);
16191295Srobert		return (1);
16291295Srobert	}
16391295Srobert	return (args[4]);
16490699Srobert}
16590699Srobert
16690699Srobertint
16790699Srobertofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
16890699Srobert{
16991295Srobert	ofwcell_t args[] = {
17091295Srobert		(ofwcell_t)"getprop",
17191295Srobert		4,
17291295Srobert		1,
17391295Srobert		(u_ofwh_t)ofwh,
17491295Srobert		(ofwcell_t)name,
17591295Srobert		(ofwcell_t)buf,
17691295Srobert		len,
17790699Srobert	0
17891295Srobert	};
17991295Srobert
18091295Srobert	if ((*ofw)(args)) {
18191295Srobert		printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n",
18291295Srobert			ofwh, buf, len);
18391295Srobert		return (1);
18491295Srobert	}
18591295Srobert	return (0);
18690699Srobert}
18790699Srobert
18890699Srobertofwh_t
18990699Srobertofw_open(const char *path)
19090699Srobert{
19191295Srobert	ofwcell_t args[] = {
19291295Srobert		(ofwcell_t)"open",
19391295Srobert		1,
19491295Srobert		1,
19591295Srobert		(ofwcell_t)path,
19691295Srobert		0
19791295Srobert	};
19891295Srobert
19991295Srobert	if ((*ofw)(args)) {
20091295Srobert		printf("ofw_open: path=\"%s\"\n", path);
20191295Srobert		return (-1);
20291295Srobert	}
20391295Srobert	return (args[4]);
20490699Srobert}
20590699Srobert
20690699Srobertint
20790699Srobertofw_close(ofwh_t devh)
20890699Srobert{
20991295Srobert	ofwcell_t args[] = {
21091295Srobert		(ofwcell_t)"close",
21191295Srobert		1,
21291295Srobert		0,
21391295Srobert		(u_ofwh_t)devh
21491295Srobert	};
21591295Srobert
21691295Srobert	if ((*ofw)(args)) {
21791295Srobert		printf("ofw_close: devh=0x%x\n", devh);
21891295Srobert		return (1);
21991295Srobert	}
22091295Srobert	return (0);
22190699Srobert}
22290699Srobert
22390699Srobertint
22490699Srobertofw_read(ofwh_t devh, void *buf, size_t len)
22590699Srobert{
22691295Srobert	ofwcell_t args[] = {
22791295Srobert		(ofwcell_t)"read",
22891295Srobert		4,
22991295Srobert		1,
23091295Srobert		(u_ofwh_t)devh,
23191295Srobert		(ofwcell_t)buf,
23291295Srobert		len,
23391295Srobert		0
23491295Srobert	};
23591295Srobert
23691295Srobert	if ((*ofw)(args)) {
23791295Srobert		printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len);
23891295Srobert		return (1);
23991295Srobert	}
24091295Srobert	return (0);
24190699Srobert}
24290699Srobert
24390699Srobertint
24490699Srobertofw_write(ofwh_t devh, const void *buf, size_t len)
24590699Srobert{
24691295Srobert	ofwcell_t args[] = {
24791295Srobert		(ofwcell_t)"write",
24891295Srobert		3,
24991295Srobert		1,
25091295Srobert		(u_ofwh_t)devh,
25191295Srobert		(ofwcell_t)buf,
25291295Srobert		len,
25391295Srobert		0
25491295Srobert	};
25591295Srobert
25691295Srobert	if ((*ofw)(args)) {
25791295Srobert		printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len);
25891295Srobert		return (1);
25991295Srobert	}
26091295Srobert	return (0);
26190699Srobert}
26290699Srobert
26390699Srobertint
26490699Srobertofw_seek(ofwh_t devh, u_int64_t off)
26590699Srobert{
26691295Srobert	ofwcell_t args[] = {
26791295Srobert		(ofwcell_t)"seek",
26891295Srobert		4,
26991295Srobert		1,
27091295Srobert		(u_ofwh_t)devh,
27191295Srobert		off >> 32,
27291678Srobert		off,
27391295Srobert		0
27491295Srobert	};
27591295Srobert
27691295Srobert	if ((*ofw)(args)) {
27791295Srobert		printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off);
27891295Srobert		return (1);
27991295Srobert	}
28091295Srobert	return (0);
28190699Srobert}
28290699Srobert
28395342Sjakevoid
28495342Sjakeofw_exit(void)
28595342Sjake{
28695342Sjake	ofwcell_t args[3];
28795342Sjake
28895342Sjake	args[0] = (ofwcell_t)"exit";
28995342Sjake	args[1] = 0;
29095342Sjake	args[2] = 0;
29195342Sjake
29295351Sjake	for (;;)
29395351Sjake		(*ofw)(args);
29495342Sjake}
29595342Sjake
29695340Sjakestatic void
29797863Sphkbcopy(const void *src, void *dst, size_t len)
29895340Sjake{
29997863Sphk	const char *s = src;
30097863Sphk	char *d = dst;
30195340Sjake
30295340Sjake	while (len-- != 0)
30397863Sphk		*d++ = *s++;
30495340Sjake}
30595340Sjake
30695340Sjakestatic void
30797864Sphkmemcpy(void *dst, const void *src, size_t len)
30897864Sphk{
30997864Sphk	bcopy(src, dst, len);
31097864Sphk}
31197864Sphk
31297864Sphkstatic void
31395340Sjakebzero(void *b, size_t len)
31495340Sjake{
31595340Sjake	char *p = b;
31695340Sjake
31795340Sjake	while (len-- != 0)
31895340Sjake		*p++ = 0;
31995340Sjake}
32095340Sjake
32190699Srobertstatic int
32290699Srobertstrcmp(const char *s1, const char *s2)
32390699Srobert{
32491295Srobert	for (; *s1 == *s2 && *s1; s1++, s2++)
32591295Srobert		;
32691295Srobert	return ((u_char)*s1 - (u_char)*s2);
32790699Srobert}
32890699Srobert
32997864Sphk#include "ufsread.c"
33090699Srobert
33195346Sjakeint
33295346Sjakemain(int ac, char **av)
33390699Srobert{
33495346Sjake	const char *path;
33595346Sjake	int i;
33691295Srobert
33795346Sjake	path = _PATH_LOADER;
33895346Sjake	for (i = 0; i < ac; i++) {
33995346Sjake		switch (av[i][0]) {
34095346Sjake		case '-':
34195346Sjake			switch (av[i][1]) {
34295346Sjake			default:
34395351Sjake				usage();
34495346Sjake			}
34595346Sjake			break;
34695346Sjake		default:
34795346Sjake			path = av[i];
34895346Sjake			break;
34995346Sjake		}
35095346Sjake	}
35190699Srobert
35291295Srobert	printf(" \n>> FreeBSD/sparc64 boot block\n"
35390699Srobert	"   Boot path:   %s\n"
35495346Sjake	"   Boot loader: %s\n", bootpath, path);
35595351Sjake
35695351Sjake	if (mount(bootpath) == -1)
35795351Sjake		panic("mount");
35895351Sjake
35995346Sjake	load(path);
36091295Srobert	return (1);
36190699Srobert}
36290699Srobert
36390699Srobertstatic void
36495351Sjakeusage(void)
36595351Sjake{
36695351Sjake
36795351Sjake	printf("usage: boot device [/path/to/loader]\n");
36895351Sjake	exit(1);
36995351Sjake}
37095351Sjake
37195351Sjakestatic void
37295342Sjakeexit(int code)
37395342Sjake{
37495342Sjake
37595342Sjake	ofw_exit();
37695342Sjake}
37795342Sjake
37897864Sphkstatic struct dmadat __dmadat;
37997864Sphk
38095351Sjakestatic int
38195351Sjakemount(const char *device)
38295351Sjake{
38395351Sjake
38497864Sphk	dmadat = &__dmadat;
38595351Sjake	if ((bootdev = ofw_open(device)) == -1) {
38695351Sjake		printf("mount: can't open device\n");
38795351Sjake		return (-1);
38895351Sjake	}
38997864Sphk	if (fsread(0, NULL, 0)) {
39095351Sjake		printf("mount: can't read superblock\n");
39195351Sjake		return (-1);
39295351Sjake	}
39395351Sjake	return (0);
39495351Sjake}
39595351Sjake
39695342Sjakestatic void
39790699Srobertload(const char *fname)
39890699Srobert{
39991295Srobert	Elf64_Ehdr eh;
40095339Sjake	Elf64_Phdr ph;
40191295Srobert	caddr_t p;
40291295Srobert	ino_t ino;
40395339Sjake	int i;
40490699Srobert
40591295Srobert	if ((ino = lookup(fname)) == 0) {
40695337Sjake		printf("File %s not found\n", fname);
40790699Srobert		return;
40890699Srobert	}
40995339Sjake	if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) {
41095339Sjake		printf("Can't read elf header\n");
41191295Srobert		return;
41295339Sjake	}
41391295Srobert	if (!IS_ELF(eh)) {
41491295Srobert		printf("Not an ELF file\n");
41591295Srobert		return;
41691295Srobert	}
41795339Sjake	for (i = 0; i < eh.e_phnum; i++) {
41895339Sjake		fs_off = eh.e_phoff + i * eh.e_phentsize;
41995339Sjake		if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) {
42095339Sjake			printf("Can't read program header %d\n", i);
42191295Srobert			return;
42291295Srobert		}
42395339Sjake		if (ph.p_type != PT_LOAD)
42495339Sjake			continue;
42595339Sjake		fs_off = ph.p_offset;
42695339Sjake		p = (caddr_t)ph.p_vaddr;
42795339Sjake		if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) {
42895339Sjake			printf("Can't read content of section %d\n", i);
42991295Srobert			return;
43091295Srobert		}
43195339Sjake		if (ph.p_filesz != ph.p_memsz)
43295340Sjake			bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
43391295Srobert	}
43495351Sjake	ofw_close(bootdev);
43595339Sjake	(*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
43690699Srobert}
43790699Srobert
43890699Srobertstatic int
43990699Srobertdskread(void *buf, u_int64_t lba, int nblk)
44090699Srobert{
44191295Srobert	/*
44291295Srobert	 * The OpenFirmware should open the correct partition for us.
44391295Srobert	 * That means, if we read from offset zero on an open instance handle,
44491295Srobert	 * we should read from offset zero of that partition.
44591295Srobert	 */
44695351Sjake	ofw_seek(bootdev, lba * DEV_BSIZE);
44795351Sjake	ofw_read(bootdev, buf, nblk * DEV_BSIZE);
44891295Srobert	return (0);
44990699Srobert}
45090699Srobert
45195351Sjakestatic void
45295351Sjakepanic(const char *fmt, ...)
45390699Srobert{
45495351Sjake	char buf[128];
45591295Srobert	va_list ap;
45695346Sjake
45795346Sjake	va_start(ap, fmt);
45895351Sjake	vsnprintf(buf, sizeof buf, fmt, ap);
45995351Sjake	printf("panic: %s\n", buf);
46095346Sjake	va_end(ap);
46195351Sjake
46295351Sjake	exit(1);
46395346Sjake}
46495346Sjake
46595346Sjakestatic int
46695351Sjakeprintf(const char *fmt, ...)
46795346Sjake{
46895351Sjake	va_list ap;
46995346Sjake	int ret;
47095346Sjake
47195351Sjake	va_start(ap, fmt);
47295351Sjake	ret = vprintf(fmt, ap);
47395351Sjake	va_end(ap);
47495346Sjake	return (ret);
47595346Sjake}
47695346Sjake
47795346Sjakestatic int
47895346Sjakeputchar(int c, void *arg)
47995346Sjake{
48095346Sjake	char buf;
48195346Sjake
48295346Sjake	if (c == '\n') {
48395346Sjake		buf = '\r';
48495346Sjake		ofw_write(stdouth, &buf, 1);
48595346Sjake	}
48695346Sjake	buf = c;
48795346Sjake	ofw_write(stdouth, &buf, 1);
48895346Sjake	return (1);
48995346Sjake}
49095346Sjake
49195346Sjakestatic int
49295351Sjakevprintf(const char *fmt, va_list ap)
49395351Sjake{
49495351Sjake	int ret;
49595351Sjake
49695351Sjake	ret = __printf(fmt, putchar, 0, ap);
49795351Sjake	return (ret);
49895351Sjake}
49995351Sjake
50095351Sjakestatic int
50195351Sjakevsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
50295351Sjake{
50395351Sjake	struct sp_data sp;
50495351Sjake	int ret;
50595351Sjake
50695351Sjake	sp.sp_buf = str;
50795351Sjake	sp.sp_len = 0;
50895351Sjake	sp.sp_size = sz;
50995351Sjake	ret = __printf(fmt, __sputc, &sp, ap);
51095351Sjake	return (ret);
51195351Sjake}
51295351Sjake
51395351Sjakestatic int
51495346Sjake__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
51595346Sjake{
51695346Sjake	char buf[(sizeof(long) * 8) + 1];
51795346Sjake	char *nbuf;
51895346Sjake	u_long ul;
51995346Sjake	u_int ui;
52095346Sjake	int lflag;
52195346Sjake	int sflag;
52291295Srobert	char *s;
52395346Sjake	int pad;
52495346Sjake	int ret;
52595346Sjake	int c;
52690699Srobert
52795346Sjake	nbuf = &buf[sizeof buf - 1];
52895346Sjake	ret = 0;
52995346Sjake	while ((c = *fmt++) != 0) {
53095346Sjake		if (c != '%') {
53195346Sjake			ret += putc(c, arg);
53295346Sjake			continue;
53395346Sjake		}
53495346Sjake		lflag = 0;
53595346Sjake		sflag = 0;
53695346Sjake		pad = 0;
53795346Sjakereswitch:	c = *fmt++;
53895346Sjake		switch (c) {
53995346Sjake		case '#':
54095346Sjake			sflag = 1;
54195346Sjake			goto reswitch;
54295346Sjake		case '%':
54395346Sjake			ret += putc('%', arg);
54495346Sjake			break;
54595346Sjake		case 'c':
54695346Sjake			c = va_arg(ap, int);
54795346Sjake			ret += putc(c, arg);
54895346Sjake			break;
54995346Sjake		case 'd':
55095346Sjake			if (lflag == 0) {
55195346Sjake				ui = (u_int)va_arg(ap, int);
55295346Sjake				if (ui < (int)ui) {
55395346Sjake					ui = -ui;
55495346Sjake					ret += putc('-', arg);
55591295Srobert				}
55695346Sjake				s = __uitoa(nbuf, ui, 10);
55795346Sjake			} else {
55895346Sjake				ul = (u_long)va_arg(ap, long);
55995346Sjake				if (ul < (long)ul) {
56095346Sjake					ul = -ul;
56195346Sjake					ret += putc('-', arg);
56295346Sjake				}
56395346Sjake				s = __ultoa(nbuf, ul, 10);
56491295Srobert			}
56595346Sjake			ret += __puts(s, putc, arg);
56695346Sjake			break;
56795346Sjake		case 'l':
56895346Sjake			lflag = 1;
56995346Sjake			goto reswitch;
57095346Sjake		case 'o':
57195346Sjake			if (lflag == 0) {
57295346Sjake				ui = (u_int)va_arg(ap, u_int);
57395346Sjake				s = __uitoa(nbuf, ui, 8);
57495346Sjake			} else {
57595346Sjake				ul = (u_long)va_arg(ap, u_long);
57695346Sjake				s = __ultoa(nbuf, ul, 8);
57795346Sjake			}
57895346Sjake			ret += __puts(s, putc, arg);
57995346Sjake			break;
58095346Sjake		case 'p':
58195346Sjake			ul = (u_long)va_arg(ap, void *);
58295346Sjake			s = __ultoa(nbuf, ul, 16);
58395346Sjake			ret += __puts("0x", putc, arg);
58495346Sjake			ret += __puts(s, putc, arg);
58595346Sjake			break;
58695346Sjake		case 's':
58795346Sjake			s = va_arg(ap, char *);
58895346Sjake			ret += __puts(s, putc, arg);
58995346Sjake			break;
59095346Sjake		case 'u':
59195346Sjake			if (lflag == 0) {
59295346Sjake				ui = va_arg(ap, u_int);
59395346Sjake				s = __uitoa(nbuf, ui, 10);
59495346Sjake			} else {
59595346Sjake				ul = va_arg(ap, u_long);
59695346Sjake				s = __ultoa(nbuf, ul, 10);
59795346Sjake			}
59895346Sjake			ret += __puts(s, putc, arg);
59995346Sjake			break;
60095346Sjake		case 'x':
60195346Sjake			if (lflag == 0) {
60295346Sjake				ui = va_arg(ap, u_int);
60395346Sjake				s = __uitoa(nbuf, ui, 16);
60495346Sjake			} else {
60595346Sjake				ul = va_arg(ap, u_long);
60695346Sjake				s = __ultoa(nbuf, ul, 16);
60795346Sjake			}
60895346Sjake			if (sflag)
60995346Sjake				ret += __puts("0x", putc, arg);
61095346Sjake			ret += __puts(s, putc, arg);
61195346Sjake			break;
61295346Sjake		case '0': case '1': case '2': case '3': case '4':
61395346Sjake		case '5': case '6': case '7': case '8': case '9':
61495346Sjake			pad = pad * 10 + c - '0';
61595346Sjake			goto reswitch;
61695346Sjake		default:
61795346Sjake			break;
61890699Srobert		}
61990699Srobert	}
62095346Sjake	return (ret);
62190699Srobert}
62290699Srobert
62390699Srobertstatic int
62495351Sjake__sputc(int c, void *arg)
62595351Sjake{
62695351Sjake	struct sp_data *sp;
62795351Sjake
62895351Sjake	sp = arg;
62995351Sjake	if (sp->sp_len < sp->sp_size)
63095351Sjake		sp->sp_buf[sp->sp_len++] = c;
63195351Sjake	sp->sp_buf[sp->sp_len] = '\0';
63295351Sjake	return (1);
63395351Sjake}
63495351Sjake
63595351Sjakestatic int
63695346Sjake__puts(const char *s, putc_func_t *putc, void *arg)
63790699Srobert{
63895346Sjake	const char *p;
63995346Sjake	int ret;
64095346Sjake
64195346Sjake	ret = 0;
64295346Sjake	for (p = s; *p != '\0'; p++)
64395346Sjake		ret += putc(*p, arg);
64495346Sjake	return (ret);
64590699Srobert}
64695346Sjake
64795346Sjakestatic char *
64895346Sjake__uitoa(char *buf, u_int ui, int base)
64995346Sjake{
65095346Sjake	char *p;
65195346Sjake
65295346Sjake	p = buf;
65395346Sjake	*p = '\0';
65495346Sjake	do
65595346Sjake		*--p = digits[ui % base];
65695346Sjake	while ((ui /= base) != 0);
65795346Sjake	return (p);
65895346Sjake}
65995346Sjake
66095346Sjakestatic char *
66195346Sjake__ultoa(char *buf, u_long ul, int base)
66295346Sjake{
66395346Sjake	char *p;
66495346Sjake
66595346Sjake	p = buf;
66695346Sjake	*p = '\0';
66795346Sjake	do
66895346Sjake		*--p = digits[ul % base];
66995346Sjake	while ((ul /= base) != 0);
67095346Sjake	return (p);
67195346Sjake}
672