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