xref: /freebsd/usr.sbin/bsdinstall/scripts/auto (revision 389e4940069316fe667ffa263fa7d6390d0a960f)
1#!/bin/sh
2#-
3# Copyright (c) 2011 Nathan Whitehorn
4# Copyright (c) 2013 Devin Teske
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28# $FreeBSD$
29#
30############################################################ INCLUDES
31
32BSDCFG_SHARE="/usr/share/bsdconfig"
33. $BSDCFG_SHARE/common.subr || exit 1
34f_include $BSDCFG_SHARE/dialog.subr
35
36############################################################ FUNCTIONS
37
38error() {
39	local msg
40	if [ -n "$1" ]; then
41		msg="$1\n\n"
42	fi
43	test -n "$DISTDIR_IS_UNIONFS" && umount -f $BSDINSTALL_DISTDIR
44	test -f $PATH_FSTAB && bsdinstall umount
45	dialog --backtitle "FreeBSD Installer" --title "Abort" \
46	    --no-label "Exit" --yes-label "Restart" --yesno \
47	    "${msg}An installation step has been aborted. Would you like to restart the installation or exit the installer?" 0 0
48	if [ $? -ne 0 ]; then
49		exit 1
50	else
51		exec $0
52	fi
53}
54
55hline_arrows_tab_enter="Press arrows, TAB or ENTER"
56msg_gpt_active_fix="Your hardware is known to have issues booting in CSM/Legacy/BIOS mode from GPT partitions that are not set active. Would you like the installer to apply this workaround for you?"
57msg_lenovo_fix="Your model of Lenovo is known to have a BIOS bug that prevents it booting from GPT partitions without UEFI. Would you like the installer to apply a workaround for you?"
58msg_no="NO"
59msg_yes="YES"
60
61# dialog_workaround
62#
63# Ask the user if they wish to apply a workaround
64#
65dialog_workaround()
66{
67	local passed_msg="$1"
68	local title="$DIALOG_TITLE"
69	local btitle="$DIALOG_BACKTITLE"
70	local prompt # Calculated below
71	local hline="$hline_arrows_tab_enter"
72
73	local height=8 width=50 prefix="   "
74	local plen=${#prefix} list= line=
75	local max_width=$(( $width - 3 - $plen ))
76
77	local yes no defaultno extra_args format
78	if [ "$USE_XDIALOG" ]; then
79		yes=ok no=cancel defaultno=default-no
80		extra_args="--wrap --left"
81		format="$passed_msg"
82	else
83		yes=yes no=no defaultno=defaultno
84		extra_args="--cr-wrap"
85		format="$passed_msg"
86	fi
87
88	# Add height for Xdialog(1)
89	[ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 ))
90
91	prompt=$( printf "$format" )
92	f_dprintf "%s: Workaround prompt" "$0"
93	$DIALOG \
94		--title "$title"        \
95		--backtitle "$btitle"   \
96		--hline "$hline"        \
97		--$yes-label "$msg_yes" \
98		--$no-label "$msg_no"   \
99		$extra_args             \
100		--yesno "$prompt" $height $width
101}
102
103############################################################ MAIN
104
105f_dprintf "Began Installation at %s" "$( date )"
106
107rm -rf $BSDINSTALL_TMPETC
108mkdir $BSDINSTALL_TMPETC
109
110trap true SIGINT	# This section is optional
111bsdinstall keymap
112
113trap error SIGINT	# Catch cntrl-C here
114bsdinstall hostname || error "Set hostname failed"
115
116export DISTRIBUTIONS="base.txz kernel.txz"
117if [ -f $BSDINSTALL_DISTDIR/MANIFEST ]; then
118	DISTMENU=`awk -F'\t' '!/^(kernel\.txz|base\.txz)/{print $1,$5,$6}' $BSDINSTALL_DISTDIR/MANIFEST`
119	DISTMENU="$(echo ${DISTMENU} | sed -E 's/\.txz//g')"
120
121	exec 3>&1
122	EXTRA_DISTS=$( eval dialog \
123	    --backtitle \"FreeBSD Installer\" \
124	    --title \"Distribution Select\" --nocancel --separate-output \
125	    --checklist \"Choose optional system components to install:\" \
126	    0 0 0 $DISTMENU \
127	2>&1 1>&3 )
128	for dist in $EXTRA_DISTS; do
129		export DISTRIBUTIONS="$DISTRIBUTIONS $dist.txz"
130	done
131fi
132
133LOCAL_DISTRIBUTIONS="MANIFEST"
134FETCH_DISTRIBUTIONS=""
135for dist in $DISTRIBUTIONS; do
136	if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
137		FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
138	else
139		LOCAL_DISTRIBUTIONS="$LOCAL_DISTRIBUTIONS $dist"
140	fi
141done
142LOCAL_DISTRIBUTIONS=`echo $LOCAL_DISTRIBUTIONS`	# Trim white space
143FETCH_DISTRIBUTIONS=`echo $FETCH_DISTRIBUTIONS`	# Trim white space
144
145if [ -n "$FETCH_DISTRIBUTIONS" -a -n "$BSDINSTALL_CONFIGCURRENT" ]; then
146	dialog --backtitle "FreeBSD Installer" --title "Network Installation" --msgbox "Some installation files were not found on the boot volume. The next few screens will allow you to configure networking so that they can be downloaded from the Internet." 0 0
147	bsdinstall netconfig || error
148	NETCONFIG_DONE=yes
149fi
150
151if [ -n "$FETCH_DISTRIBUTIONS" ]; then
152	exec 3>&1
153	BSDINSTALL_DISTSITE=$(`dirname $0`/mirrorselect 2>&1 1>&3)
154	MIRROR_BUTTON=$?
155	exec 3>&-
156	test $MIRROR_BUTTON -eq 0 || error "No mirror selected"
157	export BSDINSTALL_DISTSITE
158fi
159
160rm -f $PATH_FSTAB
161touch $PATH_FSTAB
162
163#
164# Try to detect known broken platforms and apply their workarounds
165#
166
167if f_interactive; then
168	sys_maker=$( kenv -q smbios.system.maker )
169	f_dprintf "smbios.system.maker=[%s]" "$sys_maker"
170	sys_model=$( kenv -q smbios.system.product )
171	f_dprintf "smbios.system.product=[%s]" "$sys_model"
172	sys_version=$( kenv -q smbios.system.version )
173	f_dprintf "smbios.system.version=[%s]" "$sys_version"
174	sys_mb_maker=$( kenv -q smbios.planar.maker )
175	f_dprintf "smbios.planar.maker=[%s]" "$sys_mb_maker"
176	sys_mb_product=$( kenv -q smbios.planar.product )
177	f_dprintf "smbios.planar.product=[%s]" "$sys_mb_product"
178
179	#
180	# Laptop Models
181	#
182	case "$sys_maker" in
183	"LENOVO")
184		case "$sys_version" in
185		"ThinkPad X220"|"ThinkPad T420"|"ThinkPad T520"|"ThinkPad W520"|"ThinkPad X1")
186			dialog_workaround "$msg_lenovo_fix"
187			retval=$?
188			f_dprintf "lenovofix_prompt=[%s]" "$retval"
189			if [ $retval -eq $DIALOG_OK ]; then
190				export ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix"
191				export WORKAROUND_LENOVO=1
192			fi
193			;;
194		esac
195		;;
196	"Dell Inc.")
197		case "$sys_model" in
198		"Latitude E6330"|"Latitude E7440"|"Latitude E7240"|"Precision Tower 5810")
199			dialog_workaround "$msg_gpt_active_fix"
200			retval=$?
201			f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
202			if [ $retval -eq $DIALOG_OK ]; then
203				export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
204				export WORKAROUND_GPTACTIVE=1
205			fi
206			;;
207		esac
208		;;
209	"Hewlett-Packard")
210		case "$sys_model" in
211		"HP ProBook 4330s")
212			dialog_workaround "$msg_gpt_active_fix"
213			retval=$?
214			f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
215			if [ $retval -eq $DIALOG_OK ]; then
216				export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
217				export WORKAROUND_GPTACTIVE=1
218			fi
219			;;
220		esac
221		;;
222	esac
223	#
224	# Motherboard Models
225	#
226	case "$sys_mb_maker" in
227	"Intel Corporation")
228		case "$sys_mb_product" in
229		"DP965LT"|"D510MO")
230			dialog_workaround "$msg_gpt_active_fix"
231			retval=$?
232			f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
233			if [ $retval -eq $DIALOG_OK ]; then
234				export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
235				export WORKAROUND_GPTACTIVE=1
236			fi
237			;;
238		esac
239		;;
240	"Acer")
241		case "$sys_mb_product" in
242		"Veriton M6630G")
243			dialog_workaround "$msg_gpt_active_fix"
244			retval=$?
245			f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
246			if [ $retval -eq $DIALOG_OK ]; then
247				export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
248				export WORKAROUND_GPTACTIVE=1
249			fi
250			;;
251		esac
252		;;
253	esac
254fi
255
256PMODES="\
257\"Auto (UFS)\" \"Guided Disk Setup\" \
258Manual \"Manual Disk Setup (experts)\" \
259Shell \"Open a shell and partition by hand\""
260
261CURARCH=$( uname -m )
262case $CURARCH in
263	amd64|arm64|i386)	# Booting ZFS Supported
264		PMODES="$PMODES \"Auto (ZFS)\" \"Guided Root-on-ZFS\""
265		;;
266	*)		# Booting ZFS Unspported
267		;;
268esac
269
270exec 3>&1
271PARTMODE=`echo $PMODES | xargs dialog --backtitle "FreeBSD Installer" \
272	--title "Partitioning" \
273	--menu "How would you like to partition your disk?" \
274	0 0 0 2>&1 1>&3` || exit 1
275exec 3>&-
276
277case "$PARTMODE" in
278"Auto (UFS)")	# Guided
279	bsdinstall autopart || error "Partitioning error"
280	bsdinstall mount || error "Failed to mount filesystem"
281	;;
282"Shell")	# Shell
283	clear
284	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'."
285	sh 2>&1
286	;;
287"Manual")	# Manual
288	if f_isset debugFile; then
289		# Give partedit the path to our logfile so it can append
290		BSDINSTALL_LOG="${debugFile#+}" bsdinstall partedit || error "Partitioning error"
291	else
292		bsdinstall partedit || error "Partitioning error"
293	fi
294	bsdinstall mount || error "Failed to mount filesystem"
295	;;
296"Auto (ZFS)")	# ZFS
297	bsdinstall zfsboot || error "ZFS setup failed"
298	bsdinstall mount || error "Failed to mount filesystem"
299	;;
300*)
301	error "Unknown partitioning mode"
302	;;
303esac
304
305if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then
306	ALL_DISTRIBUTIONS="$DISTRIBUTIONS"
307	WANT_DEBUG=
308
309	# Download to a directory in the new system as scratch space
310	BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
311	mkdir -p "$BSDINSTALL_FETCHDEST" || error "Could not create directory $BSDINSTALL_FETCHDEST"
312
313	export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
314	# Try to use any existing distfiles
315	if [ -d $BSDINSTALL_DISTDIR ]; then
316		DISTDIR_IS_UNIONFS=1
317		mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
318	else
319		export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
320		export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
321	fi
322
323	export FTP_PASSIVE_MODE=YES
324	# Iterate through the distribution list and set a flag if debugging
325	# distributions have been selected.
326	for _DISTRIBUTION in $DISTRIBUTIONS; do
327		case $_DISTRIBUTION in
328			*-dbg.*)
329				[ -e $BSDINSTALL_DISTDIR/$_DISTRIBUTION ] \
330					&& continue
331				WANT_DEBUG=1
332				DEBUG_LIST="\n$DEBUG_LIST\n$_DISTRIBUTION"
333				;;
334			*)
335				;;
336		esac
337	done
338
339	# Fetch the distributions.
340	bsdinstall distfetch
341	rc=$?
342
343	if [ $rc -ne 0 ]; then
344		# If unable to fetch the remote distributions, recommend
345		# deselecting the debugging distributions, and retrying the
346		# installation, since failure to fetch *-dbg.txz should not
347		# be considered a fatal installation error.
348		msg="Failed to fetch remote distribution"
349		if [ ! -z "$WANT_DEBUG" ]; then
350			# Trim leading and trailing newlines.
351			DEBUG_LIST="${DEBUG_LIST%%\n}"
352			DEBUG_LIST="${DEBUG_LIST##\n}"
353			msg="$msg\n\nPlease deselect the following distributions"
354			msg="$msg and retry the installation:"
355			msg="$msg\n$DEBUG_LIST"
356		fi
357		error "$msg"
358	fi
359	export DISTRIBUTIONS="$ALL_DISTRIBUTIONS"
360fi
361
362if [ ! -z "$LOCAL_DISTRIBUTIONS" ]; then
363	# Download to a directory in the new system as scratch space
364	BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
365	mkdir -p "$BSDINSTALL_FETCHDEST" || error "Could not create directory $BSDINSTALL_FETCHDEST"
366	# Try to use any existing distfiles
367	if [ -d $BSDINSTALL_DISTDIR ]; then
368		DISTDIR_IS_UNIONFS=1
369		mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
370		export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
371	fi
372	env DISTRIBUTIONS="$LOCAL_DISTRIBUTIONS" \
373		BSDINSTALL_DISTSITE="file:///usr/freebsd-dist" \
374		bsdinstall distfetch || \
375		error "Failed to fetch distribution from local media"
376fi
377
378bsdinstall checksum || error "Distribution checksum failed"
379bsdinstall distextract || error "Distribution extract failed"
380
381# Set up boot loader
382bsdinstall bootconfig || error "Failed to configure bootloader"
383
384bsdinstall rootpass || error "Could not set root password"
385
386trap true SIGINT	# This section is optional
387if [ "$NETCONFIG_DONE" != yes ]; then
388	bsdinstall netconfig	# Don't check for errors -- the user may cancel
389fi
390bsdinstall time
391bsdinstall services
392bsdinstall hardening
393
394dialog --backtitle "FreeBSD Installer" --title "Add User Accounts" --yesno \
395    "Would you like to add users to the installed system now?" 0 0 && \
396    bsdinstall adduser
397
398finalconfig() {
399	exec 3>&1
400	REVISIT=$(dialog --backtitle "FreeBSD Installer" \
401	    --title "Final Configuration" --no-cancel --menu \
402	    "Setup of your FreeBSD system is nearly complete. You can now modify your configuration choices. After this screen, you will have an opportunity to make more complex changes using a shell." 0 0 0 \
403		"Exit" "Apply configuration and exit installer" \
404		"Add User" "Add a user to the system" \
405		"Root Password" "Change root password" \
406		"Hostname" "Set system hostname" \
407		"Network" "Networking configuration" \
408		"Services" "Set daemons to run on startup" \
409		"System Hardening" "Set security options" \
410		"Time Zone" "Set system timezone" \
411		"Handbook" "Install FreeBSD Handbook (requires network)" 2>&1 1>&3)
412	exec 3>&-
413
414	case "$REVISIT" in
415	"Add User")
416		bsdinstall adduser
417		finalconfig
418		;;
419	"Root Password")
420		bsdinstall rootpass
421		finalconfig
422		;;
423	"Hostname")
424		bsdinstall hostname
425		finalconfig
426		;;
427	"Network")
428		bsdinstall netconfig
429		finalconfig
430		;;
431	"Services")
432		bsdinstall services
433		finalconfig
434		;;
435	"System Hardening")
436		bsdinstall hardening
437		finalconfig
438		;;
439	"Time Zone")
440		bsdinstall time
441		finalconfig
442		;;
443	"Handbook")
444		bsdinstall docsinstall
445		finalconfig
446		;;
447	esac
448}
449
450# Allow user to change his mind
451finalconfig
452
453trap error SIGINT	# SIGINT is bad again
454bsdinstall config  || error "Failed to save config"
455
456if [ -n "$DISTDIR_IS_UNIONFS" ]; then
457	umount -f $BSDINSTALL_DISTDIR
458fi
459
460if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then
461	rm -rf "$BSDINSTALL_FETCHDEST"
462fi
463
464dialog --backtitle "FreeBSD Installer" --title "Manual Configuration" \
465    --default-button no --yesno \
466   "The installation is now finished. Before exiting the installer, would you like to open a shell in the new system to make any final manual modifications?" 0 0
467if [ $? -eq 0 ]; then
468	clear
469	echo This shell is operating in a chroot in the new system. \
470	    When finished making configuration changes, type \"exit\".
471	chroot "$BSDINSTALL_CHROOT" /bin/sh 2>&1
472fi
473
474bsdinstall entropy
475bsdinstall umount
476
477f_dprintf "Installation Completed at %s" "$( date )"
478
479################################################################################
480# END
481################################################################################
482