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