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