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# Reset the ESP list 182: > ${TMPDIR:-"/tmp"}/bsdinstall-esps 183 184# With pkgbase, pkg OOM has been observed with QEMU-default 128 MiB memory size. 185# Ensure we have at least about 256 MiB (with an allowance for rounding etc.). 186physmem=$(($(sysctl -n hw.physmem) / 1048576)) 187if [ $physmem -lt 200 ]; then 188 bsddialog --backtitle "$OSNAME Installer" --title "Warning" \ 189 --msgbox "Insufficient physical memory (${physmem} MiB) detected. At least 256 MiB is recommended. The installer or installed system may not function correctly." 0 0 190fi 191 192[ -f /usr/libexec/bsdinstall/local.pre-everything ] && f_dprintf "Running local.pre-everything" && sh /usr/libexec/bsdinstall/local.pre-everything "$BSDINSTALL_CHROOT" 193 194trap true SIGINT # This section is optional 195[ -z "$BSDINSTALL_SKIP_KEYMAP" ] && bsdinstall keymap 196 197trap error SIGINT # Catch cntrl-C here 198if [ -z "$BSDINSTALL_SKIP_HOSTNAME" ]; then bsdinstall hostname || error "Set hostname failed"; fi 199 200if [ -f /usr/freebsd-packages/repos/FreeBSD-base-offline.conf ]; then 201 HAVE_BASE_PACKAGES=yes 202 PKGBASE_DEFAULT_BUTTON=--default-no 203else 204 unset HAVE_BASE_PACKAGES 205 unset PKGBASE_DEFAULT_BUTTON 206fi 207 208if [ ! -f $BSDINSTALL_DISTDIR/MANIFEST ]; then 209 PKGBASE=yes 210else 211 bsddialog --backtitle "$OSNAME Installer" --title "Select Installation Type" \ 212 --yes-label "Traditional" --no-label "Packages (Experimental)" --yesno \ 213 $PKGBASE_DEFAULT_BUTTON \ 214 "Would you like to install the base system using traditional distribution sets or packages (experimental)?" 0 0 215 if [ $? -eq 1 ]; then 216 PKGBASE=yes 217 fi 218fi 219 220if [ "$PKGBASE" == yes ]; then 221 if [ "$HAVE_BASE_PACKAGES" == yes ]; then 222 bsddialog --backtitle "$OSNAME Installer" --title "Network or Offline Installation" \ 223 --yes-label "Network" --no-label "Offline (Limited Packages)" --yesno \ 224 "Would you like to fetch packages from the internet or use the limited set of packages included in this installation media?" 0 0 225 if [ $? -eq 1 ]; then 226 export BSDINSTALL_PKG_REPOS_DIR=/usr/freebsd-packages/repos/ 227 else 228 bsdinstall netconfig || error 229 NETCONFIG_DONE=yes 230 fi 231 else 232 bsddialog --backtitle "$OSNAME Installer" --title "Network Installation" \ 233 --msgbox "No base system packages are included in this installation media. The next few screens will allow you to configure networking." 0 0 234 bsdinstall netconfig || error 235 NETCONFIG_DONE=yes 236 fi 237else 238 export DISTRIBUTIONS="${DISTRIBUTIONS:-base.txz kernel.txz}" 239 if [ -f $BSDINSTALL_DISTDIR/MANIFEST ]; then 240 DISTMENU=`awk -F'\t' '!/^(kernel\.txz|base\.txz)/{print $1,$5,$6}' $BSDINSTALL_DISTDIR/MANIFEST` 241 DISTMENU="$(echo ${DISTMENU} | sed -E 's/\.txz//g')" 242 243 if [ -n "$DISTMENU" ]; then 244 exec 5>&1 245 EXTRA_DISTS=$( eval bsddialog \ 246 --backtitle \"$OSNAME Installer\" \ 247 --title \"Distribution Select\" --nocancel --separate-output \ 248 --checklist \"Choose optional system components to install:\" \ 249 0 0 0 $DISTMENU \ 250 2>&1 1>&5 ) 251 for dist in $EXTRA_DISTS; do 252 export DISTRIBUTIONS="$DISTRIBUTIONS $dist.txz" 253 done 254 fi 255 fi 256 257 FETCH_DISTRIBUTIONS="" 258 for dist in $DISTRIBUTIONS; do 259 if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then 260 FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist" 261 fi 262 done 263 264 if [ -n "$FETCH_DISTRIBUTIONS" -a -n "$BSDINSTALL_CONFIGCURRENT" ]; then 265 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 266 bsdinstall netconfig || error 267 NETCONFIG_DONE=yes 268 fi 269fi 270 271rm -f $PATH_FSTAB 272touch $PATH_FSTAB 273 274[ -f /usr/libexec/bsdinstall/local.pre-partition ] && f_dprintf "Running local.pre-partition" && sh /usr/libexec/bsdinstall/local.pre-partition "$BSDINSTALL_CHROOT" 275 276# 277# Try to detect known broken platforms and apply their workarounds 278# 279 280if f_interactive; then 281 sys_maker=$( kenv -q smbios.system.maker ) 282 f_dprintf "smbios.system.maker=[%s]" "$sys_maker" 283 sys_model=$( kenv -q smbios.system.product ) 284 f_dprintf "smbios.system.product=[%s]" "$sys_model" 285 sys_version=$( kenv -q smbios.system.version ) 286 f_dprintf "smbios.system.version=[%s]" "$sys_version" 287 sys_mb_maker=$( kenv -q smbios.planar.maker ) 288 f_dprintf "smbios.planar.maker=[%s]" "$sys_mb_maker" 289 sys_mb_product=$( kenv -q smbios.planar.product ) 290 f_dprintf "smbios.planar.product=[%s]" "$sys_mb_product" 291 292 # 293 # Laptop Models 294 # 295 case "$sys_maker" in 296 "LENOVO") 297 case "$sys_version" in 298 "ThinkPad X220"|"ThinkPad T420"|"ThinkPad T520"|"ThinkPad W520"|"ThinkPad X1") 299 dialog_workaround "$msg_lenovo_fix" 300 retval=$? 301 f_dprintf "lenovofix_prompt=[%s]" "$retval" 302 if [ $retval -eq $DIALOG_OK ]; then 303 export ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix" 304 export WORKAROUND_LENOVO=1 305 fi 306 ;; 307 esac 308 ;; 309 "Dell Inc.") 310 case "$sys_model" in 311 "Latitude E6330"|"Latitude E7440"|"Latitude E7240"|"Precision Tower 5810") 312 dialog_workaround "$msg_gpt_active_fix" 313 retval=$? 314 f_dprintf "gpt_active_fix_prompt=[%s]" "$retval" 315 if [ $retval -eq $DIALOG_OK ]; then 316 export ZFSBOOT_PARTITION_SCHEME="GPT + Active" 317 export WORKAROUND_GPTACTIVE=1 318 fi 319 ;; 320 esac 321 ;; 322 "Hewlett-Packard") 323 case "$sys_model" in 324 "HP ProBook 4330s") 325 dialog_workaround "$msg_gpt_active_fix" 326 retval=$? 327 f_dprintf "gpt_active_fix_prompt=[%s]" "$retval" 328 if [ $retval -eq $DIALOG_OK ]; then 329 export ZFSBOOT_PARTITION_SCHEME="GPT + Active" 330 export WORKAROUND_GPTACTIVE=1 331 fi 332 ;; 333 esac 334 ;; 335 esac 336 # 337 # Motherboard Models 338 # 339 case "$sys_mb_maker" in 340 "Intel Corporation") 341 case "$sys_mb_product" in 342 "DP965LT"|"D510MO") 343 dialog_workaround "$msg_gpt_active_fix" 344 retval=$? 345 f_dprintf "gpt_active_fix_prompt=[%s]" "$retval" 346 if [ $retval -eq $DIALOG_OK ]; then 347 export ZFSBOOT_PARTITION_SCHEME="GPT + Active" 348 export WORKAROUND_GPTACTIVE=1 349 fi 350 ;; 351 esac 352 ;; 353 "Acer") 354 case "$sys_mb_product" in 355 "Veriton M6630G") 356 dialog_workaround "$msg_gpt_active_fix" 357 retval=$? 358 f_dprintf "gpt_active_fix_prompt=[%s]" "$retval" 359 if [ $retval -eq $DIALOG_OK ]; then 360 export ZFSBOOT_PARTITION_SCHEME="GPT + Active" 361 export WORKAROUND_GPTACTIVE=1 362 fi 363 ;; 364 esac 365 ;; 366 esac 367fi 368 369PMODES=" 370 '$msg_auto_ufs' '$msg_auto_ufs_desc' '$msg_auto_ufs_help' 371 '$msg_manual' '$msg_manual_desc' '$msg_manual_help' 372 '$msg_shell' '$msg_shell_desc' '$msg_shell_help' 373" # END-QUOTE 374 375CURARCH=$( uname -m ) 376case $CURARCH in 377 amd64|arm64|i386|riscv) # Booting ZFS Supported 378 PMODES=" 379 '$msg_auto_zfs' '$msg_auto_zfs_desc' '$msg_auto_zfs_help' 380 $PMODES 381 " # END-QUOTE 382 ;; 383 *) # Booting ZFS Unsupported 384 ;; 385esac 386 387exec 5>&1 388PARTMODE=`echo $PMODES | xargs -o bsddialog --backtitle "$OSNAME Installer" \ 389 --title "Partitioning" \ 390 --item-help \ 391 --menu "How would you like to partition your disk?" \ 392 0 0 0 2>&1 1>&5` || exit 1 393exec 5>&- 394 395case "$PARTMODE" in 396"$msg_auto_zfs") # ZFS 397 bsdinstall zfsboot || error "ZFS setup failed" 398 bsdinstall mount || error "Failed to mount filesystem" 399 ;; 400"$msg_auto_ufs") # Guided UFS 401 bsdinstall autopart || error "Partitioning error" 402 bsdinstall mount || error "Failed to mount filesystem" 403 ;; 404"$msg_shell") # Shell 405 clear 406 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'." 407 sh 2>&1 408 ;; 409"$msg_manual") # Manual 410 if f_isset debugFile; then 411 # Give partedit the path to our logfile so it can append 412 BSDINSTALL_LOG="${debugFile#+}" bsdinstall partedit || error "Partitioning error" 413 else 414 bsdinstall partedit || error "Partitioning error" 415 fi 416 bsdinstall mount || error "Failed to mount filesystem" 417 ;; 418*) 419 error "Unknown partitioning mode" 420 ;; 421esac 422 423[ -f /usr/libexec/bsdinstall/local.pre-fetch ] && f_dprintf "Running local.pre-fetch" && sh /usr/libexec/bsdinstall/local.pre-fetch "$BSDINSTALL_CHROOT" 424 425if [ "$PKGBASE" == yes ]; then 426 bsdinstall pkgbase || error "Installation of base system packages failed" 427else 428 if [ -n "$FETCH_DISTRIBUTIONS" ]; then 429 exec 5>&1 430 export BSDINSTALL_DISTDIR=$(`dirname $0`/fetchmissingdists 2>&1 1>&5) 431 FETCH_RESULT=$? 432 exec 5>&- 433 434 [ $FETCH_RESULT -ne 0 ] && error "Could not fetch remote distributions" 435 fi 436 bsdinstall checksum || error "Distribution checksum failed" 437 bsdinstall distextract || error "Distribution extract failed" 438fi 439 440# Set up boot loader 441bsdinstall bootconfig || error "Failed to configure bootloader" 442 443[ -f /usr/libexec/bsdinstall/local.pre-configure ] && f_dprintf "Running local.pre-configure" && sh /usr/libexec/bsdinstall/local.pre-configure "$BSDINSTALL_CHROOT" 444 445bsdinstall rootpass || error "Could not set root password" 446 447trap true SIGINT # This section is optional 448if [ "$NETCONFIG_DONE" != yes ]; then 449 bsdinstall netconfig # Don't check for errors -- the user may cancel 450fi 451[ -z "$BSDINSTALL_SKIP_TIME" ] && bsdinstall time 452[ -z "$BSDINSTALL_SKIP_SERVICES" ] && bsdinstall services 453[ -z "$BSDINSTALL_SKIP_HARDENING" ] && bsdinstall hardening 454[ -z "$BSDINSTALL_SKIP_FIRMWARE" ] && bsdinstall firmware 455 456[ -z "$BSDINSTALL_SKIP_USERS" ] && bsddialog --backtitle "$OSNAME Installer" \ 457 --title "Add User Accounts" --yesno \ 458 "Would you like to add users to the installed system now?" 0 0 && \ 459 bsdinstall adduser 460 461# Allow user to change his mind 462[ -z "$BSDINSTALL_SKIP_FINALCONFIG" ] && bsdinstall finalconfig 463 464trap error SIGINT # SIGINT is bad again 465bsdinstall config || error "Failed to save config" 466 467if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then 468 rm -rf "$BSDINSTALL_FETCHDEST" 469fi 470 471[ -f /usr/libexec/bsdinstall/local.post-configure ] && f_dprintf "Running local.post-configure" && sh /usr/libexec/bsdinstall/local.post-configure "$BSDINSTALL_CHROOT" 472 473if [ -z "$BSDINSTALL_SKIP_MANUAL" ]; then 474 bsddialog --backtitle "$OSNAME Installer" --title "Manual Configuration" \ 475 --default-no --yesno \ 476 "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 477 if [ $? -eq 0 ]; then 478 clear 479 echo This shell is operating in a chroot in the new system. \ 480 When finished making configuration changes, type \"exit\". 481 chroot "$BSDINSTALL_CHROOT" /bin/sh -l 2>&1 482 fi 483fi 484 485bsdinstall entropy 486bsdinstall umount 487 488f_dprintf "Installation Completed at %s" "$( date )" 489 490################################################################################ 491# END 492################################################################################ 493