1 #!/bin/sh 2 # $NetBSD: install.sh,v 1.29 2025/08/30 15:14:32 thorpej Exp $ 3 # 4 # Copyright (c) 1996,1997,1999,2000,2006 The NetBSD Foundation, Inc. 5 # All rights reserved. 6 # 7 # This code is derived from software contributed to The NetBSD Foundation 8 # by Jason R. Thorpe. 9 # 10 # Redistribution and use in source and binary forms, with or without 11 # modification, are permitted provided that the following conditions 12 # are met: 13 # 1. Redistributions of source code must retain the above copyright 14 # notice, this list of conditions and the following disclaimer. 15 # 2. Redistributions in binary form must reproduce the above copyright 16 # notice, this list of conditions and the following disclaimer in the 17 # documentation and/or other materials provided with the distribution. 18 # 19 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 # POSSIBILITY OF SUCH DAMAGE. 30 # 31 32 # NetBSD installation script. 33 # In a perfect world, this would be a nice C program, with a reasonable 34 # user interface. 35 36 FILESYSTEMS="/tmp/filesystems" # used throughout 37 FQDN="" # domain name 38 39 trap "umount /tmp > /dev/null 2>&1" 0 40 41 MODE="install" 42 43 # include machine-dependent functions 44 # The following functions must be provided: 45 # md_copy_kernel() - copy a kernel to the installed disk 46 # md_get_diskdevs() - return available disk devices 47 # md_get_cddevs() - return available CD-ROM devices 48 # md_get_ifdevs() - return available network interfaces 49 # md_get_partition_range() - return range of valid partition letters 50 # md_installboot() - install boot-blocks on disk 51 # md_labeldisk() - put label on a disk 52 # md_prep_disklabel() - label the root disk 53 # md_welcome_banner() - display friendly message 54 # md_not_going_to_install() - display friendly message 55 # md_congrats() - display friendly message 56 # md_native_fstype() - native filesystem type for disk installs 57 # md_native_fsopts() - native filesystem options for disk installs 58 # md_makerootwritable() - make root writable (at least /tmp) 59 60 # The following are optional: 61 # md_view_labels_possible - variable: md_view_labels defined 62 # md_view_labels - peek at preexisting disk labels, to 63 # better identify disks 64 65 # we need to make sure .'s below work if this directory is not in $PATH 66 # dirname may not be available but expr is 67 Mydir=$(expr $0 : '^\(.*\)/[^/]*$') 68 Mydir=$(cd ${Mydir:-.}; pwd) 69 70 # this is the most likely place to find the binary sets 71 # so save them having to type it in 72 Default_sets_dir=$Mydir/../../binary/sets 73 74 # include machine dependent subroutines 75 . $Mydir/install.md 76 77 # include common subroutines 78 . $Mydir/install.sub 79 80 # which sets? 81 THESETS="$ALLSETS $MDSETS" 82 83 # Good {morning,afternoon,evening,night}. 84 md_welcome_banner 85 echo -n "Proceed with installation? [n] " 86 getresp "n" 87 case "$resp" in 88 y*|Y*) 89 echo "Cool! Let's get to it..." 90 ;; 91 *) 92 md_not_going_to_install 93 exit 94 ;; 95 esac 96 97 # XXX Work around vnode aliasing bug (thanks for the tip, Chris...) 98 ls -l /dev > /dev/null 2>&1 99 100 # Deal with terminal issues 101 md_set_term 102 103 # Get timezone info 104 get_timezone 105 106 # Make sure we can write files (at least in /tmp) 107 # This might make an MFS mount on /tmp, or it may 108 # just re-mount the root with read-write enabled. 109 md_makerootwritable 110 111 # Create a disktab file; lets us write to it for temporary 112 # purposes without mounting the miniroot read-write. 113 echo "# disktab" > /tmp/disktab.shadow 114 115 test "$md_view_labels_possible" && md_view_labels 116 117 while [ -z "${ROOTDISK}" ]; do 118 getrootdisk 119 done 120 121 # Deal with disklabels, including editing the root disklabel 122 # and labeling additional disks. This is machine-dependent since 123 # some platforms may not be able to provide this functionality. 124 md_prep_disklabel ${ROOTDISK} 125 126 # Assume partition 'a' of $ROOTDISK is for the root filesystem. Loop and 127 # get the rest. 128 # XXX ASSUMES THAT THE USER DOESN'T PROVIDE BOGUS INPUT. 129 cat << \__get_filesystems_1 130 131 You will now have the opportunity to enter filesystem information. 132 You will be prompted for device name and mount point (full path, 133 including the prepending '/' character). 134 135 Note that these do not have to be in any particular order. You will 136 be given the opportunity to edit the resulting 'fstab' file before 137 any of the filesystems are mounted. At that time you will be able 138 to resolve any filesystem order dependencies. 139 140 __get_filesystems_1 141 142 echo "The following will be used for the root filesystem:" 143 echo " ${ROOTDISK}a /" 144 145 echo "${ROOTDISK}a /" > ${FILESYSTEMS} 146 147 resp="not-done" # force at least one iteration 148 while [ "$resp" != "done" ]; do 149 echo "" 150 echo -n "Device name? [RETURN if you already entered all devices] " 151 getresp "done" 152 case "$resp" in 153 done) 154 ;; 155 156 *) 157 _device_name=$(basename $resp) 158 159 # force at least one iteration 160 _first_char="X" 161 while [ "${_first_char}" != "/" ]; do 162 echo -n "Mount point? " 163 getresp "" 164 _mount_point=$resp 165 if [ "${_mount_point}" = "/" ]; then 166 # Invalid response; no multiple roots 167 _first_char="X" 168 else 169 _first_char=$(firstchar ${_mount_point}) 170 fi 171 done 172 echo "${_device_name} ${_mount_point}" >> ${FILESYSTEMS} 173 resp="X" # force loop to repeat 174 ;; 175 esac 176 done 177 178 # configure swap 179 resp="" # force at least one iteration 180 while [ -z "${resp}" ]; do 181 echo -n "Ok to configure ${ROOTDISK}b as a swap device? [] " 182 getresp "" 183 case "$resp" in 184 y*|Y*) 185 echo "${ROOTDISK}b swap" >> ${FILESYSTEMS} 186 ;; 187 n*|N*) 188 ;; 189 *) ;; 190 esac 191 done 192 193 194 echo "" 195 echo "You have configured the following devices and mount points:" 196 echo "" 197 cat ${FILESYSTEMS} 198 echo "" 199 echo "Filesystems will now be created on these devices. If you made any" 200 echo -n "mistakes, you may edit this now. Edit? [n] " 201 getresp "n" 202 case "$resp" in 203 y*|Y*) 204 ${EDITOR} ${FILESYSTEMS} 205 ;; 206 *) 207 ;; 208 esac 209 210 # Loop though the file, place filesystems on each device. 211 echo "Creating filesystems..." 212 ( 213 while read _device_name _mp; do 214 if [ "$_mp" != "swap" ]; then 215 newfs /dev/r${_device_name} 216 echo "" 217 fi 218 done 219 ) < ${FILESYSTEMS} 220 221 # Get network configuration information, and store it for placement in the 222 # root filesystem later. 223 cat << \__network_config_1 224 You will now be given the opportunity to configure the network. This will 225 be useful if you need to transfer the installation sets via FTP or NFS. 226 Even if you choose not to transfer installation sets that way, this 227 information will be preserved and copied into the new root filesystem. 228 229 Note, enter all symbolic host names WITHOUT the domain name appended. 230 I.e. use 'hostname' NOT 'hostname.domain.name'. 231 232 __network_config_1 233 echo -n "Configure the network? [y] " 234 getresp "y" 235 case "$resp" in 236 y*|Y*) 237 resp="" # force at least one iteration 238 if [ -f /etc/myname ]; then 239 resp=$(cat /etc/myname) 240 fi 241 echo -n "Enter system hostname: [$resp] " 242 while [ -z "${resp}" ]; do 243 getresp "$resp" 244 done 245 hostname $resp 246 echo $resp > /tmp/myname 247 248 echo -n "Enter DNS domain name: " 249 getresp "none" 250 if [ "${resp:-none}" != "none" ]; then 251 FQDN=$resp 252 fi 253 254 configurenetwork 255 256 echo -n "Enter IP address of default route: [none] " 257 getresp "none" 258 if [ "${resp:-none}" != "none" ]; then 259 route delete default > /dev/null 2>&1 260 if route add default $resp > /dev/null ; then 261 echo $resp > /tmp/mygate 262 fi 263 fi 264 265 resp="none" 266 if [ -n "${FQDN}" ]; then 267 echo -n "Enter IP address of primary nameserver: [none] " 268 getresp "none" 269 fi 270 if [ "${resp:-none}" != "none" ]; then 271 echo "domain $FQDN" > /tmp/resolv.conf 272 echo "nameserver $resp" >> /tmp/resolv.conf 273 echo "search $FQDN" >> /tmp/resolv.conf 274 275 echo -n "Would you like to use the nameserver now? [y] " 276 getresp "y" 277 case "$resp" in 278 y*|Y*) 279 cp /tmp/resolv.conf \ 280 /tmp/resolv.conf.shadow 281 ;; 282 283 *) 284 ;; 285 esac 286 fi 287 288 echo "" 289 echo "The host table is as follows:" 290 echo "" 291 cat /tmp/hosts 292 echo "" 293 echo "You may want to edit the host table in the event that" 294 echo "you need to mount an NFS server." 295 echo -n "Would you like to edit the host table? [n] " 296 getresp "n" 297 case "$resp" in 298 y*|Y*) 299 ${EDITOR} /tmp/hosts 300 ;; 301 302 *) 303 ;; 304 esac 305 306 cat << \__network_config_2 307 308 You will now be given the opportunity to escape to the command shell to 309 do any additional network configuration you may need. This may include 310 adding additional routes, if needed. In addition, you might take this 311 opportunity to redo the default route in the event that it failed above. 312 If you do change the default route, and wish for that change to carry over 313 to the installed system, execute the following command at the shell 314 prompt: 315 316 echo <ip_address_of_gateway> > /tmp/mygate 317 318 where <ip_address_of_gateway> is the IP address of the default router. 319 320 __network_config_2 321 echo -n "Escape to shell? [n] " 322 getresp "n" 323 case "$resp" in 324 y*|Y*) 325 echo "Type 'exit' to return to install." 326 sh 327 ;; 328 329 *) 330 ;; 331 esac 332 ;; 333 *) 334 ;; 335 esac 336 337 # Now that the network has been configured, it is safe to configure the 338 # fstab. 339 ( 340 while read _dev _mp; do 341 if [ "$_mp" = "/" ]; then 342 echo /dev/$_dev $_mp ffs rw 1 1 343 elif [ "$_mp" = "swap" ]; then 344 echo /dev/$_dev none swap sw 0 0 345 else 346 echo /dev/$_dev $_mp ffs rw 1 2 347 fi 348 done 349 350 # 351 # A PTYFS instance is required for programs that use 352 # pseudo-terminals (e.g. sshd). 353 # 354 echo ptyfs /dev/pts ptyfs rw 0 0 355 ) < ${FILESYSTEMS} > /tmp/fstab 356 357 echo "The fstab is configured as follows:" 358 echo "" 359 cat /tmp/fstab 360 cat << \__fstab_config_1 361 362 You may wish to edit the fstab. For example, you may need to resolve 363 dependencies in the order which the filesystems are mounted. You may 364 also wish to take this opportunity to place NFS mounts in the fstab. 365 This would be especially useful if you plan to keep '/usr' on an NFS 366 server. 367 368 __fstab_config_1 369 echo -n "Edit the fstab? [n] " 370 getresp "n" 371 case "$resp" in 372 y*|Y*) 373 ${EDITOR} /tmp/fstab 374 ;; 375 376 *) 377 ;; 378 esac 379 380 echo "" 381 munge_fstab /tmp/fstab /tmp/fstab.shadow 382 mount_fs /tmp/fstab.shadow 383 384 mount | while read line; do 385 set -- $line 386 if [ "$2" = "/" ] && [ "$3" = "nfs" ]; then 387 echo "You appear to be running diskless." 388 echo -n "Are the install sets on one of your currently mounted filesystems? [n] " 389 getresp "n" 390 case "$resp" in 391 y*|Y*) 392 get_localdir 393 ;; 394 *) 395 ;; 396 esac 397 fi 398 done 399 400 install_sets 401 402 # Copy in configuration information and make devices in target root. 403 ( 404 cd /tmp 405 for file in fstab ifconfig.* hosts myname mygate resolv.conf; do 406 if [ -f $file ]; then 407 echo -n "Copying $file..." 408 cp $file /mnt/etc/$file 409 echo "done." 410 fi 411 done 412 413 # Enable rc.conf 414 if [ -e /mnt/etc/rc.conf ]; then 415 cp /mnt/etc/rc.conf /tmp 416 sed 's/^rc_configured=NO/rc_configured=YES/' /tmp/rc.conf \ 417 > /mnt/etc/rc.conf 418 fi 419 420 # If no zoneinfo on the installfs, give them a second chance 421 if [ ! -e /usr/share/zoneinfo ]; then 422 get_timezone 423 fi 424 if [ ! -e /mnt/usr/share/zoneinfo ]; then 425 echo "Cannot install timezone link..." 426 else 427 echo -n "Installing timezone link..." 428 rm -f /mnt/etc/localtime 429 ln -s /usr/share/zoneinfo/$TZ /mnt/etc/localtime 430 echo "done." 431 fi 432 if [ ! -x /mnt/dev/MAKEDEV ]; then 433 echo "No /dev/MAKEDEV installed, something is wrong here..." 434 else 435 echo -n "Making devices..." 436 pid=$(twiddle) 437 cd /mnt/dev 438 sh MAKEDEV all 439 kill $pid 440 echo "done." 441 fi 442 md_copy_kernel 443 444 md_installboot ${ROOTDISK} 445 ) 446 447 unmount_fs /tmp/fstab.shadow 448 449 # Pat on the back. 450 md_congrats 451 452 # ALL DONE! 453 exit 0 454