diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h index 261eefaac943..cc22cbcb729d 100644 --- a/stand/common/bootstrap.h +++ b/stand/common/bootstrap.h @@ -1,424 +1,393 @@ /*- * 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 #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[]); bool interp_has_builtin_cmd(const char *cmd); /* Called by interp.c for interp_*.c embedded interpreters */ int interp_include(const char *); /* Execute commands from filename */ void interp_init(void); /* Initialize interpreater */ int interp_run(const char *); /* 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[]); 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 *, int, daddr_t, size_t, char *, size_t *); 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 */ /* set c_flags to match hardware */ void (* c_probe)(struct console *cp); /* reinit XXX may need more args */ int (* c_init)(int arg); /* emit c */ void (* c_out)(int c); /* wait for and return input */ int (* c_in)(void); /* return nonzero if input waiting */ int (* c_ready)(void); }; extern struct console *consoles[]; void cons_probe(void); bool cons_update_mode(bool); void autoload_font(bool); extern int module_verbose; enum { MODULE_VERBOSE_SILENT, /* say nothing */ MODULE_VERBOSE_SIZE, /* print name and size */ MODULE_VERBOSE_TWIDDLE, /* show progress */ MODULE_VERBOSE_FULL, /* all we have */ }; /* * 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 { /* ASCII identifier, actual format varies with bus/handler */ char *id_ident; 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; vm_offset_t md_addr; /* Valid after copied to kernel space */ 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 */ /* metadata that will be placed in the module directory */ struct file_metadata *f_metadata; 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 */ #ifdef __amd64__ bool f_kernphys_relocatable; #endif #if defined(__i386__) bool f_tg_kernel_support; #endif }; struct file_format { /* * Load function must return EFTYPE if it can't handle * the module supplied */ int (*l_load)(char *, uint64_t, struct preloaded_file **); /* * Only a loader that will load a kernel (first module) * should have an exec handler */ int (*l_exec)(struct preloaded_file *); }; 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 *, int, size_t, void *); int file_addmodule(struct preloaded_file *, char *, int, struct kernel_module **); void file_removemetadata(struct preloaded_file *fp); int file_addbuf(const char *name, const char *type, size_t len, void *buf); int tslog_init(void); int tslog_publish(void); vm_offset_t build_font_module(vm_offset_t); /* 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 *, uint64_t, struct preloaded_file **); int __elfN(obj_loadfile)(char *, uint64_t, struct preloaded_file **); 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 *, uint64_t, struct preloaded_file **, int); int __elfN(load_modmetadata)(struct preloaded_file *, uint64_t); #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 *, vm_offset_t, const size_t); /* * Copy to local address space from module address space, * similar to bcopy() */ ssize_t (*arch_copyout)(const vm_offset_t, void *, const size_t); /* Read from file to module address space, same semantics as read() */ ssize_t (*arch_readin)(readin_handle_t, vm_offset_t, const size_t); /* 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); -/* - * nvstore API. - */ -typedef int (nvstore_getter_cb_t)(void *, const char *, void **); -typedef int (nvstore_setter_cb_t)(void *, int, const char *, - const void *, size_t); -typedef int (nvstore_setter_str_cb_t)(void *, const char *, const char *, - const char *); -typedef int (nvstore_unset_cb_t)(void *, const char *); -typedef int (nvstore_print_cb_t)(void *, void *); -typedef int (nvstore_iterate_cb_t)(void *, int (*)(void *, void *)); - -typedef struct nvs_callbacks { - nvstore_getter_cb_t *nvs_getter; - nvstore_setter_cb_t *nvs_setter; - nvstore_setter_str_cb_t *nvs_setter_str; - nvstore_unset_cb_t *nvs_unset; - nvstore_print_cb_t *nvs_print; - nvstore_iterate_cb_t *nvs_iterate; -} nvs_callbacks_t; - -int nvstore_init(const char *, nvs_callbacks_t *, void *); -int nvstore_fini(const char *); -void *nvstore_get_store(const char *); -int nvstore_print(void *); -int nvstore_get_var(void *, const char *, void **); -int nvstore_set_var(void *, int, const char *, void *, size_t); -int nvstore_set_var_from_string(void *, const char *, const char *, - const char *); -int nvstore_unset_var(void *, const char *); - /* common code to set currdev variable. */ int gen_setcurrdev(struct env_var *ev, int flags, const void *value); int mount_currdev(struct env_var *, int, const void *); void set_currdev(const char *devname); #ifndef CTASSERT #define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") #endif #endif /* !_BOOTSTRAP_H_ */ diff --git a/stand/common/nvstore.c b/stand/common/nvstore.c index c6d230584f9d..3cdb094c858f 100644 --- a/stand/common/nvstore.c +++ b/stand/common/nvstore.c @@ -1,310 +1,184 @@ /*- * Copyright 2020 Toomas Soome * * 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. */ /* * Big Theory Statement. * * nvstore is abstraction layer to implement data read/write to different * types of non-volatile storage. * - * User interfaces: - * Provide mapping via environment: setenv/unsetenv/putenv. Access via - * environment functions/commands is available once nvstore has - * attached the backend and stored textual data is mapped to environment. - * - * Provide command "nvstore" to create new data instances. - * - * API: TBD. - * nvstore_init(): attach new backend and create the environment mapping. - * nvstore_fini: detach backend and unmap the related environment. - * - * The disk based storage, such as UFS file or ZFS bootenv label area, is - * only accessible after root file system is set. Root file system change - * will switch the back end storage. + * Provides cli command 'nvostre' */ -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include #include "stand.h" - -typedef struct nvstore { - char *nvs_name; - void *nvs_data; - nvs_callbacks_t *nvs_cb; - STAILQ_ENTRY(nvstore) nvs_next; -} nvstore_t; - -typedef STAILQ_HEAD(store_list, nvstore) nvstore_list_t; - -nvstore_list_t stores = STAILQ_HEAD_INITIALIZER(stores); - -void * -nvstore_get_store(const char *name) -{ - nvstore_t *st; - - st = NULL; - - STAILQ_FOREACH(st, &stores, nvs_next) { - if (strcmp(name, st->nvs_name) == 0) - break; - } - - return (st); -} - -int -nvstore_init(const char *name, nvs_callbacks_t *cb, void *data) -{ - nvstore_t *st; - - st = nvstore_get_store(name); - if (st != NULL) - return (EEXIST); - - if ((st = malloc(sizeof (*st))) == NULL) - return (ENOMEM); - - if ((st->nvs_name = strdup(name)) == NULL) { - free(st); - return (ENOMEM); - } - - st->nvs_data = data; - st->nvs_cb = cb; - - STAILQ_INSERT_TAIL(&stores, st, nvs_next); - return (0); -} - -int -nvstore_fini(const char *name) -{ - nvstore_t *st; - - st = nvstore_get_store(name); - if (st == NULL) - return (ENOENT); - - STAILQ_REMOVE(&stores, st, nvstore, nvs_next); - - free(st->nvs_name); - free(st->nvs_data); - free(st); - return (0); -} - -int -nvstore_print(void *ptr) -{ - nvstore_t *st = ptr; - - return (st->nvs_cb->nvs_iterate(st->nvs_data, st->nvs_cb->nvs_print)); -} - -int -nvstore_get_var(void *ptr, const char *name, void **data) -{ - nvstore_t *st = ptr; - - return (st->nvs_cb->nvs_getter(st->nvs_data, name, data)); -} - -int -nvstore_set_var(void *ptr, int type, const char *name, - void *data, size_t size) -{ - nvstore_t *st = ptr; - - return (st->nvs_cb->nvs_setter(st->nvs_data, type, name, data, size)); -} - -int -nvstore_set_var_from_string(void *ptr, const char *type, const char *name, - const char *data) -{ - nvstore_t *st = ptr; - - return (st->nvs_cb->nvs_setter_str(st->nvs_data, type, name, data)); -} - -int -nvstore_unset_var(void *ptr, const char *name) -{ - nvstore_t *st = ptr; - - return (st->nvs_cb->nvs_unset(st->nvs_data, name)); -} +#include "nvstore.h" +#include "bootstrap.h" COMMAND_SET(nvstore, "nvstore", "manage non-volatile data", command_nvstore); static void nvstore_usage(const char *me) { printf("Usage:\t%s -l\n", me); printf("\t%s store -l\n", me); printf("\t%s store [-t type] key value\n", me); printf("\t%s store -g key\n", me); printf("\t%s store -d key\n", me); } /* * Usage: nvstore -l # list stores * nvstore store -l # list data in store * nvstore store [-t type] key value * nvstore store -g key # get value * nvstore store -d key # delete key */ static int command_nvstore(int argc, char *argv[]) { int c; bool list, get, delete; nvstore_t *st; char *me, *name, *type; me = argv[0]; optind = 1; optreset = 1; list = false; while ((c = getopt(argc, argv, "l")) != -1) { switch (c) { case 'l': list = true; break; case '?': default: return (CMD_ERROR); } } argc -= optind; argv += optind; if (argc == 0) { if (list) { if (STAILQ_EMPTY(&stores)) { printf("No configured nvstores\n"); return (CMD_OK); } printf("List of configured nvstores:\n"); STAILQ_FOREACH(st, &stores, nvs_next) { printf("\t%s\n", st->nvs_name); } return (CMD_OK); } nvstore_usage(me); return (CMD_ERROR); } if (argc == 0 || (argc != 0 && list)) { nvstore_usage(me); return (CMD_ERROR); } st = nvstore_get_store(argv[0]); if (st == NULL) { nvstore_usage(me); return (CMD_ERROR); } optind = 1; optreset = 1; name = NULL; type = NULL; get = delete = false; while ((c = getopt(argc, argv, "d:g:lt:")) != -1) { switch (c) { case 'd': if (list || get) { nvstore_usage(me); return (CMD_ERROR); } name = optarg; delete = true; break; case 'g': if (delete || list) { nvstore_usage(me); return (CMD_ERROR); } name = optarg; get = true; break; case 'l': if (delete || get) { nvstore_usage(me); return (CMD_ERROR); } list = true; break; case 't': type = optarg; break; case '?': default: return (CMD_ERROR); } } argc -= optind; argv += optind; if (list) { (void) nvstore_print(st); return (CMD_OK); } if (delete && name != NULL) { (void) nvstore_unset_var(st, name); return (CMD_OK); } if (get && name != NULL) { char *ptr = NULL; if (nvstore_get_var(st, name, (void **)&ptr) == 0) printf("%s = %s\n", name, ptr); return (CMD_OK); } if (argc == 2) { c = nvstore_set_var_from_string(st, type, argv[0], argv[1]); if (c != 0) { printf("error: %s\n", strerror(c)); return (CMD_ERROR); } return (CMD_OK); } nvstore_usage(me); return (CMD_OK); } diff --git a/stand/libsa/Makefile b/stand/libsa/Makefile index 8ec62f276a09..f009b55e89ef 100644 --- a/stand/libsa/Makefile +++ b/stand/libsa/Makefile @@ -1,214 +1,214 @@ # $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 \ - hexdump.c pager.c panic.c printf.c strdup.c strerror.c \ + hexdump.c nvstore.c pager.c panic.c printf.c strdup.c strerror.c \ random.c sbrk.c tslog.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 strchrnul.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 .for i in bzlib.c crctable.c decompress.c huffman.c randtable.c CFLAGS.${i}+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS SRCS+=${i} .endfor # decompression functionality from zlib # https://github.com/madler/zlib/issues/633 documents why we suppress deprecated # prototype warnings. .PATH: ${SRCTOP}/sys/contrib/zlib ZLIB_CFLAGS=-DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib ${NO_WDEPRECATED_NON_PROTOTYPE} .for i in adler32.c crc32.c infback.c inffast.c inflate.c inftrees.c zutil.c CFLAGS.${i}+=${ZLIB_CFLAGS} SRCS+= ${i} .endfor # 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 inttypes.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 ] || :> 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 mount.c \ fstat.c close.c lseek.c open.c read.c write.c readdir.c preload.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 # Time support SRCS+= time.c # kernel ufs support .PATH: ${SRCTOP}/sys/ufs/ffs SRCS+=ffs_subr.c ffs_tables.c # # i386 has a constrained space for its /boot/loader, so compile out the # extensive messages diagnosing bad superblocks. i386 doesn't support UEFI # booting, so doing it always makes sense natively there. When we compile # for 32-bit on amd64, LIBSA_CPUARCH is also i386 and we use libsa32 only # for the BIOS /boot/loader which has the same constraints. # .if ${LIBSA_CPUARCH} == "i386" CFLAGS.ffs_subr.c+= -DSTANDALONE_SMALL .endif CFLAGS.gzipfs.c+= ${ZLIB_CFLAGS} CFLAGS.pkgfs.c+= ${ZLIB_CFLAGS} CFLAGS.bzipfs.c+= -I${SRCTOP}/contrib/bzip2 -DBZ_NO_STDIO -DBZ_NO_COMPRESS # 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" # XXX Note that these pollutes CFLAGS in a way that's not easy to fix .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 .if ${DO32:U0} == 0 MAN=libsa.3 .endif .include diff --git a/stand/common/nvstore.c b/stand/libsa/nvstore.c similarity index 57% copy from stand/common/nvstore.c copy to stand/libsa/nvstore.c index c6d230584f9d..e5a804ff15e8 100644 --- a/stand/common/nvstore.c +++ b/stand/libsa/nvstore.c @@ -1,310 +1,151 @@ /*- * Copyright 2020 Toomas Soome * * 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. */ /* * Big Theory Statement. * * nvstore is abstraction layer to implement data read/write to different * types of non-volatile storage. * * User interfaces: * Provide mapping via environment: setenv/unsetenv/putenv. Access via * environment functions/commands is available once nvstore has * attached the backend and stored textual data is mapped to environment. * - * Provide command "nvstore" to create new data instances. - * - * API: TBD. * nvstore_init(): attach new backend and create the environment mapping. * nvstore_fini: detach backend and unmap the related environment. * * The disk based storage, such as UFS file or ZFS bootenv label area, is * only accessible after root file system is set. Root file system change * will switch the back end storage. */ #include __FBSDID("$FreeBSD$"); #include #include -#include #include "stand.h" - -typedef struct nvstore { - char *nvs_name; - void *nvs_data; - nvs_callbacks_t *nvs_cb; - STAILQ_ENTRY(nvstore) nvs_next; -} nvstore_t; - -typedef STAILQ_HEAD(store_list, nvstore) nvstore_list_t; +#include "nvstore.h" nvstore_list_t stores = STAILQ_HEAD_INITIALIZER(stores); void * nvstore_get_store(const char *name) { nvstore_t *st; st = NULL; STAILQ_FOREACH(st, &stores, nvs_next) { if (strcmp(name, st->nvs_name) == 0) break; } return (st); } int nvstore_init(const char *name, nvs_callbacks_t *cb, void *data) { nvstore_t *st; st = nvstore_get_store(name); if (st != NULL) return (EEXIST); if ((st = malloc(sizeof (*st))) == NULL) return (ENOMEM); if ((st->nvs_name = strdup(name)) == NULL) { free(st); return (ENOMEM); } st->nvs_data = data; st->nvs_cb = cb; STAILQ_INSERT_TAIL(&stores, st, nvs_next); return (0); } int nvstore_fini(const char *name) { nvstore_t *st; st = nvstore_get_store(name); if (st == NULL) return (ENOENT); STAILQ_REMOVE(&stores, st, nvstore, nvs_next); free(st->nvs_name); free(st->nvs_data); free(st); return (0); } int nvstore_print(void *ptr) { nvstore_t *st = ptr; return (st->nvs_cb->nvs_iterate(st->nvs_data, st->nvs_cb->nvs_print)); } int nvstore_get_var(void *ptr, const char *name, void **data) { nvstore_t *st = ptr; return (st->nvs_cb->nvs_getter(st->nvs_data, name, data)); } int nvstore_set_var(void *ptr, int type, const char *name, void *data, size_t size) { nvstore_t *st = ptr; return (st->nvs_cb->nvs_setter(st->nvs_data, type, name, data, size)); } int nvstore_set_var_from_string(void *ptr, const char *type, const char *name, const char *data) { nvstore_t *st = ptr; return (st->nvs_cb->nvs_setter_str(st->nvs_data, type, name, data)); } int nvstore_unset_var(void *ptr, const char *name) { nvstore_t *st = ptr; return (st->nvs_cb->nvs_unset(st->nvs_data, name)); } - -COMMAND_SET(nvstore, "nvstore", "manage non-volatile data", command_nvstore); - -static void -nvstore_usage(const char *me) -{ - printf("Usage:\t%s -l\n", me); - printf("\t%s store -l\n", me); - printf("\t%s store [-t type] key value\n", me); - printf("\t%s store -g key\n", me); - printf("\t%s store -d key\n", me); -} - -/* - * Usage: nvstore -l # list stores - * nvstore store -l # list data in store - * nvstore store [-t type] key value - * nvstore store -g key # get value - * nvstore store -d key # delete key - */ -static int -command_nvstore(int argc, char *argv[]) -{ - int c; - bool list, get, delete; - nvstore_t *st; - char *me, *name, *type; - - me = argv[0]; - optind = 1; - optreset = 1; - - list = false; - while ((c = getopt(argc, argv, "l")) != -1) { - switch (c) { - case 'l': - list = true; - break; - case '?': - default: - return (CMD_ERROR); - } - } - - argc -= optind; - argv += optind; - - if (argc == 0) { - if (list) { - if (STAILQ_EMPTY(&stores)) { - printf("No configured nvstores\n"); - return (CMD_OK); - } - printf("List of configured nvstores:\n"); - STAILQ_FOREACH(st, &stores, nvs_next) { - printf("\t%s\n", st->nvs_name); - } - return (CMD_OK); - } - nvstore_usage(me); - return (CMD_ERROR); - } - - if (argc == 0 || (argc != 0 && list)) { - nvstore_usage(me); - return (CMD_ERROR); - } - - st = nvstore_get_store(argv[0]); - if (st == NULL) { - nvstore_usage(me); - return (CMD_ERROR); - } - - optind = 1; - optreset = 1; - name = NULL; - type = NULL; - get = delete = false; - - while ((c = getopt(argc, argv, "d:g:lt:")) != -1) { - switch (c) { - case 'd': - if (list || get) { - nvstore_usage(me); - return (CMD_ERROR); - } - name = optarg; - delete = true; - break; - case 'g': - if (delete || list) { - nvstore_usage(me); - return (CMD_ERROR); - } - name = optarg; - get = true; - break; - case 'l': - if (delete || get) { - nvstore_usage(me); - return (CMD_ERROR); - } - list = true; - break; - case 't': - type = optarg; - break; - case '?': - default: - return (CMD_ERROR); - } - } - - argc -= optind; - argv += optind; - - if (list) { - (void) nvstore_print(st); - return (CMD_OK); - } - - if (delete && name != NULL) { - (void) nvstore_unset_var(st, name); - return (CMD_OK); - } - - if (get && name != NULL) { - char *ptr = NULL; - - if (nvstore_get_var(st, name, (void **)&ptr) == 0) - printf("%s = %s\n", name, ptr); - return (CMD_OK); - } - - if (argc == 2) { - c = nvstore_set_var_from_string(st, type, argv[0], argv[1]); - if (c != 0) { - printf("error: %s\n", strerror(c)); - return (CMD_ERROR); - } - return (CMD_OK); - } - - nvstore_usage(me); - return (CMD_OK); -} diff --git a/stand/libsa/nvstore.h b/stand/libsa/nvstore.h new file mode 100644 index 000000000000..a03a73249194 --- /dev/null +++ b/stand/libsa/nvstore.h @@ -0,0 +1,39 @@ +/*- + * Copyright 2020 Toomas Soome + * + * 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. + */ + +/* Private part of nvstore API, for internal use only */ + +#pragma once + +typedef struct nvstore { + char *nvs_name; + void *nvs_data; + nvs_callbacks_t *nvs_cb; + STAILQ_ENTRY(nvstore) nvs_next; +} nvstore_t; + +typedef STAILQ_HEAD(store_list, nvstore) nvstore_list_t; + +extern nvstore_list_t stores; diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h index 87b86fb98b20..83bfabd1c878 100644 --- a/stand/libsa/stand.h +++ b/stand/libsa/stand.h @@ -1,518 +1,547 @@ /* * 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 #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 __BEGIN_DECLS 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); int (*fo_preload)(struct open_file *f); int (*fo_mount)(const char *, const char *, void **); int (*fo_unmount)(const char *, void *); }; /* * libsa-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 */ #define DEV_NAMLEN 8 /* Length of name of device class */ #define DEV_DEVLEN 128 /* Length of longest device instance name */ struct devdesc; struct devsw { const char dv_name[DEV_NAMLEN]; int dv_type; /* opaque type constant */ #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); char * (*dv_fmtdev)(struct devdesc *); int (*dv_parsedev)(struct devdesc **, const char *, const char **); bool (*dv_match)(struct devsw *, const char *); }; /* * libsa-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. The larger device specifiers store more data * than can fit in the generic one that's gleaned after parsing the device * string, or used in some cases to indicate wildcards that match a variety of * situations based on what's on the drive itself rather than what the progammer * might know in advance. Information about open files is stored in d_opendata, * though what's passed into the open routine may differ from what's present * after the open on some configurations. */ struct devdesc { struct devsw *d_dev; int d_unit; void *d_opendata; }; char *devformat(struct devdesc *d); int devparse(struct devdesc **, const char *, const char **); int devinit(void); void dev_cleanup(void); 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 */ int f_id; /* file number */ TAILQ_ENTRY(open_file) f_link; /* next entry */ #define SOPEN_RASIZE 512 }; typedef TAILQ_HEAD(file_list, open_file) file_list_t; extern file_list_t files; extern struct open_file *fd2open_file(int); /* 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 mount(const char *dev, const char *path, int flags, void *data); extern int unmount(const char *dev, int flags); 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 int ioctl(int, u_long, void *); extern struct dirent *readdirfd(int); extern void preload(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); +/* nvstore.c */ +typedef int (nvstore_getter_cb_t)(void *, const char *, void **); +typedef int (nvstore_setter_cb_t)(void *, int, const char *, + const void *, size_t); +typedef int (nvstore_setter_str_cb_t)(void *, const char *, const char *, + const char *); +typedef int (nvstore_unset_cb_t)(void *, const char *); +typedef int (nvstore_print_cb_t)(void *, void *); +typedef int (nvstore_iterate_cb_t)(void *, int (*)(void *, void *)); + +typedef struct nvs_callbacks { + nvstore_getter_cb_t *nvs_getter; + nvstore_setter_cb_t *nvs_setter; + nvstore_setter_str_cb_t *nvs_setter_str; + nvstore_unset_cb_t *nvs_unset; + nvstore_print_cb_t *nvs_print; + nvstore_iterate_cb_t *nvs_iterate; +} nvs_callbacks_t; + +int nvstore_init(const char *, nvs_callbacks_t *, void *); +int nvstore_fini(const char *); +void *nvstore_get_store(const char *); +int nvstore_print(void *); +int nvstore_get_var(void *, const char *, void **); +int nvstore_set_var(void *, int, const char *, void *, size_t); +int nvstore_set_var_from_string(void *, const char *, const char *, + const char *); +int nvstore_unset_var(void *, const char *); + /* tslog.c */ #define TSRAW(a, b, c) tslog(a, b, c) #define TSENTER() TSRAW("ENTER", __func__, NULL) #define TSENTER2(x) TSRAW("ENTER", __func__, x) #define TSEXIT() TSRAW("EXIT", __func__, NULL) #define TSLINE() TSRAW("EVENT", __FILE__, __XSTRING(__LINE__)) void tslog(const char *, const char *, const char *); void tslog_setbuf(void * buf, size_t len); void tslog_getbuf(void ** buf, size_t * len); __END_DECLS #endif /* STAND_H */