Index: head/sys/boot/forth/check-password.4th =================================================================== --- head/sys/boot/forth/check-password.4th (revision 281615) +++ head/sys/boot/forth/check-password.4th (revision 281616) @@ -1,170 +1,179 @@ \ Copyright (c) 2006-2015 Devin Teske \ 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$ marker task-check-password.4th include /boot/screen.4th vocabulary password-processing only forth also password-processing definitions 13 constant enter_key \ The decimal ASCII value for Enter key 8 constant bs_key \ The decimal ASCII value for Backspace key 21 constant ctrl_u \ The decimal ASCII value for Ctrl-U sequence 255 constant readmax \ Maximum number of characters for the password variable read-tick \ Twiddle position (used by read) variable read-start \ Starting X offset (column)(used by read) create readval readmax allot \ input obtained (up to readmax characters) variable readlen \ input length \ This function blocks program flow (loops forever) until a key is pressed. \ The key that was pressed is added to the top of the stack in the form of its \ decimal ASCII representation. Note: the stack cannot be empty when this \ function starts or an underflow exception will occur. Simplest way to prevent \ this is to pass 0 as a stack parameter (ie. `0 sgetkey'). This function is \ called by the read function. You need not call it directly. NOTE: arrow keys \ show as 0 on the stack \ : sgetkey ( -- ) begin \ Loop forever key? if \ Was a key pressed? (see loader(8)) drop \ Remove stack-cruft key \ Get the key that was pressed \ Check key pressed (see loader(8)) and input limit dup 0<> if ( and ) readlen @ readmax < if \ Spin the twiddle and then exit this function read-tick @ dup 1+ 4 mod read-tick ! 2 spaces dup 0 = if ( 1 ) ." /" else dup 1 = if ( 2 ) ." -" else dup 2 = if ( 3 ) ." \" else dup 3 = if ( 4 ) ." |" else 1 spaces then then then then drop read-start @ 25 at-xy exit then then \ Always allow Backspace, Enter, and Ctrl-U dup bs_key = if exit then dup enter_key = if exit then dup ctrl_u = if exit then then 50 ms \ Sleep for 50 milliseconds (see loader(8)) again ; : cfill ( c c-addr/u -- ) begin dup 0> while -rot 2dup c! 1+ rot 1- repeat 2drop drop ; : read-reset ( -- ) 0 readlen ! 0 readval readmax cfill ; : read ( c-addr/u -- ) \ Expects string prompt as stack input 0 25 at-xy \ Move the cursor to the bottom-left dup 1+ read-start ! \ Store X offset after the prompt 0 readlen ! \ Initialize the read length type \ Print the prompt begin \ Loop forever 0 sgetkey \ Block here, waiting for a key to be pressed \ We are not going to echo the password to the screen (for \ security reasons). If Enter is pressed, we process the \ password, otherwise augment the key to a string. dup enter_key = if drop \ Clean up stack cruft 3 spaces \ Erase the twiddle 10 emit \ Echo new line exit else dup ctrl_u = if 3 spaces read-start @ 25 at-xy \ Erase the twiddle 0 readlen ! \ Reset input to NULL else dup bs_key = if readlen @ 1 - dup readlen ! \ Decrement input length dup 0< if drop 0 dup readlen ! then \ Don't go negative 0= if 3 spaces read-start @ 25 at-xy then \ Twiddle else dup \ Store the character \ NB: sgetkey prevents overflow by way of blocking \ at readmax except for Backspace or Enter readlen @ 1+ dup readlen ! 1- readval + c! then then then drop \ last key pressed again \ Enter was not pressed; repeat ; only forth definitions also password-processing : check-password ( -- ) \ Do not allow the user to proceed beyond this point if a boot-lock \ password has been set (preventing even boot from proceeding) s" bootlock_password" getenv dup -1 <> if dup readmax > if drop readmax then begin s" Boot Password: " read ( prompt -- ) 2dup readval readlen @ compare 0<> while 3000 ms ." loader: incorrect password" 10 emit repeat 2drop read-reset else drop then + \ Prompt for GEOM ELI (geli(8)) passphrase if enabled + s" geom_eli_passphrase_prompt" getenv dup -1 <> if + s" YES" compare-insensitive 0= if + s" GELI Passphrase: " read ( prompt -- ) + readval readlen @ s" kern.geom.eli.passphrase" setenv + read-reset + then + else drop then + \ Exit if a password was not set s" password" getenv -1 = if exit else drop then \ We should prevent the user from visiting the menu or dropping to the \ interactive loader(8) prompt, but still allow the machine to boot... 0 autoboot \ Only reached if autoboot fails for any reason (including if/when \ the user aborts/escapes the countdown sequence leading to boot). s" password" getenv dup readmax > if drop readmax then begin s" Password: " read ( prompt -- ) 2dup readval readlen @ compare 0= if \ Correct password? 2drop read-reset exit then 3000 ms ." loader: incorrect password" 10 emit again ; only forth definitions Index: head/sys/boot/forth/check-password.4th.8 =================================================================== --- head/sys/boot/forth/check-password.4th.8 (revision 281615) +++ head/sys/boot/forth/check-password.4th.8 (revision 281616) @@ -1,139 +1,167 @@ -.\" Copyright (c) 2011-2012 Devin Teske +.\" Copyright (c) 2011-2015 Devin Teske .\" 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$ .\" -.Dd December 10, 2012 +.Dd March 20, 2015 .Dt CHECK-PASSWORD.4TH 8 .Os .Sh NAME .Nm check-password.4th .Nd FreeBSD password-checking boot module .Sh DESCRIPTION The file that goes by the name of .Nm -is a set of commands designed to either prevent booting or prevent modification -of boot options without an appropriately configured password. +is a set of commands designed to do one or more of the following: +.Pp +.Dl o Prevent booting without password +.Dl o Prevent modification of boot options without password +.Dl o Provide a password to mount geli(8) encrypted root disk(s) +.Pp The commands of .Nm by themselves are not enough for most uses. Please refer to the examples below for the most common situations, and to .Xr loader 8 for additional commands. .Pp Before using any of the commands provided in .Nm , it must be included through the command: .Pp .Dl include check-password.4th .Pp This line is present in .Pa /boot/loader.4th file, so it is not needed (and should not be re-issued) in a normal setup. .Pp The commands provided by it are: .Pp .Bl -tag -width disable-module_module -compact -offset indent .It Ic check-password -Dual-purpose function that can either protect the interactive boot menu or -prevent boot without password (separately). +Multi-purpose function that can protect the interactive boot menu, +prevent boot without password, or prompt for geli(8) passphrase +.Pq depending on Xr loader.conf 5 settings . .Pp First checks .Va bootlock_password and if-set, the user cannot continue until the correct password is entered. .Pp -Next checks +Next, checks +.Va geom_eli_passphrase_prompt +and if set to +.Li YES +.Pq case-insensitive +prompts the user to enter their GELI password for later mounting of the root +device(s) during boot. +.Pp +Last, checks .Va password and if-set, tries to .Ic autoboot and only prompts for password on failure or user-interrupt. See .Xr loader.conf 5 for additional information. .El .Pp The environment variables that effect its behavior are: .Bl -tag -width bootlock_password -offset indent .It Va bootlock_password Sets the bootlock password (up to 16 characters long) that is required by .Ic check-password to be entered before the system is allowed to boot. +.It Va geom_eli_passphrase_prompt +Selects whether loader(8) will prompt for GELI credentials, handing-off to the +kernel for later mounting of +.Xr geli 8 +encrypted root device(s). .It Va password Sets the password (up to 16 characters long) that is required by .Ic check-password before the user is allowed to visit the boot menu. .El .Sh FILES .Bl -tag -width /boot/check-password.4th -compact .It Pa /boot/loader The .Xr loader 8 . .It Pa /boot/check-password.4th .Nm itself. .It Pa /boot/loader.rc .Xr loader 8 bootstrapping script. .El .Sh EXAMPLES Standard i386 .Pa /boot/loader.rc : .Pp .Bd -literal -offset indent -compact include /boot/loader.4th check-password .Ed .Pp Set a password in .Xr loader.conf 5 to prevent modification of boot options: .Pp .Bd -literal -offset indent -compact password="abc123" .Ed .Pp Set a password in .Xr loader.conf 5 to prevent booting without password: .Pp .Bd -literal -offset indent -compact bootlock_password="boot" +.Ed +.Pp +Add the following to +.Xr loader.conf 5 +to generate a prompt at boot to collect GELI credentials for mounting +.Xr geli 8 +encrypted root device(s): +.Pp +.Bd -literal -offset indent -compact +geom_eli_passphrase_prompt="YES" .Ed .Sh SEE ALSO .Xr loader.conf 5 , .Xr loader 8 , .Xr loader.4th 8 .Sh HISTORY The .Nm set of commands first appeared in .Fx 9.0 . .Sh AUTHORS The .Nm set of commands was written by .An -nosplit .An Devin Teske Aq dteske@FreeBSD.org . Index: head/sys/boot/forth/loader.conf =================================================================== --- head/sys/boot/forth/loader.conf (revision 281615) +++ head/sys/boot/forth/loader.conf (revision 281616) @@ -1,533 +1,534 @@ # This is loader.conf - a file full of useful variables that you can # set to change the default load behavior of your system. You should # not edit this file! Put any overrides into one of the # loader_conf_files instead and you will be able to update these # defaults later without spamming your local configuration information. # # All arguments must be in double quotes. # # $FreeBSD$ ############################################################## ### Basic configuration options ############################ ############################################################## exec="echo Loading /boot/defaults/loader.conf" kernel="kernel" # /boot sub-directory containing kernel and modules bootfile="kernel" # Kernel name (possibly absolute path) kernel_options="" # Flags to be passed to the kernel loader_conf_files="/boot/device.hints /boot/loader.conf /boot/loader.conf.local" nextboot_conf="/boot/nextboot.conf" nextboot_enable="NO" verbose_loading="NO" # Set to YES for verbose loader output ############################################################## ### Splash screen configuration ############################ ############################################################## splash_bmp_load="NO" # Set this to YES for bmp splash screen! splash_pcx_load="NO" # Set this to YES for pcx splash screen! splash_txt_load="NO" # Set this to YES for TheDraw splash screen! vesa_load="NO" # Set this to YES to load the vesa module bitmap_load="NO" # Set this to YES if you want splash screen! bitmap_name="splash.bmp" # Set this to the name of the file bitmap_type="splash_image_data" # and place it on the module_path ############################################################## ### Random number generator configuration ################### ############################################################## entropy_cache_load="NO" # Set this to YES to load entropy at boot time entropy_cache_name="/boot/entropy" # Set this to the name of the file entropy_cache_type="/boot/entropy" #kern.random.sys.seeded="0" # Set this to 1 to start /dev/random # without waiting for a (re)seed. ############################################################## ### Loader settings ######################################## ############################################################## #loader_delay="3" # Delay in seconds before loading anything. # Default is unset and disabled (no delay). #autoboot_delay="10" # Delay in seconds before autobooting, # set to -1 if you don't want user to be # allowed to interrupt autoboot process and # escape to the loader prompt, set to # "NO" to disable autobooting #password="" # Prevent changes to boot options #bootlock_password="" # Prevent booting (see check-password.4th(8)) +#geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root #beastie_disable="NO" # Turn the beastie boot menu on and off #kernels="kernel kernel.old" # Kernels to display in the boot menu #loader_logo="orbbw" # Desired logo: orbbw, orb, fbsdbw, beastiebw, beastie, none #comconsole_speed="9600" # Set the current serial console speed #console="vidconsole" # A comma separated list of console(s) #currdev="disk1s1a" # Set the current device module_path="/boot/modules" # Set the module search path #prompt="\\${interpret}" # Set the command prompt #root_disk_unit="0" # Force the root disk unit number #rootdev="disk1s1a" # Set the root filesystem #tftp.blksize="1428" # Set the RFC 2348 TFTP block size. # If the TFTP server does not support RFC 2348, # the block size is set to 512. If the value # is out of range ( < 8 || > 9008 ) an error is # returned. #twiddle_divisor="1" # >1 means slow down the progress indicator. ############################################################## ### Kernel settings ######################################## ############################################################## # The following boot_ variables are enabled by setting them to any value. # Their presence in the kernel environment (see kenv(1)) has the same # effect as setting the given boot flag (see boot(8)). #boot_askname="" # -a: Prompt the user for the name of the root device #boot_cdrom="" # -C: Attempt to mount root file system from CD-ROM #boot_ddb="" # -d: Instructs the kernel to start in the DDB debugger #boot_dfltroot="" # -r: Use the statically configured root file system #boot_gdb="" # -g: Selects gdb-remote mode for the kernel debugger #boot_multicons="" # -D: Use multiple consoles #boot_mute="" # -m: Mute the console #boot_pause="" # -p: Pause after each line during device probing #boot_serial="" # -h: Use serial console #boot_single="" # -s: Start system in single-user mode #boot_verbose="" # -v: Causes extra debugging information to be printed #init_path="/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init" # Sets the list of init candidates #init_shell="/bin/sh" # The shell binary used by init(8). #init_script="" # Initial script to run by init(8) before chrooting. #init_chroot="" # Directory for init(8) to chroot into. ############################################################## ### Kernel tunables ######################################## ############################################################## #hw.physmem="1G" # Limit physical memory. See loader(8) #kern.dfldsiz="" # Set the initial data size limit #kern.dflssiz="" # Set the initial stack size limit #kern.hz="100" # Set the kernel interval timer rate #kern.maxbcache="" # Set the max buffer cache KVA storage #kern.maxdsiz="" # Set the max data size #kern.maxfiles="" # Set the sys. wide open files limit #kern.maxproc="" # Set the maximum # of processes #kern.maxssiz="" # Set the max stack size #kern.maxswzone="" # Set the max swmeta KVA storage #kern.maxtsiz="" # Set the max text size #kern.maxusers="32" # Set size of various static tables #kern.msgbufsize="65536" # Set size of kernel message buffer #kern.nbuf="" # Set the number of buffer headers #kern.ncallout="" # Set the maximum # of timer events #kern.ngroups="1023" # Set the maximum # of supplemental groups #kern.sgrowsiz="" # Set the amount to grow stack #kern.cam.boot_delay="10000" # Delay (in ms) of root mount for CAM bus # registration, useful for USB sticks as root #kern.cam.scsi_delay="2000" # Delay (in ms) before probing SCSI #kern.ipc.maxsockets="" # Set the maximum number of sockets avaliable #kern.ipc.nmbclusters="" # Set the number of mbuf clusters #kern.ipc.nsfbufs="" # Set the number of sendfile(2) bufs #net.inet.tcp.tcbhashsize="" # Set the value of TCBHASHSIZE #vfs.root.mountfrom="" # Specify root partition in a way the # kernel understands #vm.kmem_size="" # Sets the size of kernel memory (bytes) #debug.kdb.break_to_debugger="0" # Allow console to break into debugger. #debug.ktr.cpumask="0xf" # Bitmask of CPUs to enable KTR on #debug.ktr.mask="0x1200" # Bitmask of KTR events to enable #debug.ktr.verbose="1" # Enable console dump of KTR events #net.graph.maxalloc="128" # Maximum number of queue items to allocate ############################################################## ### ATA modules ############################################## ############################################################## ataacard_load="NO" # ACARD ataacerlabs_load="NO" # Acer Labs Inc. (ALI) ataamd_load="NO" # American Micro Devices (AMD) ataati_load="NO" # ATI atacenatek_load="NO" # Cenatek atacypress_load="NO" # Cypress atacyrix_load="NO" # Cyrix atahighpoint_load="NO" # HighPoint ataintel_load="NO" # Intel ataite_load="NO" # Integrated Technology Inc. (ITE) atajmicron_load="NO" # JMicron atamarvell_load="NO" # Marvell atamicron_load="NO" # Micron atanational_load="NO" # National atanetcell_load="NO" # NetCell atanvidia_load="NO" # nVidia atapromise_load="NO" # Promise ataserverworks_load="NO" # ServerWorks atasiliconimage_load="NO" # Silicon Image Inc. (SiI) (formerly CMD) atasis_load="NO" # Silicon Integrated Systems Corp.(SiS) atavia_load="NO" # VIA Technologies Inc. ############################################################## ### Filesystem and related modules ######################### ############################################################## # Filesystems cd9660_load="NO" # ISO 9660 filesystem fdescfs_load="NO" # Filedescriptors filesystem linprocfs_load="NO" # Linux compatibility process filesystem linsysfs_load="NO" # Linux compatibility system filesystem msdosfs_load="NO" # FAT-12/16/32 nfsclient_load="NO" # NFS client nfsserver_load="NO" # NFS server nullfs_load="NO" # Null filesystem procfs_load="NO" # Process filesystem reiserfs_load="NO" # ReiserFS unionfs_load="NO" # Union filesystem zfs_load="NO" # ZFS # Related stuff geom_bde_load="NO" # Disk encryption driver (see gbde(4,8)) geom_ccd_load="NO" # Concatenated disk driver (see ccd(4), # ccdconfig(8)) geom_concat_load="NO" # Concatenated disk driver (see gconcat(8)) geom_eli_load="NO" # Disk encryption driver (see geli(8)) geom_gate_load="NO" # Userland disk driver (see geom_gate(4), # ggatec(8), ggated(8), ggatel(8)) geom_journal_load="NO" # Journaled filesystem driver (see gjournal(8)) geom_label_load="NO" # File system labels (see glabel(8)) geom_md_load="NO" # Memory disk driver (vnode/swap/malloc) (see # md(4), mdconfig(8)) geom_mirror_load="NO" # RAID1 disk driver (see gmirror(8)) geom_mountver_load="NO" # Mount verification disk driver geom_nop_load="NO" # Transparent disk driver (see gnop(8)) geom_raid3_load="NO" # RAID3 disk driver (see graid3(8)) geom_shsec_load="NO" # Shared secret disk driver (see gshsec(8)) geom_stripe_load="NO" # RAID0 disk driver (see gstripe(8)) geom_uncompress_load="NO" # Compressed disk images driver (see mkulzma(8)) geom_uzip_load="NO" # Compressed disk images driver (see mkuzip(8)) geom_vinum_load="NO" # Concatenated/mirror/raid driver (see vinum(4)) ############################################################## ### FireWire modules ####################################### ############################################################## firewire_load="NO" # IEEE1394 High-performance Serial Bus fwe_load="NO" # Ethernet emulation driver for FireWire fwip_load="NO" # IP over FireWire driver fwohci_load="NO" # OHCI FireWire chipset device driver sbp_load="NO" # SBP-2 Mass Storage Devices driver sbp_targ_load="NO" # SBP-2 Target mode ############################################################## ### Screen saver modules ################################### ############################################################## # This is best done in rc.conf screensave_load="NO" # Set to YES to load a screensaver module screensave_name="green_saver" # Set to the name of the screensaver module ############################################################## ### Emulation modules ###################################### ############################################################## ibcs2_load="NO" # IBCS2 (SCO) emulation ibcs2_coff_load="NO" linux_load="NO" # Linux emulation svr4_load="NO" # SystemV R4 emulation streams_load="NO" # System V streams module ############################################################## ### Networking modules ##################################### ############################################################## if_disc_load="NO" # Discard device if_ef_load="NO" # pseudo-device providing support for multiple # ethernet frame types if_epair_load="NO" # Virtual b-t-b Ethernet-like interface pair if_gif_load="NO" # generic tunnel interface if_gre_load="NO" # encapsulating network device if_stf_load="NO" # 6to4 tunnel interface if_tap_load="NO" # Ethernet tunnel software network interface if_tun_load="NO" # Tunnel driver (user process ppp) if_vlan_load="NO" # IEEE 802.1Q VLAN network interface ipfw_load="NO" # Firewall pf_load="NO" # packet filter ############################################################## ### Networking drivers ##################################### ############################################################## bridgestp_load="NO" # if_bridge(4) support miibus_load="NO" # miibus support, needed for some drivers carp_load="NO" # carp(4) protocol if_ae_load="NO" # Attansic/Atheros L2 FastEthernet if_age_load="NO" # Attansic/Atheros L1 Gigabit Ethernet if_alc_load="NO" # Atheros AR8131/AR8132 Ethernet if_ale_load="NO" # Atheros AR8121/AR8113/AR8114 Ethernet if_an_load="NO" # Aironet 4500/4800 802.11 wireless NICs if_ath_load="NO" # Atheros IEEE 802.11 wireless NICs if_aue_load="NO" # ADMtek AN986 Pegasus USB Ethernet if_axe_load="NO" # ASIX Electronics AX88172 USB Ethernet if_bce_load="NO" # Broadcom NetXtreme II Gigabit Ethernet if_bfe_load="NO" # Broadcom BCM4401 if_bge_load="NO" # Broadcom BCM570x PCI Gigabit Ethernet if_bridge_load="NO" # if_bridge(4) devices if_bwi_load="NO" # Broadcom BCM53xx IEEE 802.11b/g wireness NICs if_bwn_load="NO" # Broadcom BCM43xx IEEE 802.11 wireless NICs if_bxe_load="NO" # Broadcom NetXtreme II 10Gb Ethernet if_cas_load="NO" # Sun Cassini/Cassini+ and NS DP83065 Saturn if_cm_load="NO" # SMC (90c26, 90c56, 90c66) if_cs_load="NO" # Crystal Semiconductor CS8920 if_cue_load="NO" # CATC USB-EL1210A USB Ethernet if_cxgb_load="NO" # Chelsio T3 10 Gigabit Ethernet if_dc_load="NO" # DEC/Intel 21143 and various workalikes if_de_load="NO" # DEC DC21x4x Ethernet if_ed_load="NO" # National Semiconductor DS8390/WD83C690 # Ethernet if_em_load="NO" # Intel(R) PRO/1000 Gigabit Ethernet if_en_load="NO" # Midway-based ATM interfaces if_ep_load="NO" # 3Com Etherlink III (3c5x9) if_et_load="NO" # Agere ET1310 10/100/Gigabit Ethernet if_ex_load="NO" # Intel EtherExpress Pro/10 Ethernet if_fatm_load="NO" # Fore PCA200E ATM if_fe_load="NO" # Fujitsu MB86960A/MB86965A based Ethernet # adapters if_fxp_load="NO" # Intel EtherExpress PRO/100B (82557, 82558) if_gem_load="NO" # Sun GEM/Sun ERI/Apple GMAC if_hatm_load="NO" # Fore/Marconi HE155 and HE622 if_hme_load="NO" # Sun Microelectronics STP2002-STQ Ethernet if_ie_load="NO" # Intel 82586 if_igb_load="NO" # Intel(R) PRO/1000 Gigabit Ethernet if_ipw_load="NO" # Intel PRO/Wireless 2100 wireless if_iwi_load="NO" # Intel PRO/Wireless 2200BG/2225BG/2915ABG # wireless if_iwn_load="NO" # Intel Wireless WiFi Link 802.11n wireless if_ixgb_load="NO" # Intel PRO/10Gb Ethernet if_ixgbe_load="NO" # Intel PRO/10Gb Ethernet PCI Express if_jme_load="NO" # JMicron JMC250 Gigabit/JMC260 Fast Ethernet if_lagg_load="NO" # lagg(4) devices if_le_load="NO" # AMD Am7900 LANCE and Am79C9xx PCnet if_lge_load="NO" # Level 1 LXT1001 NetCellerator PCI Gigabit # Ethernet if_malo_load="NO" # Marvell Libertas 88W8335 802.11 wireless # adapter if_msk_load="NO" # Marvell/SysKonnect Yukon II Gigabit Ethernet if_mxge_load="NO" # Myricom Myri10GE 10Gb Ethernet if_my_load="NO" # Myson PCI Fast Ethernet if_nfe_load="NO" # NVIDIA nForce MCP Networking Adapter if_nge_load="NO" # National Semiconductor PCI Gigabit Ethernet if_nxge_load="NO" # Neterion Xframe 10Gb Ethernet if_patm_load="NO" # IDT77252 ATM if_pcn_load="NO" # AMD PCnet PCI if_ral_load="NO" # Ralink Technology wireless if_re_load="NO" # RealTek 8139C+/8169/8169S/8110S if_rl_load="NO" # RealTek 8129/8139 if_rue_load="NO" # RealTek RTL8150 USB to Fast Ethernet if_rum_load="NO" # Ralink Technology USB 802.11a/b/g wireless if_run_load="NO" # Ralink Technology USB 802.11a/g/n wireless if_sbni_load="NO" # Granch SBNI12 leased line adapters if_sf_load="NO" # Adaptec Duralink PCI (AIC-6915 "starfire") if_sge_load="NO" # Silicon Integrated Systems SiS 190/191 if_sis_load="NO" # Silicon Integrated Systems SiS 900/7016 if_sk_load="NO" # SysKonnect SK-984x series PCI Gigabit Ethernet if_sn_load="NO" # SMC 91Cxx if_ste_load="NO" # Sundance Technologies ST201 Fast Ethernet if_stge_load="NO" # Sundance/Tamarack TC9021 Gigabit Ethernet if_ti_load="NO" # Alteon Networks Tigon 1 and Tigon 2 if_tl_load="NO" # Texas Instruments TNETE100 ("ThunderLAN") if_tx_load="NO" # SMC 83c17x Fast Ethernet if_txp_load="NO" # 3Com 3XP Typhoon/Sidewinder (3CR990) if_vge_load="NO" # VIA VT6122 PCI Gigabit Ethernet if_vte_load="NO" # DM&P Vortex86 RDC R6040 Fast Ethernet if_uath_load="NO" # Atheros USB wireless for AR5005UG & AR5005UX if_udav_load="NO" # Davicom DM9601 USB Ethernet if_upgt_load="NO" # Conexant/Intersil PrismGT USB wireless if_ural_load="NO" # Ralink Technology USB wireless if_urtw_load="NO" # Realtek 8187L USB wireless if_vr_load="NO" # VIA Rhine I and Rhine II if_vx_load="NO" # 3Com 3C590 family if_wb_load="NO" # Winbond W89C840F if_wi_load="NO" # WaveLAN/IEEE 802.11 wireless NICs if_wpi_load="NO" # Intel 3945ABG Wireless LAN IEEE 802.11 if_xe_load="NO" # Xircom CreditCard PCMCIA if_xl_load="NO" # 3Com Etherlink XL (3c900, 3c905, 3c905B) utopia_load="NO" # ATM PHY driver ############################################################## ### Netgraph modules ####################################### ############################################################## ng_UI_load="NO" # UI netgraph node type ng_async_load="NO" # asynchronous framing netgraph node type ng_bpf_load="NO" # Berkeley packet filter netgraph node type ng_bridge_load="NO" # Ethernet bridging netgraph node type ng_cisco_load="NO" # Cisco HDLC protocol netgraph node type ng_echo_load="NO" # Netgraph echo node type ng_eiface_load="NO" # generic Ethernet interface netgraph node type ng_etf_load="NO" # Ethertype filtering netgraph node type ng_ether_load="NO" # Ethernet netgraph node type ng_frame_relay_load="NO" # frame relay netgraph node type ng_gif_load="NO" # generic tunnel interface netgraph node type ng_gif_demux_load="NO" # demultiplexer for packets from ng_gif(4) nodes ng_hole_load="NO" # Netgraph discard node type ng_hub_load="NO" # packet distribution netgraph node type ng_iface_load="NO" # interface Netgraph node type ng_ip_input_load="NO" # netgraph IP input node type ng_ksocket_load="NO" # kernel socket netgraph node type ng_l2tp_load="NO" # L2TP protocol netgraph node type ng_lmi_load="NO" # frame relay LMI protocol netgraph node type ng_mppc_load="NO" # Microsoft MPPC/MPPE compression and # encryption netgraph node type ng_netflow_load="NO" # Cisco's NetFlow netgraph node type ng_one2many_load="NO" # packet multiplexing netgraph node type ng_ppp_load="NO" # PPP protocol netgraph node type ng_pppoe_load="NO" # RFC 2516 PPPOE protocol netgraph node type ng_pptpgre_load="NO" # PPTP GRE protocol netgraph node type ng_rfc1490_load="NO" # RFC 1490 netgraph node type ng_socket_load="NO" # Netgraph socket node type ng_split_load="NO" # netgraph node to separate incoming and # outgoing flows ng_sppp_load="NO" # sppp netgraph node type ng_tee_load="NO" # Netgraph ``tee'' node type ng_tty_load="NO" # Netgraph node type that is also a line # discipline ng_vjc_load="NO" # Van Jacobsen compression netgraph node type ng_vlan_load="NO" # IEEE 802.1Q VLAN tagging netgraph node type ############################################################## ### Sound modules ########################################## ############################################################## sound_load="NO" # Digital sound subsystem snd_ad1816_load="NO" # ad1816 snd_als4000_load="NO" # als4000 snd_atiixp_load="NO" # atiixp snd_cmi_load="NO" # cmi snd_cs4281_load="NO" # cs4281 snd_csa_load="NO" # csa snd_ds1_load="NO" # ds1 snd_emu10k1_load="NO" # Creative Sound Blaster Live snd_emu10kx_load="NO" # Creative SoundBlaster Live! and Audigy snd_envy24_load="NO" # VIA Envy24 snd_envy24ht_load="NO" # VIA Envy24HT snd_es137x_load="NO" # es137x snd_ess_load="NO" # ess snd_fm801_load="NO" # fm801 snd_hda_load="NO" # Intel High Definition Audio (Controller) snd_ich_load="NO" # Intel ICH snd_maestro_load="NO" # Maestro snd_maestro3_load="NO" # Maestro3 snd_mss_load="NO" # Mss snd_neomagic_load="NO" # Neomagic snd_sb16_load="NO" # Sound Blaster 16 snd_sb8_load="NO" # Sound Blaster Pro snd_sbc_load="NO" # Sbc snd_solo_load="NO" # Solo snd_spicds_load="NO" # SPI codecs snd_t4dwave_load="NO" # t4dwave snd_via8233_load="NO" # via8233 snd_via82c686_load="NO" # via82c686 snd_vibes_load="NO" # vibes snd_driver_load="NO" # All sound drivers ############################################################## ### USB modules ############################################ ############################################################## usb_load="NO" # USB subsystem udbp_load="NO" # USB double bulk pipe host 2 host cables ugen_load="NO" # USB generic device, if all else fails ... ucycom_load="NO" # Cyprus USB serial adapters ufm_load="NO" # Fm Radio uhid_load="NO" # Human Interface Devices ukbd_load="NO" # Keyboard ulpt_load="NO" # Printer ums_load="NO" # Mouse umass_load="NO" # Mass Storage Devices umct_load="NO" # Magic Control Technology USB-RS232 umodem_load="NO" # Modems uplcom_load="NO" # Prolific USB serial adapters urio_load="NO" # Rio MP3 players uvisor_load="NO" # PalmOS based PDAs if_aue_load="NO" # ADMtek USB ethernet if_axe_load="NO" # ASIX Electronics AX88172 USB ethernet if_cdce_load="NO" # Ethernet over USB (CDC) if_cue_load="NO" # CATC USB ethernet if_kue_load="NO" # Kawasaki LSI USB ethernet if_rae_load="NO" # Realtek RTL8150 USB adapter. if_rum_load="NO" # Ralink USB 802.11 wireless adapter if_uath_load="NO" # Atheros AR5523 wireless adapter if_run_load="NO" # Ralink USB 802.11 wireless adapter if_ural_load="NO" # Ralink RT2500USB 802.11 wireless adapter if_zyd_load="NO" # ZyDAS ZD1211(B) USB 802.11 wireless adapter snd_uaudio_load="NO" # USB audio ############################################################## ### Other modules ########################################## ############################################################## aio_load="NO" # Asynchronous I/O bktr_load="NO" # Brooktree Bt848/Bt878 TV/Video Capture Card ispfw_load="NO" # Qlogic ISP Firmware agp_load="NO" # agp module accf_data_load="NO" # Wait for data accept filter accf_dns_load="NO" # Wait for full DNS request accept filter accf_http_load="NO" # Wait for full HTTP request accept filter ppi_load="NO" # Interface to ppbus parallel 'geek' port pps_load="NO" # Pulse per second devices puc_load="NO" # PCI "Universal" Communications driver random_load="NO" # Random device speaker_load="NO" # AT speaker module coretemp_load="NO" # Intel Core CPU temperature monitor vkbd_load="NO" # Virtual AT keyboard interface vpd_load="NO" # Vital Product Data kernel interface vpo_load="NO" # Parallel to SCSI interface driver amdtemp_load="NO" # AMD K8/K10/K11 temperature monitor tpm_load="NO" # Trusted Platform Module wbwd_load="NO" # Winbond watchdog ############################################################## ### ACPI settings ########################################## ############################################################## acpi_dsdt_load="NO" # DSDT Overriding acpi_dsdt_type="acpi_dsdt" # Don't change this acpi_dsdt_name="/boot/acpi_dsdt.aml" # Override DSDT in BIOS by this file acpi_video_load="NO" # Load the ACPI video extension driver ############################################################## ### TrustedBSD MAC settings ################################## ############################################################## mac_biba_load="NO" # Biba MAC policy mac_bsdextended_load="NO" # BSD/extended MAC policy mac_ifoff="NO" # Interface silencing policy mac_mls_load="NO" # MLS MAC policy mac_none_load="NO" # Null MAC policy mac_partition_load="NO" # Partition MAC policy mac_seeotheruids_load="NO" # UID visbility MAC policy ############################################################## ### Module loading syntax example ########################## ############################################################## #module_load="YES" # loads module "module" #module_name="realname" # uses "realname" instead of "module" #module_type="type" # passes "-t type" to load #module_flags="flags" # passes "flags" to the module #module_before="cmd" # executes "cmd" before loading the module #module_after="cmd" # executes "cmd" after loading the module #module_error="cmd" # executes "cmd" if load fails Index: head/sys/kern/init_main.c =================================================================== --- head/sys/kern/init_main.c (revision 281615) +++ head/sys/kern/init_main.c (revision 281616) @@ -1,864 +1,867 @@ /*- * Copyright (c) 1995 Terrence R. Lambert * All rights reserved. * * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * * @(#)init_main.c 8.9 (Berkeley) 1/21/94 */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_init_path.h" #include "opt_verbose_sysinit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void mi_startup(void); /* Should be elsewhere */ /* Components of the first process -- never freed. */ static struct session session0; static struct pgrp pgrp0; struct proc proc0; struct thread thread0 __aligned(16); struct vmspace vmspace0; struct proc *initproc; #ifndef BOOTHOWTO #define BOOTHOWTO 0 #endif int boothowto = BOOTHOWTO; /* initialized so that it can be patched */ SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, "Boot control flags, passed from loader"); #ifndef BOOTVERBOSE #define BOOTVERBOSE 0 #endif int bootverbose = BOOTVERBOSE; SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, "Control the output of verbose kernel messages"); /* * This ensures that there is at least one entry so that the sysinit_set * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never * executed. */ SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL); /* * The sysinit table itself. Items are checked off as the are run. * If we want to register new sysinit types, add them to newsysinit. */ SET_DECLARE(sysinit_set, struct sysinit); struct sysinit **sysinit, **sysinit_end; struct sysinit **newsysinit, **newsysinit_end; /* * Merge a new sysinit set into the current set, reallocating it if * necessary. This can only be called after malloc is running. */ void sysinit_add(struct sysinit **set, struct sysinit **set_end) { struct sysinit **newset; struct sysinit **sipp; struct sysinit **xipp; int count; count = set_end - set; if (newsysinit) count += newsysinit_end - newsysinit; else count += sysinit_end - sysinit; newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT); if (newset == NULL) panic("cannot malloc for sysinit"); xipp = newset; if (newsysinit) for (sipp = newsysinit; sipp < newsysinit_end; sipp++) *xipp++ = *sipp; else for (sipp = sysinit; sipp < sysinit_end; sipp++) *xipp++ = *sipp; for (sipp = set; sipp < set_end; sipp++) *xipp++ = *sipp; if (newsysinit) free(newsysinit, M_TEMP); newsysinit = newset; newsysinit_end = newset + count; } #if defined (DDB) && defined(VERBOSE_SYSINIT) static const char * symbol_name(vm_offset_t va, db_strategy_t strategy) { const char *name; c_db_sym_t sym; db_expr_t offset; if (va == 0) return (NULL); sym = db_search_symbol(va, strategy, &offset); if (offset != 0) return (NULL); db_symbol_values(sym, &name, NULL); return (name); } #endif /* * System startup; initialize the world, create process 0, mount root * filesystem, and fork to create init and pagedaemon. Most of the * hard work is done in the lower-level initialization routines including * startup(), which does memory initialization and autoconfiguration. * * This allows simple addition of new kernel subsystems that require * boot time initialization. It also allows substitution of subsystem * (for instance, a scheduler, kernel profiler, or VM system) by object * module. Finally, it allows for optional "kernel threads". */ void mi_startup(void) { register struct sysinit **sipp; /* system initialization*/ register struct sysinit **xipp; /* interior loop of sort*/ register struct sysinit *save; /* bubble*/ #if defined(VERBOSE_SYSINIT) int last; int verbose; #endif if (boothowto & RB_VERBOSE) bootverbose++; if (sysinit == NULL) { sysinit = SET_BEGIN(sysinit_set); sysinit_end = SET_LIMIT(sysinit_set); } restart: /* * Perform a bubble sort of the system initialization objects by * their subsystem (primary key) and order (secondary key). */ for (sipp = sysinit; sipp < sysinit_end; sipp++) { for (xipp = sipp + 1; xipp < sysinit_end; xipp++) { if ((*sipp)->subsystem < (*xipp)->subsystem || ((*sipp)->subsystem == (*xipp)->subsystem && (*sipp)->order <= (*xipp)->order)) continue; /* skip*/ save = *sipp; *sipp = *xipp; *xipp = save; } } #if defined(VERBOSE_SYSINIT) last = SI_SUB_COPYRIGHT; verbose = 0; #if !defined(DDB) printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n"); #endif #endif /* * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. */ for (sipp = sysinit; sipp < sysinit_end; sipp++) { if ((*sipp)->subsystem == SI_SUB_DUMMY) continue; /* skip dummy task(s)*/ if ((*sipp)->subsystem == SI_SUB_DONE) continue; #if defined(VERBOSE_SYSINIT) if ((*sipp)->subsystem > last) { verbose = 1; last = (*sipp)->subsystem; printf("subsystem %x\n", last); } if (verbose) { #if defined(DDB) const char *func, *data; func = symbol_name((vm_offset_t)(*sipp)->func, DB_STGY_PROC); data = symbol_name((vm_offset_t)(*sipp)->udata, DB_STGY_ANY); if (func != NULL && data != NULL) printf(" %s(&%s)... ", func, data); else if (func != NULL) printf(" %s(%p)... ", func, (*sipp)->udata); else #endif printf(" %p(%p)... ", (*sipp)->func, (*sipp)->udata); } #endif /* Call function */ (*((*sipp)->func))((*sipp)->udata); #if defined(VERBOSE_SYSINIT) if (verbose) printf("done.\n"); #endif /* Check off the one we're just done */ (*sipp)->subsystem = SI_SUB_DONE; /* Check if we've installed more sysinit items via KLD */ if (newsysinit != NULL) { if (sysinit != SET_BEGIN(sysinit_set)) free(sysinit, M_TEMP); sysinit = newsysinit; sysinit_end = newsysinit_end; newsysinit = NULL; newsysinit_end = NULL; goto restart; } } mtx_assert(&Giant, MA_OWNED | MA_NOTRECURSED); mtx_unlock(&Giant); /* * Now hand over this thread to swapper. */ swapper(); /* NOTREACHED*/ } /* *************************************************************************** **** **** The following SYSINIT's belong elsewhere, but have not yet **** been moved. **** *************************************************************************** */ static void print_caddr_t(void *data) { printf("%s", (char *)data); } static void print_version(void *data __unused) { int len; /* Strip a trailing newline from version. */ len = strlen(version); while (len > 0 && version[len - 1] == '\n') len--; printf("%.*s %s\n", len, version, machine); printf("%s\n", compiler_version); } SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright); SYSINIT(trademark, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, trademark); SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_THIRD, print_version, NULL); #ifdef WITNESS static char wit_warn[] = "WARNING: WITNESS option enabled, expect reduced performance.\n"; SYSINIT(witwarn, SI_SUB_COPYRIGHT, SI_ORDER_THIRD + 1, print_caddr_t, wit_warn); SYSINIT(witwarn2, SI_SUB_LAST, SI_ORDER_THIRD + 1, print_caddr_t, wit_warn); #endif #ifdef DIAGNOSTIC static char diag_warn[] = "WARNING: DIAGNOSTIC option enabled, expect reduced performance.\n"; SYSINIT(diagwarn, SI_SUB_COPYRIGHT, SI_ORDER_THIRD + 2, print_caddr_t, diag_warn); SYSINIT(diagwarn2, SI_SUB_LAST, SI_ORDER_THIRD + 2, print_caddr_t, diag_warn); #endif static int null_fetch_syscall_args(struct thread *td __unused, struct syscall_args *sa __unused) { panic("null_fetch_syscall_args"); } static void null_set_syscall_retval(struct thread *td __unused, int error __unused) { panic("null_set_syscall_retval"); } struct sysentvec null_sysvec = { .sv_size = 0, .sv_table = NULL, .sv_mask = 0, .sv_sigsize = 0, .sv_sigtbl = NULL, .sv_errsize = 0, .sv_errtbl = NULL, .sv_transtrap = NULL, .sv_fixup = NULL, .sv_sendsig = NULL, .sv_sigcode = NULL, .sv_szsigcode = NULL, .sv_prepsyscall = NULL, .sv_name = "null", .sv_coredump = NULL, .sv_imgact_try = NULL, .sv_minsigstksz = 0, .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_ALL, .sv_copyout_strings = NULL, .sv_setregs = NULL, .sv_fixlimit = NULL, .sv_maxssiz = NULL, .sv_flags = 0, .sv_set_syscall_retval = null_set_syscall_retval, .sv_fetch_syscall_args = null_fetch_syscall_args, .sv_syscallnames = NULL, .sv_schedtail = NULL, }; /* *************************************************************************** **** **** The two following SYSINIT's are proc0 specific glue code. I am not **** convinced that they can not be safely combined, but their order of **** operation has been maintained as the same as the original init_main.c **** for right now. **** **** These probably belong in init_proc.c or kern_proc.c, since they **** deal with proc0 (the fork template process). **** *************************************************************************** */ /* ARGSUSED*/ static void proc0_init(void *dummy __unused) { struct proc *p; struct thread *td; struct ucred *newcred; vm_paddr_t pageablemem; int i; GIANT_REQUIRED; p = &proc0; td = &thread0; /* * Initialize magic number and osrel. */ p->p_magic = P_MAGIC; p->p_osrel = osreldate; /* * Initialize thread and process structures. */ procinit(); /* set up proc zone */ threadinit(); /* set up UMA zones */ /* * Initialise scheduler resources. * Add scheduler specific parts to proc, thread as needed. */ schedinit(); /* scheduler gets its house in order */ /* * Create process 0 (the swapper). */ LIST_INSERT_HEAD(&allproc, p, p_list); LIST_INSERT_HEAD(PIDHASH(0), p, p_hash); mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK); p->p_pgrp = &pgrp0; LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); LIST_INIT(&pgrp0.pg_members); LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); pgrp0.pg_session = &session0; mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF); refcount_init(&session0.s_count, 1); session0.s_leader = p; p->p_sysent = &null_sysvec; p->p_flag = P_SYSTEM | P_INMEM; p->p_flag2 = 0; p->p_state = PRS_NORMAL; knlist_init_mtx(&p->p_klist, &p->p_mtx); STAILQ_INIT(&p->p_ktr); p->p_nice = NZERO; /* pid_max cannot be greater than PID_MAX */ td->td_tid = PID_MAX + 1; LIST_INSERT_HEAD(TIDHASH(td->td_tid), td, td_hash); td->td_state = TDS_RUNNING; td->td_pri_class = PRI_TIMESHARE; td->td_user_pri = PUSER; td->td_base_user_pri = PUSER; td->td_lend_user_pri = PRI_MAX; td->td_priority = PVM; td->td_base_pri = PVM; td->td_oncpu = 0; td->td_flags = TDF_INMEM; td->td_pflags = TDP_KTHREAD; td->td_cpuset = cpuset_thread0(); prison0_init(); p->p_peers = 0; p->p_leader = p; p->p_reaper = p; LIST_INIT(&p->p_reaplist); strncpy(p->p_comm, "kernel", sizeof (p->p_comm)); strncpy(td->td_name, "swapper", sizeof (td->td_name)); callout_init_mtx(&p->p_itcallout, &p->p_mtx, 0); callout_init_mtx(&p->p_limco, &p->p_mtx, 0); callout_init(&td->td_slpcallout, CALLOUT_MPSAFE); /* Create credentials. */ newcred = crget(); newcred->cr_ngroups = 1; /* group 0 */ newcred->cr_uidinfo = uifind(0); newcred->cr_ruidinfo = uifind(0); newcred->cr_prison = &prison0; newcred->cr_loginclass = loginclass_find("default"); proc_set_cred_init(p, newcred); #ifdef AUDIT audit_cred_kproc0(newcred); #endif #ifdef MAC mac_cred_create_swapper(newcred); #endif td->td_ucred = crhold(newcred); /* Create sigacts. */ p->p_sigacts = sigacts_alloc(); /* Initialize signal state for process 0. */ siginit(&proc0); /* Create the file descriptor table. */ p->p_fd = fdinit(NULL, false); p->p_fdtol = NULL; /* Create the limits structures. */ p->p_limit = lim_alloc(); for (i = 0; i < RLIM_NLIMITS; i++) p->p_limit->pl_rlimit[i].rlim_cur = p->p_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY; p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_cur = p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_cur = p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; p->p_limit->pl_rlimit[RLIMIT_DATA].rlim_cur = dfldsiz; p->p_limit->pl_rlimit[RLIMIT_DATA].rlim_max = maxdsiz; p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur = dflssiz; p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_max = maxssiz; /* Cast to avoid overflow on i386/PAE. */ pageablemem = ptoa((vm_paddr_t)vm_cnt.v_free_count); p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_cur = p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_max = pageablemem; p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = pageablemem / 3; p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = pageablemem; p->p_cpulimit = RLIM_INFINITY; /* Initialize resource accounting structures. */ racct_create(&p->p_racct); p->p_stats = pstats_alloc(); /* Allocate a prototype map so we have something to fork. */ pmap_pinit0(vmspace_pmap(&vmspace0)); p->p_vmspace = &vmspace0; vmspace0.vm_refcnt = 1; /* * proc0 is not expected to enter usermode, so there is no special * handling for sv_minuser here, like is done for exec_new_vmspace(). */ vm_map_init(&vmspace0.vm_map, vmspace_pmap(&vmspace0), p->p_sysent->sv_minuser, p->p_sysent->sv_maxuser); /* * Call the init and ctor for the new thread and proc. We wait * to do this until all other structures are fairly sane. */ EVENTHANDLER_INVOKE(process_init, p); EVENTHANDLER_INVOKE(thread_init, td); EVENTHANDLER_INVOKE(process_ctor, p); EVENTHANDLER_INVOKE(thread_ctor, td); /* * Charge root for one process. */ (void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0); PROC_LOCK(p); racct_add_force(p, RACCT_NPROC, 1); PROC_UNLOCK(p); } SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL); /* ARGSUSED*/ static void proc0_post(void *dummy __unused) { struct timespec ts; struct proc *p; struct rusage ru; struct thread *td; /* * Now we can look at the time, having had a chance to verify the * time from the filesystem. Pretend that proc0 started now. */ sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { microuptime(&p->p_stats->p_start); PROC_STATLOCK(p); rufetch(p, &ru); /* Clears thread stats */ PROC_STATUNLOCK(p); p->p_rux.rux_runtime = 0; p->p_rux.rux_uticks = 0; p->p_rux.rux_sticks = 0; p->p_rux.rux_iticks = 0; FOREACH_THREAD_IN_PROC(p, td) { td->td_runtime = 0; } } sx_sunlock(&allproc_lock); PCPU_SET(switchtime, cpu_ticks()); PCPU_SET(switchticks, ticks); /* * Give the ``random'' number generator a thump. */ nanotime(&ts); srandom(ts.tv_sec ^ ts.tv_nsec); } SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL); static void random_init(void *dummy __unused) { /* * After CPU has been started we have some randomness on most * platforms via get_cyclecount(). For platforms that don't * we will reseed random(9) in proc0_post() as well. */ srandom(get_cyclecount()); } SYSINIT(random, SI_SUB_RANDOM, SI_ORDER_FIRST, random_init, NULL); /* *************************************************************************** **** **** The following SYSINIT's and glue code should be moved to the **** respective files on a per subsystem basis. **** *************************************************************************** */ /* *************************************************************************** **** **** The following code probably belongs in another file, like **** kern/init_init.c. **** *************************************************************************** */ /* * List of paths to try when searching for "init". */ static char init_path[MAXPATHLEN] = #ifdef INIT_PATH __XSTRING(INIT_PATH); #else "/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init"; #endif SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, "Path used to search the init process"); /* * Shutdown timeout of init(8). * Unused within kernel, but used to control init(8), hence do not remove. */ #ifndef INIT_SHUTDOWN_TIMEOUT #define INIT_SHUTDOWN_TIMEOUT 120 #endif static int init_shutdown_timeout = INIT_SHUTDOWN_TIMEOUT; SYSCTL_INT(_kern, OID_AUTO, init_shutdown_timeout, CTLFLAG_RW, &init_shutdown_timeout, 0, "Shutdown timeout of init(8). " "Unused within kernel, but used to control init(8)"); /* * Start the initial user process; try exec'ing each pathname in init_path. * The program is invoked with one argument containing the boot flags. */ static void start_init(void *dummy) { vm_offset_t addr; struct execve_args args; int options, error; char *var, *path, *next, *s; char *ucp, **uap, *arg0, *arg1; struct thread *td; struct proc *p; mtx_lock(&Giant); GIANT_REQUIRED; td = curthread; p = td->td_proc; vfs_mountroot(); + /* Wipe GELI passphrase from the environment. */ + kern_unsetenv("kern.geom.eli.passphrase"); + /* * Need just enough stack to hold the faked-up "execve()" arguments. */ addr = p->p_sysent->sv_usrstack - PAGE_SIZE; if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) panic("init: couldn't allocate argument space"); p->p_vmspace->vm_maxsaddr = (caddr_t)addr; p->p_vmspace->vm_ssize = 1; if ((var = kern_getenv("init_path")) != NULL) { strlcpy(init_path, var, sizeof(init_path)); freeenv(var); } for (path = init_path; *path != '\0'; path = next) { while (*path == ':') path++; if (*path == '\0') break; for (next = path; *next != '\0' && *next != ':'; next++) /* nothing */ ; if (bootverbose) printf("start_init: trying %.*s\n", (int)(next - path), path); /* * Move out the boot flag argument. */ options = 0; ucp = (char *)p->p_sysent->sv_usrstack; (void)subyte(--ucp, 0); /* trailing zero */ if (boothowto & RB_SINGLE) { (void)subyte(--ucp, 's'); options = 1; } #ifdef notyet if (boothowto & RB_FASTBOOT) { (void)subyte(--ucp, 'f'); options = 1; } #endif #ifdef BOOTCDROM (void)subyte(--ucp, 'C'); options = 1; #endif if (options == 0) (void)subyte(--ucp, '-'); (void)subyte(--ucp, '-'); /* leading hyphen */ arg1 = ucp; /* * Move out the file name (also arg 0). */ (void)subyte(--ucp, 0); for (s = next - 1; s >= path; s--) (void)subyte(--ucp, *s); arg0 = ucp; /* * Move out the arg pointers. */ uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1)); (void)suword((caddr_t)--uap, (long)0); /* terminator */ (void)suword((caddr_t)--uap, (long)(intptr_t)arg1); (void)suword((caddr_t)--uap, (long)(intptr_t)arg0); /* * Point at the arguments. */ args.fname = arg0; args.argv = uap; args.envv = NULL; /* * Now try to exec the program. If can't for any reason * other than it doesn't exist, complain. * * Otherwise, return via fork_trampoline() all the way * to user mode as init! */ if ((error = sys_execve(td, &args)) == 0) { mtx_unlock(&Giant); return; } if (error != ENOENT) printf("exec %.*s: error %d\n", (int)(next - path), path, error); } printf("init: not found in path %s\n", init_path); panic("no init"); } /* * Like kproc_create(), but runs in it's own address space. * We do this early to reserve pid 1. * * Note special case - do not make it runnable yet. Other work * in progress will change this more. */ static void create_init(const void *udata __unused) { struct ucred *newcred, *oldcred; int error; error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc, NULL, 0); if (error) panic("cannot fork init: %d\n", error); KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); /* divorce init's credentials from the kernel's */ newcred = crget(); sx_xlock(&proctree_lock); PROC_LOCK(initproc); initproc->p_flag |= P_SYSTEM | P_INMEM; initproc->p_treeflag |= P_TREE_REAPER; LIST_INSERT_HEAD(&initproc->p_reaplist, &proc0, p_reapsibling); oldcred = initproc->p_ucred; crcopy(newcred, oldcred); #ifdef MAC mac_cred_create_init(newcred); #endif #ifdef AUDIT audit_cred_proc1(newcred); #endif proc_set_cred(initproc, newcred); PROC_UNLOCK(initproc); sx_xunlock(&proctree_lock); crfree(oldcred); cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); } SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL); /* * Make it runnable now. */ static void kick_init(const void *udata __unused) { struct thread *td; td = FIRST_THREAD_IN_PROC(initproc); thread_lock(td); TD_SET_CAN_RUN(td); sched_add(td, SRQ_BORING); thread_unlock(td); } SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_MIDDLE, kick_init, NULL); Index: head/usr.sbin/bsdinstall/scripts/zfsboot =================================================================== --- head/usr.sbin/bsdinstall/scripts/zfsboot (revision 281615) +++ head/usr.sbin/bsdinstall/scripts/zfsboot (revision 281616) @@ -1,1585 +1,1588 @@ #!/bin/sh #- # Copyright (c) 2013-2014 Allan Jude # Copyright (c) 2013-2015 Devin Teske # 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$ # ############################################################ INCLUDES BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." "$0" f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/password/password.subr f_include $BSDCFG_SHARE/variable.subr ############################################################ CONFIGURATION # # Default name of the boot-pool # : ${ZFSBOOT_POOL_NAME:=zroot} # # Default options to use when creating zroot pool # : ${ZFSBOOT_POOL_CREATE_OPTIONS:=-O compress=lz4 -O atime=off} # # Default name for the boot environment parent dataset # : ${ZFSBOOT_BEROOT_NAME:=ROOT} # # Default name for the primany boot environment # : ${ZFSBOOT_BOOTFS_NAME:=default} # # Default Virtual Device (vdev) type to create # : ${ZFSBOOT_VDEV_TYPE:=stripe} # # Should we use sysctl(8) vfs.zfs.min_auto_ashift=12 to force 4K sectors? # : ${ZFSBOOT_FORCE_4K_SECTORS:=1} # # Should we use geli(8) to encrypt the drives? # NB: Automatically enables ZFSBOOT_BOOT_POOL # : ${ZFSBOOT_GELI_ENCRYPTION=} # # Default path to the geli(8) keyfile used in drive encryption # : ${ZFSBOOT_GELI_KEY_FILE:=/boot/encryption.key} # # Create a separate boot pool? # NB: Automatically set when using geli(8) or MBR # : ${ZFSBOOT_BOOT_POOL=} # # Options to use when creating separate boot pool (if any) # : ${ZFSBOOT_BOOT_POOL_CREATE_OPTIONS:=} # # Default name for boot pool when enabled (e.g., geli(8) or MBR) # : ${ZFSBOOT_BOOT_POOL_NAME:=bootpool} # # Default size for boot pool when enabled (e.g., geli(8) or MBR) # : ${ZFSBOOT_BOOT_POOL_SIZE:=2g} # # Default disks to use (always empty unless being scripted) # : ${ZFSBOOT_DISKS:=} # # Default partitioning scheme to use on disks # : ${ZFSBOOT_PARTITION_SCHEME:=GPT} # # How much swap to put on each block device in the boot zpool # NOTE: Value passed to gpart(8); which supports SI unit suffixes. # : ${ZFSBOOT_SWAP_SIZE:=2g} # # Should we use geli(8) to encrypt the swap? # : ${ZFSBOOT_SWAP_ENCRYPTION=} # # Should we use gmirror(8) to mirror the swap? # : ${ZFSBOOT_SWAP_MIRROR=} # # Default ZFS datasets for root zpool # # NOTE: Requires /tmp, /var/tmp, /$ZFSBOOT_BOOTFS_NAME/$ZFSBOOT_BOOTFS_NAME # NOTE: Anything after pound/hash character [#] is ignored as a comment. # f_isset ZFSBOOT_DATASETS || ZFSBOOT_DATASETS=" # DATASET OPTIONS (comma or space separated; or both) # Boot Environment [BE] root and default boot dataset /$ZFSBOOT_BEROOT_NAME mountpoint=none /$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME mountpoint=/ # Compress /tmp, allow exec but not setuid /tmp mountpoint=/tmp,exec=on,setuid=off # Don't mount /usr so that 'base' files go to the BEROOT /usr mountpoint=/usr,canmount=off # Home directories separated so they are common to all BEs /usr/home # NB: /home is a symlink to /usr/home # Ports tree /usr/ports setuid=off # Source tree (compressed) /usr/src # Create /var and friends /var mountpoint=/var,canmount=off /var/crash exec=off,setuid=off /var/log exec=off,setuid=off /var/mail atime=on /var/tmp setuid=off " # END-QUOTE # # If interactive and the user has not explicitly chosen a vdev type or disks, # make the user confirm scripted/default choices when proceeding to install. # : ${ZFSBOOT_CONFIRM_LAYOUT:=1} ############################################################ GLOBALS # # Format of a line in printf(1) syntax to add to fstab(5) # FSTAB_FMT="%s\t\t%s\t%s\t%s\t\t%s\t%s\n" # # Command strings for various tasks # CHMOD_MODE='chmod %s "%s"' DD_WITH_OPTIONS='dd if="%s" of="%s" %s' ECHO_APPEND='echo "%s" >> "%s"' GELI_ATTACH='geli attach -j - -k "%s" "%s"' GELI_DETACH_F='geli detach -f "%s"' GELI_PASSWORD_INIT='geli init -b -B "%s" -e %s -J - -K "%s" -l 256 -s 4096 "%s"' GPART_ADD='gpart add -t %s "%s"' GPART_ADD_INDEX='gpart add -i %s -t %s "%s"' GPART_ADD_INDEX_WITH_SIZE='gpart add -i %s -t %s -s %s "%s"' GPART_ADD_LABEL='gpart add -l %s -t %s "%s"' GPART_ADD_LABEL_WITH_SIZE='gpart add -l %s -t %s -s %s "%s"' GPART_BOOTCODE='gpart bootcode -b "%s" "%s"' GPART_BOOTCODE_PART='gpart bootcode -b "%s" -p "%s" -i %s "%s"' GPART_CREATE='gpart create -s %s "%s"' GPART_DESTROY_F='gpart destroy -F "%s"' GPART_SET_ACTIVE='gpart set -a active -i %s "%s"' GRAID_DELETE='graid delete "%s"' LN_SF='ln -sf "%s" "%s"' MKDIR_P='mkdir -p "%s"' MOUNT_TYPE='mount -t %s "%s" "%s"' PRINTF_CONF="printf '%s=\"%%s\"\\\n' %s >> \"%s\"" PRINTF_FSTAB='printf "$FSTAB_FMT" "%s" "%s" "%s" "%s" "%s" "%s" >> "%s"' SHELL_TRUNCATE=':> "%s"' SWAP_GMIRROR_LABEL='gmirror label swap %s' SYSCTL_ZFS_MIN_ASHIFT_12='sysctl vfs.zfs.min_auto_ashift=12' UMOUNT='umount "%s"' ZFS_CREATE_WITH_OPTIONS='zfs create %s "%s"' ZFS_SET='zfs set "%s" "%s"' ZFS_UNMOUNT='zfs unmount "%s"' ZPOOL_CREATE_WITH_OPTIONS='zpool create %s "%s" %s %s' ZPOOL_DESTROY='zpool destroy "%s"' ZPOOL_EXPORT='zpool export "%s"' ZPOOL_IMPORT_WITH_OPTIONS='zpool import %s "%s"' ZPOOL_LABELCLEAR_F='zpool labelclear -f "%s"' ZPOOL_SET='zpool set %s "%s"' # # Strings that should be moved to an i18n file and loaded with f_include_lang() # hline_alnum_arrows_punc_tab_enter="Use alnum, arrows, punctuation, TAB or ENTER" hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER" hline_arrows_tab_enter="Press arrows, TAB or ENTER" msg_an_unknown_error_occurred="An unknown error occurred" msg_back="Back" msg_cancel="Cancel" msg_change_selection="Change Selection" msg_configure_options="Configure Options:" msg_detailed_disk_info="gpart(8) show %s:\n%s\n\ncamcontrol(8) inquiry %s:\n%s\n\n\ncamcontrol(8) identify %s:\n%s\n" msg_disk_info="Disk Info" msg_disk_info_help="Get detailed information on disk device(s)" msg_disk_singular="disk" msg_disk_plural="disks" msg_encrypt_disks="Encrypt Disks?" msg_encrypt_disks_help="Use geli(8) to encrypt all data partitions" msg_error="Error" msg_force_4k_sectors="Force 4K Sectors?" msg_force_4k_sectors_help="Use sysctl(8) vfs.zfs.min_auto_ashift=12 to force 4K sectors" msg_freebsd_installer="FreeBSD Installer" msg_geli_password="Enter a strong passphrase, used to protect your encryption keys. You will be required to enter this passphrase each time the system is booted" msg_geli_setup="Initializing encryption on selected disks,\n this will take several seconds per disk" msg_install="Install" msg_install_desc="Proceed with Installation" msg_install_help="Create ZFS boot pool with displayed options" msg_invalid_boot_pool_size="Invalid boot pool size \`%s'" msg_invalid_disk_argument="Invalid disk argument \`%s'" msg_invalid_index_argument="Invalid index argument \`%s'" msg_invalid_swap_size="Invalid swap size \`%s'" msg_invalid_virtual_device_type="Invalid Virtual Device type \`%s'" msg_last_chance_are_you_sure="Last Chance! Are you sure you want to destroy\nthe current contents of the following disks:\n\n %s" msg_last_chance_are_you_sure_color='\\ZrLast Chance!\\ZR Are you \\Z1sure\\Zn you want to \\Zr\\Z1destroy\\Zn\nthe current contents of the following disks:\n\n %s' msg_mirror_desc="Mirror - n-Way Mirroring" msg_mirror_help="[2+ Disks] Mirroring provides the best performance, but the least storage" msg_missing_disk_arguments="missing disk arguments" msg_missing_one_or_more_scripted_disks="Missing one or more scripted disks!" msg_no="NO" msg_no_disks_present_to_configure="No disk(s) present to configure" msg_no_disks_selected="No disks selected." msg_not_enough_disks_selected="Not enough disks selected. (%u < %u minimum)" msg_null_disk_argument="NULL disk argument" msg_null_index_argument="NULL index argument" msg_null_poolname="NULL poolname" msg_ok="OK" msg_partition_scheme="Partition Scheme" msg_partition_scheme_help="Toggle between GPT and MBR partitioning schemes" msg_please_enter_a_name_for_your_zpool="Please enter a name for your zpool:" msg_please_enter_amount_of_swap_space="Please enter amount of swap space (SI-Unit suffixes\nrecommended; e.g., \`2g' for 2 Gigabytes):" msg_please_select_one_or_more_disks="Please select one or more disks to create a zpool:" msg_pool_name="Pool Name" msg_pool_name_cannot_be_empty="Pool name cannot be empty." msg_pool_name_help="Customize the name of the zpool to be created (Required)" msg_pool_type_disks="Pool Type/Disks:" msg_pool_type_disks_help="Choose type of ZFS Virtual Device and disks to use (Required)" msg_processing_selection="Processing selection..." msg_raidz1_desc="RAID-Z1 - Single Redundant RAID" msg_raidz1_help="[3+ Disks] Withstand failure of 1 disk. Recommended for: 3, 5 or 9 disks" msg_raidz2_desc="RAID-Z2 - Double Redundant RAID" msg_raidz2_help="[4+ Disks] Withstand failure of 2 disks. Recommended for: 4, 6 or 10 disks" msg_raidz3_desc="RAID-Z3 - Triple Redundant RAID" msg_raidz3_help="[5+ Disks] Withstand failure of 3 disks. Recommended for: 5, 7 or 11 disks" msg_rescan_devices="Rescan Devices" msg_rescan_devices_help="Scan for device changes" msg_select="Select" msg_select_a_disk_device="Select a disk device" msg_select_virtual_device_type="Select Virtual Device type:" msg_stripe_desc="Stripe - No Redundancy" msg_stripe_help="[1+ Disks] Striping provides maximum storage but no redundancy" msg_swap_encrypt="Encrypt Swap?" msg_swap_encrypt_help="Encrypt swap partitions with temporary keys, discarded on reboot" msg_swap_mirror="Mirror Swap?" msg_swap_mirror_help="Mirror swap partitions for redundancy, breaks crash dumps" msg_swap_size="Swap Size" msg_swap_size_help="Customize how much swap space is allocated to each selected disk" msg_these_disks_are_too_small="These disks are too small given the amount of requested\nswap (%s) and/or geli(8) (%s) partitions, which would\ntake 50%% or more of each of the following selected disk\ndevices (not recommended):\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of devices." msg_uefi_not_supported="The FreeBSD UEFI loader does not currently support booting root-on-ZFS. Your system will need to boot in legacy (CSM) mode.\nDo you want to continue?" msg_unable_to_get_disk_capacity="Unable to get disk capacity of \`%s'" msg_unsupported_partition_scheme="%s is an unsupported partition scheme" msg_user_cancelled="User Cancelled." msg_yes="YES" msg_zfs_configuration="ZFS Configuration" ############################################################ FUNCTIONS # dialog_menu_main # # Display the dialog(1)-based application main menu. # dialog_menu_main() { local title="$DIALOG_TITLE" local btitle="$DIALOG_BACKTITLE" local prompt="$msg_configure_options" local force4k="$msg_no" local usegeli="$msg_no" local swapgeli="$msg_no" local swapmirror="$msg_no" [ "$ZFSBOOT_FORCE_4K_SECTORS" ] && force4k="$msg_yes" [ "$ZFSBOOT_GELI_ENCRYPTION" ] && usegeli="$msg_yes" [ "$ZFSBOOT_SWAP_ENCRYPTION" ] && swapgeli="$msg_yes" [ "$ZFSBOOT_SWAP_MIRROR" ] && swapmirror="$msg_yes" local disks n disks_grammar f_count n $ZFSBOOT_DISKS { [ $n -eq 1 ] && disks_grammar=$msg_disk_singular; } || disks_grammar=$msg_disk_plural # grammar local menu_list=" '>>> $msg_install' '$msg_install_desc' '$msg_install_help' 'T $msg_pool_type_disks' '$ZFSBOOT_VDEV_TYPE: $n $disks_grammar' '$msg_pool_type_disks_help' '- $msg_rescan_devices' '*' '$msg_rescan_devices_help' '- $msg_disk_info' '*' '$msg_disk_info_help' 'N $msg_pool_name' '$ZFSBOOT_POOL_NAME' '$msg_pool_name_help' '4 $msg_force_4k_sectors' '$force4k' '$msg_force_4k_sectors_help' 'E $msg_encrypt_disks' '$usegeli' '$msg_encrypt_disks_help' 'P $msg_partition_scheme' '$ZFSBOOT_PARTITION_SCHEME' '$msg_partition_scheme_help' 'S $msg_swap_size' '$ZFSBOOT_SWAP_SIZE' '$msg_swap_size_help' 'M $msg_swap_mirror' '$swapmirror' '$msg_swap_mirror_help' 'W $msg_swap_encrypt' '$swapgeli' '$msg_swap_encrypt_help' " # END-QUOTE local defaultitem= # Calculated below local hline="$hline_alnum_arrows_punc_tab_enter" local height width rows eval f_dialog_menu_with_help_size height width rows \ \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" $menu_list # Obtain default-item from previously stored selection f_dialog_default_fetch defaultitem local menu_choice menu_choice=$( eval $DIALOG \ --title \"\$title\" \ --backtitle \"\$btitle\" \ --hline \"\$hline\" \ --item-help \ --ok-label \"\$msg_select\" \ --cancel-label \"\$msg_cancel\" \ --default-item \"\$defaultitem\" \ --menu \"\$prompt\" \ $height $width $rows \ $menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) local retval=$? f_dialog_data_sanitize menu_choice f_dialog_menutag_store "$menu_choice" # Only update default-item on success [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice" return $retval } # dialog_last_chance $disks ... # # Display a list of the disks that the user is about to destroy. The default # action is to return error status unless the user explicitly (non-default) # selects "Yes" from the noyes dialog. # dialog_last_chance() { local title="$DIALOG_TITLE" local btitle="$DIALOG_BACKTITLE" local prompt # Calculated below local hline="$hline_arrows_tab_enter" local height=8 width=50 prefix=" " local plen=${#prefix} list= line= local max_width=$(( $width - 3 - $plen )) local yes no defaultno extra_args format if [ "$USE_XDIALOG" ]; then yes=ok no=cancel defaultno=default-no extra_args="--wrap --left" format="$msg_last_chance_are_you_sure" else yes=yes no=no defaultno=defaultno extra_args="--colors --cr-wrap" format="$msg_last_chance_are_you_sure_color" fi local disk line_width for disk in $*; do if [ "$line" ]; then line_width=${#line} else line_width=$plen fi line_width=$(( $line_width + 1 + ${#disk} )) # Add newline before disk if it would exceed max_width if [ $line_width -gt $max_width ]; then list="$list$line\n" line="$prefix" height=$(( $height + 1 )) fi # Add the disk to the list line="$line $disk" done # Append the left-overs if [ "${line#$prefix}" ]; then list="$list$line" height=$(( $height + 1 )) fi # Add height for Xdialog(1) [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 )) prompt=$( printf "$format" "$list" ) f_dprintf "%s: Last Chance!" "$0" $DIALOG \ --title "$title" \ --backtitle "$btitle" \ --hline "$hline" \ --$defaultno \ --$yes-label "$msg_yes" \ --$no-label "$msg_no" \ $extra_args \ --yesno "$prompt" $height $width } # dialog_menu_layout # # Configure Virtual Device type and disks to use for the ZFS boot pool. User # must select enough disks to satisfy the chosen vdev type. # dialog_menu_layout() { local funcname=dialog_menu_layout local title="$DIALOG_TITLE" local btitle="$DIALOG_BACKTITLE" local vdev_prompt="$msg_select_virtual_device_type" local disk_prompt="$msg_please_select_one_or_more_disks" local vdev_menu_list=" 'stripe' '$msg_stripe_desc' '$msg_stripe_help' 'mirror' '$msg_mirror_desc' '$msg_mirror_help' 'raidz1' '$msg_raidz1_desc' '$msg_raidz1_help' 'raidz2' '$msg_raidz2_desc' '$msg_raidz2_help' 'raidz3' '$msg_raidz3_desc' '$msg_raidz3_help' " # END-QUOTE local disk_check_list= # Calculated below local vdev_hline="$hline_arrows_tab_enter" local disk_hline="$hline_arrows_space_tab_enter" # Warn the user if vdev type is not valid case "$ZFSBOOT_VDEV_TYPE" in stripe|mirror|raidz1|raidz2|raidz3) : known good ;; *) f_dprintf "%s: Invalid virtual device type \`%s'" \ $funcname "$ZFSBOOT_VDEV_TYPE" f_show_err "$msg_invalid_virtual_device_type" \ "$ZFSBOOT_VDEV_TYPE" f_interactive || return $FAILURE esac # Calculate size of vdev menu once only local vheight vwidth vrows eval f_dialog_menu_with_help_size vheight vwidth vrows \ \"\$title\" \"\$btitle\" \"\$vdev_prompt\" \"\$vdev_hline\" \ $vdev_menu_list # Get a list of probed disk devices local disks= debug= f_device_find "" $DEVICE_TYPE_DISK disks # Prune out mounted md(4) devices that may be part of the boot process local disk name new_list= for disk in $disks; do debug= $disk get name name case "$name" in md[0-9]*) f_mounted -b "/dev/$name" && continue ;; esac new_list="$new_list $disk" done disks="${new_list# }" # Debugging if [ "$debug" ]; then local disk_names= for disk in $disks; do debug= $disk get name name disk_names="$disk_names $name" done f_dprintf "$funcname: disks=[%s]" "${disk_names# }" fi if [ ! "$disks" ]; then f_dprintf "No disk(s) present to configure" f_show_err "$msg_no_disks_present_to_configure" return $FAILURE fi # Lets sort the disks array to be more user friendly f_device_sort_by name disks disks # # Operate in a loop so we can (if interactive) repeat if not enough # disks are selected to satisfy the chosen vdev type or user wants to # back-up to the previous menu. # local vardisk ndisks onoff selections vdev_choice breakout device local valid_disks all_valid want_disks desc height width rows while :; do # # Confirm the vdev type that was selected # if f_interactive && [ "$ZFSBOOT_CONFIRM_LAYOUT" ]; then vdev_choice=$( eval $DIALOG \ --title \"\$title\" \ --backtitle \"\$btitle\" \ --hline \"\$vdev_hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_cancel\" \ --item-help \ --default-item \"\$ZFSBOOT_VDEV_TYPE\" \ --menu \"\$vdev_prompt\" \ $vheight $vwidth $vrows \ $vdev_menu_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) || return $? # Exit if user pressed ESC or chose Cancel/No f_dialog_data_sanitize vdev_choice ZFSBOOT_VDEV_TYPE="$vdev_choice" f_dprintf "$funcname: ZFSBOOT_VDEV_TYPE=[%s]" \ "$ZFSBOOT_VDEV_TYPE" fi # Determine the number of disks needed for this vdev type want_disks=0 case "$ZFSBOOT_VDEV_TYPE" in stripe) want_disks=1 ;; mirror) want_disks=2 ;; raidz1) want_disks=3 ;; raidz2) want_disks=4 ;; raidz3) want_disks=5 ;; esac # # Warn the user if any scripted disks are invalid # valid_disks= all_valid=${ZFSBOOT_DISKS:+1} # optimism for disk in $ZFSBOOT_DISKS; do if debug= f_device_find -1 \ $disk $DEVICE_TYPE_DISK device then valid_disks="$valid_disks $disk" continue fi f_dprintf "$funcname: \`%s' is not a real disk" "$disk" all_valid= done if [ ! "$all_valid" ]; then if [ "$ZFSBOOT_DISKS" ]; then f_show_err \ "$msg_missing_one_or_more_scripted_disks" else f_dprintf "No disks selected." f_interactive || f_show_err "$msg_no_disks_selected" fi f_interactive || return $FAILURE fi ZFSBOOT_DISKS="${valid_disks# }" # # Short-circuit if we're running non-interactively # if ! f_interactive || [ ! "$ZFSBOOT_CONFIRM_LAYOUT" ]; then f_count ndisks $ZFSBOOT_DISKS [ $ndisks -ge $want_disks ] && break # to success # Not enough disks selected f_dprintf "$funcname: %s: %s (%u < %u minimum)" \ "$ZFSBOOT_VDEV_TYPE" \ "Not enough disks selected." \ $ndisks $want_disks f_interactive || return $FAILURE msg_yes="$msg_change_selection" msg_no="$msg_cancel" \ f_yesno "%s: $msg_not_enough_disks_selected" \ "$ZFSBOOT_VDEV_TYPE" $ndisks $want_disks || return $FAILURE fi # # Confirm the disks that were selected # Loop until the user cancels or selects enough disks # breakout= while :; do # Loop over list of available disks, resetting state for disk in $disks; do f_isset _${disk}_status && _${disk}_status= done # Loop over list of selected disks and create temporary # locals to map statuses onto up-to-date list of disks for disk in $ZFSBOOT_DISKS; do debug= f_device_find -1 \ $disk $DEVICE_TYPE_DISK disk f_isset _${disk}_status || local _${disk}_status _${disk}_status=on done # Create the checklist menu of discovered disk devices disk_check_list= for disk in $disks; do desc= $disk get name name $disk get desc desc f_shell_escape "$desc" desc f_getvar _${disk}_status:-off onoff disk_check_list="$disk_check_list $name '$desc' $onoff" done eval f_dialog_checklist_size height width rows \ \"\$title\" \"\$btitle\" \"\$prompt\" \ \"\$hline\" $disk_check_list selections=$( eval $DIALOG \ --title \"\$DIALOG_TITLE\" \ --backtitle \"\$DIALOG_BACKTITLE\" \ --separate-output \ --hline \"\$hline\" \ --ok-label \"\$msg_ok\" \ --cancel-label \"\$msg_back\" \ --checklist \"\$prompt\" \ $height $width $rows \ $disk_check_list \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) || break # Loop if user pressed ESC or chose Cancel/No f_dialog_data_sanitize selections ZFSBOOT_DISKS="$selections" f_dprintf "$funcname: ZFSBOOT_DISKS=[%s]" \ "$ZFSBOOT_DISKS" f_count ndisks $ZFSBOOT_DISKS [ $ndisks -ge $want_disks ] && breakout=break && break # Not enough disks selected f_dprintf "$funcname: %s: %s (%u < %u minimum)" \ "$ZFSBOOT_VDEV_TYPE" \ "Not enough disks selected." \ $ndisks $want_disks msg_yes="$msg_change_selection" msg_no="$msg_cancel" \ f_yesno "%s: $msg_not_enough_disks_selected" \ "$ZFSBOOT_VDEV_TYPE" $ndisks $want_disks || break done [ "$breakout" = "break" ] && break [ "$ZFSBOOT_CONFIRM_LAYOUT" ] || return $FAILURE done return $DIALOG_OK } # dialog_uefi_prompt # # Confirm that the user wants to continue with the installation on a BIOS # system when they have booted with UEFI # dialog_uefi_prompt() { local title="$DIALOG_TITLE" local btitle="$DIALOG_BACKTITLE" local prompt # Calculated below local hline="$hline_arrows_tab_enter" local height=8 width=50 prefix=" " local plen=${#prefix} list= line= local max_width=$(( $width - 3 - $plen )) local yes no defaultno extra_args format if [ "$USE_XDIALOG" ]; then yes=ok no=cancel defaultno=default-no extra_args="--wrap --left" format="$msg_uefi_not_supported" else yes=yes no=no defaultno=defaultno extra_args="--cr-wrap" format="$msg_uefi_not_supported" fi # Add height for Xdialog(1) [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 )) prompt=$( printf "$format" ) f_dprintf "%s: UEFI prompt" "$0" $DIALOG \ --title "$title" \ --backtitle "$btitle" \ --hline "$hline" \ --$yes-label "$msg_yes" \ --$no-label "$msg_no" \ $extra_args \ --yesno "$prompt" $height $width } # zfs_create_diskpart $disk $index # # For each block device to be used in the zpool, rather than just create the # zpool with the raw block devices (e.g., da0, da1, etc.) we create partitions # so we can have some real swap. This also provides wiggle room incase your # replacement drivers do not have the exact same sector counts. # # NOTE: $swapsize and $bootsize should be defined by the calling function. # NOTE: Sets $bootpart and $targetpart for the calling function. # zfs_create_diskpart() { local funcname=zfs_create_diskpart local disk="$1" index="$2" # Check arguments if [ ! "$disk" ]; then f_dprintf "$funcname: NULL disk argument" msg_error="$msg_error: $funcname" \ f_show_err "$msg_null_disk_argument" return $FAILURE fi if [ "${disk#*[$IFS]}" != "$disk" ]; then f_dprintf "$funcname: Invalid disk argument \`%s'" "$disk" msg_error="$msg_error: $funcname" \ f_show_err "$msg_invalid_disk_argument" "$disk" return $FAILURE fi if [ ! "$index" ]; then f_dprintf "$funcname: NULL index argument" msg_error="$msg_error: $funcname" \ f_show_err "$msg_null_index_argument" return $FAILURE fi if ! f_isinteger "$index"; then f_dprintf "$funcname: Invalid index argument \`%s'" "$index" msg_error="$msg_error: $funcname" \ f_show_err "$msg_invalid_index_argument" "$index" return $FAILURE fi f_dprintf "$funcname: disk=[%s] index=[%s]" "$disk" "$index" # Check for unknown partition scheme before proceeding further case "$ZFSBOOT_PARTITION_SCHEME" in ""|MBR|GPT) : known good ;; *) f_dprintf "$funcname: %s is an unsupported partition scheme" \ "$ZFSBOOT_PARTITION_SCHEME" msg_error="$msg_error: $funcname" f_show_err \ "$msg_unsupported_partition_scheme" \ "$ZFSBOOT_PARTITION_SCHEME" return $FAILURE esac # # Destroy whatever partition layout is currently on disk. # NOTE: `-F' required to destroy if partitions still exist. # NOTE: Failure is ok here, blank disk will have nothing to destroy. # f_dprintf "$funcname: Destroying all data/layouts on \`%s'..." "$disk" f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk f_eval_catch -d $funcname graid "$GRAID_DELETE" $disk f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" /dev/$disk # Make doubly-sure backup GPT is destroyed f_eval_catch -d $funcname gpart "$GPART_CREATE" gpt $disk f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk # # Enable boot pool if encryption is desired # [ "$ZFSBOOT_GELI_ENCRYPTION" ] && ZFSBOOT_BOOT_POOL=1 # # Lay down the desired type of partition scheme # local setsize mbrindex case "$ZFSBOOT_PARTITION_SCHEME" in ""|GPT) f_dprintf "$funcname: Creating GPT layout..." # # 1. Create GPT layout using labels # f_eval_catch $funcname gpart "$GPART_CREATE" gpt $disk || return $FAILURE # # 2. Add small freebsd-boot partition labeled `boot#' # f_eval_catch $funcname gpart "$GPART_ADD_LABEL_WITH_SIZE" \ gptboot$index freebsd-boot 512k $disk || return $FAILURE f_eval_catch $funcname gpart "$GPART_BOOTCODE_PART" \ /boot/pmbr /boot/gptzfsboot 1 $disk || return $FAILURE # NB: zpool will use the `zfs#' GPT labels bootpart=p2 swappart=p2 targetpart=p2 [ ${swapsize:-0} -gt 0 ] && targetpart=p3 # # Prepare boot pool if enabled (e.g., for geli(8)) # if [ "$ZFSBOOT_BOOT_POOL" ]; then bootpart=p2 swappart=p3 targetpart=p3 [ ${swapsize:-0} -gt 0 ] && targetpart=p4 f_eval_catch $funcname gpart \ "$GPART_ADD_LABEL_WITH_SIZE" boot$index \ freebsd-zfs ${bootsize}b $disk || return $FAILURE # Pedantically nuke any old labels f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/$disk$bootpart if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then # Pedantically detach targetpart for later f_eval_catch -d $funcname geli \ "$GELI_DETACH_F" \ /dev/$disk$targetpart fi fi # # 3. Add freebsd-swap partition labeled `swap#' # if [ ${swapsize:-0} -gt 0 ]; then f_eval_catch $funcname gpart \ "$GPART_ADD_LABEL_WITH_SIZE" swap$index \ freebsd-swap ${swapsize}b $disk || return $FAILURE # Pedantically nuke any old labels on the swap f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/$disk$swappart fi # # 4. Add freebsd-zfs partition labeled `zfs#' for zroot # f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ zfs$index freebsd-zfs $disk || return $FAILURE f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/$disk$targetpart ;; MBR) f_dprintf "$funcname: Creating MBR layout..." # # 1. Create MBR layout (no labels) # f_eval_catch $funcname gpart "$GPART_CREATE" mbr $disk || return $FAILURE f_eval_catch $funcname gpart "$GPART_BOOTCODE" /boot/mbr \ $disk || return $FAILURE # # 2. Add freebsd slice with all available space # f_eval_catch $funcname gpart "$GPART_ADD" freebsd $disk || return $FAILURE f_eval_catch $funcname gpart "$GPART_SET_ACTIVE" 1 $disk || return $FAILURE # Pedantically nuke any old labels f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/${disk}s1 # Pedantically nuke any old scheme f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" ${disk}s1 # # 3. Write BSD scheme to the freebsd slice # f_eval_catch $funcname gpart "$GPART_CREATE" BSD ${disk}s1 || return $FAILURE # NB: zpool will use s1a (no labels) bootpart=s1a swappart=s1b targetpart=s1d mbrindex=4 # # Always prepare a boot pool on MBR # ZFSBOOT_BOOT_POOL=1 f_eval_catch $funcname gpart \ "$GPART_ADD_INDEX_WITH_SIZE" \ 1 freebsd-zfs ${bootsize}b ${disk}s1 || return $FAILURE # Pedantically nuke any old labels f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/$disk$bootpart if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then # Pedantically detach targetpart for later f_eval_catch -d $funcname geli \ "$GELI_DETACH_F" \ /dev/$disk$targetpart fi # # 4. Add freebsd-swap partition # if [ ${swapsize:-0} -gt 0 ]; then f_eval_catch $funcname gpart \ "$GPART_ADD_INDEX_WITH_SIZE" 2 \ freebsd-swap ${swapsize}b ${disk}s1 || return $FAILURE # Pedantically nuke any old labels on the swap f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/${disk}s1b fi # # 5. Add freebsd-zfs partition for zroot # f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \ $mbrindex freebsd-zfs ${disk}s1 || return $FAILURE f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \ /dev/$disk$targetpart # Pedantic f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ /boot/zfsboot /dev/${disk}s1 count=1 || return $FAILURE ;; esac # $ZFSBOOT_PARTITION_SCHEME # Update fstab(5) if [ "$isswapmirror" ]; then # This is not the first disk in the mirror, do nothing elif [ "$ZFSBOOT_SWAP_ENCRYPTION" -a "$ZFSBOOT_SWAP_MIRROR" ]; then f_eval_catch $funcname printf "$PRINTF_FSTAB" \ /dev/mirror/swap.eli none swap sw 0 0 \ $BSDINSTALL_TMPETC/fstab || return $FAILURE isswapmirror=1 elif [ "$ZFSBOOT_SWAP_MIRROR" ]; then f_eval_catch $funcname printf "$PRINTF_FSTAB" \ /dev/mirror/swap none swap sw 0 0 \ $BSDINSTALL_TMPETC/fstab || return $FAILURE isswapmirror=1 elif [ "$ZFSBOOT_SWAP_ENCRYPTION" ]; then f_eval_catch $funcname printf "$PRINTF_FSTAB" \ /dev/$disk${swappart}.eli none swap sw 0 0 \ $BSDINSTALL_TMPETC/fstab || return $FAILURE else f_eval_catch $funcname printf "$PRINTF_FSTAB" \ /dev/$disk$swappart none swap sw 0 0 \ $BSDINSTALL_TMPETC/fstab || return $FAILURE fi return $SUCCESS } # zfs_create_boot $poolname $vdev_type $disks ... # # Creates boot pool and dataset layout. Returns error if something goes wrong. # Errors are printed to stderr for collection and display. # zfs_create_boot() { local funcname=zfs_create_boot local zroot_name="$1" local zroot_vdevtype="$2" local zroot_vdevs= # Calculated below local swap_devs= # Calculated below local boot_vdevs= # Used for geli(8) and/or MBR layouts shift 2 # poolname vdev_type local disks="$*" disk local isswapmirror local bootpart targetpart swappart # Set by zfs_create_diskpart() below local create_options # # Pedantic checks; should never be seen # if [ ! "$zroot_name" ]; then f_dprintf "$funcname: NULL poolname" msg_error="$msg_error: $funcname" \ f_show_err "$msg_null_poolname" return $FAILURE fi if [ $# -lt 1 ]; then f_dprintf "$funcname: missing disk arguments" msg_error="$msg_error: $funcname" \ f_show_err "$msg_missing_disk_arguments" return $FAILURE fi f_dprintf "$funcname: poolname=[%s] vdev_type=[%s]" \ "$zroot_name" "$zroot_vdevtype" # # Initialize fstab(5) # f_dprintf "$funcname: Initializing temporary fstab(5) file..." f_eval_catch $funcname sh "$SHELL_TRUNCATE" $BSDINSTALL_TMPETC/fstab || return $FAILURE f_eval_catch $funcname printf "$PRINTF_FSTAB" \ "# Device" Mountpoint FStype Options Dump "Pass#" \ $BSDINSTALL_TMPETC/fstab || return $FAILURE # # Expand SI units in desired sizes # f_dprintf "$funcname: Expanding supplied size values..." local swapsize bootsize if ! f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize; then f_dprintf "$funcname: Invalid swap size \`%s'" \ "$ZFSBOOT_SWAP_SIZE" f_show_err "$msg_invalid_swap_size" "$ZFSBOOT_SWAP_SIZE" return $FAILURE fi if ! f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize; then f_dprintf "$funcname: Invalid boot pool size \`%s'" \ "$ZFSBOOT_BOOT_POOL_SIZE" f_show_err "$msg_invalid_boot_pool_size" \ "$ZFSBOOT_BOOT_POOL_SIZE" return $FAILURE fi f_dprintf "$funcname: ZFSBOOT_SWAP_SIZE=[%s] swapsize=[%s]" \ "$ZFSBOOT_SWAP_SIZE" "$swapsize" f_dprintf "$funcname: ZFSBOOT_BOOT_POOL_SIZE=[%s] bootsize=[%s]" \ "$ZFSBOOT_BOOT_POOL_SIZE" "$bootsize" # # Destroy the pool in-case this is our second time 'round (case of # failure and installer presented ``Retry'' option to come back). # # NB: If we don't destroy the pool, later gpart(8) destroy commands # that try to clear existing partitions (see zfs_create_diskpart()) # will fail with a `Device Busy' error, leading to `GEOM exists'. # f_eval_catch -d $funcname zpool "$ZPOOL_DESTROY" "$zroot_name" # # Prepare the disks and build pool device list(s) # f_dprintf "$funcname: Preparing disk partitions for ZFS pool..." # Force 4K sectors using vfs.zfs.min_auto_ashift=12 if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then f_dprintf "$funcname: With 4K sectors..." f_eval_catch $funcname sysctl "$SYSCTL_ZFS_MIN_ASHIFT_12" \ || return $FAILURE fi local n=0 for disk in $disks; do zfs_create_diskpart $disk $n || return $FAILURE # Now $bootpart, $targetpart, and $swappart are set (suffix # for $disk) if [ "$ZFSBOOT_BOOT_POOL" ]; then boot_vdevs="$boot_vdevs $disk$bootpart" fi zroot_vdevs="$zroot_vdevs $disk$targetpart" if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then zroot_vdevs="$zroot_vdevs.eli" fi n=$(( $n + 1 )) done # disks # # If we need/want a boot pool, create it # if [ "$ZFSBOOT_BOOT_POOL" ]; then local bootpool_vdevtype= # Calculated below local bootpool_options= # Calculated below local bootpool_name="$ZFSBOOT_BOOT_POOL_NAME" local bootpool="$BSDINSTALL_CHROOT/$bootpool_name" local zroot_key="${ZFSBOOT_GELI_KEY_FILE#/}" f_dprintf "$funcname: Setting up boot pool..." [ "$ZFSBOOT_GELI_ENCRYPTION" ] && f_dprintf "$funcname: For encrypted root disk..." # Create parent directory for boot pool f_eval_catch -d $funcname umount "$UMOUNT" /mnt f_eval_catch $funcname mount "$MOUNT_TYPE" tmpfs none \ $BSDINSTALL_CHROOT || return $FAILURE # Create mirror across the boot partition on all disks local nvdevs f_count nvdevs $boot_vdevs [ $nvdevs -gt 1 ] && bootpool_vdevtype=mirror create_options="$ZFSBOOT_BOOT_POOL_CREATE_OPTIONS" bootpool_options="-o altroot=$BSDINSTALL_CHROOT" bootpool_options="$bootpool_options $create_options" bootpool_options="$bootpool_options -m \"/$bootpool_name\" -f" f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ "$bootpool_options" "$bootpool_name" \ "$bootpool_vdevtype" "$boot_vdevs" || return $FAILURE f_eval_catch $funcname mkdir "$MKDIR_P" "$bootpool/boot" || return $FAILURE if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then # Generate an encryption key using random(4) f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ /dev/random "$bootpool/$zroot_key" \ "bs=4096 count=1" || return $FAILURE f_eval_catch $funcname chmod "$CHMOD_MODE" \ go-wrx "$bootpool/$zroot_key" || return $FAILURE else # Clean up f_eval_catch $funcname zfs "$ZFS_UNMOUNT" \ "$bootpool_name" || return $FAILURE f_eval_catch -d $funcname umount "$UMOUNT" /mnt # tmpfs fi fi # # Create the geli(8) GEOMS # if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then # Prompt user for password (twice) if ! msg_enter_new_password="$msg_geli_password" \ f_dialog_input_password then f_dprintf "$funcname: User cancelled" f_show_err "$msg_user_cancelled" return $FAILURE fi # Initialize geli(8) on each of the target partitions for disk in $disks; do f_dialog_info "$msg_geli_setup" \ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD if ! echo "$pw_password" | f_eval_catch \ $funcname geli "$GELI_PASSWORD_INIT" \ "$bootpool/boot/$disk$targetpart.eli" \ AES-XTS "$bootpool/$zroot_key" \ $disk$targetpart then f_interactive || f_die unset pw_password # Sensitive info return $FAILURE fi if ! echo "$pw_password" | f_eval_catch \ $funcname geli "$GELI_ATTACH" \ "$bootpool/$zroot_key" $disk$targetpart then f_interactive || f_die unset pw_password # Sensitive info return $FAILURE fi done unset pw_password # Sensitive info # Clean up f_eval_catch $funcname zfs "$ZFS_UNMOUNT" "$bootpool_name" || return $FAILURE f_eval_catch -d $funcname umount "$UMOUNT" /mnt # tmpfs fi # # Create the gmirror(8) GEOMS for swap # if [ "$ZFSBOOT_SWAP_MIRROR" ]; then for disk in $disks; do swap_devs="$swap_devs $disk$swappart" done f_eval_catch $funcname gmirror "$SWAP_GMIRROR_LABEL" \ "$swap_devs" || return $FAILURE fi # # Create the ZFS root pool with desired type and disk devices # f_dprintf "$funcname: Creating root pool..." create_options="$ZFSBOOT_POOL_CREATE_OPTIONS" f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ "-o altroot=$BSDINSTALL_CHROOT $create_options -m none -f" \ "$zroot_name" "$zroot_vdevtype" "$zroot_vdevs" || return $FAILURE # # Create ZFS dataset layout within the new root pool # f_dprintf "$funcname: Creating ZFS datasets..." echo "$ZFSBOOT_DATASETS" | while read dataset options; do # Skip blank lines and comments case "$dataset" in "#"*|"") continue; esac # Remove potential inline comments in options options="${options%%#*}" # Replace tabs with spaces f_replaceall "$options" " " " " options # Reduce contiguous runs of space to one single space oldoptions= while [ "$oldoptions" != "$options" ]; do oldoptions="$options" f_replaceall "$options" " " " " options done # Replace both commas and spaces with ` -o ' f_replaceall "$options" "[ ,]" " -o " options # Create the dataset with desired options f_eval_catch $funcname zfs "$ZFS_CREATE_WITH_OPTIONS" \ "${options:+-o $options}" "$zroot_name$dataset" || return $FAILURE done # Touch up permissions on the tmp directories f_dprintf "$funcname: Modifying directory permissions..." local dir for dir in /tmp /var/tmp; do f_eval_catch $funcname chmod "$CHMOD_MODE" 1777 \ $BSDINSTALL_CHROOTDIR$dir || return $FAILURE done # Create symlink(s) if [ "$ZFSBOOT_BOOT_POOL" ]; then f_dprintf "$funcname: Creating /boot symlink for boot pool..." f_eval_catch $funcname ln "$LN_SF" "$bootpool_name/boot" \ $BSDINSTALL_CHROOT/boot || return $FAILURE fi # Set bootfs property local zroot_bootfs="$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME" f_dprintf "$funcname: Setting bootfs property..." f_eval_catch $funcname zpool "$ZPOOL_SET" \ "bootfs=\"$zroot_name/$zroot_bootfs\"" "$zroot_name" || return $FAILURE # Export the pool(s) f_dprintf "$funcname: Temporarily exporting ZFS pool(s)..." f_eval_catch $funcname zpool "$ZPOOL_EXPORT" "$zroot_name" || return $FAILURE if [ "$ZFSBOOT_BOOT_POOL" ]; then f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \ "$bootpool_name" || return $FAILURE fi # MBR boot loader touch-up if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then f_dprintf "$funcname: Updating MBR boot loader on disks..." # Stick the ZFS boot loader in the "convienient hole" after # the ZFS internal metadata for disk in $disks; do f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ /boot/zfsboot /dev/$disk$bootpart \ "skip=1 seek=1024" || return $FAILURE done fi # Re-import the ZFS pool(s) f_dprintf "$funcname: Re-importing ZFS pool(s)..." f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ "-o altroot=\"$BSDINSTALL_CHROOT\"" "$zroot_name" || return $FAILURE if [ "$ZFSBOOT_BOOT_POOL" ]; then f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ "-o altroot=\"$BSDINSTALL_CHROOT\"" \ "$bootpool_name" || return $FAILURE fi # While this is apparently not needed, it seems to help MBR f_dprintf "$funcname: Configuring zpool.cache for zroot..." f_eval_catch $funcname mkdir "$MKDIR_P" $BSDINSTALL_CHROOT/boot/zfs || return $FAILURE f_eval_catch $funcname zpool "$ZPOOL_SET" \ "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \ "$zroot_name" || return $FAILURE # Last, but not least... required lines for rc.conf(5)/loader.conf(5) # NOTE: We later concatenate these into their destination f_dprintf "%s: Configuring rc.conf(5)/loader.conf(5) additions..." \ "$funcname" f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_enable=\"YES\"' \ $BSDINSTALL_TMPETC/rc.conf.zfs || return $FAILURE f_eval_catch $funcname echo "$ECHO_APPEND" \ 'kern.geom.label.disk_ident.enable=\"0\"' \ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE f_eval_catch $funcname echo "$ECHO_APPEND" \ 'kern.geom.label.gptid.enable=\"0\"' \ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE if [ "$ZFSBOOT_SWAP_MIRROR" ]; then f_eval_catch $funcname echo "$ECHO_APPEND" \ 'geom_mirror_load=\"YES\"' \ $BSDINSTALL_TMPBOOT/loader.conf.gmirror || return $FAILURE fi # We're all done unless we should go on for boot pool [ "$ZFSBOOT_BOOT_POOL" ] || return $SUCCESS # Set cachefile for boot pool so it auto-imports at system start f_dprintf "$funcname: Configuring zpool.cache for boot pool..." f_eval_catch $funcname zpool "$ZPOOL_SET" \ "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \ "$bootpool_name" || return $FAILURE # Some additional geli(8) requirements for loader.conf(5) for option in \ 'zpool_cache_load=\"YES\"' \ 'zpool_cache_type=\"/boot/zfs/zpool.cache\"' \ 'zpool_cache_name=\"/boot/zfs/zpool.cache\"' \ ; do f_eval_catch $funcname echo "$ECHO_APPEND" "$option" \ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE done f_eval_catch $funcname printf "$PRINTF_CONF" vfs.root.mountfrom \ "\"zfs:$zroot_name/$zroot_bootfs\"" \ $BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE # We're all done unless we should go on to do encryption [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS # # Configure geli(8)-based encryption # f_dprintf "$funcname: Configuring disk encryption..." f_eval_catch $funcname echo "$ECHO_APPEND" 'aesni_load=\"YES\"' \ $BSDINSTALL_TMPBOOT/loader.conf.aesni || return $FAILURE f_eval_catch $funcname echo "$ECHO_APPEND" 'geom_eli_load=\"YES\"' \ $BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE + f_eval_catch $funcname echo "$ECHO_APPEND" \ + 'geom_eli_passphrase_prompt=\"YES\"' \ + $BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE for disk in $disks; do f_eval_catch $funcname printf "$PRINTF_CONF" \ geli_%s_keyfile0_load "$disk$targetpart YES" \ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || return $FAILURE f_eval_catch $funcname printf "$PRINTF_CONF" \ geli_%s_keyfile0_type \ "$disk$targetpart $disk$targetpart:geli_keyfile0" \ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || return $FAILURE f_eval_catch $funcname printf "$PRINTF_CONF" \ geli_%s_keyfile0_name \ "$disk$targetpart \"$ZFSBOOT_GELI_KEY_FILE\"" \ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || return $FAILURE done return $SUCCESS } # dialog_menu_diskinfo # # Prompt the user to select a disk and then provide detailed info on it. # dialog_menu_diskinfo() { local device disk # # Break from loop when user cancels disk selection # while :; do device=$( msg_cancel="$msg_back" f_device_menu \ "$DIALOG_TITLE" "$msg_select_a_disk_device" "" \ $DEVICE_TYPE_DISK 2>&1 ) || break $device get name disk # Show gpart(8) `show' and camcontrol(8) `inquiry' data f_show_msg "$msg_detailed_disk_info" \ "$disk" "$( gpart show $disk 2> /dev/null )" \ "$disk" "$( camcontrol inquiry $disk 2> /dev/null )" \ "$disk" "$( camcontrol identify $disk 2> /dev/null )" done return $SUCCESS } ############################################################ MAIN # # Initialize # f_dialog_title "$msg_zfs_configuration" f_dialog_backtitle "$msg_freebsd_installer" # User may have specifically requested ZFS-related operations be interactive ! f_interactive && f_zfsinteractive && unset $VAR_NONINTERACTIVE # # Debugging # f_dprintf "BSDINSTALL_CHROOT=[%s]" "$BSDINSTALL_CHROOT" f_dprintf "BSDINSTALL_TMPETC=[%s]" "$BSDINSTALL_TMPETC" f_dprintf "FSTAB_FMT=[%s]" "$FSTAB_FMT" # # If the system was booted with UEFI, warn the user that FreeBSD can't do # ZFS with UEFI yet # if f_interactive; then bootmethod=$( sysctl -n machdep.bootmethod ) f_dprintf "machdep.bootmethod=[%s]" "$bootmethod" if [ "$bootmethod" != "BIOS" ]; then dialog_uefi_prompt retval=$? f_dprintf "uefi_prompt=[%s]" "$retval" [ $retval -eq $DIALOG_OK ] || f_die fi fi # # Loop over the main menu until we've accomplished what we came here to do # while :; do if ! f_interactive; then retval=$DIALOG_OK mtag=">>> $msg_install" else dialog_menu_main retval=$? f_dialog_menutag_fetch mtag fi f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" [ $retval -eq $DIALOG_OK ] || f_die case "$mtag" in ">>> $msg_install") # # First, validate the user's selections # # Make sure they gave us a name for the pool if [ ! "$ZFSBOOT_POOL_NAME" ]; then f_dprintf "Pool name cannot be empty." f_show_err "$msg_pool_name_cannot_be_empty" continue fi # Validate vdev type against number of disks selected/scripted # (also validates that ZFSBOOT_DISKS are real [probed] disks) # NB: dialog_menu_layout supports running non-interactively dialog_menu_layout || continue # Make sure each disk will be at least 50% ZFS if f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize && f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize then minsize=$swapsize teeny_disks= [ "$ZFSBOOT_BOOT_POOL" ] && minsize=$(( $minsize + $bootsize )) for disk in $ZFSBOOT_DISKS; do debug= f_device_find -1 \ $disk $DEVICE_TYPE_DISK device $device get capacity disksize || continue [ ${disksize:-0} -ge 0 ] || disksize=0 disksize=$(( $disksize - $minsize )) [ $disksize -lt $minsize ] && teeny_disks="$teeny_disks $disk" done if [ "$teeny_disks" ]; then f_dprintf "swapsize=[%s] bootsize[%s] %s" \ "$ZFSBOOT_SWAP_SIZE" \ "$ZFSBOOT_BOOT_POOL_SIZE" \ "minsize=[$minsize]" f_dprintf "These disks are too small: %s" \ "$teeny_disks" f_show_err "$msg_these_disks_are_too_small" \ "$ZFSBOOT_SWAP_SIZE" \ "$ZFSBOOT_BOOT_POOL_SIZE" \ "$teeny_disks" continue fi fi # # Last Chance! # if f_interactive; then dialog_last_chance $ZFSBOOT_DISKS || continue fi # # Let's do this # vdev_type="$ZFSBOOT_VDEV_TYPE" # Blank the vdev type for the default layout [ "$vdev_type" = "stripe" ] && vdev_type= zfs_create_boot "$ZFSBOOT_POOL_NAME" \ "$vdev_type" $ZFSBOOT_DISKS || continue break # to success ;; ?" $msg_pool_type_disks") ZFSBOOT_CONFIRM_LAYOUT=1 dialog_menu_layout # User has poked settings, disable later confirmation ZFSBOOT_CONFIRM_LAYOUT= ;; "- $msg_rescan_devices") f_device_rescan ;; "- $msg_disk_info") dialog_menu_diskinfo ;; ?" $msg_pool_name") # Prompt the user to input/change the name for the new pool f_dialog_input input \ "$msg_please_enter_a_name_for_your_zpool" \ "$ZFSBOOT_POOL_NAME" && ZFSBOOT_POOL_NAME="$input" ;; ?" $msg_force_4k_sectors") # Toggle the variable referenced both by the menu and later if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then ZFSBOOT_FORCE_4K_SECTORS= else ZFSBOOT_FORCE_4K_SECTORS=1 fi ;; ?" $msg_encrypt_disks") # Toggle the variable referenced both by the menu and later if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then ZFSBOOT_GELI_ENCRYPTION= else ZFSBOOT_FORCE_4K_SECTORS=1 ZFSBOOT_GELI_ENCRYPTION=1 fi ;; ?" $msg_partition_scheme") # Toggle between GPT and MBR if [ "$ZFSBOOT_PARTITION_SCHEME" = GPT ]; then ZFSBOOT_PARTITION_SCHEME=MBR else ZFSBOOT_PARTITION_SCHEME=GPT fi ;; ?" $msg_swap_size") # Prompt the user to input/change the swap size for each disk f_dialog_input input \ "$msg_please_enter_amount_of_swap_space" \ "$ZFSBOOT_SWAP_SIZE" && ZFSBOOT_SWAP_SIZE="${input:-0}" ;; ?" $msg_swap_mirror") # Toggle the variable referenced both by the menu and later if [ "$ZFSBOOT_SWAP_MIRROR" ]; then ZFSBOOT_SWAP_MIRROR= else ZFSBOOT_SWAP_MIRROR=1 fi ;; ?" $msg_swap_encrypt") # Toggle the variable referenced both by the menu and later if [ "$ZFSBOOT_SWAP_ENCRYPTION" ]; then ZFSBOOT_SWAP_ENCRYPTION= else ZFSBOOT_SWAP_ENCRYPTION=1 fi ;; esac done return $SUCCESS ################################################################################ # END ################################################################################