summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authordteske <dteske@FreeBSD.org>2013-10-11 23:12:05 +0000
committerdteske <dteske@FreeBSD.org>2013-10-11 23:12:05 +0000
commitc8e8fef3a6ed1142b7f9f4081f1db75bca9b1770 (patch)
treee91e00a2760af23e32a9218c6d71595249a35fe7 /usr.sbin
parentf6c283672e887f04524b02fb957fbfd53a349f6e (diff)
downloadFreeBSD-src-c8e8fef3a6ed1142b7f9f4081f1db75bca9b1770.zip
FreeBSD-src-c8e8fef3a6ed1142b7f9f4081f1db75bca9b1770.tar.gz
MFC revisions 256321-256323,256331,256333,256335,256343:
Bring in a new zfsboot auto script for performing automatic setup of a boot pool (optionally encrypted) with many other options, validations, features. Originally submitted by Allan Jude; modified in collaboration. MFC revisions 256325,256330,256345: Rewrite the keymap selection menu to display keymaps and provide a test mechanism. Test mechanism originally submitted by Warren Block; modified. MFC r256347: Prominently display "Wireless" for each wireless network interface. Part of PR bin/161547; submitted by Warren Block; slightly modified. MFC r256348: Remove the dumpdev configuration dialog, merge it into the regular services configuration and enable it by default. Originally submitted by Allan Jude; slightly modified. PR: bin/161547 Submitted by: Allan Jude, Warren Block <wblock@wonkity.com> In collaboration with: Allan Jude <freebsd@allanjude.com> Approved by: re (glebius)
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bsdconfig/include/messages.subr1
-rw-r--r--usr.sbin/bsdconfig/share/Makefile5
-rw-r--r--usr.sbin/bsdconfig/share/device.subr121
-rw-r--r--usr.sbin/bsdconfig/share/dialog.subr15
-rw-r--r--usr.sbin/bsdconfig/share/keymap.subr262
-rw-r--r--usr.sbin/bsdconfig/share/strings.subr111
-rw-r--r--usr.sbin/bsdconfig/share/variable.subr17
-rwxr-xr-xusr.sbin/bsdinstall/bsdinstall2
-rw-r--r--usr.sbin/bsdinstall/scripts/Makefile2
-rwxr-xr-xusr.sbin/bsdinstall/scripts/auto36
-rwxr-xr-xusr.sbin/bsdinstall/scripts/config5
-rwxr-xr-xusr.sbin/bsdinstall/scripts/keymap214
-rwxr-xr-xusr.sbin/bsdinstall/scripts/netconfig12
-rwxr-xr-xusr.sbin/bsdinstall/scripts/services21
-rwxr-xr-xusr.sbin/bsdinstall/scripts/zfsboot1043
15 files changed, 1814 insertions, 53 deletions
diff --git a/usr.sbin/bsdconfig/include/messages.subr b/usr.sbin/bsdconfig/include/messages.subr
index 1c558f2..70b5c3d 100644
--- a/usr.sbin/bsdconfig/include/messages.subr
+++ b/usr.sbin/bsdconfig/include/messages.subr
@@ -201,6 +201,7 @@ msg_lithuania="Lithuania"
msg_loading_of_dependent_package_failed="Loading of dependent package %s failed"
msg_located_index_now_reading_package_data_from_it="Located INDEX, now reading package data from it..."
msg_logging_in_to_user_at_host="Logging in to %s@%s.."
+msg_looking_for_keymap_files="Looking for keymap files..."
msg_looking_up_host="Looking up host %s"
msg_mail_desc="Electronic mail packages and utilities."
msg_main_menu="Main Menu"
diff --git a/usr.sbin/bsdconfig/share/Makefile b/usr.sbin/bsdconfig/share/Makefile
index 3392e2a..98cc779 100644
--- a/usr.sbin/bsdconfig/share/Makefile
+++ b/usr.sbin/bsdconfig/share/Makefile
@@ -5,8 +5,9 @@ NO_OBJ=
SUBDIR= media packages
FILESDIR= ${SHAREDIR}/bsdconfig
-FILES= common.subr device.subr dialog.subr mustberoot.subr \
- script.subr strings.subr struct.subr sysrc.subr variable.subr
+FILES= common.subr device.subr dialog.subr keymap.subr \
+ mustberoot.subr script.subr strings.subr struct.subr \
+ sysrc.subr variable.subr
beforeinstall:
mkdir -p ${DESTDIR}${FILESDIR}
diff --git a/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr
index b920809..f15c067 100644
--- a/usr.sbin/bsdconfig/share/device.subr
+++ b/usr.sbin/bsdconfig/share/device.subr
@@ -49,6 +49,7 @@ f_struct_define DEVICE \
desc \
devname \
type \
+ capacity \
enabled \
init \
get \
@@ -114,7 +115,7 @@ f_device_try()
}
# f_device_register $name $desc $devname $type $enabled $init_function \
-# $get_function $shutdown_function $private
+# $get_function $shutdown_function $private $capacity
#
# Register a device. A `structure' (see struct.subr) is created with the name
# device_$name (so make sure $name contains only alpha-numeric characters or
@@ -128,6 +129,7 @@ f_device_register()
{
local name="$1" desc="$2" devname="$3" type="$4" enabled="$5"
local init_func="$6" get_func="$7" shutdown_func="$8" private="$9"
+ local capacity="${10}"
f_struct_new DEVICE "device_$name" || return $FAILURE
device_$name set name "$name"
@@ -139,6 +141,7 @@ f_device_register()
device_$name set get "$get_func"
device_$name set shutdown "$shutdown_func"
device_$name set private "$private"
+ device_$name set capacity "$capacity"
# Scan our global register to see if it needs ammending
local dev found=
@@ -196,7 +199,7 @@ f_device_get_all()
f_dprintf "Found a network device named %s" "$devname"
f_device_register $devname \
"$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \
- f_media_init_network "" f_media_shutdown_network ""
+ f_media_init_network "" f_media_shutdown_network "" -1
done
# Next, try to find all the types of devices one might use
@@ -208,6 +211,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
@@ -222,7 +229,8 @@ f_device_get_all()
f_device_register "${devname##*/}" "$desc" \
"$devname" $DEVICE_TYPE_CDROM 1 \
f_media_init_cdrom f_media_get_cdrom \
- f_media_shutdown_cdrom ""
+ f_media_shutdown_cdrom "" \
+ "$( f_device_capacity "$devname" )"
f_dprintf "Found a CDROM device for %s" \
"$devname"
;;
@@ -232,7 +240,8 @@ f_device_get_all()
"$devname" $DEVICE_TYPE_FLOPPY 1 \
f_media_init_floppy \
f_media_get_floppy \
- f_media_shutdown_floppy ""
+ f_media_shutdown_floppy "" \
+ "$( f_device_capacity "$devname" )"
f_dprintf "Found a floppy device for %s" \
"$devname"
;;
@@ -241,7 +250,8 @@ f_device_get_all()
f_device_register "${devname##*/}" "$desc" \
"$devname" $DEVICE_TYPE_USB 1 \
f_media_init_usb f_media_get_usb \
- f_media_shutdown_usb ""
+ f_media_shutdown_usb "" \
+ "$( f_device_capacity "$devname" )"
f_dprintf "Found a USB disk for %s" "$devname"
;;
esac
@@ -254,7 +264,8 @@ f_device_get_all()
f_device_register "${devname##*/}" "ISO9660 file system" \
"$devname" $DEVICE_TYPE_CDROM 1 \
f_media_init_cdrom f_media_get_cdrom \
- f_media_shutdown_cdrom ""
+ f_media_shutdown_cdrom "" \
+ "$( f_device_capacity "$devname" )"
f_dprintf "Found a CDROM device for %s" "$devname"
done
@@ -281,7 +292,8 @@ f_device_get_all()
"md(4) vnode file system" \
"$devname" $DEVICE_TYPE_CDROM 1 \
f_media_init_cdrom f_media_get_cdrom \
- f_media_shutdown_cdrom ""
+ f_media_shutdown_cdrom "" \
+ "$( f_device_capacity "$devname" )"
f_dprintf "Found a CDROM device for %s" "$devname"
;;
esac
@@ -313,8 +325,13 @@ f_device_get_all()
continue
fi
- f_device_register "$diskname" "" \
- "/dev/$diskname" $DEVICE_TYPE_DISK 0
+ # 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_device_capacity "$diskname" )"
f_dprintf "Found a disk device named %s" "$diskname"
# Look for existing partitions to register
@@ -327,7 +344,8 @@ f_device_get_all()
f_device_register "$slice" "" \
"/dev/$slice" $DEVICE_TYPE_DOS 1 \
f_media_init_dos f_media_get_dos \
- f_media_shutdown_dos ""
+ f_media_shutdown_dos "" \
+ "$( f_device_capacity "/dev/$slice" )"
f_dprintf "Found a DOS partition %s" "$slice"
;;
0xa5) # FreeBSD partition
@@ -347,7 +365,9 @@ f_device_get_all()
$DEVICE_TYPE_UFS 1 \
f_media_init_ufs \
f_media_get_ufs \
- f_media_shutdown_ufs ""
+ f_media_shutdown_ufs "" \
+ "$( f_device_capacity \
+ "$/dev/$part" )"
f_dprintf "Found a UFS partition %s" \
"$part"
done # parts
@@ -379,10 +399,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 +500,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 +542,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,6 +722,25 @@ f_device_menu()
return $retval
}
+# f_device_capacity $device [$var_to_set]
+#
+# Return the capacity of $device in bytes.
+#
+f_device_capacity()
+{
+ local __dev="$1" __var_to_set="$2"
+ local __bytes
+
+ __bytes=$( diskinfo -v "$__dev" 2> /dev/null |
+ awk '/# mediasize in bytes/{print $1}' ) || __bytes=-1
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__bytes"
+ else
+ echo "$__bytes"
+ fi
+}
+
#
# Short-hand
#
@@ -680,6 +766,7 @@ f_disk "ipsd%d" "IBM ServeRAID RAID array" 4
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
diff --git a/usr.sbin/bsdconfig/share/dialog.subr b/usr.sbin/bsdconfig/share/dialog.subr
index ff7fc86..01e928d 100644
--- a/usr.sbin/bsdconfig/share/dialog.subr
+++ b/usr.sbin/bsdconfig/share/dialog.subr
@@ -415,8 +415,8 @@ f_dialog_size_constrain()
if [ "$debug" ]; then
# Print final constrained values to debugging
- f_quietly f_getvar "$__var_height"
- f_quietly f_getvar "$__var_width"
+ [ "$__var_height" ] && f_quietly f_getvar "$__var_height"
+ [ "$__var_width" ] && f_quietly f_getvar "$__var_width"
fi
return $__retval # success if no debug warnings were printed
@@ -532,10 +532,10 @@ f_dialog_menu_constrain()
fi
if [ "$debug" ]; then
- # Print final constrained values to debuggin
- f_quietly f_getvar "$__var_height"
- f_quietly f_getvar "$__var_width"
- f_quietly f_getvar "$__var_rows"
+ # Print final constrained values to debugging
+ [ "$__var_height" ] && f_quietly f_getvar "$__var_height"
+ [ "$__var_width" ] && f_quietly f_getvar "$__var_width"
+ [ "$__var_rows" ] && f_quietly f_getvar "$__var_rows"
fi
return $__retval # success if no debug warnings were printed
@@ -2044,6 +2044,7 @@ f_dialog_menutag2index_with_help()
f_dialog_init()
{
DIALOG_SELF_INITIALIZE=
+ USE_DIALOG=1
#
# Clone terminal stdout so we can redirect to it from within sub-shells
@@ -2087,7 +2088,7 @@ f_dialog_init()
#
# Process `-X' command-line option
#
- [ "$USE_XDIALOG" ] && DIALOG=Xdialog
+ [ "$USE_XDIALOG" ] && DIALOG=Xdialog USE_DIALOG=
#
# Sanity check, or die gracefully
diff --git a/usr.sbin/bsdconfig/share/keymap.subr b/usr.sbin/bsdconfig/share/keymap.subr
new file mode 100644
index 0000000..b2e615a
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/keymap.subr
@@ -0,0 +1,262 @@
+if [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1
+#
+# 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..." keymap.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+############################################################ CONFIGURATION
+
+#
+# Defaults taken from usr.sbin/kbdmap/kbdmap.h
+#
+: ${DEFAULT_LANG:=en}
+: ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps}
+
+############################################################ GLOBALS
+
+KEYMAPS=
+
+# A "keymap" from kbdmap's point of view
+f_struct_define KEYMAP \
+ desc \
+ keym \
+ mark
+
+#
+# Default behavior is to call f_keymap_get_all() automatically when loaded.
+#
+: ${KEYMAP_SELF_SCAN_ALL=1}
+
+############################################################ FUNCTIONS
+
+# f_keymap_register $name $desc $keym $mark
+#
+# Register a keymap. A `structure' (see struct.subr) is created with the name
+# keymap_$name (so make sure $name contains only alpha-numeric characters or
+# the underscore, `_'). The remaining arguments after $name correspond to the
+# propertise of the `KEYMAP' structure-type (defined above).
+#
+# If not already registered, the keymap is then appended to the KEYMAPS
+# environment variable, a space-separated list of all registered keymaps.
+#
+f_keymap_register()
+{
+ local name="$1" desc="$2" keym="$3" mark="$4"
+
+ f_struct_new KEYMAP "keymap_$name" || return $FAILURE
+ keymap_$name set desc "$desc"
+ keymap_$name set keym "$keym"
+ keymap_$name set mark "$mark"
+
+ # Scan our global register to see if needs ammending
+ local k found=
+ for k in $KEYMAPS; do
+ [ "$k" = "$name" ] || continue
+ found=1 && break
+ done
+ [ "$found" ] || KEYMAPS="$KEYMAPS $name"
+
+ return $SUCCESS
+}
+
+# f_keymap_checkfile $keymap
+#
+# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap
+# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure.
+# If debugging is enabled, an appropriate debug error message is printed if
+# $keymap is not available.
+#
+f_keymap_checkfile()
+{
+ local keym="$1"
+
+ # Fixup keymap if it doesn't already contain at least one `/'
+ [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym"
+
+ # Short-cuts
+ [ -f "$keym" -a -r "$keym" ] && return $SUCCESS
+ f_debugging || return $FAILURE
+
+ # Print an appropriate debug error message
+ if [ ! -e "$keym" ]; then
+ f_dprintf "%s: No such file or directory" "$keym"
+ elif [ ! -f "$keym" ]; then
+ f_dprintf "%s: Not a file!" "$keym"
+ elif [ ! -r "$keym" ]; then
+ f_dprintf "%s: Permission denied" "$keym"
+ fi
+
+ return $FAILURE
+}
+
+# f_keymap_get_all
+#
+# Get all keymap information for kbdmap(5) entries both in the database and
+# loosely existing in $DEFAULT_KEYMAP_DIR.
+#
+f_keymap_get_all()
+{
+ local fname=f_keymap_get_all
+ local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}"
+ [ "$lang" = "C" ] && lang="$DEFAULT_LANG"
+
+ f_dprintf "%s: Looking for keymap files..." $fname
+ f_dialog_info "$msg_looking_for_keymap_files"
+ f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG"
+
+ eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" '
+ BEGIN {
+ # en_US.ISO8859-1 -> en_..\.ISO8859-1
+ dialect = lang
+ if (length(dialect) >= 6 &&
+ substr(dialect, 3, 1) == "_")
+ dialect = substr(dialect, 1, 3) ".." \
+ substr(dialect, 6)
+ printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect
+
+ # en_US.ISO8859-1 -> en
+ lang_abk = lang
+ if (length(lang_abk) >= 3 &&
+ substr(lang_abk, 3, 1) == "_")
+ lang_abk = substr(lang_abk, 1, 2)
+ printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n",
+ lang_abk
+ }
+ function find_token(buffer, token)
+ {
+ if (split(buffer, tokens, /,/) == 0) return 0
+ found = 0
+ for (t in tokens)
+ if (token == tokens[t]) { found = 1; break }
+ return found
+ }
+ function add_keymap(desc,mark,keym)
+ {
+ marks[keym] = mark
+ name = keym
+ gsub(/[^[:alnum:]_]/, "_", name)
+ gsub(/'\''/, "'\''\\'\'''\''", desc);
+ printf "f_keymap_checkfile %s && " \
+ "f_keymap_register %s '\'%s\'' %s %u\n",
+ keym, name, desc, keym, mark
+ }
+ !/^[[:space:]]*(#|$)/ {
+ sub(/^[[:space:]]*/, "", $0)
+ keym = $1
+ if (keym ~ /^(MENU|FONT)$/) next
+ lg = ($2 == "" ? lang_default : $2)
+
+ # Match the entry and store the type of match we made
+ # as the mark value (so that if we make a better match
+ # later on with a higher mark, it overwrites previous)
+
+ mark = marks[keym];
+ if (find_token(lg, lang))
+ add_keymap($3, 4, keym) # Best match
+ else if (mark <= 3 && find_token(lg, dialect))
+ add_keymap($3, 3, keym)
+ else if (mark <= 2 && find_token(lg, lang_abk))
+ add_keymap($3, 2, keym)
+ else if (mark <= 1 && find_token(lg, lang_default))
+ add_keymap($3, 1, keym)
+ else if (mark <= 0)
+ add_keymap($3, 0, keym)
+ }
+ ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )"
+
+
+ #
+ # Look for keymaps not in database
+ #
+ local direntry keym name
+ set +f # glob
+ for direntry in "$DEFAULT_KEYMAP_DIR"/*; do
+ [ "${direntry##*.}" = ".kbd" ] || continue
+ keym="${direntry##*/}"
+ f_str2varname "$keym" name
+ f_struct keymap_$name && continue
+ f_keymap_checkfile "$keym" &&
+ f_keymap_register $name "${keym%.*}" "$keym" 0
+ f_dprintf "%s: not in kbdmap(5) database" "$keym"
+ done
+
+ #
+ # Sort the items by their descriptions
+ #
+ f_dprintf "%s: Sorting keymap entries by description..." $fname
+ KEYMAPS=$(
+ for k in $KEYMAPS; do
+ echo -n "$k "
+ # NOTE: Translate '8x8' to '8x08' before sending to
+ # sort(1) so that things work out as we might expect.
+ debug= keymap_$k get desc | sed -e 's/8x8/8x08/g'
+ done | sort -k2 | awk '{
+ printf "%s%s", (started ? " " : ""), $1; started = 1
+ }'
+ )
+
+ return $SUCCESS
+}
+
+# f_keymap_kbdcontrol $keymap
+#
+# Install keyboard map file from $keymap.
+#
+f_keymap_kbdcontrol()
+{
+ local keymap="$1"
+
+ [ "$keymap" ] || return $SUCCESS
+
+ # Fixup keymap if it doesn't already contain at least one `/'
+ [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap"
+
+ [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap"
+}
+
+############################################################ MAIN
+
+#
+# Scan for keymaps unless requeted otherwise
+#
+f_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL"
+case "$KEYMAP_SELF_SCAN_ALL" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_keymap_get_all
+esac
+
+f_dprintf "%s: Found %u keymap file(s)." keymap.subr \
+ "$( set -- $KEYMAPS; echo $# )"
+
+f_dprintf "%s: Successfully loaded." keymap.subr
+
+fi # ! $_KEYMAP_SUBR
diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr
index 0a77048..4621fda 100644
--- a/usr.sbin/bsdconfig/share/strings.subr
+++ b/usr.sbin/bsdconfig/share/strings.subr
@@ -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
diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr
index 86523d6..b947529 100644
--- a/usr.sbin/bsdconfig/share/variable.subr
+++ b/usr.sbin/bsdconfig/share/variable.subr
@@ -205,6 +205,21 @@ f_netinteractive()
f_getvar $VAR_NETINTERACTIVE value && [ "$value" ]
}
+# f_zfsinteractive()
+#
+# Has the user specifically requested the ZFS-portion of configuration and
+# setup to be performed interactively? Returns success if the user has asked
+# for the ZFS configuration to be done interactively even if perhaps overall
+# non-interactive mode has been requested (by setting nonInteractive).
+#
+# Returns success if $zfsInteractive is set and non-NULL.
+#
+f_zfsinteractive()
+{
+ local value
+ f_getvar $VAR_ZFSINTERACTIVE value && [ "$value" ]
+}
+
############################################################ MAIN
#
@@ -240,6 +255,7 @@ f_variable_new VAR_IFCONFIG ifconfig_
f_variable_new VAR_IPADDR ipaddr
f_variable_new VAR_IPV6ADDR ipv6addr
f_variable_new VAR_IPV6_ENABLE ipv6_activate_all_interfaces
+f_variable_new VAR_KEYMAP keymap
f_variable_new VAR_MEDIA_TIMEOUT MEDIA_TIMEOUT
f_variable_new VAR_MEDIA_TYPE mediaType
f_variable_new VAR_NAMESERVER nameserver
@@ -263,6 +279,7 @@ f_variable_new VAR_SLOW_ETHER slowEthernetCard
f_variable_new VAR_TRY_DHCP tryDHCP
f_variable_new VAR_TRY_RTSOL tryRTSOL
f_variable_new VAR_UFS_PATH ufs
+f_variable_new VAR_ZFSINTERACTIVE zfsInteractive
#
# Self-initialize unless requested otherwise
diff --git a/usr.sbin/bsdinstall/bsdinstall b/usr.sbin/bsdinstall/bsdinstall
index 2b55501..612fc11 100755
--- a/usr.sbin/bsdinstall/bsdinstall
+++ b/usr.sbin/bsdinstall/bsdinstall
@@ -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"
diff --git a/usr.sbin/bsdinstall/scripts/Makefile b/usr.sbin/bsdinstall/scripts/Makefile
index 8429e37..07e3338 100644
--- a/usr.sbin/bsdinstall/scripts/Makefile
+++ b/usr.sbin/bsdinstall/scripts/Makefile
@@ -2,7 +2,7 @@
SCRIPTS= auto adduser checksum config docsinstall entropy hostname jail \
keymap mirrorselect mount netconfig netconfig_ipv4 netconfig_ipv6 \
- rootpass script services time umount wlanconfig
+ rootpass script services time umount wlanconfig zfsboot
BINDIR= /usr/libexec/bsdinstall
NO_MAN= true
diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto
index a609e06..cd49021 100755
--- a/usr.sbin/bsdinstall/scripts/auto
+++ b/usr.sbin/bsdinstall/scripts/auto
@@ -93,24 +93,46 @@ 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)\" \
+Shell \"Open a shell and partition by hand\""
+
+CURARCH=$( uname -m )
+case $CURARCH in
+ amd64|i386) # Booting ZFS Supported
+ PMODES="$PMODES ZFS \"Automatic Root-on-ZFS (Experimental)\""
+ ;;
+ *) # Booting ZFS Unspported
+ ;;
+esac
-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
;;
diff --git a/usr.sbin/bsdinstall/scripts/config b/usr.sbin/bsdinstall/scripts/config
index 4340450..e50a179 100755
--- a/usr.sbin/bsdinstall/scripts/config
+++ b/usr.sbin/bsdinstall/scripts/config
@@ -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
diff --git a/usr.sbin/bsdinstall/scripts/keymap b/usr.sbin/bsdinstall/scripts/keymap
index 97ae833..c36651f 100755
--- a/usr.sbin/bsdinstall/scripts/keymap
+++ b/usr.sbin/bsdinstall/scripts/keymap
@@ -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,11 +26,212 @@
# 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/keymap.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default file to store keymap selection in
+#
+: ${KEYMAPFILE:=$BSDINSTALL_TMPETC/rc.conf.keymap}
+
+#
+# Default path to keymap INDEX containing descriptions
+#
+: ${MAPDESCFILE:=/usr/share/syscons/keymaps/INDEX.keymaps}
+
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_continue_with_keymap="Continue with %s keymap"
+msg_default="default"
+msg_error="Error"
+msg_freebsd_installer="FreeBSD Installer"
+msg_keymap_menu_text="The system console driver for FreeBSD defaults to standard \"US\"\nkeyboard map. Other keymaps can be chosen below."
+msg_keymap_selection="Keymap Selection"
+msg_ok="OK"
+msg_select="Select"
+msg_test_keymap="Test %s keymap"
+msg_test_the_currently_selected_keymap="Test the currently selected keymap"
+msg_test_the_keymap_by_typing="Test the keymap by typing letters, numbers, and symbols. Characters\nshould match labels on the keyboard keys. Press Enter to stop testing."
+
+############################################################ FUNCTIONS
+
+# dialog_keymap_test $keymap
+#
+# Activate $keymap and display an input box (without cancel button) for the
+# user to test keyboard input and return. Always returns success.
+#
+dialog_keymap_test()
+{
+ local keym="$1"
+ local title= # Calculated below
+ local btitle= # Calculated below
+ local prompt="$msg_test_the_keymap_by_typing"
+ local hline=
+
+ # Attempt to activate the keymap
+ if [ "$keym" ]; then
+ local err
+ err=$( f_keymap_kbdcontrol "$keym" 2>&1 > /dev/null )
+ if [ "$err" ]; then
+ f_dialog_title "$msg_error"
+ f_dialog_msgbox "$err"
+ f_dialog_title_restore
+ return $FAILURE
+ fi
+ fi
+
+ f_dialog_title "$( printf "$msg_test_keymap" "${keym:-$msg_default}" )"
+ title="$DIALOG_TITLE"
+ btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+
+ local height width
+ f_dialog_inputbox_size height width \
+ "$title" "$btitle" "$prompt" "" "$hline"
+
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --no-cancel \
+ --inputbox "$prompt" \
+ $height $width \
+ 2>/dev/null >&$DIALOG_TERMINAL_PASSTHRU_FD
-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
- exec 3>&1
- kbdmap 2>&1 1>&3 | grep 'keymap=' > $BSDINSTALL_TMPETC/rc.conf.keymap
+ return $DIALOG_OK
+}
+
+############################################################ MAIN
+
+#
+# Initialize
+#
+f_dialog_title "$msg_keymap_selection"
+f_dialog_backtitle "$msg_freebsd_installer"
+
+#
+# Die immediately if we can't dump the current keyboard map
+#
+#error=$( kbdcontrol -d 2>&1 > /dev/null ) || f_die $FAILURE "%s" "$error"
+
+# Capture Ctrl-C for clean-up
+trap 'rm -f $KEYMAPFILE; exit $FAILURE' SIGINT
+
+# Get a value from rc.conf(5) as initial value (if not being scripted)
+f_getvar $VAR_KEYMAP keymap
+if [ ! "$keymap" ]; then
+ keymap=$( f_sysrc_get keymap )
+ case "$keymap" in [Nn][Oo]) keymap="";; esac
fi
+
+#
+# Loop until the user has finalized their selection (by clicking the
+# [relabeled] Cancel button).
+#
+width=67 first_pass=1 back_from_testing=
+[ "$USE_XDIALOG" ] && width=70
+prompt="$msg_keymap_menu_text"
+hline="$hline_arrows_tab_enter"
+while :; do
+ #
+ # Re/Build list of keymaps
+ #
+ cont_msg=$( printf "$msg_continue_with_keymap" \
+ "${keymap:-$msg_default}" )
+ test_msg=$( printf "$msg_test_keymap" "${keymap:-$msg_default}" )
+ menu_list="
+ '>>> $cont_msg' '' '$msg_continue_with_current_keymap'
+ '->- $test_msg' '' '$msg_test_the_currently_selected_keymap'
+ " # END-QUOTE
+ if [ "$first_pass" ]; then
+ defaultitem=
+ first_pass=
+ else
+ defaultitem="->- $test_msg"
+ fi
+ for k in $KEYMAPS; do
+ keymap_$k get keym keym
+ keymap_$k get desc desc
+ radio=" "
+ if [ "$keym" = "$keymap" ]; then
+ radio="*"
+ if [ "$back_from_testing" ]; then
+ defaultitem="(*) $desc"
+ back_from_testing=
+ fi
+ fi
+ f_shell_escape "$desc" desc
+ menu_list="$menu_list
+ '($radio) $desc' '' '$keym: $desc'
+ " # END-QUOTE
+ done
+ back_from_testing=
+
+ #
+ # Display keymap configuration menu
+ #
+ eval f_dialog_menu_with_help_size height \"\" rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --keep-tite \
+ --item-help \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || {
+ f_quietly rm -f "$KEYMAPFILE"
+ exit $FAILURE # Exit with an error so bsdinstall restarts
+ }
+ f_dialog_data_sanitize menu_choice
+
+ case "$menu_choice" in
+ ">>> "*) # Continue with keymap
+ break ;;
+ "->-"*) # Test keymap
+ dialog_keymap_test "$keymap"
+ back_from_testing=1
+ continue ;;
+ esac
+
+ # Turn the user's choice into a number
+ n=$( eval f_dialog_menutag2index_with_help \
+ \"\$menu_choice\" $menu_list )
+
+ # Turn that number ithe name of the keymap struct
+ k=$( set -- $KEYMAPS; eval echo \"\${$(( $n - 2))}\" )
+
+ # Get actual keymap setting while we update $keymap and $KEYMAPFILE
+ keymap_$k get keym keymap
+ echo "keymap=\"$keymap\"" > "$KEYMAPFILE"
+done
+
+f_quietly f_keymap_kbdcontrol "$keymap"
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/netconfig b/usr.sbin/bsdinstall/scripts/netconfig
index 382ff2c..d5a14ce 100755
--- a/usr.sbin/bsdinstall/scripts/netconfig
+++ b/usr.sbin/bsdinstall/scripts/netconfig
@@ -41,11 +41,19 @@ DIALOG_TAGS=""
: ${DIALOG_ITEM_HELP=4}
: ${DIALOG_ESC=255}
+# Do a dirty check to see if this a wireless interface -- there should be a
+# better way
+is_wireless_if() {
+ ifconfig $1 | grep -q 'media: IEEE 802.11 Wireless'
+}
+
for IF in `ifconfig -l`; do
test "$IF" = "lo0" && continue
(ifconfig -g wlan | egrep -wq $IF) && continue
INTERFACES="$INTERFACES $IF"
DESC=`sysctl -n dev.$(echo $IF | sed -E 's/([[:alpha:]]*)([[:digit:]]*)/\1.\2/g').%desc`
+ is_wireless_if $IF && echo $DESC |
+ grep -iqv wireless && DESC="Wireless $DESC"
DIALOG_TAGS="$DIALOG_TAGS $IF \"$DESC\""
done
@@ -63,10 +71,8 @@ exec 3>&-
: > $BSDINSTALL_TMPETC/._rc.conf.net
-# Do a dirty check to see if this a wireless interface -- there should be a
-# better way
IFCONFIG_PREFIX=""
-if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then
+if is_wireless_if $INTERFACE; then
NEXT_WLAN_IFACE=wlan0 # XXX
echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/._rc.conf.net
IFCONFIG_PREFIX="WPA "
diff --git a/usr.sbin/bsdinstall/scripts/services b/usr.sbin/bsdinstall/scripts/services
index a4cfd46..cf6e739 100755
--- a/usr.sbin/bsdinstall/scripts/services
+++ b/usr.sbin/bsdinstall/scripts/services
@@ -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 "Enable kernel crash dumps to /var/crash" ${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
diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot
new file mode 100755
index 0000000..715ea31
--- /dev/null
+++ b/usr.sbin/bsdinstall/scripts/zfsboot
@@ -0,0 +1,1043 @@
+#!/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
+f_include $BSDCFG_SHARE/password/password.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default name of the boot-pool
+#
+: ${ZFSBOOT_POOL_NAME:=zroot}
+
+#
+# Default 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:=}
+
+#
+# Default name the unencrypted pool when using geli(8) to encrypt the drives
+#
+: ${ZFSBOOT_GELI_POOL_NAME:=bootpool}
+
+#
+# Default size for the unencrypted boot pool when using geli(8)
+#
+: ${ZFSBOOT_GELI_BOOT_SIZE:=2g}
+
+#
+# Default path to the geli(8) keyfile used in drive encryption
+#
+: ${ZFSBOOT_GELI_KEY_FILE:=/boot/encryption.key}
+
+#
+# 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, /$ZFSBOOT_BOOTFS_NAME/$ZFSBOOT_BOOTFS_NAME
+# NOTE: Anything after pound/hash character [#] is ignored as a comment.
+#
+f_isset ZFSBOOT_DATASETS || ZFSBOOT_DATASETS="
+ # DATASET OPTIONS (comma or space separated; or both)
+
+ # Boot Environment [BE] root and default boot dataset
+ /$ZFSBOOT_BEROOT_NAME mountpoint=none
+ /$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME mountpoint=/
+
+ # Compress /tmp, allow exec but not setuid
+ /tmp mountpoint=/tmp,compression=lz4,exec=on,setuid=off
+
+ # 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
+
+ # 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
+
+############################################################ 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_back="Back"
+msg_cancel="Cancel"
+msg_change="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_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_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_mirror_desc="Mirror - n-Way Mirroring"
+msg_mirror_help="[2+ Disks] Mirroring provides the best performance, but the least storage"
+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_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_processing_selection="Processing selection..."
+msg_raidz1_desc="RAID-Z1 - Single Redundant RAID"
+msg_raidz1_help="[3+ Disks] Withstand failure of 1 disk. Recommended for: 3, 5 or 9 disks"
+msg_raidz2_desc="RAID-Z2 - Double Redundant RAID"
+msg_raidz2_help="[4+ Disks] Withstand failure of 2 disks. Recommended for: 4, 6 or 10 disks"
+msg_raidz3_desc="RAID-Z3 - Triple Redundant RAID"
+msg_raidz3_help="[5+ Disks] Withstand failure of 3 disks. Recommended for: 5, 7 or 11 disks"
+msg_rescan_devices="Rescan Devices"
+msg_rescan_devices_help="Scan for device changes"
+msg_select="Select"
+msg_select_a_disk_device="Select a disk device"
+msg_select_virtual_device_type="Select Virtual Device type:"
+msg_stripe_desc="Stripe - No Redundancy"
+msg_stripe_help="[1+ Disks] Striping provides maximum storage but no redundancy"
+msg_swap_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_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_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'
+ '$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 \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+# dialog_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 $DIALOG_OK
+}
+
+# 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' '$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 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 ;;
+ *)
+ f_show_msg "$msg_invalid_virtual_device_type" \
+ "$menu_choice"
+ continue
+ 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"
+ fi
+}
+
+# zfs_create_diskpart $disk $index
+#
+# For each block device to be used in the zpool, rather than just create the
+# zpool with the raw block devices (e.g., da0, da1, etc.) we create partitions
+# so we can have some real swap. This also provides wiggle room incase your
+# replacement drivers do not have the exact same sector counts.
+#
+# NOTE: The MBR layout is more complicated (GPT is preferred).
+#
+zfs_create_diskpart()
+{
+ local disk="$1" index="$2"
+ local funcname=zfs_create_diskpart
+ local disksize partsize
+
+ # Check arguments
+ [ "$disk" -a "$index" ] || return $FAILURE
+
+ #
+ # 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_quietly gpart destroy -F $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
+
+ # Calculate partition size given desired amount of swap
+ device_$disk get capacity disksize || return $FAILURE
+ partsize=$(( $disksize - $swapsize ))
+
+ #
+ # Lay down the desired type of partition scheme
+ #
+ local setsize mbrindex
+ case "$ZFSBOOT_PARTITION_SCHEME" in
+ ""|GPT)
+ #
+ # 1. Create GPT layout using labels
+ #
+ gpart create -s 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
+
+ # zpool will use the `zfs#' GPT labels
+ bootpart=p2 targetpart=p2
+
+ # Change things around if we are using GELI
+ 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
+ # Pedantically nuke any old labels, stop geli
+ 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
+
+ #
+ # 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
+ # Update fstab(5)
+ printf "$fstab_fmt" \
+ /dev/gpt/swap$index none swap sw 0 0 \
+ >> $BSDINSTALL_TMPETC/fstab || return $FAILURE
+ fi
+ ;;
+
+ MBR)
+ #
+ # 1. Create MBR layout (no labels)
+ #
+ gpart create -s mbr $disk || return $FAILURE
+ gpart bootcode -b /boot/boot0 $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_quietly zpool labelclear -f /dev/${disk}s1 # Pedantic
+ f_quietly gpart destroy -F ${disk}s1 # Pedantic
+
+ #
+ # 3. Write BSD sceme to the freebsd slice
+ #
+ gpart create -s 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
+ 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
+ # Pedantically nuke any old labels, stop geli
+ 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
+ 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
+ # 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 # $ZFSBOOT_PARTITION_SCHEME
+
+ return $SUCCESS
+}
+
+# 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
+ local bootpart targetpart
+
+ shift 2 # name vdev_type
+
+ # We may need this later
+ local realdisks=$*
+
+ # 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
+
+ # Expand SI units in desired sizes
+ local swapsize gelisize
+ f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize || return $FAILURE
+ f_expand_number "$ZFSBOOT_GELI_BOOT_SIZE" gelisize || return $FAILURE
+
+ # Prepare the disks
+ local n=0
+ for disk in $*; do
+ zfs_create_diskpart $disk $n || return $FAILURE
+ 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"
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] &&
+ unenc_list="$unenc_list $disk$bootpart"
+ done
+ set -- $new_list
+ fi
+
+ #
+ # If encryption is enabled, we need to create the GEOMs
+ #
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ local bootvdev=
+ local geli_pool="$BSDINSTALL_CHROOT/$ZFSBOOT_GELI_POOL_NAME"
+ local key="$ZFSBOOT_GELI_KEY_FILE"
+
+ # Create the parent directories for our unencrypted pool
+ f_quietly umount /mnt
+ mount -t 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
+
+ # Generate an encryption key using random(4)
+ dd if=/dev/random of="$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 ||
+ return $FAILURE
+ geli_list="$geli_list $disk$targetpart.eli"
+ done
+ set -- $geli_list
+ 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
+
+ # 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" " " " " options
+ # Reduce contiguous runs of space to one single space
+ oldoptions=
+ while [ "$oldoptions" != "$options" ]; do
+ oldoptions="$options"
+ f_replaceall "$options" " " " " options
+ done
+ # Replace both commas and spaces with ` -o '
+ f_replaceall "$options" "[ ,]" " -o " options
+ # Create the dataset with desired options
+ 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
+
+ # Create symlink(s)
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] &&
+ { ln -s $ZFSBOOT_GELI_POOL_NAME/boot $BSDINSTALL_CHROOT/boot ||
+ return $FAILURE; }
+
+ # Set bootfs property
+ 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; }
+
+ # Destroy the gnop devices (if enabled)
+ for disk in ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:+$realdisks}; do
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ f_quietly gnop destroy $disk$bootpart.nop
+ else
+ f_quietly gnop destroy $disk$targetpart.nop
+ fi
+ done
+
+ # 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(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; }
+
+ # 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
+
+ # We're all done unless we should go on to do encryption
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS
+
+ #
+ # 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 ||
+ return $FAILURE
+ printf 'geli_%s_keyfile0_type="%s:geli_keyfile0"\n' \
+ "$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 ||
+ return $FAILURE
+ done
+
+ return $SUCCESS
+}
+
+# dialog_menu_diskinfo
+#
+# Prompt the user to select a disk and then provide detailed info on it.
+#
+dialog_menu_diskinfo()
+{
+ local disk
+
+ #
+ # Break from loop when user cancels disk selection
+ #
+ while :; do
+ disk=$( msg_cancel="$msg_back" 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"
+
+# User may have specifically requested ZFS-related operations be interactive
+! f_interactive && f_zfsinteractive && unset $VAR_NONINTERACTIVE
+
+#
+# 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"
+ else
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ fi
+
+ f_dprintf "retval=%u mtag=[%s]" $reval "$mtag"
+ [ $retval -eq $DIALOG_OK ] || 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"
+ 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
+ continue
+ fi
+ # 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
+ then
+ minsize=$swapsize teeny_disks=
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] &&
+ minsize=$(( $minsize + $gelisize ))
+ for disk in $real_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" \
+ "$ZFSBOOT_SWAP_SIZE" \
+ "$ZFSBOOT_GELI_BOOT_SIZE" \
+ "$teeny_disks"
+ f_interactive || f_die
+ continue
+ fi
+ fi
+
+ #
+ # 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
+ fi
+
+ #
+ # 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"
+ f_interactive || f_die
+ 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" &&
+ 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" &&
+ ZFSBOOT_SWAP_SIZE="$input"
+ ;;
+ esac
+done
+
+return $SUCCESS
+
+################################################################################
+# END
+################################################################################
OpenPOWER on IntegriCloud