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

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