diff options
Diffstat (limited to 'sys/boot/common')
40 files changed, 0 insertions, 10756 deletions
diff --git a/sys/boot/common/Makefile.depend b/sys/boot/common/Makefile.depend deleted file mode 100644 index f80275d86ab1..000000000000 --- a/sys/boot/common/Makefile.depend +++ /dev/null @@ -1,11 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - - -.include <dirdeps.mk> - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/sys/boot/common/bcache.c b/sys/boot/common/bcache.c deleted file mode 100644 index 198dd5f3b7ae..000000000000 --- a/sys/boot/common/bcache.c +++ /dev/null @@ -1,503 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * Copyright 2015 Toomas Soome <tsoome@me.com> - * 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 <sys/cdefs.h> -#include <sys/param.h> -__FBSDID("$FreeBSD$"); - -/* - * Simple hashed block cache - */ - -#include <sys/stdint.h> - -#include <stand.h> -#include <string.h> -#include <strings.h> - -#include "bootstrap.h" - -/* #define BCACHE_DEBUG */ - -#ifdef BCACHE_DEBUG -# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args) -#else -# define DEBUG(fmt, args...) -#endif - -struct bcachectl -{ - daddr_t bc_blkno; - int bc_count; -}; - -/* - * bcache per device node. cache is allocated on device first open and freed - * on last close, to save memory. The issue there is the size; biosdisk - * supports up to 31 (0x1f) devices. Classic setup would use single disk - * to boot from, but this has changed with zfs. - */ -struct bcache { - struct bcachectl *bcache_ctl; - caddr_t bcache_data; - size_t bcache_nblks; - size_t ra; -}; - -static u_int bcache_total_nblks; /* set by bcache_init */ -static u_int bcache_blksize; /* set by bcache_init */ -static u_int bcache_numdev; /* set by bcache_add_dev */ -/* statistics */ -static u_int bcache_units; /* number of devices with cache */ -static u_int bcache_unit_nblks; /* nblocks per unit */ -static u_int bcache_hits; -static u_int bcache_misses; -static u_int bcache_ops; -static u_int bcache_bypasses; -static u_int bcache_bcount; -static u_int bcache_rablks; - -#define BHASH(bc, blkno) ((blkno) & ((bc)->bcache_nblks - 1)) -#define BCACHE_LOOKUP(bc, blkno) \ - ((bc)->bcache_ctl[BHASH((bc), (blkno))].bc_blkno != (blkno)) -#define BCACHE_READAHEAD 256 -#define BCACHE_MINREADAHEAD 32 -#define BCACHE_MARKER 0xdeadbeef - -static void bcache_invalidate(struct bcache *bc, daddr_t blkno); -static void bcache_insert(struct bcache *bc, daddr_t blkno); -static void bcache_free_instance(struct bcache *bc); - -/* - * Initialise the cache for (nblks) of (bsize). - */ -void -bcache_init(size_t nblks, size_t bsize) -{ - /* set up control data */ - bcache_total_nblks = nblks; - bcache_blksize = bsize; -} - -/* - * add number of devices to bcache. we have to divide cache space - * between the devices, so bcache_add_dev() can be used to set up the - * number. The issue is, we need to get the number before actual allocations. - * bcache_add_dev() is supposed to be called from device init() call, so the - * assumption is, devsw dv_init is called for plain devices first, and - * for zfs, last. - */ -void -bcache_add_dev(int devices) -{ - bcache_numdev += devices; -} - -void * -bcache_allocate(void) -{ - u_int i; - struct bcache *bc = malloc(sizeof (struct bcache)); - int disks = bcache_numdev; - uint32_t *marker; - - if (disks == 0) - disks = 1; /* safe guard */ - - if (bc == NULL) { - errno = ENOMEM; - return (bc); - } - - /* - * the bcache block count must be power of 2 for hash function - */ - i = fls(disks) - 1; /* highbit - 1 */ - if (disks > (1 << i)) /* next power of 2 */ - i++; - - bc->bcache_nblks = bcache_total_nblks >> i; - bcache_unit_nblks = bc->bcache_nblks; - bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize + - sizeof(uint32_t)); - if (bc->bcache_data == NULL) { - /* dont error out yet. fall back to 32 blocks and try again */ - bc->bcache_nblks = 32; - bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize + - sizeof(uint32_t)); - } - - bc->bcache_ctl = malloc(bc->bcache_nblks * sizeof(struct bcachectl)); - - if ((bc->bcache_data == NULL) || (bc->bcache_ctl == NULL)) { - bcache_free_instance(bc); - errno = ENOMEM; - return (NULL); - } - /* Insert cache end marker. */ - marker = (uint32_t *)(bc->bcache_data + bc->bcache_nblks * bcache_blksize); - *marker = BCACHE_MARKER; - - /* Flush the cache */ - for (i = 0; i < bc->bcache_nblks; i++) { - bc->bcache_ctl[i].bc_count = -1; - bc->bcache_ctl[i].bc_blkno = -1; - } - bcache_units++; - bc->ra = BCACHE_READAHEAD; /* optimistic read ahead */ - return (bc); -} - -void -bcache_free(void *cache) -{ - struct bcache *bc = cache; - - if (bc == NULL) - return; - - bcache_free_instance(bc); - bcache_units--; -} - -/* - * Handle a write request; write directly to the disk, and populate the - * cache with the new values. - */ -static int -write_strategy(void *devdata, int rw, daddr_t blk, size_t size, - char *buf, size_t *rsize) -{ - struct bcache_devdata *dd = (struct bcache_devdata *)devdata; - struct bcache *bc = dd->dv_cache; - daddr_t i, nblk; - - nblk = size / bcache_blksize; - - /* Invalidate the blocks being written */ - for (i = 0; i < nblk; i++) { - bcache_invalidate(bc, blk + i); - } - - /* Write the blocks */ - return (dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize)); -} - -/* - * Handle a read request; fill in parts of the request that can - * be satisfied by the cache, use the supplied strategy routine to do - * device I/O and then use the I/O results to populate the cache. - */ -static int -read_strategy(void *devdata, int rw, daddr_t blk, size_t size, - char *buf, size_t *rsize) -{ - struct bcache_devdata *dd = (struct bcache_devdata *)devdata; - struct bcache *bc = dd->dv_cache; - size_t i, nblk, p_size, r_size, complete, ra; - int result; - daddr_t p_blk; - caddr_t p_buf; - uint32_t *marker; - - if (bc == NULL) { - errno = ENODEV; - return (-1); - } - - marker = (uint32_t *)(bc->bcache_data + bc->bcache_nblks * bcache_blksize); - - if (rsize != NULL) - *rsize = 0; - - nblk = size / bcache_blksize; - if (nblk == 0 && size != 0) - nblk++; - result = 0; - complete = 1; - - /* Satisfy any cache hits up front, break on first miss */ - for (i = 0; i < nblk; i++) { - if (BCACHE_LOOKUP(bc, (daddr_t)(blk + i))) { - bcache_misses += (nblk - i); - complete = 0; - if (nblk - i > BCACHE_MINREADAHEAD && bc->ra > BCACHE_MINREADAHEAD) - bc->ra >>= 1; /* reduce read ahead */ - break; - } else { - bcache_hits++; - } - } - - if (complete) { /* whole set was in cache, return it */ - if (bc->ra < BCACHE_READAHEAD) - bc->ra <<= 1; /* increase read ahead */ - bcopy(bc->bcache_data + (bcache_blksize * BHASH(bc, blk)), buf, size); - goto done; - } - - /* - * Fill in any misses. From check we have i pointing to first missing - * block, read in all remaining blocks + readahead. - * We have space at least for nblk - i before bcache wraps. - */ - p_blk = blk + i; - p_buf = bc->bcache_data + (bcache_blksize * BHASH(bc, p_blk)); - r_size = bc->bcache_nblks - BHASH(bc, p_blk); /* remaining blocks */ - - p_size = MIN(r_size, nblk - i); /* read at least those blocks */ - - /* - * The read ahead size setup. - * While the read ahead can save us IO, it also can complicate things: - * 1. We do not want to read ahead by wrapping around the - * bcache end - this would complicate the cache management. - * 2. We are using bc->ra as dynamic hint for read ahead size, - * detected cache hits will increase the read-ahead block count, and - * misses will decrease, see the code above. - * 3. The bcache is sized by 512B blocks, however, the underlying device - * may have a larger sector size, and we should perform the IO by - * taking into account these larger sector sizes. We could solve this by - * passing the sector size to bcache_allocate(), or by using ioctl(), but - * in this version we are using the constant, 16 blocks, and are rounding - * read ahead block count down to multiple of 16. - * Using the constant has two reasons, we are not entirely sure if the - * BIOS disk interface is providing the correct value for sector size. - * And secondly, this way we get the most conservative setup for the ra. - * - * The selection of multiple of 16 blocks (8KB) is quite arbitrary, however, - * we want to cover CDs (2K) and 4K disks. - * bcache_allocate() will always fall back to a minimum of 32 blocks. - * Our choice of 16 read ahead blocks will always fit inside the bcache. - */ - - if ((rw & F_NORA) == F_NORA) - ra = 0; - else - ra = bc->bcache_nblks - BHASH(bc, p_blk + p_size); - - if (ra != 0 && ra != bc->bcache_nblks) { /* do we have RA space? */ - ra = MIN(bc->ra, ra - 1); - ra = rounddown(ra, 16); /* multiple of 16 blocks */ - p_size += ra; - } - - /* invalidate bcache */ - for (i = 0; i < p_size; i++) { - bcache_invalidate(bc, p_blk + i); - } - - r_size = 0; - /* - * with read-ahead, it may happen we are attempting to read past - * disk end, as bcache has no information about disk size. - * in such case we should get partial read if some blocks can be - * read or error, if no blocks can be read. - * in either case we should return the data in bcache and only - * return error if there is no data. - */ - rw &= F_MASK; - result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, - p_size * bcache_blksize, p_buf, &r_size); - - r_size /= bcache_blksize; - for (i = 0; i < r_size; i++) - bcache_insert(bc, p_blk + i); - - /* update ra statistics */ - if (r_size != 0) { - if (r_size < p_size) - bcache_rablks += (p_size - r_size); - else - bcache_rablks += ra; - } - - /* check how much data can we copy */ - for (i = 0; i < nblk; i++) { - if (BCACHE_LOOKUP(bc, (daddr_t)(blk + i))) - break; - } - - if (size > i * bcache_blksize) - size = i * bcache_blksize; - - if (size != 0) { - bcopy(bc->bcache_data + (bcache_blksize * BHASH(bc, blk)), buf, size); - result = 0; - } - - if (*marker != BCACHE_MARKER) { - printf("BUG: bcache corruption detected: nblks: %zu p_blk: %lu, " - "p_size: %zu, ra: %zu\n", bc->bcache_nblks, - (long unsigned)BHASH(bc, p_blk), p_size, ra); - } - - done: - if ((result == 0) && (rsize != NULL)) - *rsize = size; - return(result); -} - -/* - * Requests larger than 1/2 cache size will be bypassed and go - * directly to the disk. XXX tune this. - */ -int -bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size, - char *buf, size_t *rsize) -{ - struct bcache_devdata *dd = (struct bcache_devdata *)devdata; - struct bcache *bc = dd->dv_cache; - u_int bcache_nblks = 0; - int nblk, cblk, ret; - size_t csize, isize, total; - - bcache_ops++; - - if (bc != NULL) - bcache_nblks = bc->bcache_nblks; - - /* bypass large requests, or when the cache is inactive */ - if (bc == NULL || - ((size * 2 / bcache_blksize) > bcache_nblks)) { - DEBUG("bypass %zu from %qu", size / bcache_blksize, blk); - bcache_bypasses++; - rw &= F_MASK; - return (dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize)); - } - - switch (rw & F_MASK) { - case F_READ: - nblk = size / bcache_blksize; - if (size != 0 && nblk == 0) - nblk++; /* read at least one block */ - - ret = 0; - total = 0; - while(size) { - cblk = bcache_nblks - BHASH(bc, blk); /* # of blocks left */ - cblk = MIN(cblk, nblk); - - if (size <= bcache_blksize) - csize = size; - else - csize = cblk * bcache_blksize; - - ret = read_strategy(devdata, rw, blk, csize, buf+total, &isize); - - /* - * we may have error from read ahead, if we have read some data - * return partial read. - */ - if (ret != 0 || isize == 0) { - if (total != 0) - ret = 0; - break; - } - blk += isize / bcache_blksize; - total += isize; - size -= isize; - nblk = size / bcache_blksize; - } - - if (rsize) - *rsize = total; - - return (ret); - case F_WRITE: - return write_strategy(devdata, F_WRITE, blk, size, buf, rsize); - } - return -1; -} - -/* - * Free allocated bcache instance - */ -static void -bcache_free_instance(struct bcache *bc) -{ - if (bc != NULL) { - if (bc->bcache_ctl) - free(bc->bcache_ctl); - if (bc->bcache_data) - free(bc->bcache_data); - free(bc); - } -} - -/* - * Insert a block into the cache. - */ -static void -bcache_insert(struct bcache *bc, daddr_t blkno) -{ - u_int cand; - - cand = BHASH(bc, blkno); - - DEBUG("insert blk %llu -> %u # %d", blkno, cand, bcache_bcount); - bc->bcache_ctl[cand].bc_blkno = blkno; - bc->bcache_ctl[cand].bc_count = bcache_bcount++; -} - -/* - * Invalidate a block from the cache. - */ -static void -bcache_invalidate(struct bcache *bc, daddr_t blkno) -{ - u_int i; - - i = BHASH(bc, blkno); - if (bc->bcache_ctl[i].bc_blkno == blkno) { - bc->bcache_ctl[i].bc_count = -1; - bc->bcache_ctl[i].bc_blkno = -1; - DEBUG("invalidate blk %llu", blkno); - } -} - -#ifndef BOOT2 -COMMAND_SET(bcachestat, "bcachestat", "get disk block cache stats", command_bcache); - -static int -command_bcache(int argc, char *argv[]) -{ - if (argc != 1) { - command_errmsg = "wrong number of arguments"; - return(CMD_ERROR); - } - - printf("\ncache blocks: %d\n", bcache_total_nblks); - printf("cache blocksz: %d\n", bcache_blksize); - printf("cache readahead: %d\n", bcache_rablks); - printf("unit cache blocks: %d\n", bcache_unit_nblks); - printf("cached units: %d\n", bcache_units); - printf("%d ops %d bypasses %d hits %d misses\n", bcache_ops, - bcache_bypasses, bcache_hits, bcache_misses); - return(CMD_OK); -} -#endif diff --git a/sys/boot/common/boot.c b/sys/boot/common/boot.c deleted file mode 100644 index 5ee95215283c..000000000000 --- a/sys/boot/common/boot.c +++ /dev/null @@ -1,410 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Loading modules, booting the system - */ - -#include <stand.h> -#include <string.h> - -#include "bootstrap.h" - -static char *getbootfile(int try); -static int loadakernel(int try, int argc, char* argv[]); - -/* List of kernel names to try (may be overwritten by boot.config) XXX should move from here? */ -static const char *default_bootfiles = "kernel"; - -static int autoboot_tried; - -/* - * The user wants us to boot. - */ -COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot); - -static int -command_boot(int argc, char *argv[]) -{ - struct preloaded_file *fp; - - /* - * See if the user has specified an explicit kernel to boot. - */ - if ((argc > 1) && (argv[1][0] != '-')) { - - /* XXX maybe we should discard everything and start again? */ - if (file_findfile(NULL, NULL) != NULL) { - snprintf(command_errbuf, sizeof(command_errbuf), - "can't boot '%s', kernel module already loaded", argv[1]); - return(CMD_ERROR); - } - - /* find/load the kernel module */ - if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0) - return(CMD_ERROR); - /* we have consumed all arguments */ - argc = 1; - } - - /* - * See if there is a kernel module already loaded - */ - if (file_findfile(NULL, NULL) == NULL) - if (loadakernel(0, argc - 1, argv + 1)) - /* we have consumed all arguments */ - argc = 1; - - /* - * Loaded anything yet? - */ - if ((fp = file_findfile(NULL, NULL)) == NULL) { - command_errmsg = "no bootable kernel"; - return(CMD_ERROR); - } - - /* - * If we were given arguments, discard any previous. - * XXX should we merge arguments? Hard to DWIM. - */ - if (argc > 1) { - if (fp->f_args != NULL) - free(fp->f_args); - fp->f_args = unargv(argc - 1, argv + 1); - } - - /* Hook for platform-specific autoloading of modules */ - if (archsw.arch_autoload() != 0) - return(CMD_ERROR); - - /* Call the exec handler from the loader matching the kernel */ - file_formats[fp->f_loader]->l_exec(fp); - return(CMD_ERROR); -} - - -/* - * Autoboot after a delay - */ - -COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", command_autoboot); - -static int -command_autoboot(int argc, char *argv[]) -{ - int howlong; - char *cp, *prompt; - - prompt = NULL; - howlong = -1; - switch(argc) { - case 3: - prompt = argv[2]; - /* FALLTHROUGH */ - case 2: - howlong = strtol(argv[1], &cp, 0); - if (*cp != 0) { - snprintf(command_errbuf, sizeof(command_errbuf), - "bad delay '%s'", argv[1]); - return(CMD_ERROR); - } - /* FALLTHROUGH */ - case 1: - return(autoboot(howlong, prompt)); - } - - command_errmsg = "too many arguments"; - return(CMD_ERROR); -} - -/* - * Called before we go interactive. If we think we can autoboot, and - * we haven't tried already, try now. - */ -void -autoboot_maybe() -{ - char *cp; - - cp = getenv("autoboot_delay"); - if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO"))) - autoboot(-1, NULL); /* try to boot automatically */ -} - -int -autoboot(int timeout, char *prompt) -{ - time_t when, otime, ntime; - int c, yes; - char *argv[2], *cp, *ep; - char *kernelname; -#ifdef BOOT_PROMPT_123 - const char *seq = "123", *p = seq; -#endif - - autoboot_tried = 1; - - if (timeout == -1) { - timeout = 10; - /* try to get a delay from the environment */ - if ((cp = getenv("autoboot_delay"))) { - timeout = strtol(cp, &ep, 0); - if (cp == ep) - timeout = 10; /* Unparseable? Set default! */ - } - } - - kernelname = getenv("kernelname"); - if (kernelname == NULL) { - argv[0] = NULL; - loadakernel(0, 0, argv); - kernelname = getenv("kernelname"); - if (kernelname == NULL) { - command_errmsg = "no valid kernel found"; - return(CMD_ERROR); - } - } - - if (timeout >= 0) { - otime = time(NULL); - when = otime + timeout; /* when to boot */ - - yes = 0; - -#ifdef BOOT_PROMPT_123 - printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or " - "1 2 3 sequence for command prompt." : prompt); -#else - printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or any other key for command prompt." : prompt); -#endif - - for (;;) { - if (ischar()) { - c = getchar(); -#ifdef BOOT_PROMPT_123 - if ((c == '\r') || (c == '\n')) { - yes = 1; - break; - } else if (c != *p++) - p = seq; - if (*p == 0) - break; -#else - if ((c == '\r') || (c == '\n')) - yes = 1; - break; -#endif - } - ntime = time(NULL); - if (ntime >= when) { - yes = 1; - break; - } - - if (ntime != otime) { - printf("\rBooting [%s] in %d second%s... ", - kernelname, (int)(when - ntime), - (when-ntime)==1?"":"s"); - otime = ntime; - } - } - } else { - yes = 1; - } - - if (yes) - printf("\rBooting [%s]... ", kernelname); - putchar('\n'); - if (yes) { - argv[0] = "boot"; - argv[1] = NULL; - return(command_boot(1, argv)); - } - return(CMD_OK); -} - -/* - * Scrounge for the name of the (try)'th file we will try to boot. - */ -static char * -getbootfile(int try) -{ - static char *name = NULL; - const char *spec, *ep; - size_t len; - - /* we use dynamic storage */ - if (name != NULL) { - free(name); - name = NULL; - } - - /* - * Try $bootfile, then try our builtin default - */ - if ((spec = getenv("bootfile")) == NULL) - spec = default_bootfiles; - - while ((try > 0) && (spec != NULL)) { - spec = strchr(spec, ';'); - if (spec) - spec++; /* skip over the leading ';' */ - try--; - } - if (spec != NULL) { - if ((ep = strchr(spec, ';')) != NULL) { - len = ep - spec; - } else { - len = strlen(spec); - } - name = malloc(len + 1); - strncpy(name, spec, len); - name[len] = 0; - } - if (name && name[0] == 0) { - free(name); - name = NULL; - } - return(name); -} - -/* - * Try to find the /etc/fstab file on the filesystem (rootdev), - * which should be be the root filesystem, and parse it to find - * out what the kernel ought to think the root filesystem is. - * - * If we're successful, set vfs.root.mountfrom to <vfstype>:<path> - * so that the kernel can tell both which VFS and which node to use - * to mount the device. If this variable's already set, don't - * overwrite it. - */ -int -getrootmount(char *rootdev) -{ - char lbuf[128], *cp, *ep, *dev, *fstyp, *options; - int fd, error; - - if (getenv("vfs.root.mountfrom") != NULL) - return(0); - - error = 1; - sprintf(lbuf, "%s/etc/fstab", rootdev); - if ((fd = open(lbuf, O_RDONLY)) < 0) - goto notfound; - - /* loop reading lines from /etc/fstab What was that about sscanf again? */ - while (fgetstr(lbuf, sizeof(lbuf), fd) >= 0) { - if ((lbuf[0] == 0) || (lbuf[0] == '#')) - continue; - - /* skip device name */ - for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++) - ; - if (*cp == 0) /* misformatted */ - continue; - /* delimit and save */ - *cp++ = 0; - dev = strdup(lbuf); - - /* skip whitespace up to mountpoint */ - while ((*cp != 0) && isspace(*cp)) - cp++; - /* must have /<space> to be root */ - if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1))) - continue; - /* skip whitespace up to fstype */ - cp += 2; - while ((*cp != 0) && isspace(*cp)) - cp++; - if (*cp == 0) /* misformatted */ - continue; - /* skip text to end of fstype and delimit */ - ep = cp; - while ((*cp != 0) && !isspace(*cp)) - cp++; - *cp = 0; - fstyp = strdup(ep); - - /* skip whitespace up to mount options */ - cp += 1; - while ((*cp != 0) && isspace(*cp)) - cp++; - if (*cp == 0) /* misformatted */ - continue; - /* skip text to end of mount options and delimit */ - ep = cp; - while ((*cp != 0) && !isspace(*cp)) - cp++; - *cp = 0; - options = strdup(ep); - /* Build the <fstype>:<device> and save it in vfs.root.mountfrom */ - sprintf(lbuf, "%s:%s", fstyp, dev); - free(dev); - free(fstyp); - setenv("vfs.root.mountfrom", lbuf, 0); - - /* Don't override vfs.root.mountfrom.options if it is already set */ - if (getenv("vfs.root.mountfrom.options") == NULL) { - /* save mount options */ - setenv("vfs.root.mountfrom.options", options, 0); - } - free(options); - error = 0; - break; - } - close(fd); - -notfound: - if (error) { - const char *currdev; - - currdev = getenv("currdev"); - if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) { - cp = strdup(currdev); - cp[strlen(cp) - 1] = '\0'; - setenv("vfs.root.mountfrom", cp, 0); - error = 0; - } - } - - return(error); -} - -static int -loadakernel(int try, int argc, char* argv[]) -{ - char *cp; - - for (try = 0; (cp = getbootfile(try)) != NULL; try++) - if (mod_loadkld(cp, argc - 1, argv + 1) != 0) - printf("can't load '%s'\n", cp); - else - return 1; - return 0; -} diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h deleted file mode 100644 index 2234e05e67e5..000000000000 --- a/sys/boot/common/bootstrap.h +++ /dev/null @@ -1,334 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/types.h> -#include <sys/queue.h> -#include <sys/linker_set.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 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(const char *rc); -int include(const char *filename); - -/* interp_backslash.c */ -char *backslash(char *str); - -/* interp_parse.c */ -int parse(int *argc, char ***argv, char *str); - -/* interp_forth.c */ -void bf_init(const char *rc); -int bf_run(char *line); - -/* boot.c */ -int autoboot(int timeout, char *prompt); -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(int fd, vm_offset_t dest, size_t len, off_t off); -void *alloc_pread(int 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(u_int8_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; - -/* - * 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; - u_int16_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, u_int64_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 u_int64_t __elfN(relocation_offset); - -struct elf_file; -typedef Elf_Addr (symaddr_fn)(struct elf_file *ef, Elf_Size symidx); - -int __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result); -int __elfN(obj_loadfile)(char *filename, u_int64_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, u_int64_t dest, - struct preloaded_file **result, int multiboot); -int __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_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)(const int 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); -}; -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); - -time_t time(time_t *tloc); - -#ifndef CTASSERT /* Allow lint to override */ -#define CTASSERT(x) _CTASSERT(x, __LINE__) -#define _CTASSERT(x, y) __CTASSERT(x, y) -#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] -#endif - -#endif /* !_BOOTSTRAP_H_ */ diff --git a/sys/boot/common/commands.c b/sys/boot/common/commands.c deleted file mode 100644 index def7ff284649..000000000000 --- a/sys/boot/common/commands.c +++ /dev/null @@ -1,511 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> - -#include "bootstrap.h" - -char *command_errmsg; -/* XXX should have procedural interface for setting, size limit? */ -char command_errbuf[COMMAND_ERRBUFSZ]; - -static int page_file(char *filename); - -/* - * Help is read from a formatted text file. - * - * Entries in the file are formatted as - -# Ttopic [Ssubtopic] Ddescription -help -text -here -# - - * - * Note that for code simplicity's sake, the above format must be followed - * exactly. - * - * Subtopic entries must immediately follow the topic (this is used to - * produce the listing of subtopics). - * - * If no argument(s) are supplied by the user, the help for 'help' is displayed. - */ -COMMAND_SET(help, "help", "detailed help", command_help); - -static int -help_getnext(int fd, char **topic, char **subtopic, char **desc) -{ - char line[81], *cp, *ep; - - for (;;) { - if (fgetstr(line, 80, fd) < 0) - return(0); - - if ((strlen(line) < 3) || (line[0] != '#') || (line[1] != ' ')) - continue; - - *topic = *subtopic = *desc = NULL; - cp = line + 2; - while((cp != NULL) && (*cp != 0)) { - ep = strchr(cp, ' '); - if ((*cp == 'T') && (*topic == NULL)) { - if (ep != NULL) - *ep++ = 0; - *topic = strdup(cp + 1); - } else if ((*cp == 'S') && (*subtopic == NULL)) { - if (ep != NULL) - *ep++ = 0; - *subtopic = strdup(cp + 1); - } else if (*cp == 'D') { - *desc = strdup(cp + 1); - ep = NULL; - } - cp = ep; - } - if (*topic == NULL) { - if (*subtopic != NULL) - free(*subtopic); - if (*desc != NULL) - free(*desc); - continue; - } - return(1); - } -} - -static int -help_emitsummary(char *topic, char *subtopic, char *desc) -{ - int i; - - pager_output(" "); - pager_output(topic); - i = strlen(topic); - if (subtopic != NULL) { - pager_output(" "); - pager_output(subtopic); - i += strlen(subtopic) + 1; - } - if (desc != NULL) { - do { - pager_output(" "); - } while (i++ < 30); - pager_output(desc); - } - return (pager_output("\n")); -} - - -static int -command_help(int argc, char *argv[]) -{ - char buf[81]; /* XXX buffer size? */ - int hfd, matched, doindex; - char *topic, *subtopic, *t, *s, *d; - - /* page the help text from our load path */ - snprintf(buf, sizeof(buf), "%s/boot/loader.help", getenv("loaddev")); - if ((hfd = open(buf, O_RDONLY)) < 0) { - printf("Verbose help not available, use '?' to list commands\n"); - return(CMD_OK); - } - - /* pick up request from arguments */ - topic = subtopic = NULL; - switch(argc) { - case 3: - subtopic = strdup(argv[2]); - case 2: - topic = strdup(argv[1]); - break; - case 1: - topic = strdup("help"); - break; - default: - command_errmsg = "usage is 'help <topic> [<subtopic>]"; - close(hfd); - return(CMD_ERROR); - } - - /* magic "index" keyword */ - doindex = !strcmp(topic, "index"); - matched = doindex; - - /* Scan the helpfile looking for help matching the request */ - pager_open(); - while(help_getnext(hfd, &t, &s, &d)) { - - if (doindex) { /* dink around formatting */ - if (help_emitsummary(t, s, d)) - break; - - } else if (strcmp(topic, t)) { - /* topic mismatch */ - if(matched) /* nothing more on this topic, stop scanning */ - break; - - } else { - /* topic matched */ - matched = 1; - if (((subtopic == NULL) && (s == NULL)) || - ((subtopic != NULL) && (s != NULL) && !strcmp(subtopic, s))) { - /* exact match, print text */ - while((fgetstr(buf, 80, hfd) >= 0) && (buf[0] != '#')) { - if (pager_output(buf)) - break; - if (pager_output("\n")) - break; - } - } else if ((subtopic == NULL) && (s != NULL)) { - /* topic match, list subtopics */ - if (help_emitsummary(t, s, d)) - break; - } - } - free(t); - free(s); - free(d); - } - pager_close(); - close(hfd); - if (!matched) { - snprintf(command_errbuf, sizeof(command_errbuf), - "no help available for '%s'", topic); - free(topic); - if (subtopic) - free(subtopic); - return(CMD_ERROR); - } - free(topic); - if (subtopic) - free(subtopic); - return(CMD_OK); -} - - -COMMAND_SET(commandlist, "?", "list commands", command_commandlist); - -/* - * Please note: although we use the pager for the list of commands, - * this routine is called from the ? FORTH function which then - * unconditionally prints some commands. This will lead to anomalous - * behavior. There's no 'pager_output' binding to FORTH to allow - * things to work right, so I'm documenting the bug rather than - * fixing it. - */ -static int -command_commandlist(int argc, char *argv[]) -{ - struct bootblk_command **cmdp; - int res; - char name[20]; - - res = 0; - pager_open(); - res = pager_output("Available commands:\n"); - SET_FOREACH(cmdp, Xcommand_set) { - if (res) - break; - if (((*cmdp)->c_name != NULL) && ((*cmdp)->c_desc != NULL)) { - sprintf(name, " %-15s ", (*cmdp)->c_name); - pager_output(name); - pager_output((*cmdp)->c_desc); - res = pager_output("\n"); - } - } - pager_close(); - return(CMD_OK); -} - -/* - * XXX set/show should become set/echo if we have variable - * substitution happening. - */ - -COMMAND_SET(show, "show", "show variable(s)", command_show); - -static int -command_show(int argc, char *argv[]) -{ - struct env_var *ev; - char *cp; - - if (argc < 2) { - /* - * With no arguments, print everything. - */ - pager_open(); - for (ev = environ; ev != NULL; ev = ev->ev_next) { - pager_output(ev->ev_name); - cp = getenv(ev->ev_name); - if (cp != NULL) { - pager_output("="); - pager_output(cp); - } - if (pager_output("\n")) - break; - } - pager_close(); - } else { - if ((cp = getenv(argv[1])) != NULL) { - printf("%s\n", cp); - } else { - snprintf(command_errbuf, sizeof(command_errbuf), - "variable '%s' not found", argv[1]); - return(CMD_ERROR); - } - } - return(CMD_OK); -} - -COMMAND_SET(set, "set", "set a variable", command_set); - -static int -command_set(int argc, char *argv[]) -{ - int err; - - if (argc != 2) { - command_errmsg = "wrong number of arguments"; - return(CMD_ERROR); - } else { - if ((err = putenv(argv[1])) != 0) { - command_errmsg = strerror(err); - return(CMD_ERROR); - } - } - return(CMD_OK); -} - -COMMAND_SET(unset, "unset", "unset a variable", command_unset); - -static int -command_unset(int argc, char *argv[]) -{ - int err; - - if (argc != 2) { - command_errmsg = "wrong number of arguments"; - return(CMD_ERROR); - } else { - if ((err = unsetenv(argv[1])) != 0) { - command_errmsg = strerror(err); - return(CMD_ERROR); - } - } - return(CMD_OK); -} - -COMMAND_SET(echo, "echo", "echo arguments", command_echo); - -static int -command_echo(int argc, char *argv[]) -{ - char *s; - int nl, ch; - - nl = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "n")) != -1) { - switch(ch) { - case 'n': - nl = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); - } - } - argv += (optind); - argc -= (optind); - - s = unargv(argc, argv); - if (s != NULL) { - printf("%s", s); - free(s); - } - if (!nl) - printf("\n"); - return(CMD_OK); -} - -/* - * A passable emulation of the sh(1) command of the same name. - */ - -COMMAND_SET(read, "read", "read input from the terminal", command_read); - -static int -command_read(int argc, char *argv[]) -{ - char *prompt; - int timeout; - time_t when; - char *cp; - char *name; - char buf[256]; /* XXX size? */ - int c; - - timeout = -1; - prompt = NULL; - optind = 1; - optreset = 1; - while ((c = getopt(argc, argv, "p:t:")) != -1) { - switch(c) { - - case 'p': - prompt = optarg; - break; - case 't': - timeout = strtol(optarg, &cp, 0); - if (cp == optarg) { - snprintf(command_errbuf, sizeof(command_errbuf), - "bad timeout '%s'", optarg); - return(CMD_ERROR); - } - break; - default: - return(CMD_OK); - } - } - - argv += (optind); - argc -= (optind); - name = (argc > 0) ? argv[0]: NULL; - - if (prompt != NULL) - printf("%s", prompt); - if (timeout >= 0) { - when = time(NULL) + timeout; - while (!ischar()) - if (time(NULL) >= when) - return(CMD_OK); /* is timeout an error? */ - } - - ngets(buf, sizeof(buf)); - - if (name != NULL) - setenv(name, buf, 1); - return(CMD_OK); -} - -/* - * File pager - */ -COMMAND_SET(more, "more", "show contents of a file", command_more); - -static int -command_more(int argc, char *argv[]) -{ - int i; - int res; - char line[80]; - - res=0; - pager_open(); - for (i = 1; (i < argc) && (res == 0); i++) { - sprintf(line, "*** FILE %s BEGIN ***\n", argv[i]); - if (pager_output(line)) - break; - res = page_file(argv[i]); - if (!res) { - sprintf(line, "*** FILE %s END ***\n", argv[i]); - res = pager_output(line); - } - } - pager_close(); - - if (res == 0) - return CMD_OK; - else - return CMD_ERROR; -} - -static int -page_file(char *filename) -{ - int result; - - result = pager_file(filename); - - if (result == -1) { - snprintf(command_errbuf, sizeof(command_errbuf), - "error showing %s", filename); - } - - return result; -} - -/* - * List all disk-like devices - */ -COMMAND_SET(lsdev, "lsdev", "list all devices", command_lsdev); - -static int -command_lsdev(int argc, char *argv[]) -{ - int verbose, ch, i; - char line[80]; - - verbose = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "v")) != -1) { - switch(ch) { - case 'v': - verbose = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); - } - } - argv += (optind); - argc -= (optind); - - pager_open(); - for (i = 0; devsw[i] != NULL; i++) { - if (devsw[i]->dv_print != NULL){ - if (devsw[i]->dv_print(verbose)) - break; - } else { - sprintf(line, "%s: (unknown)\n", devsw[i]->dv_name); - if (pager_output(line)) - break; - } - } - pager_close(); - return(CMD_OK); -} - diff --git a/sys/boot/common/console.c b/sys/boot/common/console.c deleted file mode 100644 index f4ffc563889c..000000000000 --- a/sys/boot/common/console.c +++ /dev/null @@ -1,302 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> - -#include "bootstrap.h" -/* - * Core console support - */ - -static int cons_set(struct env_var *ev, int flags, const void *value); -static int cons_find(const char *name); -static int cons_check(const char *string); -static int cons_change(const char *string); -static int twiddle_set(struct env_var *ev, int flags, const void *value); - -/* - * Detect possible console(s) to use. If preferred console(s) have been - * specified, mark them as active. Else, mark the first probed console - * as active. Also create the console variable. - */ -void -cons_probe(void) -{ - int cons; - int active; - char *prefconsole; - - /* We want a callback to install the new value when this var changes. */ - env_setenv("twiddle_divisor", EV_VOLATILE, "1", twiddle_set, env_nounset); - - /* Do all console probes */ - for (cons = 0; consoles[cons] != NULL; cons++) { - consoles[cons]->c_flags = 0; - consoles[cons]->c_probe(consoles[cons]); - } - /* Now find the first working one */ - active = -1; - for (cons = 0; consoles[cons] != NULL && active == -1; cons++) { - consoles[cons]->c_flags = 0; - consoles[cons]->c_probe(consoles[cons]); - if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)) - active = cons; - } - /* Force a console even if all probes failed */ - if (active == -1) - active = 0; - - /* Check to see if a console preference has already been registered */ - prefconsole = getenv("console"); - if (prefconsole != NULL) - prefconsole = strdup(prefconsole); - if (prefconsole != NULL) { - unsetenv("console"); /* we want to replace this */ - cons_change(prefconsole); - } else { - consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; - consoles[active]->c_init(0); - prefconsole = strdup(consoles[active]->c_name); - } - - printf("Consoles: "); - for (cons = 0; consoles[cons] != NULL; cons++) - if (consoles[cons]->c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) - printf("%s ", consoles[cons]->c_desc); - printf("\n"); - - if (prefconsole != NULL) { - env_setenv("console", EV_VOLATILE, prefconsole, cons_set, - env_nounset); - free(prefconsole); - } -} - -int -getchar(void) -{ - int cons; - int rv; - - /* Loop forever polling all active consoles */ - for(;;) - for (cons = 0; consoles[cons] != NULL; cons++) - if ((consoles[cons]->c_flags & (C_PRESENTIN | C_ACTIVEIN)) == - (C_PRESENTIN | C_ACTIVEIN) && - ((rv = consoles[cons]->c_in()) != -1)) - return(rv); -} - -int -ischar(void) -{ - int cons; - - for (cons = 0; consoles[cons] != NULL; cons++) - if ((consoles[cons]->c_flags & (C_PRESENTIN | C_ACTIVEIN)) == - (C_PRESENTIN | C_ACTIVEIN) && - (consoles[cons]->c_ready() != 0)) - return(1); - return(0); -} - -void -putchar(int c) -{ - int cons; - - /* Expand newlines */ - if (c == '\n') - putchar('\r'); - - for (cons = 0; consoles[cons] != NULL; cons++) - if ((consoles[cons]->c_flags & (C_PRESENTOUT | C_ACTIVEOUT)) == - (C_PRESENTOUT | C_ACTIVEOUT)) - consoles[cons]->c_out(c); -} - -/* - * Find the console with the specified name. - */ -static int -cons_find(const char *name) -{ - int cons; - - for (cons = 0; consoles[cons] != NULL; cons++) - if (!strcmp(consoles[cons]->c_name, name)) - return (cons); - return (-1); -} - -/* - * Select one or more consoles. - */ -static int -cons_set(struct env_var *ev, int flags, const void *value) -{ - int ret; - - if ((value == NULL) || (cons_check(value) == 0)) { - /* - * Return CMD_OK instead of CMD_ERROR to prevent forth syntax error, - * which would prevent it processing any further loader.conf entries. - */ - return (CMD_OK); - } - - ret = cons_change(value); - if (ret != CMD_OK) - return (ret); - - env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); - return (CMD_OK); -} - -/* - * Check that at least one the consoles listed in *string is valid - */ -static int -cons_check(const char *string) -{ - int cons, found, failed; - char *curpos, *dup, *next; - - dup = next = strdup(string); - found = failed = 0; - while (next != NULL) { - curpos = strsep(&next, " ,"); - if (*curpos != '\0') { - cons = cons_find(curpos); - if (cons == -1) { - printf("console %s is invalid!\n", curpos); - failed++; - } else { - found++; - } - } - } - - free(dup); - - if (found == 0) - printf("no valid consoles!\n"); - - if (found == 0 || failed != 0) { - printf("Available consoles:\n"); - for (cons = 0; consoles[cons] != NULL; cons++) - printf(" %s\n", consoles[cons]->c_name); - } - - return (found); -} - -/* - * Activate all the valid consoles listed in *string and disable all others. - */ -static int -cons_change(const char *string) -{ - int cons, active; - char *curpos, *dup, *next; - - /* Disable all consoles */ - for (cons = 0; consoles[cons] != NULL; cons++) { - consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT); - } - - /* Enable selected consoles */ - dup = next = strdup(string); - active = 0; - while (next != NULL) { - curpos = strsep(&next, " ,"); - if (*curpos == '\0') - continue; - cons = cons_find(curpos); - if (cons >= 0) { - consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; - consoles[cons]->c_init(0); - if ((consoles[cons]->c_flags & (C_PRESENTIN | C_PRESENTOUT)) == - (C_PRESENTIN | C_PRESENTOUT)) { - active++; - continue; - } - - if (active != 0) { - /* If no consoles have initialised we wouldn't see this. */ - printf("console %s failed to initialize\n", consoles[cons]->c_name); - } - } - } - - free(dup); - - if (active == 0) { - /* All requested consoles failed to initialise, try to recover. */ - for (cons = 0; consoles[cons] != NULL; cons++) { - consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; - consoles[cons]->c_init(0); - if ((consoles[cons]->c_flags & - (C_PRESENTIN | C_PRESENTOUT)) == - (C_PRESENTIN | C_PRESENTOUT)) - active++; - } - - if (active == 0) - return (CMD_ERROR); /* Recovery failed. */ - } - - return (CMD_OK); -} - -/* - * Change the twiddle divisor. - * - * The user can set the twiddle_divisor variable to directly control how fast - * the progress twiddle spins, useful for folks with slow serial consoles. The - * code to monitor changes to the variable and propagate them to the twiddle - * routines has to live somewhere. Twiddling is console-related so it's here. - */ -static int -twiddle_set(struct env_var *ev, int flags, const void *value) -{ - u_long tdiv; - char * eptr; - - tdiv = strtoul(value, &eptr, 0); - if (*(const char *)value == 0 || *eptr != 0) { - printf("invalid twiddle_divisor '%s'\n", (const char *)value); - return (CMD_ERROR); - } - twiddle_divisor((u_int)tdiv); - env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); - - return(CMD_OK); -} diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c deleted file mode 100644 index c5b1e0abd92b..000000000000 --- a/sys/boot/common/dev_net.c +++ /dev/null @@ -1,435 +0,0 @@ -/* $NetBSD: dev_net.c,v 1.23 2008/04/28 20:24:06 martin Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Gordon W. Ross. - * - * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/*- - * This module implements a "raw device" interface suitable for - * use by the stand-alone I/O library NFS code. This interface - * does not support any "block" access, and exists only for the - * purpose of initializing the network interface, getting boot - * parameters, and performing the NFS mount. - * - * At open time, this does: - * - * find interface - netif_open() - * RARP for IP address - rarp_getipaddress() - * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) - * RPC/mountd - nfs_mount(sock, ip, path) - * - * the root file handle from mountd is saved in a global - * for use by the NFS open code (NFS/lookup). - */ - -#include <machine/stdarg.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> - -#include <stand.h> -#include <stddef.h> -#include <string.h> -#include <net.h> -#include <netif.h> -#include <bootp.h> -#include <bootparam.h> - -#include "dev_net.h" -#include "bootstrap.h" - -#ifdef NETIF_DEBUG -int debug = 0; -#endif - -static char *netdev_name; -static int netdev_sock = -1; -static int netdev_opens; - -static int net_init(void); -static int net_open(struct open_file *, ...); -static int net_close(struct open_file *); -static void net_cleanup(void); -static int net_strategy(void *, int, daddr_t, size_t, char *, size_t *); -static int net_print(int); - -static int net_getparams(int sock); - -struct devsw netdev = { - "net", - DEVT_NET, - net_init, - net_strategy, - net_open, - net_close, - noioctl, - net_print, - net_cleanup -}; - -static struct uri_scheme { - const char *scheme; - int proto; -} uri_schemes[] = { - { "tftp:/", NET_TFTP }, - { "nfs:/", NET_NFS }, -}; - -static int -net_init(void) -{ - - return (0); -} - -/* - * Called by devopen after it sets f->f_dev to our devsw entry. - * This opens the low-level device and sets f->f_devdata. - * This is declared with variable arguments... - */ -static int -net_open(struct open_file *f, ...) -{ - struct iodesc *d; - va_list args; - char *devname; /* Device part of file name (or NULL). */ - int error = 0; - - va_start(args, f); - devname = va_arg(args, char*); - va_end(args); - - /* Before opening another interface, close the previous one first. */ - if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0) - net_cleanup(); - - /* On first open, do netif open, mount, etc. */ - if (netdev_opens == 0) { - /* Find network interface. */ - if (netdev_sock < 0) { - netdev_sock = netif_open(devname); - if (netdev_sock < 0) { - printf("net_open: netif_open() failed\n"); - return (ENXIO); - } - netdev_name = strdup(devname); -#ifdef NETIF_DEBUG - if (debug) - printf("net_open: netif_open() succeeded\n"); -#endif - } - /* - * If network params were not set by netif_open(), try to get - * them via bootp, rarp, etc. - */ - if (rootip.s_addr == 0) { - /* Get root IP address, and path, etc. */ - error = net_getparams(netdev_sock); - if (error) { - /* getparams makes its own noise */ - free(netdev_name); - netif_close(netdev_sock); - netdev_sock = -1; - return (error); - } - } - /* - * Set the variables required by the kernel's nfs_diskless - * mechanism. This is the minimum set of variables required to - * mount a root filesystem without needing to obtain additional - * info from bootp or other sources. - */ - d = socktodesc(netdev_sock); - setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 1); - setenv("boot.netif.ip", inet_ntoa(myip), 1); - setenv("boot.netif.netmask", intoa(netmask), 1); - setenv("boot.netif.gateway", inet_ntoa(gateip), 1); - setenv("boot.netif.server", inet_ntoa(rootip), 1); - if (netproto == NET_TFTP) { - setenv("boot.tftproot.server", inet_ntoa(rootip), 1); - setenv("boot.tftproot.path", rootpath, 1); - } else if (netproto == NET_NFS) { - setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); - setenv("boot.nfsroot.path", rootpath, 1); - } - if (intf_mtu != 0) { - char mtu[16]; - snprintf(mtu, sizeof(mtu), "%u", intf_mtu); - setenv("boot.netif.mtu", mtu, 1); - } - - } - netdev_opens++; - f->f_devdata = &netdev_sock; - return (error); -} - -static int -net_close(struct open_file *f) -{ - -#ifdef NETIF_DEBUG - if (debug) - printf("net_close: opens=%d\n", netdev_opens); -#endif - - f->f_devdata = NULL; - - return (0); -} - -static void -net_cleanup(void) -{ - - if (netdev_sock >= 0) { -#ifdef NETIF_DEBUG - if (debug) - printf("net_cleanup: calling netif_close()\n"); -#endif - rootip.s_addr = 0; - free(netdev_name); - netif_close(netdev_sock); - netdev_sock = -1; - } -} - -static int -net_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, - size_t *rsize) -{ - - return (EIO); -} - -#define SUPPORT_BOOTP - -/* - * Get info for NFS boot: our IP address, our hostname, - * server IP address, and our root path on the server. - * There are two ways to do this: The old, Sun way, - * and the more modern, BOOTP way. (RFC951, RFC1048) - * - * The default is to use the Sun bootparams RPC - * (because that is what the kernel will do). - * MD code can make try_bootp initialied data, - * which will override this common definition. - */ -#ifdef SUPPORT_BOOTP -int try_bootp = 1; -#endif - -extern n_long ip_convertaddr(char *p); - -static int -net_getparams(int sock) -{ - char buf[MAXHOSTNAMELEN]; - n_long rootaddr, smask; - -#ifdef SUPPORT_BOOTP - /* - * Try to get boot info using BOOTP. If we succeed, then - * the server IP address, gateway, and root path will all - * be initialized. If any remain uninitialized, we will - * use RARP and RPC/bootparam (the Sun way) to get them. - */ - if (try_bootp) - bootp(sock); - if (myip.s_addr != 0) - goto exit; -#ifdef NETIF_DEBUG - if (debug) - printf("net_open: BOOTP failed, trying RARP/RPC...\n"); -#endif -#endif - - /* - * Use RARP to get our IP address. This also sets our - * netmask to the "natural" default for our address. - */ - if (rarp_getipaddress(sock)) { - printf("net_open: RARP failed\n"); - return (EIO); - } - printf("net_open: client addr: %s\n", inet_ntoa(myip)); - - /* Get our hostname, server IP address, gateway. */ - if (bp_whoami(sock)) { - printf("net_open: bootparam/whoami RPC failed\n"); - return (EIO); - } -#ifdef NETIF_DEBUG - if (debug) - printf("net_open: client name: %s\n", hostname); -#endif - - /* - * Ignore the gateway from whoami (unreliable). - * Use the "gateway" parameter instead. - */ - smask = 0; - gateip.s_addr = 0; - if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { - /* Got it! Parse the netmask. */ - smask = ip_convertaddr(buf); - } - if (smask) { - netmask = smask; -#ifdef NETIF_DEBUG - if (debug) - printf("net_open: subnet mask: %s\n", intoa(netmask)); -#endif - } -#ifdef NETIF_DEBUG - if (gateip.s_addr && debug) - printf("net_open: net gateway: %s\n", inet_ntoa(gateip)); -#endif - - /* Get the root server and pathname. */ - if (bp_getfile(sock, "root", &rootip, rootpath)) { - printf("net_open: bootparam/getfile RPC failed\n"); - return (EIO); - } -exit: - if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) - rootip.s_addr = rootaddr; - -#ifdef NETIF_DEBUG - if (debug) { - printf("net_open: server addr: %s\n", inet_ntoa(rootip)); - printf("net_open: server path: %s\n", rootpath); - } -#endif - - return (0); -} - -static int -net_print(int verbose) -{ - struct netif_driver *drv; - int i, d, cnt; - int ret = 0; - - if (netif_drivers[0] == NULL) - return (ret); - - printf("%s devices:", netdev.dv_name); - if ((ret = pager_output("\n")) != 0) - return (ret); - - cnt = 0; - for (d = 0; netif_drivers[d]; d++) { - drv = netif_drivers[d]; - for (i = 0; i < drv->netif_nifs; i++) { - printf("\t%s%d:", netdev.dv_name, cnt++); - if (verbose) { - printf(" (%s%d)", drv->netif_bname, - drv->netif_ifs[i].dif_unit); - } - if ((ret = pager_output("\n")) != 0) - return (ret); - } - } - return (ret); -} - -/* - * Parses the rootpath if present - * - * The rootpath format can be in the form - * <scheme>://ip/path - * <scheme>:/path - * - * For compatibility with previous behaviour it also accepts as an NFS scheme - * ip:/path - * /path - * - * If an ip is set it returns it in network byte order. - * The default scheme defined in the global netproto, if not set it defaults to - * NFS. - * It leaves just the pathname in the global rootpath. - */ -uint32_t -net_parse_rootpath() -{ - n_long addr = htonl(INADDR_NONE); - size_t i; - char ip[FNAME_SIZE]; - char *ptr, *val; - - netproto = NET_NONE; - - for (i = 0; i < nitems(uri_schemes); i++) { - if (strncmp(rootpath, uri_schemes[i].scheme, - strlen(uri_schemes[i].scheme)) != 0) - continue; - - netproto = uri_schemes[i].proto; - break; - } - ptr = rootpath; - /* Fallback for compatibility mode */ - if (netproto == NET_NONE) { - netproto = NET_NFS; - (void)strsep(&ptr, ":"); - if (ptr != NULL) { - addr = inet_addr(rootpath); - bcopy(ptr, rootpath, strlen(ptr) + 1); - } - } else { - ptr += strlen(uri_schemes[i].scheme); - if (*ptr == '/') { - /* we are in the form <scheme>://, we do expect an ip */ - ptr++; - /* - * XXX when http will be there we will need to check for - * a port, but right now we do not need it yet - */ - val = strchr(ptr, '/'); - if (val != NULL) { - snprintf(ip, sizeof(ip), "%.*s", - (int)((uintptr_t)val - (uintptr_t)ptr), - ptr); - addr = inet_addr(ip); - bcopy(val, rootpath, strlen(val) + 1); - } - } else { - ptr--; - bcopy(ptr, rootpath, strlen(ptr) + 1); - } - } - - return (addr); -} diff --git a/sys/boot/common/dev_net.h b/sys/boot/common/dev_net.h deleted file mode 100644 index 995b67241de8..000000000000 --- a/sys/boot/common/dev_net.h +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * Copyright (c) 1998 Doug Rabson <dfr@freebsd.org> - * 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 _BOOT_DEV_NET_H_ -#define _BOOT_DEV_NET_H_ - -extern struct devsw netdev; - -uint32_t net_parse_rootpath(void); - -#endif diff --git a/sys/boot/common/devopen.c b/sys/boot/common/devopen.c deleted file mode 100644 index de6165c03e8e..000000000000 --- a/sys/boot/common/devopen.c +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> - -#include "bootstrap.h" - -int -devopen(struct open_file *f, const char *fname, const char **file) -{ - struct devdesc *dev; - int result; - - result = archsw.arch_getdev((void **)&dev, fname, file); - if (result) - return (result); - - /* point to device-specific data so that device open can use it */ - f->f_devdata = dev; - result = dev->d_dev->dv_open(f, dev); - if (result != 0) { - f->f_devdata = NULL; - free(dev); - return (result); - } - - /* reference the devsw entry from the open_file structure */ - f->f_dev = dev->d_dev; - return (0); -} - -int -devclose(struct open_file *f) -{ - - if (f->f_devdata != NULL) { - free(f->f_devdata); - } - return (0); -} diff --git a/sys/boot/common/disk.c b/sys/boot/common/disk.c deleted file mode 100644 index 4cb57d466a5e..000000000000 --- a/sys/boot/common/disk.c +++ /dev/null @@ -1,432 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * Copyright (c) 2012 Andrey V. Elsukov <ae@FreeBSD.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/disk.h> -#include <sys/queue.h> -#include <stand.h> -#include <stdarg.h> -#include <bootstrap.h> -#include <part.h> - -#include "disk.h" - -#ifdef DISK_DEBUG -# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args) -#else -# define DEBUG(fmt, args...) -#endif - -struct open_disk { - struct ptable *table; - uint64_t mediasize; - uint64_t entrysize; - u_int sectorsize; -}; - -struct print_args { - struct disk_devdesc *dev; - const char *prefix; - int verbose; -}; - -/* Convert size to a human-readable number. */ -static char * -display_size(uint64_t size, u_int sectorsize) -{ - static char buf[80]; - char unit; - - size = size * sectorsize / 1024; - unit = 'K'; - if (size >= 10485760000LL) { - size /= 1073741824; - unit = 'T'; - } else if (size >= 10240000) { - size /= 1048576; - unit = 'G'; - } else if (size >= 10000) { - size /= 1024; - unit = 'M'; - } - sprintf(buf, "%ld%cB", (long)size, unit); - return (buf); -} - -int -ptblread(void *d, void *buf, size_t blocks, uint64_t offset) -{ - struct disk_devdesc *dev; - struct open_disk *od; - - dev = (struct disk_devdesc *)d; - od = (struct open_disk *)dev->d_opendata; - - /* - * The strategy function assumes the offset is in units of 512 byte - * sectors. For larger sector sizes, we need to adjust the offset to - * match the actual sector size. - */ - offset *= (od->sectorsize / 512); - /* - * As the GPT backup partition is located at the end of the disk, - * to avoid reading past disk end, flag bcache not to use RA. - */ - return (dev->d_dev->dv_strategy(dev, F_READ | F_NORA, offset, - blocks * od->sectorsize, (char *)buf, NULL)); -} - -#define PWIDTH 35 -static int -ptable_print(void *arg, const char *pname, const struct ptable_entry *part) -{ - struct disk_devdesc dev; - struct print_args *pa, bsd; - struct open_disk *od; - struct ptable *table; - char line[80]; - int res; - - pa = (struct print_args *)arg; - od = (struct open_disk *)pa->dev->d_opendata; - sprintf(line, " %s%s: %s", pa->prefix, pname, - parttype2str(part->type)); - if (pa->verbose) - sprintf(line, "%-*s%s", PWIDTH, line, - display_size(part->end - part->start + 1, - od->sectorsize)); - strcat(line, "\n"); - if (pager_output(line)) - return 1; - res = 0; - if (part->type == PART_FREEBSD) { - /* Open slice with BSD label */ - dev.d_dev = pa->dev->d_dev; - dev.d_unit = pa->dev->d_unit; - dev.d_slice = part->index; - dev.d_partition = -1; - if (disk_open(&dev, part->end - part->start + 1, - od->sectorsize) == 0) { - table = ptable_open(&dev, part->end - part->start + 1, - od->sectorsize, ptblread); - if (table != NULL) { - sprintf(line, " %s%s", pa->prefix, pname); - bsd.dev = pa->dev; - bsd.prefix = line; - bsd.verbose = pa->verbose; - res = ptable_iterate(table, &bsd, ptable_print); - ptable_close(table); - } - disk_close(&dev); - } - } - - return (res); -} -#undef PWIDTH - -int -disk_print(struct disk_devdesc *dev, char *prefix, int verbose) -{ - struct open_disk *od; - struct print_args pa; - - /* Disk should be opened */ - od = (struct open_disk *)dev->d_opendata; - pa.dev = dev; - pa.prefix = prefix; - pa.verbose = verbose; - return (ptable_iterate(od->table, &pa, ptable_print)); -} - -int -disk_read(struct disk_devdesc *dev, void *buf, uint64_t offset, u_int blocks) -{ - struct open_disk *od; - int ret; - - od = (struct open_disk *)dev->d_opendata; - ret = dev->d_dev->dv_strategy(dev, F_READ, dev->d_offset + offset, - blocks * od->sectorsize, buf, NULL); - - return (ret); -} - -int -disk_write(struct disk_devdesc *dev, void *buf, uint64_t offset, u_int blocks) -{ - struct open_disk *od; - int ret; - - od = (struct open_disk *)dev->d_opendata; - ret = dev->d_dev->dv_strategy(dev, F_WRITE, dev->d_offset + offset, - blocks * od->sectorsize, buf, NULL); - - return (ret); -} - -int -disk_ioctl(struct disk_devdesc *dev, u_long cmd, void *data) -{ - struct open_disk *od = dev->d_opendata; - - if (od == NULL) - return (ENOTTY); - - switch (cmd) { - case DIOCGSECTORSIZE: - *(u_int *)data = od->sectorsize; - break; - case DIOCGMEDIASIZE: - if (dev->d_offset == 0) - *(uint64_t *)data = od->mediasize; - else - *(uint64_t *)data = od->entrysize * od->sectorsize; - break; - default: - return (ENOTTY); - } - - return (0); -} - -int -disk_open(struct disk_devdesc *dev, uint64_t mediasize, u_int sectorsize) -{ - struct open_disk *od; - struct ptable *table; - struct ptable_entry part; - int rc, slice, partition; - - rc = 0; - /* - * While we are reading disk metadata, make sure we do it relative - * to the start of the disk - */ - dev->d_offset = 0; - table = NULL; - slice = dev->d_slice; - partition = dev->d_partition; - od = (struct open_disk *)malloc(sizeof(struct open_disk)); - if (od == NULL) { - DEBUG("no memory"); - return (ENOMEM); - } - dev->d_opendata = od; - od->entrysize = 0; - od->mediasize = mediasize; - od->sectorsize = sectorsize; - DEBUG("%s unit %d, slice %d, partition %d => %p", - disk_fmtdev(dev), dev->d_unit, dev->d_slice, dev->d_partition, od); - - /* Determine disk layout. */ - od->table = ptable_open(dev, mediasize / sectorsize, sectorsize, - ptblread); - if (od->table == NULL) { - DEBUG("Can't read partition table"); - rc = ENXIO; - goto out; - } - - if (ptable_getsize(od->table, &mediasize) != 0) { - rc = ENXIO; - goto out; - } - if (mediasize > od->mediasize) { - od->mediasize = mediasize; - } - - if (ptable_gettype(od->table) == PTABLE_BSD && - partition >= 0) { - /* It doesn't matter what value has d_slice */ - rc = ptable_getpart(od->table, &part, partition); - if (rc == 0) { - dev->d_offset = part.start; - od->entrysize = part.end - part.start + 1; - } - } else if (slice >= 0) { - /* Try to get information about partition */ - if (slice == 0) - rc = ptable_getbestpart(od->table, &part); - else - rc = ptable_getpart(od->table, &part, slice); - if (rc != 0) /* Partition doesn't exist */ - goto out; - dev->d_offset = part.start; - od->entrysize = part.end - part.start + 1; - slice = part.index; - if (ptable_gettype(od->table) == PTABLE_GPT) { - partition = 255; - goto out; /* Nothing more to do */ - } else if (partition == 255) { - /* - * When we try to open GPT partition, but partition - * table isn't GPT, reset d_partition value to -1 - * and try to autodetect appropriate value. - */ - partition = -1; - } - /* - * If d_partition < 0 and we are looking at a BSD slice, - * then try to read BSD label, otherwise return the - * whole MBR slice. - */ - if (partition == -1 && - part.type != PART_FREEBSD) - goto out; - /* Try to read BSD label */ - table = ptable_open(dev, part.end - part.start + 1, - od->sectorsize, ptblread); - if (table == NULL) { - DEBUG("Can't read BSD label"); - rc = ENXIO; - goto out; - } - /* - * If slice contains BSD label and d_partition < 0, then - * assume the 'a' partition. Otherwise just return the - * whole MBR slice, because it can contain ZFS. - */ - if (partition < 0) { - if (ptable_gettype(table) != PTABLE_BSD) - goto out; - partition = 0; - } - rc = ptable_getpart(table, &part, partition); - if (rc != 0) - goto out; - dev->d_offset += part.start; - od->entrysize = part.end - part.start + 1; - } -out: - if (table != NULL) - ptable_close(table); - - if (rc != 0) { - if (od->table != NULL) - ptable_close(od->table); - free(od); - DEBUG("%s could not open", disk_fmtdev(dev)); - } else { - /* Save the slice and partition number to the dev */ - dev->d_slice = slice; - dev->d_partition = partition; - DEBUG("%s offset %lld => %p", disk_fmtdev(dev), - (long long)dev->d_offset, od); - } - return (rc); -} - -int -disk_close(struct disk_devdesc *dev) -{ - struct open_disk *od; - - od = (struct open_disk *)dev->d_opendata; - DEBUG("%s closed => %p", disk_fmtdev(dev), od); - ptable_close(od->table); - free(od); - return (0); -} - -char* -disk_fmtdev(struct disk_devdesc *dev) -{ - static char buf[128]; - char *cp; - - cp = buf + sprintf(buf, "%s%d", dev->d_dev->dv_name, dev->d_unit); - if (dev->d_slice >= 0) { -#ifdef LOADER_GPT_SUPPORT - if (dev->d_partition == 255) { - sprintf(cp, "p%d:", dev->d_slice); - return (buf); - } else -#endif -#ifdef LOADER_MBR_SUPPORT - cp += sprintf(cp, "s%d", dev->d_slice); -#endif - } - if (dev->d_partition >= 0) - cp += sprintf(cp, "%c", dev->d_partition + 'a'); - strcat(cp, ":"); - return (buf); -} - -int -disk_parsedev(struct disk_devdesc *dev, const char *devspec, const char **path) -{ - int unit, slice, partition; - const char *np; - char *cp; - - np = devspec; - unit = slice = partition = -1; - if (*np != '\0' && *np != ':') { - unit = strtol(np, &cp, 10); - if (cp == np) - return (EUNIT); -#ifdef LOADER_GPT_SUPPORT - if (*cp == 'p') { - np = cp + 1; - slice = strtol(np, &cp, 10); - if (np == cp) - return (ESLICE); - /* we don't support nested partitions on GPT */ - if (*cp != '\0' && *cp != ':') - return (EINVAL); - partition = 255; - } else -#endif -#ifdef LOADER_MBR_SUPPORT - if (*cp == 's') { - np = cp + 1; - slice = strtol(np, &cp, 10); - if (np == cp) - return (ESLICE); - } -#endif - if (*cp != '\0' && *cp != ':') { - partition = *cp - 'a'; - if (partition < 0) - return (EPART); - cp++; - } - } else - return (EINVAL); - - if (*cp != '\0' && *cp != ':') - return (EINVAL); - dev->d_unit = unit; - dev->d_slice = slice; - dev->d_partition = partition; - if (path != NULL) - *path = (*cp == '\0') ? cp: cp + 1; - return (0); -} diff --git a/sys/boot/common/disk.h b/sys/boot/common/disk.h deleted file mode 100644 index 51e1498e3dae..000000000000 --- a/sys/boot/common/disk.h +++ /dev/null @@ -1,117 +0,0 @@ -/*- - * Copyright (c) 2011 Google, 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. - * - * $FreeBSD$ - */ - -/* - * Device descriptor for partitioned disks. To use, set the - * d_slice and d_partition variables as follows: - * - * Whole disk access: - * - * d_slice = -1 - * d_partition = -1 - * - * Whole MBR slice: - * - * d_slice = MBR slice number (typically 1..4) - * d_partition = -1 - * - * BSD disklabel partition within an MBR slice: - * - * d_slice = MBR slice number (typically 1..4) - * d_partition = disklabel partition (typically 0..19) - * - * BSD disklabel partition on the true dedicated disk: - * - * d_slice = -1 - * d_partition = disklabel partition (typically 0..19) - * - * GPT partition: - * - * d_slice = GPT partition number (typically 1..N) - * d_partition = 255 - * - * For both MBR and GPT, to automatically find the 'best' slice or partition, - * set d_slice to zero. This uses the partition type to decide which partition - * to use according to the following list of preferences: - * - * FreeBSD (active) - * FreeBSD (inactive) - * Linux (active) - * Linux (inactive) - * DOS/Windows (active) - * DOS/Windows (inactive) - * - * Active MBR slices (marked as bootable) are preferred over inactive. GPT - * doesn't have the concept of active/inactive partitions. In both MBR and GPT, - * if there are multiple slices/partitions of a given type, the first one - * is chosen. - * - * The low-level disk device will typically call disk_open() from its open - * method to interpret the disk partition tables according to the rules above. - * This will initialize d_offset to the block offset of the start of the - * selected partition - this offset should be added to the offset passed to - * the device's strategy method. - */ - -#ifndef _DISK_H -#define _DISK_H - -struct disk_devdesc -{ - struct devsw *d_dev; - int d_type; - int d_unit; - void *d_opendata; - int d_slice; - int d_partition; - uint64_t d_offset; -}; - -enum disk_ioctl { - IOCTL_GET_BLOCKS, - IOCTL_GET_BLOCK_SIZE -}; - -/* - * Parse disk metadata and initialise dev->d_offset. - */ -extern int disk_open(struct disk_devdesc *, uint64_t, u_int); -extern int disk_close(struct disk_devdesc *); -extern int disk_ioctl(struct disk_devdesc *, u_long, void *); -extern int disk_read(struct disk_devdesc *, void *, uint64_t, u_int); -extern int disk_write(struct disk_devdesc *, void *, uint64_t, u_int); -extern int ptblread(void *, void *, size_t, uint64_t); - -/* - * Print information about slices on a disk. - */ -extern int disk_print(struct disk_devdesc *, char *, int); -extern char* disk_fmtdev(struct disk_devdesc *); -extern int disk_parsedev(struct disk_devdesc *, const char *, const char **); - -#endif /* _DISK_H */ diff --git a/sys/boot/common/help.common b/sys/boot/common/help.common deleted file mode 100644 index 3618501c18ff..000000000000 --- a/sys/boot/common/help.common +++ /dev/null @@ -1,407 +0,0 @@ -################################################################################ -# Thelp DDisplay command help - - help [topic [subtopic]] - help index - - The help command displays help on commands and their usage. - - In command help, a term enclosed with <...> indicates a value as - described by the term. A term enclosed with [...] is optional, - and may not be required by all forms of the command. - - Some commands may not be available. Use the '?' command to list - most available commands. - -################################################################################ -# T? DList available commands - - ? - - Lists all available commands. - -################################################################################ -# Tautoboot DBoot after a delay - - autoboot [<delay> [<prompt>]] - - Displays <prompt> or a default prompt, and counts down <delay> seconds - before attempting to boot. If <delay> is not specified, the default - value is 10. - -################################################################################ -# Tboot DBoot immediately - - boot [<kernelname>] [-<arg> ...] - - Boot the system. If arguments are specified, they are added to the - arguments for the kernel. If <kernelname> is specified, and a kernel - has not already been loaded, it will be booted instead of the default - kernel. - -################################################################################ -# Tbcachestat DGet disk block cache stats - - bcachestat - - Displays statistics about disk cache usage. For debugging only. - -################################################################################ -# Techo DEcho arguments - - echo [-n] [<message>] - - Emits <message>, with no trailing newline if -n is specified. This is - most useful in conjunction with scripts and the '@' line prefix. - - Variables are substituted by prefixing them with $, eg. - - echo Current device is $currdev - - will print the current device. - -################################################################################ -# Tload DLoad a kernel or module - - load [-t <type>] <filename> - - Loads the module contained in <filename> into memory. If no other - modules are loaded, <filename> must be a kernel or the command will - fail. - - If -t is specified, the module is loaded as raw data of <type>, for - later use by the kernel or other modules. <type> may be any string. - -################################################################################ -# Tls DList files - - ls [-l] [<path>] - - Displays a listing of files in the directory <path>, or the root - directory of the current device if <path> is not specified. - - The -l argument displays file sizes as well; the process of obtaining - file sizes on some media may be very slow. - -################################################################################ -# Tlsdev DList devices - - lsdev [-v] - - List all of the devices from which it may be possible to load modules. - If -v is specified, print more details. - -################################################################################ -# Tlsmod DList modules - - lsmod [-v] - - List loaded modules. If [-v] is specified, print more details. - -################################################################################ -# Tmore DPage files - - more <filename> [<filename> ...] - - Show contents of text files. When displaying the contents of more, - than one file, if the user elects to quit displaying a file, the - remaining files will not be shown. - -################################################################################ -# Tpnpscan DScan for PnP devices - - pnpscan [-v] - - Scan for Plug-and-Play devices. This command is normally automatically - run as part of the boot process, in order to dynamically load modules - required for system operation. - - If the -v argument is specified, details on the devices found will - be printed. - -################################################################################ -# Tset DSet a variable - - set <variable name> - set <variable name>=<value> - - The set command is used to set variables. - -################################################################################ -# Tset Sautoboot_delay DSet the default autoboot delay - - set autoboot_delay=<value> - - Sets the default delay for the autoboot command to <value> seconds. - Set value to -1 if you don't want to allow user to interrupt autoboot - process and escape to the loader prompt. - -################################################################################ -# Tset Sbootfile DSet the default boot file set - - set bootfile=<filename>[;<filename>...] - - Sets the default set of kernel boot filename(s). It may be overridden - by setting the bootfile variable to a semicolon-separated list of - filenames, each of which will be searched for in the module_path - directories. The default bootfile set is "kernel". - -################################################################################ -# Tset Sboot_askname DPrompt for root device - - set boot_askname - - Instructs the kernel to prompt the user for the name of the root device - when the kernel is booted. - -################################################################################ -# Tset Sboot_cdrom DMount root file system from CD-ROM - - set boot_cdrom - - Instructs the kernel to try to mount the root file system from CD-ROM. - -################################################################################ -# Tset Sboot_ddb DDrop to the kernel debugger (DDB) - - set boot_ddb - - Instructs the kernel to start in the DDB debugger, rather than - proceeding to initialize when booted. - -################################################################################ -# Tset Sboot_dfltroot DUse default root file system - - set boot_dfltroot - - Instructs the kernel to mount the statically compiled-in root - file system. - -################################################################################ -# Tset Sboot_gdb DSelect gdb-remote mode for the kernel debugger - - set boot_gdb - - Selects gdb-remote mode for the kernel debugger by default. - -################################################################################ -# Tset Sboot_multicons DUse multiple consoles - - set boot_multicons - - Enables multiple console support in the kernel early on boot. - In a running system, console configuration can be manipulated - by the conscontrol(8) utility. - -################################################################################ -# Tset Sboot_mute DMute the console - - set boot_mute - - All console output is suppressed when console is muted. - In a running system, the state of console muting can be - manipulated by the conscontrol(8) utility. - -################################################################################ -# Tset Sboot_pause DPause after each line during device probing - - set boot_pause - - During the device probe, pause after each line is printed. - -################################################################################ -# Tset Sboot_serial DUse serial console - - set boot_serial - - Force the use of a serial console even when an internal console - is present. - -################################################################################ -# Tset Sboot_single DStart system in single-user mode - - set boot_single - - Prevents the kernel from initiating a multi-user startup; instead, - a single-user mode will be entered when the kernel has finished - device probes. - -################################################################################ -# Tset Sboot_verbose DVerbose boot messages - - set boot_verbose - - Setting this variable causes extra debugging information to be printed - by the kernel during the boot phase. - -################################################################################ -# Tset Sconsole DSet the current console - - set console[=<value>] - - Sets the current console. If <value> is omitted, a list of valid - consoles will be displayed. - -################################################################################ -# Tset Scurrdev DSet the current device - - set currdev=<device> - - Selects the default device. See lsdev for available devices. - -################################################################################ -# Tset Sinit_path DSet the list of init candidates - - set init_path=<path>[:<path>...] - - Sets the list of binaries which the kernel will try to run as initial - process. - - -################################################################################ -# Tset Smodule_path DSet the module search path - - set module_path=<path>[;<path>...] - - Sets the list of directories which will be searched in for modules - named in a load command or implicitly required by a dependency. The - default module_path is "/boot/modules" with the kernel directory - prepended. - -################################################################################ -# Tset Sprompt DSet the command prompt - - set prompt=<value> - - The command prompt is displayed when the loader is waiting for input. - Variable substitution is performed on the prompt. The default - prompt can be set with: - - set prompt=\${interpret} - -################################################################################ -# Tset Srootdev DSet the root filesystem - - set rootdev=<path> - - By default the value of $currdev is used to set the root filesystem - when the kernel is booted. This can be overridden by setting - $rootdev explicitly. - -################################################################################ -# Tset Stunables DSet kernel tunable values - - Various kernel tunable parameters can be overridden by specifying new - values in the environment. - - set kern.ipc.nmbclusters=<value> - - Set the number of mbuf clusters to be allocated. The value - cannot be set below the default determined when the kernel - was compiled. - - set kern.ipc.nsfbufs=<value> NSFBUFS - - Set the number of sendfile buffers to be allocated. This - overrides the value determined when the kernel was compiled. - - set vm.kmem_size=<value> VM_KMEM_SIZE - - Sets the size of kernel memory (bytes). This overrides - the value determined when the kernel was compiled. - - set machdep.disable_mtrrs=1 - - Disable the use of i686 MTRRs (i386 only) - - set net.inet.tcp.tcbhashsize=<value> TCBHASHSIZE - - Overrides the compile-time set value of TCBHASHSIZE or - the preset default of 512. Must be a power of 2. - - hw.syscons.sc_no_suspend_vtswitch=<value> - - Disable VT switching on suspend. - - value is 0 (default) or non-zero to enable. - - set hw.physmem=<value> MAXMEM (i386 only) - - Limits the amount of physical memory space available to - the system to <value> bytes. <value> may have a k, M or G - suffix to indicate kilobytes, megabytes and gigabytes - respectively. Note that the current i386 architecture - limits this value to 4GB. - - On systems where memory cannot be accurately probed, - this option provides a hint as to the actual size of - system memory (which will be tested before use). - - set hw.{acpi,pci}.host_start_mem=<value> - - Sets the lowest address that the pci code will assign - when it doesn't have other information about the address - to assign (like from a pci bridge). This is only useful - in older systems without a pci bridge. Also, it only - impacts devices that the BIOS doesn't assign to, typically - CardBus bridges. The default <value> is 0x80000000, but - some systems need values like 0xf0000000, 0xfc000000 or - 0xfe000000 may be suitable for older systems (the older - the system, the higher the number typically should be). - - set hw.pci.enable_io_modes=<value> - - Enable PCI resources which are left off by some BIOSes - or are not enabled correctly by the device driver. - - value is 1 (default), but this may cause problems with - some peripherals. Set to 0 to disable. - -################################################################################ -# Tshow DShow the values of variables - - show [<variable>] - - Displays the value of <variable>, or all variables if not specified. - Multiple paths can be separated with a semicolon. - -################################################################################ -# Tinclude DRead commands from a script file - - include <filename> [<filename> ...] - - The entire contents of <filename> are read into memory before executing - commands, so it is safe to source a file from removable media. - -################################################################################ -# Tread DRead input from the terminal - - read [-t <value>] [-p <prompt>] [<variable name>] - - The read command reads a line of input from the terminal. If the - -t argument is specified, it will return nothing if no input has been - received after <value> seconds. (Any keypress will cancel the - timeout). - - If -p is specified, <prompt> is printed before reading input. No - newline is emitted after the prompt. - - If a variable name is supplied, the variable is set to the value read, - less any terminating newline. - -################################################################################ -# Tunload DRemove all modules from memory - - unload - - This command removes any kernel and all loaded modules from memory. - -################################################################################ -# Tunset DUnset a variable - - unset <variable name> - - If allowed, the named variable's value is discarded and the variable - is removed. - -################################################################################ diff --git a/sys/boot/common/install.c b/sys/boot/common/install.c deleted file mode 100644 index 8c19066894ab..000000000000 --- a/sys/boot/common/install.c +++ /dev/null @@ -1,355 +0,0 @@ -/*- - * Copyright (c) 2008-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 ``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 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/socket.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> - -#include <stand.h> -#include <net.h> -#include <string.h> - -#include "bootstrap.h" - -extern struct in_addr servip; - -extern int pkgfs_init(const char *, struct fs_ops *); -extern void pkgfs_cleanup(void); - -COMMAND_SET(install, "install", "install software package", command_install); - -static char *inst_kernel; -static char **inst_modules; -static char *inst_rootfs; -static char *inst_loader_rc; - -static int -setpath(char **what, char *val) -{ - char *path; - size_t len; - int rel; - - len = strlen(val) + 1; - rel = (val[0] != '/') ? 1 : 0; - path = malloc(len + rel); - if (path == NULL) - return (ENOMEM); - path[0] = '/'; - strcpy(path + rel, val); - - *what = path; - return (0); -} - -static int -setmultipath(char ***what, char *val) -{ - char *s, *v; - int count, error, idx; - - count = 0; - v = val; - do { - count++; - s = strchr(v, ','); - v = (s == NULL) ? NULL : s + 1; - } while (v != NULL); - - *what = calloc(count + 1, sizeof(char *)); - if (*what == NULL) - return (ENOMEM); - - for (idx = 0; idx < count; idx++) { - s = strchr(val, ','); - if (s != NULL) - *s++ = '\0'; - error = setpath(*what + idx, val); - if (error) - return (error); - val = s; - } - - return (0); -} - -static int -read_metatags(int fd) -{ - char buf[1024]; - char *p, *tag, *val; - ssize_t fsize; - int error; - - fsize = read(fd, buf, sizeof(buf)); - if (fsize == -1) - return (errno); - - /* - * Assume that if we read a whole buffer worth of data, we - * haven't read the entire file. In other words, the buffer - * size must always be larger than the file size. That way - * we can append a '\0' and use standard string operations. - * Return an error if this is not possible. - */ - if (fsize == sizeof(buf)) - return (ENOMEM); - - buf[fsize] = '\0'; - error = 0; - tag = buf; - while (!error && *tag != '\0') { - val = strchr(tag, '='); - if (val == NULL) { - error = EINVAL; - break; - } - *val++ = '\0'; - p = strchr(val, '\n'); - if (p == NULL) { - error = EINVAL; - break; - } - *p++ = '\0'; - - if (strcmp(tag, "KERNEL") == 0) - error = setpath(&inst_kernel, val); - else if (strcmp(tag, "MODULES") == 0) - error = setmultipath(&inst_modules, val); - else if (strcmp(tag, "ROOTFS") == 0) - error = setpath(&inst_rootfs, val); - else if (strcmp(tag, "LOADER_RC") == 0) - error = setpath(&inst_loader_rc, val); - - tag = p; - } - - return (error); -} - -static void -cleanup(void) -{ - u_int i; - - if (inst_kernel != NULL) { - free(inst_kernel); - inst_kernel = NULL; - } - if (inst_modules != NULL) { - i = 0; - while (inst_modules[i] != NULL) - free(inst_modules[i++]); - free(inst_modules); - inst_modules = NULL; - } - if (inst_rootfs != NULL) { - free(inst_rootfs); - inst_rootfs = NULL; - } - if (inst_loader_rc != NULL) { - free(inst_loader_rc); - inst_loader_rc = NULL; - } - pkgfs_cleanup(); -} - -/* - * usage: install URL - * where: URL = (tftp|file)://[host]/<package> - */ -static int -install(char *pkgname) -{ - static char buf[256]; - struct fs_ops *proto; - struct preloaded_file *fp; - char *s, *currdev; - const char *devname; - int error, fd, i, local; - - s = strstr(pkgname, "://"); - if (s == NULL) - goto invalid_url; - - i = s - pkgname; - if (i == 4 && !strncasecmp(pkgname, "tftp", i)) { - devname = "net0"; - proto = &tftp_fsops; - local = 0; - } else if (i == 4 && !strncasecmp(pkgname, "file", i)) { - currdev = getenv("currdev"); - if (currdev != NULL && strcmp(currdev, "pxe0:") == 0) { - devname = "pxe0"; - proto = NULL; - } else { - devname = "disk1"; - proto = &dosfs_fsops; - } - local = 1; - } else - goto invalid_url; - - s += 3; - if (*s == '\0') - goto invalid_url; - - if (*s != '/' ) { - if (local) - goto invalid_url; - - pkgname = strchr(s, '/'); - if (pkgname == NULL) - goto invalid_url; - - *pkgname = '\0'; - servip.s_addr = inet_addr(s); - if (servip.s_addr == htonl(INADDR_NONE)) - goto invalid_url; - - setenv("serverip", inet_ntoa(servip), 1); - - *pkgname = '/'; - } else - pkgname = s; - - if (strlen(devname) + strlen(pkgname) + 2 > sizeof(buf)) { - command_errmsg = "package name too long"; - return (CMD_ERROR); - } - sprintf(buf, "%s:%s", devname, pkgname); - setenv("install_package", buf, 1); - - error = pkgfs_init(buf, proto); - if (error) { - command_errmsg = "cannot open package"; - goto fail; - } - - /* - * Point of no return: unload anything that may have been - * loaded and prune the environment from harmful variables. - */ - unload(); - unsetenv("vfs.root.mountfrom"); - - /* - * read the metatags file. - */ - fd = open("/metatags", O_RDONLY); - if (fd != -1) { - error = read_metatags(fd); - close(fd); - if (error) { - command_errmsg = "cannot load metatags"; - goto fail; - } - } - - s = (inst_kernel == NULL) ? "/kernel" : inst_kernel; - error = mod_loadkld(s, 0, NULL); - if (error) { - command_errmsg = "cannot load kernel from package"; - goto fail; - } - - /* If there is a loader.rc in the package, execute it */ - s = (inst_loader_rc == NULL) ? "/loader.rc" : inst_loader_rc; - fd = open(s, O_RDONLY); - if (fd != -1) { - close(fd); - error = include(s); - if (error == CMD_ERROR) - goto fail; - } - - i = 0; - while (inst_modules != NULL && inst_modules[i] != NULL) { - error = mod_loadkld(inst_modules[i], 0, NULL); - if (error) { - command_errmsg = "cannot load module(s) from package"; - goto fail; - } - i++; - } - - s = (inst_rootfs == NULL) ? "/install.iso" : inst_rootfs; - if (file_loadraw(s, "mfs_root", 1) == NULL) { - error = errno; - command_errmsg = "cannot load root file system"; - goto fail; - } - - cleanup(); - - fp = file_findfile(NULL, NULL); - if (fp != NULL) - file_formats[fp->f_loader]->l_exec(fp); - error = CMD_ERROR; - command_errmsg = "unable to start installation"; - - fail: - sprintf(buf, "%s (error %d)", command_errmsg, error); - cleanup(); - unload(); - exclusive_file_system = NULL; - command_errmsg = buf; /* buf is static. */ - return (CMD_ERROR); - - invalid_url: - command_errmsg = "invalid URL"; - return (CMD_ERROR); -} - -static int -command_install(int argc, char *argv[]) -{ - int argidx; - - unsetenv("install_format"); - - argidx = 1; - while (1) { - if (argc == argidx) { - command_errmsg = - "usage: install [--format] <URL>"; - return (CMD_ERROR); - } - if (!strcmp(argv[argidx], "--format")) { - setenv("install_format", "yes", 1); - argidx++; - continue; - } - break; - } - - return (install(argv[argidx])); -} diff --git a/sys/boot/common/interp.c b/sys/boot/common/interp.c deleted file mode 100644 index f4117b9b3e58..000000000000 --- a/sys/boot/common/interp.c +++ /dev/null @@ -1,371 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Simple commandline interpreter, toplevel and misc. - * - * XXX may be obsoleted by BootFORTH or some other, better, interpreter. - */ - -#include <stand.h> -#include <string.h> -#include "bootstrap.h" - -#ifdef BOOT_FORTH -#include "ficl.h" -#define RETURN(x) stackPushINT(bf_vm->pStack,!x); return(x) - -extern FICL_VM *bf_vm; -#else -#define RETURN(x) return(x) -#endif - -#define MAXARGS 20 /* maximum number of arguments allowed */ - -static void prompt(void); - -#ifndef BOOT_FORTH -static int perform(int argc, char *argv[]); - -/* - * Perform the command - */ -int -perform(int argc, char *argv[]) -{ - int result; - struct bootblk_command **cmdp; - bootblk_cmd_t *cmd; - - if (argc < 1) - return(CMD_OK); - - /* set return defaults; a successful command will override these */ - command_errmsg = command_errbuf; - strcpy(command_errbuf, "no error message"); - cmd = NULL; - result = CMD_ERROR; - - /* search the command set for the command */ - SET_FOREACH(cmdp, Xcommand_set) { - if (((*cmdp)->c_name != NULL) && !strcmp(argv[0], (*cmdp)->c_name)) - cmd = (*cmdp)->c_fn; - } - if (cmd != NULL) { - result = (cmd)(argc, argv); - } else { - command_errmsg = "unknown command"; - } - RETURN(result); -} -#endif /* ! BOOT_FORTH */ - -/* - * Interactive mode - */ -void -interact(const char *rc) -{ - static char input[256]; /* big enough? */ -#ifndef BOOT_FORTH - int argc; - char **argv; -#endif - -#ifdef BOOT_FORTH - bf_init((rc) ? "" : NULL); -#endif - - if (rc == NULL) { - /* Read our default configuration. */ - include("/boot/loader.rc"); - } else if (*rc != '\0') - include(rc); - - printf("\n"); - - /* - * Before interacting, we might want to autoboot. - */ - autoboot_maybe(); - - /* - * Not autobooting, go manual - */ - printf("\nType '?' for a list of commands, 'help' for more detailed help.\n"); - if (getenv("prompt") == NULL) - setenv("prompt", "${interpret}", 1); - if (getenv("interpret") == NULL) - setenv("interpret", "OK", 1); - - - for (;;) { - input[0] = '\0'; - prompt(); - ngets(input, sizeof(input)); -#ifdef BOOT_FORTH - bf_vm->sourceID.i = 0; - bf_run(input); -#else - if (!parse(&argc, &argv, input)) { - if (perform(argc, argv)) - printf("%s: %s\n", argv[0], command_errmsg); - free(argv); - } else { - printf("parse error\n"); - } -#endif - } -} - -/* - * Read commands from a file, then execute them. - * - * We store the commands in memory and close the source file so that the media - * holding it can safely go away while we are executing. - * - * Commands may be prefixed with '@' (so they aren't displayed) or '-' (so - * that the script won't stop if they fail). - */ -COMMAND_SET(include, "include", "read commands from a file", command_include); - -static int -command_include(int argc, char *argv[]) -{ - int i; - int res; - char **argvbuf; - - /* - * Since argv is static, we need to save it here. - */ - argvbuf = (char**) calloc((u_int)argc, sizeof(char*)); - for (i = 0; i < argc; i++) - argvbuf[i] = strdup(argv[i]); - - res=CMD_OK; - for (i = 1; (i < argc) && (res == CMD_OK); i++) - res = include(argvbuf[i]); - - for (i = 0; i < argc; i++) - free(argvbuf[i]); - free(argvbuf); - - return(res); -} - -/* - * Header prepended to each line. The text immediately follows the header. - * We try to make this short in order to save memory -- the loader has - * limited memory available, and some of the forth files are very long. - */ -struct includeline -{ - struct includeline *next; -#ifndef BOOT_FORTH - int flags; - int line; -#define SL_QUIET (1<<0) -#define SL_IGNOREERR (1<<1) -#endif - char text[0]; -}; - -int -include(const char *filename) -{ - struct includeline *script, *se, *sp; - char input[256]; /* big enough? */ -#ifdef BOOT_FORTH - int res; - char *cp; - int prevsrcid, fd, line; -#else - int argc,res; - char **argv, *cp; - int fd, flags, line; -#endif - - if (((fd = open(filename, O_RDONLY)) == -1)) { - snprintf(command_errbuf, sizeof(command_errbuf), - "can't open '%s': %s", filename, strerror(errno)); - return(CMD_ERROR); - } - - /* - * Read the script into memory. - */ - script = se = NULL; - line = 0; - - while (fgetstr(input, sizeof(input), fd) >= 0) { - line++; -#ifdef BOOT_FORTH - cp = input; -#else - flags = 0; - /* Discard comments */ - if (strncmp(input+strspn(input, " "), "\\ ", 2) == 0) - continue; - cp = input; - /* Echo? */ - if (input[0] == '@') { - cp++; - flags |= SL_QUIET; - } - /* Error OK? */ - if (input[0] == '-') { - cp++; - flags |= SL_IGNOREERR; - } -#endif - /* Allocate script line structure and copy line, flags */ - if (*cp == '\0') - continue; /* ignore empty line, save memory */ - sp = malloc(sizeof(struct includeline) + strlen(cp) + 1); - /* On malloc failure (it happens!), free as much as possible and exit */ - if (sp == NULL) { - while (script != NULL) { - se = script; - script = script->next; - free(se); - } - snprintf(command_errbuf, sizeof(command_errbuf), - "file '%s' line %d: memory allocation failure - aborting", - filename, line); - return (CMD_ERROR); - } - strcpy(sp->text, cp); -#ifndef BOOT_FORTH - sp->flags = flags; - sp->line = line; -#endif - sp->next = NULL; - - if (script == NULL) { - script = sp; - } else { - se->next = sp; - } - se = sp; - } - close(fd); - - /* - * Execute the script - */ -#ifndef BOOT_FORTH - argv = NULL; -#else - prevsrcid = bf_vm->sourceID.i; - bf_vm->sourceID.i = fd; -#endif - res = CMD_OK; - for (sp = script; sp != NULL; sp = sp->next) { - -#ifdef BOOT_FORTH - res = bf_run(sp->text); - if (res != VM_OUTOFTEXT) { - snprintf(command_errbuf, sizeof(command_errbuf), - "Error while including %s, in the line:\n%s", - filename, sp->text); - res = CMD_ERROR; - break; - } else - res = CMD_OK; -#else - /* print if not being quiet */ - if (!(sp->flags & SL_QUIET)) { - prompt(); - printf("%s\n", sp->text); - } - - /* Parse the command */ - if (!parse(&argc, &argv, sp->text)) { - if ((argc > 0) && (perform(argc, argv) != 0)) { - /* normal command */ - printf("%s: %s\n", argv[0], command_errmsg); - if (!(sp->flags & SL_IGNOREERR)) { - res=CMD_ERROR; - break; - } - } - free(argv); - argv = NULL; - } else { - printf("%s line %d: parse error\n", filename, sp->line); - res=CMD_ERROR; - break; - } -#endif - } -#ifndef BOOT_FORTH - if (argv != NULL) - free(argv); -#else - bf_vm->sourceID.i = prevsrcid; -#endif - while(script != NULL) { - se = script; - script = script->next; - free(se); - } - return(res); -} - -/* - * Emit the current prompt; use the same syntax as the parser - * for embedding environment variables. - */ -static void -prompt(void) -{ - char *pr, *p, *cp, *ev; - - if ((cp = getenv("prompt")) == NULL) - cp = ">"; - pr = p = strdup(cp); - - while (*p != 0) { - if ((*p == '$') && (*(p+1) == '{')) { - for (cp = p + 2; (*cp != 0) && (*cp != '}'); cp++) - ; - *cp = 0; - ev = getenv(p + 2); - - if (ev != NULL) - printf("%s", ev); - p = cp + 1; - continue; - } - putchar(*p++); - } - putchar(' '); - free(pr); -} diff --git a/sys/boot/common/interp_backslash.c b/sys/boot/common/interp_backslash.c deleted file mode 100644 index 09b8f57bf029..000000000000 --- a/sys/boot/common/interp_backslash.c +++ /dev/null @@ -1,167 +0,0 @@ -/*- - * 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. - * - * Jordan K. Hubbard - * 29 August 1998 - * - * Routine for doing backslash elimination. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> -#include "bootstrap.h" - -#define DIGIT(x) (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A') - -/* - * backslash: Return malloc'd copy of str with all standard "backslash - * processing" done on it. Original can be free'd if desired. - */ -char * -backslash(char *str) -{ - /* - * Remove backslashes from the strings. Turn \040 etc. into a single - * character (we allow eight bit values). Currently NUL is not - * allowed. - * - * Turn "\n" and "\t" into '\n' and '\t' characters. Etc. - * - */ - char *new_str; - int seenbs = 0; - int i = 0; - - if ((new_str = strdup(str)) == NULL) - return NULL; - - while (*str) { - if (seenbs) { - seenbs = 0; - switch (*str) { - case '\\': - new_str[i++] = '\\'; - str++; - break; - - /* preserve backslashed quotes, dollar signs */ - case '\'': - case '"': - case '$': - new_str[i++] = '\\'; - new_str[i++] = *str++; - break; - - case 'b': - new_str[i++] = '\b'; - str++; - break; - - case 'f': - new_str[i++] = '\f'; - str++; - break; - - case 'r': - new_str[i++] = '\r'; - str++; - break; - - case 'n': - new_str[i++] = '\n'; - str++; - break; - - case 's': - new_str[i++] = ' '; - str++; - break; - - case 't': - new_str[i++] = '\t'; - str++; - break; - - case 'v': - new_str[i++] = '\13'; - str++; - break; - - case 'z': - str++; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - char val; - - /* Three digit octal constant? */ - if (*str >= '0' && *str <= '3' && - *(str + 1) >= '0' && *(str + 1) <= '7' && - *(str + 2) >= '0' && *(str + 2) <= '7') { - - val = (DIGIT(*str) << 6) + (DIGIT(*(str + 1)) << 3) + - DIGIT(*(str + 2)); - - /* Allow null value if user really wants to shoot - at feet, but beware! */ - new_str[i++] = val; - str += 3; - break; - } - - /* One or two digit hex constant? - * If two are there they will both be taken. - * Use \z to split them up if this is not wanted. - */ - if (*str == '0' && - (*(str + 1) == 'x' || *(str + 1) == 'X') && - isxdigit(*(str + 2))) { - val = DIGIT(*(str + 2)); - if (isxdigit(*(str + 3))) { - val = (val << 4) + DIGIT(*(str + 3)); - str += 4; - } - else - str += 3; - /* Yep, allow null value here too */ - new_str[i++] = val; - break; - } - } - break; - - default: - new_str[i++] = *str++; - break; - } - } - else { - if (*str == '\\') { - seenbs = 1; - str++; - } - else - new_str[i++] = *str++; - } - } - - if (seenbs) { - /* - * The final character was a '\'. Put it in as a single backslash. - */ - new_str[i++] = '\\'; - } - new_str[i] = '\0'; - return new_str; -} diff --git a/sys/boot/common/interp_forth.c b/sys/boot/common/interp_forth.c deleted file mode 100644 index a3b77769d38a..000000000000 --- a/sys/boot/common/interp_forth.c +++ /dev/null @@ -1,332 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> /* to pick up __FreeBSD_version */ -#include <string.h> -#include <stand.h> -#include "bootstrap.h" -#include "ficl.h" - -extern unsigned bootprog_rev; - -/* #define BFORTH_DEBUG */ - -#ifdef BFORTH_DEBUG -#define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args) -#else -#define DEBUG(fmt, args...) -#endif - -/* - * Eventually, all builtin commands throw codes must be defined - * elsewhere, possibly bootstrap.h. For now, just this code, used - * just in this file, it is getting defined. - */ -#define BF_PARSE 100 - -/* - * FreeBSD loader default dictionary cells - */ -#ifndef BF_DICTSIZE -#define BF_DICTSIZE 10000 -#endif - -/* - * BootForth Interface to Ficl Forth interpreter. - */ - -FICL_SYSTEM *bf_sys; -FICL_VM *bf_vm; - -/* - * Shim for taking commands from BF and passing them out to 'standard' - * argv/argc command functions. - */ -static void -bf_command(FICL_VM *vm) -{ - char *name, *line, *tail, *cp; - size_t len; - struct bootblk_command **cmdp; - bootblk_cmd_t *cmd; - int nstrings, i; - int argc, result; - char **argv; - - /* Get the name of the current word */ - name = vm->runningWord->name; - - /* Find our command structure */ - cmd = NULL; - SET_FOREACH(cmdp, Xcommand_set) { - if (((*cmdp)->c_name != NULL) && !strcmp(name, (*cmdp)->c_name)) - cmd = (*cmdp)->c_fn; - } - if (cmd == NULL) - panic("callout for unknown command '%s'", name); - - /* Check whether we have been compiled or are being interpreted */ - if (stackPopINT(vm->pStack)) { - /* - * Get parameters from stack, in the format: - * an un ... a2 u2 a1 u1 n -- - * Where n is the number of strings, a/u are pairs of - * address/size for strings, and they will be concatenated - * in LIFO order. - */ - nstrings = stackPopINT(vm->pStack); - for (i = 0, len = 0; i < nstrings; i++) - len += stackFetch(vm->pStack, i * 2).i + 1; - line = malloc(strlen(name) + len + 1); - strcpy(line, name); - - if (nstrings) - for (i = 0; i < nstrings; i++) { - len = stackPopINT(vm->pStack); - cp = stackPopPtr(vm->pStack); - strcat(line, " "); - strncat(line, cp, len); - } - } else { - /* Get remainder of invocation */ - tail = vmGetInBuf(vm); - for (cp = tail, len = 0; cp != vm->tib.end && *cp != 0 && *cp != '\n'; cp++, len++) - ; - - line = malloc(strlen(name) + len + 2); - strcpy(line, name); - if (len > 0) { - strcat(line, " "); - strncat(line, tail, len); - vmUpdateTib(vm, tail + len); - } - } - DEBUG("cmd '%s'", line); - - command_errmsg = command_errbuf; - command_errbuf[0] = 0; - if (!parse(&argc, &argv, line)) { - result = (cmd)(argc, argv); - free(argv); - } else { - result=BF_PARSE; - } - - switch (result) { - case CMD_CRIT: - printf("%s\n", command_errmsg); - break; - case CMD_FATAL: - panic("%s\n", command_errmsg); - } - - free(line); - /* - * If there was error during nested ficlExec(), we may no longer have - * valid environment to return. Throw all exceptions from here. - */ - if (result != CMD_OK) - vmThrow(vm, result); - - /* This is going to be thrown!!! */ - stackPushINT(vm->pStack,result); -} - -/* - * Replace a word definition (a builtin command) with another - * one that: - * - * - Throw error results instead of returning them on the stack - * - Pass a flag indicating whether the word was compiled or is - * being interpreted. - * - * There is one major problem with builtins that cannot be overcome - * in anyway, except by outlawing it. We want builtins to behave - * differently depending on whether they have been compiled or they - * are being interpreted. Notice that this is *not* the interpreter's - * current state. For example: - * - * : example ls ; immediate - * : problem example ; \ "ls" gets executed while compiling - * example \ "ls" gets executed while interpreting - * - * Notice that, though the current state is different in the two - * invocations of "example", in both cases "ls" has been - * *compiled in*, which is what we really want. - * - * The problem arises when you tick the builtin. For example: - * - * : example-1 ['] ls postpone literal ; immediate - * : example-2 example-1 execute ; immediate - * : problem example-2 ; - * example-2 - * - * We have no way, when we get EXECUTEd, of knowing what our behavior - * should be. Thus, our only alternative is to "outlaw" this. See RFI - * 0007, and ANS Forth Standard's appendix D, item 6.7 for a related - * problem, concerning compile semantics. - * - * The problem is compounded by the fact that "' builtin CATCH" is valid - * and desirable. The only solution is to create an intermediary word. - * For example: - * - * : my-ls ls ; - * : example ['] my-ls catch ; - * - * So, with the below implementation, here is a summary of the behavior - * of builtins: - * - * ls -l \ "interpret" behavior, ie, - * \ takes parameters from TIB - * : ex-1 s" -l" 1 ls ; \ "compile" behavior, ie, - * \ takes parameters from the stack - * : ex-2 ['] ls catch ; immediate \ undefined behavior - * : ex-3 ['] ls catch ; \ undefined behavior - * ex-2 ex-3 \ "interpret" behavior, - * \ catch works - * : ex-4 ex-2 ; \ "compile" behavior, - * \ catch does not work - * : ex-5 ex-3 ; immediate \ same as ex-2 - * : ex-6 ex-3 ; \ same as ex-3 - * : ex-7 ['] ex-1 catch ; \ "compile" behavior, - * \ catch works - * : ex-8 postpone ls ; immediate \ same as ex-2 - * : ex-9 postpone ls ; \ same as ex-3 - * - * As the definition below is particularly tricky, and it's side effects - * must be well understood by those playing with it, I'll be heavy on - * the comments. - * - * (if you edit this definition, pay attention to trailing spaces after - * each word -- I warned you! :-) ) - */ -#define BUILTIN_CONSTRUCTOR \ -": builtin: " \ - ">in @ " /* save the tib index pointer */ \ - "' " /* get next word's xt */ \ - "swap >in ! " /* point again to next word */ \ - "create " /* create a new definition of the next word */ \ - ", " /* save previous definition's xt */ \ - "immediate " /* make the new definition an immediate word */ \ - \ - "does> " /* Now, the *new* definition will: */ \ - "state @ if " /* if in compiling state: */ \ - "1 postpone literal " /* pass 1 flag to indicate compile */ \ - "@ compile, " /* compile in previous definition */ \ - "postpone throw " /* throw stack-returned result */ \ - "else " /* if in interpreting state: */ \ - "0 swap " /* pass 0 flag to indicate interpret */ \ - "@ execute " /* call previous definition */ \ - "throw " /* throw stack-returned result */ \ - "then ; " - -/* - * Initialise the Forth interpreter, create all our commands as words. - */ -void -bf_init(const char *rc) -{ - struct bootblk_command **cmdp; - char create_buf[41]; /* 31 characters-long builtins */ - int fd; - - bf_sys = ficlInitSystem(BF_DICTSIZE); - bf_vm = ficlNewVM(bf_sys); - - /* Put all private definitions in a "builtins" vocabulary */ - ficlExec(bf_vm, "vocabulary builtins also builtins definitions"); - - /* Builtin constructor word */ - ficlExec(bf_vm, BUILTIN_CONSTRUCTOR); - - /* make all commands appear as Forth words */ - SET_FOREACH(cmdp, Xcommand_set) { - ficlBuild(bf_sys, (char *)(*cmdp)->c_name, bf_command, FW_DEFAULT); - ficlExec(bf_vm, "forth definitions builtins"); - sprintf(create_buf, "builtin: %s", (*cmdp)->c_name); - ficlExec(bf_vm, create_buf); - ficlExec(bf_vm, "builtins definitions"); - } - ficlExec(bf_vm, "only forth definitions"); - - /* Export some version numbers so that code can detect the loader/host version */ - ficlSetEnv(bf_sys, "FreeBSD_version", __FreeBSD_version); - ficlSetEnv(bf_sys, "loader_version", bootprog_rev); - - /* try to load and run init file if present */ - if (rc == NULL) - rc = "/boot/boot.4th"; - if (*rc != '\0') { - fd = open(rc, O_RDONLY); - if (fd != -1) { - (void)ficlExecFD(bf_vm, fd); - close(fd); - } - } -} - -/* - * Feed a line of user input to the Forth interpreter - */ -int -bf_run(char *line) -{ - int result; - - result = ficlExec(bf_vm, line); - - DEBUG("ficlExec '%s' = %d", line, result); - switch (result) { - case VM_OUTOFTEXT: - case VM_ABORTQ: - case VM_QUIT: - case VM_ERREXIT: - break; - case VM_USEREXIT: - printf("No where to leave to!\n"); - break; - case VM_ABORT: - printf("Aborted!\n"); - break; - case BF_PARSE: - printf("Parse error!\n"); - break; - default: - if (command_errmsg != NULL) { - printf("%s\n", command_errmsg); - command_errmsg = NULL; - } - } - - if (result == VM_USEREXIT) - panic("interpreter exit"); - setenv("interpret", bf_vm->state ? "" : "OK", 1); - - return (result); -} diff --git a/sys/boot/common/interp_parse.c b/sys/boot/common/interp_parse.c deleted file mode 100644 index 8d8a2e290983..000000000000 --- a/sys/boot/common/interp_parse.c +++ /dev/null @@ -1,222 +0,0 @@ -/*- - * 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. - * - * Jordan K. Hubbard - * 29 August 1998 - * - * The meat of the simple parser. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> -#include "bootstrap.h" - -static void clean(void); -static int insert(int *argcp, char *buf); -static char *variable_lookup(char *name); - -#define PARSE_BUFSIZE 1024 /* maximum size of one element */ -#define MAXARGS 20 /* maximum number of elements */ -static char *args[MAXARGS]; - -/* - * parse: accept a string of input and "parse" it for backslash - * substitutions and environment variable expansions (${var}), - * returning an argc/argv style vector of whitespace separated - * arguments. Returns 0 on success, 1 on failure (ok, ok, so I - * wimped-out on the error codes! :). - * - * Note that the argv array returned must be freed by the caller, but - * we own the space allocated for arguments and will free that on next - * invocation. This allows argv consumers to modify the array if - * required. - * - * NB: environment variables that expand to more than one whitespace - * separated token will be returned as a single argv[] element, not - * split in turn. Expanded text is also immune to further backslash - * elimination or expansion since this is a one-pass, non-recursive - * parser. You didn't specify more than this so if you want more, ask - * me. - jkh - */ - -#define PARSE_FAIL(expr) \ -if (expr) { \ - printf("fail at line %d\n", __LINE__); \ - clean(); \ - free(copy); \ - free(buf); \ - return 1; \ -} - -/* Accept the usual delimiters for a variable, returning counterpart */ -static char -isdelim(int ch) -{ - if (ch == '{') - return '}'; - else if (ch == '(') - return ')'; - return '\0'; -} - -static int -isquote(int ch) -{ - return (ch == '\''); -} - -static int -isdquote(int ch) -{ - return (ch == '"'); -} - -int -parse(int *argc, char ***argv, char *str) -{ - int ac; - char *val, *p, *q, *copy = NULL; - size_t i = 0; - char token, tmp, quote, dquote, *buf; - enum { STR, VAR, WHITE } state; - - ac = *argc = 0; - dquote = quote = 0; - if (!str || (p = copy = backslash(str)) == NULL) - return 1; - - /* Initialize vector and state */ - clean(); - state = STR; - buf = (char *)malloc(PARSE_BUFSIZE); - token = 0; - - /* And awaaaaaaaaay we go! */ - while (*p) { - switch (state) { - case STR: - if ((*p == '\\') && p[1]) { - p++; - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } else if (isquote(*p)) { - quote = quote ? 0 : *p; - if (dquote) { /* keep quote */ - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } else - ++p; - } else if (isdquote(*p)) { - dquote = dquote ? 0 : *p; - if (quote) { /* keep dquote */ - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } else - ++p; - } else if (isspace(*p) && !quote && !dquote) { - state = WHITE; - if (i) { - buf[i] = '\0'; - PARSE_FAIL(insert(&ac, buf)); - i = 0; - } - ++p; - } else if (*p == '$' && !quote) { - token = isdelim(*(p + 1)); - if (token) - p += 2; - else - ++p; - state = VAR; - } else { - PARSE_FAIL(i == (PARSE_BUFSIZE - 1)); - buf[i++] = *p++; - } - break; - - case WHITE: - if (isspace(*p)) - ++p; - else - state = STR; - break; - - case VAR: - if (token) { - PARSE_FAIL((q = strchr(p, token)) == NULL); - } else { - q = p; - while (*q && !isspace(*q)) - ++q; - } - tmp = *q; - *q = '\0'; - if ((val = variable_lookup(p)) != NULL) { - size_t len = strlen(val); - - strncpy(buf + i, val, PARSE_BUFSIZE - (i + 1)); - i += min(len, PARSE_BUFSIZE - 1); - } - *q = tmp; /* restore value */ - p = q + (token ? 1 : 0); - state = STR; - break; - } - } - /* missing terminating ' or " */ - PARSE_FAIL(quote || dquote); - /* If at end of token, add it */ - if (i && state == STR) { - buf[i] = '\0'; - PARSE_FAIL(insert(&ac, buf)); - } - args[ac] = NULL; - *argc = ac; - *argv = (char **)malloc((sizeof(char *) * ac + 1)); - bcopy(args, *argv, sizeof(char *) * ac + 1); - free(buf); - free(copy); - return 0; -} - -#define MAXARGS 20 - -/* Clean vector space */ -static void -clean(void) -{ - int i; - - for (i = 0; i < MAXARGS; i++) { - if (args[i] != NULL) { - free(args[i]); - args[i] = NULL; - } - } -} - -static int -insert(int *argcp, char *buf) -{ - if (*argcp >= MAXARGS) - return 1; - args[(*argcp)++] = strdup(buf); - return 0; -} - -static char * -variable_lookup(char *name) -{ - /* XXX search "special variable" space first? */ - return (char *)getenv(name); -} diff --git a/sys/boot/common/isapnp.c b/sys/boot/common/isapnp.c deleted file mode 100644 index 58676007248c..000000000000 --- a/sys/boot/common/isapnp.c +++ /dev/null @@ -1,313 +0,0 @@ -/*- - * Copyright (c) 1998, Michael Smith - * Copyright (c) 1996, Sujal M. Patel - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Machine-independant ISA PnP enumerator implementing a subset of the - * ISA PnP specification. - */ -#include <stand.h> -#include <string.h> -#include <bootstrap.h> -#include <isapnp.h> - -#define inb(x) (archsw.arch_isainb((x))) -#define outb(x,y) (archsw.arch_isaoutb((x),(y))) - -static void isapnp_write(int d, int r); -static void isapnp_send_Initiation_LFSR(void); -static int isapnp_get_serial(u_int8_t *p); -static int isapnp_isolation_protocol(void); -static void isapnp_enumerate(void); - -/* PnP read data port */ -int isapnp_readport = 0; - -#define _PNP_ID_LEN 9 - -struct pnphandler isapnphandler = -{ - "ISA bus", - isapnp_enumerate -}; - -static void -isapnp_write(int d, int r) -{ - outb (_PNP_ADDRESS, d); - outb (_PNP_WRITE_DATA, r); -} - -/* - * Send Initiation LFSR as described in "Plug and Play ISA Specification", - * Intel May 94. - */ -static void -isapnp_send_Initiation_LFSR(void) -{ - int cur, i; - - /* Reset the LSFR */ - outb(_PNP_ADDRESS, 0); - outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ - - cur = 0x6a; - outb(_PNP_ADDRESS, cur); - - for (i = 1; i < 32; i++) { - cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); - outb(_PNP_ADDRESS, cur); - } -} - -/* - * Get the device's serial number. Returns 1 if the serial is valid. - */ -static int -isapnp_get_serial(u_int8_t *data) -{ - int i, bit, valid = 0, sum = 0x6a; - - bzero(data, _PNP_ID_LEN); - outb(_PNP_ADDRESS, SERIAL_ISOLATION); - for (i = 0; i < 72; i++) { - bit = inb(isapnp_readport) == 0x55; - delay(250); /* Delay 250 usec */ - - /* Can't Short Circuit the next evaluation, so 'and' is last */ - bit = (inb(isapnp_readport) == 0xaa) && bit; - delay(250); /* Delay 250 usec */ - - valid = valid || bit; - - if (i < 64) - sum = (sum >> 1) | - (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); - - data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); - } - - valid = valid && (data[8] == sum); - - return valid; -} - -/* - * Fills the buffer with resource info from the device. - * Returns nonzero if the device fails to report - */ -static int -isapnp_get_resource_info(u_int8_t *buffer, int len) -{ - int i, j; - u_char temp; - - for (i = 0; i < len; i++) { - outb(_PNP_ADDRESS, STATUS); - for (j = 0; j < 100; j++) { - if ((inb(isapnp_readport)) & 0x1) - break; - delay(1); - } - if (j == 100) { - printf("PnP device failed to report resource data\n"); - return(1); - } - outb(_PNP_ADDRESS, RESOURCE_DATA); - temp = inb(isapnp_readport); - if (buffer != NULL) - buffer[i] = temp; - } - return(0); -} - -/* - * Scan Resource Data for useful information. - * - * We scan the resource data for compatible device IDs and - * identifier strings; we only take the first identifier string - * and assume it's for the card as a whole. - * - * Returns 0 if the scan completed OK, nonzero on error. - */ -static int -isapnp_scan_resdata(struct pnpinfo *pi) -{ - u_char tag, resinfo[8]; - u_int limit; - size_t large_len; - u_char *str; - - limit = 1000; - while ((limit-- > 0) && !isapnp_get_resource_info(&tag, 1)) { - if (PNP_RES_TYPE(tag) == 0) { - /* Small resource */ - switch (PNP_SRES_NUM(tag)) { - - case COMP_DEVICE_ID: - /* Got a compatible device id resource */ - if (isapnp_get_resource_info(resinfo, PNP_SRES_LEN(tag))) - return(1); - pnp_addident(pi, pnp_eisaformat(resinfo)); - - case END_TAG: - return(0); - break; - - default: - /* Skip this resource */ - if (isapnp_get_resource_info(NULL, PNP_SRES_LEN(tag))) - return(1); - break; - } - } else { - /* Large resource */ - if (isapnp_get_resource_info(resinfo, 2)) - return(1); - - large_len = resinfo[1]; - large_len = (large_len << 8) + resinfo[0]; - - switch(PNP_LRES_NUM(tag)) { - - case ID_STRING_ANSI: - str = malloc(large_len + 1); - if (isapnp_get_resource_info(str, (ssize_t)large_len)) { - free(str); - return(1); - } - str[large_len] = 0; - if (pi->pi_desc == NULL) { - pi->pi_desc = (char *)str; - } else { - free(str); - } - break; - - default: - /* Large resource, skip it */ - if (isapnp_get_resource_info(NULL, (ssize_t)large_len)) - return(1); - } - } - } - return(1); -} - -/* - * Run the isolation protocol. Upon exiting, all cards are aware that - * they should use isapnp_readport as the READ_DATA port. - */ -static int -isapnp_isolation_protocol(void) -{ - int csn; - struct pnpinfo *pi; - u_int8_t cardid[_PNP_ID_LEN]; - int ndevs; - - isapnp_send_Initiation_LFSR(); - ndevs = 0; - - isapnp_write(CONFIG_CONTROL, 0x04); /* Reset CSN for All Cards */ - - for (csn = 1; ; csn++) { - /* Wake up cards without a CSN (ie. all of them) */ - isapnp_write(WAKE, 0); - isapnp_write(SET_RD_DATA, (isapnp_readport >> 2)); - outb(_PNP_ADDRESS, SERIAL_ISOLATION); - delay(1000); /* Delay 1 msec */ - - if (isapnp_get_serial(cardid)) { - isapnp_write(SET_CSN, csn); - pi = pnp_allocinfo(); - ndevs++; - pnp_addident(pi, pnp_eisaformat(cardid)); - /* scan the card obtaining all the identifiers it holds */ - if (isapnp_scan_resdata(pi)) { - pnp_freeinfo(pi); /* error getting data, ignore */ - } else { - pnp_addinfo(pi); - } - } else { - break; - } - } - /* Move all cards to wait-for-key state */ - while (--csn > 0) { - isapnp_send_Initiation_LFSR(); - isapnp_write(WAKE, csn); - isapnp_write(CONFIG_CONTROL, 0x02); - delay(1000); /* XXX is it really necessary ? */ - csn--; - } - return(ndevs); -} - -/* - * Locate ISA-PnP devices and populate the supplied list. - */ -static void -isapnp_enumerate(void) -{ - int pnp_rd_port; - - /* Check for I/O port access */ - if ((archsw.arch_isainb == NULL) || (archsw.arch_isaoutb == NULL)) - return; - - /* - * Validate a possibly-suggested read port value. If the autoscan failed - * last time, this will return us to autoscan mode again. - */ - if ((isapnp_readport > 0) && - (((isapnp_readport < 0x203) || - (isapnp_readport > 0x3ff) || - (isapnp_readport & 0x3) != 0x3))) - /* invalid, go look for ourselves */ - isapnp_readport = 0; - - if (isapnp_readport < 0) { - /* someone is telling us there is no ISA in the system */ - return; - - } else if (isapnp_readport > 0) { - /* Someone has told us where the port is/should be, or we found one last time */ - isapnp_isolation_protocol(); - - } else { - /* No clues, look for it ourselves */ - for (pnp_rd_port = 0x80; pnp_rd_port < 0xff; pnp_rd_port += 0x10) { - /* Look for something, quit when we find it */ - isapnp_readport = (pnp_rd_port << 2) | 0x3; - if (isapnp_isolation_protocol() > 0) - break; - } - } -} diff --git a/sys/boot/common/isapnp.h b/sys/boot/common/isapnp.h deleted file mode 100644 index a5b8f28304f7..000000000000 --- a/sys/boot/common/isapnp.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) 1996, Sujal M. Patel - * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Sujal M. Patel - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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 _I386_ISA_PNP_H_ -#define _I386_ISA_PNP_H_ - -/* Maximum Number of PnP Devices. 8 should be plenty */ -#define MAX_PNP_CARDS 8 -/* - * the following is the maximum number of PnP Logical devices that - * userconfig can handle. - */ -#define MAX_PNP_LDN 20 - -/* Static ports to access PnP state machine */ -#ifndef _KERNEL -#define _PNP_ADDRESS 0x279 -#define _PNP_WRITE_DATA 0xa79 -#endif - -/* PnP Registers. Write to ADDRESS and then use WRITE/READ_DATA */ -#define SET_RD_DATA 0x00 - /*** - Writing to this location modifies the address of the port used for - reading from the Plug and Play ISA cards. Bits[7:0] become I/O - read port address bits[9:2]. Reads from this register are ignored. - ***/ - -#define SERIAL_ISOLATION 0x01 - /*** - A read to this register causes a Plug and Play cards in the Isolation - state to compare one bit of the boards ID. - This register is read only. - ***/ - -#define CONFIG_CONTROL 0x02 - /*** - Bit[2] Reset CSN to 0 - Bit[1] Return to the Wait for Key state - Bit[0] Reset all logical devices and restore configuration - registers to their power-up values. - - A write to bit[0] of this register performs a reset function on - all logical devices. This resets the contents of configuration - registers to their default state. All card's logical devices - enter their default state and the CSN is preserved. - - A write to bit[1] of this register causes all cards to enter the - Wait for Key state but all CSNs are preserved and logical devices - are not affected. - - A write to bit[2] of this register causes all cards to reset their - CSN to zero . - - This register is write-only. The values are not sticky, that is, - hardware will automatically clear them and there is no need for - software to clear the bits. - ***/ - -#define WAKE 0x03 - /*** - A write to this port will cause all cards that have a CSN that - matches the write data[7:0] to go from the Sleep state to the either - the Isolation state if the write data for this command is zero or - the Config state if the write data is not zero. Additionally, the - pointer to the byte-serial device is reset. This register is - writeonly. - ***/ - -#define RESOURCE_DATA 0x04 - /*** - A read from this address reads the next byte of resource information. - The Status register must be polled until bit[0] is set before this - register may be read. This register is read only. - ***/ - -#define STATUS 0x05 - /*** - Bit[0] when set indicates it is okay to read the next data byte - from the Resource Data register. This register is readonly. - ***/ - -#define SET_CSN 0x06 - /*** - A write to this port sets a card's CSN. The CSN is a value uniquely - assigned to each ISA card after the serial identification process - so that each card may be individually selected during a Wake[CSN] - command. This register is read/write. - ***/ - -#define SET_LDN 0x07 - /*** - Selects the current logical device. All reads and writes of memory, - I/O, interrupt and DMA configuration information access the registers - of the logical device written here. In addition, the I/O Range - Check and Activate commands operate only on the selected logical - device. This register is read/write. If a card has only 1 logical - device, this location should be a read-only value of 0x00. - ***/ - -/*** addresses 0x08 - 0x1F Card Level Reserved for future use ***/ -/*** addresses 0x20 - 0x2F Card Level, Vendor Defined ***/ - -#define ACTIVATE 0x30 - /*** - For each logical device there is one activate register that controls - whether or not the logical device is active on the ISA bus. Bit[0], - if set, activates the logical device. Bits[7:1] are reserved and - must return 0 on reads. This is a read/write register. Before a - logical device is activated, I/O range check must be disabled. - ***/ - -#define IO_RANGE_CHECK 0x31 - /*** - This register is used to perform a conflict check on the I/O port - range programmed for use by a logical device. - - Bit[7:2] Reserved and must return 0 on reads - Bit[1] Enable I/O Range check, if set then I/O Range Check - is enabled. I/O range check is only valid when the logical - device is inactive. - - Bit[0], if set, forces the logical device to respond to I/O reads - of the logical device's assigned I/O range with a 0x55 when I/O - range check is in operation. If clear, the logical device drives - 0xAA. This register is read/write. - ***/ - -/*** addr 0x32 - 0x37 Logical Device Control Reserved for future use ***/ -/*** addr 0x38 - 0x3F Logical Device Control Vendor Define ***/ - -#define MEM_CONFIG 0x40 - /*** - Four memory resource registers per range, four ranges. - Fill with 0 if no ranges are enabled. - - Offset 0: RW Memory base address bits[23:16] - Offset 1: RW Memory base address bits[15:8] - Offset 2: Memory control - Bit[1] specifies 8/16-bit control. This bit is set to indicate - 16-bit memory, and cleared to indicate 8-bit memory. - Bit[0], if cleared, indicates the next field can be used as a range - length for decode (implies range length and base alignment of memory - descriptor are equal). - Bit[0], if set, indicates the next field is the upper limit for - the address. - - Bit[0] is read-only. - Offset 3: RW upper limit or range len, bits[23:16] - Offset 4: RW upper limit or range len, bits[15:8] - Offset 5-Offset 7: filler, unused. - ***/ - -#define IO_CONFIG_BASE 0x60 - /*** - Eight ranges, two bytes per range. - Offset 0: I/O port base address bits[15:8] - Offset 1: I/O port base address bits[7:0] - ***/ - -#define IRQ_CONFIG 0x70 - /*** - Two entries, two bytes per entry. - Offset 0: RW interrupt level (1..15, 0=unused). - Offset 1: Bit[1]: level(1:hi, 0:low), - Bit[0]: type (1:level, 0:edge) - byte 1 can be readonly if 1 type of int is used. - ***/ - -#define DRQ_CONFIG 0x74 - /*** - Two entries, one byte per entry. Bits[2:0] select - which DMA channel is in use for DMA 0. Zero selects DMA channel - 0, seven selects DMA channel 7. DMA channel 4, the cascade channel - is used to indicate no DMA channel is active. - ***/ - -/*** 32-bit memory accesses are at 0x76 ***/ - -/* Macros to parse Resource IDs */ -#define PNP_RES_TYPE(a) (a >> 7) -#define PNP_SRES_NUM(a) (a >> 3) -#define PNP_SRES_LEN(a) (a & 0x07) -#define PNP_LRES_NUM(a) (a & 0x7f) - -/* Small Resource Item names */ -#define PNP_VERSION 0x1 -#define LOG_DEVICE_ID 0x2 -#define COMP_DEVICE_ID 0x3 -#define IRQ_FORMAT 0x4 -#define DMA_FORMAT 0x5 -#define START_DEPEND_FUNC 0x6 -#define END_DEPEND_FUNC 0x7 -#define IO_PORT_DESC 0x8 -#define FIXED_IO_PORT_DESC 0x9 -#define SM_RES_RESERVED 0xa-0xd -#define SM_VENDOR_DEFINED 0xe -#define END_TAG 0xf - -/* Large Resource Item names */ -#define MEMORY_RANGE_DESC 0x1 -#define ID_STRING_ANSI 0x2 -#define ID_STRING_UNICODE 0x3 -#define LG_VENDOR_DEFINED 0x4 -#define _32BIT_MEM_RANGE_DESC 0x5 -#define _32BIT_FIXED_LOC_DESC 0x6 -#define LG_RES_RESERVED 0x7-0x7f - -/* - * pnp_cinfo contains Configuration Information. They are used - * to communicate to the device driver the actual configuration - * of the device, and also by the userconfig menu to let the - * operating system override any configuration set by the bios. - * - */ -struct pnp_cinfo { - u_int vendor_id; /* board id */ - u_int serial; /* Board's Serial Number */ - u_long flags; /* OS-reserved flags */ - u_char csn; /* assigned Card Select Number */ - u_char ldn; /* Logical Device Number */ - u_char enable; /* pnp enable */ - u_char override; /* override bios parms (in userconfig) */ - u_char irq[2]; /* IRQ Number */ - u_char irq_type[2]; /* IRQ Type */ - u_char drq[2]; - u_short port[8]; /* The Base Address of the Port */ - struct { - u_long base; /* Memory Base Address */ - int control; /* Memory Control Register */ - u_long range; /* Memory Range *OR* Upper Limit */ - } mem[4]; -}; - -#ifdef _KERNEL - -struct pnp_device { - char *pd_name; - char * (*pd_probe ) (u_long csn, u_long vendor_id); - void (*pd_attach ) (u_long csn, u_long vend_id, char * name, - struct isa_device *dev); - u_long *pd_count; - u_int *imask ; -}; - -struct _pnp_id { - u_long vendor_id; - u_long serial; - u_char checksum; -} ; - -struct pnp_dlist_node { - struct pnp_device *pnp; - struct isa_device dev; - struct pnp_dlist_node *next; -}; - -typedef struct _pnp_id pnp_id; -extern struct pnp_dlist_node *pnp_device_list; -extern pnp_id pnp_devices[MAX_PNP_CARDS]; -extern struct pnp_cinfo pnp_ldn_overrides[MAX_PNP_LDN]; -extern int pnp_overrides_valid; - -/* - * these two functions are for use in drivers - */ -int read_pnp_parms(struct pnp_cinfo *d, int ldn); -int write_pnp_parms(struct pnp_cinfo *d, int ldn); -int enable_pnp_card(void); - -/* - * used by autoconfigure to actually probe and attach drivers - */ -void pnp_configure(void); - -#endif /* _KERNEL */ - -#endif /* !_I386_ISA_PNP_H_ */ diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c deleted file mode 100644 index 679842b9423e..000000000000 --- a/sys/boot/common/load_elf.c +++ /dev/null @@ -1,1038 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * Copyright (c) 1998 Peter Wemm <peter@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/exec.h> -#include <sys/linker.h> -#include <sys/module.h> -#include <sys/stdint.h> -#include <string.h> -#include <machine/elf.h> -#include <stand.h> -#define FREEBSD_ELF -#include <link.h> - -#include "bootstrap.h" - -#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) - -#if defined(__i386__) && __ELF_WORD_SIZE == 64 -#undef ELF_TARG_CLASS -#undef ELF_TARG_MACH -#define ELF_TARG_CLASS ELFCLASS64 -#define ELF_TARG_MACH EM_X86_64 -#endif - -typedef struct elf_file { - Elf_Phdr *ph; - Elf_Ehdr *ehdr; - Elf_Sym *symtab; - Elf_Hashelt *hashtab; - Elf_Hashelt nbuckets; - Elf_Hashelt nchains; - Elf_Hashelt *buckets; - Elf_Hashelt *chains; - Elf_Rel *rel; - size_t relsz; - Elf_Rela *rela; - size_t relasz; - char *strtab; - size_t strsz; - int fd; - caddr_t firstpage; - size_t firstlen; - int kernel; - u_int64_t off; -} *elf_file_t; - -static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t loadaddr); -static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym); -static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, - Elf_Addr p, void *val, size_t len); -static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef, - Elf_Addr p_start, Elf_Addr p_end); -static symaddr_fn __elfN(symaddr); -static char *fake_modname(const char *name); - -const char *__elfN(kerneltype) = "elf kernel"; -const char *__elfN(moduletype) = "elf module"; - -u_int64_t __elfN(relocation_offset) = 0; - -static int -__elfN(load_elf_header)(char *filename, elf_file_t ef) -{ - ssize_t bytes_read; - Elf_Ehdr *ehdr; - int err; - - /* - * Open the image, read and validate the ELF header - */ - if (filename == NULL) /* can't handle nameless */ - return (EFTYPE); - if ((ef->fd = open(filename, O_RDONLY)) == -1) - return (errno); - ef->firstpage = malloc(PAGE_SIZE); - if (ef->firstpage == NULL) { - close(ef->fd); - return (ENOMEM); - } - bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE); - ef->firstlen = (size_t)bytes_read; - if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) { - err = EFTYPE; /* could be EIO, but may be small file */ - goto error; - } - ehdr = ef->ehdr = (Elf_Ehdr *)ef->firstpage; - - /* Is it ELF? */ - if (!IS_ELF(*ehdr)) { - err = EFTYPE; - goto error; - } - if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ - ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || - ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ - ehdr->e_version != EV_CURRENT || - ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ - err = EFTYPE; - goto error; - } - - return (0); - -error: - if (ef->firstpage != NULL) { - free(ef->firstpage); - ef->firstpage = NULL; - } - if (ef->fd != -1) { - close(ef->fd); - ef->fd = -1; - } - return (err); -} - -/* - * Attempt to load the file (file) as an ELF module. It will be stored at - * (dest), and a pointer to a module structure describing the loaded object - * will be saved in (result). - */ -int -__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result) -{ - return (__elfN(loadfile_raw)(filename, dest, result, 0)); -} - -int -__elfN(loadfile_raw)(char *filename, u_int64_t dest, - struct preloaded_file **result, int multiboot) -{ - struct preloaded_file *fp, *kfp; - struct elf_file ef; - Elf_Ehdr *ehdr; - int err; - - fp = NULL; - bzero(&ef, sizeof(struct elf_file)); - ef.fd = -1; - - err = __elfN(load_elf_header)(filename, &ef); - if (err != 0) - return (err); - - ehdr = ef.ehdr; - - /* - * Check to see what sort of module we are. - */ - kfp = file_findfile(NULL, __elfN(kerneltype)); -#ifdef __powerpc__ - /* - * Kernels can be ET_DYN, so just assume the first loaded object is the - * kernel. This assumption will be checked later. - */ - if (kfp == NULL) - ef.kernel = 1; -#endif - if (ef.kernel || ehdr->e_type == ET_EXEC) { - /* Looks like a kernel */ - if (kfp != NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n"); - err = EPERM; - goto oerr; - } - /* - * Calculate destination address based on kernel entrypoint. - * - * For ARM, the destination address is independent of any values in the - * elf header (an ARM kernel can be loaded at any 2MB boundary), so we - * leave dest set to the value calculated by archsw.arch_loadaddr() and - * passed in to this function. - */ -#ifndef __arm__ - if (ehdr->e_type == ET_EXEC) - dest = (ehdr->e_entry & ~PAGE_MASK); -#endif - if ((ehdr->e_entry & ~PAGE_MASK) == 0) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n"); - err = EPERM; - goto oerr; - } - ef.kernel = 1; - - } else if (ehdr->e_type == ET_DYN) { - /* Looks like a kld module */ - if (multiboot != 0) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n"); - err = EPERM; - goto oerr; - } - if (kfp == NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n"); - err = EPERM; - goto oerr; - } - if (strcmp(__elfN(kerneltype), kfp->f_type)) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type); - err = EPERM; - goto oerr; - } - /* Looks OK, got ahead */ - ef.kernel = 0; - - } else { - err = EFTYPE; - goto oerr; - } - - if (archsw.arch_loadaddr != NULL) - dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest); - else - dest = roundup(dest, PAGE_SIZE); - - /* - * Ok, we think we should handle this. - */ - fp = file_alloc(); - if (fp == NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n"); - err = EPERM; - goto out; - } - if (ef.kernel == 1 && multiboot == 0) - setenv("kernelname", filename, 1); - fp->f_name = strdup(filename); - if (multiboot == 0) - fp->f_type = strdup(ef.kernel ? - __elfN(kerneltype) : __elfN(moduletype)); - else - fp->f_type = strdup("elf multiboot kernel"); - -#ifdef ELF_VERBOSE - if (ef.kernel) - printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry); -#else - printf("%s ", filename); -#endif - - fp->f_size = __elfN(loadimage)(fp, &ef, dest); - if (fp->f_size == 0 || fp->f_addr == 0) - goto ioerr; - - /* save exec header as metadata */ - file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); - - /* Load OK, return module pointer */ - *result = (struct preloaded_file *)fp; - err = 0; - goto out; - - ioerr: - err = EIO; - oerr: - file_discard(fp); - out: - if (ef.firstpage) - free(ef.firstpage); - if (ef.fd != -1) - close(ef.fd); - return(err); -} - -/* - * With the file (fd) open on the image, and (ehdr) containing - * the Elf header, load the image at (off) - */ -static int -__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) -{ - int i; - u_int j; - Elf_Ehdr *ehdr; - Elf_Phdr *phdr, *php; - Elf_Shdr *shdr; - char *shstr; - int ret; - vm_offset_t firstaddr; - vm_offset_t lastaddr; - size_t chunk; - ssize_t result; - Elf_Addr ssym, esym; - Elf_Dyn *dp; - Elf_Addr adp; - Elf_Addr ctors; - int ndp; - int symstrindex; - int symtabindex; - Elf_Size size; - u_int fpcopy; - Elf_Sym sym; - Elf_Addr p_start, p_end; - - dp = NULL; - shdr = NULL; - ret = 0; - firstaddr = lastaddr = 0; - ehdr = ef->ehdr; - if (ehdr->e_type == ET_EXEC) { -#if defined(__i386__) || defined(__amd64__) -#if __ELF_WORD_SIZE == 64 - off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */ -#else - off = - (off & 0xff000000u); /* i386 relocates after locore */ -#endif -#elif defined(__powerpc__) - /* - * On the purely virtual memory machines like e500, the kernel is - * linked against its final VA range, which is most often not - * available at the loader stage, but only after kernel initializes - * and completes its VM settings. In such cases we cannot use p_vaddr - * field directly to load ELF segments, but put them at some - * 'load-time' locations. - */ - if (off & 0xf0000000u) { - off = -(off & 0xf0000000u); - /* - * XXX the physical load address should not be hardcoded. Note - * that the Book-E kernel assumes that it's loaded at a 16MB - * boundary for now... - */ - off += 0x01000000; - ehdr->e_entry += off; -#ifdef ELF_VERBOSE - printf("Converted entry 0x%08x\n", ehdr->e_entry); -#endif - } else - off = 0; -#elif defined(__arm__) && !defined(EFI) - /* - * The elf headers in arm kernels specify virtual addresses in all - * header fields, even the ones that should be physical addresses. - * We assume the entry point is in the first page, and masking the page - * offset will leave us with the virtual address the kernel was linked - * at. We subtract that from the load offset, making 'off' into the - * value which, when added to a virtual address in an elf header, - * translates it to a physical address. We do the va->pa conversion on - * the entry point address in the header now, so that later we can - * launch the kernel by just jumping to that address. - * - * When booting from UEFI the copyin and copyout functions handle - * adjusting the location relative to the first virtual address. - * Because of this there is no need to adjust the offset or entry - * point address as these will both be handled by the efi code. - */ - off -= ehdr->e_entry & ~PAGE_MASK; - ehdr->e_entry += off; -#ifdef ELF_VERBOSE - printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off); -#endif -#else - off = 0; /* other archs use direct mapped kernels */ -#endif - } - ef->off = off; - - if (ef->kernel) - __elfN(relocation_offset) = off; - - if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n"); - goto out; - } - phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; i++) { - /* We want to load PT_LOAD segments only.. */ - if (phdr[i].p_type != PT_LOAD) - continue; - -#ifdef ELF_VERBOSE - printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx", - (long)phdr[i].p_filesz, (long)phdr[i].p_offset, - (long)(phdr[i].p_vaddr + off), - (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); -#else - if ((phdr[i].p_flags & PF_W) == 0) { - printf("text=0x%lx ", (long)phdr[i].p_filesz); - } else { - printf("data=0x%lx", (long)phdr[i].p_filesz); - if (phdr[i].p_filesz < phdr[i].p_memsz) - printf("+0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz)); - printf(" "); - } -#endif - fpcopy = 0; - if (ef->firstlen > phdr[i].p_offset) { - fpcopy = ef->firstlen - phdr[i].p_offset; - archsw.arch_copyin(ef->firstpage + phdr[i].p_offset, - phdr[i].p_vaddr + off, fpcopy); - } - if (phdr[i].p_filesz > fpcopy) { - if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy, - phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_loadimage: read failed\n"); - goto out; - } - } - /* clear space from oversized segments; eg: bss */ - if (phdr[i].p_filesz < phdr[i].p_memsz) { -#ifdef ELF_VERBOSE - printf(" (bss: 0x%lx-0x%lx)", - (long)(phdr[i].p_vaddr + off + phdr[i].p_filesz), - (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); -#endif - - kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz, - phdr[i].p_memsz - phdr[i].p_filesz); - } -#ifdef ELF_VERBOSE - printf("\n"); -#endif - - if (archsw.arch_loadseg != NULL) - archsw.arch_loadseg(ehdr, phdr + i, off); - - if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off)) - firstaddr = phdr[i].p_vaddr + off; - if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz)) - lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz; - } - lastaddr = roundup(lastaddr, sizeof(long)); - - /* - * Get the section headers. We need this for finding the .ctors - * section as well as for loading any symbols. Both may be hard - * to do if reading from a .gz file as it involves seeking. I - * think the rule is going to have to be that you must strip a - * file to remove symbols before gzipping it. - */ - chunk = ehdr->e_shnum * ehdr->e_shentsize; - if (chunk == 0 || ehdr->e_shoff == 0) - goto nosyms; - shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk); - if (shdr == NULL) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_loadimage: failed to read section headers"); - goto nosyms; - } - file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr); - - /* - * Read the section string table and look for the .ctors section. - * We need to tell the kernel where it is so that it can call the - * ctors. - */ - chunk = shdr[ehdr->e_shstrndx].sh_size; - if (chunk) { - shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset, chunk); - if (shstr) { - for (i = 0; i < ehdr->e_shnum; i++) { - if (strcmp(shstr + shdr[i].sh_name, ".ctors") != 0) - continue; - ctors = shdr[i].sh_addr; - file_addmetadata(fp, MODINFOMD_CTORS_ADDR, sizeof(ctors), - &ctors); - size = shdr[i].sh_size; - file_addmetadata(fp, MODINFOMD_CTORS_SIZE, sizeof(size), - &size); - break; - } - free(shstr); - } - } - - /* - * Now load any symbols. - */ - symtabindex = -1; - symstrindex = -1; - for (i = 0; i < ehdr->e_shnum; i++) { - if (shdr[i].sh_type != SHT_SYMTAB) - continue; - for (j = 0; j < ehdr->e_phnum; j++) { - if (phdr[j].p_type != PT_LOAD) - continue; - if (shdr[i].sh_offset >= phdr[j].p_offset && - (shdr[i].sh_offset + shdr[i].sh_size <= - phdr[j].p_offset + phdr[j].p_filesz)) { - shdr[i].sh_offset = 0; - shdr[i].sh_size = 0; - break; - } - } - if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0) - continue; /* alread loaded in a PT_LOAD above */ - /* Save it for loading below */ - symtabindex = i; - symstrindex = shdr[i].sh_link; - } - if (symtabindex < 0 || symstrindex < 0) - goto nosyms; - - /* Ok, committed to a load. */ -#ifndef ELF_VERBOSE - printf("syms=["); -#endif - ssym = lastaddr; - for (i = symtabindex; i >= 0; i = symstrindex) { -#ifdef ELF_VERBOSE - char *secname; - - switch(shdr[i].sh_type) { - case SHT_SYMTAB: /* Symbol table */ - secname = "symtab"; - break; - case SHT_STRTAB: /* String table */ - secname = "strtab"; - break; - default: - secname = "WHOA!!"; - break; - } -#endif - - size = shdr[i].sh_size; - archsw.arch_copyin(&size, lastaddr, sizeof(size)); - lastaddr += sizeof(size); - -#ifdef ELF_VERBOSE - printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname, - (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset, - (uintmax_t)lastaddr, (uintmax_t)(lastaddr + shdr[i].sh_size)); -#else - if (i == symstrindex) - printf("+"); - printf("0x%lx+0x%lx", (long)sizeof(size), (long)size); -#endif - - if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!"); - lastaddr = ssym; - ssym = 0; - goto nosyms; - } - result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size); - if (result < 0 || (size_t)result != shdr[i].sh_size) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! (%ju != %ju)", (uintmax_t)result, - (uintmax_t)shdr[i].sh_size); - lastaddr = ssym; - ssym = 0; - goto nosyms; - } - /* Reset offsets relative to ssym */ - lastaddr += shdr[i].sh_size; - lastaddr = roundup(lastaddr, sizeof(size)); - if (i == symtabindex) - symtabindex = -1; - else if (i == symstrindex) - symstrindex = -1; - } - esym = lastaddr; -#ifndef ELF_VERBOSE - printf("]"); -#endif - - file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym); - file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym); - -nosyms: - printf("\n"); - - ret = lastaddr - firstaddr; - fp->f_addr = firstaddr; - - php = NULL; - for (i = 0; i < ehdr->e_phnum; i++) { - if (phdr[i].p_type == PT_DYNAMIC) { - php = phdr + i; - adp = php->p_vaddr; - file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp); - break; - } - } - - if (php == NULL) /* this is bad, we cannot get to symbols or _DYNAMIC */ - goto out; - - ndp = php->p_filesz / sizeof(Elf_Dyn); - if (ndp == 0) - goto out; - dp = malloc(php->p_filesz); - if (dp == NULL) - goto out; - archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz); - - ef->strsz = 0; - for (i = 0; i < ndp; i++) { - if (dp[i].d_tag == 0) - break; - switch (dp[i].d_tag) { - case DT_HASH: - ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_STRTAB: - ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_STRSZ: - ef->strsz = dp[i].d_un.d_val; - break; - case DT_SYMTAB: - ef->symtab = (Elf_Sym*)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_REL: - ef->rel = (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_RELSZ: - ef->relsz = dp[i].d_un.d_val; - break; - case DT_RELA: - ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_RELASZ: - ef->relasz = dp[i].d_un.d_val; - break; - default: - break; - } - } - if (ef->hashtab == NULL || ef->symtab == NULL || - ef->strtab == NULL || ef->strsz == 0) - goto out; - COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets)); - COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains)); - ef->buckets = ef->hashtab + 2; - ef->chains = ef->buckets + ef->nbuckets; - - if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0) - return 0; - p_start = sym.st_value + ef->off; - if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0) - return ENOENT; - p_end = sym.st_value + ef->off; - - if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0) - goto out; - - if (ef->kernel) /* kernel must not depend on anything */ - goto out; - -out: - if (dp) - free(dp); - if (shdr) - free(shdr); - return ret; -} - -static char invalid_name[] = "bad"; - -char * -fake_modname(const char *name) -{ - const char *sp, *ep; - char *fp; - size_t len; - - sp = strrchr(name, '/'); - if (sp) - sp++; - else - sp = name; - ep = strrchr(name, '.'); - if (ep) { - if (ep == name) { - sp = invalid_name; - ep = invalid_name + sizeof(invalid_name) - 1; - } - } else - ep = name + strlen(name); - len = ep - sp; - fp = malloc(len + 1); - if (fp == NULL) - return NULL; - memcpy(fp, sp, len); - fp[len] = '\0'; - return fp; -} - -#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 -struct mod_metadata64 { - int md_version; /* structure version MDTV_* */ - int md_type; /* type of entry MDT_* */ - u_int64_t md_data; /* specific data */ - u_int64_t md_cval; /* common string label */ -}; -#endif -#if defined(__amd64__) && __ELF_WORD_SIZE == 32 -struct mod_metadata32 { - int md_version; /* structure version MDTV_* */ - int md_type; /* type of entry MDT_* */ - u_int32_t md_data; /* specific data */ - u_int32_t md_cval; /* common string label */ -}; -#endif - -int -__elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest) -{ - struct elf_file ef; - int err, i, j; - Elf_Shdr *sh_meta, *shdr = NULL; - Elf_Shdr *sh_data[2]; - char *shstrtab = NULL; - size_t size; - Elf_Addr p_start, p_end; - - bzero(&ef, sizeof(struct elf_file)); - ef.fd = -1; - - err = __elfN(load_elf_header)(fp->f_name, &ef); - if (err != 0) - goto out; - - if (ef.kernel == 1 || ef.ehdr->e_type == ET_EXEC) { - ef.kernel = 1; - } else if (ef.ehdr->e_type != ET_DYN) { - err = EFTYPE; - goto out; - } - - size = ef.ehdr->e_shnum * ef.ehdr->e_shentsize; - shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size); - if (shdr == NULL) { - err = ENOMEM; - goto out; - } - - /* Load shstrtab. */ - shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset, - shdr[ef.ehdr->e_shstrndx].sh_size); - if (shstrtab == NULL) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "load_modmetadata: unable to load shstrtab\n"); - err = EFTYPE; - goto out; - } - - /* Find set_modmetadata_set and data sections. */ - sh_data[0] = sh_data[1] = sh_meta = NULL; - for (i = 0, j = 0; i < ef.ehdr->e_shnum; i++) { - if (strcmp(&shstrtab[shdr[i].sh_name], - "set_modmetadata_set") == 0) { - sh_meta = &shdr[i]; - } - if ((strcmp(&shstrtab[shdr[i].sh_name], ".data") == 0) || - (strcmp(&shstrtab[shdr[i].sh_name], ".rodata") == 0)) { - sh_data[j++] = &shdr[i]; - } - } - if (sh_meta == NULL || sh_data[0] == NULL || sh_data[1] == NULL) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "load_modmetadata: unable to find set_modmetadata_set or data sections\n"); - err = EFTYPE; - goto out; - } - - /* Load set_modmetadata_set into memory */ - err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset); - if (err != 0) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "load_modmetadata: unable to load set_modmetadata_set: %d\n", err); - goto out; - } - p_start = dest; - p_end = dest + sh_meta->sh_size; - dest += sh_meta->sh_size; - - /* Load data sections into memory. */ - err = kern_pread(ef.fd, dest, sh_data[0]->sh_size, - sh_data[0]->sh_offset); - if (err != 0) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "load_modmetadata: unable to load data: %d\n", err); - goto out; - } - - /* - * We have to increment the dest, so that the offset is the same into - * both the .rodata and .data sections. - */ - ef.off = -(sh_data[0]->sh_addr - dest); - dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr); - - err = kern_pread(ef.fd, dest, sh_data[1]->sh_size, - sh_data[1]->sh_offset); - if (err != 0) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "load_modmetadata: unable to load data: %d\n", err); - goto out; - } - - err = __elfN(parse_modmetadata)(fp, &ef, p_start, p_end); - if (err != 0) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "load_modmetadata: unable to parse metadata: %d\n", err); - goto out; - } - -out: - if (shstrtab != NULL) - free(shstrtab); - if (shdr != NULL) - free(shdr); - if (ef.firstpage != NULL) - free(ef.firstpage); - if (ef.fd != -1) - close(ef.fd); - return (err); -} - -int -__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef, - Elf_Addr p_start, Elf_Addr p_end) -{ - struct mod_metadata md; -#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 - struct mod_metadata64 md64; -#elif defined(__amd64__) && __ELF_WORD_SIZE == 32 - struct mod_metadata32 md32; -#endif - struct mod_depend *mdepend; - struct mod_version mver; - char *s; - int error, modcnt, minfolen; - Elf_Addr v, p; - - modcnt = 0; - p = p_start; - while (p < p_end) { - COPYOUT(p, &v, sizeof(v)); - error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v)); - if (error == EOPNOTSUPP) - v += ef->off; - else if (error != 0) - return (error); -#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 - COPYOUT(v, &md64, sizeof(md64)); - error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64)); - if (error == EOPNOTSUPP) { - md64.md_cval += ef->off; - md64.md_data += ef->off; - } else if (error != 0) - return (error); - md.md_version = md64.md_version; - md.md_type = md64.md_type; - md.md_cval = (const char *)(uintptr_t)md64.md_cval; - md.md_data = (void *)(uintptr_t)md64.md_data; -#elif defined(__amd64__) && __ELF_WORD_SIZE == 32 - COPYOUT(v, &md32, sizeof(md32)); - error = __elfN(reloc_ptr)(fp, ef, v, &md32, sizeof(md32)); - if (error == EOPNOTSUPP) { - md32.md_cval += ef->off; - md32.md_data += ef->off; - } else if (error != 0) - return (error); - md.md_version = md32.md_version; - md.md_type = md32.md_type; - md.md_cval = (const char *)(uintptr_t)md32.md_cval; - md.md_data = (void *)(uintptr_t)md32.md_data; -#else - COPYOUT(v, &md, sizeof(md)); - error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md)); - if (error == EOPNOTSUPP) { - md.md_cval += ef->off; - md.md_data = (void *)((uintptr_t)md.md_data + (uintptr_t)ef->off); - } else if (error != 0) - return (error); -#endif - p += sizeof(Elf_Addr); - switch(md.md_type) { - case MDT_DEPEND: - if (ef->kernel) /* kernel must not depend on anything */ - break; - s = strdupout((vm_offset_t)md.md_cval); - minfolen = sizeof(*mdepend) + strlen(s) + 1; - mdepend = malloc(minfolen); - if (mdepend == NULL) - return ENOMEM; - COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend)); - strcpy((char*)(mdepend + 1), s); - free(s); - file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend); - free(mdepend); - break; - case MDT_VERSION: - s = strdupout((vm_offset_t)md.md_cval); - COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); - file_addmodule(fp, s, mver.mv_version, NULL); - free(s); - modcnt++; - break; - } - } - if (modcnt == 0) { - s = fake_modname(fp->f_name); - file_addmodule(fp, s, 1, NULL); - free(s); - } - return 0; -} - -static unsigned long -elf_hash(const char *name) -{ - const unsigned char *p = (const unsigned char *) name; - unsigned long h = 0; - unsigned long g; - - while (*p != '\0') { - h = (h << 4) + *p++; - if ((g = h & 0xf0000000) != 0) - h ^= g >> 24; - h &= ~g; - } - return h; -} - -static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE) "_lookup_symbol: corrupt symbol table\n"; -int -__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name, - Elf_Sym *symp) -{ - Elf_Hashelt symnum; - Elf_Sym sym; - char *strp; - unsigned long hash; - - hash = elf_hash(name); - COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum)); - - while (symnum != STN_UNDEF) { - if (symnum >= ef->nchains) { - printf(__elfN(bad_symtable)); - return ENOENT; - } - - COPYOUT(ef->symtab + symnum, &sym, sizeof(sym)); - if (sym.st_name == 0) { - printf(__elfN(bad_symtable)); - return ENOENT; - } - - strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name)); - if (strcmp(name, strp) == 0) { - free(strp); - if (sym.st_shndx != SHN_UNDEF || - (sym.st_value != 0 && - ELF_ST_TYPE(sym.st_info) == STT_FUNC)) { - *symp = sym; - return 0; - } - return ENOENT; - } - free(strp); - COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum)); - } - return ENOENT; -} - -/* - * Apply any intra-module relocations to the value. p is the load address - * of the value and val/len is the value to be modified. This does NOT modify - * the image in-place, because this is done by kern_linker later on. - * - * Returns EOPNOTSUPP if no relocation method is supplied. - */ -static int -__elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, - Elf_Addr p, void *val, size_t len) -{ - size_t n; - Elf_Rela a; - Elf_Rel r; - int error; - - /* - * The kernel is already relocated, but we still want to apply - * offset adjustments. - */ - if (ef->kernel) - return (EOPNOTSUPP); - - for (n = 0; n < ef->relsz / sizeof(r); n++) { - COPYOUT(ef->rel + n, &r, sizeof(r)); - - error = __elfN(reloc)(ef, __elfN(symaddr), &r, ELF_RELOC_REL, - ef->off, p, val, len); - if (error != 0) - return (error); - } - for (n = 0; n < ef->relasz / sizeof(a); n++) { - COPYOUT(ef->rela + n, &a, sizeof(a)); - - error = __elfN(reloc)(ef, __elfN(symaddr), &a, ELF_RELOC_RELA, - ef->off, p, val, len); - if (error != 0) - return (error); - } - - return (0); -} - -static Elf_Addr -__elfN(symaddr)(struct elf_file *ef, Elf_Size symidx) -{ - - /* Symbol lookup by index not required here. */ - return (0); -} diff --git a/sys/boot/common/load_elf32.c b/sys/boot/common/load_elf32.c deleted file mode 100644 index 0c9f460d4863..000000000000 --- a/sys/boot/common/load_elf32.c +++ /dev/null @@ -1,7 +0,0 @@ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define __ELF_WORD_SIZE 32 -#define _MACHINE_ELF_WANT_32BIT - -#include "load_elf.c" diff --git a/sys/boot/common/load_elf32_obj.c b/sys/boot/common/load_elf32_obj.c deleted file mode 100644 index 94b089618836..000000000000 --- a/sys/boot/common/load_elf32_obj.c +++ /dev/null @@ -1,7 +0,0 @@ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define __ELF_WORD_SIZE 32 -#define _MACHINE_ELF_WANT_32BIT - -#include "load_elf_obj.c" diff --git a/sys/boot/common/load_elf64.c b/sys/boot/common/load_elf64.c deleted file mode 100644 index c29e8e3596a7..000000000000 --- a/sys/boot/common/load_elf64.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define __ELF_WORD_SIZE 64 - -#include "load_elf.c" diff --git a/sys/boot/common/load_elf64_obj.c b/sys/boot/common/load_elf64_obj.c deleted file mode 100644 index 3c9371ba0130..000000000000 --- a/sys/boot/common/load_elf64_obj.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define __ELF_WORD_SIZE 64 - -#include "load_elf_obj.c" diff --git a/sys/boot/common/load_elf_obj.c b/sys/boot/common/load_elf_obj.c deleted file mode 100644 index a32b9fde4b75..000000000000 --- a/sys/boot/common/load_elf_obj.c +++ /dev/null @@ -1,537 +0,0 @@ -/*- - * Copyright (c) 2004 Ian Dowse <iedowse@freebsd.org> - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * Copyright (c) 1998 Peter Wemm <peter@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/exec.h> -#include <sys/linker.h> -#include <sys/module.h> -#include <inttypes.h> -#include <string.h> -#include <machine/elf.h> -#include <stand.h> -#define FREEBSD_ELF -#include <link.h> - -#include "bootstrap.h" - -#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) - -#if defined(__i386__) && __ELF_WORD_SIZE == 64 -#undef ELF_TARG_CLASS -#undef ELF_TARG_MACH -#define ELF_TARG_CLASS ELFCLASS64 -#define ELF_TARG_MACH EM_X86_64 -#endif - -typedef struct elf_file { - Elf_Ehdr hdr; - Elf_Shdr *e_shdr; - - int symtabindex; /* Index of symbol table */ - int shstrindex; /* Index of section name string table */ - - int fd; - vm_offset_t off; -} *elf_file_t; - -static int __elfN(obj_loadimage)(struct preloaded_file *mp, elf_file_t ef, - u_int64_t loadaddr); -static int __elfN(obj_lookup_set)(struct preloaded_file *mp, elf_file_t ef, - const char *name, Elf_Addr *startp, Elf_Addr *stopp, int *countp); -static int __elfN(obj_reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, - Elf_Addr p, void *val, size_t len); -static int __elfN(obj_parse_modmetadata)(struct preloaded_file *mp, - elf_file_t ef); -static Elf_Addr __elfN(obj_symaddr)(struct elf_file *ef, Elf_Size symidx); - -const char *__elfN(obj_kerneltype) = "elf kernel"; -const char *__elfN(obj_moduletype) = "elf obj module"; - -/* - * Attempt to load the file (file) as an ELF module. It will be stored at - * (dest), and a pointer to a module structure describing the loaded object - * will be saved in (result). - */ -int -__elfN(obj_loadfile)(char *filename, u_int64_t dest, - struct preloaded_file **result) -{ - struct preloaded_file *fp, *kfp; - struct elf_file ef; - Elf_Ehdr *hdr; - int err; - ssize_t bytes_read; - - fp = NULL; - bzero(&ef, sizeof(struct elf_file)); - - /* - * Open the image, read and validate the ELF header - */ - if (filename == NULL) /* can't handle nameless */ - return(EFTYPE); - if ((ef.fd = open(filename, O_RDONLY)) == -1) - return(errno); - - hdr = &ef.hdr; - bytes_read = read(ef.fd, hdr, sizeof(*hdr)); - if (bytes_read != sizeof(*hdr)) { - err = EFTYPE; /* could be EIO, but may be small file */ - goto oerr; - } - - /* Is it ELF? */ - if (!IS_ELF(*hdr)) { - err = EFTYPE; - goto oerr; - } - if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ - hdr->e_ident[EI_DATA] != ELF_TARG_DATA || - hdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ - hdr->e_version != EV_CURRENT || - hdr->e_machine != ELF_TARG_MACH || /* Machine ? */ - hdr->e_type != ET_REL) { - err = EFTYPE; - goto oerr; - } - - if (hdr->e_shnum * hdr->e_shentsize == 0 || hdr->e_shoff == 0 || - hdr->e_shentsize != sizeof(Elf_Shdr)) { - err = EFTYPE; - goto oerr; - } - - kfp = file_findfile(NULL, __elfN(obj_kerneltype)); - if (kfp == NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadfile: can't load module before kernel\n"); - err = EPERM; - goto oerr; - } - - if (archsw.arch_loadaddr != NULL) - dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest); - else - dest = roundup(dest, PAGE_SIZE); - - /* - * Ok, we think we should handle this. - */ - fp = file_alloc(); - if (fp == NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadfile: cannot allocate module info\n"); - err = EPERM; - goto out; - } - fp->f_name = strdup(filename); - fp->f_type = strdup(__elfN(obj_moduletype)); - - printf("%s ", filename); - - fp->f_size = __elfN(obj_loadimage)(fp, &ef, dest); - if (fp->f_size == 0 || fp->f_addr == 0) - goto ioerr; - - /* save exec header as metadata */ - file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*hdr), hdr); - - /* Load OK, return module pointer */ - *result = (struct preloaded_file *)fp; - err = 0; - goto out; - -ioerr: - err = EIO; -oerr: - file_discard(fp); -out: - close(ef.fd); - if (ef.e_shdr != NULL) - free(ef.e_shdr); - - return(err); -} - -/* - * With the file (fd) open on the image, and (ehdr) containing - * the Elf header, load the image at (off) - */ -static int -__elfN(obj_loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) -{ - Elf_Ehdr *hdr; - Elf_Shdr *shdr, *cshdr, *lshdr; - vm_offset_t firstaddr, lastaddr; - int i, nsym, res, ret, shdrbytes, symstrindex; - - ret = 0; - firstaddr = lastaddr = (vm_offset_t)off; - hdr = &ef->hdr; - ef->off = (vm_offset_t)off; - - /* Read in the section headers. */ - shdrbytes = hdr->e_shnum * hdr->e_shentsize; - shdr = alloc_pread(ef->fd, (off_t)hdr->e_shoff, shdrbytes); - if (shdr == NULL) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadimage: read section headers failed\n"); - goto out; - } - ef->e_shdr = shdr; - - /* - * Decide where to load everything, but don't read it yet. - * We store the load address as a non-zero sh_addr value. - * Start with the code/data and bss. - */ - for (i = 0; i < hdr->e_shnum; i++) - shdr[i].sh_addr = 0; - for (i = 0; i < hdr->e_shnum; i++) { - if (shdr[i].sh_size == 0) - continue; - switch (shdr[i].sh_type) { - case SHT_PROGBITS: - case SHT_NOBITS: -#if defined(__i386__) || defined(__amd64__) - case SHT_X86_64_UNWIND: -#endif - lastaddr = roundup(lastaddr, shdr[i].sh_addralign); - shdr[i].sh_addr = (Elf_Addr)lastaddr; - lastaddr += shdr[i].sh_size; - break; - } - } - - /* Symbols. */ - nsym = 0; - for (i = 0; i < hdr->e_shnum; i++) { - switch (shdr[i].sh_type) { - case SHT_SYMTAB: - nsym++; - ef->symtabindex = i; - shdr[i].sh_addr = (Elf_Addr)lastaddr; - lastaddr += shdr[i].sh_size; - break; - } - } - if (nsym != 1) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadimage: file has no valid symbol table\n"); - goto out; - } - lastaddr = roundup(lastaddr, shdr[ef->symtabindex].sh_addralign); - shdr[ef->symtabindex].sh_addr = (Elf_Addr)lastaddr; - lastaddr += shdr[ef->symtabindex].sh_size; - - symstrindex = shdr[ef->symtabindex].sh_link; - if (symstrindex < 0 || symstrindex >= hdr->e_shnum || - shdr[symstrindex].sh_type != SHT_STRTAB) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadimage: file has invalid symbol strings\n"); - goto out; - } - lastaddr = roundup(lastaddr, shdr[symstrindex].sh_addralign); - shdr[symstrindex].sh_addr = (Elf_Addr)lastaddr; - lastaddr += shdr[symstrindex].sh_size; - - /* Section names. */ - if (hdr->e_shstrndx == 0 || hdr->e_shstrndx >= hdr->e_shnum || - shdr[hdr->e_shstrndx].sh_type != SHT_STRTAB) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadimage: file has no section names\n"); - goto out; - } - ef->shstrindex = hdr->e_shstrndx; - lastaddr = roundup(lastaddr, shdr[ef->shstrindex].sh_addralign); - shdr[ef->shstrindex].sh_addr = (Elf_Addr)lastaddr; - lastaddr += shdr[ef->shstrindex].sh_size; - - /* Relocation tables. */ - for (i = 0; i < hdr->e_shnum; i++) { - switch (shdr[i].sh_type) { - case SHT_REL: - case SHT_RELA: - lastaddr = roundup(lastaddr, shdr[i].sh_addralign); - shdr[i].sh_addr = (Elf_Addr)lastaddr; - lastaddr += shdr[i].sh_size; - break; - } - } - - /* Clear the whole area, including bss regions. */ - kern_bzero(firstaddr, lastaddr - firstaddr); - - /* Figure section with the lowest file offset we haven't loaded yet. */ - for (cshdr = NULL; /* none */; /* none */) - { - /* - * Find next section to load. The complexity of this loop is - * O(n^2), but with the number of sections being typically - * small, we do not care. - */ - lshdr = cshdr; - - for (i = 0; i < hdr->e_shnum; i++) { - if (shdr[i].sh_addr == 0 || - shdr[i].sh_type == SHT_NOBITS) - continue; - /* Skip sections that were loaded already. */ - if (lshdr != NULL && - lshdr->sh_offset >= shdr[i].sh_offset) - continue; - /* Find section with smallest offset. */ - if (cshdr == lshdr || - cshdr->sh_offset > shdr[i].sh_offset) - cshdr = &shdr[i]; - } - - if (cshdr == lshdr) - break; - - if (kern_pread(ef->fd, (vm_offset_t)cshdr->sh_addr, - cshdr->sh_size, (off_t)cshdr->sh_offset) != 0) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_obj_loadimage: read failed\n"); - goto out; - } - } - - file_addmetadata(fp, MODINFOMD_SHDR, shdrbytes, shdr); - - res = __elfN(obj_parse_modmetadata)(fp, ef); - if (res != 0) - goto out; - - ret = lastaddr - firstaddr; - fp->f_addr = firstaddr; - - printf("size 0x%lx at 0x%lx", (u_long)ret, (u_long)firstaddr); - -out: - printf("\n"); - return ret; -} - -#if defined(__i386__) && __ELF_WORD_SIZE == 64 -struct mod_metadata64 { - int md_version; /* structure version MDTV_* */ - int md_type; /* type of entry MDT_* */ - u_int64_t md_data; /* specific data */ - u_int64_t md_cval; /* common string label */ -}; -#endif - -int -__elfN(obj_parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef) -{ - struct mod_metadata md; -#if defined(__i386__) && __ELF_WORD_SIZE == 64 - struct mod_metadata64 md64; -#endif - struct mod_depend *mdepend; - struct mod_version mver; - char *s; - int error, modcnt, minfolen; - Elf_Addr v, p, p_stop; - - if (__elfN(obj_lookup_set)(fp, ef, "modmetadata_set", &p, &p_stop, - &modcnt) != 0) - return 0; - - modcnt = 0; - while (p < p_stop) { - COPYOUT(p, &v, sizeof(v)); - error = __elfN(obj_reloc_ptr)(fp, ef, p, &v, sizeof(v)); - if (error != 0) - return (error); -#if defined(__i386__) && __ELF_WORD_SIZE == 64 - COPYOUT(v, &md64, sizeof(md64)); - error = __elfN(obj_reloc_ptr)(fp, ef, v, &md64, sizeof(md64)); - if (error != 0) - return (error); - md.md_version = md64.md_version; - md.md_type = md64.md_type; - md.md_cval = (const char *)(uintptr_t)md64.md_cval; - md.md_data = (void *)(uintptr_t)md64.md_data; -#else - COPYOUT(v, &md, sizeof(md)); - error = __elfN(obj_reloc_ptr)(fp, ef, v, &md, sizeof(md)); - if (error != 0) - return (error); -#endif - p += sizeof(Elf_Addr); - switch(md.md_type) { - case MDT_DEPEND: - s = strdupout((vm_offset_t)md.md_cval); - minfolen = sizeof(*mdepend) + strlen(s) + 1; - mdepend = malloc(minfolen); - if (mdepend == NULL) - return ENOMEM; - COPYOUT((vm_offset_t)md.md_data, mdepend, - sizeof(*mdepend)); - strcpy((char*)(mdepend + 1), s); - free(s); - file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, - mdepend); - free(mdepend); - break; - case MDT_VERSION: - s = strdupout((vm_offset_t)md.md_cval); - COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); - file_addmodule(fp, s, mver.mv_version, NULL); - free(s); - modcnt++; - break; - case MDT_MODULE: - case MDT_PNP_INFO: - break; - default: - printf("unknown type %d\n", md.md_type); - break; - } - } - return 0; -} - -static int -__elfN(obj_lookup_set)(struct preloaded_file *fp, elf_file_t ef, - const char* name, Elf_Addr *startp, Elf_Addr *stopp, int *countp) -{ - Elf_Ehdr *hdr; - Elf_Shdr *shdr; - char *p; - vm_offset_t shstrtab; - int i; - - hdr = &ef->hdr; - shdr = ef->e_shdr; - shstrtab = shdr[ef->shstrindex].sh_addr; - - for (i = 0; i < hdr->e_shnum; i++) { - if (shdr[i].sh_type != SHT_PROGBITS) - continue; - if (shdr[i].sh_name == 0) - continue; - p = strdupout(shstrtab + shdr[i].sh_name); - if (strncmp(p, "set_", 4) == 0 && strcmp(p + 4, name) == 0) { - *startp = shdr[i].sh_addr; - *stopp = shdr[i].sh_addr + shdr[i].sh_size; - *countp = (*stopp - *startp) / sizeof(Elf_Addr); - free(p); - return (0); - } - free(p); - } - - return (ESRCH); -} - -/* - * Apply any intra-module relocations to the value. p is the load address - * of the value and val/len is the value to be modified. This does NOT modify - * the image in-place, because this is done by kern_linker later on. - */ -static int -__elfN(obj_reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p, - void *val, size_t len) -{ - Elf_Ehdr *hdr; - Elf_Shdr *shdr; - Elf_Addr off = p; - Elf_Addr base; - Elf_Rela a, *abase; - Elf_Rel r, *rbase; - int error, i, j, nrel, nrela; - - hdr = &ef->hdr; - shdr = ef->e_shdr; - - for (i = 0; i < hdr->e_shnum; i++) { - if (shdr[i].sh_type != SHT_RELA && shdr[i].sh_type != SHT_REL) - continue; - base = shdr[shdr[i].sh_info].sh_addr; - if (base == 0 || shdr[i].sh_addr == 0) - continue; - if (off < base || off + len > base + - shdr[shdr[i].sh_info].sh_size) - continue; - - switch (shdr[i].sh_type) { - case SHT_RELA: - abase = (Elf_Rela *)(intptr_t)shdr[i].sh_addr; - - nrela = shdr[i].sh_size / sizeof(Elf_Rela); - for (j = 0; j < nrela; j++) { - COPYOUT(abase + j, &a, sizeof(a)); - - error = __elfN(reloc)(ef, __elfN(obj_symaddr), - &a, ELF_RELOC_RELA, base, off, val, len); - if (error != 0) - return (error); - } - break; - case SHT_REL: - rbase = (Elf_Rel *)(intptr_t)shdr[i].sh_addr; - - nrel = shdr[i].sh_size / sizeof(Elf_Rel); - for (j = 0; j < nrel; j++) { - COPYOUT(rbase + j, &r, sizeof(r)); - - error = __elfN(reloc)(ef, __elfN(obj_symaddr), - &r, ELF_RELOC_REL, base, off, val, len); - if (error != 0) - return (error); - } - break; - } - } - return (0); -} - -/* Look up the address of a specified symbol. */ -static Elf_Addr -__elfN(obj_symaddr)(struct elf_file *ef, Elf_Size symidx) -{ - Elf_Sym sym; - Elf_Addr base; - - if (symidx >= ef->e_shdr[ef->symtabindex].sh_size / sizeof(Elf_Sym)) - return (0); - COPYOUT(ef->e_shdr[ef->symtabindex].sh_addr + symidx * sizeof(Elf_Sym), - &sym, sizeof(sym)); - if (sym.st_shndx == SHN_UNDEF || sym.st_shndx >= ef->hdr.e_shnum) - return (0); - base = ef->e_shdr[sym.st_shndx].sh_addr; - if (base == 0) - return (0); - return (base + sym.st_value); -} diff --git a/sys/boot/common/ls.c b/sys/boot/common/ls.c deleted file mode 100644 index cd6b7c49ea5f..000000000000 --- a/sys/boot/common/ls.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $ - */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1996 - * Matthias Drochner. 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <ufs/ufs/dinode.h> -#include <ufs/ufs/dir.h> - -#include <stand.h> -#include <string.h> - -#include "bootstrap.h" - -static char typestr[] = "?fc?d?b? ?l?s?w"; - -static int ls_getdir(char **pathp); - -COMMAND_SET(ls, "ls", "list files", command_ls); - -static int -command_ls(int argc, char *argv[]) -{ - int fd; - struct stat sb; - struct dirent *d; - char *buf, *path; - char lbuf[128]; /* one line */ - int result, ch; - int verbose; - - result = CMD_OK; - fd = -1; - verbose = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "l")) != -1) { - switch (ch) { - case 'l': - verbose = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return (CMD_OK); - } - } - argv += (optind - 1); - argc -= (optind - 1); - - if (argc < 2) { - path = ""; - } else { - path = argv[1]; - } - - if (stat(path, &sb) == 0 && !S_ISDIR(sb.st_mode)) { - if (verbose) { - printf(" %c %8d %s\n", - typestr[sb.st_mode >> 12], - (int)sb.st_size, path); - } else { - printf(" %c %s\n", - typestr[sb.st_mode >> 12], path); - } - return (CMD_OK); - } - - fd = ls_getdir(&path); - if (fd == -1) { - result = CMD_ERROR; - goto out; - } - pager_open(); - pager_output(path); - pager_output("\n"); - - while ((d = readdirfd(fd)) != NULL) { - if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { - if (d->d_type == 0 || verbose) { - /* stat the file, if possible */ - sb.st_size = 0; - sb.st_mode = 0; - buf = malloc(strlen(path) + strlen(d->d_name) + 2); - if (buf != NULL) { - sprintf(buf, "%s/%s", path, d->d_name); - /* ignore return, could be symlink, etc. */ - if (stat(buf, &sb)) { - sb.st_size = 0; - sb.st_mode = 0; - } - free(buf); - } - } - if (verbose) { - snprintf(lbuf, sizeof(lbuf), " %c %8d %s\n", - typestr[d->d_type? d->d_type:sb.st_mode >> 12], - (int)sb.st_size, d->d_name); - } else { - snprintf(lbuf, sizeof(lbuf), " %c %s\n", - typestr[d->d_type? d->d_type:sb.st_mode >> 12], d->d_name); - } - if (pager_output(lbuf)) - goto out; - } - } - out: - pager_close(); - if (fd != -1) - close(fd); - free(path); /* ls_getdir() did allocate path */ - return (result); -} - -/* - * Given (path) containing a vaguely reasonable path specification, return an fd - * on the directory, and an allocated copy of the path to the directory. - */ -static int -ls_getdir(char **pathp) -{ - struct stat sb; - int fd; - const char *cp; - char *path; - - fd = -1; - - /* one extra byte for a possible trailing slash required */ - path = malloc(strlen(*pathp) + 2); - if (path == NULL) { - snprintf(command_errbuf, sizeof (command_errbuf), - "out of memory"); - goto out; - } - strcpy(path, *pathp); - - /* Make sure the path is respectable to begin with */ - if (archsw.arch_getdev(NULL, path, &cp)) { - snprintf(command_errbuf, sizeof(command_errbuf), - "bad path '%s'", path); - goto out; - } - - /* If there's no path on the device, assume '/' */ - if (*cp == 0) - strcat(path, "/"); - - fd = open(path, O_RDONLY); - if (fd < 0) { - snprintf(command_errbuf, sizeof(command_errbuf), - "open '%s' failed: %s", path, strerror(errno)); - goto out; - } - if (fstat(fd, &sb) < 0) { - snprintf(command_errbuf, sizeof(command_errbuf), - "stat failed: %s", strerror(errno)); - goto out; - } - if (!S_ISDIR(sb.st_mode)) { - snprintf(command_errbuf, sizeof(command_errbuf), - "%s: %s", path, strerror(ENOTDIR)); - goto out; - } - - *pathp = path; - return (fd); - - out: - free(path); - *pathp = NULL; - if (fd != -1) - close(fd); - return (-1); -} diff --git a/sys/boot/common/md.c b/sys/boot/common/md.c deleted file mode 100644 index 5585218b3276..000000000000 --- a/sys/boot/common/md.c +++ /dev/null @@ -1,157 +0,0 @@ -/*- - * Copyright (c) 2009 Marcel Moolenaar - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <sys/param.h> -#include <sys/endian.h> -#include <sys/queue.h> -#include <machine/stdarg.h> - -#include "bootstrap.h" - -#define MD_BLOCK_SIZE 512 - -#ifndef MD_IMAGE_SIZE -#error Must be compiled with MD_IMAGE_SIZE defined -#endif -#if (MD_IMAGE_SIZE == 0 || MD_IMAGE_SIZE % MD_BLOCK_SIZE) -#error Image size must be a multiple of 512. -#endif - -/* - * Preloaded image gets put here. - * Applications that patch the object with the image can determine - * the size looking at the start and end markers (strings), - * so we want them contiguous. - */ -static struct { - u_char start[MD_IMAGE_SIZE]; - u_char end[128]; -} md_image = { - .start = "MFS Filesystem goes here", - .end = "MFS Filesystem had better STOP here", -}; - -/* devsw I/F */ -static int md_init(void); -static int md_strategy(void *, int, daddr_t, size_t, char *, size_t *); -static int md_open(struct open_file *, ...); -static int md_close(struct open_file *); -static int md_print(int); - -struct devsw md_dev = { - "md", - DEVT_DISK, - md_init, - md_strategy, - md_open, - md_close, - noioctl, - md_print, - NULL -}; - -static int -md_init(void) -{ - - return (0); -} - -static int -md_strategy(void *devdata, int rw, daddr_t blk, size_t size, - char *buf, size_t *rsize) -{ - struct devdesc *dev = (struct devdesc *)devdata; - size_t ofs; - - if (dev->d_unit != 0) - return (ENXIO); - - if (blk < 0 || blk >= (MD_IMAGE_SIZE / MD_BLOCK_SIZE)) - return (EIO); - - if (size % MD_BLOCK_SIZE) - return (EIO); - - ofs = blk * MD_BLOCK_SIZE; - if ((ofs + size) > MD_IMAGE_SIZE) - size = MD_IMAGE_SIZE - ofs; - - if (rsize != NULL) - *rsize = size; - - switch (rw & F_MASK) { - case F_READ: - bcopy(md_image.start + ofs, buf, size); - return (0); - case F_WRITE: - bcopy(buf, md_image.start + ofs, size); - return (0); - } - - return (ENODEV); -} - -static int -md_open(struct open_file *f, ...) -{ - va_list ap; - struct devdesc *dev; - - va_start(ap, f); - dev = va_arg(ap, struct devdesc *); - va_end(ap); - - if (dev->d_unit != 0) - return (ENXIO); - - return (0); -} - -static int -md_close(struct open_file *f) -{ - struct devdesc *dev; - - dev = (struct devdesc *)(f->f_devdata); - return ((dev->d_unit != 0) ? ENXIO : 0); -} - -static int -md_print(int verbose) -{ - - printf("%s devices:", md_dev.dv_name); - if (pager_output("\n") != 0) - return (1); - - printf("MD (%u bytes)", MD_IMAGE_SIZE); - return (pager_output("\n")); -} diff --git a/sys/boot/common/merge_help.awk b/sys/boot/common/merge_help.awk deleted file mode 100644 index 1070f73f1fe9..000000000000 --- a/sys/boot/common/merge_help.awk +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/awk -f -# -# $FreeBSD$ -# -# Merge two boot loader help files for FreeBSD 3.0 -# Joe Abley <jabley@patho.gen.nz> - -BEGIN \ -{ - state = 0; - first = -1; - ind = 0; -} - -# beginning of first command -/^###/ && (state == 0) \ -{ - state = 1; - next; -} - -# entry header -/^# T[[:graph:]]+ (S[[:graph:]]+ )*D[[:graph:]][[:print:]]*$/ && (state == 1) \ -{ - match($0, " T[[:graph:]]+"); - T = substr($0, RSTART + 2, RLENGTH - 2); - match($0, " S[[:graph:]]+"); - SSTART = RSTART - S = (RLENGTH == -1) ? "" : substr($0, RSTART + 2, RLENGTH - 2); - match($0, " D[[:graph:]][[:print:]]*$"); - D = substr($0, RSTART + 2); - if (SSTART > RSTART) - S = ""; - - # find a suitable place to store this one... - ind++; - if (ind == 1) - { - first = ind; - help[ind, "T"] = T; - help[ind, "S"] = S; - help[ind, "link"] = -1; - } else { - i = first; j = -1; - while (help[i, "T"] help[i, "S"] < T S) - { - j = i; - i = help[i, "link"]; - if (i == -1) break; - } - - if (i == -1) - { - help[j, "link"] = ind; - help[ind, "link"] = -1; - } else { - help[ind, "link"] = i; - if (j == -1) - first = ind; - else - help[j, "link"] = ind; - } - } - help[ind, "T"] = T; - help[ind, "S"] = S; - help[ind, "D"] = D; - - # set our state - state = 2; - help[ind, "text"] = 0; - next; -} - -# end of last command, beginning of next one -/^###/ && (state == 2) \ -{ - state = 1; -} - -(state == 2) \ -{ - sub("[[:blank:]]+$", ""); - if (help[ind, "text"] == 0 && $0 ~ /^[[:blank:]]*$/) next; - help[ind, "text", help[ind, "text"]] = $0; - help[ind, "text"]++; - next; -} - -# show them what we have (it's already sorted in help[]) -END \ -{ - node = first; - while (node != -1) - { - printf "################################################################################\n"; - printf "# T%s ", help[node, "T"]; - if (help[node, "S"] != "") printf "S%s ", help[node, "S"]; - printf "D%s\n\n", help[node, "D"]; - for (i = 0; i < help[node, "text"]; i++) - printf "%s\n", help[node, "text", i]; - node = help[node, "link"]; - } - printf "################################################################################\n"; -} diff --git a/sys/boot/common/misc.c b/sys/boot/common/misc.c deleted file mode 100644 index 9b938afdf8c8..000000000000 --- a/sys/boot/common/misc.c +++ /dev/null @@ -1,219 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <string.h> -#include <stand.h> -#include <bootstrap.h> - -/* - * 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(int fd, vm_offset_t dest, size_t len, off_t off) -{ - - if (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. - */ -void * -alloc_pread(int 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 - return (NULL); - } - if (lseek(fd, off, SEEK_SET) == -1) { -#ifdef DEBUG - printf("\nlseek failed\n"); -#endif - free(buf); - return (NULL); - } - if ((size_t)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 ", *(u_int8_t *)(line + x)); - } else { - emit("-- "); - } - if (x == 7) - emit(" "); - } - emit(" |"); - for (x = 0; x < 16; x++) { - if ((line + x) < (region + len)) { - c = *(u_int8_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)(); -} diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c deleted file mode 100644 index d651ad10bc86..000000000000 --- a/sys/boot/common/module.c +++ /dev/null @@ -1,1095 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * file/module function dispatcher, support, etc. - */ - -#include <stand.h> -#include <string.h> -#include <sys/param.h> -#include <sys/linker.h> -#include <sys/module.h> -#include <sys/queue.h> -#include <sys/stdint.h> - -#include "bootstrap.h" - -#define MDIR_REMOVED 0x0001 -#define MDIR_NOHINTS 0x0002 - -struct moduledir { - char *d_path; /* path of modules directory */ - u_char *d_hints; /* content of linker.hints file */ - int d_hintsz; /* size of hints data */ - int d_flags; - STAILQ_ENTRY(moduledir) d_link; -}; - -static int file_load(char *filename, vm_offset_t dest, struct preloaded_file **result); -static int file_load_dependencies(struct preloaded_file *base_mod); -static char * file_search(const char *name, char **extlist); -static struct kernel_module * file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo); -static int file_havepath(const char *name); -static char *mod_searchmodule(char *name, struct mod_depend *verinfo); -static void file_insert_tail(struct preloaded_file *mp); -struct file_metadata* metadata_next(struct file_metadata *base_mp, int type); -static void moduledir_readhints(struct moduledir *mdp); -static void moduledir_rebuild(void); - -/* load address should be tweaked by first module loaded (kernel) */ -static vm_offset_t loadaddr = 0; - -#if defined(LOADER_FDT_SUPPORT) -static const char *default_searchpath = - "/boot/kernel;/boot/modules;/boot/dtb"; -#else -static const char *default_searchpath ="/boot/kernel;/boot/modules"; -#endif - -static STAILQ_HEAD(, moduledir) moduledir_list = STAILQ_HEAD_INITIALIZER(moduledir_list); - -struct preloaded_file *preloaded_files = NULL; - -static char *kld_ext_list[] = { - ".ko", - "", - ".debug", - NULL -}; - - -/* - * load an object, either a disk file or code module. - * - * To load a file, the syntax is: - * - * load -t <type> <path> - * - * code modules are loaded as: - * - * load <path> <options> - */ - -COMMAND_SET(load, "load", "load a kernel or module", command_load); - -static int -command_load(int argc, char *argv[]) -{ - struct preloaded_file *fp; - char *typestr; - int dofile, dokld, ch, error; - - dokld = dofile = 0; - optind = 1; - optreset = 1; - typestr = NULL; - if (argc == 1) { - command_errmsg = "no filename specified"; - return (CMD_CRIT); - } - while ((ch = getopt(argc, argv, "kt:")) != -1) { - switch(ch) { - case 'k': - dokld = 1; - break; - case 't': - typestr = optarg; - dofile = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return (CMD_OK); - } - } - argv += (optind - 1); - argc -= (optind - 1); - - /* - * Request to load a raw file? - */ - if (dofile) { - if ((argc != 2) || (typestr == NULL) || (*typestr == 0)) { - command_errmsg = "invalid load type"; - return (CMD_CRIT); - } - - fp = file_findfile(argv[1], typestr); - if (fp) { - snprintf(command_errbuf, sizeof(command_errbuf), - "warning: file '%s' already loaded", argv[1]); - return (CMD_WARN); - } - - if (file_loadraw(argv[1], typestr, 1) != NULL) - return (CMD_OK); - - /* Failing to load mfs_root is never going to end well! */ - if (strcmp("mfs_root", typestr) == 0) - return (CMD_FATAL); - - return (CMD_ERROR); - } - /* - * Do we have explicit KLD load ? - */ - if (dokld || file_havepath(argv[1])) { - error = mod_loadkld(argv[1], argc - 2, argv + 2); - if (error == EEXIST) { - snprintf(command_errbuf, sizeof(command_errbuf), - "warning: KLD '%s' already loaded", argv[1]); - return (CMD_WARN); - } - - return (error == 0 ? CMD_OK : CMD_CRIT); - } - /* - * Looks like a request for a module. - */ - error = mod_load(argv[1], NULL, argc - 2, argv + 2); - if (error == EEXIST) { - snprintf(command_errbuf, sizeof(command_errbuf), - "warning: module '%s' already loaded", argv[1]); - return (CMD_WARN); - } - - return (error == 0 ? CMD_OK : CMD_CRIT); -} - -#ifdef LOADER_GELI_SUPPORT -COMMAND_SET(load_geli, "load_geli", "load a geli key", command_load_geli); - -static int -command_load_geli(int argc, char *argv[]) -{ - char typestr[80]; - char *cp; - int ch, num; - - if (argc < 3) { - command_errmsg = "usage is [-n key#] <prov> <file>"; - return(CMD_ERROR); - } - - num = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "n:")) != -1) { - switch(ch) { - case 'n': - num = strtol(optarg, &cp, 0); - if (cp == optarg) { - snprintf(command_errbuf, sizeof(command_errbuf), - "bad key index '%s'", optarg); - return(CMD_ERROR); - } - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); - } - } - argv += (optind - 1); - argc -= (optind - 1); - sprintf(typestr, "%s:geli_keyfile%d", argv[1], num); - return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR); -} -#endif - -void -unload(void) -{ - struct preloaded_file *fp; - - while (preloaded_files != NULL) { - fp = preloaded_files; - preloaded_files = preloaded_files->f_next; - file_discard(fp); - } - loadaddr = 0; - unsetenv("kernelname"); -} - -COMMAND_SET(unload, "unload", "unload all modules", command_unload); - -static int -command_unload(int argc, char *argv[]) -{ - unload(); - return(CMD_OK); -} - -COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); - -static int -command_lsmod(int argc, char *argv[]) -{ - struct preloaded_file *fp; - struct kernel_module *mp; - struct file_metadata *md; - char lbuf[80]; - int ch, verbose, ret = 0; - - verbose = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "v")) != -1) { - switch(ch) { - case 'v': - verbose = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); - } - } - - pager_open(); - for (fp = preloaded_files; fp; fp = fp->f_next) { - snprintf(lbuf, sizeof(lbuf), " %p: ", (void *) fp->f_addr); - pager_output(lbuf); - pager_output(fp->f_name); - snprintf(lbuf, sizeof(lbuf), " (%s, 0x%lx)\n", fp->f_type, - (long)fp->f_size); - if (pager_output(lbuf)) - break; - if (fp->f_args != NULL) { - pager_output(" args: "); - pager_output(fp->f_args); - if (pager_output("\n")) - break; - } - if (fp->f_modules) { - pager_output(" modules: "); - for (mp = fp->f_modules; mp; mp = mp->m_next) { - snprintf(lbuf, sizeof(lbuf), "%s.%d ", mp->m_name, - mp->m_version); - pager_output(lbuf); - } - if (pager_output("\n")) - break; - } - if (verbose) { - /* XXX could add some formatting smarts here to display some better */ - for (md = fp->f_metadata; md != NULL; md = md->md_next) { - snprintf(lbuf, sizeof(lbuf), " 0x%04x, 0x%lx\n", - md->md_type, (long) md->md_size); - if (pager_output(lbuf)) - break; - } - } - if (ret) - break; - } - pager_close(); - return(CMD_OK); -} - -/* - * File level interface, functions file_* - */ -int -file_load(char *filename, vm_offset_t dest, struct preloaded_file **result) -{ - static int last_file_format = 0; - struct preloaded_file *fp; - int error; - int i; - - if (archsw.arch_loadaddr != NULL) - dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest); - - error = EFTYPE; - for (i = last_file_format, fp = NULL; - file_formats[i] && fp == NULL; i++) { - error = (file_formats[i]->l_load)(filename, dest, &fp); - if (error == 0) { - fp->f_loader = last_file_format = i; /* remember the loader */ - *result = fp; - break; - } else if (last_file_format == i && i != 0) { - /* Restart from the beginning */ - i = -1; - last_file_format = 0; - fp = NULL; - continue; - } - if (error == EFTYPE) - continue; /* Unknown to this handler? */ - if (error) { - snprintf(command_errbuf, sizeof(command_errbuf), - "can't load file '%s': %s", filename, strerror(error)); - break; - } - } - return (error); -} - -static int -file_load_dependencies(struct preloaded_file *base_file) -{ - struct file_metadata *md; - struct preloaded_file *fp; - struct mod_depend *verinfo; - struct kernel_module *mp; - char *dmodname; - int error; - - md = file_findmetadata(base_file, MODINFOMD_DEPLIST); - if (md == NULL) - return (0); - error = 0; - do { - verinfo = (struct mod_depend*)md->md_data; - dmodname = (char *)(verinfo + 1); - if (file_findmodule(NULL, dmodname, verinfo) == NULL) { - printf("loading required module '%s'\n", dmodname); - error = mod_load(dmodname, verinfo, 0, NULL); - if (error) - break; - /* - * If module loaded via kld name which isn't listed - * in the linker.hints file, we should check if it have - * required version. - */ - mp = file_findmodule(NULL, dmodname, verinfo); - if (mp == NULL) { - snprintf(command_errbuf, sizeof(command_errbuf), - "module '%s' exists but with wrong version", dmodname); - error = ENOENT; - break; - } - } - md = metadata_next(md, MODINFOMD_DEPLIST); - } while (md); - if (!error) - return (0); - /* Load failed; discard everything */ - while (base_file != NULL) { - fp = base_file; - base_file = base_file->f_next; - file_discard(fp); - } - return (error); -} - -/* - * We've been asked to load (fname) as (type), so just suck it in, - * no arguments or anything. - */ -struct preloaded_file * -file_loadraw(const char *fname, char *type, int insert) -{ - struct preloaded_file *fp; - char *name; - int fd, got; - vm_offset_t laddr; - - /* We can't load first */ - if ((file_findfile(NULL, NULL)) == NULL) { - command_errmsg = "can't load file before kernel"; - return(NULL); - } - - /* locate the file on the load path */ - name = file_search(fname, NULL); - if (name == NULL) { - snprintf(command_errbuf, sizeof(command_errbuf), - "can't find '%s'", fname); - return(NULL); - } - - if ((fd = open(name, O_RDONLY)) < 0) { - snprintf(command_errbuf, sizeof(command_errbuf), - "can't open '%s': %s", name, strerror(errno)); - free(name); - return(NULL); - } - - if (archsw.arch_loadaddr != NULL) - loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); - - printf("%s ", name); - - laddr = loadaddr; - for (;;) { - /* read in 4k chunks; size is not really important */ - got = archsw.arch_readin(fd, laddr, 4096); - if (got == 0) /* end of file */ - break; - if (got < 0) { /* error */ - snprintf(command_errbuf, sizeof(command_errbuf), - "error reading '%s': %s", name, strerror(errno)); - free(name); - close(fd); - return(NULL); - } - laddr += got; - } - - printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr)); - - /* Looks OK so far; create & populate control structure */ - fp = file_alloc(); - fp->f_name = strdup(name); - fp->f_type = strdup(type); - fp->f_args = NULL; - fp->f_metadata = NULL; - fp->f_loader = -1; - fp->f_addr = loadaddr; - fp->f_size = laddr - loadaddr; - - /* recognise space consumption */ - loadaddr = laddr; - - /* Add to the list of loaded files */ - if (insert != 0) - file_insert_tail(fp); - close(fd); - return(fp); -} - -/* - * Load the module (name), pass it (argc),(argv), add container file - * to the list of loaded files. - * If module is already loaded just assign new argc/argv. - */ -int -mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[]) -{ - struct kernel_module *mp; - int err; - char *filename; - - if (file_havepath(modname)) { - printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname); - return (mod_loadkld(modname, argc, argv)); - } - /* see if module is already loaded */ - mp = file_findmodule(NULL, modname, verinfo); - if (mp) { -#ifdef moduleargs - if (mp->m_args) - free(mp->m_args); - mp->m_args = unargv(argc, argv); -#endif - snprintf(command_errbuf, sizeof(command_errbuf), - "warning: module '%s' already loaded", mp->m_name); - return (0); - } - /* locate file with the module on the search path */ - filename = mod_searchmodule(modname, verinfo); - if (filename == NULL) { - snprintf(command_errbuf, sizeof(command_errbuf), - "can't find '%s'", modname); - return (ENOENT); - } - err = mod_loadkld(filename, argc, argv); - return (err); -} - -/* - * Load specified KLD. If path is omitted, then try to locate it via - * search path. - */ -int -mod_loadkld(const char *kldname, int argc, char *argv[]) -{ - struct preloaded_file *fp, *last_file; - int err; - char *filename; - - /* - * Get fully qualified KLD name - */ - filename = file_search(kldname, kld_ext_list); - if (filename == NULL) { - snprintf(command_errbuf, sizeof(command_errbuf), - "can't find '%s'", kldname); - return (ENOENT); - } - /* - * Check if KLD already loaded - */ - fp = file_findfile(filename, NULL); - if (fp) { - snprintf(command_errbuf, sizeof(command_errbuf), - "warning: KLD '%s' already loaded", filename); - free(filename); - return (0); - } - for (last_file = preloaded_files; - last_file != NULL && last_file->f_next != NULL; - last_file = last_file->f_next) - ; - - do { - err = file_load(filename, loadaddr, &fp); - if (err) - break; - fp->f_args = unargv(argc, argv); - loadaddr = fp->f_addr + fp->f_size; - file_insert_tail(fp); /* Add to the list of loaded files */ - if (file_load_dependencies(fp) != 0) { - err = ENOENT; - last_file->f_next = NULL; - loadaddr = last_file->f_addr + last_file->f_size; - fp = NULL; - break; - } - } while(0); - if (err == EFTYPE) { - snprintf(command_errbuf, sizeof(command_errbuf), - "don't know how to load module '%s'", filename); - } - if (err && fp) - file_discard(fp); - free(filename); - return (err); -} - -/* - * Find a file matching (name) and (type). - * NULL may be passed as a wildcard to either. - */ -struct preloaded_file * -file_findfile(const char *name, const char *type) -{ - struct preloaded_file *fp; - - for (fp = preloaded_files; fp != NULL; fp = fp->f_next) { - if (((name == NULL) || !strcmp(name, fp->f_name)) && - ((type == NULL) || !strcmp(type, fp->f_type))) - break; - } - return (fp); -} - -/* - * Find a module matching (name) inside of given file. - * NULL may be passed as a wildcard. - */ -struct kernel_module * -file_findmodule(struct preloaded_file *fp, char *modname, - struct mod_depend *verinfo) -{ - struct kernel_module *mp, *best; - int bestver, mver; - - if (fp == NULL) { - for (fp = preloaded_files; fp; fp = fp->f_next) { - mp = file_findmodule(fp, modname, verinfo); - if (mp) - return (mp); - } - return (NULL); - } - best = NULL; - bestver = 0; - for (mp = fp->f_modules; mp; mp = mp->m_next) { - if (strcmp(modname, mp->m_name) == 0) { - if (verinfo == NULL) - return (mp); - mver = mp->m_version; - if (mver == verinfo->md_ver_preferred) - return (mp); - if (mver >= verinfo->md_ver_minimum && - mver <= verinfo->md_ver_maximum && - mver > bestver) { - best = mp; - bestver = mver; - } - } - } - return (best); -} -/* - * Make a copy of (size) bytes of data from (p), and associate them as - * metadata of (type) to the module (mp). - */ -void -file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p) -{ - struct file_metadata *md; - - md = malloc(sizeof(struct file_metadata) - sizeof(md->md_data) + size); - md->md_size = size; - md->md_type = type; - bcopy(p, md->md_data, size); - md->md_next = fp->f_metadata; - fp->f_metadata = md; -} - -/* - * Find a metadata object of (type) associated with the file (fp) - */ -struct file_metadata * -file_findmetadata(struct preloaded_file *fp, int type) -{ - struct file_metadata *md; - - for (md = fp->f_metadata; md != NULL; md = md->md_next) - if (md->md_type == type) - break; - return(md); -} - -/* - * Remove all metadata from the file. - */ -void -file_removemetadata(struct preloaded_file *fp) -{ - struct file_metadata *md, *next; - - for (md = fp->f_metadata; md != NULL; md = next) - { - next = md->md_next; - free(md); - } - fp->f_metadata = NULL; -} - -struct file_metadata * -metadata_next(struct file_metadata *md, int type) -{ - if (md == NULL) - return (NULL); - while((md = md->md_next) != NULL) - if (md->md_type == type) - break; - return (md); -} - -static char *emptyextlist[] = { "", NULL }; - -/* - * Check if the given file is in place and return full path to it. - */ -static char * -file_lookup(const char *path, const char *name, int namelen, char **extlist) -{ - struct stat st; - char *result, *cp, **cpp; - int pathlen, extlen, len; - - pathlen = strlen(path); - extlen = 0; - if (extlist == NULL) - extlist = emptyextlist; - for (cpp = extlist; *cpp; cpp++) { - len = strlen(*cpp); - if (len > extlen) - extlen = len; - } - result = malloc(pathlen + namelen + extlen + 2); - if (result == NULL) - return (NULL); - bcopy(path, result, pathlen); - if (pathlen > 0 && result[pathlen - 1] != '/') - result[pathlen++] = '/'; - cp = result + pathlen; - bcopy(name, cp, namelen); - cp += namelen; - for (cpp = extlist; *cpp; cpp++) { - strcpy(cp, *cpp); - if (stat(result, &st) == 0 && S_ISREG(st.st_mode)) - return result; - } - free(result); - return NULL; -} - -/* - * Check if file name have any qualifiers - */ -static int -file_havepath(const char *name) -{ - const char *cp; - - archsw.arch_getdev(NULL, name, &cp); - return (cp != name || strchr(name, '/') != NULL); -} - -/* - * Attempt to find the file (name) on the module searchpath. - * If (name) is qualified in any way, we simply check it and - * return it or NULL. If it is not qualified, then we attempt - * to construct a path using entries in the environment variable - * module_path. - * - * The path we return a pointer to need never be freed, as we manage - * it internally. - */ -static char * -file_search(const char *name, char **extlist) -{ - struct moduledir *mdp; - struct stat sb; - char *result; - int namelen; - - /* Don't look for nothing */ - if (name == NULL) - return(NULL); - - if (*name == 0) - return(strdup(name)); - - if (file_havepath(name)) { - /* Qualified, so just see if it exists */ - if (stat(name, &sb) == 0) - return(strdup(name)); - return(NULL); - } - moduledir_rebuild(); - result = NULL; - namelen = strlen(name); - STAILQ_FOREACH(mdp, &moduledir_list, d_link) { - result = file_lookup(mdp->d_path, name, namelen, extlist); - if (result) - break; - } - return(result); -} - -#define INT_ALIGN(base, ptr) ptr = \ - (base) + roundup2((ptr) - (base), sizeof(int)) - -static char * -mod_search_hints(struct moduledir *mdp, const char *modname, - struct mod_depend *verinfo) -{ - u_char *cp, *recptr, *bufend, *best; - char *result; - int *intp, bestver, blen, clen, found, ival, modnamelen, reclen; - - moduledir_readhints(mdp); - modnamelen = strlen(modname); - found = 0; - result = NULL; - bestver = 0; - if (mdp->d_hints == NULL) - goto bad; - recptr = mdp->d_hints; - bufend = recptr + mdp->d_hintsz; - clen = blen = 0; - best = cp = NULL; - while (recptr < bufend && !found) { - intp = (int*)recptr; - reclen = *intp++; - ival = *intp++; - cp = (u_char*)intp; - switch (ival) { - case MDT_VERSION: - clen = *cp++; - if (clen != modnamelen || bcmp(cp, modname, clen) != 0) - break; - cp += clen; - INT_ALIGN(mdp->d_hints, cp); - ival = *(int*)cp; - cp += sizeof(int); - clen = *cp++; - if (verinfo == NULL || ival == verinfo->md_ver_preferred) { - found = 1; - break; - } - if (ival >= verinfo->md_ver_minimum && - ival <= verinfo->md_ver_maximum && - ival > bestver) { - bestver = ival; - best = cp; - blen = clen; - } - break; - default: - break; - } - recptr += reclen + sizeof(int); - } - /* - * Finally check if KLD is in the place - */ - if (found) - result = file_lookup(mdp->d_path, (const char *)cp, clen, NULL); - else if (best) - result = file_lookup(mdp->d_path, (const char *)best, blen, NULL); -bad: - /* - * If nothing found or hints is absent - fallback to the old way - * by using "kldname[.ko]" as module name. - */ - if (!found && !bestver && result == NULL) - result = file_lookup(mdp->d_path, modname, modnamelen, kld_ext_list); - return result; -} - -/* - * Attempt to locate the file containing the module (name) - */ -static char * -mod_searchmodule(char *name, struct mod_depend *verinfo) -{ - struct moduledir *mdp; - char *result; - - moduledir_rebuild(); - /* - * Now we ready to lookup module in the given directories - */ - result = NULL; - STAILQ_FOREACH(mdp, &moduledir_list, d_link) { - result = mod_search_hints(mdp, name, verinfo); - if (result) - break; - } - - return(result); -} - -int -file_addmodule(struct preloaded_file *fp, char *modname, int version, - struct kernel_module **newmp) -{ - struct kernel_module *mp; - struct mod_depend mdepend; - - bzero(&mdepend, sizeof(mdepend)); - mdepend.md_ver_preferred = version; - mp = file_findmodule(fp, modname, &mdepend); - if (mp) - return (EEXIST); - mp = malloc(sizeof(struct kernel_module)); - if (mp == NULL) - return (ENOMEM); - bzero(mp, sizeof(struct kernel_module)); - mp->m_name = strdup(modname); - mp->m_version = version; - mp->m_fp = fp; - mp->m_next = fp->f_modules; - fp->f_modules = mp; - if (newmp) - *newmp = mp; - return (0); -} - -/* - * Throw a file away - */ -void -file_discard(struct preloaded_file *fp) -{ - struct file_metadata *md, *md1; - struct kernel_module *mp, *mp1; - if (fp == NULL) - return; - md = fp->f_metadata; - while (md) { - md1 = md; - md = md->md_next; - free(md1); - } - mp = fp->f_modules; - while (mp) { - if (mp->m_name) - free(mp->m_name); - mp1 = mp; - mp = mp->m_next; - free(mp1); - } - if (fp->f_name != NULL) - free(fp->f_name); - if (fp->f_type != NULL) - free(fp->f_type); - if (fp->f_args != NULL) - free(fp->f_args); - free(fp); -} - -/* - * Allocate a new file; must be used instead of malloc() - * to ensure safe initialisation. - */ -struct preloaded_file * -file_alloc(void) -{ - struct preloaded_file *fp; - - if ((fp = malloc(sizeof(struct preloaded_file))) != NULL) { - bzero(fp, sizeof(struct preloaded_file)); - } - return (fp); -} - -/* - * Add a module to the chain - */ -static void -file_insert_tail(struct preloaded_file *fp) -{ - struct preloaded_file *cm; - - /* Append to list of loaded file */ - fp->f_next = NULL; - if (preloaded_files == NULL) { - preloaded_files = fp; - } else { - for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) - ; - cm->f_next = fp; - } -} - -static char * -moduledir_fullpath(struct moduledir *mdp, const char *fname) -{ - char *cp; - - cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2); - if (cp == NULL) - return NULL; - strcpy(cp, mdp->d_path); - strcat(cp, "/"); - strcat(cp, fname); - return (cp); -} - -/* - * Read linker.hints file into memory performing some sanity checks. - */ -static void -moduledir_readhints(struct moduledir *mdp) -{ - struct stat st; - char *path; - int fd, size, version; - - if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS)) - return; - path = moduledir_fullpath(mdp, "linker.hints"); - if (stat(path, &st) != 0 || - st.st_size < (ssize_t)(sizeof(version) + sizeof(int)) || - st.st_size > LINKER_HINTS_MAX || (fd = open(path, O_RDONLY)) < 0) { - free(path); - mdp->d_flags |= MDIR_NOHINTS; - return; - } - free(path); - size = read(fd, &version, sizeof(version)); - if (size != sizeof(version) || version != LINKER_HINTS_VERSION) - goto bad; - size = st.st_size - size; - mdp->d_hints = malloc(size); - if (mdp->d_hints == NULL) - goto bad; - if (read(fd, mdp->d_hints, size) != size) - goto bad; - mdp->d_hintsz = size; - close(fd); - return; -bad: - close(fd); - if (mdp->d_hints) { - free(mdp->d_hints); - mdp->d_hints = NULL; - } - mdp->d_flags |= MDIR_NOHINTS; - return; -} - -/* - * Extract directories from the ';' separated list, remove duplicates. - */ -static void -moduledir_rebuild(void) -{ - struct moduledir *mdp, *mtmp; - const char *path, *cp, *ep; - size_t cplen; - - path = getenv("module_path"); - if (path == NULL) - path = default_searchpath; - /* - * Rebuild list of module directories if it changed - */ - STAILQ_FOREACH(mdp, &moduledir_list, d_link) - mdp->d_flags |= MDIR_REMOVED; - - for (ep = path; *ep != 0; ep++) { - cp = ep; - for (; *ep != 0 && *ep != ';'; ep++) - ; - /* - * Ignore trailing slashes - */ - for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; cplen--) - ; - STAILQ_FOREACH(mdp, &moduledir_list, d_link) { - if (strlen(mdp->d_path) != cplen || bcmp(cp, mdp->d_path, cplen) != 0) - continue; - mdp->d_flags &= ~MDIR_REMOVED; - break; - } - if (mdp == NULL) { - mdp = malloc(sizeof(*mdp) + cplen + 1); - if (mdp == NULL) - return; - mdp->d_path = (char*)(mdp + 1); - bcopy(cp, mdp->d_path, cplen); - mdp->d_path[cplen] = 0; - mdp->d_hints = NULL; - mdp->d_flags = 0; - STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link); - } - if (*ep == 0) - break; - } - /* - * Delete unused directories if any - */ - mdp = STAILQ_FIRST(&moduledir_list); - while (mdp) { - if ((mdp->d_flags & MDIR_REMOVED) == 0) { - mdp = STAILQ_NEXT(mdp, d_link); - } else { - if (mdp->d_hints) - free(mdp->d_hints); - mtmp = mdp; - mdp = STAILQ_NEXT(mdp, d_link); - STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link); - free(mtmp); - } - } - return; -} diff --git a/sys/boot/common/newvers.sh b/sys/boot/common/newvers.sh deleted file mode 100755 index 75efeceab26b..000000000000 --- a/sys/boot/common/newvers.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh - -# -# $FreeBSD$ -# $NetBSD: newvers.sh,v 1.1 1997/07/26 01:50:38 thorpej Exp $ -# -# Copyright (c) 1984, 1986, 1990, 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. -# -# @(#)newvers.sh 8.1 (Berkeley) 4/20/94 - -tempfile=$(mktemp tmp.XXXXXX) || exit -trap "rm -f $tempfile" EXIT INT TERM - -include_metadata=true -while getopts r opt; do - case "$opt" in - r) - include_metadata= - ;; - esac -done -shift $((OPTIND - 1)) - -LC_ALL=C; export LC_ALL -u=${USER-root} h=${HOSTNAME-`hostname`} t=`date` -#r=`head -n 6 $1 | tail -n 1 | awk -F: ' { print $1 } '` -r=`awk -F: ' /^[0-9]\.[0-9]+:/ { print $1; exit }' $1` - -bootprog_info="FreeBSD/${3} ${2}, Revision ${r}\\n" -if [ -n "${include_metadata}" ]; then - bootprog_info="$bootprog_info(${t} ${u}@${h})\\n" -fi - -echo "char bootprog_info[] = \"$bootprog_info\";" > $tempfile -echo "unsigned bootprog_rev = ${r%%.*}${r##*.};" >> $tempfile -mv $tempfile vers.c diff --git a/sys/boot/common/part.c b/sys/boot/common/part.c deleted file mode 100644 index cdb1e006695d..000000000000 --- a/sys/boot/common/part.c +++ /dev/null @@ -1,898 +0,0 @@ -/*- - * Copyright (c) 2012 Andrey V. Elsukov <ae@FreeBSD.org> - * 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 AUTHORS 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 AUTHORS 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <sys/param.h> -#include <sys/diskmbr.h> -#include <sys/disklabel.h> -#include <sys/endian.h> -#include <sys/gpt.h> -#include <sys/stddef.h> -#include <sys/queue.h> -#include <sys/vtoc.h> - -#include <crc32.h> -#include <part.h> -#include <uuid.h> - -#ifdef PART_DEBUG -#define DEBUG(fmt, args...) printf("%s: " fmt "\n", __func__, ## args) -#else -#define DEBUG(fmt, args...) -#endif - -#ifdef LOADER_GPT_SUPPORT -#define MAXTBLSZ 64 -static const uuid_t gpt_uuid_unused = GPT_ENT_TYPE_UNUSED; -static const uuid_t gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; -static const uuid_t gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; -static const uuid_t gpt_uuid_efi = GPT_ENT_TYPE_EFI; -static const uuid_t gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD; -static const uuid_t gpt_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; -static const uuid_t gpt_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS; -static const uuid_t gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; -static const uuid_t gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; -static const uuid_t gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; -#endif - -struct pentry { - struct ptable_entry part; - uint64_t flags; - union { - uint8_t bsd; - uint8_t mbr; - uuid_t gpt; - uint16_t vtoc8; - } type; - STAILQ_ENTRY(pentry) entry; -}; - -struct ptable { - enum ptable_type type; - uint16_t sectorsize; - uint64_t sectors; - - STAILQ_HEAD(, pentry) entries; -}; - -static struct parttypes { - enum partition_type type; - const char *desc; -} ptypes[] = { - { PART_UNKNOWN, "Unknown" }, - { PART_EFI, "EFI" }, - { PART_FREEBSD, "FreeBSD" }, - { PART_FREEBSD_BOOT, "FreeBSD boot" }, - { PART_FREEBSD_NANDFS, "FreeBSD nandfs" }, - { PART_FREEBSD_UFS, "FreeBSD UFS" }, - { PART_FREEBSD_ZFS, "FreeBSD ZFS" }, - { PART_FREEBSD_SWAP, "FreeBSD swap" }, - { PART_FREEBSD_VINUM, "FreeBSD vinum" }, - { PART_LINUX, "Linux" }, - { PART_LINUX_SWAP, "Linux swap" }, - { PART_DOS, "DOS/Windows" }, -}; - -const char * -parttype2str(enum partition_type type) -{ - size_t i; - - for (i = 0; i < nitems(ptypes); i++) - if (ptypes[i].type == type) - return (ptypes[i].desc); - return (ptypes[0].desc); -} - -#ifdef LOADER_GPT_SUPPORT -static void -uuid_letoh(uuid_t *uuid) -{ - - uuid->time_low = le32toh(uuid->time_low); - uuid->time_mid = le16toh(uuid->time_mid); - uuid->time_hi_and_version = le16toh(uuid->time_hi_and_version); -} - -static enum partition_type -gpt_parttype(uuid_t type) -{ - - if (uuid_equal(&type, &gpt_uuid_efi, NULL)) - return (PART_EFI); - else if (uuid_equal(&type, &gpt_uuid_ms_basic_data, NULL)) - return (PART_DOS); - else if (uuid_equal(&type, &gpt_uuid_freebsd_boot, NULL)) - return (PART_FREEBSD_BOOT); - else if (uuid_equal(&type, &gpt_uuid_freebsd_ufs, NULL)) - return (PART_FREEBSD_UFS); - else if (uuid_equal(&type, &gpt_uuid_freebsd_zfs, NULL)) - return (PART_FREEBSD_ZFS); - else if (uuid_equal(&type, &gpt_uuid_freebsd_swap, NULL)) - return (PART_FREEBSD_SWAP); - else if (uuid_equal(&type, &gpt_uuid_freebsd_vinum, NULL)) - return (PART_FREEBSD_VINUM); - else if (uuid_equal(&type, &gpt_uuid_freebsd_nandfs, NULL)) - return (PART_FREEBSD_NANDFS); - else if (uuid_equal(&type, &gpt_uuid_freebsd, NULL)) - return (PART_FREEBSD); - return (PART_UNKNOWN); -} - -static struct gpt_hdr * -gpt_checkhdr(struct gpt_hdr *hdr, uint64_t lba_self, uint64_t lba_last, - uint16_t sectorsize) -{ - uint32_t sz, crc; - - if (memcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0) { - DEBUG("no GPT signature"); - return (NULL); - } - sz = le32toh(hdr->hdr_size); - if (sz < 92 || sz > sectorsize) { - DEBUG("invalid GPT header size: %d", sz); - return (NULL); - } - crc = le32toh(hdr->hdr_crc_self); - hdr->hdr_crc_self = 0; - if (crc32(hdr, sz) != crc) { - DEBUG("GPT header's CRC doesn't match"); - return (NULL); - } - hdr->hdr_crc_self = crc; - hdr->hdr_revision = le32toh(hdr->hdr_revision); - if (hdr->hdr_revision < GPT_HDR_REVISION) { - DEBUG("unsupported GPT revision %d", hdr->hdr_revision); - return (NULL); - } - hdr->hdr_lba_self = le64toh(hdr->hdr_lba_self); - if (hdr->hdr_lba_self != lba_self) { - DEBUG("self LBA doesn't match"); - return (NULL); - } - hdr->hdr_lba_alt = le64toh(hdr->hdr_lba_alt); - if (hdr->hdr_lba_alt == hdr->hdr_lba_self) { - DEBUG("invalid alternate LBA"); - return (NULL); - } - hdr->hdr_entries = le32toh(hdr->hdr_entries); - hdr->hdr_entsz = le32toh(hdr->hdr_entsz); - if (hdr->hdr_entries == 0 || - hdr->hdr_entsz < sizeof(struct gpt_ent) || - sectorsize % hdr->hdr_entsz != 0) { - DEBUG("invalid entry size or number of entries"); - return (NULL); - } - hdr->hdr_lba_start = le64toh(hdr->hdr_lba_start); - hdr->hdr_lba_end = le64toh(hdr->hdr_lba_end); - hdr->hdr_lba_table = le64toh(hdr->hdr_lba_table); - hdr->hdr_crc_table = le32toh(hdr->hdr_crc_table); - uuid_letoh(&hdr->hdr_uuid); - return (hdr); -} - -static int -gpt_checktbl(const struct gpt_hdr *hdr, uint8_t *tbl, size_t size, - uint64_t lba_last) -{ - struct gpt_ent *ent; - uint32_t i, cnt; - - cnt = size / hdr->hdr_entsz; - if (hdr->hdr_entries <= cnt) { - cnt = hdr->hdr_entries; - /* Check CRC only when buffer size is enough for table. */ - if (hdr->hdr_crc_table != - crc32(tbl, hdr->hdr_entries * hdr->hdr_entsz)) { - DEBUG("GPT table's CRC doesn't match"); - return (-1); - } - } - for (i = 0; i < cnt; i++) { - ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz); - uuid_letoh(&ent->ent_type); - if (uuid_equal(&ent->ent_type, &gpt_uuid_unused, NULL)) - continue; - ent->ent_lba_start = le64toh(ent->ent_lba_start); - ent->ent_lba_end = le64toh(ent->ent_lba_end); - } - return (0); -} - -static struct ptable * -ptable_gptread(struct ptable *table, void *dev, diskread_t dread) -{ - struct pentry *entry; - struct gpt_hdr *phdr, hdr; - struct gpt_ent *ent; - uint8_t *buf, *tbl; - uint64_t offset; - int pri, sec; - size_t size, i; - - buf = malloc(table->sectorsize); - if (buf == NULL) - return (NULL); - tbl = malloc(table->sectorsize * MAXTBLSZ); - if (tbl == NULL) { - free(buf); - return (NULL); - } - /* Read the primary GPT header. */ - if (dread(dev, buf, 1, 1) != 0) { - ptable_close(table); - table = NULL; - goto out; - } - pri = sec = 0; - /* Check the primary GPT header. */ - phdr = gpt_checkhdr((struct gpt_hdr *)buf, 1, table->sectors - 1, - table->sectorsize); - if (phdr != NULL) { - /* Read the primary GPT table. */ - size = MIN(MAXTBLSZ, - howmany(phdr->hdr_entries * phdr->hdr_entsz, - table->sectorsize)); - if (dread(dev, tbl, size, phdr->hdr_lba_table) == 0 && - gpt_checktbl(phdr, tbl, size * table->sectorsize, - table->sectors - 1) == 0) { - memcpy(&hdr, phdr, sizeof(hdr)); - pri = 1; - } - } - offset = pri ? hdr.hdr_lba_alt: table->sectors - 1; - /* Read the backup GPT header. */ - if (dread(dev, buf, 1, offset) != 0) - phdr = NULL; - else - phdr = gpt_checkhdr((struct gpt_hdr *)buf, offset, - table->sectors - 1, table->sectorsize); - if (phdr != NULL) { - /* - * Compare primary and backup headers. - * If they are equal, then we do not need to read backup - * table. If they are different, then prefer backup header - * and try to read backup table. - */ - if (pri == 0 || - uuid_equal(&hdr.hdr_uuid, &phdr->hdr_uuid, NULL) == 0 || - hdr.hdr_revision != phdr->hdr_revision || - hdr.hdr_size != phdr->hdr_size || - hdr.hdr_lba_start != phdr->hdr_lba_start || - hdr.hdr_lba_end != phdr->hdr_lba_end || - hdr.hdr_entries != phdr->hdr_entries || - hdr.hdr_entsz != phdr->hdr_entsz || - hdr.hdr_crc_table != phdr->hdr_crc_table) { - /* Read the backup GPT table. */ - size = MIN(MAXTBLSZ, - howmany(phdr->hdr_entries * phdr->hdr_entsz, - table->sectorsize)); - if (dread(dev, tbl, size, phdr->hdr_lba_table) == 0 && - gpt_checktbl(phdr, tbl, size * table->sectorsize, - table->sectors - 1) == 0) { - memcpy(&hdr, phdr, sizeof(hdr)); - sec = 1; - } - } - } - if (pri == 0 && sec == 0) { - /* Both primary and backup tables are invalid. */ - table->type = PTABLE_NONE; - goto out; - } - DEBUG("GPT detected"); - size = MIN(hdr.hdr_entries * hdr.hdr_entsz, - MAXTBLSZ * table->sectorsize); - - /* - * If the disk's sector count is smaller than the sector count recorded - * in the disk's GPT table header, set the table->sectors to the value - * recorded in GPT tables. This is done to work around buggy firmware - * that returns truncated disk sizes. - * - * Note, this is still not a foolproof way to get disk's size. For - * example, an image file can be truncated when copied to smaller media. - */ - if (hdr.hdr_lba_alt + 1 > table->sectors) - table->sectors = hdr.hdr_lba_alt + 1; - - for (i = 0; i < size / hdr.hdr_entsz; i++) { - ent = (struct gpt_ent *)(tbl + i * hdr.hdr_entsz); - if (uuid_equal(&ent->ent_type, &gpt_uuid_unused, NULL)) - continue; - - /* Simple sanity checks. */ - if (ent->ent_lba_start < hdr.hdr_lba_start || - ent->ent_lba_end > hdr.hdr_lba_end || - ent->ent_lba_start > ent->ent_lba_end) - continue; - - entry = malloc(sizeof(*entry)); - if (entry == NULL) - break; - entry->part.start = ent->ent_lba_start; - entry->part.end = ent->ent_lba_end; - entry->part.index = i + 1; - entry->part.type = gpt_parttype(ent->ent_type); - entry->flags = le64toh(ent->ent_attr); - memcpy(&entry->type.gpt, &ent->ent_type, sizeof(uuid_t)); - STAILQ_INSERT_TAIL(&table->entries, entry, entry); - DEBUG("new GPT partition added"); - } -out: - free(buf); - free(tbl); - return (table); -} -#endif /* LOADER_GPT_SUPPORT */ - -#ifdef LOADER_MBR_SUPPORT -/* We do not need to support too many EBR partitions in the loader */ -#define MAXEBRENTRIES 8 -static enum partition_type -mbr_parttype(uint8_t type) -{ - - switch (type) { - case DOSPTYP_386BSD: - return (PART_FREEBSD); - case DOSPTYP_LINSWP: - return (PART_LINUX_SWAP); - case DOSPTYP_LINUX: - return (PART_LINUX); - case 0x01: - case 0x04: - case 0x06: - case 0x07: - case 0x0b: - case 0x0c: - case 0x0e: - return (PART_DOS); - } - return (PART_UNKNOWN); -} - -static struct ptable * -ptable_ebrread(struct ptable *table, void *dev, diskread_t dread) -{ - struct dos_partition *dp; - struct pentry *e1, *entry; - uint32_t start, end, offset; - u_char *buf; - int i, index; - - STAILQ_FOREACH(e1, &table->entries, entry) { - if (e1->type.mbr == DOSPTYP_EXT || - e1->type.mbr == DOSPTYP_EXTLBA) - break; - } - if (e1 == NULL) - return (table); - index = 5; - offset = e1->part.start; - buf = malloc(table->sectorsize); - if (buf == NULL) - return (table); - DEBUG("EBR detected"); - for (i = 0; i < MAXEBRENTRIES; i++) { -#if 0 /* Some BIOSes return an incorrect number of sectors */ - if (offset >= table->sectors) - break; -#endif - if (dread(dev, buf, 1, offset) != 0) - break; - dp = (struct dos_partition *)(buf + DOSPARTOFF); - if (dp[0].dp_typ == 0) - break; - start = le32toh(dp[0].dp_start); - if (dp[0].dp_typ == DOSPTYP_EXT && - dp[1].dp_typ == 0) { - offset = e1->part.start + start; - continue; - } - end = le32toh(dp[0].dp_size); - entry = malloc(sizeof(*entry)); - if (entry == NULL) - break; - entry->part.start = offset + start; - entry->part.end = entry->part.start + end - 1; - entry->part.index = index++; - entry->part.type = mbr_parttype(dp[0].dp_typ); - entry->flags = dp[0].dp_flag; - entry->type.mbr = dp[0].dp_typ; - STAILQ_INSERT_TAIL(&table->entries, entry, entry); - DEBUG("new EBR partition added"); - if (dp[1].dp_typ == 0) - break; - offset = e1->part.start + le32toh(dp[1].dp_start); - } - free(buf); - return (table); -} -#endif /* LOADER_MBR_SUPPORT */ - -static enum partition_type -bsd_parttype(uint8_t type) -{ - - switch (type) { - case FS_NANDFS: - return (PART_FREEBSD_NANDFS); - case FS_SWAP: - return (PART_FREEBSD_SWAP); - case FS_BSDFFS: - return (PART_FREEBSD_UFS); - case FS_VINUM: - return (PART_FREEBSD_VINUM); - case FS_ZFS: - return (PART_FREEBSD_ZFS); - } - return (PART_UNKNOWN); -} - -static struct ptable * -ptable_bsdread(struct ptable *table, void *dev, diskread_t dread) -{ - struct disklabel *dl; - struct partition *part; - struct pentry *entry; - uint8_t *buf; - uint32_t raw_offset; - int i; - - if (table->sectorsize < sizeof(struct disklabel)) { - DEBUG("Too small sectorsize"); - return (table); - } - buf = malloc(table->sectorsize); - if (buf == NULL) - return (table); - if (dread(dev, buf, 1, 1) != 0) { - DEBUG("read failed"); - ptable_close(table); - table = NULL; - goto out; - } - dl = (struct disklabel *)buf; - if (le32toh(dl->d_magic) != DISKMAGIC && - le32toh(dl->d_magic2) != DISKMAGIC) - goto out; - if (le32toh(dl->d_secsize) != table->sectorsize) { - DEBUG("unsupported sector size"); - goto out; - } - dl->d_npartitions = le16toh(dl->d_npartitions); - if (dl->d_npartitions > 20 || dl->d_npartitions < 8) { - DEBUG("invalid number of partitions"); - goto out; - } - DEBUG("BSD detected"); - part = &dl->d_partitions[0]; - raw_offset = le32toh(part[RAW_PART].p_offset); - for (i = 0; i < dl->d_npartitions; i++, part++) { - if (i == RAW_PART) - continue; - if (part->p_size == 0) - continue; - entry = malloc(sizeof(*entry)); - if (entry == NULL) - break; - entry->part.start = le32toh(part->p_offset) - raw_offset; - entry->part.end = entry->part.start + - le32toh(part->p_size) - 1; - entry->part.type = bsd_parttype(part->p_fstype); - entry->part.index = i; /* starts from zero */ - entry->type.bsd = part->p_fstype; - STAILQ_INSERT_TAIL(&table->entries, entry, entry); - DEBUG("new BSD partition added"); - } - table->type = PTABLE_BSD; -out: - free(buf); - return (table); -} - -#ifdef LOADER_VTOC8_SUPPORT -static enum partition_type -vtoc8_parttype(uint16_t type) -{ - - switch (type) { - case VTOC_TAG_FREEBSD_NANDFS: - return (PART_FREEBSD_NANDFS); - case VTOC_TAG_FREEBSD_SWAP: - return (PART_FREEBSD_SWAP); - case VTOC_TAG_FREEBSD_UFS: - return (PART_FREEBSD_UFS); - case VTOC_TAG_FREEBSD_VINUM: - return (PART_FREEBSD_VINUM); - case VTOC_TAG_FREEBSD_ZFS: - return (PART_FREEBSD_ZFS); - } - return (PART_UNKNOWN); -} - -static struct ptable * -ptable_vtoc8read(struct ptable *table, void *dev, diskread_t dread) -{ - struct pentry *entry; - struct vtoc8 *dl; - uint8_t *buf; - uint16_t sum, heads, sectors; - int i; - - if (table->sectorsize != sizeof(struct vtoc8)) - return (table); - buf = malloc(table->sectorsize); - if (buf == NULL) - return (table); - if (dread(dev, buf, 1, 0) != 0) { - DEBUG("read failed"); - ptable_close(table); - table = NULL; - goto out; - } - dl = (struct vtoc8 *)buf; - /* Check the sum */ - for (i = sum = 0; i < sizeof(struct vtoc8); i += sizeof(sum)) - sum ^= be16dec(buf + i); - if (sum != 0) { - DEBUG("incorrect checksum"); - goto out; - } - if (be16toh(dl->nparts) != VTOC8_NPARTS) { - DEBUG("invalid number of entries"); - goto out; - } - sectors = be16toh(dl->nsecs); - heads = be16toh(dl->nheads); - if (sectors * heads == 0) { - DEBUG("invalid geometry"); - goto out; - } - DEBUG("VTOC8 detected"); - for (i = 0; i < VTOC8_NPARTS; i++) { - dl->part[i].tag = be16toh(dl->part[i].tag); - if (i == VTOC_RAW_PART || - dl->part[i].tag == VTOC_TAG_UNASSIGNED) - continue; - entry = malloc(sizeof(*entry)); - if (entry == NULL) - break; - entry->part.start = be32toh(dl->map[i].cyl) * heads * sectors; - entry->part.end = be32toh(dl->map[i].nblks) + - entry->part.start - 1; - entry->part.type = vtoc8_parttype(dl->part[i].tag); - entry->part.index = i; /* starts from zero */ - entry->type.vtoc8 = dl->part[i].tag; - STAILQ_INSERT_TAIL(&table->entries, entry, entry); - DEBUG("new VTOC8 partition added"); - } - table->type = PTABLE_VTOC8; -out: - free(buf); - return (table); - -} -#endif /* LOADER_VTOC8_SUPPORT */ - -struct ptable * -ptable_open(void *dev, uint64_t sectors, uint16_t sectorsize, - diskread_t *dread) -{ - struct dos_partition *dp; - struct ptable *table; - uint8_t *buf; - int i, count; -#ifdef LOADER_MBR_SUPPORT - struct pentry *entry; - uint32_t start, end; - int has_ext; -#endif - table = NULL; - buf = malloc(sectorsize); - if (buf == NULL) - return (NULL); - /* First, read the MBR. */ - if (dread(dev, buf, 1, DOSBBSECTOR) != 0) { - DEBUG("read failed"); - goto out; - } - - table = malloc(sizeof(*table)); - if (table == NULL) - goto out; - table->sectors = sectors; - table->sectorsize = sectorsize; - table->type = PTABLE_NONE; - STAILQ_INIT(&table->entries); - -#ifdef LOADER_VTOC8_SUPPORT - if (be16dec(buf + offsetof(struct vtoc8, magic)) == VTOC_MAGIC) { - if (ptable_vtoc8read(table, dev, dread) == NULL) { - /* Read error. */ - table = NULL; - goto out; - } else if (table->type == PTABLE_VTOC8) - goto out; - } -#endif - /* Check the BSD label. */ - if (ptable_bsdread(table, dev, dread) == NULL) { /* Read error. */ - table = NULL; - goto out; - } else if (table->type == PTABLE_BSD) - goto out; - -#if defined(LOADER_GPT_SUPPORT) || defined(LOADER_MBR_SUPPORT) - /* Check the MBR magic. */ - if (buf[DOSMAGICOFFSET] != 0x55 || - buf[DOSMAGICOFFSET + 1] != 0xaa) { - DEBUG("magic sequence not found"); -#if defined(LOADER_GPT_SUPPORT) - /* There is no PMBR, check that we have backup GPT */ - table->type = PTABLE_GPT; - table = ptable_gptread(table, dev, dread); -#endif - goto out; - } - /* Check that we have PMBR. Also do some validation. */ - dp = (struct dos_partition *)(buf + DOSPARTOFF); - for (i = 0, count = 0; i < NDOSPART; i++) { - if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80) { - DEBUG("invalid partition flag %x", dp[i].dp_flag); - goto out; - } -#ifdef LOADER_GPT_SUPPORT - if (dp[i].dp_typ == DOSPTYP_PMBR) { - table->type = PTABLE_GPT; - DEBUG("PMBR detected"); - } -#endif - if (dp[i].dp_typ != 0) - count++; - } - /* Do we have some invalid values? */ - if (table->type == PTABLE_GPT && count > 1) { - if (dp[1].dp_typ != DOSPTYP_HFS) { - table->type = PTABLE_NONE; - DEBUG("Incorrect PMBR, ignore it"); - } else { - DEBUG("Bootcamp detected"); - } - } -#ifdef LOADER_GPT_SUPPORT - if (table->type == PTABLE_GPT) { - table = ptable_gptread(table, dev, dread); - goto out; - } -#endif -#ifdef LOADER_MBR_SUPPORT - /* Read MBR. */ - DEBUG("MBR detected"); - table->type = PTABLE_MBR; - for (i = has_ext = 0; i < NDOSPART; i++) { - if (dp[i].dp_typ == 0) - continue; - start = le32dec(&(dp[i].dp_start)); - end = le32dec(&(dp[i].dp_size)); - if (start == 0 || end == 0) - continue; -#if 0 /* Some BIOSes return an incorrect number of sectors */ - if (start + end - 1 >= sectors) - continue; /* XXX: ignore */ -#endif - if (dp[i].dp_typ == DOSPTYP_EXT || - dp[i].dp_typ == DOSPTYP_EXTLBA) - has_ext = 1; - entry = malloc(sizeof(*entry)); - if (entry == NULL) - break; - entry->part.start = start; - entry->part.end = start + end - 1; - entry->part.index = i + 1; - entry->part.type = mbr_parttype(dp[i].dp_typ); - entry->flags = dp[i].dp_flag; - entry->type.mbr = dp[i].dp_typ; - STAILQ_INSERT_TAIL(&table->entries, entry, entry); - DEBUG("new MBR partition added"); - } - if (has_ext) { - table = ptable_ebrread(table, dev, dread); - /* FALLTHROUGH */ - } -#endif /* LOADER_MBR_SUPPORT */ -#endif /* LOADER_MBR_SUPPORT || LOADER_GPT_SUPPORT */ -out: - free(buf); - return (table); -} - -void -ptable_close(struct ptable *table) -{ - struct pentry *entry; - - while (!STAILQ_EMPTY(&table->entries)) { - entry = STAILQ_FIRST(&table->entries); - STAILQ_REMOVE_HEAD(&table->entries, entry); - free(entry); - } - free(table); -} - -enum ptable_type -ptable_gettype(const struct ptable *table) -{ - - return (table->type); -} - -int -ptable_getsize(const struct ptable *table, uint64_t *sizep) -{ - uint64_t tmp = table->sectors * table->sectorsize; - - if (tmp < table->sectors) - return (EOVERFLOW); - - if (sizep != NULL) - *sizep = tmp; - return (0); -} - -int -ptable_getpart(const struct ptable *table, struct ptable_entry *part, int index) -{ - struct pentry *entry; - - if (part == NULL || table == NULL) - return (EINVAL); - - STAILQ_FOREACH(entry, &table->entries, entry) { - if (entry->part.index != index) - continue; - memcpy(part, &entry->part, sizeof(*part)); - return (0); - } - return (ENOENT); -} - -/* - * Search for a slice with the following preferences: - * - * 1: Active FreeBSD slice - * 2: Non-active FreeBSD slice - * 3: Active Linux slice - * 4: non-active Linux slice - * 5: Active FAT/FAT32 slice - * 6: non-active FAT/FAT32 slice - */ -#define PREF_RAWDISK 0 -#define PREF_FBSD_ACT 1 -#define PREF_FBSD 2 -#define PREF_LINUX_ACT 3 -#define PREF_LINUX 4 -#define PREF_DOS_ACT 5 -#define PREF_DOS 6 -#define PREF_NONE 7 -int -ptable_getbestpart(const struct ptable *table, struct ptable_entry *part) -{ - struct pentry *entry, *best; - int pref, preflevel; - - if (part == NULL || table == NULL) - return (EINVAL); - - best = NULL; - preflevel = pref = PREF_NONE; - STAILQ_FOREACH(entry, &table->entries, entry) { -#ifdef LOADER_MBR_SUPPORT - if (table->type == PTABLE_MBR) { - switch (entry->type.mbr) { - case DOSPTYP_386BSD: - pref = entry->flags & 0x80 ? PREF_FBSD_ACT: - PREF_FBSD; - break; - case DOSPTYP_LINUX: - pref = entry->flags & 0x80 ? PREF_LINUX_ACT: - PREF_LINUX; - break; - case 0x01: /* DOS/Windows */ - case 0x04: - case 0x06: - case 0x0c: - case 0x0e: - case DOSPTYP_FAT32: - pref = entry->flags & 0x80 ? PREF_DOS_ACT: - PREF_DOS; - break; - default: - pref = PREF_NONE; - } - } -#endif /* LOADER_MBR_SUPPORT */ -#ifdef LOADER_GPT_SUPPORT - if (table->type == PTABLE_GPT) { - if (entry->part.type == PART_DOS) - pref = PREF_DOS; - else if (entry->part.type == PART_FREEBSD_UFS || - entry->part.type == PART_FREEBSD_ZFS) - pref = PREF_FBSD; - else - pref = PREF_NONE; - } -#endif /* LOADER_GPT_SUPPORT */ - if (pref < preflevel) { - preflevel = pref; - best = entry; - } - } - if (best != NULL) { - memcpy(part, &best->part, sizeof(*part)); - return (0); - } - return (ENOENT); -} - -int -ptable_iterate(const struct ptable *table, void *arg, ptable_iterate_t *iter) -{ - struct pentry *entry; - char name[32]; - int ret = 0; - - name[0] = '\0'; - STAILQ_FOREACH(entry, &table->entries, entry) { -#ifdef LOADER_MBR_SUPPORT - if (table->type == PTABLE_MBR) - sprintf(name, "s%d", entry->part.index); - else -#endif -#ifdef LOADER_GPT_SUPPORT - if (table->type == PTABLE_GPT) - sprintf(name, "p%d", entry->part.index); - else -#endif -#ifdef LOADER_VTOC8_SUPPORT - if (table->type == PTABLE_VTOC8) - sprintf(name, "%c", (uint8_t) 'a' + - entry->part.index); - else -#endif - if (table->type == PTABLE_BSD) - sprintf(name, "%c", (uint8_t) 'a' + - entry->part.index); - if ((ret = iter(arg, name, &entry->part)) != 0) - return (ret); - } - return (ret); -} diff --git a/sys/boot/common/part.h b/sys/boot/common/part.h deleted file mode 100644 index 19bd6702fc69..000000000000 --- a/sys/boot/common/part.h +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * Copyright (c) 2012 Andrey V. Elsukov <ae@FreeBSD.org> - * 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 AUTHORS 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 AUTHORS 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 _PART_H_ -#define _PART_H_ - -struct ptable; - -enum ptable_type { - PTABLE_NONE, - PTABLE_BSD, - PTABLE_MBR, - PTABLE_GPT, - PTABLE_VTOC8 -}; - -enum partition_type { - PART_UNKNOWN, - PART_EFI, - PART_FREEBSD, - PART_FREEBSD_BOOT, - PART_FREEBSD_NANDFS, - PART_FREEBSD_UFS, - PART_FREEBSD_ZFS, - PART_FREEBSD_SWAP, - PART_FREEBSD_VINUM, - PART_LINUX, - PART_LINUX_SWAP, - PART_DOS, -}; - -struct ptable_entry { - uint64_t start; - uint64_t end; - int index; - enum partition_type type; -}; - -/* The offset and size are in sectors */ -typedef int (diskread_t)(void *arg, void *buf, size_t blocks, uint64_t offset); -typedef int (ptable_iterate_t)(void *arg, const char *partname, - const struct ptable_entry *part); - -struct ptable *ptable_open(void *dev, uint64_t sectors, uint16_t sectorsize, - diskread_t *dread); -void ptable_close(struct ptable *table); -enum ptable_type ptable_gettype(const struct ptable *table); -int ptable_getsize(const struct ptable *table, uint64_t *sizep); - -int ptable_getpart(const struct ptable *table, struct ptable_entry *part, - int index); -int ptable_getbestpart(const struct ptable *table, struct ptable_entry *part); - -int ptable_iterate(const struct ptable *table, void *arg, - ptable_iterate_t *iter); -const char *parttype2str(enum partition_type type); - -#endif /* !_PART_H_ */ diff --git a/sys/boot/common/paths.h b/sys/boot/common/paths.h deleted file mode 100644 index 9ed45e646a3e..000000000000 --- a/sys/boot/common/paths.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 2016 M. Warner Losh <imp@freebsd.org> - * 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 AUTHORS 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 AUTHORS 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 _PATHS_H_ -#define _PATHS_H_ - -#define PATH_DOTCONFIG "/boot.config" -#define PATH_CONFIG "/boot/config" -#define PATH_LOADER "/boot/loader" -#define PATH_LOADER_EFI "/boot/loader.efi" -#define PATH_LOADER_ZFS "/boot/zfsloader" -#define PATH_KERNEL "/boot/kernel/kernel" - -#endif /* _PATHS_H_ */ diff --git a/sys/boot/common/pnp.c b/sys/boot/common/pnp.c deleted file mode 100644 index 6197776a1d7d..000000000000 --- a/sys/boot/common/pnp.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * mjs copyright - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * "Plug and Play" functionality. - * - * We use the PnP enumerators to obtain identifiers for installed hardware, - * and the contents of a database to determine modules to be loaded to support - * such hardware. - */ - -#include <stand.h> -#include <string.h> -#include <bootstrap.h> -#ifdef BOOT_FORTH -#include "ficl.h" -#endif - -static struct pnpinfo_stql pnp_devices; -static int pnp_devices_initted = 0; - -static void pnp_discard(void); - -/* - * Perform complete enumeration sweep - */ - -COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan); - -static int -pnp_scan(int argc, char *argv[]) -{ - struct pnpinfo *pi; - int hdlr; - int verbose; - int ch; - - if (pnp_devices_initted == 0) { - STAILQ_INIT(&pnp_devices); - pnp_devices_initted = 1; - } - - verbose = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "v")) != -1) { - switch(ch) { - case 'v': - verbose = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); - } - } - - /* forget anything we think we knew */ - pnp_discard(); - - /* iterate over all of the handlers */ - for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) { - if (verbose) - printf("Probing %s...\n", pnphandlers[hdlr]->pp_name); - pnphandlers[hdlr]->pp_enumerate(); - } - if (verbose) { - pager_open(); - if (pager_output("PNP scan summary:\n")) - goto out; - STAILQ_FOREACH(pi, &pnp_devices, pi_link) { - pager_output(STAILQ_FIRST(&pi->pi_ident)->id_ident); /* first ident should be canonical */ - if (pi->pi_desc != NULL) { - pager_output(" : "); - pager_output(pi->pi_desc); - } - if (pager_output("\n")) - break; - } -out: - pager_close(); - } - return(CMD_OK); -} - -/* - * Throw away anything we think we know about PnP devices. - */ -static void -pnp_discard(void) -{ - struct pnpinfo *pi; - - while (STAILQ_FIRST(&pnp_devices) != NULL) { - pi = STAILQ_FIRST(&pnp_devices); - STAILQ_REMOVE_HEAD(&pnp_devices, pi_link); - pnp_freeinfo(pi); - } -} - -/* - * Add a unique identifier to (pi) - */ -void -pnp_addident(struct pnpinfo *pi, char *ident) -{ - struct pnpident *id; - - STAILQ_FOREACH(id, &pi->pi_ident, id_link) - if (!strcmp(id->id_ident, ident)) - return; /* already have this one */ - - id = malloc(sizeof(struct pnpident)); - id->id_ident = strdup(ident); - STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link); -} - -/* - * Allocate a new pnpinfo struct - */ -struct pnpinfo * -pnp_allocinfo(void) -{ - struct pnpinfo *pi; - - pi = malloc(sizeof(struct pnpinfo)); - bzero(pi, sizeof(struct pnpinfo)); - STAILQ_INIT(&pi->pi_ident); - return(pi); -} - -/* - * Release storage held by a pnpinfo struct - */ -void -pnp_freeinfo(struct pnpinfo *pi) -{ - struct pnpident *id; - - while (!STAILQ_EMPTY(&pi->pi_ident)) { - id = STAILQ_FIRST(&pi->pi_ident); - STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link); - free(id->id_ident); - free(id); - } - if (pi->pi_desc) - free(pi->pi_desc); - if (pi->pi_module) - free(pi->pi_module); - if (pi->pi_argv) - free(pi->pi_argv); - free(pi); -} - -/* - * Add a new pnpinfo struct to the list. - */ -void -pnp_addinfo(struct pnpinfo *pi) -{ - STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link); -} - - -/* - * Format an EISA id as a string in standard ISA PnP format, AAAIIRR - * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID. - */ -char * -pnp_eisaformat(u_int8_t *data) -{ - static char idbuf[8]; - const char hextoascii[] = "0123456789abcdef"; - - idbuf[0] = '@' + ((data[0] & 0x7c) >> 2); - idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5)); - idbuf[2] = '@' + (data[1] & 0x1f); - idbuf[3] = hextoascii[(data[2] >> 4)]; - idbuf[4] = hextoascii[(data[2] & 0xf)]; - idbuf[5] = hextoascii[(data[3] >> 4)]; - idbuf[6] = hextoascii[(data[3] & 0xf)]; - idbuf[7] = 0; - return(idbuf); -} - -#ifdef BOOT_FORTH -void -ficlPnpdevices(FICL_VM *pVM) -{ - static int pnp_devices_initted = 0; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - - if(!pnp_devices_initted) { - STAILQ_INIT(&pnp_devices); - pnp_devices_initted = 1; - } - - stackPushPtr(pVM->pStack, &pnp_devices); - - return; -} - -void -ficlPnphandlers(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - - stackPushPtr(pVM->pStack, pnphandlers); - - return; -} - -/* - * Glue function to add the appropriate forth words to access pnp BIOS - * functionality. - */ -static void ficlCompilePnp(FICL_SYSTEM *pSys) -{ - FICL_DICT *dp = pSys->dp; - assert (dp); - - dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT); - dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT); -} - -FICL_COMPILE_SET(ficlCompilePnp); -#endif diff --git a/sys/boot/common/rbx.h b/sys/boot/common/rbx.h deleted file mode 100644 index 21371a563805..000000000000 --- a/sys/boot/common/rbx.h +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * Copyright (c) 1998 Robert Nordier - * All rights reserved. - * - * Redistribution and use in source and binary forms are freely - * permitted provided that the above copyright notice and this - * paragraph and the following disclaimer are duplicated in all - * such forms. - * - * This software is provided "AS IS" and without any express or - * implied warranties, including, without limitation, the implied - * warranties of merchantability and fitness for a particular - * purpose. - * - * $FreeBSD$ - */ - -#ifndef _RBX_H_ -#define _RBX_H_ - -#define RBX_ASKNAME 0x0 /* -a */ -#define RBX_SINGLE 0x1 /* -s */ -/* 0x2 is reserved for log2(RB_NOSYNC). */ -/* 0x3 is reserved for log2(RB_HALT). */ -/* 0x4 is reserved for log2(RB_INITNAME). */ -#define RBX_DFLTROOT 0x5 /* -r */ -#define RBX_KDB 0x6 /* -d */ -/* 0x7 is reserved for log2(RB_RDONLY). */ -/* 0x8 is reserved for log2(RB_DUMP). */ -/* 0x9 is reserved for log2(RB_MINIROOT). */ -#define RBX_CONFIG 0xa /* -c */ -#define RBX_VERBOSE 0xb /* -v */ -#define RBX_SERIAL 0xc /* -h */ -#define RBX_CDROM 0xd /* -C */ -/* 0xe is reserved for log2(RB_POWEROFF). */ -#define RBX_GDB 0xf /* -g */ -#define RBX_MUTE 0x10 /* -m */ -/* 0x11 is reserved for log2(RB_SELFTEST). */ -/* 0x12 is reserved for boot programs. */ -/* 0x13 is reserved for boot programs. */ -#define RBX_PAUSE 0x14 /* -p */ -#define RBX_QUIET 0x15 /* -q */ -#define RBX_NOINTR 0x1c /* -n */ -/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ -#define RBX_DUAL 0x1d /* -D */ -/* 0x1f is reserved for log2(RB_BOOTINFO). */ - -/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */ -#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ - OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \ - OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \ - OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \ - OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \ - OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL)) - -#define OPT_SET(opt) (1 << (opt)) -#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) - -extern uint32_t opts; - -#endif /* !_RBX_H_ */ diff --git a/sys/boot/common/reloc_elf.c b/sys/boot/common/reloc_elf.c deleted file mode 100644 index 6d4a00ff8f68..000000000000 --- a/sys/boot/common/reloc_elf.c +++ /dev/null @@ -1,223 +0,0 @@ -/*- - * Copyright (c) 2003 Jake Burkholder. - * Copyright 1996-1998 John D. Polstra. - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * Copyright (c) 1998 Peter Wemm <peter@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <machine/elf.h> - -#include <stand.h> - -#define FREEBSD_ELF -#include <link.h> - -#include "bootstrap.h" - -#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) - -/* - * Apply a single intra-module relocation to the data. `relbase' is the - * target relocation base for the section (i.e. it corresponds to where - * r_offset == 0). `dataaddr' is the relocated address corresponding to - * the start of the data, and `len' is the number of bytes. - */ -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) -{ -#ifdef __sparc__ - Elf_Size w; - const Elf_Rela *a; - - switch (reltype) { - case ELF_RELOC_RELA: - a = reldata; - if (relbase + a->r_offset >= dataaddr && - relbase + a->r_offset < dataaddr + len) { - switch (ELF_R_TYPE(a->r_info)) { - case R_SPARC_RELATIVE: - w = relbase + a->r_addend; - bcopy(&w, (u_char *)data + (relbase + - a->r_offset - dataaddr), sizeof(w)); - break; - default: - printf("\nunhandled relocation type %u\n", - (u_int)ELF_R_TYPE(a->r_info)); - return (EFTYPE); - } - } - break; - } - - return (0); -#elif (defined(__i386__) || defined(__amd64__)) && __ELF_WORD_SIZE == 64 - Elf64_Addr *where, val; - Elf_Addr addend, addr; - Elf_Size rtype, symidx; - const Elf_Rel *rel; - const Elf_Rela *rela; - - switch (reltype) { - case ELF_RELOC_REL: - rel = (const Elf_Rel *)reldata; - where = (Elf_Addr *)((char *)data + relbase + rel->r_offset - - dataaddr); - addend = 0; - rtype = ELF_R_TYPE(rel->r_info); - symidx = ELF_R_SYM(rel->r_info); - addend = 0; - break; - case ELF_RELOC_RELA: - rela = (const Elf_Rela *)reldata; - where = (Elf_Addr *)((char *)data + relbase + rela->r_offset - - dataaddr); - addend = rela->r_addend; - rtype = ELF_R_TYPE(rela->r_info); - symidx = ELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if ((char *)where < (char *)data || (char *)where >= (char *)data + len) - return (0); - - if (reltype == ELF_RELOC_REL) - addend = *where; - -/* XXX, definitions not available on i386. */ -#define R_X86_64_64 1 -#define R_X86_64_RELATIVE 8 - - switch (rtype) { - case R_X86_64_64: /* S + A */ - addr = symaddr(ef, symidx); - if (addr == 0) - return (ESRCH); - val = addr + addend; - *where = val; - break; - case R_X86_64_RELATIVE: - addr = (Elf_Addr)addend + relbase; - val = addr; - *where = val; - break; - default: - printf("\nunhandled relocation type %u\n", (u_int)rtype); - return (EFTYPE); - } - - return (0); -#elif defined(__i386__) && __ELF_WORD_SIZE == 32 - Elf_Addr addend, addr, *where, val; - Elf_Size rtype, symidx; - const Elf_Rel *rel; - const Elf_Rela *rela; - - switch (reltype) { - case ELF_RELOC_REL: - rel = (const Elf_Rel *)reldata; - where = (Elf_Addr *)((char *)data + relbase + rel->r_offset - - dataaddr); - addend = 0; - rtype = ELF_R_TYPE(rel->r_info); - symidx = ELF_R_SYM(rel->r_info); - addend = 0; - break; - case ELF_RELOC_RELA: - rela = (const Elf_Rela *)reldata; - where = (Elf_Addr *)((char *)data + relbase + rela->r_offset - - dataaddr); - addend = rela->r_addend; - rtype = ELF_R_TYPE(rela->r_info); - symidx = ELF_R_SYM(rela->r_info); - break; - default: - return (EINVAL); - } - - if ((char *)where < (char *)data || (char *)where >= (char *)data + len) - return (0); - - if (reltype == ELF_RELOC_REL) - addend = *where; - -/* XXX, definitions not available on amd64. */ -#define R_386_32 1 /* Add symbol value. */ -#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ -#define R_386_RELATIVE 8 /* Add load address of shared object. */ - - switch (rtype) { - case R_386_RELATIVE: - addr = addend + relbase; - *where = addr; - break; - case R_386_32: /* S + A */ - addr = symaddr(ef, symidx); - if (addr == 0) - return (ESRCH); - val = addr + addend; - *where = val; - break; - default: - printf("\nunhandled relocation type %u\n", (u_int)rtype); - return (EFTYPE); - } - - return (0); -#elif defined(__powerpc__) - Elf_Size w; - const Elf_Rela *rela; - - switch (reltype) { - case ELF_RELOC_RELA: - rela = reldata; - if (relbase + rela->r_offset >= dataaddr && - relbase + rela->r_offset < dataaddr + len) { - switch (ELF_R_TYPE(rela->r_info)) { - case R_PPC_RELATIVE: - w = relbase + rela->r_addend; - bcopy(&w, (u_char *)data + (relbase + - rela->r_offset - dataaddr), sizeof(w)); - break; - default: - printf("\nunhandled relocation type %u\n", - (u_int)ELF_R_TYPE(rela->r_info)); - return (EFTYPE); - } - } - break; - } - - return (0); -#else - return (EOPNOTSUPP); -#endif -} diff --git a/sys/boot/common/reloc_elf32.c b/sys/boot/common/reloc_elf32.c deleted file mode 100644 index 03d9d73bab7f..000000000000 --- a/sys/boot/common/reloc_elf32.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define __ELF_WORD_SIZE 32 - -#include "reloc_elf.c" diff --git a/sys/boot/common/reloc_elf64.c b/sys/boot/common/reloc_elf64.c deleted file mode 100644 index c8dcf2a36b0d..000000000000 --- a/sys/boot/common/reloc_elf64.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define __ELF_WORD_SIZE 64 - -#include "reloc_elf.c" diff --git a/sys/boot/common/self_reloc.c b/sys/boot/common/self_reloc.c deleted file mode 100644 index 5f6bfcbb27bb..000000000000 --- a/sys/boot/common/self_reloc.c +++ /dev/null @@ -1,124 +0,0 @@ -/*- - * Copyright (c) 2008-2010 Rui Paulo <rpaulo@FreeBSD.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <elf.h> -#include <bootstrap.h> - -#if defined(__aarch64__) || defined(__amd64__) -#define ElfW_Rel Elf64_Rela -#define ElfW_Dyn Elf64_Dyn -#define ELFW_R_TYPE ELF64_R_TYPE -#define ELF_RELA -#elif defined(__arm__) || defined(__i386__) -#define ElfW_Rel Elf32_Rel -#define ElfW_Dyn Elf32_Dyn -#define ELFW_R_TYPE ELF32_R_TYPE -#else -#error architecture not supported -#endif -#if defined(__aarch64__) -#define RELOC_TYPE_NONE R_AARCH64_NONE -#define RELOC_TYPE_RELATIVE R_AARCH64_RELATIVE -#elif defined(__amd64__) -#define RELOC_TYPE_NONE R_X86_64_NONE -#define RELOC_TYPE_RELATIVE R_X86_64_RELATIVE -#elif defined(__arm__) -#define RELOC_TYPE_NONE R_ARM_NONE -#define RELOC_TYPE_RELATIVE R_ARM_RELATIVE -#elif defined(__i386__) -#define RELOC_TYPE_NONE R_386_NONE -#define RELOC_TYPE_RELATIVE R_386_RELATIVE -#endif - -void self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic); - -/* - * A simple elf relocator. - */ -void -self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic) -{ - Elf_Word relsz, relent; - Elf_Addr *newaddr; - ElfW_Rel *rel; - ElfW_Dyn *dynp; - - /* - * Find the relocation address, its size and the relocation entry. - */ - relsz = 0; - relent = 0; - for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) { - switch (dynp->d_tag) { - case DT_REL: - case DT_RELA: - rel = (ElfW_Rel *)(dynp->d_un.d_ptr + baseaddr); - break; - case DT_RELSZ: - case DT_RELASZ: - relsz = dynp->d_un.d_val; - break; - case DT_RELENT: - case DT_RELAENT: - relent = dynp->d_un.d_val; - break; - default: - break; - } - } - - /* - * Perform the actual relocation. We rely on the object having been - * linked at 0, so that the difference between the load and link - * address is the same as the load address. - */ - for (; relsz > 0; relsz -= relent) { - switch (ELFW_R_TYPE(rel->r_info)) { - case RELOC_TYPE_NONE: - /* No relocation needs be performed. */ - break; - - case RELOC_TYPE_RELATIVE: - newaddr = (Elf_Addr *)(rel->r_offset + baseaddr); -#ifdef ELF_RELA - /* Addend relative to the base address. */ - *newaddr = baseaddr + rel->r_addend; -#else - /* Address relative to the base address. */ - *newaddr += baseaddr; -#endif - break; - default: - /* XXX: do we need other relocations ? */ - break; - } - rel = (ElfW_Rel *)(void *)((caddr_t) rel + relent); - } -} |
