diff options
author | dteske <dteske@FreeBSD.org> | 2013-11-21 03:40:52 +0000 |
---|---|---|
committer | dteske <dteske@FreeBSD.org> | 2013-11-21 03:40:52 +0000 |
commit | d0873bf093c417f6d6ea3548a18a804c4ccf0230 (patch) | |
tree | efc7845c2535d49ddc896a2a1a992c2ec9c1a585 | |
parent | 7f36b7bf087251733bd30c159e873d5bd427ed53 (diff) | |
download | FreeBSD-src-d0873bf093c417f6d6ea3548a18a804c4ccf0230.zip FreeBSD-src-d0873bf093c417f6d6ea3548a18a804c4ccf0230.tar.gz |
MFC Revisions:
256549: man-page updates
256551: .Dd bump in manpage
256553: bootenv -> ROOT fix
257842: monster list of fixes
257843: minor touchup
257844: copy install log
257845: fixup to last
257872: mdoc fixup
257939: debug check
258021: MBR bootcode fixup
Reviewed by: many
Discussed on: -current
Approved by: re (hrs)
-rwxr-xr-x | usr.sbin/bsdinstall/bsdinstall | 54 | ||||
-rw-r--r-- | usr.sbin/bsdinstall/bsdinstall.8 | 39 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/auto | 23 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/config | 8 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/docsinstall | 176 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/jail | 15 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/netconfig_ipv4 | 21 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/netconfig_ipv6 | 24 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/script | 55 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/wlanconfig | 20 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/zfsboot | 1083 |
11 files changed, 1064 insertions, 454 deletions
diff --git a/usr.sbin/bsdinstall/bsdinstall b/usr.sbin/bsdinstall/bsdinstall index 612fc11..e57005dd 100755 --- a/usr.sbin/bsdinstall/bsdinstall +++ b/usr.sbin/bsdinstall/bsdinstall @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2011 Nathan Whitehorn +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,17 +26,62 @@ # SUCH DAMAGE. # # $FreeBSD$ +# +############################################################ INCLUDES + +# Delay processing of debug flags as the parent until MAIN. export'd to disable +# re-processing of flags (all children log to the parent's log file). +# +export DEBUG_SELF_INITIALIZE= + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 + +############################################################ GLOBALS -: ${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 -VERB=${1:-auto}; shift +export debugFile="${debugFile-${BSDINSTALL_LOG-/tmp/bsdinstall_log}}" + +############################################################ MAIN + +# +# Process command-line arguments +# +while getopts $GETOPTS_STDARGS ignored; do + : just skipping known flags +done +shift $(( $OPTIND - 1 )) + +# What are we here to do? +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" + +# Only enable debugging if debugFile is non-NULL and can be initialized +f_quietly f_debug_init +f_isset debugFile || debug= + +f_dprintf "Running installation step: %s %s" "$VERB" "$*" +if [ "$debug" ]; then + case "$debugFile" in + # If NULL, send errors to the bit-bucket + "") exec "/usr/libexec/bsdinstall/$VERB" "$@" 2> /dev/null ;; + # If begins with `+', send errors to both terminal and file (no `+') + +*) exec "/usr/libexec/bsdinstall/$VERB" "$@" \ + 2>&1 >&$TERMINAL_STDOUT_PASSTHRU | tee "${debugFile#+}" ;; + # Otherwise, just send errors to the file specified + *) exec "/usr/libexec/bsdinstall/$VERB" "$@" 2>> "$debugFile" + esac +else + exec "/usr/libexec/bsdinstall/$VERB" "$@" 2> /dev/null +fi + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/bsdinstall.8 b/usr.sbin/bsdinstall/bsdinstall.8 index 503dce7..b841c36 100644 --- a/usr.sbin/bsdinstall/bsdinstall.8 +++ b/usr.sbin/bsdinstall/bsdinstall.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 6, 2013 +.Dd October 15, 2013 .Dt BSDINSTALL 8 .Os .Sh NAME @@ -33,6 +33,7 @@ .Nd system installer .Sh SYNOPSIS .Nm +.Op Ar options .Op Ar target .Op Ar ... .Sh DESCRIPTION @@ -49,6 +50,18 @@ invoked with no arguments, it will invoke the target, which provides a standard interactive installation, invoking the others in sequence. To perform a scripted installation, these subtargets can be invoked separately by an installation script. +.Sh OPTIONS +.Nm +supports the following options, global to all targets: +.Bl -tag -width indent+ +.It Fl D Ar file +Provide a path for the installation log file +.Pq overrides Ev BSDINSTALL_LOG . +See +.Sx ENVIRONMENT VARIABLES +for more information on +.Ev BSDINSTALL_LOG . +.El .Sh TARGETS Most of the following targets are only useful for scripting the installer. For interactive use, most users will be interested only in the @@ -108,6 +121,21 @@ installations. Partitions disks, runs .Xr newfs 8 , and writes the new system's .Pa fstab . +.It Cm zfsboot +Provides the installer's +.Pq experimental +interactive/scriptable ZFS partitioner for multi-disk installations. +Creates a single +.Ic zpool +with datasets and writes to the new system's +.Pa rc.conf , +.Pa loader.conf , +and +.Pa fstab . +Supports +.Xr geli 8 , +.Xr gnop 8 , +and many other features. .It Cm partedit Provides the installer's interactive manual disk partitioner, with support for multi disk setups, non-UFS file systems, and manual selection of @@ -315,6 +343,15 @@ the preamble can contain a variable which is passed to the .Cm scriptedpart target to control disk setup. +Alternatively, +instead of +.Ev PARTITIONS , +the preamble can contain the variable +.Ev ZFSBOOT_DATASETS +which is parsed by the +.Pq experimental +.Cm zfsboot +target to control ZFS datasets/options of the boot pool setup. .Ss SETUP SCRIPT Following the preamble is an optional shell script, beginning with a #! declaration. This script will be run at the end of the installation process diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto index cd49021..dce4fe5 100755 --- a/usr.sbin/bsdinstall/scripts/auto +++ b/usr.sbin/bsdinstall/scripts/auto @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2011 Nathan Whitehorn +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,8 +26,13 @@ # SUCH DAMAGE. # # $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 -echo "Begun Installation at $(date)" > $BSDINSTALL_LOG +############################################################ FUNCTIONS error() { test -n "$DISTDIR_IS_UNIONFS" && umount -f $BSDINSTALL_DISTDIR @@ -41,6 +47,9 @@ error() { fi } +############################################################ MAIN + +f_dprintf "Began Installation at %s" "$( date )" rm -rf $BSDINSTALL_TMPETC mkdir $BSDINSTALL_TMPETC @@ -126,7 +135,12 @@ case "$PARTMODE" in sh 2>&1 ;; "Manual") # Manual - bsdinstall partedit || error + if f_isset debugFile; then + # Give partedit the path to our logfile so it can append + BSDINSTALL_LOG="${debugFile#+}" bsdinstall partedit || error + else + bsdinstall partedit || error + fi bsdinstall mount || error ;; "ZFS") # ZFS @@ -247,5 +261,8 @@ fi bsdinstall entropy bsdinstall umount -echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG +f_dprintf "Installation Completed at %s" "$( date )" +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/config b/usr.sbin/bsdinstall/scripts/config index e50a179..3ddcada 100755 --- a/usr.sbin/bsdinstall/scripts/config +++ b/usr.sbin/bsdinstall/scripts/config @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2011 Nathan Whitehorn +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,6 +26,8 @@ # SUCH DAMAGE. # # $FreeBSD$ +# +############################################################ MAIN cat $BSDINSTALL_TMPETC/rc.conf.* >> $BSDINSTALL_TMPETC/rc.conf rm $BSDINSTALL_TMPETC/rc.conf.* @@ -36,6 +39,11 @@ rm $BSDINSTALL_TMPBOOT/loader.conf.* cp $BSDINSTALL_TMPBOOT/* $BSDINSTALL_CHROOT/boot +[ "${debugFile#+}" ] && cp "${debugFile#+}" $BSDINSTALL_CHROOT/var/log/ + # Set up other things from installed config chroot $BSDINSTALL_CHROOT /usr/bin/newaliases +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/docsinstall b/usr.sbin/bsdinstall/scripts/docsinstall index 46d731f..2e893b5 100755 --- a/usr.sbin/bsdinstall/scripts/docsinstall +++ b/usr.sbin/bsdinstall/scripts/docsinstall @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2011 Marc Fonvieille +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,62 +26,137 @@ # 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/dialog.subr +f_include $BSDCFG_SHARE/mustberoot.subr +f_include $BSDCFG_SHARE/packages/packages.subr + +############################################################ CONFIGURATION + +# +# List of languages to display (descriptions pulled from $msg_{lang}doc_desc) +# +: ${DOCSINSTALL_LANGS:=\ + bn da de el en es fr hu it ja mn nl pl pt ru sr tr zh_cn zh_tw \ +} + +############################################################ GLOBALS + +# +# Strings that should be moved to an i18n file and loaded with f_include_lang() +# +hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER" +msg_bndoc_desc="Bengali Documentation" +msg_cancel="Cancel" +msg_dadoc_desc="Danish Documentation" +msg_dedoc_desc="German Documentation" +msg_docsinstall_menu_text="This menu allows you to install the whole documentation set from\nthe FreeBSD Documentation Project: Handbook, FAQ, and articles.\n\nPlease select the language versions you wish to install. At\nminimum, you should install the English version, the original\nversion of the documentation." +msg_eldoc_desc="Greek Documentation" +msg_endoc_desc="English Documentation (recommended)" +msg_esdoc_desc="Spanish Documentation" +msg_frdoc_desc="French Documentation" +msg_freebsd_documentation_installation="FreeBSD Documentation Installation" +msg_freebsd_installer="FreeBSD Installer" +msg_hudoc_desc="Hungarian Documentation" +msg_itdoc_desc="Italian Documentation" +msg_jadoc_desc="Japanese Documentation" +msg_mndoc_desc="Mongolian Documentation" +msg_nldoc_desc="Dutch Documentation" +msg_ok="OK" +msg_pldoc_desc="Polish Documentation" +msg_ptdoc_desc="Portuguese Documentation" +msg_rudoc_desc="Russian Documentation" +msg_srdoc_desc="Serbian Documentation" +msg_trdoc_desc="Turkish Documentation" +msg_zh_cndoc_desc="Simplified Chinese Documentation" +msg_zh_twdoc_desc="Traditional Chinese Documentation" + +############################################################ 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_docsinstall_menu_text" + local check_list= # Calculated below + local hline="$hline_arrows_space_tab_enter" + + local lang desc upper status + for lang in $DOCSINSTALL_LANGS; do + # Fetch the i18n description to display + f_getvar msg_${lang}doc_desc desc + f_shell_escape "$desc" desc -exec 3>&1 -DOCS=$(dialog --backtitle "FreeBSD Installer" \ - --title "FreeBSD Documentation Installation" --separate-output \ - --checklist "This menu will allow you to install the whole documentation set -from the FreeBSD Documentation Project: Handbook, FAQ and articles.\n\n -Please select the language versions you wish to install. At minimum, -you should install the English version, this is the original version -of the documentation.\n\n -NB: This requires a working, configured network connection." 0 0 0 \ - bn "Bengali Documentation" ${DIST_DOC_BN:-off} \ - da "Danish Documentation" ${DIST_DOC_DA:-off} \ - de "German Documentation" ${DIST_DOC_DE:-off} \ - el "Greek Documentation" ${DIST_DOC_EL:-off} \ - en "English Documentation (recommended)" ${DIST_DOC_EN:-on} \ - es "Spanish Documentation" ${DIST_DOC_ES:-off} \ - fr "French Documentation" ${DIST_DOC_FR:-off} \ - hu "Hungarian Documentation" ${DIST_DOC_HU:-off} \ - it "Italian Documentation" ${DIST_DOC_IT:-off} \ - ja "Japanese Documentation" ${DIST_DOC_JA:-off} \ - mn "Mongolian Documentation" ${DIST_DOC_MN:-off} \ - nl "Dutch Documentation" ${DIST_DOC_NL:-off} \ - pl "Polish Documentation" ${DIST_DOC_PL:-off} \ - pt "Portuguese Documentation" ${DIST_DOC_PT:-off} \ - ru "Russian Documentation" ${DIST_DOC_RU:-off} \ - sr "Serbian Documentation" ${DIST_DOC_SR:-off} \ - tr "Turkish Documentation" ${DIST_DOC_TR:-off} \ - zh_cn "Simplified Chinese Documentation" ${DIST_DOC_ZH_CN:-off} \ - zh_tw "Traditional Chinese Documentation" ${DIST_DOC_ZH_TW:-off} \ -2>&1 1>&3) -test $? -eq 0 || exit 0 -exec 3>&- - -# Let pkg(8) be able to use name servers -cp ${BSDINSTALL_TMPETC}/resolv.conf ${BSDINSTALL_CHROOT}/etc - -error() { - dialog --backtitle "FreeBSD Installer" --title "Error" --msgbox \ - "Could not install package $1 (`tail -n 1 ${BSDINSTALL_LOG}`)" 0 0 - exit 1 + # Get default status for each language + upper=$( echo "$lang" | awk '{print toupper($0)}' ) + case "$lang" in + en) f_getvar DIST_DOC_$upper:-on status ;; + *) f_getvar DIST_DOC_$upper:-off status + esac + + check_list="$check_list + '$lang' '$desc' '$status' + " # END-QUOTE + done + + local height width rows + eval f_dialog_checklist_size height width rows \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $check_list + local selected + selected=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --checklist \"\$prompt\" \ + $height $width $rows \ + $check_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + f_dialog_menutag_store -s "$selected" + return $retval } +############################################################ MAIN -clear -echo "FreeBSD Installer" -echo "========================" -echo +# +# Initialize +# +f_dialog_title "$msg_freebsd_documentation_installation" +f_dialog_backtitle "$msg_freebsd_installer" +f_mustberoot_init -echo "Please wait while the repository metadata is fetched." -echo "This may take a few moments." +# +# Launch application main menu +# +dialog_menu_main || f_die +f_dialog_menutag_fetch selected -env ASSUME_ALWAYS_YES=1 pkg -c ${BSDINSTALL_CHROOT} install pkg \ - || error pkg +# Let pkg_add be able to use name servers +f_quietly cp -f $BSDINSTALL_TMPETC/resolv.conf $BSDINSTALL_CHROOT/etc/ -for i in $DOCS; do - env ASSUME_ALWAYS_YES=1 pkg -c ${BSDINSTALL_CHROOT} install ${i}-freebsd-doc \ - || error $i-freebsd-doc +# +# Install each of the selected packages +# +for lang in $selected; do + f_package_add $lang-freebsd-doc || return $FAILURE done + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/jail b/usr.sbin/bsdinstall/scripts/jail index af7a00e..e709145 100755 --- a/usr.sbin/bsdinstall/scripts/jail +++ b/usr.sbin/bsdinstall/scripts/jail @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2011 Nathan Whitehorn +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,8 +26,15 @@ # SUCH DAMAGE. # # $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 + +############################################################ MAIN -echo "Begun Installation at $(date)" > $BSDINSTALL_LOG +f_dprintf "Began Installation at %s" "$( date )" export BSDINSTALL_CHROOT=$1 error() { @@ -112,5 +120,8 @@ cp /etc/localtime $1/etc bsdinstall entropy -echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG +f_dprintf "Installation Completed at %s" "$(date)" +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv4 b/usr.sbin/bsdinstall/scripts/netconfig_ipv4 index 452a592..856c999 100755 --- a/usr.sbin/bsdinstall/scripts/netconfig_ipv4 +++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv4 @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2011 Nathan Whitehorn +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,13 +26,15 @@ # 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/dialog.subr -: ${DIALOG_OK=0} -: ${DIALOG_CANCEL=1} -: ${DIALOG_HELP=2} -: ${DIALOG_EXTRA=3} -: ${DIALOG_ITEM_HELP=4} -: ${DIALOG_ESC=255} +############################################################ MAIN INTERFACE=$1 IFCONFIG_PREFIX="$2" @@ -49,8 +52,9 @@ if [ $? -eq $DIALOG_OK ]; then if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0 - dhclient $INTERFACE 2>> $BSDINSTALL_LOG + err=$( dhclient $INTERFACE 2>&1 ) if [ $? -ne 0 ]; then + f_dprintf "%s" "$err" dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0 exec $0 ${INTERFACE} "${IFCONFIG_PREFIX}" fi @@ -86,3 +90,6 @@ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then fi fi +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv6 b/usr.sbin/bsdinstall/scripts/netconfig_ipv6 index dc0d69f..aa1a579 100755 --- a/usr.sbin/bsdinstall/scripts/netconfig_ipv6 +++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv6 @@ -1,8 +1,8 @@ #!/bin/sh #- # Copyright (c) 2011 Nathan Whitehorn -# All rights reserved. # Copyright (c) 2011 The FreeBSD Foundation +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Portions of this software were developed by Bjoern Zeeb @@ -30,19 +30,21 @@ # 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/dialog.subr + +############################################################ MAIN # # TODO: # - Add DHCPv6 support once FreeBSD ships with it. # -: ${DIALOG_OK=0} -: ${DIALOG_CANCEL=1} -: ${DIALOG_HELP=2} -: ${DIALOG_EXTRA=3} -: ${DIALOG_ITEM_HELP=4} -: ${DIALOG_ESC=255} - INTERFACE=$1 case "${INTERFACE}" in "") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ @@ -61,8 +63,9 @@ while : ; do dialog --backtitle 'FreeBSD Installer' \ --infobox "Sending Router Solicitation ..." 0 0 ifconfig ${INTERFACE} inet6 -ifdisabled accept_rtadv up - rtsol -F $INTERFACE 2>> $BSDINSTALL_LOG + err=$( rtsol -F $INTERFACE 2>&1 ) if [ $? -ne 0 ]; then + f_dprintf "%s" "$err" dialog --backtitle 'FreeBSD Installer' --msgbox "SLAAC failed." 0 0 AGAIN=" again" continue @@ -148,3 +151,6 @@ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then fi fi +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/script b/usr.sbin/bsdinstall/scripts/script index 244f345..2915391 100755 --- a/usr.sbin/bsdinstall/scripts/script +++ b/usr.sbin/bsdinstall/scripts/script @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2013 Nathan Whitehorn +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,27 +26,55 @@ # 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/dialog.subr +f_include $BSDCFG_SHARE/variable.subr + +############################################################ CONFIGURATION # VARIABLES: # PARTITIONS # DISTRIBUTIONS # BSDINSTALL_DISTDIR -error() { - test -f $PATH_FSTAB && bsdinstall umount - echo "Installation Error!" - cat $BSDINSTALL_LOG - echo "Installation Error!" +############################################################ GLOBALS + +# +# Strings that should be moved to an i18n file and loaded with f_include_lang() +# +msg_installation_error="Installation Error!" + +############################################################ FUNCTIONS + +error() +{ + [ -f "$PATH_FSTAB" ] && bsdinstall umount + + local file + f_getvar "$VAR_DEBUG_FILE#+" file + if [ "$file" ]; then + f_dialog_title "$msg_installation_error" + f_dialog_textbox "$file" + # No need to restore title, pining for the fjords + fi + exit 1 } +############################################################ MAIN + set -e trap error EXIT SCRIPT="$1" shift -echo "Begun Installation at $(date)" > $BSDINSTALL_LOG +f_dprintf "Began Instalation at %s" "$( date )" rm -rf $BSDINSTALL_TMPETC mkdir $BSDINSTALL_TMPETC @@ -55,6 +84,14 @@ split -a 2 -p '^#!.*' "$SCRIPT" /tmp/bsdinstall-installscript- : ${DISTRIBUTIONS="kernel.txz base.txz"}; export DISTRIBUTIONS export BSDINSTALL_DISTDIR +# Re-initialize a new log if preamble changed BSDINSTALL_LOG +if [ "$BSDINSTALL_LOG" != "${debugFile#+}" ]; then + export debugFile="$BSDINSTALL_LOG" + f_quietly f_debug_init + # NB: Being scripted, let debug go to terminal for invalid debugFile + f_dprintf "Began Instalation at %s" "$( date )" +fi + # Make partitions rm -f $PATH_FSTAB touch $PATH_FSTAB @@ -86,6 +123,10 @@ fi bsdinstall entropy bsdinstall umount -echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG +f_dprintf "Installation Completed at %s" "$( date )" trap true EXIT + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/wlanconfig b/usr.sbin/bsdinstall/scripts/wlanconfig index 0a3599c..a1ccaf7 100755 --- a/usr.sbin/bsdinstall/scripts/wlanconfig +++ b/usr.sbin/bsdinstall/scripts/wlanconfig @@ -1,6 +1,7 @@ #!/bin/sh #- # Copyright (c) 2011 Nathan Whitehorn +# Copyright (c) 2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -25,6 +26,13 @@ # SUCH DAMAGE. # # $FreeBSD$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 + +############################################################ MAIN echo -n > $BSDINSTALL_TMPETC/wpa_supplicant.conf chmod 0600 $BSDINSTALL_TMPETC/wpa_supplicant.conf @@ -50,7 +58,8 @@ if [ $? -ne 0 -a -z $BSDINSTALL_CONFIGCURRENT ]; then exit 1 fi -wpa_cli scan >>$BSDINSTALL_LOG +output=$( wpa_cli scan 2>&1 ) +f_dprintf "%s" "$output" dialog --backtitle "FreeBSD Installer" --title "Scanning" --ok-label "Skip" \ --pause "Waiting 5 seconds to scan for wireless networks..." \ 9 40 5 || exit 1 @@ -132,6 +141,13 @@ echo "network={ }" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf # Bring up new network -test ! -z $BSDINSTALL_CONFIGCURRENT && wpa_cli reconfigure >>$BSDINSTALL_LOG +if [ "$BSDINSTALL_CONFIGCURRENT" ]; then + output=$( wpa_cli reconfigure 2>&1 ) + f_dprintf "%s" "$output" +fi exit 0 + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot index 4d14e22..2248a0d 100755 --- a/usr.sbin/bsdinstall/scripts/zfsboot +++ b/usr.sbin/bsdinstall/scripts/zfsboot @@ -47,7 +47,7 @@ f_include $BSDCFG_SHARE/variable.subr # # Default name for the boot environment parent dataset # -: ${ZFSBOOT_BEROOT_NAME:=bootenv} +: ${ZFSBOOT_BEROOT_NAME:=ROOT} # # Default name for the primany boot environment @@ -67,7 +67,7 @@ f_include $BSDCFG_SHARE/variable.subr # # Should we use geli(8) to encrypt the drives? # -: ${ZFSBOOT_GELI_ENCRYPTION:=} +: ${ZFSBOOT_GELI_ENCRYPTION=} # # Default name the unencrypted pool when using geli(8) to encrypt the drives @@ -101,7 +101,7 @@ f_include $BSDCFG_SHARE/variable.subr : ${ZFSBOOT_SWAP_SIZE:=2g} # -# Default ZFS layout for root zpool +# 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. @@ -119,69 +119,110 @@ f_isset ZFSBOOT_DATASETS || ZFSBOOT_DATASETS=" # Don't mount /usr so that 'base' files go to the BEROOT /usr mountpoint=/usr,canmount=off - /usr/local # local files (i.e. from packages) separate from base system - # Home directories separated so they are common to all BEs - /usr/home setuid=off + /usr/home # NB: /home is a symlink to /usr/home # 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 # Source tree (compressed) /usr/src compression=lz4,exec=off,setuid=off - /usr/obj # Object files # 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 +# +# 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_PASSWORD_INIT='geli init -b -B "%s" -e %s -J - -K "%s" -l 256 -s 4096 "%s"' +GNOP_CREATE='gnop create -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_SET_ACTIVE='gpart set -a active -i %s "%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"' +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_EXPORT='zpool export "%s"' +ZPOOL_IMPORT_WITH_OPTIONS='zpool import %s "%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="Change Selection" +msg_change_selection="Change Selection" 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_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 gnop(8) to configure forced 4K sector alignment" msg_freebsd_installer="FreeBSD Installer" -msg_geli_encryption="Encrypt Disks?" -msg_geli_encryption_help="Use geli(8) to encrypt all data partitions" 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 the selected disks, 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_disk_argument="Invalid disk argument \`%s'" +msg_invalid_geli_boot_size="Invalid geli(8) boot size \`%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_invalid_virtual_device_type_help="Select another Virtual Device type or Cancel to\nreturn to the ZFS menu. From there you can select\nmore disks or rescan for additional devices." -msg_last_chance_are_you_sure="Last Chance! Are you sure you want to destroy the current contents of the following disks:\n%s" -msg_last_chance_are_you_sure_color="\\\\ZrLast Chance!\\\\ZR Are you \\\\Z1sure\\\\Zn you want to \\\\Zr\\\\Z1destroy\\\\Zn the current contents of the following disks:\n%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 wanted)" +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" @@ -191,6 +232,8 @@ msg_please_select_one_or_more_disks="Please select one or more disks to create a 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" @@ -207,11 +250,12 @@ msg_stripe_desc="Stripe - No Redundancy" msg_stripe_help="[1+ Disks] Striping provides maximum storage but no redundancy" 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 (%s) partitions, which would take\n50%% or more (not recommended) of each of the following\nselected disk devices:\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of devices." +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_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" -msg_zfs_vdev_type="ZFS VDev Type" -msg_zfs_vdev_type_help="Select type of ZFS Virtual Device to create" ############################################################ FUNCTIONS @@ -228,26 +272,26 @@ dialog_menu_main() local usegeli="$msg_no" [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ] && force4k="$msg_yes" [ "$ZFSBOOT_GELI_ENCRYPTION" ] && usegeli="$msg_yes" + local disks n=$( set -- $ZFSBOOT_DISKS; echo $# ) + { [ $n -eq 1 ] && disks=disk; } || disks=disks # grammar local menu_list=" - '>>> $msg_create' '$msg_create_desc' - '$msg_create_help' + '>>> $msg_install' '$msg_install_desc' + '$msg_install_help' + 'T $msg_pool_type_disks' '$ZFSBOOT_VDEV_TYPE: $n $disks' + '$msg_pool_type_disks_help' '- $msg_rescan_devices' '*' '$msg_rescan_devices_help' '- $msg_disk_info' '*' '$msg_disk_info_help' - '1 $msg_pool_name' '$ZFSBOOT_POOL_NAME' + 'N $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_type_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' + 'E $msg_encrypt_disks' '$usegeli' + '$msg_encrypt_disks_help' + 'P $msg_partition_scheme' '$ZFSBOOT_PARTITION_SCHEME' '$msg_partition_scheme_help' - '7 $msg_swap_size' '$ZFSBOOT_SWAP_SIZE' + 'S $msg_swap_size' '$ZFSBOOT_SWAP_SIZE' '$msg_swap_size_help' " # END-QUOTE local defaultitem= # Calculated below @@ -284,158 +328,279 @@ dialog_menu_main() return $retval } -# dialog_edit_disks +# dialog_last_chance $disks ... # -# Edit the list of disks to be used by the ZFS boot pool. +# 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_edit_disks() +dialog_last_chance() { 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 + local prompt # Calculated below + local hline="$hline_arrows_tab_enter" - # Lets sort the disks array to be more user friendly - disks=$( echo "$disks" | tr ' ' '\n' | sort | tr '\n' ' ' ) + local height=8 width=50 prefix=" " + local plen=${#prefix} list= line= + local max_width=$(( $width - 3 - $plen )) - # - # 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 + 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 - # - # 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" + 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 - # - # 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 $DIALOG_OK + # 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_vdev +# dialog_menu_layout # -# Prompt the user to select a a Virtual Device type. +# 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_vdev() +dialog_menu_layout() { + local funcname=dialog_menu_layout 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=" + 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" - local defaultitem="$ZFSBOOT_VDEV_TYPE" - local hline="$hline_arrows_tab_enter" - local error_msg revalidate_choice - - local mheight mwidth mrows - eval f_dialog_menu_size mheight mwidth mrows \ - \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" $menu_list - local iheight iwidth - f_dialog_infobox_size iheight iwidth \ - "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$msg_processing_selection" - - local menu_choice - menu_choice=$( eval $DIALOG \ - --title \"\$title\" \ - --backtitle \"\$btitle\" \ - --hline \"\$hline\" \ - --ok-label \"\$msg_ok\" \ - --cancel-label \"\$msg_cancel\" \ - --item-help \ - --default-item \"\$defaultitem\" \ - --menu \"\$prompt\" \ - $mheight $mwidth $mrows \ - $menu_list \ - --and-widget \ - ${USE_XDIALOG:+--no-buttons} \ - --infobox \"\$msg_processing_selection\" \ - $iheight $iwidth \ - 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD - ) || return $FAILURE - f_dialog_data_sanitize menu_choice - sleep 0.5 # Give time to read `--and-widget --info-box' - - # Make sure we have enough disks for the desired vdev type - case "$menu_choice" in - stripe) want_disks=1 ;; - mirror) want_disks=2 ;; - raidz1) want_disks=3 ;; - raidz2) want_disks=4 ;; - raidz3) want_disks=5 ;; + # Warn the user if vdev type is not valid + case "$ZFSBOOT_VDEV_TYPE" in + stripe|mirror|raidz1|raidz2|raidz3) : known good ;; *) - f_show_msg "$msg_invalid_virtual_device_type" \ - "$menu_choice" - continue + 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 - if [ $ndisks -lt $want_disks ]; then - msg_yes="$msg_change" msg_no="$msg_cancel" f_yesno \ - "%s: $msg_not_enough_disks_selected\n%s" \ - "$menu_choice" $ndisks $want_disks \ - "$msg_invalid_virtual_device_type_help" || - return $FAILURE - dialog_menu_vdev - else - ZFSBOOT_VDEV_TYPE="$menu_choice" + + # 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= + f_device_find "" $DEVICE_TYPE_DISK disks + f_dprintf "$funcname: disks=[%s]" "$disks" + 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 + disks=$( echo "$disks" | tr ' ' '\n' | sort | tr '\n' ' ' ) + + # + # 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 + 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 + local 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 + local disk valid_disks= + local all_valid=${ZFSBOOT_DISKS:+1} # optimism + for disk in $ZFSBOOT_DISKS; do + if f_struct device_$disk; 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 + ndisks=$( set -- $ZFSBOOT_DISKS; echo $# ) + [ $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 + # + local breakout= + while :; do + # Loop over list of available disks, resetting state + for disk in $disks; do unset _${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 + local _${disk}_status=on + done + + # Create the checklist menu of discovered disk devices + disk_check_list= + for disk in $disks; do + local desc= + device_$disk get desc desc + f_shell_escape "$desc" desc + f_getvar _${disk}_status:-off onoff + disk_check_list="$disk_check_list + $disk '$desc' $onoff" + done + + local height width rows + eval f_dialog_checklist_size height width rows \ + \"\$title\" \"\$btitle\" \"\$prompt\" \ + \"\$hline\" $disk_check_list + + selections=$( eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --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" + + ndisks=$( set -- $ZFSBOOT_DISKS; echo $# ) + [ $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 } # zfs_create_diskpart $disk $index @@ -449,188 +614,297 @@ dialog_menu_vdev() # zfs_create_diskpart() { - local disk="$1" index="$2" local funcname=zfs_create_diskpart + local disk="$1" index="$2" local disksize partsize # Check arguments - [ "$disk" -a "$index" ] || return $FAILURE + 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_quietly gpart destroy -F $disk + f_quietly graid destroy $disk f_quietly zpool labelclear -f /dev/$disk # Kill it with fire # Make doubly-sure backup GPT is destroyed - f_quietly gpart create -s gpt $disk || return $FAILURE - f_quietly gpart destroy -F $disk || return $FAILURE + f_quietly gpart create -s gpt $disk + f_quietly gpart destroy -F $disk # Calculate partition size given desired amount of swap - device_$disk get capacity disksize || return $FAILURE + f_dprintf "$funcname: Getting disk capactiy for \`%s'" "$disk" + if ! device_$disk get capacity disksize; then + f_dprintf "$funcname: Unable to get disk capacity of \`%s'" \ + "$disk" + msg_error="$msg_error: $funcname" \ + f_show_err "$msg_unable_to_get_disk_capacity" "$disk" + return $FAILURE + fi partsize=$(( $disksize - $swapsize )) + f_dprintf "$funcname: disksize=[%s] partsize=[%s]" \ + "$disksize" "$partsize" # # Lay down the desired type of partition scheme # local setsize mbrindex case "$ZFSBOOT_PARTITION_SCHEME" in - ""|GPT) + ""|GPT) f_dprintf "$funcname: Creating GPT layout..." # # 1. Create GPT layout using labels # - gpart create -s gpt $disk || return $FAILURE + f_eval_catch $funcname gpart "$GPART_CREATE" gpt \$disk || + return $FAILURE # # 2. Add small freebsd-boot partition labeled `boot#' # - gpart add -l gptboot$index -t freebsd-boot -s 512k $disk || - return $FAILURE - gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 $disk || - return $FAILURE + 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 # zpool will use the `zfs#' GPT labels bootpart=p2 targetpart=p2 - # Change things around if we are using GELI + # Change things around if we are using geli(8) if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then bootpart=p2 targetpart=p3 partsize=$(( $partsize - $gelisize )) - gpart add -l boot$index -t freebsd-zfs \ - -s ${gelisize}b -a 1m $disk || return $FAILURE + f_dprintf "$funcname: gelisize=[%s]" \ + "gelisize=[$gelisize]" + f_eval_catch $funcname gpart \ + "$GPART_ADD_LABEL_WITH_SIZE" boot\$index \ + freebsd-zfs \${gelisize}b \$disk || + return $FAILURE + # Pedantically nuke any old labels, stop geli - f_quietly zpool labelclear -f /dev/$disk$bootpart - f_quietly geli detach -f /dev/$disk$targetpart + f_quietly zpool labelclear -f "/dev/$disk$bootpart" + f_quietly geli detach -f "/dev/$disk$targetpart" fi # # 3. Add freebsd-zfs partition labeled `zfs#' for zpool # NOTE: Using above calculated partsize to leave room for swap. # - [ $swapsize -gt 0 ] && setsize="-s ${partsize}b" - gpart add -l zfs$index -t freebsd-zfs $setsize -a 1m $disk || - return $FAILURE - f_quietly zpool labelclear -f /dev/$disk$targetpart # Pedantic + if [ ${swapsize:-0} -gt 0 ]; then + f_dprintf "$funcname: partsize=[%s]" \ + "partsize=[$partsize]" + f_eval_catch $funcname gpart \ + "$GPART_ADD_LABEL_WITH_SIZE" zfs\$index \ + freebsd-zfs \${partsize}b \$disk || + return $FAILURE + else + f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ + zfs\$index freebsd-zfs \$disk || + return $FAILURE + fi + f_quietly zpool labelclear -f "/dev/$disk$targetpart" # # 4. Add freebsd-swap partition labeled `swap#' # if [ $swapsize -gt 0 ]; then - gpart add -l swap$index -t freebsd-swap -a 1m $disk || - return $FAILURE + f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \ + swap\$index freebsd-swap \$disk || + return $FAILURE # Update fstab(5) - printf "$fstab_fmt" \ - /dev/gpt/swap$index none swap sw 0 0 \ - >> $BSDINSTALL_TMPETC/fstab || return $FAILURE + f_eval_catch $funcname printf "$PRINTF_FSTAB" \ + /dev/gpt/swap\$index none swap sw 0 0 \ + \$BSDINSTALL_TMPETC/fstab || + return $FAILURE fi ;; - MBR) + MBR) f_dprintf "$funcname: Creating MBR layout..." # # 1. Create MBR layout (no labels) # - gpart create -s mbr $disk || return $FAILURE - gpart bootcode -b /boot/boot0 $disk || return $FAILURE + 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 # - gpart add -t freebsd $disk || return $FAILURE - gpart set -a active -i 1 $disk || return $FAILURE + f_eval_catch $funcname gpart "$GPART_ADD" freebsd \$disk || + return $FAILURE + f_eval_catch $funcname gpart "$GPART_SET_ACTIVE" 1 \$disk || + return $FAILURE f_quietly zpool labelclear -f /dev/${disk}s1 # Pedantic f_quietly gpart destroy -F ${disk}s1 # Pedantic # - # 3. Write BSD sceme to the freebsd slice + # 3. Write BSD scheme to the freebsd slice # - gpart create -s BSD ${disk}s1 || return $FAILURE + f_eval_catch $funcname gpart "$GPART_CREATE" BSD \${disk}s1 || + return $FAILURE # zpool will use s1a (no labels) bootpart=s1a targetpart=s1a mbrindex=1 - # Change things around if we are using GELI + # Change things around if we are using geli(8) if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then bootpart=s1a targetpart=s1d partsize=$(( $partsize - $gelisize )) mbrindex=4 # If this is s1a then make the zpool s1d - gpart add -t freebsd-zfs -i 1 -s ${gelisize}b \ - ${disk}s1 || return $FAILURE + f_dprintf "$funcname: mbrindex=[%s] gelisize=[%s]" \ + "$mbrindex" "$gelisize" + f_eval_catch $funcname gpart \ + "$GPART_ADD_INDEX_WITH_SIZE" \ + 1 freebsd-zfs \${gelisize}b \${disk}s1 || + return $FAILURE # Pedantically nuke any old labels, stop geli - f_quietly zpool labelclear -f /dev/$disk$bootpart - f_quietly geli detach -f /dev/$disk$targetpart + f_quietly zpool labelclear -f "/dev/$disk$bootpart" + f_quietly geli detach -f "/dev/$disk$targetpart" fi # # 4. Partition the BSD slice for ZFS # NOTE: Using above calculated partsize to leave room for swap. # - [ $swapsize -gt 0 ] && setsize="-s ${partsize}b" - gpart add -t freebsd-zfs -i $mbrindex $setsize ${disk}s1 || - return $FAILURE + if [ ${swapsize:-0} -gt 0 ]; then + f_dprintf "$funcname: mbrindex=[%s] partsize=[%s]" \ + "$mbrindex" "$partsize" + f_eval_catch $funcname gpart \ + "$GPART_ADD_INDEX_WITH_SIZE" \ + \$mbrindex freebsd-zfs \${partsize}b \ + \${disk}s1 || return $FAILURE + else + f_dprintf "$funcname: mbrindex=[%s]" "$mbrindex" + f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \ + \$mbrindex freebsd-zfs \${disk}s1 || + return $FAILURE + fi f_quietly zpool labelclear -f /dev/$disk$targetpart # Pedantic # # 5. Add freebsd-swap partition # if [ $swapsize -gt 0 ]; then - gpart add -t freebsd-swap -i 2 ${disk}s1 || - return $FAILURE + f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \ + 2 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 + f_eval_catch $funcname printf "$PRINTF_FSTAB" \ + /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 # $ZFSBOOT_PARTITION_SCHEME return $SUCCESS } -# zfs_create_boot $poolname $vdev_type $real_disks ... +# 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 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 + local poolname="$1" vdev_type="$2" local bootpart targetpart shift 2 # name vdev_type # We may need this later - local realdisks=$* + local disks="$*" # Pedantic checks; should never be seen if [ ! "$poolname" ]; then - echo "$funcname: NULL poolname" >&2 + f_dprintf "$funcname: NULL poolname" + msg_error="$msg_error: $funcname" \ + f_show_err "$msg_null_poolname" return $FAILURE fi if [ $# -lt 1 ]; then - echo "$funcname: missing disk arguments" >&2 + 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]" \ + "$poolname" "$vdev_type" # Initialize fstab(5) - printf "$fstab_fmt" \ - "# Device" Mountpoint FStype Options Dump "Pass#" \ - >> $BSDINSTALL_TMPETC/fstab || return $FAILURE + 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 swapsize/gelisize values..." local swapsize gelisize - f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize || return $FAILURE - f_expand_number "$ZFSBOOT_GELI_BOOT_SIZE" gelisize || return $FAILURE + 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_GELI_BOOT_SIZE" gelisize; then + f_dprintf "$funcname: Invalid geli(8) boot size \`%s'" \ + "$ZFSBOOT_GELI_BOOT_SIZE" + f_show_err "$msg_invalid_geli_boot_size" \ + "$ZFSBOOT_GELI_BOOT_SIZE" + return $FAILURE + fi + f_dprintf "$funcname: ZFSBOOT_SWAP_SIZE=[%s] swapsize=[%s]" \ + "$ZFSBOOT_SWAP_SIZE" "$swapsize" + f_dprintf "$funcname: ZFSBOOT_GELI_BOOT_SIZE=[%s] gelisize=[%s]" \ + "$ZFSBOOT_GELI_BOOT_SIZE" "$gelisize" # Prepare the disks + f_dprintf "$funcname: Preparing disk partitions for ZFS pool..." local n=0 for disk in $*; do zfs_create_diskpart $disk $n || return $FAILURE @@ -640,27 +914,35 @@ zfs_create_boot() # 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 + f_dprintf "$funcname: Copying MBR boot loader to disks..." + f_dprintf "$funcname: disks=[%s]" "$disks" + for disk in $disks; do + f_dprintf "$funcname: disk=[%s]" "$disk" + f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ + /boot/zfsboot /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= + local part="$targetpart" new_list= + + # We don't gnop the encrypted partition because geli will do + # this for us gnop the unencrypted disk + [ "$ZFSBOOT_GELI_ENCRYPTION" ] && part="$bootpart" + + f_dprintf "$funcname: Applying 4k alignment with gnop(8)..." + f_dprintf "$funcname: *=[%s]" "$*" for disk in $*; do + f_dprintf "$funcname: disk=[%s] part=[%s]" \ + "$disk" "$part" + f_eval_catch $funcname gnop "$GNOP_CREATE" \ + \$disk\$part || return $FAILURE 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" + unenc_list="$unenc_list $disk$part.nop" else - gnop create -S 4096 $disk$targetpart || - return $FAILURE new_list="$new_list $disk$targetpart.nop" fi done @@ -683,57 +965,96 @@ zfs_create_boot() local geli_pool="$BSDINSTALL_CHROOT/$ZFSBOOT_GELI_POOL_NAME" local key="$ZFSBOOT_GELI_KEY_FILE" + f_dprintf "$funcname: Setting up disk encryption..." + # Create the parent directories for our unencrypted pool f_quietly umount /mnt - mount -t tmpfs none $BSDINSTALL_CHROOT || return $FAILURE + f_eval_catch $funcname mount "$MOUNT_TYPE" tmpfs none \ + \$BSDINSTALL_CHROOT || return $FAILURE # Create mirror across the unencrypted partition on all disks [ $( set -- $unenc_list; echo $# ) -gt 1 ] && bootvdev=mirror - zpool create -o altroot=$BSDINSTALL_CHROOT \ - -m "/$ZFSBOOT_GELI_POOL_NAME" -f \ - "$ZFSBOOT_GELI_POOL_NAME" $bootvdev $unenc_list || - return $FAILURE - mkdir -p $geli_pool/boot || return $FAILURE + f_dprintf "$funcname: %s %s %s" \ + "ZFSBOOT_GELI_POOL_NAME=[$ZFSBOOT_GELI_POOL_NAME]" \ + "bootvdev=[$bootvdev]" "unenc_list=[$unenc_list]" + f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ + "-o altroot=\"\$BSDINSTALL_CHROOT\" + -m \"/\$ZFSBOOT_GELI_POOL_NAME\" -f" \ + \$ZFSBOOT_GELI_POOL_NAME \$bootvdev \ + \$unenc_list || return $FAILURE + f_dprintf "$funcname: geli_pool=[%s]" "$geli_pool" + f_eval_catch $funcname mkdir "$MKDIR_P" \$geli_pool/boot || + return $FAILURE # Generate an encryption key using random(4) - dd if=/dev/random of="$geli_pool/$key" bs=4096 count=1 || - return $FAILURE + f_dprintf "$funcname: key=[%s]" "$key" + f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \ + /dev/random \$geli_pool/\$key "bs=4096 count=1" || + return $FAILURE # Create the geli(8) GEOMS local geli_list - msg_enter_new_password="$msg_geli_password" \ - f_dialog_input_password || return $FAILURE - f_dialog_info "$msg_geli_setup" \ - 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD - for disk in $realdisks; do - echo "$pw_password" | geli init -b -B \ - "$geli_pool/boot/$disk$targetpart.eli" \ - -e AES-XTS -J - -K "$geli_pool/$key" -l 256 \ - -s 4096 $disk$targetpart || return $FAILURE - echo "$pw_password" | geli attach -j - \ - -k "$geli_pool/$key" $disk$targetpart || + 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 + f_dprintf "$funcname: disks=[%s]" "$disks" + for disk in $disks; do + f_dprintf "$funcname: disk=[%s] targetpart=[%s]" \ + "$disk" "$targetpart" + f_dialog_info "$msg_geli_setup" \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + if ! echo "$pw_password" | f_eval_catch $funcname \ + geli "$GELI_PASSWORD_INIT" \ + \$geli_pool/boot/\$disk\$targetpart.eli \ + AES-XTS \$geli_pool/\$key \$disk\$targetpart + then + f_interactive || f_die + return $FAILURE + fi + if ! echo "$pw_password" | f_eval_catch $funcname \ + geli "$GELI_ATTACH" \$geli_pool/\$key \ + \$disk\$targetpart + then + f_interactive || f_die return $FAILURE + fi geli_list="$geli_list $disk$targetpart.eli" done set -- $geli_list - zfs unmount "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE + f_eval_catch $funcname zfs "$ZFS_UNMOUNT" \ + \$ZFSBOOT_GELI_POOL_NAME || return $FAILURE f_quietly umount /mnt # done with tmpfs fi # # Create the ZFS pool with desired type and disk devices # - zpool create -o altroot=$BSDINSTALL_CHROOT -m none -f \ - "$poolname" $vdev_type $* || return $FAILURE + local vdevs="$*" + f_dprintf "$funcname: Creating boot pool..." + f_dprintf "poolname=[%s] vdev_type=[%s] vdevs=[%s]" \ + "$poolname" "$vdev_type" "$vdevs" + f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \ + "-o altroot=\"\$BSDINSTALL_CHROOT\" -m none -f" \ + \$poolname \$vdev_type \$vdevs # Customize the zpool a bit... - zfs set checksum=fletcher4 "$poolname" || return $FAILURE - zfs set atime=off "$poolname" || return $FAILURE + local option + f_dprintf "$funcname: Setting miscellaneous options on boot pool..." + for option in checksum=fletcher4 atime=off; do + f_dprintf "$funcname: option=[%s]" "$option" + f_eval_catch $funcname zfs "$ZFS_SET" \$option \$poolname || + return $FAILURE + done # # Create ZFS dataset layout within the new boot 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 @@ -750,30 +1071,50 @@ zfs_create_boot() # 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 + f_dprintf "$funcname: dataset=[%s] options=[%s]" \ + "$dataset" "$options" + f_eval_catch $funcname zfs "$ZFS_CREATE_WITH_OPTIONS" \ + "\${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 + f_dprintf "$funcname: Modifying directory permissions..." + local dir + for dir in /tmp /var/tmp; do + f_dprintf "$funcname: dir=[%s]" "$dir" + f_eval_catch $funcname chmod "$CHMOD_MODE" 1777 \ + \$BSDINSTALL_CHROOTDIR\$dir || return $FAILURE + done # Create symlink(s) - [ "$ZFSBOOT_GELI_ENCRYPTION" ] && - { ln -s $ZFSBOOT_GELI_POOL_NAME/boot $BSDINSTALL_CHROOT/boot || - return $FAILURE; } + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + f_dprintf "$funcname: Creating /boot symlink for GELI..." + f_eval_catch $funcname ln "$LN_SF" \ + \$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 + f_dprintf "$funcname: Setting bootfs property..." + f_dprintf "$funcname: %s %s" \ + "ZFSBOOT_BEROOT_NAME=[$ZFSBOOT_BEROOT_NAME]" \ + "ZFSBOOT_BOOTFS_NAME=[$ZFSBOOT_BOOTFS_NAME]" + f_eval_catch $funcname zpool "$ZPOOL_SET" \ + bootfs=\"\$poolname/\$ZFSBOOT_BEROOT_NAME/\$ZFSBOOT_BOOTFS_NAME\" \ + \$poolname || return $FAILURE # Export the pool(s) - zpool export "$poolname" || return $FAILURE - [ "$ZFSBOOT_GELI_ENCRYPTION" ] && - { zpool export "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE; } + f_dprintf "$funcname: Temporarily exporting ZFS pool(s)..." + f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \$poolname || + return $FAILURE + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \ + \$ZFSBOOT_GELI_POOL_NAME || return $FAILURE + fi # Destroy the gnop devices (if enabled) - for disk in ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:+$realdisks}; do + for disk in ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:+$disks}; do if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then f_quietly gnop destroy $disk$bootpart.nop else @@ -783,65 +1124,90 @@ zfs_create_boot() # MBR boot loader hack part 2 if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then + f_dprintf "$funcname: Updating MBR boot loader on disks..." + f_dprintf "$funcname: disks=[%s]" # 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 + for disk in $disks; do + f_dprintf "$funcname: disk=[%s] bootpart=[%s]" \ + "$disk" "$bootpart" + 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) - zpool import -o altroot=$BSDINSTALL_CHROOT $poolname || return $FAILURE - [ "$ZFSBOOT_GELI_ENCRYPTION" ] && - { zpool import -o altroot=$BSDINSTALL_CHROOT \ - "$ZFSBOOT_GELI_POOL_NAME" || return $FAILURE; } + f_dprintf "$funcname: Re-importing ZFS pool(s)..." + f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ + "-o altroot=\"\$BSDINSTALL_CHROOT\"" \$poolname || + return $FAILURE + if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then + f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \ + "-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 + f_dprintf "$funcname: Configuring zpool.cache..." + 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\" \ + \$poolname || return $FAILURE # Last, but not least... required lines for rc.conf(5)/loader.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 + 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" 'zfs_load=\"YES\"' \ + \$BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE # We're all done unless we should go on to do encryption [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS - # Some additional GELI requirements for loader.conf(5) - echo 'zpool_cache_load="YES"' \ - >> $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE - echo 'zpool_cache_type="/boot/zfs/zpool.cache"' \ - >> $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE - echo 'zpool_cache_name="/boot/zfs/zpool.cache"' \ - >> $BSDINSTALL_TMPBOOT/loader.conf.zfs || 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 # # Configure geli(8)-based encryption # - echo 'aesni_load="YES"' \ - > $BSDINSTALL_TMPBOOT/loader.conf.aesni || return $FAILURE - echo 'geom_eli_load="YES"' \ - > $BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE - printf 'vfs.root.mountfrom="zfs:%s/%s/%s"\n' "$poolname" \ - "$ZFSBOOT_BEROOT_NAME" "$ZFSBOOT_BOOTFS_NAME" \ - > $BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE - for disk in $realdisks; do - printf 'geli_%s_keyfile0_load="YES"\n' \ - "$disk$targetpart" \ - > $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || + 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 printf "$PRINTF_CONF" vfs.root.mountfrom \ + '"zfs:$poolname/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOT_FSNAME"' \ + \$BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE + f_dprintf "$funcname: disks=[%s]" "$disks" + for disk in $disks; do + f_dprintf "$funcname: %s %s %s" \ + "disk=[$disk]" "targetpart=[$targetpart]" \ + "ZFSBOOT_GELI_KEY_FILE=[$ZFSBOOT_GELI_KEY_FILE]" + f_eval_catch $funcname printf "$PRINTF_CONF" \ + geli_%s_keyfile0_load '"$disk$targetpart" YES' \ + \$BSDINSTALL_TMPBOOT/loader.conf.\$disk\$targetpart || return $FAILURE - printf 'geli_%s_keyfile0_type="%s:geli_keyfile0"\n' \ - "$disk$targetpart" "$disk$targetpart" \ - >> $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || + f_eval_catch $funcname printf "$PRINTF_CONF" \ + geli_%s_keyfile0_type \ + '"$disk$targetpart" "$disk$targetpart"' \ + \$BSDINSTALL_TMPBOOT/loader.conf.\$disk\$targetpart || return $FAILURE - printf 'geli_%s_keyfile0_name="%s"\n' \ - "$disk$targetpart" "$ZFSBOOT_GELI_KEY_FILE" \ - >> $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart || + 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 @@ -886,64 +1252,46 @@ f_dialog_backtitle "$msg_freebsd_installer" ! f_interactive && f_zfsinteractive && unset $VAR_NONINTERACTIVE # +# Debugging +# +f_dprintf "BSDINSTALL_CHROOT=[%s]" "$BSDINSTALL_CHROOT" +f_dprintf "BSDINSTALL_TMPETC=[%s]" "$BSDINSTALL_TMPETC" +f_dprintf "PRINTF_FSTAB=[%s]" "$PRINTF_FSTAB" + +# # 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_create" + mtag=">>> $msg_install" else dialog_menu_main retval=$? f_dialog_menutag_fetch mtag fi - f_dprintf "retval=%u mtag=[%s]" $reval "$mtag" + f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" [ $retval -eq $DIALOG_OK ] || f_die case "$mtag" in - ">>> $msg_create") + ">>> $msg_install") # # 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" - f_interactive || f_die - 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" - f_interactive || f_die - 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" - f_interactive || f_die - continue - esac - if [ $ndisks -lt $want_disks ]; then - f_show_msg "%s: $msg_not_enough_disks_selected" \ - "$ZFSBOOT_VDEV_TYPE" "$want_disks" - f_interactive || f_die + 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_GELI_BOOT_SIZE" gelisize @@ -951,18 +1299,22 @@ while :; do minsize=$swapsize teeny_disks= [ "$ZFSBOOT_GELI_ENCRYPTION" ] && minsize=$(( $minsize + $gelisize )) - for disk in $real_disks; do + for disk in $ZFSBOOT_DISKS; do device_$disk get capacity disksize || continue disksize=$(( $disksize - $minsize )) [ $disksize -lt $minsize ] && teeny_disks="$teeny_disks $disk" done if [ "$teeny_disks" ]; then - f_show_msg "$msg_these_disks_are_too_small" \ + f_dprintf "swapsize=[%s] gelisize[%s]" \ + "$ZFSBOOT_SWAP_SIZE" \ + "$ZFSBOOT_GELI_BOOT_SIZE" + f_dprintf "These disks are too small: %s" \ + "$teeny_disks" + f_show_err "$msg_these_disks_are_too_small" \ "$ZFSBOOT_SWAP_SIZE" \ "$ZFSBOOT_GELI_BOOT_SIZE" \ "$teeny_disks" - f_interactive || f_die continue fi fi @@ -970,14 +1322,8 @@ while :; do # # Last Chance! # - if [ ! "$USE_XDIALOG" ]; then - f_interactive && DIALOG="$DIALOG --colors" f_noyes \ - "$msg_last_chance_are_you_sure_color" \ - "$ZFSBOOT_DISKS" || continue - else - f_interactive && f_noyes \ - "$msg_last_chance_are_you_sure" \ - "$ZFSBOOT_DISKS" || continue + if f_interactive; then + dialog_last_chance $ZFSBOOT_DISKS || continue fi # @@ -989,16 +1335,17 @@ while :; do # 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" - f_interactive || f_die - continue - fi + 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") @@ -1008,8 +1355,6 @@ while :; do "$ZFSBOOT_POOL_NAME" && 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 @@ -1018,7 +1363,7 @@ while :; do ZFSBOOT_GNOP_4K_FORCE_ALIGN=1 fi ;; - ?" $msg_geli_encryption") + ?" $msg_encrypt_disks") # Toggle the variable referenced both by the menu and later if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then ZFSBOOT_GELI_ENCRYPTION= |