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

syslinux/iso2exe.sh: show flavor.info size
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Jan 16 16:19:14 2016 +0100 (2016-01-16)
parents 6e468bea3c84
children fc572791f0a0
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/dev
38 cp -a /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 && mkdir $TMP/bin &&
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 gzsize()
129 {
130 echo $(($(hexdump -C | awk ' {
131 for (i = 2; i < 18; i++) if ($i != "00") break;
132 if (i == 18) {
133 for (i = 17; i > 1; i--) if ($i != "00") break;
134 print "0x" $1 " + 2 - " (16 - i)
135 exit
136 }
137 }')))
138 }
140 fileofs()
141 {
142 [ $(get 1024 "$ISO") -eq 35615 ] && i=1024 ||
143 i=$((512*(1+$(get 417 "$ISO" 1))))
144 stub=$(($(get 20 "$ISO") - 0xC0))
145 SIZE=0; OFFSET=0
146 case "$1" in
147 win32.exe) [ $i -eq 1024 ] || SIZE=$(($i - 512));;
148 syslinux.mbr) [ $i -eq 1024 ] || OFFSET=$(($i - 512)); SIZE=512;;
149 flavor.info) OFFSET=$i
150 SIZE=$(ddq bs=512 skip=$(($i/512)) if="$ISO" | gzsize);;
151 floppy.boot) SIZE=$(($(get 26 "$ISO" 1)*512))
152 OFFSET=$(($(get 64 "$ISO") - 0xC0 - $SIZE));;
153 rootfs.gz) SIZE=$(get 24 "$ISO"); OFFSET=$(($stub - $SIZE));;
154 tazboot.com) OFFSET=$(($(get 64 "$ISO") - 0xC0))
155 SIZE=$(($stub - $(get 24 "$ISO") - $OFFSET));;
156 dosstub) OFFSET=$stub; SIZE=$((0x8000 - $OFFSET));;
157 md5) OFFSET=$((0x7FF0)); SIZE=16;;
158 esac
159 }
161 list()
162 {
163 HEAP=0
164 TOP=32768
165 for f in win32.exe syslinux.mbr flavor.info floppy.boot \
166 tazboot.com rootfs.gz dosstub md5 ; do
167 fileofs $f
168 [ $SIZE -eq 0 ] && continue
169 [ "${OFFSET:6}" ] && continue
170 [ $OFFSET -lt 0 ] && continue
171 [ $(get $OFFSET "$ISO") -eq 0 ] && continue
172 printf "$f at %04X ($SIZE bytes).\n" $OFFSET
173 if [ $OFFSET -le $i ]; then
174 [ $OFFSET -ge $HEAP ] && HEAP=$(($OFFSET+$SIZE))
175 else
176 [ $OFFSET -lt $TOP ] && TOP=$OFFSET
177 fi
178 done
179 printf "%d free bytes in %04X..%04X\n" $(($TOP - $HEAP)) $HEAP $TOP
180 }
182 extract()
183 {
184 for f in $@; do
185 fileofs $f
186 [ $SIZE -eq 0 ] ||
187 ddq bs=1 count=$SIZE skip=$OFFSET if="$ISO" >$f
188 done
189 }
191 custom_config_sector()
192 {
193 echo $(($(get 32848 "$1" 4)+16))
194 }
196 clear_custom_config()
197 {
198 start=$(custom_config_sector $1)
199 cnt=$((512 - ($start % 512)))
200 [ $cnt -ne 512 ] &&
201 ddq if=/dev/zero of=$1 bs=2k seek=$start count=$cnt
202 }
204 extract_custom_config()
205 {
206 ISO="$1"
207 header=
208 ddq bs=2k skip=$(custom_config_sector "$ISO") if="$ISO" | \
209 while read line; do
210 case "$line" in
211 \#!boot*) header=1 ;;
212 append=*) [ "$header" ] &&
213 echo "${line#append=}" > "$ISO.append" &&
214 ls -l "$ISO.append" ;;
215 initrd:*) [ "$header" ] &&
216 ddq bs=1 count=${line#initrd:} > "$ISO.initrd" &&
217 ls -l "$ISO.initrd" ;;
218 esac
219 [ "$header" ] || break
220 done
221 }
222 case "$1" in
223 --build)
224 shift
225 ls -l $@
226 cat >> $0 <<EOM
227 $(tar cf - $@ | compress | uuencode -m -)
228 EOT
229 EOM
230 sed -i '/^case/,/^esac/d' $0
231 exit ;;
232 --get)
233 cat $2
234 exit ;;
235 --array)
236 DATA=/tmp/dataiso$$
237 ddq if=/dev/zero bs=32k count=1 of=$DATA
238 add_win32exe $DATA $2 > /dev/null
239 HSZ=$OFS
240 add_dosexe $DATA > /dev/null
241 add_rootfs $DATA > /dev/null
242 add_doscom $DATA > /dev/null
243 add_fdbootstrap $DATA > /dev/null
244 name=${3:-bootiso}
245 BOOTISOSZ=$((0x8000 - $OFS + $HSZ))
246 cat <<EOT
248 #define $(echo $name | tr '[a-z]' '[A-Z]')SZ $BOOTISOSZ
250 #ifndef __MSDOS__
251 static char $name[] = {
252 /* head */
253 $(hexdump -v -n $HSZ -e '" " 16/1 "0x%02X, "' -e '" // %04.4_ax |" 16/1 "%_p" "| \n"' $DATA | sed 's/ 0x ,/ /g')
254 /* tail */
255 $(hexdump -v -s $OFS -e '" " 16/1 "0x%02X, "' -e '" // %04.4_ax |" 16/1 "%_p" "| \n"' $DATA | sed 's/ 0x ,/ /g')
257 /* These strange constants are defined in RFC 1321 as
258 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
259 */
260 /* static const uint32_t C_array[64] */
261 EOT
262 while read a b c d; do
263 for i in $a $b $c $d; do
264 echo $i | sed 's/0x\(..\)\(..\)\(..\)\(..\),/0x\4, 0x\3, 0x\2, 0x\1, /'
265 done
266 done <<EOT
267 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
268 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
269 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
270 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
271 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
272 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
273 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
274 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
275 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
276 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
277 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
278 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
279 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
280 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
281 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
282 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
283 EOT
284 cat <<EOT
285 /* static const char P_array[64] */
286 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
287 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
288 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
289 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, /* 4 */
290 /* static const char S_array[16] */
291 7, 12, 17, 22,
292 5, 9, 14, 20,
293 4, 11, 16, 23,
294 6, 10, 15, 21,
295 EOT
297 for mode in data offset ; do
298 ofs=0
299 while read tag str; do
300 if [ "$mode" == "data" ]; then
301 echo -en "$str\0" | hexdump -v -e '" " 16/1 "0x%02X, "' \
302 -e '" // %04.4_ax |" 16/1 "%_p" "| \n"' | \
303 sed 's/ 0x ,/ /g'
304 else
305 if [ $ofs -eq 0 ]; then
306 cat <<EOT
307 };
308 #else
309 static char *$name;
310 #endif
312 #define C_array (uint32_t *) ($name + $(($BOOTISOSZ)))
313 #define P_array (char *) ($name + $(($BOOTISOSZ+(64*4))))
314 #define S_array (char *) ($name + $(($BOOTISOSZ+(64*4)+64)))
315 #define ELTORITOOFS 3
316 EOT
317 fi
318 echo "#define $tag $(($BOOTISOSZ+(64*4)+64+16+$ofs))"
319 ofs=$(($(echo -en "$str\0" | wc -c)+$ofs))
320 fi
321 done <<EOT
322 READSECTORERR Read sector failure.
323 USAGE Usage: isohybrid.exe [--append cmdline] [--initrd file] file.iso [--forced|--undo|--quick]
324 OPENERR Can't open r/w the iso file.
325 ELTORITOERR No EL TORITO SPECIFICATION signature.
326 CATALOGERR Invalid boot catalog.
327 HYBRIDERR No isolinux.bin hybrid signature.
328 SUCCESSMSG Now you can create a USB key with your .iso file.\\\\nSimply rename it to an .exe file and run it.
329 FORCEMSG You can add --forced to proceed anyway.
330 MD5MSG Computing md5sum...
331 UNINSTALLMSG Uninstall done.
332 OPENINITRDERR Can't open the initrd file.
333 ALREADYEXEERR Already an EXE file.
334 EOT
335 done
336 rm -rf $DATA
337 exit ;;
338 --exe)
339 # --exe mvcom.bin x.com y.exe > xy.exe
340 cat $4 $3 > /tmp/exe$$
341 S=$(stat -c %s /tmp/exe$$)
342 store 2 $(($S%512)) /tmp/exe$$
343 store 4 $((($S+511)/512)) /tmp/exe$$
344 store 14 -16 /tmp/exe$$
345 store 16 -2 /tmp/exe$$
346 store 20 256 /tmp/exe$$
347 store 22 -16 /tmp/exe$$
348 ddq if=$2 bs=1 seek=64 of=/tmp/exe$$ conv=notrunc
349 store 65 $(stat -c %s $3) /tmp/exe$$
350 store 68 $((0x100-0x40+$(stat -c %s $4))) /tmp/exe$$
351 cat /tmp/exe$$
352 rm -f /tmp/exe$$
353 exit ;;
354 esac
356 main()
357 {
358 [ $(id -u) -ne 0 ] && cmd="$0 $@" && exec su -c "$cmd" < /dev/tty
359 append=
360 initrd=
361 while [ "$1" ]; do
362 case "${1/--/-}" in
363 -get) shift
364 uudecode | unlzma | tar xOf - $@
365 exit ;;
366 -a*) append="$2" ; shift 2 ;;
367 -i*) initrd="$2" ; shift 2 ;;
368 -e*) extract_custom_config "$2"
369 exit ;;
370 -r*) ISO="$2" ; shift 2
371 [ -z "$1" ] && list || extract $@
372 exit ;;
373 *) cat > /dev/null
374 break
375 esac
376 done
378 [ ! -s "$1" ] && cat 1>&2 <<EOT && exit 1
379 usage: $0 [--append custom_cmdline ] [ --initrd custom_initramfs ] image.iso [--force|--undo|"DOS help message"]
380 or: $0 --extract-custom-config image.iso
381 EOT
382 case "${2/--/-}" in
383 -u*|-r*|-w*|-f*)
384 case "$(get 0 $1)" in
385 23117)
386 b=$(get 417 $1 1)
387 n=$(($(get 64 $1) + 0xC0 - ($(get 26 $1 1)*512) - ($b+1)*512))
388 ddq if=$1 bs=512 count=1 skip=$b of=$1 conv=notrunc
389 ddq if=/dev/zero bs=512 seek=1 count=1 of=$1 conv=notrunc
390 ddq if=$1 bs=512 seek=2 count=30 skip=$(($b+1)) of=$1 conv=notrunc
391 ddq if=/dev/zero bs=1 seek=$n count=$((0x8000 - $n)) of=$1 conv=notrunc ;;
392 *) ddq if=/dev/zero bs=1k count=32 of=$1 conv=notrunc ;;
393 esac
394 case "${2/--/-}" in
395 -f*)
396 [ "$append$initrd" ] && clear_custom_config $1 ;;
397 *)
398 clear_custom_config $1
399 exit 0 ;;
400 esac
401 esac
402 case "$(get 0 $1)" in
403 23117) echo "The file $1 is already an EXE file." 1>&2 && exit 1;;
404 0) [ -x /usr/bin/isohybrid ] && isohybrid $1;;
405 esac
407 echo "Read hybrid & tazlito data..."
408 ddq if=$1 bs=512 count=1 of=/tmp/hybrid$$
409 ddq if=$1 bs=512 skip=2 count=20 of=/tmp/tazlito$$
410 add_win32exe $1 /tmp/hybrid$$
411 add_tazlito_info $1 /tmp/tazlito$$
412 rm -f /tmp/tazlito$$ /tmp/hybrid$$
414 # keep the largest room for the tazlito info file
415 add_dosexe $1
416 add_rootfs $1
417 add_doscom $1
418 add_fdbootstrap $1
419 printf "%d free bytes in %04X..%04X\n" $(($OFS-$HOLE)) $HOLE $OFS
420 store 440 $(date +%s) $1 32
421 [ "$2" ] && echo "$2 " | \
422 ddq bs=1 seek=$((0x7FDE)) count=15 conv=notrunc of=$1
423 if [ $(stat -c %s $1) -gt 34816 ]; then
424 echo "Adding ISO image md5 at 7FF0 (16 bytes) ..."
425 echo -en "$(ddq if=$1 bs=2k skip=16 count=$(get 32848 $1 4) | \
426 md5sum | cut -c-32 | sed 's/\(..\)/\\x\1/g')" | \
427 ddq bs=16 seek=2047 conv=notrunc of=$1
428 fi
429 echo -n "Adding boot checksum..."
430 if [ $(stat -c %s $1) -gt 32768 ]; then
431 n=$(($(get 2 $1) - 1 + ($(get 4 $1) - 1)*512))
432 n=$(($(od -v -N $n -t u2 -w2 -An $1 | \
433 awk '{ i+= $0 } END { print (i % 65536) }') \
434 + $(get $(($n+1)) $1 1)))
435 store 18 $(( (-$n -1) % 65536 )) $1
436 fi
437 echo " done."
438 if [ "$append$initrd" ]; then
439 echo -n "Adding custom config... "
440 DATA=/tmp/$(basename $0)$$
441 rm -f $DATA > /dev/null
442 isosz=$(stat -c %s $1)
443 [ "$append" ] && echo "append=$append" >> $DATA
444 [ -s "$initrd" ] && echo "initrd:$(stat -c %s $initrd)" >> $DATA &&
445 cat $initrd >> $DATA
446 echo "#!boot $(md5sum $DATA | sed 's/ .*//')" | cat - $DATA | \
447 ddq bs=2k seek=$(custom_config_sector $1) of=$1 conv=notrunc
448 if [ $(stat -c %s $1) -gt $isosz ]; then
449 echo "$(($(stat -c %s $1) - $isosz)) extra bytes."
450 else
451 echo "$(($isosz - 32768 - 2048*$(get 32848 $1 4)
452 - $(stat -c %s $DATA) - 24)) bytes free."
453 fi
454 rm -f $DATA > /dev/null
455 fi
456 }
458 main "$@" <<EOT