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

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