]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bsdinstall/scripts/auto
MFV r361280:
[FreeBSD/FreeBSD.git] / usr.sbin / bsdinstall / scripts / auto
1 #!/bin/sh
2 #-
3 # Copyright (c) 2011 Nathan Whitehorn
4 # Copyright (c) 2013-2018 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
32 BSDCFG_SHARE="/usr/share/bsdconfig"
33 . $BSDCFG_SHARE/common.subr || exit 1
34 f_include $BSDCFG_SHARE/dialog.subr
35
36 ############################################################ GLOBALS
37
38 #
39 # Strings that should be moved to an i18n file and loaded with f_include_lang()
40 #
41 hline_arrows_tab_enter="Press arrows, TAB or ENTER"
42 hline_arrows_tab_space_enter="Press arrows, TAB, SPACE or ENTER"
43 msg_abort="Abort"
44 msg_an_installation_step_has_been_aborted="An installation step has been aborted. Would you like\nto restart the installation or exit the installer?"
45 msg_auto_ufs="Auto (UFS)"
46 msg_auto_ufs_desc="Guided UFS Disk Setup"
47 msg_auto_ufs_help="Menu options help choose which disk to setup using UFS and standard partitions"
48 msg_auto_zfs="Auto (ZFS)"
49 msg_auto_zfs_desc="Guided Root-on-ZFS"
50 msg_auto_zfs_help="To use ZFS with less than 8GB RAM, see https://wiki.freebsd.org/ZFSTuningGuide"
51 msg_exit="Exit"
52 msg_freebsd_installer="FreeBSD Installer"
53 msg_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?"
54 msg_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?"
55 msg_manual="Manual"
56 msg_manual_desc="Manual Disk Setup (experts)"
57 msg_manual_help="Create customized partitions from menu options"
58 msg_no="NO"
59 msg_restart="Restart"
60 msg_shell="Shell"
61 msg_shell_desc="Open a shell and partition by hand"
62 msg_shell_help="Create customized partitions using command-line utilities"
63 msg_yes="YES"
64
65 ############################################################ FUNCTIONS
66
67 # error [$msg]
68 #
69 # Display generic error message when a script fails. An optional message
70 # argument can preceed the generic message. User is given the choice of
71 # restarting the installer or exiting.
72 #
73 error()
74 {
75         local title="$msg_abort"
76         local btitle="$msg_freebsd_installer"
77         local prompt="${1:+$1\n\n}$msg_an_installation_step_has_been_aborted"
78         local hline="$hline_arrows_tab_space_enter"
79
80         [ "$DISTDIR_IS_UNIONFS" ] && umount -f "$BSDINSTALL_DISTDIR"
81         [ -f "$PATH_FSTAB" ] && bsdinstall umount
82
83         local height width
84         f_dialog_buttonbox_size height width \
85                 "$title" "$btitle" "$prompt" "$hline"
86
87         if $DIALOG \
88                 --title "$title"           \
89                 --backtitle "$btitle"      \
90                 --hline "$hline"           \
91                 --no-label "$msg_exit"     \
92                 --yes-label "$msg_restart" \
93                 --yesno "$prompt" $height $width
94         then
95                 exec $0
96                 # NOTREACHED
97         fi
98         exit 1
99 }
100
101 # dialog_workaround
102 #
103 # Ask the user if they wish to apply a workaround
104 #
105 dialog_workaround()
106 {
107         local passed_msg="$1"
108         local title="$DIALOG_TITLE"
109         local btitle="$DIALOG_BACKTITLE"
110         local prompt # Calculated below
111         local hline="$hline_arrows_tab_enter"
112
113         local height=8 width=50 prefix="   "
114         local plen=${#prefix} list= line=
115         local max_width=$(( $width - 3 - $plen ))
116
117         local yes no defaultno extra_args format
118         if [ "$USE_XDIALOG" ]; then
119                 yes=ok no=cancel defaultno=default-no
120                 extra_args="--wrap --left"
121                 format="$passed_msg"
122         else
123                 yes=yes no=no defaultno=defaultno
124                 extra_args="--cr-wrap"
125                 format="$passed_msg"
126         fi
127
128         # Add height for Xdialog(1)
129         [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 ))
130
131         prompt=$( printf "$format" )
132         f_dprintf "%s: Workaround prompt" "$0"
133         $DIALOG \
134                 --title "$title"        \
135                 --backtitle "$btitle"   \
136                 --hline "$hline"        \
137                 --$yes-label "$msg_yes" \
138                 --$no-label "$msg_no"   \
139                 $extra_args             \
140                 --yesno "$prompt" $height $width
141 }
142
143 ############################################################ MAIN
144
145 f_dprintf "Began Installation at %s" "$( date )"
146
147 rm -rf $BSDINSTALL_TMPETC
148 mkdir $BSDINSTALL_TMPETC
149
150 trap true SIGINT        # This section is optional
151 bsdinstall keymap
152
153 trap error SIGINT       # Catch cntrl-C here
154 bsdinstall hostname || error "Set hostname failed"
155
156 export DISTRIBUTIONS="base.txz kernel.txz"
157 if [ -f $BSDINSTALL_DISTDIR/MANIFEST ]; then
158         DISTMENU=`awk -F'\t' '!/^(kernel\.txz|base\.txz)/{print $1,$5,$6}' $BSDINSTALL_DISTDIR/MANIFEST`
159         DISTMENU="$(echo ${DISTMENU} | sed -E 's/\.txz//g')"
160
161         exec 3>&1
162         EXTRA_DISTS=$( eval dialog \
163             --backtitle \"FreeBSD Installer\" \
164             --title \"Distribution Select\" --nocancel --separate-output \
165             --checklist \"Choose optional system components to install:\" \
166             0 0 0 $DISTMENU \
167         2>&1 1>&3 )
168         for dist in $EXTRA_DISTS; do
169                 export DISTRIBUTIONS="$DISTRIBUTIONS $dist.txz"
170         done
171 fi
172
173 LOCAL_DISTRIBUTIONS="MANIFEST"
174 FETCH_DISTRIBUTIONS=""
175 for dist in $DISTRIBUTIONS; do
176         if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
177                 FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
178         else
179                 LOCAL_DISTRIBUTIONS="$LOCAL_DISTRIBUTIONS $dist"
180         fi
181 done
182 LOCAL_DISTRIBUTIONS=`echo $LOCAL_DISTRIBUTIONS` # Trim white space
183 FETCH_DISTRIBUTIONS=`echo $FETCH_DISTRIBUTIONS` # Trim white space
184
185 if [ -n "$FETCH_DISTRIBUTIONS" -a -n "$BSDINSTALL_CONFIGCURRENT" ]; then
186         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
187         bsdinstall netconfig || error
188         NETCONFIG_DONE=yes
189 fi
190
191 if [ -n "$FETCH_DISTRIBUTIONS" ]; then
192         exec 3>&1
193         BSDINSTALL_DISTSITE=$(`dirname $0`/mirrorselect 2>&1 1>&3)
194         MIRROR_BUTTON=$?
195         exec 3>&-
196         test $MIRROR_BUTTON -eq 0 || error "No mirror selected"
197         export BSDINSTALL_DISTSITE
198 fi
199
200 rm -f $PATH_FSTAB
201 touch $PATH_FSTAB
202
203 #
204 # Try to detect known broken platforms and apply their workarounds
205 #
206
207 if f_interactive; then
208         sys_maker=$( kenv -q smbios.system.maker )
209         f_dprintf "smbios.system.maker=[%s]" "$sys_maker"
210         sys_model=$( kenv -q smbios.system.product )
211         f_dprintf "smbios.system.product=[%s]" "$sys_model"
212         sys_version=$( kenv -q smbios.system.version )
213         f_dprintf "smbios.system.version=[%s]" "$sys_version"
214         sys_mb_maker=$( kenv -q smbios.planar.maker )
215         f_dprintf "smbios.planar.maker=[%s]" "$sys_mb_maker"
216         sys_mb_product=$( kenv -q smbios.planar.product )
217         f_dprintf "smbios.planar.product=[%s]" "$sys_mb_product"
218
219         #
220         # Laptop Models
221         #
222         case "$sys_maker" in
223         "LENOVO")
224                 case "$sys_version" in
225                 "ThinkPad X220"|"ThinkPad T420"|"ThinkPad T520"|"ThinkPad W520"|"ThinkPad X1")
226                         dialog_workaround "$msg_lenovo_fix"
227                         retval=$?
228                         f_dprintf "lenovofix_prompt=[%s]" "$retval"
229                         if [ $retval -eq $DIALOG_OK ]; then
230                                 export ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix"
231                                 export WORKAROUND_LENOVO=1
232                         fi
233                         ;;
234                 esac
235                 ;;
236         "Dell Inc.")
237                 case "$sys_model" in
238                 "Latitude E6330"|"Latitude E7440"|"Latitude E7240"|"Precision Tower 5810")
239                         dialog_workaround "$msg_gpt_active_fix"
240                         retval=$?
241                         f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
242                         if [ $retval -eq $DIALOG_OK ]; then
243                                 export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
244                                 export WORKAROUND_GPTACTIVE=1
245                         fi
246                         ;;
247                 esac
248                 ;;
249         "Hewlett-Packard")
250                 case "$sys_model" in
251                 "HP ProBook 4330s")
252                         dialog_workaround "$msg_gpt_active_fix"
253                         retval=$?
254                         f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
255                         if [ $retval -eq $DIALOG_OK ]; then
256                                 export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
257                                 export WORKAROUND_GPTACTIVE=1
258                         fi
259                         ;;
260                 esac
261                 ;;
262         esac
263         #
264         # Motherboard Models
265         #
266         case "$sys_mb_maker" in
267         "Intel Corporation")
268                 case "$sys_mb_product" in
269                 "DP965LT"|"D510MO")
270                         dialog_workaround "$msg_gpt_active_fix"
271                         retval=$?
272                         f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
273                         if [ $retval -eq $DIALOG_OK ]; then
274                                 export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
275                                 export WORKAROUND_GPTACTIVE=1
276                         fi
277                         ;;
278                 esac
279                 ;;
280         "Acer")
281                 case "$sys_mb_product" in
282                 "Veriton M6630G")
283                         dialog_workaround "$msg_gpt_active_fix"
284                         retval=$?
285                         f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
286                         if [ $retval -eq $DIALOG_OK ]; then
287                                 export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
288                                 export WORKAROUND_GPTACTIVE=1
289                         fi
290                         ;;
291                 esac
292                 ;;
293         esac
294 fi
295
296 PMODES="
297         '$msg_auto_ufs' '$msg_auto_ufs_desc' '$msg_auto_ufs_help'
298         '$msg_manual' '$msg_manual_desc' '$msg_manual_help'
299         '$msg_shell' '$msg_shell_desc' '$msg_shell_help'
300 " # END-QUOTE
301
302 CURARCH=$( uname -m )
303 case $CURARCH in
304         amd64|arm64|i386)       # Booting ZFS Supported
305                 PMODES="
306                         '$msg_auto_zfs' '$msg_auto_zfs_desc' '$msg_auto_zfs_help'
307                         $PMODES
308                 " # END-QUOTE
309                 ;;
310         *)                      # Booting ZFS Unsupported
311                 ;;
312 esac
313
314 exec 3>&1
315 PARTMODE=`echo $PMODES | xargs dialog --backtitle "FreeBSD Installer" \
316         --title "Partitioning" \
317         --item-help \
318         --menu "How would you like to partition your disk?" \
319         0 0 0 2>&1 1>&3` || exit 1
320 exec 3>&-
321
322 case "$PARTMODE" in
323 "$msg_auto_zfs")        # ZFS
324         bsdinstall zfsboot || error "ZFS setup failed"
325         bsdinstall mount || error "Failed to mount filesystem"
326         ;;
327 "$msg_auto_ufs")        # Guided UFS
328         bsdinstall autopart || error "Partitioning error"
329         bsdinstall mount || error "Failed to mount filesystem"
330         ;;
331 "$msg_shell")           # Shell
332         clear
333         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'."
334         sh 2>&1
335         ;;
336 "$msg_manual")          # Manual
337         if f_isset debugFile; then
338                 # Give partedit the path to our logfile so it can append
339                 BSDINSTALL_LOG="${debugFile#+}" bsdinstall partedit || error "Partitioning error"
340         else
341                 bsdinstall partedit || error "Partitioning error"
342         fi
343         bsdinstall mount || error "Failed to mount filesystem"
344         ;;
345 *)
346         error "Unknown partitioning mode"
347         ;;
348 esac
349
350 if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then
351         ALL_DISTRIBUTIONS="$DISTRIBUTIONS"
352         WANT_DEBUG=
353
354         # Download to a directory in the new system as scratch space
355         BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
356         mkdir -p "$BSDINSTALL_FETCHDEST" || error "Could not create directory $BSDINSTALL_FETCHDEST"
357
358         export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
359         # Try to use any existing distfiles
360         if [ -d $BSDINSTALL_DISTDIR ]; then
361                 DISTDIR_IS_UNIONFS=1
362                 mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
363         else
364                 export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
365                 export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
366         fi
367
368         export FTP_PASSIVE_MODE=YES
369         # Iterate through the distribution list and set a flag if debugging
370         # distributions have been selected.
371         for _DISTRIBUTION in $DISTRIBUTIONS; do
372                 case $_DISTRIBUTION in
373                         *-dbg.*)
374                                 [ -e $BSDINSTALL_DISTDIR/$_DISTRIBUTION ] \
375                                         && continue
376                                 WANT_DEBUG=1
377                                 DEBUG_LIST="\n$DEBUG_LIST\n$_DISTRIBUTION"
378                                 ;;
379                         *)
380                                 ;;
381                 esac
382         done
383
384         # Fetch the distributions.
385         bsdinstall distfetch
386         rc=$?
387
388         if [ $rc -ne 0 ]; then
389                 # If unable to fetch the remote distributions, recommend
390                 # deselecting the debugging distributions, and retrying the
391                 # installation, since failure to fetch *-dbg.txz should not
392                 # be considered a fatal installation error.
393                 msg="Failed to fetch remote distribution"
394                 if [ ! -z "$WANT_DEBUG" ]; then
395                         # Trim leading and trailing newlines.
396                         DEBUG_LIST="${DEBUG_LIST%%\n}"
397                         DEBUG_LIST="${DEBUG_LIST##\n}"
398                         msg="$msg\n\nPlease deselect the following distributions"
399                         msg="$msg and retry the installation:"
400                         msg="$msg\n$DEBUG_LIST"
401                 fi
402                 error "$msg"
403         fi
404         export DISTRIBUTIONS="$ALL_DISTRIBUTIONS"
405 fi
406
407 if [ ! -z "$LOCAL_DISTRIBUTIONS" ]; then
408         # Download to a directory in the new system as scratch space
409         BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
410         mkdir -p "$BSDINSTALL_FETCHDEST" || error "Could not create directory $BSDINSTALL_FETCHDEST"
411         # Try to use any existing distfiles
412         if [ -d $BSDINSTALL_DISTDIR ]; then
413                 DISTDIR_IS_UNIONFS=1
414                 mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
415                 export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
416         fi
417         env DISTRIBUTIONS="$LOCAL_DISTRIBUTIONS" \
418                 BSDINSTALL_DISTSITE="file:///usr/freebsd-dist" \
419                 bsdinstall distfetch || \
420                 error "Failed to fetch distribution from local media"
421 fi
422
423 bsdinstall checksum || error "Distribution checksum failed"
424 bsdinstall distextract || error "Distribution extract failed"
425
426 # Set up boot loader
427 bsdinstall bootconfig || error "Failed to configure bootloader"
428
429 bsdinstall rootpass || error "Could not set root password"
430
431 trap true SIGINT        # This section is optional
432 if [ "$NETCONFIG_DONE" != yes ]; then
433         bsdinstall netconfig    # Don't check for errors -- the user may cancel
434 fi
435 bsdinstall time
436 bsdinstall services
437 bsdinstall hardening
438
439 dialog --backtitle "FreeBSD Installer" --title "Add User Accounts" --yesno \
440     "Would you like to add users to the installed system now?" 0 0 && \
441     bsdinstall adduser
442
443 finalconfig() {
444         exec 3>&1
445         REVISIT=$(dialog --backtitle "FreeBSD Installer" \
446             --title "Final Configuration" --no-cancel --menu \
447             "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 \
448                 "Exit" "Apply configuration and exit installer" \
449                 "Add User" "Add a user to the system" \
450                 "Root Password" "Change root password" \
451                 "Hostname" "Set system hostname" \
452                 "Network" "Networking configuration" \
453                 "Services" "Set daemons to run on startup" \
454                 "System Hardening" "Set security options" \
455                 "Time Zone" "Set system timezone" \
456                 "Handbook" "Install FreeBSD Handbook (requires network)" 2>&1 1>&3)
457         exec 3>&-
458
459         case "$REVISIT" in
460         "Add User")
461                 bsdinstall adduser
462                 finalconfig
463                 ;;
464         "Root Password")
465                 bsdinstall rootpass
466                 finalconfig
467                 ;;
468         "Hostname")
469                 bsdinstall hostname
470                 finalconfig
471                 ;;
472         "Network")
473                 bsdinstall netconfig
474                 finalconfig
475                 ;;
476         "Services")
477                 bsdinstall services
478                 finalconfig
479                 ;;
480         "System Hardening")
481                 bsdinstall hardening
482                 finalconfig
483                 ;;
484         "Time Zone")
485                 bsdinstall time
486                 finalconfig
487                 ;;
488         "Handbook")
489                 bsdinstall docsinstall
490                 finalconfig
491                 ;;
492         esac
493 }
494
495 # Allow user to change his mind
496 finalconfig
497
498 trap error SIGINT       # SIGINT is bad again
499 bsdinstall config  || error "Failed to save config"
500
501 if [ -n "$DISTDIR_IS_UNIONFS" ]; then
502         umount -f $BSDINSTALL_DISTDIR
503 fi
504
505 if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then
506         rm -rf "$BSDINSTALL_FETCHDEST"
507 fi
508
509 dialog --backtitle "FreeBSD Installer" --title "Manual Configuration" \
510     --default-button no --yesno \
511    "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
512 if [ $? -eq 0 ]; then
513         clear
514         echo This shell is operating in a chroot in the new system. \
515             When finished making configuration changes, type \"exit\".
516         chroot "$BSDINSTALL_CHROOT" /bin/sh 2>&1
517 fi
518
519 bsdinstall entropy
520 bsdinstall umount
521
522 f_dprintf "Installation Completed at %s" "$( date )"
523
524 ################################################################################
525 # END
526 ################################################################################