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 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|base)/{print $4,$5,$6}' $BSDINSTALL_DISTDIR/MANIFEST`
119
120	exec 3>&1
121	EXTRA_DISTS=$( eval dialog \
122	    --backtitle \"FreeBSD Installer\" \
123	    --title \"Distribution Select\" --nocancel --separate-output \
124	    --checklist \"Choose optional system components to install:\" \
125	    0 0 0 $DISTMENU \
126	2>&1 1>&3 )
127	for dist in $EXTRA_DISTS; do
128		export DISTRIBUTIONS="$DISTRIBUTIONS $dist.txz"
129	done
130fi
131
132FETCH_DISTRIBUTIONS=""
133for dist in $DISTRIBUTIONS; do
134	if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
135		FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
136	fi
137done
138FETCH_DISTRIBUTIONS=`echo $FETCH_DISTRIBUTIONS`	# Trim white space
139
140if [ -n "$FETCH_DISTRIBUTIONS" -a -n "$BSDINSTALL_CONFIGCURRENT" ]; then
141	dialog --backtitle "FreeBSD Installer" --title "Network Installation" --msgbox "No installation files were 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
142	bsdinstall netconfig || error
143	NETCONFIG_DONE=yes
144fi
145
146if [ -n "$FETCH_DISTRIBUTIONS" ]; then
147	exec 3>&1
148	BSDINSTALL_DISTSITE=$(`dirname $0`/mirrorselect 2>&1 1>&3)
149	MIRROR_BUTTON=$?
150	exec 3>&-
151	test $MIRROR_BUTTON -eq 0 || error "No mirror selected"
152	export BSDINSTALL_DISTSITE
153fi
154
155rm -f $PATH_FSTAB
156touch $PATH_FSTAB
157
158#
159# Try to detect known broken platforms and apply their workarounds
160#
161
162if f_interactive; then
163	sys_maker=$( kenv -q smbios.system.maker )
164	f_dprintf "smbios.system.maker=[%s]" "$sys_maker"
165	sys_model=$( kenv -q smbios.system.product )
166	f_dprintf "smbios.system.product=[%s]" "$sys_model"
167	sys_version=$( kenv -q smbios.system.version )
168	f_dprintf "smbios.system.version=[%s]" "$sys_version"
169	case "$sys_maker" in
170	"LENOVO")
171		case "$sys_version" in
172		"ThinkPad X220"|"ThinkPad T420"|"ThinkPad T520")
173			dialog_workaround "$msg_lenovo_fix"
174			retval=$?
175			f_dprintf "lenovofix_prompt=[%s]" "$retval"
176			if [ $retval -eq $DIALOG_OK ]; then
177				export ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix"
178				export WORKAROUND_LENOVO=1
179			fi
180			;;
181		esac
182		;;
183	"Dell Inc.")
184		case "$sys_model" in
185		"Latitude E7440")
186			dialog_workaround "$msg_gpt_active_fix"
187			retval=$?
188			f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
189			if [ $retval -eq $DIALOG_OK ]; then
190				export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
191				export WORKAROUND_GPTACTIVE=1
192			fi
193			;;
194		esac
195		;;
196	esac
197fi
198
199PMODES="\
200\"Auto (UFS)\" \"Guided Disk Setup\" \
201Manual \"Manual Disk Setup (experts)\" \
202Shell \"Open a shell and partition by hand\""
203
204CURARCH=$( uname -m )
205case $CURARCH in
206	amd64|i386)	# Booting ZFS Supported
207		PMODES="$PMODES \"Auto (ZFS)\" \"Guided Root-on-ZFS\""
208		;;
209	*)		# Booting ZFS Unspported
210		;;
211esac
212
213exec 3>&1
214PARTMODE=`echo $PMODES | xargs dialog --backtitle "FreeBSD Installer" \
215	--title "Partitioning" \
216	--menu "How would you like to partition your disk?" \
217	0 0 0 2>&1 1>&3` || exit 1
218exec 3>&-
219
220case "$PARTMODE" in
221"Auto (UFS)")	# Guided
222	bsdinstall autopart || error "Partitioning error"
223	bsdinstall mount || error "Failed to mount filesystem"
224	;;
225"Shell")	# Shell
226	clear
227	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'."
228	sh 2>&1
229	;;
230"Manual")	# Manual
231	if f_isset debugFile; then
232		# Give partedit the path to our logfile so it can append
233		BSDINSTALL_LOG="${debugFile#+}" bsdinstall partedit || error "Partitioning error"
234	else
235		bsdinstall partedit || error "Partitioning error"
236	fi
237	bsdinstall mount || error "Failed to mount filesystem"
238	;;
239"Auto (ZFS)")	# ZFS
240	bsdinstall zfsboot || error "ZFS setup failed"
241	bsdinstall mount || error "Failed to mount filesystem"
242	;;
243*)
244	error "Unknown partitioning mode"
245	;;
246esac
247
248if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then
249	ALL_DISTRIBUTIONS="$DISTRIBUTIONS"
250
251	# Download to a directory in the new system as scratch space
252	BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
253	mkdir -p "$BSDINSTALL_FETCHDEST" || error "Could not create directory $BSDINSTALL_FETCHDEST"
254
255	export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
256	# Try to use any existing distfiles
257	if [ -d $BSDINSTALL_DISTDIR ]; then
258		DISTDIR_IS_UNIONFS=1
259		mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
260	else
261		export DISTRIBUTIONS="MANIFEST $ALL_DISTRIBUTIONS"
262		export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
263	fi
264
265	export FTP_PASSIVE_MODE=YES
266	bsdinstall distfetch || error "Failed to fetch distribution"
267	export DISTRIBUTIONS="$ALL_DISTRIBUTIONS"
268fi
269
270bsdinstall checksum || error "Distribution checksum failed"
271bsdinstall distextract || error "Distribution extract failed"
272bsdinstall rootpass || error "Could not set root password"
273
274trap true SIGINT	# This section is optional
275if [ "$NETCONFIG_DONE" != yes ]; then
276	bsdinstall netconfig	# Don't check for errors -- the user may cancel
277fi
278bsdinstall time
279bsdinstall services
280
281dialog --backtitle "FreeBSD Installer" --title "Add User Accounts" --yesno \
282    "Would you like to add users to the installed system now?" 0 0 && \
283    bsdinstall adduser
284
285finalconfig() {
286	exec 3>&1
287	REVISIT=$(dialog --backtitle "FreeBSD Installer" \
288	    --title "Final Configuration" --no-cancel --menu \
289	    "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 \
290		"Exit" "Apply configuration and exit installer" \
291		"Add User" "Add a user to the system" \
292		"Root Password" "Change root password" \
293		"Hostname" "Set system hostname" \
294		"Network" "Networking configuration" \
295		"Services" "Set daemons to run on startup" \
296		"Time Zone" "Set system timezone" \
297		"Handbook" "Install FreeBSD Handbook (requires network)" 2>&1 1>&3)
298	exec 3>&-
299
300	case "$REVISIT" in
301	"Add User")
302		bsdinstall adduser
303		finalconfig
304		;;
305	"Root Password")
306		bsdinstall rootpass
307		finalconfig
308		;;
309	"Hostname")
310		bsdinstall hostname
311		finalconfig
312		;;
313	"Network")
314		bsdinstall netconfig
315		finalconfig
316		;;
317	"Services")
318		bsdinstall services
319		finalconfig
320		;;
321	"Time Zone")
322		bsdinstall time
323		finalconfig
324		;;
325	"Handbook")
326		bsdinstall docsinstall
327		finalconfig
328		;;
329	esac
330}
331
332# Allow user to change his mind
333finalconfig
334
335trap error SIGINT	# SIGINT is bad again
336bsdinstall config  || error "Failed to save config"
337
338if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then
339	[ "$BSDINSTALL_FETCHDEST" != "$BSDINSTALL_DISTDIR" ] && \
340	    umount "$BSDINSTALL_DISTDIR"
341	rm -rf "$BSDINSTALL_FETCHDEST"
342fi
343
344dialog --backtitle "FreeBSD Installer" --title "Manual Configuration" \
345    --default-button no --yesno \
346   "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
347if [ $? -eq 0 ]; then
348	clear
349	mount -t devfs devfs "$BSDINSTALL_CHROOT/dev"
350	echo This shell is operating in a chroot in the new system. \
351	    When finished making configuration changes, type \"exit\".
352	chroot "$BSDINSTALL_CHROOT" /bin/sh 2>&1
353fi
354
355bsdinstall entropy
356bsdinstall umount
357
358f_dprintf "Installation Completed at %s" "$( date )"
359
360################################################################################
361# END
362################################################################################
363