wok-6.x view syslinux/stuff/iso2exe/iso2exe.sh @ rev 23996

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