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

syslinux/iso2exe: fix recursive_partition + hybrib_mbr
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Mar 18 09:21:47 2017 +0100 (2017-03-18)
parents 3378a0c35726
children eeaaeada151a
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 -i100 $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
38 $0 --get rootfs.gz > $TMP/rootfs.gz
39 SIZE=$(wc -c < $TMP/rootfs.gz)
40 store 24 $SIZE $1
41 OFS=$(( $OFS - $SIZE ))
42 printf "Adding rootfs.gz file at %04X (%d bytes) ...\n" $OFS $SIZE
43 cat $TMP/rootfs.gz | ddq of=$1 bs=1 seek=$OFS conv=notrunc
44 rm -rf $TMP
45 }
47 add_dosexe()
48 {
49 TMP=/tmp/bootiso$$
50 $0 --get bootiso.bin > $TMP 2> /dev/null
51 OFS=$(($(get 20 $TMP) - 0xC0))
52 printf "Adding DOS/EXE stub at %04X (%d bytes) ...\n" $OFS $((0x8000 - $OFS))
53 ddq if=$TMP bs=1 skip=$OFS of=$1 seek=$OFS conv=notrunc
54 rm -f $TMP
55 }
57 add_doscom()
58 {
59 SIZE=$($0 --get boot.com | wc -c)
60 OFS=$(( $OFS - $SIZE ))
61 printf "Adding DOS boot file at %04X (%d bytes) ...\n" $OFS $SIZE
62 $0 --get boot.com | ddq of=$1 bs=1 seek=$OFS conv=notrunc
63 store 64 $(($OFS+0xC0)) $1
64 }
66 add_tazlito_info()
67 {
68 HOLE=$OFS
69 [ $(get 0 $2) -eq 35615 ] || return
70 zcat $2 | compress /tmp/rezipped$$.gz
71 n=$(stat -c %s /tmp/rezipped$$.gz)
72 printf "Moving tazlito data record at %04X ($n bytes) ...\n" $OFS
73 ddq if=/tmp/rezipped$$.gz bs=1 of=$1 seek=$OFS conv=notrunc
74 HOLE=$(($HOLE+$n))
75 rm -f /tmp/rezipped$$.gz
76 if [ -n "$gpt" ]; then
77 store $((0x25E)) $n $1
78 store $((0x25C)) $OFS $1
79 fi
80 }
82 add_win32exe()
83 {
84 SIZE=$($0 --get win32.exe 2> /dev/null | tee /tmp/exe$$ | wc -c)
85 [ -n "$gpt" ] && SIZE=$(($SIZE+1024))
86 [ -n "$mac" ] && SIZE=$(($SIZE+3072))
87 printf "Adding WIN32 file at %04X (%d bytes) ...\n" 0 $SIZE
88 ddq if=/tmp/exe$$ of=$1 conv=notrunc
89 if [ -n "$gpt" ]; then
90 printf "Adding GPT at %04X (1024 bytes) ...\n" 512
91 ddq if=$2 bs=512 skip=1 of=$1 seek=1 conv=notrunc
92 i=3; [ -n "$mac" ] && i=9
93 ddq if=/tmp/exe$$ bs=512 skip=1 of=$1 seek=$i conv=notrunc
94 for i in 12C 154 17C ; do # always 3 UPX sections
95 store $((0x$i)) $((1024 + $(get 0x$i $1))) $1
96 done
97 fi
98 printf "Adding bootiso head at %04X...\n" 0
99 $0 --get bootiso.bin 2> /dev/null > /tmp/exe$$
100 ddq if=/tmp/exe$$ of=$1 bs=128 count=1 conv=notrunc
101 store $((0x94)) $((0xE0 - 12*8)) $1
102 store $((0xF4)) $((16 - 12)) $1
103 ddq if=$1 of=/tmp/coff$$ bs=1 skip=$((0x178)) count=$((0x88))
104 ddq if=/tmp/coff$$ of=$1 conv=notrunc bs=1 seek=$((0x178 - 12*8))
105 ddq if=/tmp/exe$$ of=$1 bs=1 count=24 seek=$((0x1A0)) skip=$((0x1A0)) conv=notrunc
106 ddq if=$2 bs=1 skip=$((0x1B8)) seek=$((0x1B8)) count=72 of=$1 conv=notrunc
107 store 510 $((0xAA55)) $1
108 i=$SIZE; OFS=$(($SIZE+512))
109 [ -n "$mac" ] && OFS=$SIZE && i=1536
110 store 417 $(($i/512)) $1 8
111 printf "Moving syslinux hybrid boot record at %04X (512 bytes) ...\n" $i
112 ddq if=$2 bs=1 count=512 of=$1 seek=$i conv=notrunc
113 if [ $(get $((0x7C00)) /tmp/exe$$) -eq 60905 ]; then
114 ddq if=/tmp/exe$$ bs=1 count=66 skip=$((0x7DBE)) of=$1 seek=$(($i + 0x1BE)) conv=notrunc
115 ddq if=$1 bs=1 count=3 skip=$i of=$1 seek=$(($i + 0x1BE)) conv=notrunc
116 ddq if=/tmp/exe$$ bs=1 count=3 skip=$((0x7C00)) of=$1 seek=$i conv=notrunc
117 fi
118 rm -f /tmp/exe$$ /tmp/coff$$
119 if [ -z "$RECURSIVE_PARTITION" -a $(get 470 $1 4) -eq 0 ]; then
120 store 464 $((1+$i/512)) $1 8
121 store 470 $(($i/512)) $1 8
122 store 474 $(($(get 474 $1 4) - $i/512)) $1 32
123 fi
124 }
126 add_fdbootstrap()
127 {
128 SIZE=$($0 --get bootfd.bin 2> /dev/null | wc -c)
129 if [ $SIZE -ne 0 ]; then
130 SIZE=$(( $SIZE - 512 )) # sector 2 is data
131 OFS=$(( $OFS - $SIZE ))
132 printf "Adding floppy bootstrap file at %04X (%d bytes) ...\n" $OFS $SIZE
133 $0 --get bootfd.bin | \
134 ddq of=$1 bs=1 count=512 seek=$OFS conv=notrunc
135 $0 --get bootfd.bin | \
136 ddq of=$1 bs=1 skip=1024 seek=$((512 + $OFS)) conv=notrunc
137 store 26 $(($SIZE/512)) $1 8
138 fi
139 }
141 gzsize()
142 {
143 echo $(($(hexdump -C | awk ' {
144 for (i = 17; i > 1; i--) if ($i != "00") break;
145 if (i == 1) {
146 print "0x" $1 " + 1 + 1 - " n
147 exit
148 }
149 n = 17 - i
150 }')))
151 }
153 fileofs()
154 {
155 [ $(get 1024 "$ISO") -eq 35615 ] && x=1024 ||
156 x=$((512*(1+$(get 417 "$ISO" 1))))
157 stub=$(($(get 20 "$ISO") - 0xC0))
158 c=$(custom_config_sector "$ISO")
159 SIZE=0; OFFSET=0
160 case "$1" in
161 win32.exe) [ $x -eq 2048 ] && x=10752
162 [ $x -eq 1024 ] || SIZE=$(($x - 512));;
163 syslinux.mbr) [ $x -eq 1024 ] || OFFSET=$(($x - 512)); SIZE=512;;
164 flavor.info) [ $(get 22528 "$ISO") -eq 35615 ] && OFFSET=22528
165 [ $x -eq 2048 ] && x=$(get 0x25C "$ISO") &&
166 SIZE=$(get 0x25E "$ISO")
167 [ $(get $x "$ISO") -eq 35615 ] && OFFSET=$x
168 [ $OFFSET -ne 0 ] && [ $SIZE -eq 0 ] &&
169 SIZE=$(ddq bs=512 skip=$(($OFFSET/512)) if="$ISO" | gzsize);;
170 floppy.boot) SIZE=$(($(get 26 "$ISO" 1)*512))
171 OFFSET=$(($(get 64 "$ISO") - 0xC0 - $SIZE));;
172 rootfs.gz) SIZE=$(get 24 "$ISO"); OFFSET=$(($stub - $SIZE));;
173 tazboot.com) OFFSET=$(($(get 64 "$ISO") - 0xC0))
174 SIZE=$(($stub - $(get 24 "$ISO") - $OFFSET));;
175 dosstub) OFFSET=$stub; SIZE=$((0x8000 - $OFFSET));;
176 boot.md5) OFFSET=$((0x7FF0)); SIZE=16;;
177 fs.iso) OFFSET=$((0x8000))
178 SIZE=$((2048*$c - $OFFSET));;
179 custom.magic) ddq bs=2k skip=$c if="$ISO" | ddq bs=1 count=6 | \
180 grep -q '#!boot' && OFFSET=$((2048*$c)) &&
181 SIZE=39 ;;
182 custom.append) OFFSET=$((2048*$c+47)) &&
183 SIZE=$(ddq bs=2k skip=$c if="$ISO" count=1 | \
184 sed '/^append=/!d;s/^[^=]*=.//' | wc -c);;
185 custom.initrd) x=$(ddq bs=2k skip=$c if="$ISO" count=1 | \
186 sed '/^append=\|^initrd:/!d' | wc -c)
187 OFFSET=$((2048*$c+$x+40))
188 SIZE=$(($(ddq bs=2k skip=$c if="$ISO" count=1 | \
189 sed '/^initrd:/!d;s/.*://') + 0));;
190 esac
191 }
193 trailer()
194 {
195 OFFSET=$(stat -c %s "$1")
196 [ $OFFSET -gt $HEAP ] &&
197 printf "%d free bytes in %04X..%04X\n" $(($OFFSET - $HEAP)) $HEAP $OFFSET
198 if [ $(get 510 "$1") -eq 43605 ]; then
199 echo "MBR partitions :"
200 for i in 0 1 2 3; do
201 SIZE=$(get $((446+12+16*i)) "$1" 4)
202 [ $SIZE -eq 0 ] && continue
203 OFFSET=$(get $((446+8+16*i)) "$1" 4)
204 printf " $i:%08X %08X %02X\n" $OFFSET $SIZE \
205 $(get $((446+4+16*i)) "$1" 1)
206 done
207 if [ $(get 466 "$1") -eq 65263 ]; then
208 echo "EFI partitions :"
209 n=$(get 584 "$1" 1)
210 s=$(get 596 "$1")
211 o=$((($(get 552 "$1" 1)*512)-($(get 592 "$1")*$s)))
212 i=0
213 while [ $n -gt $i ]; do
214 f=$(get $(($o+0x20)) "$1" 4)
215 l=$(($(get $(($o+0x28)) "$1" 4)-$f))
216 [ $l -eq 0 ] && break
217 printf " $i:%08X %08X %s\n" $f $(($l+1)) \
218 "$(od -An -N 36 -w -j $(($o+0x38)) -t a "$1" \
219 | sed 's/\( nul\)*//g;s/ //g;s/ sp//')"
220 o=$(($o+$s))
221 i=$(($i+1))
222 done
223 fi
224 fi
225 o=2048
226 if [ $(get $o "$1") -eq 19792 ]; then
227 echo "Apple partitions :"
228 i=0
229 while [ $(get $o "$1") -eq 19792 ]; do
230 f=$((0x$(od -An -N 4 -j $(($o+8)) -t x1 "$1" | sed 's/ //g')))
231 l=$((0x$(od -An -N 4 -j $(($o+0x54)) -t x1 "$1" | sed 's/ //g')))
232 printf " $i:%08X %08X %s\n" $f $l \
233 "$(ddq bs=1 skip=$(($o+16)) count=32 if="$1")"
234 o=$(($o+2048))
235 i=$(($i+1))
236 done
237 fi
238 }
240 list()
241 {
242 HEAP=0
243 for f in win32.exe syslinux.mbr flavor.info floppy.boot tazboot.com \
244 rootfs.gz dosstub boot.md5 fs.iso custom.magic custom.append \
245 custom.initrd; do
246 fileofs $f
247 [ $SIZE -le 0 ] && continue
248 [ "${OFFSET:8}" ] && continue
249 [ $OFFSET -lt 0 ] && continue
250 [ $(get $OFFSET "$ISO") -eq 0 ] && continue
251 [ $OFFSET -gt $HEAP ] && [ $(($OFFSET - $HEAP)) -gt 16 ] &&
252 printf "%d free bytes in %04X..%04X\n" $(($OFFSET - $HEAP)) $HEAP $OFFSET
253 [ $OFFSET -ge $HEAP ] && HEAP=$(($OFFSET+$SIZE))
254 printf "$f at %04X ($SIZE bytes).\n" $OFFSET
255 done
256 trailer $ISO
257 }
259 restore_hybrid_mbr()
260 {
261 if [ $(get 0 "$1") -eq 60905 ]; then
262 ddq bs=1 conv=notrunc if="$1" of="$1" skip=$((0x1BE)) seek=0 count=3
263 ddq bs=1 skip=$((0x1BE)) count=66 if="$2" | \
264 ddq bs=1 seek=$((0x1BE)) count=66 of="$1" conv=notrunc
265 if [ -n "$RECURSIVE_PARTITION" ]; then
266 for i in 0 1 2 3 ; do
267 n=$(get $((0x1C6+16*i)) $1 4)
268 [ $n -eq 0 -o $n -gt 64 ] && continue
269 store $((0x1C0+16*i)) 1 $1 8
270 store $((0x1C6+16*i)) 0 $1 32
271 store $((0x1CA+16*i)) $(($(get $((0x1CA+16*i)) $1 4)+$n)) $1 32
272 done
273 fi
274 fi
275 }
277 extract()
278 {
279 for f in $@; do
280 fileofs $f
281 [ $SIZE -eq 0 ] ||
282 ddq bs=1 count=$SIZE skip=$OFFSET if="$ISO" >$f
283 [ "$f" == "syslinux.mbr" ] && restore_hybrid_mbr "$f" "$ISO"
284 done
285 }
287 custom_config_sector()
288 {
289 get 32848 "$1" 4
290 }
292 clear_custom_config()
293 {
294 start=$(custom_config_sector $1)
295 cnt=$((512 - ($start % 512)))
296 [ $cnt -ne 512 ] &&
297 ddq if=/dev/zero of=$1 bs=2k seek=$start count=$cnt
298 }
299 case "$1" in
300 --build)
301 shift
302 TMP=/tmp/iso2exe$$
303 mkdir -p $TMP/dev
304 cp -a /dev/tty /dev/tty0 $TMP/dev
305 cat init > $TMP/init.exe
306 find $TMP -type f -print0 | xargs -0 chmod +x
307 find $TMP -print0 | xargs -0 touch -t 197001010100.00
308 ( cd $TMP ; find * | grep -v rootfs.gz | cpio -o -H newc ) | \
309 compress rootfs.gz
310 rm -rf $TMP
311 ls -l $@ rootfs.gz
312 cat >> $0 <<EOM
313 $(tar cf - ${@/init/rootfs.gz} | compress | uuencode -m -)
314 EOT
315 EOM
316 sed -i '/^case/,/^esac/d' $0
317 exit ;;
318 --get)
319 cat $2
320 exit ;;
321 --array)
322 DATA=/tmp/dataiso$$
323 ddq if=/dev/zero bs=32k count=1 of=$DATA
324 add_win32exe $DATA $2 > /dev/null
325 HSZ=$OFS
326 add_dosexe $DATA > /dev/null
327 add_rootfs $DATA > /dev/null
328 add_doscom $DATA > /dev/null
329 add_fdbootstrap $DATA > /dev/null
330 name=${3:-bootiso}
331 BOOTISOSZ=$((0x8000 - $OFS + $HSZ))
332 cat <<EOT
334 #define $(echo $name | tr '[a-z]' '[A-Z]')SZ $BOOTISOSZ
336 #ifndef __MSDOS__
337 static char $name[] = {
338 /* head */
339 $(hexdump -v -n $HSZ -e '" " 16/1 "0x%02X, "' -e '" /* %04.4_ax */ \n"' $DATA | sed 's/ 0x ,/ /g')
340 /* tail */
341 $(hexdump -v -s $OFS -e '" " 16/1 "0x%02X, "' -e '" /* %04.4_ax */ \n"' $DATA | sed 's/ 0x ,/ /g')
343 /* These strange constants are defined in RFC 1321 as
344 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
345 */
346 /* static const uint32_t C_array[64] */
347 EOT
348 while read a b c d; do
349 for i in $a $b $c $d; do
350 echo $i | sed 's/0x\(..\)\(..\)\(..\)\(..\),/0x\4, 0x\3, 0x\2, 0x\1, /'
351 done
352 done <<EOT
353 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
354 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
355 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
356 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
357 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
358 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
359 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
360 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
361 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
362 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
363 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
364 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
365 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
366 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
367 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
368 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
369 EOT
370 cat <<EOT
371 /* static const char P_array[64] */
372 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
373 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
374 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
375 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, /* 4 */
376 /* static const char S_array[16] */
377 7, 12, 17, 22,
378 5, 9, 14, 20,
379 4, 11, 16, 23,
380 6, 10, 15, 21,
381 EOT
383 for mode in data offset ; do
384 ofs=0
385 while read tag str; do
386 if [ "$mode" == "data" ]; then
387 echo -en "$str\0" | hexdump -v -e '" " 16/1 "0x%02X, "' \
388 -e '" /* %04.4_ax */ \n"' | \
389 sed 's/ 0x ,/ /g'
390 else
391 if [ $ofs -eq 0 ]; then
392 cat <<EOT
393 };
394 #endif
396 #define C_array (uint32_t *) ($name + $(($BOOTISOSZ)))
397 #define P_array (char *) ($name + $(($BOOTISOSZ+(64*4))))
398 #define S_array (char *) ($name + $(($BOOTISOSZ+(64*4)+64)))
399 #define ELTORITOOFS 3
400 EOT
401 fi
402 echo "#define $tag $(($BOOTISOSZ+(64*4)+64+16+$ofs))"
403 ofs=$(($(echo -en "$str\0" | wc -c)+$ofs))
404 fi
405 done <<EOT
406 READSECTORERR Read sector failure.
407 USAGE Usage: isohybrid.exe [--list|--read] [--append cmdline] [--initrd file] file.iso [--forced|--undo|--quick|filename...]
408 OPENERR Can't open the iso file.
409 ELTORITOERR No EL TORITO SPECIFICATION signature.
410 CATALOGERR Invalid boot catalog.
411 HYBRIDERR No isolinux.bin hybrid signature.
412 SUCCESSMSG Now you can create a USB key with your .iso file.\\\\nSimply rename it to an .exe file and run it.
413 FORCEMSG You can add --forced to proceed anyway.
414 MD5MSG Computing md5sum...
415 UNINSTALLMSG Uninstall done.
416 OPENINITRDERR Can't open the initrd file.
417 ALREADYEXEERR Already an EXE file.
418 WIN32_EXE win32.exe
419 SYSLINUX_MBR syslinux.mbr
420 FLAVOR_INFO flavor.info
421 FLOPPY_BOOT floppy.boot
422 TAZBOOT_COM tazboot.com
423 ROOTFS_GZ rootfs.gz
424 DOSSTUB dosstub
425 BOOT_MD5 boot.md5
426 FS_ISO fs.iso
427 CUSTOM_MAGIC custom.magic
428 CUSTOM_APPEND custom.append
429 CUSTOM_INITRD custom.initrd
430 CUSTOM_HEADER #!boot 00000000000000000000000000000000\\\\n
431 FREE_FORMAT %ld free bytes in %04lX..%04lX\\\\n
432 USED_FORMAT %s at %04lX (%ld bytes).\\\\n
433 CMDLINE_TAG append=
434 INITRD_TAG initrd:
435 EOT
436 done
437 cat <<EOT
438 #ifdef __MSDOS__
439 #define BOOTISOFULLSIZE $(($BOOTISOSZ+(64*4)+64+16+$ofs))
440 static char bootiso[BOOTISOFULLSIZE];
441 static data_fixup(void)
442 {
443 #asm
444 push ds
445 push ds
446 pop es
447 mov ax,ds
448 sub ax,#0x1000
449 mov ds,ax
450 xor si,si
451 scanlp:
452 dec si
453 jz copydone
454 cmp byte ptr [si+2],#0xEB
455 jne scanlp
456 cmp word ptr [si],#0x5A4D
457 jne scanlp
458 mov cx,#BOOTISOFULLSIZE
459 mov di,#_bootiso
460 cld
461 rep
462 movsb
463 copydone:
464 pop ds
465 #endasm
466 if (!bootiso[0]) {
467 puts("No bootiso data");
468 exit(-1);
469 }
470 }
471 #else
472 #define data_fixup()
473 #endif
474 EOT
475 rm -rf $DATA
476 exit ;;
477 --exe)
478 # --exe mvcom.bin x.com y.exe > xy.exe
479 cat $4 $3 > /tmp/exe$$
480 S=$(stat -c %s /tmp/exe$$)
481 store 2 $(($S%512)) /tmp/exe$$
482 store 4 $((($S+511)/512)) /tmp/exe$$
483 store 14 -16 /tmp/exe$$
484 store 16 -2 /tmp/exe$$
485 store 20 256 /tmp/exe$$
486 store 22 -16 /tmp/exe$$
487 ddq if=$2 bs=1 seek=64 of=/tmp/exe$$ conv=notrunc
488 store 65 $(stat -c %s $3) /tmp/exe$$
489 store 68 $((0x100-0x40+$(stat -c %s $4))) /tmp/exe$$
490 cat /tmp/exe$$
491 rm -f /tmp/exe$$
492 exit ;;
493 esac
495 main()
496 {
497 [ $(id -u) -ne 0 ] && cmd="$0 $@" && exec su -c "$cmd" < /dev/tty
498 append=
499 initrd=
501 while [ "$1" ]; do
502 case "${1/--/-}" in
503 -get) shift
504 uudecode | unlzma | tar xOf - $@
505 exit ;;
506 -a*) append="$2" ; shift 2 ;;
507 -i*) initrd="$2" ; shift 2 ;;
508 -r*|-l*)
509 ISO="$2" ; shift 2
510 [ -z "$1" ] && list || extract $@
511 exit ;;
512 *) cat > /dev/null
513 break
514 esac
515 done
517 [ ! -s "$1" ] && cat 1>&2 <<EOT && exit 1
518 usage: $0 [--list|--read] [--append custom_cmdline ] [ --initrd custom_initrd ] image.iso [--force|--undo|"DOS help message"|filename...]
519 EOT
520 case "${2/--/-}" in
521 -u*|-r*|-w*|-f*)
522 case "$(get 0 $1)" in
523 23117)
524 b=$(get 417 $1 1)
525 n=$(($(get 64 $1) + 0xC0 - ($(get 26 $1 1)*512) - ($b+1)*512))
526 ddq if=$1 bs=512 count=1 skip=$b of=/tmp/hymbr$$
527 restore_hybrid_mbr /tmp/hymbr$$ $1
528 ddq if=/tmp/hymbr$$ of=$1 conv=notrunc
529 rm -f /tmp/hymbr$$
530 if [ $(get 512 $1) -eq 17989 ]; then
531 n=$(($(get 0x25C $1)/512))
532 ddq if=$1 bs=512 seek=44 count=20 skip=$n of=$1 conv=notrunc
533 ddq if=/dev/zero bs=512 seek=9 count=35 of=$1 conv=notrunc
534 ddq if=/dev/zero bs=512 seek=3 count=1 of=$1 conv=notrunc
535 else
536 ddq if=/dev/zero bs=512 seek=1 count=1 of=$1 conv=notrunc
537 ddq if=$1 bs=512 seek=2 count=30 skip=$(($b+1)) of=$1 conv=notrunc
538 ddq if=/dev/zero bs=1 seek=$n count=$((0x8000 - $n)) of=$1 conv=notrunc
539 fi ;;
540 *) ddq if=/dev/zero bs=1k count=32 of=$1 conv=notrunc ;;
541 esac
542 case "${2/--/-}" in
543 -f*)
544 [ "$append$initrd" ] && clear_custom_config $1
545 set -- "$1" "$3" ;;
546 *)
547 clear_custom_config $1
548 exit 0 ;;
549 esac
550 esac
551 case "$(get 0 $1)" in
552 23117) echo "The file $1 is already an EXE file." 1>&2 && exit 1;;
553 0) [ -x /usr/bin/isohybrid ] && isohybrid -entry 2 $1;;
554 esac
556 gpt= ; [ $(get 466 $1) -eq 65263 ] && gpt=1
557 mac= ; [ $(get 2048 $1) -eq 19792 ] && mac=1
558 echo "Read hybrid & tazlito data..."
559 if [ -n "$gpt" ]; then
560 echo "GUID Partition Table..."
561 n=3; [ -n "$mac" ] && n=9 && echo "Apple Partition Table..."
562 ddq if=$1 bs=512 count=$n of=/tmp/hybrid$$
563 ddq if=$1 bs=512 skip=44 count=20 of=/tmp/tazlito$$
564 else
565 ddq if=$1 bs=512 count=1 of=/tmp/hybrid$$
566 ddq if=$1 bs=512 skip=2 count=20 of=/tmp/tazlito$$
567 fi
568 add_win32exe $1 /tmp/hybrid$$
569 add_tazlito_info $1 /tmp/tazlito$$
570 rm -f /tmp/tazlito$$ /tmp/hybrid$$
572 # keep the largest room for the tazlito info file
573 add_dosexe $1
574 add_rootfs $1
575 add_doscom $1
576 add_fdbootstrap $1
577 printf "%d free bytes in %04X..%04X\n" $(($OFS-$HOLE)) $HOLE $OFS
578 store 440 $(date +%s) $1 32
579 [ "$2" ] && echo "$2 " | \
580 ddq bs=1 seek=$((0x7FDE)) count=15 conv=notrunc of=$1
581 if [ $(stat -c %s $1) -gt 34816 ]; then
582 echo "Adding ISO image md5 at 7FF0 (16 bytes) ..."
583 echo -en "$(ddq if=$1 bs=2k skip=16 count=$(($(get 32848 "$1" 4)-16)) | \
584 md5sum | cut -c-32 | sed 's/\(..\)/\\x\1/g')" | \
585 ddq bs=16 seek=2047 conv=notrunc of=$1
586 fi
587 HEAP=$(($(custom_config_sector $1)*2048))
588 if [ "$append$initrd" ]; then
589 echo -n "Adding custom config... "
590 DATA=/tmp/$(basename $0)$$
591 rm -f $DATA > /dev/null
592 isosz=$(stat -c %s $1)
593 [ "$append" ] && echo "append=$append" >> $DATA
594 [ -s "$initrd" ] && echo "initrd:$(stat -c %s $initrd)" >> $DATA &&
595 cat $initrd >> $DATA
596 echo "#!boot $(md5sum $DATA | sed 's/ .*//')" | cat - $DATA | \
597 ddq bs=2k seek=$(custom_config_sector $1) of=$1
598 newsz=$(stat -c %s $1)
599 mb=$(((($newsz -1)/1048576)+1))
600 HEAP=$(($mb*1048576))
601 ddq bs=1048576 seek=$mb count=0 of=$1
602 h=$(get 417 "$1" 1)
603 [ -z "$RECURSIVE_PARTITION" ] || h=0
604 for i in 0 1 2 3 ; do
605 [ $(get $((0x1BE+16*i)) $1 2) == $((0x0080)) ] || continue
606 store $((0x1CA+16*i)) $(($mb*2048-$h)) $1 32
607 store $((0x1C5+16*i)) $(($mb-1)) $1 8
608 done
609 if [ $newsz -gt $isosz ]; then
610 echo "$(($newsz - $isosz)) extra bytes."
611 else
612 echo "$(($isosz - 2048*$(get 32848 $1 4)
613 - $(stat -c %s $DATA) - 24)) bytes free."
614 fi
615 rm -f $DATA > /dev/null
616 fi
617 echo -n "Adding boot checksum..."
618 if [ $(stat -c %s $1) -gt 32768 ]; then
619 n=$(($(get 2 $1) - 1 + ($(get 4 $1) - 1)*512))
620 n=$(($(od -v -N $n -t u2 -w2 -An $1 | \
621 awk '{ i+= $0 } END { print (i % 65536) }') \
622 + $(get $(($n+1)) $1 1)))
623 store 18 $(( (-$n -1) % 65536 )) $1
624 fi
625 echo " done."
626 trailer $1
627 }
629 main "$@" <<EOT