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

Add gnubg
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Feb 22 21:29:18 2016 +0100 (2016-02-22)
parents f937073af512
children dbf4eeed945f
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 * | grep -v rootfs.gz | cpio -o -H newc ) | \
50 compress $TMP/rootfs.gz
51 SIZE=$(wc -c < $TMP/rootfs.gz)
52 store 24 $SIZE $1
53 OFS=$(( $OFS - $SIZE ))
54 printf "Adding rootfs.gz file at %04X (%d bytes) ...\n" $OFS $SIZE
55 cat $TMP/rootfs.gz | ddq of=$1 bs=1 seek=$OFS conv=notrunc
56 rm -rf $TMP
57 }
59 add_dosexe()
60 {
61 TMP=/tmp/bootiso$$
62 $0 --get bootiso.bin > $TMP 2> /dev/null
63 OFS=$(($(get 20 $TMP) - 0xC0))
64 printf "Adding DOS/EXE stub at %04X (%d bytes) ...\n" $OFS $((0x8000 - $OFS))
65 ddq if=$TMP bs=1 skip=$OFS of=$1 seek=$OFS conv=notrunc
66 rm -f $TMP
67 }
69 add_doscom()
70 {
71 SIZE=$($0 --get boot.com | wc -c)
72 OFS=$(( $OFS - $SIZE ))
73 printf "Adding DOS boot file at %04X (%d bytes) ...\n" $OFS $SIZE
74 $0 --get boot.com | ddq of=$1 bs=1 seek=$OFS conv=notrunc
75 store 64 $(($OFS+0xC0)) $1
76 }
78 add_tazlito_info()
79 {
80 HOLE=$OFS
81 [ $(get 0 $2) -eq 35615 ] || return
82 zcat $2 | gzip -9 > /tmp/rezipped$$.gz
83 [ "$(which advdef 2> /dev/null)" ] &&
84 advdef -z4 /tmp/rezipped$$.gz > /dev/null
85 n=$(stat -c %s /tmp/rezipped$$.gz)
86 printf "Moving tazlito data record at %04X ($n bytes) ...\n" $OFS
87 ddq if=/tmp/rezipped$$.gz bs=1 of=$1 seek=$OFS conv=notrunc
88 HOLE=$(($HOLE+$n))
89 rm -f /tmp/rezipped$$.gz
90 }
92 add_win32exe()
93 {
94 SIZE=$($0 --get win32.exe 2> /dev/null | tee /tmp/exe$$ | wc -c)
95 printf "Adding WIN32 file at %04X (%d bytes) ...\n" 0 $SIZE
96 ddq if=/tmp/exe$$ of=$1 conv=notrunc
97 printf "Adding bootiso head at %04X...\n" 0
98 $0 --get bootiso.bin 2> /dev/null > /tmp/exe$$
99 ddq if=/tmp/exe$$ of=$1 bs=128 count=1 conv=notrunc
100 store $((0x94)) $((0xE0 - 12*8)) $1
101 store $((0xF4)) $((16 - 12)) $1
102 ddq if=$1 of=/tmp/coff$$ bs=1 skip=$((0x178)) count=$((0x88))
103 ddq if=/tmp/coff$$ of=$1 conv=notrunc bs=1 seek=$((0x178 - 12*8))
104 ddq if=/tmp/exe$$ of=$1 bs=1 count=24 seek=$((0x1A0)) skip=$((0x1A0)) conv=notrunc
105 ddq if=$2 bs=1 skip=$((0x1B8)) seek=$((0x1B8)) count=72 of=$1 conv=notrunc
106 store 417 $(($SIZE/512)) $1 8
107 store 510 $((0xAA55)) $1
108 rm -f /tmp/exe$$ /tmp/coff$$
109 printf "Moving syslinux hybrid boot record at %04X (512 bytes) ...\n" $SIZE
110 ddq if=$2 bs=1 count=512 of=$1 seek=$SIZE conv=notrunc
111 OFS=$(($SIZE+512))
112 }
114 add_fdbootstrap()
115 {
116 SIZE=$($0 --get bootfd.bin 2> /dev/null | wc -c)
117 if [ $SIZE -ne 0 ]; then
118 SIZE=$(( $SIZE - 512 )) # sector 2 is data
119 OFS=$(( $OFS - $SIZE ))
120 printf "Adding floppy bootstrap file at %04X (%d bytes) ...\n" $OFS $SIZE
121 $0 --get bootfd.bin | \
122 ddq of=$1 bs=1 count=512 seek=$OFS conv=notrunc
123 $0 --get bootfd.bin | \
124 ddq of=$1 bs=1 skip=1024 seek=$((512 + $OFS)) conv=notrunc
125 store 26 $(($SIZE/512)) $1 8
126 fi
127 }
129 gzsize()
130 {
131 echo $(($(hexdump -C | awk ' {
132 for (i = 2; i < 18; i++) if ($i != "00") break;
133 if (i == 18) {
134 for (i = 17; i > 1; i--) if ($i != "00") break;
135 print "0x" $1 " + 2 - " (16 - i)
136 exit
137 }
138 }')))
139 }
141 fileofs()
142 {
143 [ $(get 1024 "$ISO") -eq 35615 ] && i=1024 ||
144 i=$((512*(1+$(get 417 "$ISO" 1))))
145 stub=$(($(get 20 "$ISO") - 0xC0))
146 c=$(custom_config_sector "$ISO")
147 SIZE=0; OFFSET=0
148 case "$1" in
149 win32.exe) [ $i -eq 1024 ] || SIZE=$(($i - 512));;
150 syslinux.mbr) [ $i -eq 1024 ] || OFFSET=$(($i - 512)); SIZE=512;;
151 flavor.info) OFFSET=$i
152 SIZE=$(ddq bs=512 skip=$(($i/512)) if="$ISO" | gzsize);;
153 floppy.boot) SIZE=$(($(get 26 "$ISO" 1)*512))
154 OFFSET=$(($(get 64 "$ISO") - 0xC0 - $SIZE));;
155 rootfs.gz) SIZE=$(get 24 "$ISO"); OFFSET=$(($stub - $SIZE));;
156 tazboot.com) OFFSET=$(($(get 64 "$ISO") - 0xC0))
157 SIZE=$(($stub - $(get 24 "$ISO") - $OFFSET));;
158 dosstub) OFFSET=$stub; SIZE=$((0x8000 - $OFFSET));;
159 boot.md5) OFFSET=$((0x7FF0)); SIZE=16;;
160 fs.iso) OFFSET=$((0x8000))
161 SIZE=$((2048*$c - $OFFSET));;
162 custom.magic) ddq bs=2k skip=$c if="$ISO" | ddq bs=1 count=6 | \
163 grep -q '#!boot' && OFFSET=$((2048*$c)) &&
164 SIZE=39 ;;
165 custom.append) OFFSET=$((2048*$c+47)) &&
166 SIZE=$(ddq bs=2k skip=$c if="$ISO" count=1 | \
167 sed '/^append=/!d;s/^[^=]*=.//' | wc -c);;
168 custom.initrd) i=$(ddq bs=2k skip=$c if="$ISO" count=1 | \
169 sed '/^append=\|^initrd:/!d' | wc -c)
170 OFFSET=$((2048*$c+$i+40))
171 SIZE=$(($(ddq bs=2k skip=$c if="$ISO" count=1 | \
172 sed '/^initrd:/!d;s/.*://') + 0));;
173 esac
174 }
176 list()
177 {
178 HEAP=0
179 for f in win32.exe syslinux.mbr flavor.info floppy.boot tazboot.com \
180 rootfs.gz dosstub boot.md5 fs.iso custom.magic custom.append \
181 custom.initrd; do
182 fileofs $f
183 [ $SIZE -le 0 ] && continue
184 [ "${OFFSET:8}" ] && continue
185 [ $OFFSET -lt 0 ] && continue
186 [ $(get $OFFSET "$ISO") -eq 0 ] && continue
187 [ $OFFSET -gt $HEAP ] && [ $(($OFFSET - $HEAP)) -gt 16 ] &&
188 printf "%d free bytes in %04X..%04X\n" $(($OFFSET - $HEAP)) $HEAP $OFFSET
189 [ $OFFSET -ge $HEAP ] && HEAP=$(($OFFSET+$SIZE))
190 printf "$f at %04X ($SIZE bytes).\n" $OFFSET
191 done
192 OFFSET=$(stat -c %s "$ISO")
193 [ $OFFSET -gt $HEAP ] &&
194 printf "%d free bytes in %04X..%04X\n" $(($OFFSET - $HEAP)) $HEAP $OFFSET
195 }
197 extract()
198 {
199 for f in $@; do
200 fileofs $f
201 [ $SIZE -eq 0 ] ||
202 ddq bs=1 count=$SIZE skip=$OFFSET if="$ISO" >$f
203 done
204 }
206 custom_config_sector()
207 {
208 echo $(($(get 32848 "$1" 4)+16))
209 }
211 clear_custom_config()
212 {
213 start=$(custom_config_sector $1)
214 cnt=$((512 - ($start % 512)))
215 [ $cnt -ne 512 ] &&
216 ddq if=/dev/zero of=$1 bs=2k seek=$start count=$cnt
217 }
218 case "$1" in
219 --build)
220 shift
221 ls -l $@
222 cat >> $0 <<EOM
223 $(tar cf - $@ | compress | uuencode -m -)
224 EOT
225 EOM
226 sed -i '/^case/,/^esac/d' $0
227 exit ;;
228 --get)
229 cat $2
230 exit ;;
231 --array)
232 DATA=/tmp/dataiso$$
233 ddq if=/dev/zero bs=32k count=1 of=$DATA
234 add_win32exe $DATA $2 > /dev/null
235 HSZ=$OFS
236 add_dosexe $DATA > /dev/null
237 add_rootfs $DATA > /dev/null
238 add_doscom $DATA > /dev/null
239 add_fdbootstrap $DATA > /dev/null
240 name=${3:-bootiso}
241 BOOTISOSZ=$((0x8000 - $OFS + $HSZ))
242 cat <<EOT
244 #define $(echo $name | tr '[a-z]' '[A-Z]')SZ $BOOTISOSZ
246 #ifndef __MSDOS__
247 static char $name[] = {
248 /* head */
249 $(hexdump -v -n $HSZ -e '" " 16/1 "0x%02X, "' -e '" /* %04.4_ax */ \n"' $DATA | sed 's/ 0x ,/ /g')
250 /* tail */
251 $(hexdump -v -s $OFS -e '" " 16/1 "0x%02X, "' -e '" /* %04.4_ax */ \n"' $DATA | sed 's/ 0x ,/ /g')
253 /* These strange constants are defined in RFC 1321 as
254 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
255 */
256 /* static const uint32_t C_array[64] */
257 EOT
258 while read a b c d; do
259 for i in $a $b $c $d; do
260 echo $i | sed 's/0x\(..\)\(..\)\(..\)\(..\),/0x\4, 0x\3, 0x\2, 0x\1, /'
261 done
262 done <<EOT
263 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
264 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
265 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
266 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
267 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
268 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
269 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
270 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
271 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
272 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
273 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
274 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
275 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
276 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
277 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
278 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
279 EOT
280 cat <<EOT
281 /* static const char P_array[64] */
282 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
283 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
284 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
285 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, /* 4 */
286 /* static const char S_array[16] */
287 7, 12, 17, 22,
288 5, 9, 14, 20,
289 4, 11, 16, 23,
290 6, 10, 15, 21,
291 EOT
293 for mode in data offset ; do
294 ofs=0
295 while read tag str; do
296 if [ "$mode" == "data" ]; then
297 echo -en "$str\0" | hexdump -v -e '" " 16/1 "0x%02X, "' \
298 -e '" /* %04.4_ax */ \n"' | \
299 sed 's/ 0x ,/ /g'
300 else
301 if [ $ofs -eq 0 ]; then
302 cat <<EOT
303 };
304 #endif
306 #define C_array (uint32_t *) ($name + $(($BOOTISOSZ)))
307 #define P_array (char *) ($name + $(($BOOTISOSZ+(64*4))))
308 #define S_array (char *) ($name + $(($BOOTISOSZ+(64*4)+64)))
309 #define ELTORITOOFS 3
310 EOT
311 fi
312 echo "#define $tag $(($BOOTISOSZ+(64*4)+64+16+$ofs))"
313 ofs=$(($(echo -en "$str\0" | wc -c)+$ofs))
314 fi
315 done <<EOT
316 READSECTORERR Read sector failure.
317 USAGE Usage: isohybrid.exe [--list|--read] [--append cmdline] [--initrd file] file.iso [--forced|--undo|--quick|filename...]
318 OPENERR Can't open the iso file.
319 ELTORITOERR No EL TORITO SPECIFICATION signature.
320 CATALOGERR Invalid boot catalog.
321 HYBRIDERR No isolinux.bin hybrid signature.
322 SUCCESSMSG Now you can create a USB key with your .iso file.\\\\nSimply rename it to an .exe file and run it.
323 FORCEMSG You can add --forced to proceed anyway.
324 MD5MSG Computing md5sum...
325 UNINSTALLMSG Uninstall done.
326 OPENINITRDERR Can't open the initrd file.
327 ALREADYEXEERR Already an EXE file.
328 WIN32_EXE win32.exe
329 SYSLINUX_MBR syslinux.mbr
330 FLAVOR_INFO flavor.info
331 FLOPPY_BOOT floppy.boot
332 TAZBOOT_COM tazboot.com
333 ROOTFS_GZ rootfs.gz
334 DOSSTUB dosstub
335 BOOT_MD5 boot.md5
336 FS_ISO fs.iso
337 CUSTOM_MAGIC custom.magic
338 CUSTOM_APPEND custom.append
339 CUSTOM_INITRD custom.initrd
340 CUSTOM_HEADER #!boot 00000000000000000000000000000000\\\\n
341 FREE_FORMAT %ld free bytes in %04lX..%04lX\\\\n
342 USED_FORMAT %s at %04lX (%ld bytes).\\\\n
343 CMDLINE_TAG append=
344 INITRD_TAG initrd:
345 EOT
346 done
347 cat <<EOT
348 #ifdef __MSDOS__
349 #define BOOTISOFULLSIZE $(($BOOTISOSZ+(64*4)+64+16+$ofs))
350 static char bootiso[BOOTISOFULLSIZE];
351 static data_fixup(void)
352 {
353 #asm
354 push ds
355 push ds
356 pop es
357 mov ax,ds
358 sub ax,#0x1000
359 mov ds,ax
360 xor si,si
361 scanlp:
362 dec si
363 jz copydone
364 cmp byte ptr [si+2],#0xEB
365 jne scanlp
366 cmp word ptr [si],#0x5A4D
367 jne scanlp
368 mov cx,#BOOTISOFULLSIZE
369 mov di,#_bootiso
370 cld
371 rep
372 movsb
373 copydone:
374 pop ds
375 #endasm
376 if (!bootiso[0]) {
377 puts("No bootiso data");
378 exit(-1);
379 }
380 }
381 #else
382 #define data_fixup()
383 #endif
384 EOT
385 rm -rf $DATA
386 exit ;;
387 --exe)
388 # --exe mvcom.bin x.com y.exe > xy.exe
389 cat $4 $3 > /tmp/exe$$
390 S=$(stat -c %s /tmp/exe$$)
391 store 2 $(($S%512)) /tmp/exe$$
392 store 4 $((($S+511)/512)) /tmp/exe$$
393 store 14 -16 /tmp/exe$$
394 store 16 -2 /tmp/exe$$
395 store 20 256 /tmp/exe$$
396 store 22 -16 /tmp/exe$$
397 ddq if=$2 bs=1 seek=64 of=/tmp/exe$$ conv=notrunc
398 store 65 $(stat -c %s $3) /tmp/exe$$
399 store 68 $((0x100-0x40+$(stat -c %s $4))) /tmp/exe$$
400 cat /tmp/exe$$
401 rm -f /tmp/exe$$
402 exit ;;
403 esac
405 main()
406 {
407 [ $(id -u) -ne 0 ] && cmd="$0 $@" && exec su -c "$cmd" < /dev/tty
408 append=
409 initrd=
410 while [ "$1" ]; do
411 case "${1/--/-}" in
412 -get) shift
413 uudecode | unlzma | tar xOf - $@
414 exit ;;
415 -a*) append="$2" ; shift 2 ;;
416 -i*) initrd="$2" ; shift 2 ;;
417 -r*|-l*)
418 ISO="$2" ; shift 2
419 [ -z "$1" ] && list || extract $@
420 exit ;;
421 *) cat > /dev/null
422 break
423 esac
424 done
426 [ ! -s "$1" ] && cat 1>&2 <<EOT && exit 1
427 usage: $0 [--list|--read] [--append custom_cmdline ] [ --initrd custom_initrd ] image.iso [--force|--undo|"DOS help message"|filename...]
428 EOT
429 case "${2/--/-}" in
430 -u*|-r*|-w*|-f*)
431 case "$(get 0 $1)" in
432 23117)
433 b=$(get 417 $1 1)
434 n=$(($(get 64 $1) + 0xC0 - ($(get 26 $1 1)*512) - ($b+1)*512))
435 ddq if=$1 bs=512 count=1 skip=$b of=$1 conv=notrunc
436 ddq if=/dev/zero bs=512 seek=1 count=1 of=$1 conv=notrunc
437 ddq if=$1 bs=512 seek=2 count=30 skip=$(($b+1)) of=$1 conv=notrunc
438 ddq if=/dev/zero bs=1 seek=$n count=$((0x8000 - $n)) of=$1 conv=notrunc ;;
439 *) ddq if=/dev/zero bs=1k count=32 of=$1 conv=notrunc ;;
440 esac
441 case "${2/--/-}" in
442 -f*)
443 [ "$append$initrd" ] && clear_custom_config $1 ;;
444 *)
445 clear_custom_config $1
446 exit 0 ;;
447 esac
448 esac
449 case "$(get 0 $1)" in
450 23117) echo "The file $1 is already an EXE file." 1>&2 && exit 1;;
451 0) [ -x /usr/bin/isohybrid ] && isohybrid $1;;
452 esac
454 echo "Read hybrid & tazlito data..."
455 ddq if=$1 bs=512 count=1 of=/tmp/hybrid$$
456 ddq if=$1 bs=512 skip=2 count=20 of=/tmp/tazlito$$
457 add_win32exe $1 /tmp/hybrid$$
458 add_tazlito_info $1 /tmp/tazlito$$
459 rm -f /tmp/tazlito$$ /tmp/hybrid$$
461 # keep the largest room for the tazlito info file
462 add_dosexe $1
463 add_rootfs $1
464 add_doscom $1
465 add_fdbootstrap $1
466 printf "%d free bytes in %04X..%04X\n" $(($OFS-$HOLE)) $HOLE $OFS
467 store 440 $(date +%s) $1 32
468 [ "$2" ] && echo "$2 " | \
469 ddq bs=1 seek=$((0x7FDE)) count=15 conv=notrunc of=$1
470 if [ $(stat -c %s $1) -gt 34816 ]; then
471 echo "Adding ISO image md5 at 7FF0 (16 bytes) ..."
472 echo -en "$(ddq if=$1 bs=2k skip=16 count=$(get 32848 $1 4) | \
473 md5sum | cut -c-32 | sed 's/\(..\)/\\x\1/g')" | \
474 ddq bs=16 seek=2047 conv=notrunc of=$1
475 fi
476 echo -n "Adding boot checksum..."
477 if [ $(stat -c %s $1) -gt 32768 ]; then
478 n=$(($(get 2 $1) - 1 + ($(get 4 $1) - 1)*512))
479 n=$(($(od -v -N $n -t u2 -w2 -An $1 | \
480 awk '{ i+= $0 } END { print (i % 65536) }') \
481 + $(get $(($n+1)) $1 1)))
482 store 18 $(( (-$n -1) % 65536 )) $1
483 fi
484 echo " done."
485 if [ "$append$initrd" ]; then
486 echo -n "Adding custom config... "
487 DATA=/tmp/$(basename $0)$$
488 rm -f $DATA > /dev/null
489 isosz=$(stat -c %s $1)
490 [ "$append" ] && echo "append=$append" >> $DATA
491 [ -s "$initrd" ] && echo "initrd:$(stat -c %s $initrd)" >> $DATA &&
492 cat $initrd >> $DATA
493 echo "#!boot $(md5sum $DATA | sed 's/ .*//')" | cat - $DATA | \
494 ddq bs=2k seek=$(custom_config_sector $1) of=$1 conv=notrunc
495 if [ $(stat -c %s $1) -gt $isosz ]; then
496 echo "$(($(stat -c %s $1) - $isosz)) extra bytes."
497 else
498 echo "$(($isosz - 32768 - 2048*$(get 32848 $1 4)
499 - $(stat -c %s $DATA) - 24)) bytes free."
500 fi
501 rm -f $DATA > /dev/null
502 fi
503 }
505 main "$@" <<EOT