1 1.1 lukem #!/bin/sh 2 1.1 lukem # 3 1.20 andvar # $NetBSD: buildfloppies.sh,v 1.20 2022/01/24 09:42:13 andvar Exp $ 4 1.1 lukem # 5 1.6 lukem # Copyright (c) 2002-2003 The NetBSD Foundation, Inc. 6 1.1 lukem # All rights reserved. 7 1.1 lukem # 8 1.1 lukem # This code is derived from software contributed to The NetBSD Foundation 9 1.1 lukem # by Luke Mewburn of Wasabi Systems. 10 1.1 lukem # 11 1.1 lukem # Redistribution and use in source and binary forms, with or without 12 1.1 lukem # modification, are permitted provided that the following conditions 13 1.1 lukem # are met: 14 1.1 lukem # 1. Redistributions of source code must retain the above copyright 15 1.1 lukem # notice, this list of conditions and the following disclaimer. 16 1.1 lukem # 2. Redistributions in binary form must reproduce the above copyright 17 1.1 lukem # notice, this list of conditions and the following disclaimer in the 18 1.1 lukem # documentation and/or other materials provided with the distribution. 19 1.1 lukem # 20 1.1 lukem # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 lukem # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 lukem # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 lukem # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 lukem # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 lukem # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 lukem # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 lukem # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 lukem # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 lukem # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 lukem # POSSIBILITY OF SUCH DAMAGE. 31 1.1 lukem # 32 1.1 lukem 33 1.1 lukem # set defaults 34 1.1 lukem # 35 1.1 lukem : ${PAX=pax} 36 1.1 lukem prog=${0##*/} 37 1.17 apb etcdir=/etc 38 1.1 lukem 39 1.1 lukem 40 1.1 lukem usage() 41 1.1 lukem { 42 1.1 lukem cat 1>&2 << _USAGE_ 43 1.17 apb Usage: ${prog} [options] base size file [...] 44 1.17 apb -i instboot eval instboot as a shell command to install a 45 1.20 andvar bootstrap. @IMAGE@ is replaced with the 46 1.17 apb file name of the floppy image. 47 1.1 lukem -m max maximum number of floppies to build 48 1.17 apb -N etcdir directory in which to find passwd and group files. 49 1.1 lukem -p pad last floppy to floppy size 50 1.3 lukem -s suffix suffix for floppies 51 1.18 christos -t timestamp set timestamp for reproducible builds 52 1.1 lukem base basename of generated floppies 53 1.1 lukem size size of a floppy in 512 byte blocks 54 1.17 apb file [...] file(s) to store in the floppies 55 1.1 lukem _USAGE_ 56 1.1 lukem exit 1 57 1.1 lukem } 58 1.1 lukem 59 1.1 lukem plural() 60 1.1 lukem { 61 1.19 kre [ "$1" -ne 1 ] && echo "s" 62 1.1 lukem } 63 1.1 lukem 64 1.7 lukem roundup() 65 1.7 lukem { 66 1.19 kre echo $(( ( ( $1 ) + ( $2 ) - 1 ) / ( $2 ) )) 67 1.7 lukem } 68 1.7 lukem 69 1.1 lukem 70 1.1 lukem # parse and check arguments 71 1.1 lukem # 72 1.1 lukem 73 1.18 christos while getopts i:m:N:ps:t: opt; do 74 1.1 lukem case ${opt} in 75 1.1 lukem i) 76 1.1 lukem instboot=${OPTARG} ;; 77 1.1 lukem m) 78 1.1 lukem maxdisks=${OPTARG} ;; 79 1.17 apb N) 80 1.17 apb etcdir=${OPTARG} ;; 81 1.1 lukem p) 82 1.1 lukem pad=1 ;; 83 1.3 lukem s) 84 1.3 lukem suffix=${OPTARG} ;; 85 1.18 christos t) 86 1.18 christos timestamp="--timestamp ${OPTARG}" ;; 87 1.1 lukem \?|*) 88 1.1 lukem usage 89 1.1 lukem ;; 90 1.1 lukem esac 91 1.1 lukem done 92 1.1 lukem 93 1.1 lukem shift $(( ${OPTIND} - 1 )) 94 1.1 lukem [ $# -lt 3 ] && usage 95 1.1 lukem floppybase=$1 96 1.1 lukem floppysize=$2 97 1.1 lukem shift 2 98 1.1 lukem files=$* 99 1.1 lukem 100 1.1 lukem # setup temp file, remove existing images 101 1.1 lukem # 102 1.1 lukem floppy=floppy.$$.tar 103 1.1 lukem trap "rm -f ${floppy}" 0 1 2 3 # EXIT HUP INT QUIT 104 1.17 apb rm -f ${floppybase}?${suffix} # XXX breaks if maxdisks > 9 105 1.1 lukem 106 1.1 lukem # create tar file 107 1.1 lukem # 108 1.1 lukem dd if=/dev/zero of=${floppy} bs=8k count=1 2>/dev/null 109 1.17 apb ( 110 1.17 apb echo ". type=dir optional" 111 1.17 apb for f in ${files}; do 112 1.17 apb echo "./$f type=file uname=root gname=wheel mode=0444" 113 1.17 apb done 114 1.17 apb ) | \ 115 1.18 christos ${PAX} ${timestamp} -O -w -b8k -M -N "${etcdir}" -s,^./,, >> ${floppy} || exit 1 116 1.17 apb 117 1.17 apb # install bootstrap before the image is split into multiple disks 118 1.17 apb # 119 1.1 lukem if [ -n "$instboot" ]; then 120 1.1 lukem instboot=$( echo $instboot | sed -e s/@IMAGE@/${floppy}/ ) 121 1.1 lukem echo "Running instboot: ${instboot}" 122 1.2 tv eval ${instboot} || exit 1 123 1.1 lukem fi 124 1.1 lukem 125 1.1 lukem # check size against available number of disks 126 1.1 lukem # 127 1.12 dsl set -- $(ls -ln $floppy) 128 1.12 dsl bytes=$5 129 1.7 lukem blocks=$(roundup ${bytes} 512) 130 1.7 lukem # when calculating numdisks, take into account: 131 1.7 lukem # a) the image already has an 8K tar header prepended 132 1.7 lukem # b) each floppy needs an 8K tar volume header 133 1.7 lukem numdisks=$(roundup ${blocks}-16 ${floppysize}-16) 134 1.1 lukem if [ -z "${maxdisks}" ]; then 135 1.1 lukem maxdisks=${numdisks} 136 1.1 lukem fi 137 1.1 lukem 138 1.12 dsl # Try to accurately summarise free space 139 1.12 dsl # 140 1.12 dsl msg= 141 1.17 apb # First floppy has 8k boot code, the rest an 8k 'multivolume header'. 142 1.17 apb # Each file has a 512 byte header and is rounded to a multiple of 512. 143 1.17 apb # The archive ends with two 512 byte blocks of zeros. 144 1.17 apb # The output file is then rounded up to a multiple of 8k. 145 1.17 apb # floppysize is in units of 512-byte blocks; free_space is in bytes. 146 1.12 dsl free_space=$(($maxdisks * ($floppysize - 16) * 512 - 512 * 2)) 147 1.12 dsl for file in $files; do 148 1.12 dsl set -- $(ls -ln $file) 149 1.12 dsl file_bytes=$5 150 1.12 dsl pad_bytes=$(($(roundup $file_bytes 512) * 512 - $file_bytes)) 151 1.19 kre if [ "$file_bytes" != 0 ] || [ "$file" = "${file#USTAR.volsize.}" ] 152 1.19 kre then 153 1.12 dsl msg="$msg $file $pad_bytes," 154 1.19 kre fi 155 1.12 dsl free_space=$(($free_space - 512 - $file_bytes - $pad_bytes)) 156 1.12 dsl done 157 1.12 dsl echo "Free space in last tar block:$msg" 158 1.12 dsl 159 1.1 lukem if [ ${numdisks} -gt ${maxdisks} ]; then 160 1.12 dsl # Add in the size of the last item (we really want the kernel) ... 161 1.12 dsl excess=$(( 0 - $free_space + $pad_bytes)) 162 1.1 lukem echo 1>&2 \ 163 1.1 lukem "$prog: Image is ${excess} bytes ($(( ${excess} / 1024 )) KB)"\ 164 1.1 lukem "too big to fit on ${maxdisks} disk"$(plural ${maxdisks}) 165 1.1 lukem exit 1 166 1.1 lukem fi 167 1.1 lukem 168 1.12 dsl padto=$(( ${floppysize} * ${maxdisks} )) 169 1.1 lukem if [ -n "${pad}" ]; then 170 1.1 lukem echo \ 171 1.12 dsl "Writing $(( ${padto} * 512 )) bytes ($(( ${padto} / 2 )) KB)" \ 172 1.1 lukem "on ${numdisks} disk"$(plural ${numdisks})"," \ 173 1.12 dsl "padded by ${free_space} bytes" \ 174 1.12 dsl "($(( ${free_space} / 1024 )) KB)" 175 1.1 lukem else 176 1.1 lukem echo "Writing ${bytes} bytes ($(( ${blocks} / 2 )) KB)"\ 177 1.5 dsl "on ${numdisks} disk"$(plural ${numdisks})"," \ 178 1.12 dsl "free space ${free_space} bytes" \ 179 1.12 dsl "($(( ${free_space} / 1024 )) KB)" 180 1.1 lukem fi 181 1.1 lukem 182 1.1 lukem # write disks 183 1.1 lukem # 184 1.1 lukem curdisk=1 185 1.1 lukem image= 186 1.8 dsl seek=0 187 1.8 dsl skip=0 188 1.1 lukem floppysize8k=$(( ${floppysize} / 16 )) 189 1.1 lukem while [ ${curdisk} -le ${numdisks} ]; do 190 1.3 lukem image="${floppybase}${curdisk}${suffix}" 191 1.1 lukem echo "Creating disk ${curdisk} to ${image}" 192 1.1 lukem if [ ${curdisk} -eq 1 ]; then 193 1.1 lukem : > ${image} 194 1.1 lukem else 195 1.1 lukem echo USTARFS ${curdisk} > ${image} 196 1.1 lukem fi 197 1.1 lukem count=$(( ${floppysize8k} - ${seek} )) 198 1.1 lukem dd bs=8k conv=sync seek=${seek} skip=${skip} count=${count} \ 199 1.1 lukem if=${floppy} of=${image} 2>/dev/null 200 1.1 lukem 201 1.1 lukem curdisk=$(( ${curdisk} + 1 )) 202 1.8 dsl skip=$(( $skip + $count )) 203 1.8 dsl seek=1 204 1.1 lukem done 205 1.1 lukem 206 1.1 lukem # pad last disk if necessary 207 1.1 lukem # 208 1.1 lukem if [ -n "${pad}" ]; then 209 1.8 dsl dd if=$image of=$image conv=notrunc conv=sync bs=${floppysize}b count=1 210 1.1 lukem fi 211 1.1 lukem 212 1.1 lukem 213 1.1 lukem # final status 214 1.1 lukem # 215 1.1 lukem echo "Final result:" 216 1.17 apb ls -l ${floppybase}?${suffix} # XXX breaks if maxdisks > 9 217 1.1 lukem 218 1.1 lukem exit 0 219