Index: head/stand/common/bootstrap.h =================================================================== --- head/stand/common/bootstrap.h (revision 364964) +++ head/stand/common/bootstrap.h (revision 364965) @@ -1,352 +1,351 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _BOOTSTRAP_H_ #define _BOOTSTRAP_H_ #include #include #include #include "readin.h" /* Commands and return values; nonzero return sets command_errmsg != NULL */ typedef int (bootblk_cmd_t)(int argc, char *argv[]); #define COMMAND_ERRBUFSZ (256) extern const char *command_errmsg; extern char command_errbuf[COMMAND_ERRBUFSZ]; #define CMD_OK 0 #define CMD_WARN 1 #define CMD_ERROR 2 #define CMD_CRIT 3 #define CMD_FATAL 4 /* interp.c */ void interact(void); void interp_emit_prompt(void); int interp_builtin_cmd(int argc, char *argv[]); /* Called by interp.c for interp_*.c embedded interpreters */ int interp_include(const char *filename); /* Execute commands from filename */ void interp_init(void); /* Initialize interpreater */ int interp_run(const char *line); /* Run a single command */ /* interp_backslash.c */ char *backslash(const char *str); /* interp_parse.c */ int parse(int *argc, char ***argv, const char *str); /* boot.c */ void autoboot_maybe(void); int getrootmount(char *rootdev); /* misc.c */ char *unargv(int argc, char *argv[]); -void hexdump(caddr_t region, size_t len); size_t strlenout(vm_offset_t str); char *strdupout(vm_offset_t str); void kern_bzero(vm_offset_t dest, size_t len); int kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off); void *alloc_pread(readin_handle_t fd, off_t off, size_t len); /* bcache.c */ void bcache_init(size_t nblks, size_t bsize); void bcache_add_dev(int); void *bcache_allocate(void); void bcache_free(void *); int bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize); /* * Disk block cache */ struct bcache_devdata { int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize); void *dv_devdata; void *dv_cache; }; /* * Modular console support. */ struct console { const char *c_name; const char *c_desc; int c_flags; #define C_PRESENTIN (1<<0) /* console can provide input */ #define C_PRESENTOUT (1<<1) /* console can provide output */ #define C_ACTIVEIN (1<<2) /* user wants input from console */ #define C_ACTIVEOUT (1<<3) /* user wants output to console */ #define C_WIDEOUT (1<<4) /* c_out routine groks wide chars */ void (* c_probe)(struct console *cp); /* set c_flags to match hardware */ int (* c_init)(int arg); /* reinit XXX may need more args */ void (* c_out)(int c); /* emit c */ int (* c_in)(void); /* wait for and return input */ int (* c_ready)(void); /* return nonzer if input waiting */ }; extern struct console *consoles[]; void cons_probe(void); /* * Plug-and-play enumerator/configurator interface. */ struct pnphandler { const char *pp_name; /* handler/bus name */ void (* pp_enumerate)(void); /* enumerate PnP devices, add to chain */ }; struct pnpident { char *id_ident; /* ASCII identifier, actual format varies with bus/handler */ STAILQ_ENTRY(pnpident) id_link; }; struct pnpinfo { char *pi_desc; /* ASCII description, optional */ int pi_revision; /* optional revision (or -1) if not supported */ char *pi_module; /* module/args nominated to handle device */ int pi_argc; /* module arguments */ char **pi_argv; struct pnphandler *pi_handler; /* handler which detected this device */ STAILQ_HEAD(,pnpident) pi_ident; /* list of identifiers */ STAILQ_ENTRY(pnpinfo) pi_link; }; STAILQ_HEAD(pnpinfo_stql, pnpinfo); extern struct pnphandler *pnphandlers[]; /* provided by MD code */ void pnp_addident(struct pnpinfo *pi, char *ident); struct pnpinfo *pnp_allocinfo(void); void pnp_freeinfo(struct pnpinfo *pi); void pnp_addinfo(struct pnpinfo *pi); char *pnp_eisaformat(uint8_t *data); /* * < 0 - No ISA in system * == 0 - Maybe ISA, search for read data port * > 0 - ISA in system, value is read data port address */ extern int isapnp_readport; /* * Version information */ extern char bootprog_info[]; /* * Interpreter information */ extern const char bootprog_interp[]; #define INTERP_DEFINE(interpstr) \ const char bootprog_interp[] = "$Interpreter:" interpstr /* * Preloaded file metadata header. * * Metadata are allocated on our heap, and copied into kernel space * before executing the kernel. */ struct file_metadata { size_t md_size; uint16_t md_type; struct file_metadata *md_next; char md_data[1]; /* data are immediately appended */ }; struct preloaded_file; struct mod_depend; struct kernel_module { char *m_name; /* module name */ int m_version; /* module version */ /* char *m_args;*/ /* arguments for the module */ struct preloaded_file *m_fp; struct kernel_module *m_next; }; /* * Preloaded file information. Depending on type, file can contain * additional units called 'modules'. * * At least one file (the kernel) must be loaded in order to boot. * The kernel is always loaded first. * * String fields (m_name, m_type) should be dynamically allocated. */ struct preloaded_file { char *f_name; /* file name */ char *f_type; /* verbose file type, eg 'ELF kernel', 'pnptable', etc. */ char *f_args; /* arguments for the file */ struct file_metadata *f_metadata; /* metadata that will be placed in the module directory */ int f_loader; /* index of the loader that read the file */ vm_offset_t f_addr; /* load address */ size_t f_size; /* file size */ struct kernel_module *f_modules; /* list of modules if any */ struct preloaded_file *f_next; /* next file */ }; struct file_format { /* Load function must return EFTYPE if it can't handle the module supplied */ int (* l_load)(char *filename, uint64_t dest, struct preloaded_file **result); /* Only a loader that will load a kernel (first module) should have an exec handler */ int (* l_exec)(struct preloaded_file *mp); }; extern struct file_format *file_formats[]; /* supplied by consumer */ extern struct preloaded_file *preloaded_files; int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]); int mod_loadkld(const char *name, int argc, char *argv[]); void unload(void); struct preloaded_file *file_alloc(void); struct preloaded_file *file_findfile(const char *name, const char *type); struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type); struct preloaded_file *file_loadraw(const char *name, char *type, int insert); void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, struct kernel_module **newmp); void file_removemetadata(struct preloaded_file *fp); /* MI module loaders */ #ifdef __elfN /* Relocation types. */ #define ELF_RELOC_REL 1 #define ELF_RELOC_RELA 2 /* Relocation offset for some architectures */ extern uint64_t __elfN(relocation_offset); struct elf_file; typedef Elf_Addr (symaddr_fn)(struct elf_file *ef, Elf_Size symidx); int __elfN(loadfile)(char *filename, uint64_t dest, struct preloaded_file **result); int __elfN(obj_loadfile)(char *filename, uint64_t dest, struct preloaded_file **result); int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, int reltype, Elf_Addr relbase, Elf_Addr dataaddr, void *data, size_t len); int __elfN(loadfile_raw)(char *filename, uint64_t dest, struct preloaded_file **result, int multiboot); int __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest); #endif /* * Support for commands */ struct bootblk_command { const char *c_name; const char *c_desc; bootblk_cmd_t *c_fn; }; #define COMMAND_SET(tag, key, desc, func) \ static bootblk_cmd_t func; \ static struct bootblk_command _cmd_ ## tag = { key, desc, func }; \ DATA_SET(Xcommand_set, _cmd_ ## tag) SET_DECLARE(Xcommand_set, struct bootblk_command); /* * The intention of the architecture switch is to provide a convenient * encapsulation of the interface between the bootstrap MI and MD code. * MD code may selectively populate the switch at runtime based on the * actual configuration of the target system. */ struct arch_switch { /* Automatically load modules as required by detected hardware */ int (*arch_autoload)(void); /* Locate the device for (name), return pointer to tail in (*path) */ int (*arch_getdev)(void **dev, const char *name, const char **path); /* Copy from local address space to module address space, similar to bcopy() */ ssize_t (*arch_copyin)(const void *src, vm_offset_t dest, const size_t len); /* Copy to local address space from module address space, similar to bcopy() */ ssize_t (*arch_copyout)(const vm_offset_t src, void *dest, const size_t len); /* Read from file to module address space, same semantics as read() */ ssize_t (*arch_readin)(readin_handle_t fd, vm_offset_t dest, const size_t len); /* Perform ISA byte port I/O (only for systems with ISA) */ int (*arch_isainb)(int port); void (*arch_isaoutb)(int port, int value); /* * Interface to adjust the load address according to the "object" * being loaded. */ uint64_t (*arch_loadaddr)(u_int type, void *data, uint64_t addr); #define LOAD_ELF 1 /* data points to the ELF header. */ #define LOAD_RAW 2 /* data points to the file name. */ /* * Interface to inform MD code about a loaded (ELF) segment. This * can be used to flush caches and/or set up translations. */ #ifdef __elfN void (*arch_loadseg)(Elf_Ehdr *eh, Elf_Phdr *ph, uint64_t delta); #else void (*arch_loadseg)(void *eh, void *ph, uint64_t delta); #endif /* Probe ZFS pool(s), if needed. */ void (*arch_zfs_probe)(void); /* Return the hypervisor name/type or NULL if not virtualized. */ const char *(*arch_hypervisor)(void); /* For kexec-type loaders, get ksegment structure */ void (*arch_kexec_kseg_get)(int *nseg, void **kseg); }; extern struct arch_switch archsw; /* This must be provided by the MD code, but should it be in the archsw? */ void delay(int delay); void dev_cleanup(void); #ifndef CTASSERT #define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") #endif #endif /* !_BOOTSTRAP_H_ */ Index: head/stand/common/misc.c =================================================================== --- head/stand/common/misc.c (revision 364964) +++ head/stand/common/misc.c (revision 364965) @@ -1,221 +1,181 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include /* * Concatenate the (argc) elements of (argv) into a single string, and return * a copy of same. */ char * unargv(int argc, char *argv[]) { size_t hlong; int i; char *cp; for (i = 0, hlong = 0; i < argc; i++) hlong += strlen(argv[i]) + 2; if(hlong == 0) return(NULL); cp = malloc(hlong); cp[0] = 0; for (i = 0; i < argc; i++) { strcat(cp, argv[i]); if (i < (argc - 1)) strcat(cp, " "); } return(cp); } /* * Get the length of a string in kernel space */ size_t strlenout(vm_offset_t src) { char c; size_t len; for (len = 0; ; len++) { archsw.arch_copyout(src++, &c, 1); if (c == 0) break; } return(len); } /* * Make a duplicate copy of a string in kernel space */ char * strdupout(vm_offset_t str) { char *result, *cp; result = malloc(strlenout(str) + 1); for (cp = result; ;cp++) { archsw.arch_copyout(str++, cp, 1); if (*cp == 0) break; } return(result); } /* Zero a region in kernel space. */ void kern_bzero(vm_offset_t dest, size_t len) { char buf[256]; size_t chunk, resid; bzero(buf, sizeof(buf)); resid = len; while (resid > 0) { chunk = min(sizeof(buf), resid); archsw.arch_copyin(buf, dest, chunk); resid -= chunk; dest += chunk; } } /* * Read the specified part of a file to kernel space. Unlike regular * pread, the file pointer is advanced to the end of the read data, * and it just returns 0 if successful. */ int kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off) { if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) { #ifdef DEBUG printf("\nlseek failed\n"); #endif return (-1); } if ((size_t)archsw.arch_readin(fd, dest, len) != len) { #ifdef DEBUG printf("\nreadin failed\n"); #endif return (-1); } return (0); } /* * Read the specified part of a file to a malloced buffer. The file * pointer is advanced to the end of the read data. */ /* coverity[ -tainted_data_return ] */ void * alloc_pread(readin_handle_t fd, off_t off, size_t len) { void *buf; buf = malloc(len); if (buf == NULL) { #ifdef DEBUG printf("\nmalloc(%d) failed\n", (int)len); #endif errno = ENOMEM; return (NULL); } if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) { #ifdef DEBUG printf("\nlseek failed\n"); #endif free(buf); return (NULL); } if ((size_t)VECTX_READ(fd, buf, len) != len) { #ifdef DEBUG printf("\nread failed\n"); #endif free(buf); return (NULL); } return (buf); } -/* - * Display a region in traditional hexdump format. - */ -void -hexdump(caddr_t region, size_t len) -{ - caddr_t line; - int x, c; - char lbuf[80]; -#define emit(fmt, args...) {sprintf(lbuf, fmt , ## args); pager_output(lbuf);} - - pager_open(); - for (line = region; line < (region + len); line += 16) { - emit("%08lx ", (long) line); - - for (x = 0; x < 16; x++) { - if ((line + x) < (region + len)) { - emit("%02x ", *(uint8_t *)(line + x)); - } else { - emit("-- "); - } - if (x == 7) - emit(" "); - } - emit(" |"); - for (x = 0; x < 16; x++) { - if ((line + x) < (region + len)) { - c = *(uint8_t *)(line + x); - if ((c < ' ') || (c > '~')) /* !isprint(c) */ - c = '.'; - emit("%c", c); - } else { - emit(" "); - } - } - emit("|\n"); - } - pager_close(); -} - void dev_cleanup(void) { int i; /* Call cleanup routines */ for (i = 0; devsw[i] != NULL; ++i) if (devsw[i]->dv_cleanup != NULL) (devsw[i]->dv_cleanup)(); } Index: head/stand/libsa/Makefile =================================================================== --- head/stand/libsa/Makefile (revision 364964) +++ head/stand/libsa/Makefile (revision 364965) @@ -1,187 +1,188 @@ # $FreeBSD$ # Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $ # # Notes: # - We don't use the libc strerror/sys_errlist because the string table is # quite large. # .include LIBSA_CPUARCH?=${MACHINE_CPUARCH} LIB?= sa # standalone components and stuff we have modified locally -SRCS+= gzguts.h zutil.h __main.c abort.c assert.c bcd.c environment.c getopt.c gets.c \ - globals.c pager.c panic.c printf.c strdup.c strerror.c \ +SRCS+= gzguts.h zutil.h __main.c abort.c assert.c bcd.c environment.c \ + getopt.c gets.c globals.c \ + hexdump.c pager.c panic.c printf.c strdup.c strerror.c \ random.c sbrk.c twiddle.c zalloc.c zalloc_malloc.c # private (pruned) versions of libc string functions SRCS+= strcasecmp.c .PATH: ${LIBCSRC}/net SRCS+= ntoh.c # string functions from libc .PATH: ${LIBCSRC}/string SRCS+= bcmp.c bcopy.c bzero.c ffs.c fls.c \ memccpy.c memchr.c memcmp.c memcpy.c memmove.c memset.c \ strcat.c strchr.c strcmp.c strcpy.c stpcpy.c stpncpy.c \ strcspn.c strlcat.c strlcpy.c strlen.c strncat.c strncmp.c strncpy.c \ strnlen.c strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c # stdlib functions from libc .PATH: ${LIBCSRC}/stdlib SRCS+= abs.c strtol.c strtoll.c strtoul.c strtoull.c # common boot code .PATH: ${SYSDIR}/kern SRCS+= subr_boot.c .if ${MACHINE_CPUARCH} == "arm" .PATH: ${LIBCSRC}/arm/gen # Do not generate movt/movw, because the relocation fixup for them does not # translate to the -Bsymbolic -pie format required by self_reloc() in loader(8). # Also, the fpu is not available in a standalone environment. CFLAGS.clang+= -mno-movt CFLAGS.clang+= -mfpu=none .PATH: ${SRCTOP}/contrib/llvm-project/compiler-rt/lib/builtins/arm/ SRCS+= aeabi_idivmod.S aeabi_ldivmod.S aeabi_uidivmod.S aeabi_uldivmod.S SRCS+= aeabi_memcmp.S aeabi_memcpy.S aeabi_memmove.S aeabi_memset.S .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "riscv" .PATH: ${LIBCSRC}/${MACHINE_CPUARCH}/gen .endif # Compiler support functions .PATH: ${SRCTOP}/contrib/llvm-project/compiler-rt/lib/builtins/ # __clzsi2 and ctzsi2 for various builtin functions SRCS+= clzsi2.c ctzsi2.c # Divide and modulus functions called by the compiler SRCS+= divmoddi4.c divmodsi4.c divdi3.c divsi3.c moddi3.c modsi3.c SRCS+= udivmoddi4.c udivmodsi4.c udivdi3.c udivsi3.c umoddi3.c umodsi3.c SRCS+= ashldi3.c ashrdi3.c lshrdi3.c .if ${MACHINE_CPUARCH:Namd64:Ni386} == "" .PATH: ${SASRC}/x86 SRCS+= hypervisor.c .endif .if ${MACHINE_CPUARCH} == "powerpc" SRCS+= syncicache.c .endif # uuid functions from libc .PATH: ${LIBCSRC}/uuid SRCS+= uuid_create_nil.c uuid_equal.c uuid_from_string.c uuid_is_nil.c uuid_to_string.c # _setjmp/_longjmp .PATH: ${SASRC}/${LIBSA_CPUARCH} SRCS+= _setjmp.S # decompression functionality from libbz2 # NOTE: to actually test this functionality after libbz2 upgrade compile # loader(8) with LOADER_BZIP2_SUPPORT defined .PATH: ${SRCTOP}/contrib/bzip2 CFLAGS+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS SRCS+=bzlib.c crctable.c decompress.c huffman.c randtable.c # decompression functionality from zlib .PATH: ${SRCTOP}/sys/contrib/zlib CFLAGS+=-DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib SRCS+= adler32.c crc32.c SRCS+= infback.c inffast.c inflate.c inftrees.c zutil.c # lz4 decompression functionality .PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4 SRCS+= lz4.c CFLAGS.lz4.c+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4 # Create a subset of includes that are safe, as well as adjusting those that aren't # The lists may drive people nuts, but they are explicitly opt-in FAKE_DIRS=xlocale arpa SAFE_INCS=a.out.h assert.h elf.h limits.h nlist.h setjmp.h stddef.h stdbool.h string.h strings.h time.h unistd.h uuid.h STAND_H_INC=ctype.h fcntl.h signal.h stdio.h stdlib.h OTHER_INC=stdarg.h errno.h stdint.h beforedepend: mkdir -p ${FAKE_DIRS}; \ for i in ${SAFE_INCS}; do \ ln -sf ${SRCTOP}/include/$$i $$i; \ done; \ ln -sf ${SYSDIR}/${MACHINE}/include/stdarg.h stdarg.h; \ ln -sf ${SYSDIR}/sys/errno.h errno.h; \ ln -sf ${SYSDIR}/sys/stdint.h stdint.h; \ ln -sf ${SRCTOP}/include/arpa/inet.h arpa/inet.h; \ ln -sf ${SRCTOP}/include/arpa/tftp.h arpa/tftp.h; \ for i in _time.h _strings.h _string.h; do \ [ -f xlocale/$$i ] || cp /dev/null xlocale/$$i; \ done; \ for i in ${STAND_H_INC}; do \ ln -sf ${SASRC}/stand.h $$i; \ done CLEANDIRS+=${FAKE_DIRS} CLEANFILES+= ${SAFE_INCS} ${STAND_H_INC} ${OTHER_INC} # io routines SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \ fstat.c close.c lseek.c open.c read.c write.c readdir.c # SMBios routines SRCS+= smbios.c .if !defined(BOOT_HIDE_SERIAL_NUMBERS) # Export serial numbers, UUID, and asset tag from loader. CFLAGS.smbios.c+= -DSMBIOS_SERIAL_NUMBERS .if defined(BOOT_LITTLE_ENDIAN_UUID) # Use little-endian UUID format as defined in SMBIOS 2.6. CFLAGS.smbios.c+= -DSMBIOS_LITTLE_ENDIAN_UUID .elif defined(BOOT_NETWORK_ENDIAN_UUID) # Use network-endian UUID format for backward compatibility. CFLAGS.smbios.c+= -DSMBIOS_NETWORK_ENDIAN_UUID .endif .endif # network routines SRCS+= arp.c ether.c ip.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c # network info services: SRCS+= bootp.c rarp.c bootparam.c # boot filesystems SRCS+= ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c SRCS+= dosfs.c ext2fs.c SRCS+= splitfs.c SRCS+= pkgfs.c # kernel ufs support .PATH: ${SRCTOP}/sys/ufs/ffs SRCS+=ffs_subr.c ffs_tables.c CFLAGS.bzipfs.c+= -I${SRCTOP}/contrib/bzip2 # explicit_bzero and calculate_crc32c .PATH: ${SYSDIR}/libkern SRCS+= explicit_bzero.c crc32_libkern.c # Maybe GELI .if ${MK_LOADER_GELI} == "yes" .include "${SASRC}/geli/Makefile.inc" .endif .if ${MK_LOADER_VERIEXEC} == "yes" && ${MK_BEARSSL} == "yes" .include "${SRCTOP}/lib/libbearssl/Makefile.libsa.inc" .include "${SRCTOP}/lib/libsecureboot/Makefile.libsa.inc" .endif # Maybe ZFS .if ${MK_LOADER_ZFS} == "yes" .include "${SASRC}/zfs/Makefile.inc" .endif .include Index: head/stand/libsa/hexdump.c =================================================================== --- head/stand/libsa/hexdump.c (nonexistent) +++ head/stand/libsa/hexdump.c (revision 364965) @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 1998 Michael Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +/* + * Display a region in traditional hexdump format. + */ +void +hexdump(caddr_t region, size_t len) +{ + caddr_t line; + int x, c; +#ifdef HEXDUMP_PAGER + /* pager causes linking issues for some apps */ +#define emit(fmt, args...) {sprintf(lbuf, fmt , ## args); pager_output(lbuf);} + char lbuf[80]; + + pager_open(); +#else +#define emit(fmt, args...) printf(fmt, ## args) +#endif + + for (line = region; line < (region + len); line += 16) { + emit("%08lx ", (long) line); + + for (x = 0; x < 16; x++) { + if ((line + x) < (region + len)) { + emit("%02x ", *(uint8_t *)(line + x)); + } else { + emit("-- "); + } + if (x == 7) + emit(" "); + } + emit(" |"); + for (x = 0; x < 16; x++) { + if ((line + x) < (region + len)) { + c = *(uint8_t *)(line + x); + if ((c < ' ') || (c > '~')) /* !isprint(c) */ + c = '.'; + emit("%c", c); + } else { + emit(" "); + } + } + emit("|\n"); + } +#ifdef HEXDUMP_PAGER + pager_close(); +#endif +} Property changes on: head/stand/libsa/hexdump.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/stand/libsa/pkgfs.c =================================================================== --- head/stand/libsa/pkgfs.c (revision 364964) +++ head/stand/libsa/pkgfs.c (revision 364965) @@ -1,822 +1,822 @@ /*- * Copyright (c) 2007-2014, Juniper Networks, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "stand.h" #include #include #include #include #ifdef PKGFS_DEBUG #define DBG(x) printf x #else #define DBG(x) #endif static int pkg_open(const char *, struct open_file *); static int pkg_close(struct open_file *); static int pkg_read(struct open_file *, void *, size_t, size_t *); static off_t pkg_seek(struct open_file *, off_t, int); static int pkg_stat(struct open_file *, struct stat *); static int pkg_readdir(struct open_file *, struct dirent *); static off_t pkg_atol(const char *, unsigned); struct fs_ops pkgfs_fsops = { "pkg", pkg_open, pkg_close, pkg_read, null_write, pkg_seek, pkg_stat, pkg_readdir }; #define PKG_BUFSIZE 512 -#define PKG_MAXCACHESZ (16384 * 3) +#define PKG_MAXCACHESZ (512 * 1024) #define PKG_FILEEXT ".tgz" /* * Layout of POSIX 'ustar' header. */ struct ustar_hdr { char ut_name[100]; char ut_mode[8]; char ut_uid[8]; char ut_gid[8]; char ut_size[12]; char ut_mtime[12]; char ut_checksum[8]; char ut_typeflag[1]; char ut_linkname[100]; char ut_magic[6]; /* For POSIX: "ustar\0" */ char ut_version[2]; /* For POSIX: "00" */ char ut_uname[32]; char ut_gname[32]; char ut_rdevmajor[8]; char ut_rdevminor[8]; union { struct { char prefix[155]; } posix; struct { char atime[12]; char ctime[12]; char offset[12]; char longnames[4]; char unused[1]; struct gnu_sparse { char offset[12]; char numbytes[12]; } sparse[4]; char isextended[1]; char realsize[12]; } gnu; } u; u_char __padding[12]; }; struct package; struct tarfile { struct package *tf_pkg; struct tarfile *tf_next; struct ustar_hdr tf_hdr; off_t tf_ofs; off_t tf_size; off_t tf_fp; size_t tf_cachesz; void *tf_cache; }; struct package { struct package *pkg_chain; int pkg_fd; off_t pkg_ofs; z_stream pkg_zs; struct tarfile *pkg_first; struct tarfile *pkg_last; u_char pkg_buf[PKG_BUFSIZE]; }; static struct package *package = NULL; static int new_package(int, struct package **); static int cache_data(struct tarfile *tf, int); void pkgfs_cleanup(void) { struct package *chain; struct tarfile *tf, *tfn; while (package != NULL) { inflateEnd(&package->pkg_zs); close(package->pkg_fd); tf = package->pkg_first; while (tf != NULL) { tfn = tf->tf_next; if (tf->tf_cachesz > 0) free(tf->tf_cache); free(tf); tf = tfn; } chain = package->pkg_chain; free(package); package = chain; } } int pkgfs_init(const char *pkgname, struct fs_ops *proto) { struct package *pkg; int error, fd; pkg = NULL; if (proto != &pkgfs_fsops) pkgfs_cleanup(); exclusive_file_system = proto; fd = open(pkgname, O_RDONLY); exclusive_file_system = NULL; if (fd == -1) return (errno); error = new_package(fd, &pkg); if (error) { close(fd); return (error); } if (pkg == NULL) return (EDOOFUS); pkg->pkg_chain = package; package = pkg; exclusive_file_system = &pkgfs_fsops; return (0); } static int get_mode(struct tarfile *); static int get_zipped(struct package *, void *, size_t); static int new_package(int, struct package **); static struct tarfile *scan_tarfile(struct package *, struct tarfile *); static int pkg_open(const char *fn, struct open_file *f) { struct tarfile *tf; if (fn == NULL || f == NULL) return (EINVAL); if (package == NULL) return (ENXIO); /* * We can only read from a package, so reject request to open * for write-only or read-write. */ if (f->f_flags != F_READ) return (EPERM); /* * Scan the file headers for the named file. We stop scanning * at the first filename that has the .pkg extension. This is * a package within a package. We assume we have all the files * we need up-front and without having to dig within nested * packages. * * Note that we preserve streaming properties as much as possible. */ while (*fn == '/') fn++; /* * Allow opening of the root directory for use by readdir() * to support listing files in the package. */ if (*fn == '\0') { f->f_fsdata = NULL; return (0); } tf = scan_tarfile(package, NULL); while (tf != NULL) { if (strcmp(fn, tf->tf_hdr.ut_name) == 0) { f->f_fsdata = tf; tf->tf_fp = 0; /* Reset the file pointer. */ return (0); } tf = scan_tarfile(package, tf); } return (errno); } static int pkg_close(struct open_file *f) { struct tarfile *tf; tf = (struct tarfile *)f->f_fsdata; if (tf == NULL) return (0); /* * Free up the cache if we read all of the file. */ if (tf->tf_fp == tf->tf_size && tf->tf_cachesz > 0) { free(tf->tf_cache); tf->tf_cachesz = 0; } return (0); } static int pkg_read(struct open_file *f, void *buf, size_t size, size_t *res) { struct tarfile *tf; char *p; off_t fp; size_t sz; tf = (struct tarfile *)f->f_fsdata; if (tf == NULL) { if (res != NULL) *res = size; return (EBADF); } if (tf->tf_cachesz == 0) cache_data(tf, 1); fp = tf->tf_fp; p = buf; sz = 0; while (size > 0) { sz = tf->tf_size - fp; if (fp < tf->tf_cachesz && tf->tf_cachesz < tf->tf_size) sz = tf->tf_cachesz - fp; if (size < sz) sz = size; if (sz == 0) break; if (fp < tf->tf_cachesz) { /* Satisfy the request from cache. */ memcpy(p, tf->tf_cache + fp, sz); fp += sz; p += sz; size -= sz; continue; } if (get_zipped(tf->tf_pkg, p, sz) == -1) { sz = -1; break; } fp += sz; p += sz; size -= sz; } tf->tf_fp = fp; if (res != NULL) *res = size; return ((sz == -1) ? errno : 0); } static off_t pkg_seek(struct open_file *f, off_t ofs, int whence) { char buf[512]; struct tarfile *tf; off_t delta; off_t nofs; size_t sz, res; int error; tf = (struct tarfile *)f->f_fsdata; if (tf == NULL) { errno = EBADF; return (-1); } switch (whence) { case SEEK_SET: delta = ofs - tf->tf_fp; break; case SEEK_CUR: delta = ofs; break; case SEEK_END: delta = tf->tf_size - tf->tf_fp + ofs; break; default: errno = EINVAL; return (-1); } if (delta < 0) { /* seeking backwards - ok if within cache */ if (tf->tf_cachesz > 0 && tf->tf_fp <= tf->tf_cachesz) { nofs = tf->tf_fp + delta; if (nofs >= 0) { tf->tf_fp = nofs; return (tf->tf_fp); } } DBG(("%s: negative file seek (%jd)\n", __func__, (intmax_t)delta)); errno = ESPIPE; return (-1); } while (delta > 0 && tf->tf_fp < tf->tf_size) { sz = (delta > sizeof(buf)) ? sizeof(buf) : delta; error = pkg_read(f, buf, sz, &res); if (error != 0) { errno = error; return (-1); } delta -= sz - res; } return (tf->tf_fp); } static int pkg_stat(struct open_file *f, struct stat *sb) { struct tarfile *tf; tf = (struct tarfile *)f->f_fsdata; if (tf == NULL) return (EBADF); memset(sb, 0, sizeof(*sb)); sb->st_mode = get_mode(tf); if ((sb->st_mode & S_IFMT) == 0) { /* tar file bug - assume regular file */ sb->st_mode |= S_IFREG; } sb->st_size = tf->tf_size; sb->st_blocks = (tf->tf_size + 511) / 512; sb->st_mtime = pkg_atol(tf->tf_hdr.ut_mtime, 12); sb->st_dev = (off_t)((uintptr_t)tf->tf_pkg); sb->st_ino = tf->tf_ofs; /* unique per tf_pkg */ return (0); } static int pkg_readdir(struct open_file *f, struct dirent *d) { struct tarfile *tf; tf = (struct tarfile *)f->f_fsdata; if (tf != NULL) return (EBADF); tf = scan_tarfile(package, NULL); if (tf == NULL) return (ENOENT); d->d_fileno = 0; d->d_reclen = sizeof(*d); d->d_type = DT_REG; memcpy(d->d_name, tf->tf_hdr.ut_name, sizeof(d->d_name)); return (0); } /* * Low-level support functions. */ static int get_byte(struct package *pkg, off_t *op) { int c; if (pkg->pkg_zs.avail_in == 0) { c = read(pkg->pkg_fd, pkg->pkg_buf, PKG_BUFSIZE); if (c <= 0) return (-1); pkg->pkg_zs.avail_in = c; pkg->pkg_zs.next_in = pkg->pkg_buf; } c = *pkg->pkg_zs.next_in; pkg->pkg_zs.next_in++; pkg->pkg_zs.avail_in--; (*op)++; return (c); } static int get_zipped(struct package *pkg, void *buf, size_t bufsz) { int c; pkg->pkg_zs.next_out = buf; pkg->pkg_zs.avail_out = bufsz; while (pkg->pkg_zs.avail_out) { if (pkg->pkg_zs.avail_in == 0) { c = read(pkg->pkg_fd, pkg->pkg_buf, PKG_BUFSIZE); if (c <= 0) { errno = EIO; return (-1); } pkg->pkg_zs.avail_in = c; pkg->pkg_zs.next_in = pkg->pkg_buf; } c = inflate(&pkg->pkg_zs, Z_SYNC_FLUSH); if (c != Z_OK && c != Z_STREAM_END) { errno = EIO; return (-1); } } pkg->pkg_ofs += bufsz; return (0); } /** * @brief * cache data of a tarfile * * @param[in] tf * tarfile pointer * * @param[in] force * If file size > PKG_MAXCACHESZ, cache that much * * @return 0, -1 (errno set to error value) */ static int cache_data(struct tarfile *tf, int force) { struct package *pkg; size_t sz; if (tf == NULL) { DBG(("%s: no file to cache data for?\n", __func__)); errno = EINVAL; return (-1); } pkg = tf->tf_pkg; if (pkg == NULL) { DBG(("%s: no package associated with file?\n", __func__)); errno = EINVAL; return (-1); } if (tf->tf_cachesz > 0) { DBG(("%s: data already cached\n", __func__)); errno = EINVAL; return (-1); } if (tf->tf_ofs != pkg->pkg_ofs) { DBG(("%s: caching after force read of file %s?\n", __func__, tf->tf_hdr.ut_name)); errno = EINVAL; return (-1); } /* We don't cache everything... */ if (tf->tf_size > PKG_MAXCACHESZ && !force) { errno = ENOBUFS; return (-1); } sz = tf->tf_size < PKG_MAXCACHESZ ? tf->tf_size : PKG_MAXCACHESZ; /* All files are padded to a multiple of 512 bytes. */ sz = (sz + 0x1ff) & ~0x1ff; tf->tf_cache = malloc(sz); if (tf->tf_cache == NULL) { DBG(("%s: could not allocate %d bytes\n", __func__, (int)sz)); errno = ENOMEM; return (-1); } tf->tf_cachesz = sz; return (get_zipped(pkg, tf->tf_cache, sz)); } /* * Note that this implementation does not (and should not!) obey * locale settings; you cannot simply substitute strtol here, since * it does obey locale. */ static off_t pkg_atol8(const char *p, unsigned char_cnt) { int64_t l, limit, last_digit_limit; int digit, sign, base; base = 8; limit = INT64_MAX / base; last_digit_limit = INT64_MAX % base; while (*p == ' ' || *p == '\t') p++; if (*p == '-') { sign = -1; p++; } else sign = 1; l = 0; digit = *p - '0'; while (digit >= 0 && digit < base && char_cnt-- > 0) { if (l>limit || (l == limit && digit > last_digit_limit)) { l = UINT64_MAX; /* Truncate on overflow. */ break; } l = (l * base) + digit; digit = *++p - '0'; } return (sign < 0) ? -l : l; } /* * Parse a base-256 integer. This is just a straight signed binary * value in big-endian order, except that the high-order bit is * ignored. Remember that "int64_t" may or may not be exactly 64 * bits; the implementation here tries to avoid making any assumptions * about the actual size of an int64_t. It does assume we're using * twos-complement arithmetic, though. */ static int64_t pkg_atol256(const char *_p, unsigned char_cnt) { int64_t l, upper_limit, lower_limit; const unsigned char *p = (const unsigned char *)_p; upper_limit = INT64_MAX / 256; lower_limit = INT64_MIN / 256; /* Pad with 1 or 0 bits, depending on sign. */ if ((0x40 & *p) == 0x40) l = (int64_t)-1; else l = 0; l = (l << 6) | (0x3f & *p++); while (--char_cnt > 0) { if (l > upper_limit) { l = INT64_MAX; /* Truncate on overflow */ break; } else if (l < lower_limit) { l = INT64_MIN; break; } l = (l << 8) | (0xff & (int64_t)*p++); } return (l); } static off_t pkg_atol(const char *p, unsigned char_cnt) { /* * Technically, GNU pkg considers a field to be in base-256 * only if the first byte is 0xff or 0x80. */ if (*p & 0x80) return (pkg_atol256(p, char_cnt)); return (pkg_atol8(p, char_cnt)); } static int get_mode(struct tarfile *tf) { return (pkg_atol(tf->tf_hdr.ut_mode, sizeof(tf->tf_hdr.ut_mode))); } /* GZip flag byte */ #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ #define COMMENT 0x10 /* bit 4 set: file comment present */ #define RESERVED 0xE0 /* bits 5..7: reserved */ static int new_package(int fd, struct package **pp) { struct package *pkg; off_t ofs; int flags, i, error; pkg = malloc(sizeof(*pkg)); if (pkg == NULL) return (ENOMEM); bzero(pkg, sizeof(*pkg)); pkg->pkg_fd = fd; /* * Parse the header. */ error = EFTYPE; ofs = 0; /* Check megic. */ if (get_byte(pkg, &ofs) != 0x1f || get_byte(pkg, &ofs) != 0x8b) goto fail; /* Check method. */ if (get_byte(pkg, &ofs) != Z_DEFLATED) goto fail; /* Check flags. */ flags = get_byte(pkg, &ofs); if (flags & RESERVED) goto fail; /* Skip time, xflags and OS code. */ for (i = 0; i < 6; i++) { if (get_byte(pkg, &ofs) == -1) goto fail; } /* Skip extra field. */ if (flags & EXTRA_FIELD) { i = (get_byte(pkg, &ofs) & 0xff) | ((get_byte(pkg, &ofs) << 8) & 0xff); while (i-- > 0) { if (get_byte(pkg, &ofs) == -1) goto fail; } } /* Skip original file name. */ if (flags & ORIG_NAME) { do { i = get_byte(pkg, &ofs); } while (i != 0 && i != -1); if (i == -1) goto fail; } /* Print the comment if it's there. */ if (flags & COMMENT) { while (1) { i = get_byte(pkg, &ofs); if (i == -1) goto fail; if (i == 0) break; putchar(i); } } /* Skip the CRC. */ if (flags & HEAD_CRC) { if (get_byte(pkg, &ofs) == -1) goto fail; if (get_byte(pkg, &ofs) == -1) goto fail; } /* * Done parsing the ZIP header. Spkgt the inflation engine. */ error = inflateInit2(&pkg->pkg_zs, -15); if (error != Z_OK) goto fail; *pp = pkg; return (0); fail: free(pkg); return (error); } static struct tarfile * scan_tarfile(struct package *pkg, struct tarfile *last) { char buf[512]; struct tarfile *cur; off_t ofs; size_t sz; cur = (last != NULL) ? last->tf_next : pkg->pkg_first; if (cur == NULL) { ofs = (last != NULL) ? last->tf_ofs + last->tf_size : pkg->pkg_ofs; ofs = (ofs + 0x1ff) & ~0x1ff; /* Check if we've reached EOF. */ if (ofs < pkg->pkg_ofs) { errno = ENOSPC; return (NULL); } if (ofs != pkg->pkg_ofs) { if (last != NULL && pkg->pkg_ofs == last->tf_ofs) { if (cache_data(last, 0) == -1) return (NULL); } else { sz = ofs - pkg->pkg_ofs; while (sz != 0) { if (sz > sizeof(buf)) sz = sizeof(buf); if (get_zipped(pkg, buf, sz) == -1) return (NULL); sz = ofs - pkg->pkg_ofs; } } } cur = malloc(sizeof(*cur)); if (cur == NULL) return (NULL); memset(cur, 0, sizeof(*cur)); cur->tf_pkg = pkg; while (1) { if (get_zipped(pkg, &cur->tf_hdr, sizeof(cur->tf_hdr)) == -1) { free(cur); return (NULL); } /* * There are always 2 empty blocks appended to * a PKG. It marks the end of the archive. */ if (strncmp(cur->tf_hdr.ut_magic, "ustar", 5) != 0) { free(cur); errno = ENOSPC; return (NULL); } cur->tf_ofs = pkg->pkg_ofs; cur->tf_size = pkg_atol(cur->tf_hdr.ut_size, sizeof(cur->tf_hdr.ut_size)); if (cur->tf_hdr.ut_name[0] != '+') break; /* * Skip package meta-files. */ ofs = cur->tf_ofs + cur->tf_size; ofs = (ofs + 0x1ff) & ~0x1ff; while (pkg->pkg_ofs < ofs) { if (get_zipped(pkg, buf, sizeof(buf)) == -1) { free(cur); return (NULL); } } } if (last != NULL) last->tf_next = cur; else pkg->pkg_first = cur; pkg->pkg_last = cur; } return (cur); } Index: head/stand/libsa/stand.h =================================================================== --- head/stand/libsa/stand.h (revision 364964) +++ head/stand/libsa/stand.h (revision 364965) @@ -1,473 +1,476 @@ /* * Copyright (c) 1998 Michael Smith. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * From $NetBSD: stand.h,v 1.22 1997/06/26 19:17:40 drochner Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)stand.h 8.1 (Berkeley) 6/11/93 */ #ifndef STAND_H #define STAND_H #include #include #include #include /* this header intentionally exports NULL from */ #include #define strcoll(a, b) strcmp((a), (b)) #define CHK(fmt, args...) printf("%s(%d): " fmt "\n", __func__, __LINE__ , ##args) #define PCHK(fmt, args...) {printf("%s(%d): " fmt "\n", __func__, __LINE__ , ##args); getchar();} #include /* special stand error codes */ #define EADAPT (ELAST+1) /* bad adaptor */ #define ECTLR (ELAST+2) /* bad controller */ #define EUNIT (ELAST+3) /* bad unit */ #define ESLICE (ELAST+4) /* bad slice */ #define EPART (ELAST+5) /* bad partition */ #define ERDLAB (ELAST+6) /* can't read disk label */ #define EUNLAB (ELAST+7) /* unlabeled disk */ #define EOFFSET (ELAST+8) /* relative seek not supported */ #define ESALAST (ELAST+8) /* */ /* Partial signal emulation for sig_atomic_t */ #include struct open_file; /* * This structure is used to define file system operations in a file system * independent way. * * XXX note that filesystem providers should export a pointer to their fs_ops * struct, so that consumers can reference this and thus include the * filesystems that they require. */ struct fs_ops { const char *fs_name; int (*fo_open)(const char *path, struct open_file *f); int (*fo_close)(struct open_file *f); int (*fo_read)(struct open_file *f, void *buf, size_t size, size_t *resid); int (*fo_write)(struct open_file *f, const void *buf, size_t size, size_t *resid); off_t (*fo_seek)(struct open_file *f, off_t offset, int where); int (*fo_stat)(struct open_file *f, struct stat *sb); int (*fo_readdir)(struct open_file *f, struct dirent *d); }; /* * libstand-supplied filesystems */ extern struct fs_ops ufs_fsops; extern struct fs_ops tftp_fsops; extern struct fs_ops nfs_fsops; extern struct fs_ops cd9660_fsops; extern struct fs_ops gzipfs_fsops; extern struct fs_ops bzipfs_fsops; extern struct fs_ops dosfs_fsops; extern struct fs_ops ext2fs_fsops; extern struct fs_ops splitfs_fsops; extern struct fs_ops pkgfs_fsops; extern struct fs_ops efihttp_fsops; /* where values for lseek(2) */ #define SEEK_SET 0 /* set file offset to offset */ #define SEEK_CUR 1 /* set file offset to current plus offset */ #define SEEK_END 2 /* set file offset to EOF plus offset */ /* * Device switch */ struct devsw { const char dv_name[8]; int dv_type; /* opaque type constant, arch-dependant */ #define DEVT_NONE 0 #define DEVT_DISK 1 #define DEVT_NET 2 #define DEVT_CD 3 #define DEVT_ZFS 4 #define DEVT_FD 5 int (*dv_init)(void); /* early probe call */ int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize); int (*dv_open)(struct open_file *f, ...); int (*dv_close)(struct open_file *f); int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data); int (*dv_print)(int verbose); /* print device information */ void (*dv_cleanup)(void); }; /* * libstand-supplied device switch */ extern struct devsw netdev; extern int errno; /* * Generic device specifier; architecture-dependent * versions may be larger, but should be allowed to * overlap. */ struct devdesc { struct devsw *d_dev; int d_unit; void *d_opendata; }; struct open_file { int f_flags; /* see F_* below */ struct devsw *f_dev; /* pointer to device operations */ void *f_devdata; /* device specific data */ struct fs_ops *f_ops; /* pointer to file system operations */ void *f_fsdata; /* file system specific data */ off_t f_offset; /* current file offset */ char *f_rabuf; /* readahead buffer pointer */ size_t f_ralen; /* valid data in readahead buffer */ off_t f_raoffset; /* consumer offset in readahead buffer */ #define SOPEN_RASIZE 512 }; #define SOPEN_MAX 64 extern struct open_file files[]; /* f_flags values */ #define F_READ 0x0001 /* file opened for reading */ #define F_WRITE 0x0002 /* file opened for writing */ #define F_RAW 0x0004 /* raw device open - no file system */ #define F_NODEV 0x0008 /* network open - no device */ #define F_MASK 0xFFFF /* Mode modifier for strategy() */ #define F_NORA (0x01 << 16) /* Disable Read-Ahead */ #define isascii(c) (((c) & ~0x7F) == 0) static __inline int isupper(int c) { return c >= 'A' && c <= 'Z'; } static __inline int islower(int c) { return c >= 'a' && c <= 'z'; } static __inline int isspace(int c) { return c == ' ' || (c >= 0x9 && c <= 0xd); } static __inline int isdigit(int c) { return c >= '0' && c <= '9'; } static __inline int isxdigit(int c) { return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } static __inline int isalpha(int c) { return isupper(c) || islower(c); } static __inline int isalnum(int c) { return isalpha(c) || isdigit(c); } static __inline int iscntrl(int c) { return (c >= 0 && c < ' ') || c == 127; } static __inline int isgraph(int c) { return c >= '!' && c <= '~'; } static __inline int ispunct(int c) { return (c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~'); } static __inline int toupper(int c) { return islower(c) ? c - 'a' + 'A' : c; } static __inline int tolower(int c) { return isupper(c) ? c - 'A' + 'a' : c; } /* sbrk emulation */ extern void setheap(void *base, void *top); extern char *sbrk(int incr); extern int printf(const char *fmt, ...) __printflike(1, 2); extern int asprintf(char **buf, const char *cfmt, ...) __printflike(2, 3); extern int sprintf(char *buf, const char *cfmt, ...) __printflike(2, 3); extern int snprintf(char *buf, size_t size, const char *cfmt, ...) __printflike(3, 4); extern int vprintf(const char *fmt, __va_list); extern int vsprintf(char *buf, const char *cfmt, __va_list); extern int vsnprintf(char *buf, size_t size, const char *cfmt, __va_list); extern void twiddle(u_int callerdiv); extern void twiddle_divisor(u_int globaldiv); extern void ngets(char *, int); #define gets(x) ngets((x), 0) extern int fgetstr(char *buf, int size, int fd); extern int open(const char *, int); #define O_RDONLY 0x0 #define O_WRONLY 0x1 #define O_RDWR 0x2 #define O_ACCMODE 0x3 /* NOT IMPLEMENTED */ #define O_CREAT 0x0200 /* create if nonexistent */ #define O_TRUNC 0x0400 /* truncate to zero length */ extern int close(int); extern void closeall(void); extern ssize_t read(int, void *, size_t); extern ssize_t write(int, const void *, size_t); extern struct dirent *readdirfd(int); extern void srandom(unsigned int); extern long random(void); /* imports from stdlib, locally modified */ extern char *optarg; /* getopt(3) external variables */ extern int optind, opterr, optopt, optreset; extern int getopt(int, char * const [], const char *); /* pager.c */ extern void pager_open(void); extern void pager_close(void); extern int pager_output(const char *lines); extern int pager_file(const char *fname); /* No signal state to preserve */ #define setjmp _setjmp #define longjmp _longjmp /* environment.c */ #define EV_DYNAMIC (1<<0) /* value was dynamically allocated, free if changed/unset */ #define EV_VOLATILE (1<<1) /* value is volatile, make a copy of it */ #define EV_NOHOOK (1<<2) /* don't call hook when setting */ struct env_var; typedef char *(ev_format_t)(struct env_var *ev); typedef int (ev_sethook_t)(struct env_var *ev, int flags, const void *value); typedef int (ev_unsethook_t)(struct env_var *ev); struct env_var { char *ev_name; int ev_flags; void *ev_value; ev_sethook_t *ev_sethook; ev_unsethook_t *ev_unsethook; struct env_var *ev_next, *ev_prev; }; extern struct env_var *environ; extern struct env_var *env_getenv(const char *name); extern int env_setenv(const char *name, int flags, const void *value, ev_sethook_t sethook, ev_unsethook_t unsethook); extern void env_discard(struct env_var *); extern char *getenv(const char *name); extern int setenv(const char *name, const char *value, int overwrite); extern int putenv(char *string); extern int unsetenv(const char *name); extern ev_sethook_t env_noset; /* refuse set operation */ extern ev_unsethook_t env_nounset; /* refuse unset operation */ /* stdlib.h routines */ extern int abs(int a); extern void abort(void) __dead2; extern long strtol(const char * __restrict, char ** __restrict, int); extern long long strtoll(const char * __restrict, char ** __restrict, int); extern unsigned long strtoul(const char * __restrict, char ** __restrict, int); extern unsigned long long strtoull(const char * __restrict, char ** __restrict, int); /* BCD conversions (undocumented) */ extern u_char const bcd2bin_data[]; extern u_char const bin2bcd_data[]; extern char const hex2ascii_data[]; #define bcd2bin(bcd) (bcd2bin_data[bcd]) #define bin2bcd(bin) (bin2bcd_data[bin]) #define hex2ascii(hex) (hex2ascii_data[hex]) #define validbcd(bcd) (bcd == 0 || (bcd > 0 && bcd <= 0x99 && bcd2bin_data[bcd] != 0)) /* min/max (undocumented) */ static __inline int imax(int a, int b) { return (a > b ? a : b); } static __inline int imin(int a, int b) { return (a < b ? a : b); } static __inline long lmax(long a, long b) { return (a > b ? a : b); } static __inline long lmin(long a, long b) { return (a < b ? a : b); } static __inline u_int max(u_int a, u_int b) { return (a > b ? a : b); } static __inline u_int min(u_int a, u_int b) { return (a < b ? a : b); } static __inline quad_t qmax(quad_t a, quad_t b) { return (a > b ? a : b); } static __inline quad_t qmin(quad_t a, quad_t b) { return (a < b ? a : b); } static __inline u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); } static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); } /* null functions for device/filesystem switches (undocumented) */ extern int nodev(void); extern int noioctl(struct open_file *, u_long, void *); extern void nullsys(void); extern int null_open(const char *path, struct open_file *f); extern int null_close(struct open_file *f); extern int null_read(struct open_file *f, void *buf, size_t size, size_t *resid); extern int null_write(struct open_file *f, const void *buf, size_t size, size_t *resid); extern off_t null_seek(struct open_file *f, off_t offset, int where); extern int null_stat(struct open_file *f, struct stat *sb); extern int null_readdir(struct open_file *f, struct dirent *d); /* * Machine dependent functions and data, must be provided or stubbed by * the consumer */ extern void exit(int) __dead2; extern int getchar(void); extern int ischar(void); extern void putchar(int); extern int devopen(struct open_file *, const char *, const char **); extern int devclose(struct open_file *f); extern void panic(const char *, ...) __dead2 __printflike(1, 2); extern void panic_action(void) __weak_symbol __dead2; extern time_t getsecs(void); extern struct fs_ops *file_system[]; extern struct fs_ops *exclusive_file_system; extern struct devsw *devsw[]; /* * Time routines */ time_t time(time_t *); /* * Expose byteorder(3) functions. */ #ifndef _BYTEORDER_PROTOTYPED #define _BYTEORDER_PROTOTYPED extern uint32_t htonl(uint32_t); extern uint16_t htons(uint16_t); extern uint32_t ntohl(uint32_t); extern uint16_t ntohs(uint16_t); #endif #ifndef _BYTEORDER_FUNC_DEFINED #define _BYTEORDER_FUNC_DEFINED #define htonl(x) __htonl(x) #define htons(x) __htons(x) #define ntohl(x) __ntohl(x) #define ntohs(x) __ntohs(x) #endif void *Malloc(size_t, const char *, int); void *Memalign(size_t, size_t, const char *, int); void *Calloc(size_t, size_t, const char *, int); void *Realloc(void *, size_t, const char *, int); void *Reallocf(void *, size_t, const char *, int); void Free(void *, const char *, int); extern void mallocstats(void); const char *x86_hypervisor(void); #ifdef USER_MALLOC extern void *malloc(size_t); extern void *memalign(size_t, size_t); extern void *calloc(size_t, size_t); extern void free(void *); extern void *realloc(void *, size_t); extern void *reallocf(void *, size_t); #elif defined(DEBUG_MALLOC) #define malloc(x) Malloc(x, __FILE__, __LINE__) #define memalign(x, y) Memalign(x, y, __FILE__, __LINE__) #define calloc(x, y) Calloc(x, y, __FILE__, __LINE__) #define free(x) Free(x, __FILE__, __LINE__) #define realloc(x, y) Realloc(x, y, __FILE__, __LINE__) #define reallocf(x, y) Reallocf(x, y, __FILE__, __LINE__) #else #define malloc(x) Malloc(x, NULL, 0) #define memalign(x, y) Memalign(x, y, NULL, 0) #define calloc(x, y) Calloc(x, y, NULL, 0) #define free(x) Free(x, NULL, 0) #define realloc(x, y) Realloc(x, y, NULL, 0) #define reallocf(x, y) Reallocf(x, y, NULL, 0) #endif /* * va <-> pa routines. MD code must supply. */ caddr_t ptov(uintptr_t); +/* hexdump.c */ +void hexdump(caddr_t region, size_t len); + #endif /* STAND_H */ Index: head/stand/libsa/zalloc_malloc.c =================================================================== --- head/stand/libsa/zalloc_malloc.c (revision 364964) +++ head/stand/libsa/zalloc_malloc.c (revision 364965) @@ -1,223 +1,232 @@ /* * This module derived from code donated to the FreeBSD Project by * Matthew Dillon * * Copyright (c) 1998 The FreeBSD Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * MALLOC.C - malloc equivalent, runs on top of zalloc and uses sbrk */ #include "zalloc_defs.h" static MemPool MallocPool; #ifdef DMALLOCDEBUG static int MallocMax; static int MallocCount; void mallocstats(void); #endif #ifdef malloc #undef malloc #undef free #endif static void *Malloc_align(size_t, size_t); +#ifndef MIN +# define MIN(a,b) ((a) <= (b)) ? (a) : (b) +#endif + void * Malloc(size_t bytes, const char *file __unused, int line __unused) { return (Malloc_align(bytes, 1)); } void * Memalign(size_t alignment, size_t bytes, const char *file __unused, int line __unused) { if (alignment == 0) alignment = 1; return (Malloc_align(bytes, alignment)); } static void * Malloc_align(size_t bytes, size_t alignment) { Guard *res; #ifdef USEENDGUARD bytes += MALLOCALIGN + 1; #else bytes += MALLOCALIGN; #endif while ((res = znalloc(&MallocPool, bytes, alignment)) == NULL) { int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK; char *base; if ((base = sbrk(incr)) == (char *)-1) return (NULL); zextendPool(&MallocPool, base, incr); zfree(&MallocPool, base, incr); } #ifdef DMALLOCDEBUG if (++MallocCount > MallocMax) MallocMax = MallocCount; #endif #ifdef USEGUARD res->ga_Magic = GAMAGIC; #endif res->ga_Bytes = bytes; #ifdef USEENDGUARD *((signed char *)res + bytes - 1) = -2; #endif return ((char *)res + MALLOCALIGN); } void Free(void *ptr, const char *file, int line) { size_t bytes; if (ptr != NULL) { Guard *res = (void *)((char *)ptr - MALLOCALIGN); if (file == NULL) file = "unknown"; #ifdef USEGUARD if (res->ga_Magic == GAFREE) { printf("free: duplicate free @ %p from %s:%d\n", ptr, file, line); return; } - if (res->ga_Magic != GAMAGIC) + if (res->ga_Magic != GAMAGIC) { + size_t dump_bytes; + + dump_bytes = MIN((ptr - MallocPool.mp_Base), 512); + hexdump(ptr - dump_bytes, dump_bytes); panic("free: guard1 fail @ %p from %s:%d", ptr, file, line); + } res->ga_Magic = GAFREE; #endif #ifdef USEENDGUARD if (*((signed char *)res + res->ga_Bytes - 1) == -1) { printf("free: duplicate2 free @ %p from %s:%d\n", ptr, file, line); return; } if (*((signed char *)res + res->ga_Bytes - 1) != -2) panic("free: guard2 fail @ %p + %zu from %s:%d", ptr, res->ga_Bytes - MALLOCALIGN, file, line); *((signed char *)res + res->ga_Bytes - 1) = -1; #endif bytes = res->ga_Bytes; zfree(&MallocPool, res, bytes); #ifdef DMALLOCDEBUG --MallocCount; #endif } } void * Calloc(size_t n1, size_t n2, const char *file, int line) { uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2; void *res; if ((res = Malloc(bytes, file, line)) != NULL) { bzero(res, bytes); #ifdef DMALLOCDEBUG if (++MallocCount > MallocMax) MallocMax = MallocCount; #endif } return (res); } /* * realloc() - I could be fancier here and free the old buffer before * allocating the new one (saving potential fragmentation * and potential buffer copies). But I don't bother. */ void * Realloc(void *ptr, size_t size, const char *file, int line) { void *res; size_t old; if ((res = Malloc(size, file, line)) != NULL) { if (ptr != NULL) { Guard *g = (Guard *)((char *)ptr - MALLOCALIGN); old = g->ga_Bytes - MALLOCALIGN; if (old < size) bcopy(ptr, res, old); else bcopy(ptr, res, size); Free(ptr, file, line); } else { #ifdef DMALLOCDEBUG if (++MallocCount > MallocMax) MallocMax = MallocCount; #ifdef EXITSTATS if (DidAtExit == 0) { DidAtExit = 1; atexit(mallocstats); } #endif #endif } } return (res); } void * Reallocf(void *ptr, size_t size, const char *file, int line) { void *res; if ((res = Realloc(ptr, size, file, line)) == NULL) Free(ptr, file, line); return (res); } #ifdef DMALLOCDEBUG void mallocstats(void) { printf("Active Allocations: %d/%d\n", MallocCount, MallocMax); #ifdef ZALLOCDEBUG zallocstats(&MallocPool); #endif } #endif