Index: usr.sbin/bsdconfig/share/device.subr =================================================================== --- usr.sbin/bsdconfig/share/device.subr (revision 256125) +++ usr.sbin/bsdconfig/share/device.subr (working copy) @@ -208,6 +208,10 @@ f_device_get_all() n=$(( $n + 1 )) # Get the desc, type, and max (with debugging disabled) # NOTE: Bypassing f_device_name_get() for efficiency + # ASIDE: This would be equivalent to the following: + # debug= f_device_name_get $dev desc + # debug= f_device_name_get $dev type + # debug= f_device_name_get $dev max debug= f_getvar _device_desc$n desc debug= f_getvar _device_type$n type debug= f_getvar _device_max$n max @@ -313,7 +317,10 @@ f_device_get_all() continue fi - f_device_register "$diskname" "" \ + # Try and find its description + f_device_desc "$diskname" $DEVICE_TYPE_DISK desc + + f_device_register "$diskname" "$desc" \ "/dev/$diskname" $DEVICE_TYPE_DISK 0 f_dprintf "Found a disk device named %s" "$diskname" @@ -379,10 +386,27 @@ f_device_name_get() case "$__prop" in type|desc|max) : good ;; *) return $FAILURE; esac + # + # Attempt to create an alternate-form of $__name that contains the + # first contiguous string of numbers replaced with `%d' for comparison + # against stored pattern names (see MAIN). + # + local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}" __dname= + if [ "$__left" != "$__name" ]; then + # Chop leading digits from right 'til we hit first non-digit + while :; do + case "$__right" in + [0-9]*) __right="${__right#[0-9]}" ;; + *) break + esac + done + __dname="${__left}%d$__right" + fi + [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type= for __dev in $DEVICE_NAMES; do __n=$(( $__n + 1 )) - [ "$__dev" = "$__name" ] || continue + [ "$__dev" = "$__name" -o "$__dev" = "$__dname" ] || continue f_getvar _device_type$__n __devtype [ "${__type:-$__devtype}" = "$__devtype" ] || continue f_getvar _device_$__prop$__n $__var_to_set @@ -463,6 +487,39 @@ f_device_desc() fi fi + # + # For disks, attempt to return camcontrol(8) descriptions. + # Otherwise fall through to below static list. + # + f_have camcontrol && + [ "${__type:-$DEVICE_TYPE_DISK}" = "$DEVICE_TYPE_DISK" ] && + __cp=$( camcontrol devlist 2> /dev/null | awk -v disk="$__name" ' + $0~"(\\(|,)"disk"(,|\\))" { + if (!match($0, "<[^>]+>")) next + print substr($0, RSTART+1, RLENGTH-2) + found = 1 + exit + } + END { exit ! found } + ' ) && setvar "$__var_to_set" "$__cp" && return $SUCCESS + + # + # Attempt to create an alternate-form of $__name that contains the + # first contiguous string of numbers replaced with `%d' for comparison + # against stored pattern names (see MAIN). + # + local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}" __dname= + if [ "$__left" != "$__name" ]; then + # Chop leading digits from right 'til we hit first non-digit + while :; do + case "$__right" in + [0-9]*) __right="${__right#[0-9]}" ;; + *) break + esac + done + __dname="${__left}%d$__right" + fi + local __dev __devtype __n=0 for __dev in $DEVICE_NAMES; do __n=$(( $__n + 1 )) @@ -472,11 +529,8 @@ f_device_desc() __devname=$( f_substr "$__name" 0 ${#__dev} ) [ "$__devname" = "$__dev" ] || continue else - __devname="${__name%%[0-9]*}" - __devunit="${__name#$__devname}" - __devunit="${__devunit%%[!0-9]*}" - __devname=$( printf "$__dev" $__devunit ) - [ "$__devname" = "$__name" ] || continue + [ "$__dev" = "$__name" -o "$__dev" = "$__dname" ] || + continue fi debug= f_getvar _device_desc$__n $__var_to_set return $? @@ -655,7 +709,25 @@ f_device_menu() return $retval } +# f_disk_size_bytes $disk # +# Return the size of the disk in bytes +# +f_disk_size_bytes() +{ + local disk="$1" + + local size_bytes=`diskinfo -v $disk|grep '# mediasize in bytes' | awk '{ print $1 }'` + local retval=$? + + if [ $retval -ne 0 ]; then + exit $retval + fi + + echo "$size_bytes" +} + +# # Short-hand # f_cdrom() { f_device_name_set $DEVICE_TYPE_CDROM "$1" "$2" "$3"; } @@ -680,6 +752,7 @@ f_disk "ipsd%d" "IBM ServeRAID RAID array" f_disk "mfid%d" "LSI MegaRAID SAS array" 4 f_disk "mlxd%d" "Mylex RAID disk" 4 f_disk "twed%d" "3ware ATA RAID array" 4 +f_disk "vtbd%d" "VirtIO Block Device" 16 f_floppy "fd%d" "Floppy Drive unit A" 4 f_serial "cuau%d" "%s on device %s (COM%d)" 16 f_usb "da%da" "USB Mass Storage Device" 16 Index: usr.sbin/bsdconfig/share/strings.subr =================================================================== --- usr.sbin/bsdconfig/share/strings.subr (revision 256125) +++ usr.sbin/bsdconfig/share/strings.subr (working copy) @@ -26,6 +26,11 @@ if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1 # # $FreeBSD$ # +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 + ############################################################ GLOBALS # @@ -319,6 +324,112 @@ f_shell_unescape() f_replaceall "$__string" "'\\''" "'" "$__var_to_set" } +# f_expand_number $string [$var_to_set] +# +# Unformat $string into a number, optionally to be stored in $var_to_set. This +# function follows the SI power of two convention. +# +# The prefixes are: +# +# Prefix Description Multiplier +# k kilo 1024 +# M mega 1048576 +# G giga 1073741824 +# T tera 1099511627776 +# P peta 1125899906842624 +# E exa 1152921504606846976 +# +# NOTE: Prefixes are case-insensitive. +# +# Upon successful completion, the value 0 is returned (or stored to +# $var_to_set); otherwise -1. Reasons for a -1 return include: +# +# Given $string contains no digits. +# An unrecognized prefix was given. +# Result too large to calculate. +# +f_expand_number() +{ + local __string="$1" __var_to_set="$2" + local __cp __num + + # Remove any leading non-digits + while :; do + __cp="$__string" + __string="${__cp#[!0-9]}" + [ "$__string" = "$__cp" ] && break + done + + # Return `-1' if string didn't contain any digits + if [ ! "$__string" ]; then + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" -1 + else + echo -1 + fi + return $FAILURE + fi + + # Store the numbers + __num="${__string%%[!0-9]*}" + + # Shortcut + if [ $__num -eq 0 ]; then + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" 0 + else + echo 0 + fi + return $SUCCESS + fi + + # Remove all the leading numbers from the string to get at the prefix + while :; do + __cp="$__string" + __string="${__cp#[0-9]}" + [ "$__string" = "$__cp" ] && break + done + + # Test for invalid prefix + case "$__string" in + ""|[KkMmGgTtPpEe]*) : known prefix ;; + *) + # Unknown prefix + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" -1 + else + echo -1 + fi + return $FAILURE + esac + + # Multiply the number out + case "$__string" in + [Kk]) __num=$(( $__num * 1024 )) ;; + [Mm]) __num=$(( $__num * 1048576 )) ;; + [Gg]) __num=$(( $__num * 1073741824 )) ;; + [Tt]) __num=$(( $__num * 1099511627776 )) ;; + [Pp]) __num=$(( $__num * 1125899906842624 )) ;; + [Ee]) __num=$(( $__num * 1152921504606846976 )) ;; + esac + if [ $__num -le 0 ]; then + # Arithmetic overflow + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" -1 + else + echo -1 + fi + return $FAILURE + fi + + # Return the number + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" $__num + else + echo $__num + fi +} + ############################################################ MAIN f_dprintf "%s: Successfully loaded." strings.subr Index: usr.sbin/bsdinstall/bsdinstall =================================================================== --- usr.sbin/bsdinstall/bsdinstall (revision 256125) +++ usr.sbin/bsdinstall/bsdinstall (working copy) @@ -28,6 +28,7 @@ : ${BSDINSTALL_LOG="/tmp/bsdinstall_log"}; export BSDINSTALL_LOG : ${BSDINSTALL_TMPETC="/tmp/bsdinstall_etc"}; export BSDINSTALL_TMPETC +: ${BSDINSTALL_TMPBOOT="/tmp/bsdinstall_boot"}; export BSDINSTALL_TMPBOOT : ${PATH_FSTAB="$BSDINSTALL_TMPETC/fstab"}; export PATH_FSTAB : ${BSDINSTALL_DISTDIR="/usr/freebsd-dist"}; export BSDINSTALL_DISTDIR : ${BSDINSTALL_CHROOT="/mnt"}; export BSDINSTALL_CHROOT @@ -35,5 +36,6 @@ VERB=${1:-auto}; shift [ -d "$BSDINSTALL_TMPETC" ] || mkdir -p "$BSDINSTALL_TMPETC" +[ -d "$BSDINSTALL_TMPBOOT" ] || mkdir -p "$BSDINSTALL_TMPBOOT" echo "Running installation step: $VERB $@" >> "$BSDINSTALL_LOG" exec "/usr/libexec/bsdinstall/$VERB" "$@" 2>> "$BSDINSTALL_LOG" Index: usr.sbin/bsdinstall/scripts/Makefile =================================================================== --- usr.sbin/bsdinstall/scripts/Makefile (revision 256125) +++ usr.sbin/bsdinstall/scripts/Makefile (working copy) @@ -2,7 +2,7 @@ SCRIPTS= auto adduser checksum config docsinstall hostname jail keymap \ mirrorselect mount netconfig netconfig_ipv4 netconfig_ipv6 rootpass \ - script services time umount wlanconfig + script services time umount wlanconfig zfsboot BINDIR= /usr/libexec/bsdinstall NO_MAN= true Index: usr.sbin/bsdinstall/scripts/auto =================================================================== --- usr.sbin/bsdinstall/scripts/auto (revision 256125) +++ usr.sbin/bsdinstall/scripts/auto (working copy) @@ -93,24 +93,39 @@ fi rm $PATH_FSTAB touch $PATH_FSTAB -dialog --backtitle "FreeBSD Installer" --title "Partitioning" --extra-button \ - --extra-label "Manual" --ok-label "Guided" --cancel-label "Shell" \ - --yesno "Would you like to use the guided partitioning tool (recommended for beginners) or to set up partitions manually (experts)? You can also open a shell and set up partitions entirely by hand." 0 0 +PMODES="\ +Guided \"Partitioning Tool (Recommended for Beginners)\" \ +Manual \"Manually Configure Partitions (Expert)\" \ +ZFS \"Automatic Root-on-ZFS (Experimental)\" \ +Shell \"Open a shell and partition by hand\" \ +" -case $? in -0) # Guided +exec 3>&1 +PARTMODE=`echo $PMODES | xargs dialog --backtitle "FreeBSD Installer" \ + --title "Partitioning" \ + --menu "How would you like to partition your disk?" \ + 0 0 0 2>&1 1>&3` +if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi +exec 3>&- + +case "$PARTMODE" in +"Guided") # Guided bsdinstall autopart || error bsdinstall mount || error ;; -1) # Shell +"Shell") # Shell clear echo "Use this shell to set up partitions for the new system. When finished, mount the system at $BSDINSTALL_CHROOT and place an fstab file for the new system at $PATH_FSTAB. Then type 'exit'. You can also enter the partition editor at any time by entering 'bsdinstall partedit'." sh 2>&1 ;; -3) # Manual +"Manual") # Manual bsdinstall partedit || error bsdinstall mount || error ;; +"ZFS") # ZFS + bsdinstall zfsboot || error + bsdinstall mount || error + ;; *) error ;; Index: usr.sbin/bsdinstall/scripts/config =================================================================== --- usr.sbin/bsdinstall/scripts/config (revision 256125) +++ usr.sbin/bsdinstall/scripts/config (working copy) @@ -31,6 +31,11 @@ rm $BSDINSTALL_TMPETC/rc.conf.* cp $BSDINSTALL_TMPETC/* $BSDINSTALL_CHROOT/etc +cat $BSDINSTALL_TMPBOOT/loader.conf.* >> $BSDINSTALL_TMPBOOT/loader.conf +rm $BSDINSTALL_TMPBOOT/loader.conf.* + +cp $BSDINSTALL_TMPBOOT/* $BSDINSTALL_CHROOT/boot + # Set up other things from installed config chroot $BSDINSTALL_CHROOT /usr/bin/newaliases Index: usr.sbin/bsdinstall/scripts/keymap =================================================================== --- usr.sbin/bsdinstall/scripts/keymap (revision 256125) +++ usr.sbin/bsdinstall/scripts/keymap (working copy) @@ -29,7 +29,8 @@ kbdcontrol -d >/dev/null 2>&1 if [ $? -eq 0 ]; then dialog --backtitle "FreeBSD Installer" --title "Keymap Selection" \ - --yesno "Would you like to set a non-default key mapping for your keyboard?" 0 0 || exit 0 + --defaultno --yesno "Would you like to set a non-default key \ + mapping for your keyboard?" 0 0 || exit 0 exec 3>&1 kbdmap 2>&1 1>&3 | grep 'keymap=' > $BSDINSTALL_TMPETC/rc.conf.keymap fi Index: usr.sbin/bsdinstall/scripts/netconfig =================================================================== --- usr.sbin/bsdinstall/scripts/netconfig (revision 256125) +++ usr.sbin/bsdinstall/scripts/netconfig (working copy) @@ -90,14 +90,18 @@ case $? in esac if [ ${IPV4_AVAIL} -eq 1 ]; then - dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ - --yesno 'Would you like to configure IPv4 for this interface?' 0 0 - if [ $? -eq $DIALOG_OK ]; then - bsdinstall netconfig_ipv4 ${INTERFACE} "${IFCONFIG_PREFIX}" || \ - exec $0 - else - IPV4_AVAIL=0 - fi + bsdinstall netconfig_ipv4 ${INTERFACE} "${IFCONFIG_PREFIX}" + case $? in + 0) #OK + break + ;; + 4) #No ipv4 + IPV4_AVAIL=0 + ;; + *) #Error + exec $0 + ;; + esac fi # In case wlanconfig left an option and we do not support IPv4 we need to write # it out on its own. We cannot write it out with IPv6 as that suffix. Index: usr.sbin/bsdinstall/scripts/netconfig_ipv4 =================================================================== --- usr.sbin/bsdinstall/scripts/netconfig_ipv4 (revision 256125) +++ usr.sbin/bsdinstall/scripts/netconfig_ipv4 (working copy) @@ -43,34 +43,58 @@ case "${INTERFACE}" in ;; esac -dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0 -if [ $? -eq $DIALOG_OK ]; then - echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/._rc.conf.net - - if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then - dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0 - dhclient $INTERFACE 2>> $BSDINSTALL_LOG - if [ $? -ne 0 ]; then - dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0 - exec $0 ${INTERFACE} "${IFCONFIG_PREFIX}" - fi - fi - exit 0 -fi - IP_ADDRESS=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $2); }'` NETMASK=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $4); }'` ROUTER=`netstat -rn -f inet | awk '/default/ {printf("%s\n", $2);}'` exec 3>&1 -IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --form 'Static Network Interface Configuration' 0 0 0 \ + + +#dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ +# --extra-button --ok-label "DHCP" --extra-label "Static" \ +# --cancel-label "None" \ +# --yesno 'How would you like to configure this interface?' 0 0 + +IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' \ + --title 'Network Configuration' \ + --extra-button --extra-label "No IPv4" --defaultno \ + --cancel-label "DHCP" --ok-label "Static" \ + --form 'Network Interface Configuration' 0 0 0 \ 'IP Address' 1 0 "$IP_ADDRESS" 1 20 16 0 \ 'Subnet Mask' 2 0 "$NETMASK" 2 20 16 0 \ 'Default Router' 3 0 "$ROUTER" 3 20 16 0 \ 2>&1 1>&3) -if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi +case $? in + 1) #DHCP + echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> \ + $BSDINSTALL_TMPETC/._rc.conf.net + + if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + dialog --backtitle 'FreeBSD Installer' \ + --infobox "Acquiring DHCP lease..." 0 0 + dhclient $INTERFACE 2>> $BSDINSTALL_LOG + if [ $? -ne 0 ]; then + dialog --backtitle 'FreeBSD Installer' \ + --msgbox "DHCP lease acquisition failed." 0 0 + exec $0 ${INTERFACE} "${IFCONFIG_PREFIX}" + fi + fi + exit 0 + ;; + 3) #None + exit 4 + ;; + 0) #Static + break + ;; + *) + error + ;; +esac exec 3>&- + + echo $INTERFACE $IF_CONFIG | awk -v prefix="$IFCONFIG_PREFIX" '{ printf("ifconfig_%s=\"%s\inet %s netmask %s\"\n", $1, prefix, $2, $3); @@ -85,4 +109,3 @@ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then route add -inet default $defaultrouter fi fi - Index: usr.sbin/bsdinstall/scripts/services =================================================================== --- usr.sbin/bsdinstall/scripts/services (revision 256125) +++ usr.sbin/bsdinstall/scripts/services (working copy) @@ -46,22 +46,23 @@ DAEMONS=$(dialog --backtitle "FreeBSD Installer" \ moused "PS/2 mouse pointer on console" ${moused_enable:-off} \ ntpd "Synchronize system and network time" ${ntpd_enable:-off} \ powerd "Adjust CPU frequency dynamically if supported" ${powerd_enable:-off} \ + dumpdev "Would you like to enable crash dumps to /var ?" ${dumpdev:-on} \ 2>&1 1>&3) exec 3>&- +local havedump= for daemon in $DAEMONS; do + if [ "$daemon" == "dumpdev" ]; then + havedump=1 + echo \# Set dumpdev to \"AUTO\" to enable crash dumps, \ + \"NO\" to disable >> \ + $BSDINSTALL_TMPETC/rc.conf.services + echo dumpdev=\"AUTO\" >> $BSDINSTALL_TMPETC/rc.conf.services + continue + fi echo ${daemon}_enable=\"YES\" >> $BSDINSTALL_TMPETC/rc.conf.services done -echo \# Set dumpdev to \"AUTO\" to enable crash dumps, \"NO\" to disable >> \ - $BSDINSTALL_TMPETC/rc.conf.services - -dialog --backtitle "FreeBSD Installer" --title "Dumpdev Configuration" \ - --nocancel --yesno \ - "Would you like to enable crash dumps? If you start having problems with the system it can help the FreeBSD developers debug the problem. But the crash dumps can take up a lot of disk space in /var." 0 0 - -if [ $? -eq $DIALOG_OK ]; then - echo dumpdev=\"AUTO\" >> $BSDINSTALL_TMPETC/rc.conf.services -else +if [ ! "$havedump" ]; then echo dumpdev=\"NO\" >> $BSDINSTALL_TMPETC/rc.conf.services fi Index: usr.sbin/bsdinstall/scripts/zfsboot =================================================================== --- usr.sbin/bsdinstall/scripts/zfsboot (revision 0) +++ usr.sbin/bsdinstall/scripts/zfsboot (working copy) @@ -0,0 +1,937 @@ +#!/bin/sh +#- +# Copyright (c) 2013 Allan Jude +# Copyright (c) 2013 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 + +############################################################ CONFIGURATION + +# +# Default name of the boot-pool +# +: ${ZFSBOOT_POOL_NAME:=zroot} + +# +# Default name for the boot environment parent dataset +# +: ${ZFSBOOT_BEROOT_NAME:=bootenv} + +# +# 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 gnop(8) to configure a transparent mapping to 4K sectors? +# +: ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:=1} + +# +# Should we use geli(8) to encrypt the drives +# +: ${ZFSBOOT_GELI_ENCRYPTION:=} + +# +# What should we name the unencrypted pool +# +: ${ZFSBOOT_GELI_POOL_NAME:=geliboot} + +# +# How big should the unencrypted boot pool be +# +: ${ZFSBOOT_GELI_BOOT_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} + +# +# Default ZFS layout for root zpool +# +# NOTE: Requires `/tmp', `/var/tmp', and `/$ZFSBOOT_BOOTFS_NAME/default' +# 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 Envionment Root, contains all boot datasets + /$ZFSBOOT_BEROOT_NAME \ + mountpoint=none + #Default boot environment dataset + /$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME \ + mountpoint=/ + #compress /tmp, allow exec but not setuid + /tmp mountpoint=/tmp,compression=lz4,exec=on,setuid=off + #/usr is not mounted so that 'base' files go to the BEROOT + /usr mountpoint=/usr,canmount=off + #keep local files, like packages separate from the base system + /usr/local + #keep home directories separate so they are common to all BEs + /usr/home setuid=off + #we only need 1 copy of the ports tree + /usr/ports compression=lz4,setuid=off + /usr/ports/distfiles compression=off,exec=off,setuid=off + /usr/ports/packages compression=off,exec=off,setuid=off + #One source tree, compressed + /usr/src compression=lz4,exec=off,setuid=off + /usr/obj + #create /var and friends + /var mountpoint=/var + /var/crash compression=lz4,exec=off,setuid=off + /var/db exec=off,setuid=off + /var/db/pkg compression=lz4,exec=off,setuid=off + /var/empty exec=off,setuid=off + /var/log compression=lz4,exec=off,setuid=off + /var/mail compression=lz4,exec=off,setuid=off + /var/run exec=off,setuid=off + /var/tmp compression=lz4,exec=on,setuid=off +" # END-QUOTE + +############################################################ GLOBALS + +# +# 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_cancel="Cancel" +msg_configure_options="Configure Options:" +msg_create="Install" +msg_create_desc="Proceed with Installation" +msg_create_help="Create ZFS boot pool with displayed 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_disks_to_use="Disks To Use" +msg_disks_to_use_help="Choose which disks to use for the Virtual Device (Required)" +msg_force_4k_sectors="Force 4K Sectors?" +msg_force_4k_sectors_help="Use gnop(8) to configure forced 4K sector alignment" +msg_geli_encryption="Encrypt Disks?" +msg_geli_encryption_help="Use geli(8) to encrypt all data partitions" +msg_freebsd_installer="FreeBSD Installer" +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%s" +msg_mirror_desc="Mirror - n-Way Mirroring" +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 (minimum %u)" +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_raidz1_desc="RAID-Z1 - Single Redundant RAID" +msg_raidz2_desc="RAID-Z2 - Double Redundant RAID" +msg_raidz3_desc="RAID-Z3 - Triple Redundant RAID" +msg_rescan_devices="Rescan Devices" +msg_rescan_devices_help="Scan for device changes" +msg_select_disk_device="Select a disk device" +msg_select_virtual_device_type="Select Virtual Device type:" +msg_stripe_desc="Stripe - No Redundancy" +msg_swap_size="Swap Size" +msg_swap_size_help="Customize how much swap space is allocated to each selected disk" +msg_yes="YES" +msg_zfs_configuration="ZFS Configuration" +msg_zfs_vdev_type="ZFS VDev Type" +msg_zfs_vdev_type_help="Select type of ZFS Virtual Device to create" + +############################################################ 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" + [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ] && force4k="$msg_yes" + [ "$ZFSBOOT_GELI_ENCRYPTION" ] && usegeli="$msg_yes" + local menu_list=" + '>>> $msg_create' '$msg_create_desc' + '$msg_create_help' + '- $msg_rescan_devices' '*' + '$msg_rescan_devices_help' + '- $msg_disk_info' '*' + '$msg_disk_info_help' + '1 $msg_pool_name' '$ZFSBOOT_POOL_NAME' + '$msg_pool_name_help' + '2 $msg_disks_to_use' '$ZFSBOOT_DISKS' + '$msg_disks_to_use_help' + '3 $msg_zfs_vdev_type' '$ZFSBOOT_VDEV_TYPE' + '$msg_zfs_vdev_help' + '4 $msg_force_4k_sectors' '$force4k' + '$msg_force_4k_sectors_help' + '5 $msg_geli_encryption' '$usegeli' + '$msg_geli_encryption_help' + '6 $msg_partition_scheme' '$ZFSBOOT_PARTITION_SCHEME' + '$msg_partition_scheme_help' + '7 $msg_swap_size' '$ZFSBOOT_SWAP_SIZE' + '$msg_swap_size_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 \ + --nook --nocancel \ + --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 0 ] && f_dialog_default_store "$menu_choice" + + return $retval +} + +# dialog_edit_disks +# +# Edit the list of disks to be used by the ZFS boot pool. +# +dialog_edit_disks() +{ + local title="$DIALOG_TITLE" + local btitle="$DIALOG_BACKTITLE" + local prompt="$msg_please_select_one_or_more_disks" + local check_list= # Calculated below + local hline="$hline_arrows_space_tab_enter" + local dev vardev disks= + + # + # Get a [new] list of disk devices + # + f_device_find "" $DEVICE_TYPE_DISK disks + if [ ! "$disks" ]; then + f_show_msg "$msg_no_disks_present_to_configure" + return $FAILURE + fi + + # Lets sort the disks array to be more user friendly + disks=`echo "$disks" | tr " " "\n" | sort | tr "\n" " "` + + # + # Loop through the list of selected disks and create temporary local + # variables mapping their status onto an up-to-date list of disks. + # + for dev in $ZFSBOOT_DISKS; do + f_str2varname "$dev" vardev + local _${vardev}_status=on + done + + # + # Create the checklist menu of discovered disk devices + # + local on_off + for dev in $disks; do + local desc= + device_$dev get desc desc + f_shell_escape "$desc" desc + f_str2varname "$dev" vardev + f_getvar _${vardev}_status:-off on_off + check_list="$check_list '$dev' '$desc' $on_off" + done + + # + # Prompt the user to check some disks + # + local height width rows + eval f_dialog_checklist_size height width rows \ + \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" $check_list + disks=$( eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --checklist \"\$prompt\" \ + $height $width $rows \ + $check_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) || return $? + # Exit if user either pressed ESC or chose Cancel/No + f_dialog_data_sanitize disks + + ZFSBOOT_DISKS="$disks" + + return $SUCCESS +} + +# dialog_menu_vdev +# +# Prompt the user to select a a Virtual Device type. +# +dialog_menu_vdev() +{ + local title="$DIALOG_TITLE" + local btitle="$DIALOG_BACKTITLE" + local prompt="$msg_select_virtual_device_type" + + # Make sure [potentially scripted] selections are real + real_disks= + for disk in $ZFSBOOT_DISKS; do + f_struct device_$disk && real_disks="$real_disks $disk" + done + # Make sure we have at least one real disk selected + ndisks=$( set -- $real_disks; echo $# ) + + local menu_list=" + 'stripe' '$msg_stripe_desc' + " # END-QUOTE + if [ $ndisks -ge 2 ]; then + menu_list="$menu_list 'mirror' '$msg_mirror_desc' + " # END-QUOTE + fi + if [ $ndisks -ge 3 ]; then + menu_list="$menu_list 'raidz1' '$msg_raidz1_desc' + " # END-QUOTE + fi + if [ $ndisks -ge 4 ]; then + menu_list="$menu_list 'raidz2' '$msg_raidz2_desc' + " # END-QUOTE + fi + if [ $ndisks -ge 5 ]; then + menu_list="$menu_list 'raidz3' '$msg_raidz3_desc' + " # END-QUOTE + fi + + local defaultitem="$ZFSBOOT_VDEV_TYPE" + local hline="$hline_arrows_tab_enter" + + local height width rows + eval f_dialog_menu_size height width rows \ + \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" $menu_list + + local menu_choice + menu_choice=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --default-item \"\$defaultitem\" \ + --menu \"\$prompt\" \ + $height $width $rows \ + $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) || return $FAILURE + f_dialog_data_sanitize menu_choice + + ZFSBOOT_VDEV_TYPE="$menu_choice" +} + +# zfs_create_boot $poolname $vdev_type $real_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 poolname="$1" vdev_type="$2" + local fstab_fmt="%s\t\t%s\t%s\t%s\t\t%s\t%s\n" + local funcname=zfs_create_boot + + shift 2 # name vdev_type + + # We may need this later + local realdisks=$* + + local targetpart=p2 + local bootpart=p2 + + # Pedantic checks; should never be seen + if [ ! "$poolname" ]; then + echo "$funcname: NULL poolname" >&2 + return $FAILURE + fi + if [ $# -lt 1 ]; then + echo "$funcname: missing disk arguments" >&2 + return $FAILURE + fi + + # Initialize fstab(5) + printf "$fstab_fmt" \ + "# Device" Mountpoint FStype Options Dump "Pass#" \ + >> $BSDINSTALL_TMPETC/fstab || return $FAILURE + + # + # 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 + # + # The layout for MBR is more complicated, hopefully everyone uses GPT + # + local disk swapsize gelisize partsize n=0 + for disk in $*; do + # Destroy whatever partition layout is currently on disk + # NOTE: `-F' required to destroy if partitions still exist + # Failure is ok here, blank disk will have nothing to destroy + gpart destroy -F $disk 2>&1 > /dev/null + # Kill it with fire + zpool labelclear -f /dev/${disk} + # Suggested by wblock, make sure backup gpt is destroyed + gpart create -s gpt $disk 2>&1 > /dev/null || return $FAILURE + gpart destroy -F $disk 2>&1 > /dev/null || return $FAILURE + + # Calculate the size of the disk + local disksize=`f_disk_size_bytes ${disk}` + # Calculate the size of the swap + f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize || + return $FAILURE + # Calculate the difference + partsize=$(( $disksize - $swapsize )) + # How big should the unencrypted partition be + f_expand_number "$ZFSBOOT_GELI_BOOT_SIZE" gelisize || + return $FAILURE + + case "$ZFSBOOT_PARTITION_SCHEME" in + ""|GPT) + # 1. Create a GPT layout using labels + # 2. Add a small freebsd-boot partition labeled `boot#' + # 3. Add a freebsd-zfs partition labeled `zfs#' + # 3. Add a 2G freebsd-swap partition labeled `swap#' + # The zpool will use the `zfs#' GPT labels. + # + # Put a GPT scheme on the disk + gpart create -s gpt $disk || return $FAILURE + # Add the `gptboot#' labeled partition + gpart add -l gptboot$n -t freebsd-boot -s 512k $disk || + return $FAILURE + gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 \ + $disk || return $FAILURE + # Change things around if we are using GELI + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + targetpart=p3 + bootpart=p2 + partsize=$(( $partsize - $gelisize )) + gpart add -l boot$n -t freebsd-zfs \ + -s ${gelisize}b -a 1m $disk || + return $FAILURE + # Nuke anything we find here + zpool labelclear -f /dev/${disk}${bootpart} + fi + # Add ZFS partition (to be used in the zpool) + # Use calculated size to leave room for swap + local setsize="-s ${partsize}b" + if [ ! $swapsize -gt 0 ]; then + setsize= + fi + gpart add -l zfs$n -t freebsd-zfs $setsize \ + -a 1m $disk || return $FAILURE + # Nuke anything we find here + zpool labelclear -f /dev/${disk}${targetpart} + + if [ $swapsize -gt 0 ]; then + # Add swap partition (labeled `swap#') + # Uses the rest of the space + gpart add -l swap$n -t freebsd-swap -a 1m \ + $disk || return $FAILURE + # Update fstab(5) + printf "$fstab_fmt" /dev/gpt/swap$n none swap sw 0 0 \ + >> $BSDINSTALL_TMPETC/fstab || \ + return $FAILURE + fi + ;; + MBR) + # 1. Create a MBR layout (no labels) + # 2. Add a freebsd slice with all available space + # 3. write a BSD sceme to the freebsd slice + # 4. Partition the BSD slice for ZFS + # 5. Add a 2G freebsd-swap partition + # + # The zpool will use s1a (no labels) + # + # Put an MBR scheme on the disk + gpart create -s mbr $disk || return $FAILURE + # Write bootcode + gpart bootcode -b /boot/boot0 $disk || return $FAILURE + # Create FreeBSD slice and mark it active + gpart add -t freebsd $disk || return $FAILURE + gpart set -a active -i 1 $disk || return $FAILURE + # Make sure there isn't a hidden BSD partition + gpart destroy -F ${disk}s1 2>&1 > /dev/null + # Create BSD partition table + gpart create -s BSD ${disk}s1 || return $FAILURE + # Change things around if we are using GELI + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + targetpart=s1d + bootpart=s1a + partsize=$(( $partsize - $gelisize )) + gpart add -t freebsd-zfs -s ${gelisize}b \ + ${disk}s1 || return $FAILURE + # Nuke anything we find here + zpool labelclear -f /dev/${disk}${bootpart} + else + targetpart=s1a + bootpart=s1a + fi + # Add ZFS partition (to be used in the zpool) + # Use calculated size to leave room for swap + local setsize="-s ${partsize}b" + if [ ! $swapsize -gt 0 ]; then + setsize= + fi + gpart add -t freebsd-zfs $setsize \ + ${disk}s1 || return $FAILURE + # Nuke anything we find here + zpool labelclear -f /dev/${disk}${targetpart} + + if [ $swapsize -gt 0 ]; then + # Add swap partition, uses the rest of the space + gpart add -t freebsd-swap ${disk}s1 || \ + return $FAILURE + # Update fstab(5) + printf "$fstab_fmt" /dev/${disk}s1b none swap sw 0 0 \ + >> $BSDINSTALL_TMPETC/fstab || \ + return $FAILURE + fi + ;; + *) + printf "%s: %s is an unsupported partition scheme" \ + "$funcname" "$ZFSBOOT_PARTITION_SCHEME" >&2 + return $FAILURE + ;; + esac + n=$(( $n + 1 )) + done + + # MBR boot loader hack part 1 + # We have to do this early because geli gets in the way later + if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then + for disk in $realdisks; do + dd if=/boot/zfsboot of=/dev/${disk}s1 count=1 || + return $FAILURE + done + fi + + # Forced 4k alignment support provided by Geom NOP (see gnop(8)) + local unenc_list= + if [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ]; then + local new_list= + for disk in $*; do + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + # We don't gnop the encrypted partition + # because geli will do this for us + # gnop the unencrypted disk + gnop create -S 4096 ${disk}${bootpart} \ + || return $FAILURE + unenc_list="$unenc_list \ + ${disk}${bootpart}.nop" + else + gnop create -S 4096 ${disk}${targetpart} \ + || return $FAILURE + new_list="$new_list \ + ${disk}${targetpart}.nop" + fi + done + set -- $new_list + else + local new_list= + for disk in $*; do + new_list="$new_list ${disk}${targetpart}" + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + unenc_list="$unenc_list ${disk}${bootpart}" + fi + done + set -- $new_list + fi + + # If encryption is enabled, we need to create the GEOMs + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + ## Create the parent directories for our unencrypted pool + umount /mnt 2>&1 > /dev/null + mount -t tmpfs none ${BSDINSTALL_CHROOT} || return $FAILURE + + # Create mirror across the unencrypted partition on all disks + local bootvdev= + if [ `echo $unenc_list | wc -w` -gt 1 ]; then + bootvdev=mirror + fi + zpool create -o altroot=${BSDINSTALL_CHROOT} \ + -m /$ZFSBOOT_GELI_POOL_NAME \ + -f $ZFSBOOT_GELI_POOL_NAME $bootvdev $unenc_list || + return $FAILURE + mkdir -p ${BSDINSTALL_CHROOT}/$ZFSBOOT_GELI_POOL_NAME/boot || + return $FAILURE + # Generate a random encryption key + dd if=/dev/random \ + of=${BSDINSTALL_CHROOT}/$ZFSBOOT_GELI_POOL_NAME/boot/encryption.key \ + bs=4096 count=1 || return $FAILURE + # Create the geli(8) GEOMS + local geli_list= + for disk in $realdisks; do + geli init -b -B \ + ${BSDINSTALL_CHROOT}/$ZFSBOOT_GELI_POOL_NAME/boot/${disk}${targetpart}.eli \ + -e AES-XTS \ + -K ${BSDINSTALL_CHROOT}/$ZFSBOOT_GELI_POOL_NAME/boot/encryption.key \ + -l 256 -s 4096 ${disk}${targetpart} || + return $FAILURE + geli attach \ + -k ${BSDINSTALL_CHROOT}/$ZFSBOOT_GELI_POOL_NAME/boot/encryption.key \ + ${disk}${targetpart} || + return $FAILURE + geli_list="$geli_list ${disk}${targetpart}.eli" + done + set -- $geli_list + zfs unmount $ZFSBOOT_GELI_POOL_NAME || return $FAILURE + fi + + # + # Create the ZFS pool with desired type and disk devices + # + zpool create -o altroot=$BSDINSTALL_CHROOT -m none -f \ + $poolname $vdevtype $* || return $FAILURE + + # Customize the zpool a bit... + zfs set checksum=fletcher4 $poolname || return $FAILURE + zfs set atime=off $poolname || return $FAILURE + + # + # Create ZFS dataset layout within the new boot pool + # + 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" " " " " foo + # 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 + zfs create ${options:+-o $options} $poolname$dataset || + return $FAILURE + done + + # Touch up permissions on the tmp directories + chmod 1777 $BSDINSTALL_CHROOT/tmp || return $FAILURE + chmod 1777 $BSDINSTALL_CHROOT/var/tmp || return $FAILURE + + if [ "$ZFSBOOT_GELI_ENCRYPTION" ];then + ln -s $ZFSBOOT_GELI_POOL_NAME/boot \ + $BSDINSTALL_CHROOT/boot || return $FAILURE + fi + # Set bootfs property + zpool set bootfs=$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME $poolname || + return $FAILURE + + # Export the pool + zpool export $poolname || return $FAILURE + + if [ "$ZFSBOOT_GELI_ENCRYPTION" ];then + zpool export $ZFSBOOT_GELI_POOL_NAME || return $FAILURE + fi + # Destroy the gnop devices + if [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ]; then + for disk in $realdisks; do + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + gnop destroy ${disk}${bootpart}.nop \ + 2>&1 > /dev/null + else + gnop destroy ${disk}${targetpart}.nop \ + 2>&1 > /dev/null + fi + done + fi + + # MBR boot loader hack part 2 + if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then + # Stick the ZFS boot loader in the "convienient hole" after + # the ZFS internal metadata + for disk in $realdisks; do + dd if=/boot/zfsboot of=/dev/${disk}${bootpart} \ + skip=1 seek=1024 || return $FAILURE + done + fi + + # Re-import the ZFS pool + zpool import -o altroot=$BSDINSTALL_CHROOT $poolname || + return $FAILURE + + if [ "$ZFSBOOT_GELI_ENCRYPTION" ];then + # Re-import the unencrypted pool + zpool import -o altroot=${BSDINSTALL_CHROOT} \ + $ZFSBOOT_GELI_POOL_NAME || + return $FAILURE + fi + + # While this is apparently not needed, it seems to help MBR + mkdir -p ${BSDINSTALL_CHROOT}/boot/zfs || return $FAILURE + zpool set cachefile=${BSDINSTALL_CHROOT}/boot/zfs/zpool.cache \ + $poolname || return $FAILURE + + # Last, but not least... add required lines to rc.conf(5) + # NOTE: We later concatenate these into their destination + echo 'zfs_enable="YES"' > $BSDINSTALL_TMPETC/rc.conf.zfs || + return $FAILURE + echo 'zfs_load="YES"' > $BSDINSTALL_TMPBOOT/loader.conf.zfs || + return $FAILURE + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + echo 'aesni_load="YES"' > \ + $BSDINSTALL_TMPBOOT/loader.conf.aesni || + return $FAILURE + echo 'geom_eli_load="YES"' > \ + $BSDINSTALL_TMPBOOT/loader.conf.geli || + return $FAILURE + echo "vfs.root.mountfrom=\"zfs:$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME\"" > \ + $BSDINSTALL_TMPBOOT/loader.conf.root || + return $FAILURE + for disk in $realdisks; do + echo "geli_${disk}${targetpart}_keyfile0_load=\"YES\"" \ + > $BSDINSTALL_TMPBOOT/loader.conf.${disk}${targetpart} || + return $FAILURE + echo "geli_${disk}${targetpart}_keyfile0_type=\"${disk}${targetpart}:geli_keyfile0\"" \ + >> $BSDINSTALL_TMPBOOT/loader.conf.${disk}${targetpart} || + return $FAILURE + echo "geli_${disk}${targetpart}_keyfile0_name=\"/boot/encryption.key\"" \ + >> $BSDINSTALL_TMPBOOT/loader.conf.${disk}${targetpart} || + return $FAILURE + done + fi + + return $SUCCESS +} + +# dialog_menu_diskinfo +# +# Prompt the user to select a disk and then provide detailed info on it. +# +dialog_menu_diskinfo() +{ + local disk + + # + # Break from loop when user cancels disk selection + # + while :; do + disk=$( f_device_menu "$DIALOG_TITLE" \ + "$msg_select_a_disk_device" "" \ + $DEVICE_TYPE_DISK 2>&1 ) || break + + # 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" + +# +# Loop over the main menu until we've accomplished what we came here to do +# +while :; do + dialog_menu_main + retval=$? + f_dialog_menutag_fetch mtag + f_dprintf "retval=%u mtag=[%s]" $reval "$mtag" + + if [ $retval -eq 255 ]; then + # User hit escape + exit 1 + fi + [ $retval -eq 0 ] || f_die + + case "$mtag" in + ">>> $msg_create") + # + # First, validate the user's selections + # + + # Make sure they gave us a name for the pool + if [ ! "$ZFSBOOT_POOL_NAME" ]; then + f_show_msg "$msg_pool_name_cannot_be_empty" + continue + fi + # Make sure [potentially scripted] selections are real + real_disks= + for disk in $ZFSBOOT_DISKS; do + f_struct device_$disk && real_disks="$real_disks $disk" + done + # Make sure we have at least one real disk selected + ndisks=$( set -- $real_disks; echo $# ) + if [ $ndisks -lt 1 ]; then + f_show_msg "$msg_no_disks_selected" + continue + fi + # Make sure we have enough disks for the desired vdev type + 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 ;; + *) + f_show_msg "$msg_invalid_virtual_device_type" \ + "$ZFSBOOT_VDEV_TYPE" + continue + ;; + esac + if [ $ndisks -lt $want_disks ]; then + f_show_msg "%s: $msg_not_enough_disks_selected" \ + "$ZFSBOOT_VDEV_TYPE" "$want_disks" + continue + fi + + # + # Last Chance! + # + f_noyes "$msg_last_chance_are_you_sure" "$ZFSBOOT_DISKS" || + continue + + # + # Let's do this + # + + vdev_type="$ZFSBOOT_VDEV_TYPE" + + # Blank the vdev type for the default layout + [ "$vdev_type" = "stripe" ] && vdev_type= + + if ! error=$( zfs_create_boot "$ZFSBOOT_POOL_NAME" \ + "$vdev_type" $real_disks 2>&1 ) + then + f_dialog_msgbox "$error" + continue + fi + + break # to success + ;; + "- $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="$input" + ;; + ?" $msg_disks_to_use") dialog_edit_disks ;; + ?" $msg_zfs_vdev_type") dialog_menu_vdev ;; + ?" $msg_force_4k_sectors") + # Toggle the variable referenced both by the menu and later + if [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ]; then + ZFSBOOT_GNOP_4K_FORCE_ALIGN= + else + ZFSBOOT_GNOP_4K_FORCE_ALIGN=1 + fi + ;; + ?" $msg_geli_encryption") + # Toggle the variable referenced both by the menu and later + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + ZFSBOOT_GELI_ENCRYPTION= + else + 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="$input" + ;; + esac +done + +return $SUCCESS + +################################################################################ +# END +################################################################################ Property changes on: usr.sbin/bsdinstall/scripts/zfsboot ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property