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