boot1.c revision 95346
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 95346 2002-04-24 04:27:49Z jake $"); 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 3690699Srobert#define BSIZEMAX 8192 3790699Srobert 3890699Srobert/* 3990699Srobert * This structure will be refined along with the addition of a bootpath 4090699Srobert * parsing routine when it is necessary to cope with bootpaths that are 4190699Srobert * not in the exact <devpath>@<controller>,<disk>:<partition> format and 4290699Srobert * for which we need to evaluate the disklabel ourselves. 4390699Srobert */ 4490699Srobertstruct disk { 4590699Srobert int meta; 4690699Srobert}; 4790699Srobertstruct disk dsk; 4890699Srobert 4995346Sjakestatic const char digits[] = "0123456789abcdef"; 5090699Srobert 5195346Sjakestatic char bootpath[128]; 5295346Sjakestatic char bootargs[128]; 5395346Sjake 5495346Sjakestatic int kflag; 5595346Sjake 5690699Srobertstatic uint32_t fs_off; 5790699Srobert 5895346Sjaketypedef int putc_func_t(int c, void *arg); 5995346Sjake 6095346Sjakeint main(int ac, char **av); 6195346Sjake 6295342Sjakestatic void exit(int); 6390699Srobertstatic void load(const char *); 6490699Srobertstatic ino_t lookup(const char *); 6590699Srobertstatic ssize_t fsread(ino_t, void *, size_t); 6690699Srobertstatic int dskread(void *, u_int64_t, int); 6790699Srobert 6895340Sjakestatic void bcopy(const void *src, void *dst, size_t len); 6995340Sjakestatic void bzero(void *b, size_t len); 7090699Srobert 7195346Sjakestatic int printf(const char *fmt, ...); 7295346Sjakestatic int vprintf(const char *fmt, va_list ap); 7395346Sjakestatic int putchar(int c, void *arg); 7495346Sjake 7595346Sjakestatic int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); 7695346Sjakestatic int __putc(int c, void *arg); 7795346Sjakestatic int __puts(const char *s, putc_func_t *putc, void *arg); 7895346Sjakestatic char *__uitoa(char *buf, u_int val, int base); 7995346Sjakestatic char *__ultoa(char *buf, u_long val, int base); 8095346Sjake 8190699Srobert/* 8290699Srobert * Open Firmware interface functions 8390699Srobert */ 8490699Sroberttypedef u_int64_t ofwcell_t; 8590699Sroberttypedef int32_t ofwh_t; 8690699Sroberttypedef u_int32_t u_ofwh_t; 8790699Sroberttypedef int (*ofwfp_t)(ofwcell_t []); 8890699Srobertofwfp_t ofw; /* the prom Open Firmware entry */ 8990699Srobert 9090699Srobertvoid ofw_init(int, int, int, int, ofwfp_t); 9190699Srobertofwh_t ofw_finddevice(const char *); 9290699Srobertofwh_t ofw_open(const char *); 9390699Srobertint ofw_getprop(ofwh_t, const char *, void *, size_t); 9490699Srobertint ofw_read(ofwh_t, void *, size_t); 9590699Srobertint ofw_write(ofwh_t, const void *, size_t); 9690699Srobertint ofw_seek(ofwh_t, u_int64_t); 9790699Srobert 9890699Srobertofwh_t bootdevh; 9990699Srobertofwh_t stdinh, stdouth; 10090699Srobert 10190699Srobert/* 10290699Srobert * This has to stay here, as the PROM seems to ignore the 10390699Srobert * entry point specified in the a.out header. (or elftoaout is broken) 10490699Srobert */ 10590699Srobert 10690699Srobertvoid 10790699Srobertofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr) 10890699Srobert{ 10990699Srobert ofwh_t chosenh; 11095346Sjake char *av[16]; 11195346Sjake char *p; 11295346Sjake int ac; 11390699Srobert 11490699Srobert ofw = ofwaddr; 11590699Srobert 11690699Srobert chosenh = ofw_finddevice("/chosen"); 11790699Srobert ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); 11890699Srobert ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); 11995346Sjake ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); 12090699Srobert ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 12190699Srobert 12295346Sjake bootargs[sizeof(bootargs) - 1] = '\0'; 12395346Sjake bootpath[sizeof(bootpath) - 1] = '\0'; 12495346Sjake 12590699Srobert if ((bootdevh = ofw_open(bootpath)) == -1) { 12690699Srobert printf("Could not open boot device.\n"); 12795346Sjake } 12890699Srobert 12995346Sjake ac = 0; 13095346Sjake p = bootargs; 13195346Sjake for (;;) { 13295346Sjake while (*p == ' ' && *p != '\0') 13395346Sjake p++; 13495346Sjake if (*p == '\0' || ac >= 16) 13595346Sjake break; 13695346Sjake av[ac++] = p; 13795346Sjake while (*p != ' ' && *p != '\0') 13895346Sjake p++; 13995346Sjake if (*p != '\0') 14095346Sjake *p++ = '\0'; 14195346Sjake } 14295346Sjake 14395346Sjake exit(main(ac, av)); 14490699Srobert} 14590699Srobert 14690699Srobertofwh_t 14790699Srobertofw_finddevice(const char *name) 14890699Srobert{ 14991295Srobert ofwcell_t args[] = { 15091295Srobert (ofwcell_t)"finddevice", 15191295Srobert 1, 15291295Srobert 1, 15391295Srobert (ofwcell_t)name, 15491295Srobert 0 15591295Srobert }; 15691295Srobert 15791295Srobert if ((*ofw)(args)) { 15891295Srobert printf("ofw_finddevice: name=\"%s\"\n", name); 15991295Srobert return (1); 16091295Srobert } 16191295Srobert return (args[4]); 16290699Srobert} 16390699Srobert 16490699Srobertint 16590699Srobertofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 16690699Srobert{ 16791295Srobert ofwcell_t args[] = { 16891295Srobert (ofwcell_t)"getprop", 16991295Srobert 4, 17091295Srobert 1, 17191295Srobert (u_ofwh_t)ofwh, 17291295Srobert (ofwcell_t)name, 17391295Srobert (ofwcell_t)buf, 17491295Srobert len, 17590699Srobert 0 17691295Srobert }; 17791295Srobert 17891295Srobert if ((*ofw)(args)) { 17991295Srobert printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", 18091295Srobert ofwh, buf, len); 18191295Srobert return (1); 18291295Srobert } 18391295Srobert return (0); 18490699Srobert} 18590699Srobert 18690699Srobertofwh_t 18790699Srobertofw_open(const char *path) 18890699Srobert{ 18991295Srobert ofwcell_t args[] = { 19091295Srobert (ofwcell_t)"open", 19191295Srobert 1, 19291295Srobert 1, 19391295Srobert (ofwcell_t)path, 19491295Srobert 0 19591295Srobert }; 19691295Srobert 19791295Srobert if ((*ofw)(args)) { 19891295Srobert printf("ofw_open: path=\"%s\"\n", path); 19991295Srobert return (-1); 20091295Srobert } 20191295Srobert return (args[4]); 20290699Srobert} 20390699Srobert 20490699Srobertint 20590699Srobertofw_close(ofwh_t devh) 20690699Srobert{ 20791295Srobert ofwcell_t args[] = { 20891295Srobert (ofwcell_t)"close", 20991295Srobert 1, 21091295Srobert 0, 21191295Srobert (u_ofwh_t)devh 21291295Srobert }; 21391295Srobert 21491295Srobert if ((*ofw)(args)) { 21591295Srobert printf("ofw_close: devh=0x%x\n", devh); 21691295Srobert return (1); 21791295Srobert } 21891295Srobert return (0); 21990699Srobert} 22090699Srobert 22190699Srobertint 22290699Srobertofw_read(ofwh_t devh, void *buf, size_t len) 22390699Srobert{ 22491295Srobert ofwcell_t args[] = { 22591295Srobert (ofwcell_t)"read", 22691295Srobert 4, 22791295Srobert 1, 22891295Srobert (u_ofwh_t)devh, 22991295Srobert (ofwcell_t)buf, 23091295Srobert len, 23191295Srobert 0 23291295Srobert }; 23391295Srobert 23491295Srobert if ((*ofw)(args)) { 23591295Srobert printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); 23691295Srobert return (1); 23791295Srobert } 23891295Srobert return (0); 23990699Srobert} 24090699Srobert 24190699Srobertint 24290699Srobertofw_write(ofwh_t devh, const void *buf, size_t len) 24390699Srobert{ 24491295Srobert ofwcell_t args[] = { 24591295Srobert (ofwcell_t)"write", 24691295Srobert 3, 24791295Srobert 1, 24891295Srobert (u_ofwh_t)devh, 24991295Srobert (ofwcell_t)buf, 25091295Srobert len, 25191295Srobert 0 25291295Srobert }; 25391295Srobert 25491295Srobert if ((*ofw)(args)) { 25591295Srobert printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); 25691295Srobert return (1); 25791295Srobert } 25891295Srobert return (0); 25990699Srobert} 26090699Srobert 26190699Srobertint 26290699Srobertofw_seek(ofwh_t devh, u_int64_t off) 26390699Srobert{ 26491295Srobert ofwcell_t args[] = { 26591295Srobert (ofwcell_t)"seek", 26691295Srobert 4, 26791295Srobert 1, 26891295Srobert (u_ofwh_t)devh, 26991295Srobert off >> 32, 27091678Srobert off, 27191295Srobert 0 27291295Srobert }; 27391295Srobert 27491295Srobert if ((*ofw)(args)) { 27591295Srobert printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); 27691295Srobert return (1); 27791295Srobert } 27891295Srobert return (0); 27990699Srobert} 28090699Srobert 28195342Sjakevoid 28295342Sjakeofw_exit(void) 28395342Sjake{ 28495342Sjake ofwcell_t args[3]; 28595342Sjake 28695342Sjake args[0] = (ofwcell_t)"exit"; 28795342Sjake args[1] = 0; 28895342Sjake args[2] = 0; 28995342Sjake 29095342Sjake (*ofw)(args); 29195342Sjake} 29295342Sjake 29395340Sjakestatic void 29495340Sjakebcopy(const void *dst, void *src, size_t len) 29595340Sjake{ 29695340Sjake const char *d = dst; 29795340Sjake char *s = src; 29895340Sjake 29995340Sjake while (len-- != 0) 30095340Sjake *s++ = *d++; 30195340Sjake} 30295340Sjake 30395340Sjakestatic void 30495340Sjakebzero(void *b, size_t len) 30595340Sjake{ 30695340Sjake char *p = b; 30795340Sjake 30895340Sjake while (len-- != 0) 30995340Sjake *p++ = 0; 31095340Sjake} 31195340Sjake 31290699Srobertstatic int 31390699Srobertstrcmp(const char *s1, const char *s2) 31490699Srobert{ 31591295Srobert for (; *s1 == *s2 && *s1; s1++, s2++) 31691295Srobert ; 31791295Srobert return ((u_char)*s1 - (u_char)*s2); 31890699Srobert} 31990699Srobert 32090699Srobertstatic int 32190699Srobertfsfind(const char *name, ino_t * ino) 32290699Srobert{ 32391295Srobert char buf[DEV_BSIZE]; 32491295Srobert struct dirent *d; 32591295Srobert char *s; 32691295Srobert ssize_t n; 32790699Srobert 32891295Srobert fs_off = 0; 32991295Srobert while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0) { 33091295Srobert for (s = buf; s < buf + DEV_BSIZE;) { 33191295Srobert d = (void *)s; 33295337Sjake if (!strcmp(name, d->d_name)) { 33391295Srobert *ino = d->d_fileno; 33491295Srobert return (d->d_type); 33591295Srobert } 33691295Srobert s += d->d_reclen; 33791295Srobert } 33890699Srobert } 33991295Srobert return (0); 34090699Srobert} 34190699Srobert 34295346Sjakeint 34395346Sjakemain(int ac, char **av) 34490699Srobert{ 34595346Sjake const char *path; 34695346Sjake int i; 34791295Srobert 34895346Sjake path = _PATH_LOADER; 34995346Sjake for (i = 0; i < ac; i++) { 35095346Sjake switch (av[i][0]) { 35195346Sjake case '-': 35295346Sjake switch (av[i][1]) { 35395346Sjake case 'k': 35495346Sjake kflag = 1; 35595346Sjake break; 35695346Sjake default: 35795346Sjake break; 35895346Sjake } 35995346Sjake break; 36095346Sjake default: 36195346Sjake path = av[i]; 36295346Sjake break; 36395346Sjake } 36495346Sjake } 36590699Srobert 36691295Srobert printf(" \n>> FreeBSD/sparc64 boot block\n" 36790699Srobert " Boot path: %s\n" 36895346Sjake " Boot loader: %s\n", bootpath, path); 36995346Sjake load(path); 37091295Srobert return (1); 37190699Srobert} 37290699Srobert 37390699Srobertstatic void 37495342Sjakeexit(int code) 37595342Sjake{ 37695342Sjake 37795342Sjake ofw_exit(); 37895342Sjake} 37995342Sjake 38095342Sjakestatic void 38190699Srobertload(const char *fname) 38290699Srobert{ 38391295Srobert Elf64_Ehdr eh; 38495339Sjake Elf64_Phdr ph; 38591295Srobert caddr_t p; 38691295Srobert ino_t ino; 38795339Sjake int i; 38890699Srobert 38991295Srobert if ((ino = lookup(fname)) == 0) { 39095337Sjake printf("File %s not found\n", fname); 39190699Srobert return; 39290699Srobert } 39395339Sjake if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { 39495339Sjake printf("Can't read elf header\n"); 39591295Srobert return; 39695339Sjake } 39791295Srobert if (!IS_ELF(eh)) { 39891295Srobert printf("Not an ELF file\n"); 39991295Srobert return; 40091295Srobert } 40195339Sjake for (i = 0; i < eh.e_phnum; i++) { 40295339Sjake fs_off = eh.e_phoff + i * eh.e_phentsize; 40395339Sjake if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { 40495339Sjake printf("Can't read program header %d\n", i); 40591295Srobert return; 40691295Srobert } 40795339Sjake if (ph.p_type != PT_LOAD) 40895339Sjake continue; 40995339Sjake fs_off = ph.p_offset; 41095339Sjake p = (caddr_t)ph.p_vaddr; 41195339Sjake if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { 41295339Sjake printf("Can't read content of section %d\n", i); 41391295Srobert return; 41491295Srobert } 41595339Sjake if (ph.p_filesz != ph.p_memsz) 41695340Sjake bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); 41791295Srobert } 41891295Srobert ofw_close(bootdevh); 41995339Sjake (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); 42090699Srobert} 42190699Srobert 42290699Srobertstatic ino_t 42390699Srobertlookup(const char *path) 42490699Srobert{ 42591295Srobert char name[MAXNAMLEN + 1]; 42691295Srobert const char *s; 42791295Srobert ino_t ino; 42891295Srobert ssize_t n; 42991295Srobert int dt; 43090699Srobert 43191295Srobert ino = ROOTINO; 43291295Srobert dt = DT_DIR; 43391678Srobert name[0] = '/'; 43491678Srobert name[1] = '\0'; 43591295Srobert for (;;) { 43691295Srobert if (*path == '/') 43791295Srobert path++; 43891295Srobert if (!*path) 43991295Srobert break; 44091295Srobert for (s = path; *s && *s != '/'; s++) 44191295Srobert ; 44291295Srobert if ((n = s - path) > MAXNAMLEN) 44391295Srobert return (0); 44495340Sjake bcopy(path, name, n); 44591295Srobert name[n] = 0; 44691678Srobert if (dt != DT_DIR) { 44791678Srobert printf("%s: not a directory.\n", name); 44891678Srobert return (0); 44991678Srobert } 45091295Srobert if ((dt = fsfind(name, &ino)) <= 0) 45191295Srobert break; 45291295Srobert path = s; 45391295Srobert } 45491295Srobert return (dt == DT_REG ? ino : 0); 45590699Srobert} 45690699Srobert 45790699Srobertstatic ssize_t 45890699Srobertfsread(ino_t inode, void *buf, size_t nbyte) 45990699Srobert{ 46091295Srobert static struct fs fs; 46191295Srobert static struct dinode din; 46295337Sjake static char blkbuf[BSIZEMAX]; 46395337Sjake static ufs_daddr_t indbuf[BSIZEMAX / sizeof(ufs_daddr_t)]; 46491295Srobert static ino_t inomap; 46591295Srobert static ufs_daddr_t blkmap, indmap; 46691295Srobert static unsigned int fsblks; 46791295Srobert char *s; 46891295Srobert ufs_daddr_t lbn, addr; 46991295Srobert size_t n, nb, off; 47090699Srobert 47191295Srobert if (!dsk.meta) { 47291295Srobert inomap = 0; 47391295Srobert if (dskread(blkbuf, SBOFF / DEV_BSIZE, SBSIZE / DEV_BSIZE)) 47491295Srobert return (-1); 47595340Sjake bcopy(blkbuf, &fs, sizeof(fs)); 47691295Srobert if (fs.fs_magic != FS_MAGIC) { 47791295Srobert printf("Not ufs\n"); 47895337Sjake return (-1); 47991295Srobert } 48091295Srobert fsblks = fs.fs_bsize >> DEV_BSHIFT; 48191295Srobert dsk.meta++; 48290699Srobert } 48391295Srobert if (!inode) 48491295Srobert return (0); 48591295Srobert if (inomap != inode) { 48691295Srobert if (dskread(blkbuf, fsbtodb(&fs, ino_to_fsba(&fs, inode)), 48790699Srobert fsblks)) 48891295Srobert return (-1); 48995340Sjake bcopy(blkbuf + ((inode % INOPB(&fs)) * sizeof(din)), &din, 49095340Sjake sizeof(din)); 49191295Srobert inomap = inode; 49291295Srobert fs_off = 0; 49391295Srobert blkmap = indmap = 0; 49490699Srobert } 49591295Srobert s = buf; 49691295Srobert if (nbyte > (n = din.di_size - fs_off)) 49791295Srobert nbyte = n; 49891295Srobert nb = nbyte; 49991295Srobert while (nb) { 50091295Srobert lbn = lblkno(&fs, fs_off); 50191295Srobert if (lbn < NDADDR) 50291295Srobert addr = din.di_db[lbn]; 50391295Srobert else { 50491295Srobert if (indmap != din.di_ib[0]) { 50591295Srobert if (dskread(indbuf, fsbtodb(&fs, din.di_ib[0]), 50691295Srobert fsblks)) 50791295Srobert return (-1); 50891295Srobert indmap = din.di_ib[0]; 50991295Srobert } 51091295Srobert addr = indbuf[(lbn - NDADDR) % NINDIR(&fs)]; 51191295Srobert } 51291295Srobert n = dblksize(&fs, &din, lbn); 51391295Srobert if (blkmap != addr) { 51491295Srobert if (dskread(blkbuf, fsbtodb(&fs, addr), 51591295Srobert n >> DEV_BSHIFT)) { 51691295Srobert return (-1); 51791295Srobert } 51891295Srobert blkmap = addr; 51991295Srobert } 52091295Srobert off = blkoff(&fs, fs_off); 52191295Srobert n -= off; 52291295Srobert if (n > nb) 52391295Srobert n = nb; 52495340Sjake bcopy(blkbuf + off, s, n); 52591295Srobert s += n; 52691295Srobert fs_off += n; 52791295Srobert nb -= n; 52890699Srobert } 52991295Srobert return (nbyte); 53090699Srobert} 53190699Srobert 53290699Srobertstatic int 53390699Srobertdskread(void *buf, u_int64_t lba, int nblk) 53490699Srobert{ 53591295Srobert /* 53691295Srobert * The OpenFirmware should open the correct partition for us. 53791295Srobert * That means, if we read from offset zero on an open instance handle, 53891295Srobert * we should read from offset zero of that partition. 53991295Srobert */ 54091295Srobert ofw_seek(bootdevh, lba * DEV_BSIZE); 54191295Srobert ofw_read(bootdevh, buf, nblk * DEV_BSIZE); 54291295Srobert return (0); 54390699Srobert} 54490699Srobert 54590699Srobertstatic int 54695346Sjakeprintf(const char *fmt, ...) 54790699Srobert{ 54891295Srobert va_list ap; 54995346Sjake int ret; 55095346Sjake 55195346Sjake va_start(ap, fmt); 55295346Sjake ret = vprintf(fmt, ap); 55395346Sjake va_end(ap); 55495346Sjake return (ret); 55595346Sjake} 55695346Sjake 55795346Sjakestatic int 55895346Sjakevprintf(const char *fmt, va_list ap) 55995346Sjake{ 56095346Sjake int ret; 56195346Sjake 56295346Sjake ret = __printf(fmt, putchar, 0, ap); 56395346Sjake return (ret); 56495346Sjake} 56595346Sjake 56695346Sjakestatic int 56795346Sjakeputchar(int c, void *arg) 56895346Sjake{ 56995346Sjake char buf; 57095346Sjake 57195346Sjake if (c == '\n') { 57295346Sjake buf = '\r'; 57395346Sjake ofw_write(stdouth, &buf, 1); 57495346Sjake } 57595346Sjake buf = c; 57695346Sjake ofw_write(stdouth, &buf, 1); 57795346Sjake return (1); 57895346Sjake} 57995346Sjake 58095346Sjakestatic int 58195346Sjake__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) 58295346Sjake{ 58395346Sjake char buf[(sizeof(long) * 8) + 1]; 58495346Sjake char *nbuf; 58595346Sjake u_long ul; 58695346Sjake u_int ui; 58795346Sjake int lflag; 58895346Sjake int sflag; 58991295Srobert char *s; 59095346Sjake int pad; 59195346Sjake int ret; 59295346Sjake int c; 59390699Srobert 59495346Sjake nbuf = &buf[sizeof buf - 1]; 59595346Sjake ret = 0; 59695346Sjake while ((c = *fmt++) != 0) { 59795346Sjake if (c != '%') { 59895346Sjake ret += putc(c, arg); 59995346Sjake continue; 60095346Sjake } 60195346Sjake lflag = 0; 60295346Sjake sflag = 0; 60395346Sjake pad = 0; 60495346Sjakereswitch: c = *fmt++; 60595346Sjake switch (c) { 60695346Sjake case '#': 60795346Sjake sflag = 1; 60895346Sjake goto reswitch; 60995346Sjake case '%': 61095346Sjake ret += putc('%', arg); 61195346Sjake break; 61295346Sjake case 'c': 61395346Sjake c = va_arg(ap, int); 61495346Sjake ret += putc(c, arg); 61595346Sjake break; 61695346Sjake case 'd': 61795346Sjake if (lflag == 0) { 61895346Sjake ui = (u_int)va_arg(ap, int); 61995346Sjake if (ui < (int)ui) { 62095346Sjake ui = -ui; 62195346Sjake ret += putc('-', arg); 62291295Srobert } 62395346Sjake s = __uitoa(nbuf, ui, 10); 62495346Sjake } else { 62595346Sjake ul = (u_long)va_arg(ap, long); 62695346Sjake if (ul < (long)ul) { 62795346Sjake ul = -ul; 62895346Sjake ret += putc('-', arg); 62995346Sjake } 63095346Sjake s = __ultoa(nbuf, ul, 10); 63191295Srobert } 63295346Sjake ret += __puts(s, putc, arg); 63395346Sjake break; 63495346Sjake case 'l': 63595346Sjake lflag = 1; 63695346Sjake goto reswitch; 63795346Sjake case 'o': 63895346Sjake if (lflag == 0) { 63995346Sjake ui = (u_int)va_arg(ap, u_int); 64095346Sjake s = __uitoa(nbuf, ui, 8); 64195346Sjake } else { 64295346Sjake ul = (u_long)va_arg(ap, u_long); 64395346Sjake s = __ultoa(nbuf, ul, 8); 64495346Sjake } 64595346Sjake ret += __puts(s, putc, arg); 64695346Sjake break; 64795346Sjake case 'p': 64895346Sjake ul = (u_long)va_arg(ap, void *); 64995346Sjake s = __ultoa(nbuf, ul, 16); 65095346Sjake ret += __puts("0x", putc, arg); 65195346Sjake ret += __puts(s, putc, arg); 65295346Sjake break; 65395346Sjake case 's': 65495346Sjake s = va_arg(ap, char *); 65595346Sjake ret += __puts(s, putc, arg); 65695346Sjake break; 65795346Sjake case 'u': 65895346Sjake if (lflag == 0) { 65995346Sjake ui = va_arg(ap, u_int); 66095346Sjake s = __uitoa(nbuf, ui, 10); 66195346Sjake } else { 66295346Sjake ul = va_arg(ap, u_long); 66395346Sjake s = __ultoa(nbuf, ul, 10); 66495346Sjake } 66595346Sjake ret += __puts(s, putc, arg); 66695346Sjake break; 66795346Sjake case 'x': 66895346Sjake if (lflag == 0) { 66995346Sjake ui = va_arg(ap, u_int); 67095346Sjake s = __uitoa(nbuf, ui, 16); 67195346Sjake } else { 67295346Sjake ul = va_arg(ap, u_long); 67395346Sjake s = __ultoa(nbuf, ul, 16); 67495346Sjake } 67595346Sjake if (sflag) 67695346Sjake ret += __puts("0x", putc, arg); 67795346Sjake ret += __puts(s, putc, arg); 67895346Sjake break; 67995346Sjake case '0': case '1': case '2': case '3': case '4': 68095346Sjake case '5': case '6': case '7': case '8': case '9': 68195346Sjake pad = pad * 10 + c - '0'; 68295346Sjake goto reswitch; 68395346Sjake default: 68495346Sjake break; 68590699Srobert } 68690699Srobert } 68795346Sjake return (ret); 68890699Srobert} 68990699Srobert 69090699Srobertstatic int 69195346Sjake__puts(const char *s, putc_func_t *putc, void *arg) 69290699Srobert{ 69395346Sjake const char *p; 69495346Sjake int ret; 69595346Sjake 69695346Sjake ret = 0; 69795346Sjake for (p = s; *p != '\0'; p++) 69895346Sjake ret += putc(*p, arg); 69995346Sjake return (ret); 70090699Srobert} 70195346Sjake 70295346Sjakestatic char * 70395346Sjake__uitoa(char *buf, u_int ui, int base) 70495346Sjake{ 70595346Sjake char *p; 70695346Sjake 70795346Sjake p = buf; 70895346Sjake *p = '\0'; 70995346Sjake do 71095346Sjake *--p = digits[ui % base]; 71195346Sjake while ((ui /= base) != 0); 71295346Sjake return (p); 71395346Sjake} 71495346Sjake 71595346Sjakestatic char * 71695346Sjake__ultoa(char *buf, u_long ul, int base) 71795346Sjake{ 71895346Sjake char *p; 71995346Sjake 72095346Sjake p = buf; 72195346Sjake *p = '\0'; 72295346Sjake do 72395346Sjake *--p = digits[ul % base]; 72495346Sjake while ((ul /= base) != 0); 72595346Sjake return (p); 72695346Sjake} 727