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