Index: head/stand/common/boot.c =================================================================== --- head/stand/common/boot.c (revision 334431) +++ head/stand/common/boot.c (revision 334432) @@ -1,415 +1,416 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Loading modules, booting the system */ #include #include #include "bootstrap.h" +static int autoboot(int timeout, char *prompt); 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 +static 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 : * 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? */ fstyp = NULL; dev = NULL; 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; free(dev); dev = strdup(lbuf); /* skip whitespace up to mountpoint */ while ((*cp != 0) && isspace(*cp)) cp++; /* must have / 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; free(fstyp); 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 : and save it in vfs.root.mountfrom */ sprintf(lbuf, "%s:%s", fstyp, dev); 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); free(dev); free(fstyp); 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; free(cp); } } 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; } Index: head/stand/common/bootstrap.h =================================================================== --- head/stand/common/bootstrap.h (revision 334431) +++ head/stand/common/bootstrap.h (revision 334432) @@ -1,337 +1,336 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _BOOTSTRAP_H_ #define _BOOTSTRAP_H_ #include #include #include /* Commands and return values; nonzero return sets command_errmsg != NULL */ typedef int (bootblk_cmd_t)(int argc, char *argv[]); #define COMMAND_ERRBUFSZ (256) extern const char *command_errmsg; extern char command_errbuf[COMMAND_ERRBUFSZ]; #define CMD_OK 0 #define CMD_WARN 1 #define CMD_ERROR 2 #define CMD_CRIT 3 #define CMD_FATAL 4 /* interp.c */ void interact(void); void interp_emit_prompt(void); int interp_builtin_cmd(int argc, char *argv[]); /* Called by interp.c for interp_*.c embedded interpreters */ int interp_include(const char *filename); /* Execute commands from filename */ void interp_init(void); /* Initialize interpreater */ int interp_run(const char *line); /* Run a single command */ /* interp_backslash.c */ char *backslash(const char *str); /* interp_parse.c */ int parse(int *argc, char ***argv, const char *str); /* boot.c */ -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(uint8_t *data); /* * < 0 - No ISA in system * == 0 - Maybe ISA, search for read data port * > 0 - ISA in system, value is read data port address */ extern int isapnp_readport; /* * Preloaded file metadata header. * * Metadata are allocated on our heap, and copied into kernel space * before executing the kernel. */ struct file_metadata { size_t md_size; uint16_t md_type; struct file_metadata *md_next; char md_data[1]; /* data are immediately appended */ }; struct preloaded_file; struct mod_depend; struct kernel_module { char *m_name; /* module name */ int m_version; /* module version */ /* char *m_args;*/ /* arguments for the module */ struct preloaded_file *m_fp; struct kernel_module *m_next; }; /* * Preloaded file information. Depending on type, file can contain * additional units called 'modules'. * * At least one file (the kernel) must be loaded in order to boot. * The kernel is always loaded first. * * String fields (m_name, m_type) should be dynamically allocated. */ struct preloaded_file { char *f_name; /* file name */ char *f_type; /* verbose file type, eg 'ELF kernel', 'pnptable', etc. */ char *f_args; /* arguments for the file */ struct file_metadata *f_metadata; /* metadata that will be placed in the module directory */ int f_loader; /* index of the loader that read the file */ vm_offset_t f_addr; /* load address */ size_t f_size; /* file size */ struct kernel_module *f_modules; /* list of modules if any */ struct preloaded_file *f_next; /* next file */ }; struct file_format { /* Load function must return EFTYPE if it can't handle the module supplied */ int (* l_load)(char *filename, uint64_t dest, struct preloaded_file **result); /* Only a loader that will load a kernel (first module) should have an exec handler */ int (* l_exec)(struct preloaded_file *mp); }; extern struct file_format *file_formats[]; /* supplied by consumer */ extern struct preloaded_file *preloaded_files; int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]); int mod_loadkld(const char *name, int argc, char *argv[]); void unload(void); struct preloaded_file *file_alloc(void); struct preloaded_file *file_findfile(const char *name, const char *type); struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type); struct preloaded_file *file_loadraw(const char *name, char *type, int insert); void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, struct kernel_module **newmp); void file_removemetadata(struct preloaded_file *fp); /* MI module loaders */ #ifdef __elfN /* Relocation types. */ #define ELF_RELOC_REL 1 #define ELF_RELOC_RELA 2 /* Relocation offset for some architectures */ extern uint64_t __elfN(relocation_offset); struct elf_file; typedef Elf_Addr (symaddr_fn)(struct elf_file *ef, Elf_Size symidx); int __elfN(loadfile)(char *filename, uint64_t dest, struct preloaded_file **result); int __elfN(obj_loadfile)(char *filename, uint64_t dest, struct preloaded_file **result); int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, int reltype, Elf_Addr relbase, Elf_Addr dataaddr, void *data, size_t len); int __elfN(loadfile_raw)(char *filename, uint64_t dest, struct preloaded_file **result, int multiboot); int __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest); #endif /* * Support for commands */ struct bootblk_command { const char *c_name; const char *c_desc; bootblk_cmd_t *c_fn; }; #define COMMAND_SET(tag, key, desc, func) \ static bootblk_cmd_t func; \ static struct bootblk_command _cmd_ ## tag = { key, desc, func }; \ DATA_SET(Xcommand_set, _cmd_ ## tag) SET_DECLARE(Xcommand_set, struct bootblk_command); /* * The intention of the architecture switch is to provide a convenient * encapsulation of the interface between the bootstrap MI and MD code. * MD code may selectively populate the switch at runtime based on the * actual configuration of the target system. */ struct arch_switch { /* Automatically load modules as required by detected hardware */ int (*arch_autoload)(void); /* Locate the device for (name), return pointer to tail in (*path) */ int (*arch_getdev)(void **dev, const char *name, const char **path); /* Copy from local address space to module address space, similar to bcopy() */ ssize_t (*arch_copyin)(const void *src, vm_offset_t dest, const size_t len); /* Copy to local address space from module address space, similar to bcopy() */ ssize_t (*arch_copyout)(const vm_offset_t src, void *dest, const size_t len); /* Read from file to module address space, same semantics as read() */ ssize_t (*arch_readin)(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); /* For kexec-type loaders, get ksegment structure */ void (*arch_kexec_kseg_get)(int *nseg, void **kseg); }; extern struct arch_switch archsw; /* This must be provided by the MD code, but should it be in the archsw? */ void delay(int delay); void dev_cleanup(void); time_t time(time_t *tloc); #ifndef CTASSERT #define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") #endif #endif /* !_BOOTSTRAP_H_ */ Index: head/stand/defs.mk =================================================================== --- head/stand/defs.mk (revision 334431) +++ head/stand/defs.mk (revision 334432) @@ -1,195 +1,195 @@ # $FreeBSD$ .include WARNS?=1 .if !defined(__BOOT_DEFS_MK__) __BOOT_DEFS_MK__=${MFILE} MK_CTF= no MK_SSP= no MK_PROFILE= no MAN= .if !defined(PIC) NO_PIC= INTERNALLIB= .endif BOOTSRC= ${SRCTOP}/stand EFISRC= ${BOOTSRC}/efi EFIINC= ${EFISRC}/include EFIINCMD= ${EFIINC}/${MACHINE} FDTSRC= ${BOOTSRC}/fdt FICLSRC= ${BOOTSRC}/ficl LDRSRC= ${BOOTSRC}/common LIBLUASRC= ${BOOTSRC}/liblua LUASRC= ${SRCTOP}/contrib/lua/src SASRC= ${BOOTSRC}/libsa SYSDIR= ${SRCTOP}/sys UBOOTSRC= ${BOOTSRC}/uboot ZFSSRC= ${BOOTSRC}/zfs BOOTOBJ= ${OBJTOP}/stand # BINDIR is where we install BINDIR?= /boot LIBSA= ${BOOTOBJ}/libsa/libsa.a .if ${MACHINE} == "i386" LIBSA32= ${LIBSA} .else LIBSA32= ${BOOTOBJ}/libsa32/libsa32.a .endif # Standard options: CFLAGS+= -nostdinc .if ${MACHINE_ARCH} == "amd64" && ${DO32:U0} == 1 CFLAGS+= -I${BOOTOBJ}/libsa32 .else CFLAGS+= -I${BOOTOBJ}/libsa .endif CFLAGS+= -I${SASRC} -D_STANDALONE CFLAGS+= -I${SYSDIR} # Spike the floating point interfaces CFLAGS+= -Ddouble=jagged-little-pill -Dfloat=floaty-mcfloatface # GELI Support, with backward compat hooks (mostly) .if defined(HAVE_GELI) .if defined(LOADER_NO_GELI_SUPPORT) MK_LOADER_GELI=no .warning "Please move from LOADER_NO_GELI_SUPPORT to WITHOUT_LOADER_GELI" .endif .if defined(LOADER_GELI_SUPPORT) MK_LOADER_GELI=yes .warning "Please move from LOADER_GELI_SUPPORT to WITH_LOADER_GELI" .endif .if ${MK_LOADER_GELI} == "yes" CFLAGS+= -DLOADER_GELI_SUPPORT CFLAGS+= -I${BOOTSRC}/geli LIBGELIBOOT= ${BOOTOBJ}/geli/libgeliboot.a .endif # MK_LOADER_GELI .endif # HAVE_GELI # These should be confined to loader.mk, but can't because uboot/lib # also uses it. It's part of loader, but isn't a loader so we can't # just include loader.mk .if ${LOADER_DISK_SUPPORT:Uyes} == "yes" CFLAGS+= -DLOADER_DISK_SUPPORT .endif # Machine specific flags for all builds here # All PowerPC builds are 32 bit. We have no 64-bit loaders on powerpc # or powerpc64. .if ${MACHINE_ARCH} == "powerpc64" CFLAGS+= -m32 -mcpu=powerpc .endif # For amd64, there's a bit of mixed bag. Some of the tree (i386, lib*32) is # build 32-bit and some 64-bit (lib*, efi). Centralize all the 32-bit magic here # and activate it when DO32 is explicitly defined to be 1. .if ${MACHINE_ARCH} == "amd64" && ${DO32:U0} == 1 -CFLAGS+= -m32 -mcpu=i386 +CFLAGS+= -m32 # LD_FLAGS is passed directly to ${LD}, not via ${CC}: LD_FLAGS+= -m elf_i386_fbsd AFLAGS+= --32 .endif SSP_CFLAGS= # Add in the no float / no SIMD stuff and announce we're freestanding # aarch64 and riscv don't have -msoft-float, but all others do. riscv # currently has no /boot/loader, but may soon. CFLAGS+= -ffreestanding ${CFLAGS_NO_SIMD} .if ${MACHINE_CPUARCH} == "aarch64" CFLAGS+= -mgeneral-regs-only -fPIC .elif ${MACHINE_CPUARCH} == "riscv" CFLAGS+= -march=rv64imac -mabi=lp64 .else CFLAGS+= -msoft-float .endif .if ${MACHINE_CPUARCH} == "i386" || (${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 1) CFLAGS+= -march=i386 CFLAGS.gcc+= -mpreferred-stack-boundary=2 .endif .if ${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 0 CFLAGS+= -fPIC -mno-red-zone .endif .if ${MACHINE_CPUARCH} == "arm" # Do not generate movt/movw, because the relocation fixup for them does not # translate to the -Bsymbolic -pie format required by self_reloc() in loader(8). # Also, the fpu is not available in a standalone environment. .if ${COMPILER_VERSION} < 30800 CFLAGS.clang+= -mllvm -arm-use-movt=0 .else CFLAGS.clang+= -mno-movt .endif CFLAGS.clang+= -mfpu=none CFLAGS+= -fPIC .endif # The boot loader build uses dd status=none, where possible, for reproducible # build output (since performance varies from run to run). Trouble is that # option was recently (10.3) added to FreeBSD and is non-standard. Only use it # when this test succeeds rather than require dd to be a bootstrap tool. DD_NOSTATUS!=(dd status=none count=0 2> /dev/null && echo status=none) || true DD=dd ${DD_NOSTATUS} .if ${MACHINE_CPUARCH} == "mips" CFLAGS+= -G0 -fno-pic -mno-abicalls .endif .if ${MK_LOADER_FORCE_LE} != "no" .if ${MACHINE_ARCH} == "powerpc64" CFLAGS+= -mlittle-endian .endif .endif # Make sure we use the machine link we're about to create CFLAGS+=-I. all: ${PROG} .if !defined(NO_OBJ) _ILINKS=machine .if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64" _ILINKS+=${MACHINE_CPUARCH} .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _ILINKS+=x86 .endif CLEANFILES+=${_ILINKS} beforedepend: ${_ILINKS} beforebuild: ${_ILINKS} # Ensure that the links exist without depending on it when it exists which # causes all the modules to be rebuilt when the directory pointed to changes. .for _link in ${_ILINKS} .if !exists(${.OBJDIR}/${_link}) ${OBJS}: ${_link} .endif # _link exists .endfor .NOPATH: ${_ILINKS} ${_ILINKS}: @case ${.TARGET} in \ machine) \ if [ ${DO32:U0} -eq 0 ]; then \ path=${SYSDIR}/${MACHINE}/include ; \ else \ path=${SYSDIR}/${MACHINE:C/amd64/i386/}/include ; \ fi ;; \ *) \ path=${SYSDIR}/${.TARGET:T}/include ;; \ esac ; \ path=`(cd $$path && /bin/pwd)` ; \ ${ECHO} ${.TARGET:T} "->" $$path ; \ ln -fhs $$path ${.TARGET:T} .endif # !NO_OBJ .endif # __BOOT_DEFS_MK__ Index: head/stand/i386/gptboot/Makefile =================================================================== --- head/stand/i386/gptboot/Makefile (revision 334431) +++ head/stand/i386/gptboot/Makefile (revision 334432) @@ -1,72 +1,72 @@ # $FreeBSD$ HAVE_GELI= yes .include .PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/common ${SASRC} FILES= gptboot MAN= gptboot.8 NM?= nm BOOT_COMCONSOLE_PORT?= 0x3f8 BOOT_COMCONSOLE_SPEED?= 9600 B2SIOFMT?= 0x3 REL1= 0x700 ORG1= 0x7c00 ORG2= 0x0 # Decide level of UFS support. GPTBOOT_UFS?= UFS1_AND_UFS2 #GPTBOOT_UFS?= UFS2_ONLY #GPTBOOT_UFS?= UFS1_ONLY CFLAGS+=-DBOOTPROG=\"gptboot\" \ -O1 \ -DGPT \ -D${GPTBOOT_UFS} \ -DSIOPRT=${BOOT_COMCONSOLE_PORT} \ -DSIOFMT=${B2SIOFMT} \ -DSIOSPD=${BOOT_COMCONSOLE_SPEED} \ -I${LDRSRC} \ -I${BOOTSRC}/i386/common \ -I${BOOTSRC}/i386/boot2 \ -Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \ -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \ - -Winline -Wno-pointer-sign + -Wno-pointer-sign CFLAGS.gcc+= --param max-inline-insns-single=100 LD_FLAGS+=${LD_FLAGS_BIN} CLEANFILES+= gptboot gptboot: gptldr.bin gptboot.bin ${BTXKERN} btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l gptldr.bin \ -o ${.TARGET} gptboot.bin CLEANFILES+= gptldr.bin gptldr.out gptldr.o gptldr.bin: gptldr.out ${OBJCOPY} -S -O binary gptldr.out ${.TARGET} gptldr.out: gptldr.o ${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} gptldr.o CLEANFILES+= gptboot.bin gptboot.out gptboot.o sio.o crc32.o drv.o \ cons.o ${OPENCRYPTO_XTS} gptboot.bin: gptboot.out ${OBJCOPY} -S -O binary gptboot.out ${.TARGET} gptboot.out: ${BTXCRT} gptboot.o sio.o crc32.o drv.o cons.o ${OPENCRYPTO_XTS} ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBGELIBOOT} ${LIBSA32} .include # XXX: clang integrated-as doesn't grok .codeNN directives yet CFLAGS.gptldr.S= ${CLANG_NO_IAS} Index: head/stand/i386/gptzfsboot/Makefile =================================================================== --- head/stand/i386/gptzfsboot/Makefile (revision 334431) +++ head/stand/i386/gptzfsboot/Makefile (revision 334432) @@ -1,85 +1,85 @@ # $FreeBSD$ HAVE_GELI= yes .include .PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/gptboot \ ${BOOTSRC}/i386/zfsboot ${BOOTSRC}/i386/common \ ${SASRC} FILES= gptzfsboot MAN= gptzfsboot.8 NM?= nm BOOT_COMCONSOLE_PORT?= 0x3f8 BOOT_COMCONSOLE_SPEED?= 9600 B2SIOFMT?= 0x3 REL1= 0x700 ORG1= 0x7c00 ORG2= 0x0 CFLAGS+=-DBOOTPROG=\"gptzfsboot\" \ -O1 \ -DGPT -DZFS -DBOOT2 \ -DSIOPRT=${BOOT_COMCONSOLE_PORT} \ -DSIOFMT=${B2SIOFMT} \ -DSIOSPD=${BOOT_COMCONSOLE_SPEED} \ -I${LDRSRC} \ -I${BOOTSRC}/i386/common \ -I${ZFSSRC} \ -I${SYSDIR}/crypto/skein \ -I${SYSDIR}/cddl/boot/zfs \ -I${BOOTSRC}/i386/btx/lib \ -I${BOOTSRC}/i386/boot2 \ -Wall -Waggregate-return -Wbad-function-cast \ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \ -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \ - -Winline -Wno-pointer-sign + -Wno-pointer-sign CFLAGS.clang+= -Wno-tentative-definition-incomplete-type NO_WCAST_ALIGN= .if ${MACHINE} == "amd64" LIBZFSBOOT=${BOOTOBJ}/zfs32/libzfsboot.a .else LIBZFSBOOT=${BOOTOBJ}/zfs/libzfsboot.a .endif CFLAGS.gcc+= --param max-inline-insns-single=100 LD_FLAGS+=${LD_FLAGS_BIN} CLEANFILES+= gptzfsboot gptzfsboot: gptldr.bin gptzfsboot.bin ${BTXKERN} btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l gptldr.bin \ -o ${.TARGET} gptzfsboot.bin CLEANFILES+= gptldr.bin gptldr.out gptldr.o gptldr.bin: gptldr.out ${OBJCOPY} -S -O binary gptldr.out ${.TARGET} gptldr.out: gptldr.o ${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} gptldr.o CLEANFILES+= gptzfsboot.bin gptzfsboot.out zfsboot.o sio.o cons.o \ drv.o gpt.o ${OPENCRYPTO_XTS} gptzfsboot.bin: gptzfsboot.out ${OBJCOPY} -S -O binary gptzfsboot.out ${.TARGET} gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o \ ${OPENCRYPTO_XTS} ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBGELIBOOT} ${LIBZFSBOOT} ${LIBSA32} zfsboot.o: ${ZFSSRC}/zfsimpl.c .include # XXX: clang integrated-as doesn't grok .codeNN directives yet CFLAGS.gptldr.S= ${CLANG_NO_IAS} Index: head/stand/i386/isoboot/Makefile =================================================================== --- head/stand/i386/isoboot/Makefile (revision 334431) +++ head/stand/i386/isoboot/Makefile (revision 334432) @@ -1,68 +1,71 @@ # $FreeBSD$ HAVE_GELI= yes .include .PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/gptboot \ ${BOOTSRC}/i386/common ${SASRC} FILES= isoboot MAN= isoboot.8 NM?= nm BOOT_COMCONSOLE_PORT?= 0x3f8 BOOT_COMCONSOLE_SPEED?= 9600 B2SIOFMT?= 0x3 REL1= 0x700 ORG1= 0x7c00 ORG2= 0x0 ISOBOOTSIZE?= 30720 CFLAGS+=-DBOOTPROG=\"isoboot\" \ -O1 \ -DSIOPRT=${BOOT_COMCONSOLE_PORT} \ -DSIOFMT=${B2SIOFMT} \ -DSIOSPD=${BOOT_COMCONSOLE_SPEED} \ -I${LDRSRC} \ -I${BOOTSRC}/i386/common \ -I${BOOTSRC}/i386/boot2 \ -Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \ -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \ -Winline -Wno-pointer-sign CFLAGS.gcc+= --param max-inline-insns-single=100 +.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} <= 40201 +CFLAGS.gcc+= -Wno-uninitialized +.endif CFLAGS.clang+= -Oz ${CLANG_OPT_SMALL} LD_FLAGS+=${LD_FLAGS_BIN} CLEANFILES+= isoboot isoboot: gptldr.bin isoboot.bin ${BTXKERN} btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l gptldr.bin \ -o ${.TARGET} isoboot.bin @set -- `ls -l ${.TARGET}`; x=$$((${ISOBOOTSIZE}-$$5)); \ echo "$$x bytes available"; test $$x -ge 0 CLEANFILES+= gptldr.bin gptldr.out gptldr.o gptldr.bin: gptldr.out ${OBJCOPY} -S -O binary gptldr.out ${.TARGET} gptldr.out: gptldr.o ${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} gptldr.o CLEANFILES+= isoboot.bin isoboot.out isoboot.o sio.o crc32.o drv.o \ cons.o ${OPENCRYPTO_XTS} isoboot.bin: isoboot.out ${OBJCOPY} -S -O binary isoboot.out ${.TARGET} isoboot.out: ${BTXCRT} isoboot.o sio.o crc32.o drv.o cons.o ${OPENCRYPTO_XTS} ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBGELIBOOT} ${LIBSA32} .include Index: head/stand/i386/zfsboot/Makefile =================================================================== --- head/stand/i386/zfsboot/Makefile (revision 334431) +++ head/stand/i386/zfsboot/Makefile (revision 334432) @@ -1,93 +1,92 @@ # $FreeBSD$ HAVE_GELI=yes .include .PATH: ${BOOTSRC}/i386/boot2 ${BOOTSRC}/i386/common ${SASRC} FILES= zfsboot MAN= zfsboot.8 NM?= nm BOOT_COMCONSOLE_PORT?= 0x3f8 BOOT_COMCONSOLE_SPEED?= 9600 B2SIOFMT?= 0x3 REL1= 0x700 ORG1= 0x7c00 ORG2= 0x2000 CFLAGS+=-DBOOTPROG=\"zfsboot\" \ -O1 \ -DZFS -DBOOT2 \ -DSIOPRT=${BOOT_COMCONSOLE_PORT} \ -DSIOFMT=${B2SIOFMT} \ -DSIOSPD=${BOOT_COMCONSOLE_SPEED} \ -I${LDRSRC} \ -I${BOOTSRC}/i386/common \ -I${BOOTSRC}/i386 \ -I${ZFSSRC} \ -I${SYSDIR}/crypto/skein \ -I${SYSDIR}/cddl/boot/zfs \ -I${BOOTSRC}/i386/boot2 \ -Wall -Waggregate-return -Wbad-function-cast -Wno-cast-align \ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \ - -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \ - -Winline + -Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings CFLAGS.gcc+= --param max-inline-insns-single=100 .if ${MACHINE} == "amd64" LIBZFSBOOT=${BOOTOBJ}/zfs32/libzfsboot.a .else LIBZFSBOOT=${BOOTOBJ}/zfs/libzfsboot.a .endif LD_FLAGS+=${LD_FLAGS_BIN} CLEANFILES+= zfsboot zfsboot: zfsboot1 zfsboot2 cat zfsboot1 zfsboot2 > zfsboot CLEANFILES+= zfsboot1 zfsldr.out zfsldr.o zfsboot1: zfsldr.out ${OBJCOPY} -S -O binary zfsldr.out ${.TARGET} zfsldr.out: zfsldr.o ${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} zfsldr.o CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \ zfsboot.o zfsboot.s zfsboot.s.tmp sio.o cons.o drv.o # We currently allow 256k bytes for zfsboot - in practice it could be # any size up to 3.5Mb but keeping it fixed size simplifies zfsldr. # BOOT2SIZE= 262144 zfsboot2: zfsboot.ld @set -- `ls -l ${.ALLSRC}`; x=$$((${BOOT2SIZE}-$$5)); \ echo "$$x bytes available"; test $$x -ge 0 ${DD} if=${.ALLSRC} of=${.TARGET} obs=${BOOT2SIZE} conv=osync zfsboot.ld: zfsboot.ldr zfsboot.bin ${BTXKERN} btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l zfsboot.ldr \ -o ${.TARGET} -P 1 zfsboot.bin zfsboot.ldr: cp /dev/null ${.TARGET} zfsboot.bin: zfsboot.out ${OBJCOPY} -S -O binary zfsboot.out ${.TARGET} zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBZFSBOOT} ${LIBGELIBOOT} ${LIBSA32} SRCS= zfsboot.c .include # XXX: clang integrated-as doesn't grok .codeNN directives yet CFLAGS.zfsldr.S= ${CLANG_NO_IAS}