wok view syslinux/stuff/iso2exe/iso2exe.sh @ rev 18802

syslinux/iso2exe.sh: fix clear_custom_config
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Jan 12 15:40:40 2016 +0100 (2016-01-12)
parents ec7b15533c2d
children 67f5b3bae0a8
line source
1 #!/bin/sh
3 ddq()
4 {
5 dd $@ 2> /dev/null
6 }
8 store()
9 {
10 n=$2; for i in $(seq 8 8 ${4:-16}); do
11 printf '\\\\x%02X' $(($n & 255))
12 n=$(($n >> 8))
13 done | xargs echo -en | ddq bs=1 conv=notrunc of=$3 seek=$(($1))
14 }
16 get()
17 {
18 echo $(od -j $(($1)) -N ${3:-2} -t u${3:-2} -An $2)
19 }
21 compress()
22 {
23 if [ "$1" ]; then
24 gzip -9 > $1
25 [ "$(which advdef 2> /dev/null)" ] &&
26 advdef -z4 $1 > /dev/null
27 elif [ "$(which xz 2> /dev/null)" ]; then
28 xz -z -e --format=lzma --lzma1=mode=normal --stdout
29 else
30 lzma e -si -so
31 fi 2> /dev/null
32 }
34 add_rootfs()
35 {
36 TMP=/tmp/iso2exe$$
37 mkdir -p $TMP/bin $TMP/dev
38 cp -a /dev/?d?* /dev/tty /dev/tty0 $TMP/dev
39 $0 --get init > $TMP/init.exe
40 # mount -o loop,ro $1 $TMP
41 # oldslitaz="$(ls $TMP/boot/isolinux/splash.lss 2> /dev/null)"
42 # umount -d $TMP
43 # [ "$oldslitaz" ] && # for SliTaz <= 3.0 only...
44 # grep -q mount.posixovl.iso2exe $TMP/init.exe &&
45 # cp /usr/sbin/mount.posixovl $TMP/bin/mount.posixovl.iso2exe \
46 # 2> /dev/null && echo "Store mount.posixovl ($(wc -c \
47 # < /usr/sbin/mount.posixovl) bytes) ..."
48 find $TMP -type f -print0 | xargs -0 chmod +x
49 ( cd $TMP ; find * | cpio -o -H newc ) | compress $TMP/rootfs.gz
50 SIZE=$(wc -c < $TMP/rootfs.gz)
51 store 24 $SIZE $1
52 OFS=$(( $OFS - $SIZE ))
53 printf "Adding rootfs.gz file at %04X (%d bytes) ...\n" $OFS $SIZE
54 cat $TMP/rootfs.gz | ddq of=$1 bs=1 seek=$OFS conv=notrunc
55 rm -rf $TMP
56 }
58 add_dosexe()
59 {
60 TMP=/tmp/bootiso$$
61 $0 --get bootiso.bin > $TMP 2> /dev/null
62 OFS=$(($(get 20 $TMP) - 0xC0))
63 printf "Adding DOS/EXE stub at %04X (%d bytes) ...\n" $OFS $((0x8000 - $OFS))
64 ddq if=$TMP bs=1 skip=$OFS of=$1 seek=$OFS conv=notrunc
65 rm -f $TMP
66 }
68 add_doscom()
69 {
70 SIZE=$($0 --get boot.com | wc -c)
71 OFS=$(( $OFS - $SIZE ))
72 printf "Adding DOS boot file at %04X (%d bytes) ...\n" $OFS $SIZE
73 $0 --get boot.com | ddq of=$1 bs=1 seek=$OFS conv=notrunc
74 store 64 $(($OFS+0xC0)) $1
75 }
77 add_tazlito_info()
78 {
79 HOLE=$OFS
80 [ $(get 0 $2) -eq 35615 ] || return
81 zcat $2 | gzip -9 > /tmp/rezipped$$.gz
82 [ "$(which advdef 2> /dev/null)" ] &&
83 advdef -z4 /tmp/rezipped$$.gz > /dev/null
84 n=$(stat -c %s /tmp/rezipped$$.gz)
85 printf "Moving tazlito data record at %04X ($n bytes) ...\n" $OFS
86 ddq if=/tmp/rezipped$$.gz bs=1 of=$1 seek=$OFS conv=notrunc
87 HOLE=$(($HOLE+$n))
88 rm -f /tmp/rezipped$$.gz
89 }
91 add_win32exe()
92 {
93 SIZE=$($0 --get win32.exe 2> /dev/null | tee /tmp/exe$$ | wc -c)
94 printf "Adding WIN32 file at %04X (%d bytes) ...\n" 0 $SIZE
95 ddq if=/tmp/exe$$ of=$1 conv=notrunc
96 printf "Adding bootiso head at %04X...\n" 0
97 $0 --get bootiso.bin 2> /dev/null > /tmp/exe$$
98 ddq if=/tmp/exe$$ of=$1 bs=128 count=1 conv=notrunc
99 store $((0x94)) $((0xE0 - 12*8)) $1
100 store $((0xF4)) $((16 - 12)) $1
101 ddq if=$1 of=/tmp/coff$$ bs=1 skip=$((0x178)) count=$((0x88))
102 ddq if=/tmp/coff$$ of=$1 conv=notrunc bs=1 seek=$((0x178 - 12*8))
103 ddq if=/tmp/exe$$ of=$1 bs=1 count=24 seek=$((0x1A0)) skip=$((0x1A0)) conv=notrunc
104 ddq if=$2 bs=1 skip=$((0x1B8)) seek=$((0x1B8)) count=72 of=$1 conv=notrunc
105 store 417 $(($SIZE/512)) $1 8
106 store 510 $((0xAA55)) $1
107 rm -f /tmp/exe$$ /tmp/coff$$
108 printf "Moving syslinux hybrid boot record at %04X (512 bytes) ...\n" $SIZE
109 ddq if=$2 bs=1 count=512 of=$1 seek=$SIZE conv=notrunc
110 OFS=$(($SIZE+512))
111 }
113 add_fdbootstrap()
114 {
115 SIZE=$($0 --get bootfd.bin 2> /dev/null | wc -c)
116 if [ $SIZE -ne 0 ]; then
117 SIZE=$(( $SIZE - 512 )) # sector 2 is data
118 OFS=$(( $OFS - $SIZE ))
119 printf "Adding floppy bootstrap file at %04X (%d bytes) ...\n" $OFS $SIZE
120 $0 --get bootfd.bin | \
121 ddq of=$1 bs=1 count=512 seek=$OFS conv=notrunc
122 $0 --get bootfd.bin | \
123 ddq of=$1 bs=1 skip=1024 seek=$((512 + $OFS)) conv=notrunc
124 store 26 $(($SIZE/512)) $1 8
125 fi
126 }
128 custom_config_sector()
129 {
130 echo $(($(get 32848 "$1" 4)+16))
131 }
133 clear_custom_config()
134 {
135 start=$(custom_config_sector $1)
136 cnt=$((512 - ($start % 512)))
137 [ $cnt -ne 512 ] &&
138 ddq if=/dev/zero of=$1 bs=2k seek=$start count=$cnt
139 }
141 extract_custom_config()
142 {
143 ISO="$1"
144 header=
145 ddq bs=2k skip=$(custom_config_sector "$ISO") if="$ISO" | \
146 while read line; do
147 case "$line" in
148 \#!boot*) header=1 ;;
149 append=*) [ "$header" ] &&
150 echo "${line#append=}" > "$ISO.append" &&
151 ls -l "$ISO.append" ;;
152 initrd:*) [ "$header" ] &&
153 ddq bs=1 count=${line#initrd:} > "$ISO.initrd" &&
154 ls -l "$ISO.initrd" ;;
155 esac
156 [ "$header" ] || break
157 done
158 }
159 case "$1" in
160 --build)
161 shift
162 ls -l $@
163 cat >> $0 <<EOM
164 $(tar cf - $@ | compress | uuencode -m -)
165 EOT
166 EOM
167 sed -i '/^case/,/^esac/d' $0
168 exit ;;
169 --get)
170 cat $2
171 exit ;;
172 --array)
173 DATA=/tmp/dataiso$$
174 ddq if=/dev/zero bs=32k count=1 of=$DATA
175 add_win32exe $DATA $2 > /dev/null
176 HSZ=$OFS
177 add_dosexe $DATA > /dev/null
178 add_rootfs $DATA > /dev/null
179 add_doscom $DATA > /dev/null
180 add_fdbootstrap $DATA > /dev/null
181 name=${3:-bootiso}
182 BOOTISOSZ=$((0x8000 - $OFS + $HSZ))
183 cat <<EOT
185 #define $(echo $name | tr '[a-z]' '[A-Z]')SZ $BOOTISOSZ
187 #ifndef __MSDOS__
188 static char $name[] = {
189 /* head */
190 $(hexdump -v -n $HSZ -e '" " 16/1 "0x%02X, "' -e '" // %04.4_ax |" 16/1 "%_p" "| \n"' $DATA | sed 's/ 0x ,/ /g')
191 /* tail */
192 $(hexdump -v -s $OFS -e '" " 16/1 "0x%02X, "' -e '" // %04.4_ax |" 16/1 "%_p" "| \n"' $DATA | sed 's/ 0x ,/ /g')
194 /* These strange constants are defined in RFC 1321 as
195 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
196 */
197 /* static const uint32_t C_array[64] */
198 EOT
199 while read a b c d; do
200 for i in $a $b $c $d; do
201 echo $i | sed 's/0x\(..\)\(..\)\(..\)\(..\),/0x\4, 0x\3, 0x\2, 0x\1, /'
202 done
203 done <<EOT
204 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
205 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
206 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
207 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
208 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
209 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
210 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
211 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
212 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
213 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
214 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
215 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
216 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
217 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
218 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
219 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
220 EOT
221 cat <<EOT
222 /* static const char P_array[64] */
223 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
224 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
225 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
226 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, /* 4 */
227 /* static const char S_array[16] */
228 7, 12, 17, 22,
229 5, 9, 14, 20,
230 4, 11, 16, 23,
231 6, 10, 15, 21,
232 EOT
234 for mode in data offset ; do
235 ofs=0
236 while read tag str; do
237 if [ "$mode" == "data" ]; then
238 echo -en "$str\0" | hexdump -v -e '" " 16/1 "0x%02X, "' \
239 -e '" // %04.4_ax |" 16/1 "%_p" "| \n"' | \
240 sed 's/ 0x ,/ /g'
241 else
242 if [ $ofs -eq 0 ]; then
243 cat <<EOT
244 };
245 #else
246 static char *$name;
247 #endif
249 #define C_array (uint32_t *) ($name + $(($BOOTISOSZ)))
250 #define P_array (char *) ($name + $(($BOOTISOSZ+(64*4))))
251 #define S_array (char *) ($name + $(($BOOTISOSZ+(64*4)+64)))
252 #define ELTORITOOFS 3
253 EOT
254 fi
255 echo "#define $tag $(($BOOTISOSZ+(64*4)+64+16+$ofs))"
256 ofs=$(($(echo -en "$str\0" | wc -c)+$ofs))
257 fi
258 done <<EOT
259 READSECTORERR Read sector failure.
260 USAGE Usage: isohybrid.exe [--append cmdline] [--initrd file] file.iso [--forced|--undo|--quick]
261 OPENERR Can't open r/w the iso file.
262 ELTORITOERR No EL TORITO SPECIFICATION signature.
263 CATALOGERR Invalid boot catalog.
264 HYBRIDERR No isolinux.bin hybrid signature.
265 SUCCESSMSG Now you can create a USB key with your .iso file.\\\\nSimply rename it to an .exe file and run it.
266 FORCEMSG You can add --forced to proceed anyway.
267 MD5MSG Computing md5sum...
268 UNINSTALLMSG Uninstall done.
269 OPENINITRDERR Can't open the initrd file.
270 ALREADYEXEERR Already an EXE file.
271 EOT
272 done
273 rm -rf $DATA
274 exit ;;
275 --exe)
276 # --exe mvcom.bin x.com y.exe > xy.exe
277 cat $4 $3 > /tmp/exe$$
278 S=$(stat -c %s /tmp/exe$$)
279 store 2 $(($S%512)) /tmp/exe$$
280 store 4 $((($S+511)/512)) /tmp/exe$$
281 store 14 -16 /tmp/exe$$
282 store 16 -2 /tmp/exe$$
283 store 20 256 /tmp/exe$$
284 store 22 -16 /tmp/exe$$
285 ddq if=$2 bs=1 seek=64 of=/tmp/exe$$ conv=notrunc
286 store 65 $(stat -c %s $3) /tmp/exe$$
287 store 68 $((0x100-0x40+$(stat -c %s $4))) /tmp/exe$$
288 cat /tmp/exe$$
289 rm -f /tmp/exe$$
290 exit ;;
291 esac
293 main()
294 {
295 [ $(id -u) -ne 0 ] && cmd="$0 $@" && exec su -c "$cmd" < /dev/tty
296 append=
297 initrd=
298 while [ "$1" ]; do
299 case "${1/--/-}" in
300 -get) shift
301 uudecode | unlzma | tar xOf - $@
302 exit ;;
303 -a*) append="$2" ; shift 2 ;;
304 -i*) initrd="$2" ; shift 2 ;;
305 -e*) extract_custom_config "$2"
306 exit ;;
307 *) cat > /dev/null
308 break
309 esac
310 done
312 [ ! -s "$1" ] && cat 1>&2 <<EOT && exit 1
313 usage: $0 [--append custom_cmdline ] [ --initrd custom_initramfs ] image.iso [--force|--undo|"DOS help message"]
314 or: $0 --extract-custom-config image.iso
315 EOT
316 case "${2/--/-}" in
317 -u*|-r*|-w*)
318 case "$(get 0 $1)" in
319 23117)
320 b=$(get 417 $1 1)
321 n=$(($(get 64 $1) + 0xC0 - ($(get 26 $1 1)*512) - ($b+1)*512))
322 ddq if=$1 bs=512 count=1 skip=$b of=$1 conv=notrunc
323 ddq if=/dev/zero bs=512 seek=1 count=1 of=$1 conv=notrunc
324 ddq if=$1 bs=512 seek=2 count=30 skip=$(($b+1)) of=$1 conv=notrunc
325 ddq if=/dev/zero bs=1 seek=$n count=$((0x8000 - $n)) of=$1 conv=notrunc ;;
326 *) ddq if=/dev/zero bs=1k count=32 of=$1 conv=notrunc ;;
327 esac
328 clear_custom_config $1
329 exit 0 ;;
330 -f*)
331 ddq if=/dev/zero bs=1k count=32 of=$1 conv=notrunc
332 [ "$append$initrd" ] && clear_custom_config $1
333 esac
334 case "$(get 0 $1)" in
335 23117) echo "The file $1 is already an EXE file." 1>&2 && exit 1;;
336 0) [ -x /usr/bin/isohybrid ] && isohybrid $1;;
337 esac
339 echo "Read hybrid & tazlito data..."
340 ddq if=$1 bs=512 count=1 of=/tmp/hybrid$$
341 ddq if=$1 bs=512 skip=2 count=20 of=/tmp/tazlito$$
342 add_win32exe $1 /tmp/hybrid$$
343 add_tazlito_info $1 /tmp/tazlito$$
344 rm -f /tmp/tazlito$$ /tmp/hybrid$$
346 # keep the largest room for the tazlito info file
347 add_dosexe $1
348 add_rootfs $1
349 add_doscom $1
350 add_fdbootstrap $1
351 printf "%d free bytes in %04X..%04X\n" $(($OFS-$HOLE)) $HOLE $OFS
352 store 440 $(date +%s) $1 32
353 [ "$2" ] && echo "$2 " | \
354 ddq bs=1 seek=$((0x7FDE)) count=15 conv=notrunc of=$1
355 if [ $(stat -c %s $1) -gt 34816 ]; then
356 echo "Adding ISO image md5 at 7FF0 (16 bytes) ..."
357 echo -en "$(ddq if=$1 bs=2k skip=16 count=$(get 32848 $1 4) | \
358 md5sum | cut -c-32 | sed 's/\(..\)/\\x\1/g')" | \
359 ddq bs=16 seek=2047 conv=notrunc of=$1
360 fi
361 echo -n "Adding boot checksum..."
362 if [ $(stat -c %s $1) -gt 32768 ]; then
363 n=$(($(get 2 $1) - 1 + ($(get 4 $1) - 1)*512))
364 n=$(($(od -v -N $n -t u2 -w2 -An $1 | \
365 awk '{ i+= $0 } END { print (i % 65536) }') \
366 + $(get $(($n+1)) $1 1)))
367 store 18 $(( (-$n -1) % 65536 )) $1
368 fi
369 echo " done."
370 if [ "$append$initrd" ]; then
371 echo -n "Adding custom config... "
372 DATA=/tmp/$(basename $0)$$
373 rm -f $DATA > /dev/null
374 isosz=$(stat -c %s $1)
375 [ "$append" ] && echo "append=$append" >> $DATA
376 [ -s "$initrd" ] && echo "initrd:$(stat -c %s $initrd)" >> $DATA &&
377 cat $initrd >> $DATA
378 echo "#!boot $(md5sum $DATA | sed 's/ .*//')" | cat - $DATA | \
379 ddq bs=2k seek=$(custom_config_sector $1) of=$1 conv=notrunc
380 if [ $(stat -c %s $1) -gt $isosz ]; then
381 echo "$(($(stat -c %s $1) - $isosz)) extra bytes."
382 else
383 echo "$(($isosz - 32768 - 2048*$(get 32848 $1 4)
384 - $(stat -c %s $DATA) - 24)) bytes free."
385 fi
386 rm -f $DATA > /dev/null
387 fi
388 }
390 main "$@" <<EOT