boot1.c revision 243305
1139738Simp/*- 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 */ 1791295Srobert 1891295Srobert#include <sys/cdefs.h> 1991295Srobert__FBSDID("$FreeBSD: head/sys/boot/sparc64/boot1/boot1.c 243305 2012-11-19 19:31:54Z marius $"); 2091295Srobert 2190699Srobert#include <sys/param.h> 2290699Srobert#include <sys/dirent.h> 23234898Smarius 2490699Srobert#include <machine/elf.h> 2590699Srobert#include <machine/stdarg.h> 2690699Srobert 27234898Smarius#define _PATH_LOADER "/boot/loader" 28234898Smarius#define _PATH_KERNEL "/boot/kernel/kernel" 29234898Smarius#define READ_BUF_SIZE 8192 3090699Srobert 31212729Smariustypedef int putc_func_t(char c, void *arg); 3295351Sjaketypedef int32_t ofwh_t; 3395351Sjake 3495351Sjakestruct sp_data { 3595351Sjake char *sp_buf; 3695351Sjake u_int sp_len; 3795351Sjake u_int sp_size; 3890699Srobert}; 3990699Srobert 4095346Sjakestatic const char digits[] = "0123456789abcdef"; 4190699Srobert 4295346Sjakestatic char bootpath[128]; 4395346Sjakestatic char bootargs[128]; 4495346Sjake 4595351Sjakestatic ofwh_t bootdev; 4695346Sjake 4790699Srobertstatic uint32_t fs_off; 4890699Srobert 4995346Sjakeint main(int ac, char **av); 50234898Smariusstatic void exit(int) __dead2; 51234898Smariusstatic void usage(void); 5295346Sjake 53234898Smarius#ifdef ZFSBOOT 54234898Smariusstatic void loadzfs(void); 55234898Smariusstatic int zbread(char *buf, off_t off, size_t bytes); 56234898Smarius#else 5790699Srobertstatic void load(const char *); 58234898Smarius#endif 5990699Srobert 6095340Sjakestatic void bcopy(const void *src, void *dst, size_t len); 6195340Sjakestatic void bzero(void *b, size_t len); 6290699Srobert 63243305Smariusstatic int domount(const char *device); 64234898Smariusstatic int dskread(void *buf, u_int64_t lba, int nblk); 6595351Sjake 6695351Sjakestatic void panic(const char *fmt, ...) __dead2; 6795346Sjakestatic int printf(const char *fmt, ...); 68212729Smariusstatic int putchar(char c, void *arg); 6995346Sjakestatic int vprintf(const char *fmt, va_list ap); 7095351Sjakestatic int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); 7195346Sjake 7295346Sjakestatic int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); 7395346Sjakestatic int __puts(const char *s, putc_func_t *putc, void *arg); 74212729Smariusstatic int __sputc(char c, void *arg); 7595346Sjakestatic char *__uitoa(char *buf, u_int val, int base); 7695346Sjakestatic char *__ultoa(char *buf, u_long val, int base); 7795346Sjake 7890699Srobert/* 7990699Srobert * Open Firmware interface functions 8090699Srobert */ 8190699Sroberttypedef u_int64_t ofwcell_t; 8290699Sroberttypedef u_int32_t u_ofwh_t; 8390699Sroberttypedef int (*ofwfp_t)(ofwcell_t []); 84212729Smariusstatic ofwfp_t ofw; /* the PROM Open Firmware entry */ 8590699Srobert 8690699Srobertvoid ofw_init(int, int, int, int, ofwfp_t); 87212729Smariusstatic ofwh_t ofw_finddevice(const char *); 88212729Smariusstatic ofwh_t ofw_open(const char *); 89212729Smariusstatic int ofw_getprop(ofwh_t, const char *, void *, size_t); 90212729Smariusstatic int ofw_read(ofwh_t, void *, size_t); 91212729Smariusstatic int ofw_write(ofwh_t, const void *, size_t); 92212729Smariusstatic int ofw_seek(ofwh_t, u_int64_t); 93212729Smariusstatic void ofw_exit(void) __dead2; 9490699Srobert 95212729Smariusstatic ofwh_t stdinh, stdouth; 9690699Srobert 9790699Srobert/* 9890699Srobert * This has to stay here, as the PROM seems to ignore the 9990699Srobert * entry point specified in the a.out header. (or elftoaout is broken) 10090699Srobert */ 10190699Srobert 10290699Srobertvoid 10390699Srobertofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr) 10490699Srobert{ 10590699Srobert ofwh_t chosenh; 10695346Sjake char *av[16]; 10795346Sjake char *p; 10895346Sjake int ac; 10990699Srobert 11090699Srobert ofw = ofwaddr; 11190699Srobert 11290699Srobert chosenh = ofw_finddevice("/chosen"); 11390699Srobert ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); 11490699Srobert ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); 11595346Sjake ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); 11690699Srobert ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); 11790699Srobert 11895346Sjake bootargs[sizeof(bootargs) - 1] = '\0'; 11995346Sjake bootpath[sizeof(bootpath) - 1] = '\0'; 12095346Sjake 12195346Sjake ac = 0; 12295346Sjake p = bootargs; 12395346Sjake for (;;) { 12495346Sjake while (*p == ' ' && *p != '\0') 12595346Sjake p++; 12695346Sjake if (*p == '\0' || ac >= 16) 12795346Sjake break; 12895346Sjake av[ac++] = p; 12995346Sjake while (*p != ' ' && *p != '\0') 13095346Sjake p++; 13195346Sjake if (*p != '\0') 13295346Sjake *p++ = '\0'; 13395346Sjake } 13495346Sjake 13595346Sjake exit(main(ac, av)); 13690699Srobert} 13790699Srobert 138212729Smariusstatic ofwh_t 13990699Srobertofw_finddevice(const char *name) 14090699Srobert{ 14191295Srobert ofwcell_t args[] = { 14291295Srobert (ofwcell_t)"finddevice", 14391295Srobert 1, 14491295Srobert 1, 14591295Srobert (ofwcell_t)name, 14691295Srobert 0 14791295Srobert }; 14891295Srobert 14991295Srobert if ((*ofw)(args)) { 15091295Srobert printf("ofw_finddevice: name=\"%s\"\n", name); 15191295Srobert return (1); 15291295Srobert } 15391295Srobert return (args[4]); 15490699Srobert} 15590699Srobert 156212729Smariusstatic int 15790699Srobertofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) 15890699Srobert{ 15991295Srobert ofwcell_t args[] = { 16091295Srobert (ofwcell_t)"getprop", 16191295Srobert 4, 16291295Srobert 1, 16391295Srobert (u_ofwh_t)ofwh, 16491295Srobert (ofwcell_t)name, 16591295Srobert (ofwcell_t)buf, 16691295Srobert len, 16790699Srobert 0 16891295Srobert }; 16991295Srobert 17091295Srobert if ((*ofw)(args)) { 17191295Srobert printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", 17291295Srobert ofwh, buf, len); 17391295Srobert return (1); 17491295Srobert } 17591295Srobert return (0); 17690699Srobert} 17790699Srobert 178212729Smariusstatic ofwh_t 17990699Srobertofw_open(const char *path) 18090699Srobert{ 18191295Srobert ofwcell_t args[] = { 18291295Srobert (ofwcell_t)"open", 18391295Srobert 1, 18491295Srobert 1, 18591295Srobert (ofwcell_t)path, 18691295Srobert 0 18791295Srobert }; 18891295Srobert 18991295Srobert if ((*ofw)(args)) { 19091295Srobert printf("ofw_open: path=\"%s\"\n", path); 19191295Srobert return (-1); 19291295Srobert } 19391295Srobert return (args[4]); 19490699Srobert} 19590699Srobert 196212729Smariusstatic int 19790699Srobertofw_close(ofwh_t devh) 19890699Srobert{ 19991295Srobert ofwcell_t args[] = { 20091295Srobert (ofwcell_t)"close", 20191295Srobert 1, 20291295Srobert 0, 20391295Srobert (u_ofwh_t)devh 20491295Srobert }; 20591295Srobert 20691295Srobert if ((*ofw)(args)) { 20791295Srobert printf("ofw_close: devh=0x%x\n", devh); 20891295Srobert return (1); 20991295Srobert } 21091295Srobert return (0); 21190699Srobert} 21290699Srobert 213212729Smariusstatic int 21490699Srobertofw_read(ofwh_t devh, void *buf, size_t len) 21590699Srobert{ 21691295Srobert ofwcell_t args[] = { 21791295Srobert (ofwcell_t)"read", 218212729Smarius 3, 21991295Srobert 1, 22091295Srobert (u_ofwh_t)devh, 22191295Srobert (ofwcell_t)buf, 22291295Srobert len, 22391295Srobert 0 22491295Srobert }; 22591295Srobert 22691295Srobert if ((*ofw)(args)) { 22791295Srobert printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); 22891295Srobert return (1); 22991295Srobert } 23091295Srobert return (0); 23190699Srobert} 23290699Srobert 233212729Smariusstatic int 23490699Srobertofw_write(ofwh_t devh, const void *buf, size_t len) 23590699Srobert{ 23691295Srobert ofwcell_t args[] = { 23791295Srobert (ofwcell_t)"write", 23891295Srobert 3, 23991295Srobert 1, 24091295Srobert (u_ofwh_t)devh, 24191295Srobert (ofwcell_t)buf, 24291295Srobert len, 24391295Srobert 0 24491295Srobert }; 24591295Srobert 24691295Srobert if ((*ofw)(args)) { 24791295Srobert printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); 24891295Srobert return (1); 24991295Srobert } 25091295Srobert return (0); 25190699Srobert} 25290699Srobert 253212729Smariusstatic int 25490699Srobertofw_seek(ofwh_t devh, u_int64_t off) 25590699Srobert{ 25691295Srobert ofwcell_t args[] = { 25791295Srobert (ofwcell_t)"seek", 258212729Smarius 3, 25991295Srobert 1, 26091295Srobert (u_ofwh_t)devh, 26191295Srobert off >> 32, 26291678Srobert off, 26391295Srobert 0 26491295Srobert }; 26591295Srobert 26691295Srobert if ((*ofw)(args)) { 26791295Srobert printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); 26891295Srobert return (1); 26991295Srobert } 27091295Srobert return (0); 27190699Srobert} 27290699Srobert 273212729Smariusstatic void 27495342Sjakeofw_exit(void) 27595342Sjake{ 27695342Sjake ofwcell_t args[3]; 27795342Sjake 27895342Sjake args[0] = (ofwcell_t)"exit"; 27995342Sjake args[1] = 0; 28095342Sjake args[2] = 0; 28195342Sjake 28295351Sjake for (;;) 28395351Sjake (*ofw)(args); 28495342Sjake} 28595342Sjake 28695340Sjakestatic void 28797863Sphkbcopy(const void *src, void *dst, size_t len) 28895340Sjake{ 28997863Sphk const char *s = src; 29097863Sphk char *d = dst; 29195340Sjake 29295340Sjake while (len-- != 0) 29397863Sphk *d++ = *s++; 29495340Sjake} 29595340Sjake 29695340Sjakestatic void 29797864Sphkmemcpy(void *dst, const void *src, size_t len) 29897864Sphk{ 299212729Smarius 30097864Sphk bcopy(src, dst, len); 30197864Sphk} 30297864Sphk 30397864Sphkstatic 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{ 315212729Smarius 31691295Srobert for (; *s1 == *s2 && *s1; s1++, s2++) 31791295Srobert ; 31891295Srobert return ((u_char)*s1 - (u_char)*s2); 31990699Srobert} 32090699Srobert 32195346Sjakeint 32295346Sjakemain(int ac, char **av) 32390699Srobert{ 32495346Sjake const char *path; 32595346Sjake int i; 32691295Srobert 32795346Sjake path = _PATH_LOADER; 32895346Sjake for (i = 0; i < ac; i++) { 32995346Sjake switch (av[i][0]) { 33095346Sjake case '-': 33195346Sjake switch (av[i][1]) { 33295346Sjake default: 33395351Sjake usage(); 33495346Sjake } 33595346Sjake break; 33695346Sjake default: 33795346Sjake path = av[i]; 33895346Sjake break; 33995346Sjake } 34095346Sjake } 34190699Srobert 342234898Smarius#ifdef ZFSBOOT 343234898Smarius printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n", 344234898Smarius bootpath); 345234898Smarius#else 346234898Smarius printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n" 347234898Smarius " Boot loader: %s\n", "", bootpath, path); 348234898Smarius#endif 34995351Sjake 350243305Smarius if (domount(bootpath) == -1) 351243305Smarius panic("domount"); 35295351Sjake 353234898Smarius#ifdef ZFSBOOT 354234898Smarius loadzfs(); 355234898Smarius#else 35695346Sjake load(path); 357234898Smarius#endif 35891295Srobert return (1); 35990699Srobert} 36090699Srobert 36190699Srobertstatic void 36295351Sjakeusage(void) 36395351Sjake{ 36495351Sjake 36595351Sjake printf("usage: boot device [/path/to/loader]\n"); 36695351Sjake exit(1); 36795351Sjake} 36895351Sjake 36995351Sjakestatic void 37095342Sjakeexit(int code) 37195342Sjake{ 37295342Sjake 37395342Sjake ofw_exit(); 37495342Sjake} 37595342Sjake 376234898Smarius#ifdef ZFSBOOT 37797864Sphk 378234898Smarius#define VDEV_BOOT_OFFSET (2 * 256 * 1024) 379234898Smariusstatic char zbuf[READ_BUF_SIZE]; 380234898Smarius 38195351Sjakestatic int 382234898Smariuszbread(char *buf, off_t off, size_t bytes) 38395351Sjake{ 384234898Smarius size_t len; 385234898Smarius off_t poff; 386234898Smarius off_t soff; 387234898Smarius char *p; 388234898Smarius unsigned int nb; 389234898Smarius unsigned int lb; 39095351Sjake 391234898Smarius p = buf; 392234898Smarius soff = VDEV_BOOT_OFFSET + off; 393234898Smarius lb = (soff + bytes + DEV_BSIZE - 1) / DEV_BSIZE; 394234898Smarius poff = soff; 395234898Smarius while (poff < soff + bytes) { 396234898Smarius nb = lb - poff / DEV_BSIZE; 397234898Smarius if (nb > READ_BUF_SIZE / DEV_BSIZE) 398234898Smarius nb = READ_BUF_SIZE / DEV_BSIZE; 399234898Smarius if (dskread(zbuf, poff / DEV_BSIZE, nb)) 400234898Smarius break; 401234898Smarius if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes) 402234898Smarius len = soff + bytes - poff; 403234898Smarius else 404234898Smarius len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff; 405234898Smarius memcpy(p, zbuf + poff % DEV_BSIZE, len); 406234898Smarius p += len; 407234898Smarius poff += len; 40895351Sjake } 409234898Smarius return (poff - soff); 410234898Smarius} 411234898Smarius 412234898Smariusstatic void 413234898Smariusloadzfs(void) 414234898Smarius{ 415234898Smarius Elf64_Ehdr eh; 416234898Smarius Elf64_Phdr ph; 417234898Smarius caddr_t p; 418234898Smarius int i; 419234898Smarius 420234898Smarius if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) { 421234898Smarius printf("Can't read elf header\n"); 422234898Smarius return; 42395351Sjake } 424234898Smarius if (!IS_ELF(eh)) { 425234898Smarius printf("Not an ELF file\n"); 426234898Smarius return; 427234898Smarius } 428234898Smarius for (i = 0; i < eh.e_phnum; i++) { 429234898Smarius fs_off = eh.e_phoff + i * eh.e_phentsize; 430234898Smarius if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) { 431234898Smarius printf("Can't read program header %d\n", i); 432234898Smarius return; 433234898Smarius } 434234898Smarius if (ph.p_type != PT_LOAD) 435234898Smarius continue; 436234898Smarius fs_off = ph.p_offset; 437234898Smarius p = (caddr_t)ph.p_vaddr; 438234898Smarius if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) { 439234898Smarius printf("Can't read content of section %d\n", i); 440234898Smarius return; 441234898Smarius } 442234898Smarius if (ph.p_filesz != ph.p_memsz) 443234898Smarius bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); 444234898Smarius } 445234898Smarius ofw_close(bootdev); 446234898Smarius (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); 44795351Sjake} 44895351Sjake 449234898Smarius#else 450234898Smarius 451234898Smarius#include "ufsread.c" 452234898Smarius 453234898Smariusstatic struct dmadat __dmadat; 454234898Smarius 45595342Sjakestatic void 45690699Srobertload(const char *fname) 45790699Srobert{ 45891295Srobert Elf64_Ehdr eh; 45995339Sjake Elf64_Phdr ph; 46091295Srobert caddr_t p; 461235988Sgleb ufs_ino_t ino; 46295339Sjake int i; 46390699Srobert 46491295Srobert if ((ino = lookup(fname)) == 0) { 46595337Sjake printf("File %s not found\n", fname); 46690699Srobert return; 46790699Srobert } 46895339Sjake if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { 46995339Sjake printf("Can't read elf header\n"); 47091295Srobert return; 47195339Sjake } 47291295Srobert if (!IS_ELF(eh)) { 47391295Srobert printf("Not an ELF file\n"); 47491295Srobert return; 47591295Srobert } 47695339Sjake for (i = 0; i < eh.e_phnum; i++) { 47795339Sjake fs_off = eh.e_phoff + i * eh.e_phentsize; 47895339Sjake if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { 47995339Sjake printf("Can't read program header %d\n", i); 48091295Srobert return; 48191295Srobert } 48295339Sjake if (ph.p_type != PT_LOAD) 48395339Sjake continue; 48495339Sjake fs_off = ph.p_offset; 48595339Sjake p = (caddr_t)ph.p_vaddr; 48695339Sjake if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { 48795339Sjake printf("Can't read content of section %d\n", i); 48891295Srobert return; 48991295Srobert } 49095339Sjake if (ph.p_filesz != ph.p_memsz) 49195340Sjake bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); 49291295Srobert } 49395351Sjake ofw_close(bootdev); 49495339Sjake (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); 49590699Srobert} 49690699Srobert 497234898Smarius#endif /* ZFSBOOT */ 498234898Smarius 49990699Srobertstatic int 500243305Smariusdomount(const char *device) 501234898Smarius{ 502234898Smarius 503234898Smarius if ((bootdev = ofw_open(device)) == -1) { 504243305Smarius printf("domount: can't open device\n"); 505234898Smarius return (-1); 506234898Smarius } 507234898Smarius#ifndef ZFSBOOT 508234898Smarius dmadat = &__dmadat; 509234898Smarius if (fsread(0, NULL, 0)) { 510243305Smarius printf("domount: can't read superblock\n"); 511234898Smarius return (-1); 512234898Smarius } 513234898Smarius#endif 514234898Smarius return (0); 515234898Smarius} 516234898Smarius 517234898Smariusstatic int 51890699Srobertdskread(void *buf, u_int64_t lba, int nblk) 51990699Srobert{ 520212729Smarius 52191295Srobert /* 522133862Smarius * The Open Firmware should open the correct partition for us. 52391295Srobert * That means, if we read from offset zero on an open instance handle, 52491295Srobert * we should read from offset zero of that partition. 52591295Srobert */ 52695351Sjake ofw_seek(bootdev, lba * DEV_BSIZE); 52795351Sjake ofw_read(bootdev, buf, nblk * DEV_BSIZE); 52891295Srobert return (0); 52990699Srobert} 53090699Srobert 53195351Sjakestatic void 53295351Sjakepanic(const char *fmt, ...) 53390699Srobert{ 53495351Sjake char buf[128]; 53591295Srobert va_list ap; 53695346Sjake 53795346Sjake va_start(ap, fmt); 53895351Sjake vsnprintf(buf, sizeof buf, fmt, ap); 53995351Sjake printf("panic: %s\n", buf); 54095346Sjake va_end(ap); 54195351Sjake 54295351Sjake exit(1); 54395346Sjake} 54495346Sjake 54595346Sjakestatic int 54695351Sjakeprintf(const char *fmt, ...) 54795346Sjake{ 54895351Sjake va_list ap; 54995346Sjake int ret; 55095346Sjake 55195351Sjake va_start(ap, fmt); 55295351Sjake ret = vprintf(fmt, ap); 55395351Sjake va_end(ap); 55495346Sjake return (ret); 55595346Sjake} 55695346Sjake 55795346Sjakestatic int 558212729Smariusputchar(char c, void *arg) 55995346Sjake{ 56095346Sjake char buf; 56195346Sjake 56295346Sjake if (c == '\n') { 56395346Sjake buf = '\r'; 56495346Sjake ofw_write(stdouth, &buf, 1); 56595346Sjake } 56695346Sjake buf = c; 56795346Sjake ofw_write(stdouth, &buf, 1); 56895346Sjake return (1); 56995346Sjake} 57095346Sjake 57195346Sjakestatic int 57295351Sjakevprintf(const char *fmt, va_list ap) 57395351Sjake{ 57495351Sjake int ret; 57595351Sjake 57695351Sjake ret = __printf(fmt, putchar, 0, ap); 57795351Sjake return (ret); 57895351Sjake} 57995351Sjake 58095351Sjakestatic int 58195351Sjakevsnprintf(char *str, size_t sz, const char *fmt, va_list ap) 58295351Sjake{ 58395351Sjake struct sp_data sp; 58495351Sjake int ret; 58595351Sjake 58695351Sjake sp.sp_buf = str; 58795351Sjake sp.sp_len = 0; 58895351Sjake sp.sp_size = sz; 58995351Sjake ret = __printf(fmt, __sputc, &sp, ap); 59095351Sjake return (ret); 59195351Sjake} 59295351Sjake 59395351Sjakestatic int 59495346Sjake__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) 59595346Sjake{ 59695346Sjake char buf[(sizeof(long) * 8) + 1]; 59795346Sjake char *nbuf; 59895346Sjake u_long ul; 59995346Sjake u_int ui; 60095346Sjake int lflag; 60195346Sjake int sflag; 60291295Srobert char *s; 60395346Sjake int pad; 60495346Sjake int ret; 60595346Sjake int c; 60690699Srobert 60795346Sjake nbuf = &buf[sizeof buf - 1]; 60895346Sjake ret = 0; 60995346Sjake while ((c = *fmt++) != 0) { 61095346Sjake if (c != '%') { 61195346Sjake ret += putc(c, arg); 61295346Sjake continue; 61395346Sjake } 61495346Sjake lflag = 0; 61595346Sjake sflag = 0; 61695346Sjake pad = 0; 61795346Sjakereswitch: c = *fmt++; 61895346Sjake switch (c) { 61995346Sjake case '#': 62095346Sjake sflag = 1; 62195346Sjake goto reswitch; 62295346Sjake case '%': 62395346Sjake ret += putc('%', arg); 62495346Sjake break; 62595346Sjake case 'c': 62695346Sjake c = va_arg(ap, int); 62795346Sjake ret += putc(c, arg); 62895346Sjake break; 62995346Sjake case 'd': 63095346Sjake if (lflag == 0) { 63195346Sjake ui = (u_int)va_arg(ap, int); 63295346Sjake if (ui < (int)ui) { 63395346Sjake ui = -ui; 63495346Sjake ret += putc('-', arg); 63591295Srobert } 63695346Sjake s = __uitoa(nbuf, ui, 10); 63795346Sjake } else { 63895346Sjake ul = (u_long)va_arg(ap, long); 63995346Sjake if (ul < (long)ul) { 64095346Sjake ul = -ul; 64195346Sjake ret += putc('-', arg); 64295346Sjake } 64395346Sjake s = __ultoa(nbuf, ul, 10); 64491295Srobert } 64595346Sjake ret += __puts(s, putc, arg); 64695346Sjake break; 64795346Sjake case 'l': 64895346Sjake lflag = 1; 64995346Sjake goto reswitch; 65095346Sjake case 'o': 65195346Sjake if (lflag == 0) { 65295346Sjake ui = (u_int)va_arg(ap, u_int); 65395346Sjake s = __uitoa(nbuf, ui, 8); 65495346Sjake } else { 65595346Sjake ul = (u_long)va_arg(ap, u_long); 65695346Sjake s = __ultoa(nbuf, ul, 8); 65795346Sjake } 65895346Sjake ret += __puts(s, putc, arg); 65995346Sjake break; 66095346Sjake case 'p': 66195346Sjake ul = (u_long)va_arg(ap, void *); 66295346Sjake s = __ultoa(nbuf, ul, 16); 66395346Sjake ret += __puts("0x", putc, arg); 66495346Sjake ret += __puts(s, putc, arg); 66595346Sjake break; 66695346Sjake case 's': 66795346Sjake s = va_arg(ap, char *); 66895346Sjake ret += __puts(s, putc, arg); 66995346Sjake break; 67095346Sjake case 'u': 67195346Sjake if (lflag == 0) { 67295346Sjake ui = va_arg(ap, u_int); 67395346Sjake s = __uitoa(nbuf, ui, 10); 67495346Sjake } else { 67595346Sjake ul = va_arg(ap, u_long); 67695346Sjake s = __ultoa(nbuf, ul, 10); 67795346Sjake } 67895346Sjake ret += __puts(s, putc, arg); 67995346Sjake break; 68095346Sjake case 'x': 68195346Sjake if (lflag == 0) { 68295346Sjake ui = va_arg(ap, u_int); 68395346Sjake s = __uitoa(nbuf, ui, 16); 68495346Sjake } else { 68595346Sjake ul = va_arg(ap, u_long); 68695346Sjake s = __ultoa(nbuf, ul, 16); 68795346Sjake } 68895346Sjake if (sflag) 68995346Sjake ret += __puts("0x", putc, arg); 69095346Sjake ret += __puts(s, putc, arg); 69195346Sjake break; 69295346Sjake case '0': case '1': case '2': case '3': case '4': 69395346Sjake case '5': case '6': case '7': case '8': case '9': 69495346Sjake pad = pad * 10 + c - '0'; 69595346Sjake goto reswitch; 69695346Sjake default: 69795346Sjake break; 69890699Srobert } 69990699Srobert } 70095346Sjake return (ret); 70190699Srobert} 70290699Srobert 70390699Srobertstatic int 704212729Smarius__sputc(char c, void *arg) 70595351Sjake{ 70695351Sjake struct sp_data *sp; 70795351Sjake 70895351Sjake sp = arg; 70995351Sjake if (sp->sp_len < sp->sp_size) 71095351Sjake sp->sp_buf[sp->sp_len++] = c; 71195351Sjake sp->sp_buf[sp->sp_len] = '\0'; 71295351Sjake return (1); 71395351Sjake} 71495351Sjake 71595351Sjakestatic int 71695346Sjake__puts(const char *s, putc_func_t *putc, void *arg) 71790699Srobert{ 71895346Sjake const char *p; 71995346Sjake int ret; 72095346Sjake 72195346Sjake ret = 0; 72295346Sjake for (p = s; *p != '\0'; p++) 72395346Sjake ret += putc(*p, arg); 72495346Sjake return (ret); 72590699Srobert} 72695346Sjake 72795346Sjakestatic char * 72895346Sjake__uitoa(char *buf, u_int ui, int base) 72995346Sjake{ 73095346Sjake char *p; 73195346Sjake 73295346Sjake p = buf; 73395346Sjake *p = '\0'; 73495346Sjake do 73595346Sjake *--p = digits[ui % base]; 73695346Sjake while ((ui /= base) != 0); 73795346Sjake return (p); 73895346Sjake} 73995346Sjake 74095346Sjakestatic char * 74195346Sjake__ultoa(char *buf, u_long ul, int base) 74295346Sjake{ 74395346Sjake char *p; 74495346Sjake 74595346Sjake p = buf; 74695346Sjake *p = '\0'; 74795346Sjake do 74895346Sjake *--p = digits[ul % base]; 74995346Sjake while ((ul /= base) != 0); 75095346Sjake return (p); 75195346Sjake} 752