wok rev 14261

syslinux/iso2exe: add NT+ support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Mar 30 18:36:46 2013 +0100 (2013-03-30)
parents bf872cb6f5c1
children 0c880b8c93be
files syslinux/stuff/iso2exe/README syslinux/stuff/iso2exe/bootiso.S syslinux/stuff/iso2exe/bootlinux.h syslinux/stuff/iso2exe/init syslinux/stuff/iso2exe/iso2exe.c syslinux/stuff/iso2exe/iso2exe.sh syslinux/stuff/iso2exe/win32.c
line diff
     1.1 --- a/syslinux/stuff/iso2exe/README	Sat Mar 30 18:45:07 2013 +0000
     1.2 +++ b/syslinux/stuff/iso2exe/README	Sat Mar 30 18:36:46 2013 +0100
     1.3 @@ -18,7 +18,7 @@
     1.4  - to start SliTaz in RAM (live) in graphics mode or text mode.
     1.5  
     1.6  - to install SliTaz "a la UMSDOS" in the \slitaz\ subdirectory. The easiest
     1.7 -  way to install SliTaz. No partitioning. No questions.
     1.8 +  way to install SliTaz. No partitioning. No questions. But (very) slow.
     1.9  
    1.10  - to create a SliTaz USB Key.
    1.11  
    1.12 @@ -55,22 +55,23 @@
    1.13      +-----------------+
    1.14      |    untouched    | ISO9660 files including /boot/bzImage and /boot/rootfs*
    1.15  32K +-----------------+
    1.16 +    |  DOS .EXE stub  | Start DOS .COM loader
    1.17 +    +-----------------+
    1.18      |  ISO initramfs  | Live loader and UMSDOS like install script
    1.19      +-----------------+
    1.20      | DOS .COM loader | Load bzImage, the last rootfs*.gz and the ISO initramfs
    1.21      +-----------------+
    1.22 -    |  WIN32 PE .exe  | NT+ boot device creator / Win9x DOS .COM launcher.
    1.23 -    +-----------------+
    1.24      | floppy bootstrap| CD-ROM emulation boot driver for hard disk ISO image
    1.25      +-----------------+
    1.26             unused
    1.27      +-----------------+
    1.28      |  tazlito info   | Flavor missing data for 'tazlito iso2flavor'
    1.29 - 1K +-----------------+
    1.30 +    +-----------------+
    1.31      | isohybrid boot  | Starts isolinux.bin
    1.32 -512 +-----------------+
    1.33 -    |  iso2exe boot   | Boot starts isohybrid (*), .EXE starts DOS .COM loader
    1.34 -  0 +-----------------+ or 32 bits Windows boot device creator
    1.35 +    +-----------------+
    1.36 +    |  iso2exe boot + | Boot starts isohybrid (*), .EXE starts DOS .COM loader
    1.37 +    |  WIN32 PE .exe  | NT+ boot device creator / Win9x DOS .COM launcher.
    1.38 +  0 +-----------------+ 
    1.39  
    1.40  * Eltorito boot (i.e. bootable CD-ROM by BIOS) is not concerned by iso2exe.
    1.41  
     2.1 --- a/syslinux/stuff/iso2exe/bootiso.S	Sat Mar 30 18:45:07 2013 +0000
     2.2 +++ b/syslinux/stuff/iso2exe/bootiso.S	Sat Mar 30 18:36:46 2013 +0100
     2.3 @@ -4,7 +4,8 @@
     2.4  
     2.5  CODESZ	=	0x8000			// 16 sectors = 32Kb
     2.6  #define EXEADRS(x)	x+0xC0
     2.7 -#define EXESTR(x)	x-0x40
     2.8 +#define EXELOC(x)	x-0x40
     2.9 +#define EXESTR(x)	x-0x7F40
    2.10  
    2.11  	.globl	_start
    2.12  _start:
    2.13 @@ -52,15 +53,15 @@
    2.14  	ljmp	$0, $0x0600+start2
    2.15  
    2.16  	.org	60
    2.17 -	.long	0			// PE header offset
    2.18 +	.long	0x0080			// PE header offset
    2.19  end_header:
    2.20  chksum:
    2.21  	.word	0
    2.22  comstart:
    2.23  	.word	0
    2.24  	
    2.25 -readsector2:
    2.26 -	incw	%cx
    2.27 +readsectorX:
    2.28 +	movb	$0, %cl
    2.29  readsector1:
    2.30  	movw	%cx, (%bx)
    2.31  	incw	%cx
    2.32 @@ -87,14 +88,14 @@
    2.33  	xchgw	%ax, %dx
    2.34  	jnz	dxloop
    2.35  fail:
    2.36 -	movw	$0x0600+noloader, %si
    2.37 -	call	putslp
    2.38 +//	movw	$0x0600+noloader, %si
    2.39 +//	call	putslp
    2.40  stop:
    2.41  	hlt
    2.42  	jmp	stop
    2.43  dxfound:
    2.44  	movw	%dx, 10(%bp)
    2.45 -	call	readsector2
    2.46 +	call	readsectorX
    2.47  	lodsw
    2.48  	shrw	$1, %ax
    2.49  	jz	fail			// read fail or not isohydrid
    2.50 @@ -102,51 +103,12 @@
    2.51  	popa
    2.52  	iret
    2.53  
    2.54 -	
    2.55 +	.org	0x0080
    2.56 +////////////////////////////// EXE/PE header //////////////////////////////////
    2.57 +
    2.58 +	.org	0x7EE0
    2.59  ////////////////////////////// DOS EXE code ///////////////////////////////////
    2.60  
    2.61 -help:
    2.62 -	.ascii	"SliTaz GNU/L"		// SliTaz GNU/Linux boot loader
    2.63 -	.byte	EXESTR(iloader)
    2.64 -no386:
    2.65 -	.ascii	"No 386"		// No 386+
    2.66 -	.byte	EXESTR(plus)
    2.67 -ERRvcpi:
    2.68 -	.ascii	"No EMM386/VCPI 4"	// No EMM386/VCPI 4.0+
    2.69 -	.byte	EXESTR(dot0)
    2.70 -chkerr:
    2.71 -	.ascii	"Broken ISO image fil"	// Broken ISO image file.
    2.72 -	.byte	EXESTR(eeol)
    2.73 -vm86modemsg:
    2.74 -	.ascii	"vm86"			// vm86 mode.
    2.75 -	.byte	EXESTR(mode)
    2.76 -rmPaging:
    2.77 -	.ascii	"Invalid: paging + "	// Invalid: paging + real mode.
    2.78 -realmodemsg:
    2.79 -	.ascii	"real"			// real mode.
    2.80 -// --------------- Must be in 00C0 013F range ------------------------
    2.81 -mode:
    2.82 -	.ascii	" mod"
    2.83 -eeol:
    2.84 -	.ascii  "e"
    2.85 -	.byte	EXESTR(eol)
    2.86 -noloader:
    2.87 -	.ascii	"No isol"		// No isolinux boot loader
    2.88 -iloader:
    2.89 -	.ascii	"inux boot loader"
    2.90 -eol:
    2.91 -	.ascii	"."
    2.92 -eol2:
    2.93 -	.asciz	"\r\n"
    2.94 -noDOS3:
    2.95 -	.ascii	"No DOS 3"		// No DOS 3.0+
    2.96 -dot0:
    2.97 -	.ascii	".0"
    2.98 -plus:
    2.99 -	.ascii	"+"
   2.100 -	.byte	EXESTR(eol2)
   2.101 -// -------------------------------------------------------------------
   2.102 -
   2.103  exestart:
   2.104  	cld
   2.105  	movw	$0x100, %si
   2.106 @@ -173,7 +135,7 @@
   2.107  	movw	(%si), %cx
   2.108  	jcxz	is386
   2.109  #endif
   2.110 -	movw	$(EXESTR(0x8000))/2, %cx
   2.111 +	movw	$(EXELOC(0x8000))/2, %cx
   2.112  chklp:
   2.113  	lodsw
   2.114  	addw	%ax, %dx
   2.115 @@ -182,7 +144,7 @@
   2.116  	je	is386		// dx == 0 ?
   2.117  abort:
   2.118  puts:
   2.119 -	movb	$1, %ah
   2.120 +	movb	$0x80, %ah
   2.121  	xchgw	%ax, %si
   2.122  putslp:
   2.123  	lodsb
   2.124 @@ -209,21 +171,14 @@
   2.125  	cmpb	$3, %al
   2.126  	movb	$EXESTR(noDOS3), %al
   2.127  	jb	abort
   2.128 -	movw	$moveend-move, %cx
   2.129 -	movw	$0xC000, %di
   2.130 -	call	move2
   2.131 -move:
   2.132 -	movb	$0x80, %ch
   2.133  	movw	$0x0100, %di
   2.134 -	pushw	comstart-end_header(%di)		// .com address
   2.135 -move2:
   2.136 -	popw	%si
   2.137 +	movw	comstart-end_header(%di), %si		// .com address
   2.138  	pushw	%di
   2.139 +	movb	$0x7D, %ch
   2.140  	rep
   2.141  	movsb
   2.142  moveret:
   2.143  	ret
   2.144 -moveend:
   2.145  
   2.146  VersionVCPI:
   2.147  	cmpb	$0x40, %dl		// >= 4.0 ?
   2.148 @@ -259,6 +214,49 @@
   2.149  	.byte	0x46			// version
   2.150  	.byte	0
   2.151  
   2.152 -	.org	440
   2.153 -//////////////////////////// partition table //////////////////////////////////
   2.154 +// -------------------------------------------------------------------
   2.155  
   2.156 +help:
   2.157 +	.ascii	"SliTaz GNU/L"		// SliTaz GNU/Linux boot loader
   2.158 +	.byte	EXESTR(iloader)
   2.159 +no386:
   2.160 +	.ascii	"No 386"		// No 386+
   2.161 +	.byte	EXESTR(plus)
   2.162 +ERRvcpi:
   2.163 +	.ascii	"No EMM386/VCPI 4"	// No EMM386/VCPI 4.0+
   2.164 +	.byte	EXESTR(dot0)
   2.165 +chkerr:
   2.166 +	.ascii	"Broken ISO image fil"	// Broken ISO image file.
   2.167 +	.byte	EXESTR(eeol)
   2.168 +vm86modemsg:
   2.169 +	.ascii	"vm86"			// vm86 mode.
   2.170 +	.byte	EXESTR(mode)
   2.171 +rmPaging:
   2.172 +	.ascii	"Invalid: paging + "	// Invalid: paging + real mode.
   2.173 +realmodemsg:
   2.174 +	.ascii	"real"			// real mode.
   2.175 +// --------------- Must be in 00C0 013F range ------------------------
   2.176 +mode:
   2.177 +	.ascii	" mod"
   2.178 +eeol:
   2.179 +	.ascii  "e"
   2.180 +	.byte	EXESTR(eol)
   2.181 +//noloader:
   2.182 +//	.ascii	"No isol"		// No isolinux boot loader
   2.183 +iloader:
   2.184 +	.ascii	"inux boot loader"
   2.185 +eol:
   2.186 +	.ascii	"."
   2.187 +eol2:
   2.188 +	.asciz	"\r\n"
   2.189 +noDOS3:
   2.190 +	.ascii	"No DOS 3"		// No DOS 3.0+
   2.191 +dot0:
   2.192 +	.ascii	".0"
   2.193 +plus:
   2.194 +	.ascii	"+"
   2.195 +	.byte	EXESTR(eol2)
   2.196 +
   2.197 +	.org	0x8000
   2.198 +////////////////////////// ISO9660 header /////////////////////////////////////
   2.199 +
     3.1 --- a/syslinux/stuff/iso2exe/bootlinux.h	Sat Mar 30 18:45:07 2013 +0000
     3.2 +++ b/syslinux/stuff/iso2exe/bootlinux.h	Sat Mar 30 18:36:46 2013 +0100
     3.3 @@ -1,6 +1,6 @@
     3.4  #ifndef __BOOTLINUX_H
     3.5  #define __BOOTLINUX_H
     3.6 -extern long loadkernel(void);
     3.7 +extern unsigned long loadkernel(void);
     3.8  extern void loadinitrd(void);
     3.9  extern void bootlinux(char *cmdline);
    3.10  #endif
     4.1 --- a/syslinux/stuff/iso2exe/init	Sat Mar 30 18:45:07 2013 +0000
     4.2 +++ b/syslinux/stuff/iso2exe/init	Sat Mar 30 18:36:46 2013 +0100
     4.3 @@ -353,6 +353,13 @@
     4.4  	[ $? -eq 0 ] || return
     4.5  	usbdev || return
     4.6  	dd if=/mnt/$ISO of=$device
     4.7 +	if [ $(get 0 /mnt/$ISO) -eq 23117 ]; then	# iso2exe ?
     4.8 +		LOC=$(get 69 /mnt/$ISO 1)
     4.9 +		# move isohybrid boot sector (partitionable)
    4.10 +		dd if=/mnt/$ISO bs=512 count=1 skip=$LOC of=$device conv=notrunc
    4.11 +		# move tazlito data (backward compatibility)
    4.12 +		dd if=/mnt/$ISO bs=512 count=20 skip=$(($LOC+1)) of=$device seek=2 conv=notrunc
    4.13 +	fi
    4.14  }
    4.15  
    4.16  usbkey()
     5.1 --- a/syslinux/stuff/iso2exe/iso2exe.c	Sat Mar 30 18:45:07 2013 +0000
     5.2 +++ b/syslinux/stuff/iso2exe/iso2exe.c	Sat Mar 30 18:36:46 2013 +0100
     5.3 @@ -26,8 +26,9 @@
     5.4  #define partition 446
     5.5  #define trksz (512 * heads * sectors)
     5.6  	unsigned long size, catalog, lba;
     5.7 -	int cylinders, i, j;
     5.8 +	int cylinders, i, j, isohybrid;
     5.9  	unsigned n;
    5.10 +	char tazlitoinfo[31*1024];
    5.11  #ifndef WIN32
    5.12  	char *bootiso;
    5.13  	for (bootiso = (char *) main;
    5.14 @@ -53,28 +54,34 @@
    5.15  	readsector(lba);
    5.16  	if (* (unsigned long *) (buffer + 64) != 1886961915)
    5.17  		quit("no isolinux.bin hybrid signature in bootloader");
    5.18 -	* (unsigned long *)  &bootiso[512 + 432] = lba * 4;
    5.19 -	* (unsigned long *)  &bootiso[512 + 440] = rand();
    5.20 -	* (unsigned long *)  &bootiso[512 + partition] = 0x10080;
    5.21 -	* (unsigned short *) &bootiso[512 + 510] = 0xAA55;
    5.22 +	isohybrid = bootiso[69] * 512;
    5.23 +	* (unsigned long *)  &bootiso[isohybrid + 432] = lba * 4;
    5.24 +	* (unsigned long *)  &bootiso[isohybrid + 440] = rand();
    5.25 +	* (unsigned long *)  &bootiso[isohybrid + partition] = 0x10080;
    5.26 +	* (unsigned short *) &bootiso[isohybrid + 510] = 0xAA55;
    5.27  	size = lseek(fd, 0UL, SEEK_END);
    5.28  	cylinders = (size + trksz - 1) / trksz;
    5.29 -	bootiso[512 + partition + 4] = 23; // "Windows hidden IFS"
    5.30 -	bootiso[512 + partition + 5] = heads - 1;
    5.31 -	bootiso[512 + partition + 6] = (((cylinders - 1) & 0x300) >> 2) + sectors;
    5.32 -	bootiso[512 + partition + 7] = (cylinders - 1) & 0xFF;
    5.33 -	* (unsigned long *) &bootiso[512 + partition + 8] = 0;
    5.34 -	* (unsigned long *) &bootiso[512 + partition + 12] = cylinders * sectors * heads;
    5.35 +	bootiso[isohybrid + partition + 4] = 23; // "Windows hidden IFS"
    5.36 +	bootiso[isohybrid + partition + 5] = heads - 1;
    5.37 +	bootiso[isohybrid + partition + 6] = (((cylinders - 1) & 0x300) >> 2) + sectors;
    5.38 +	bootiso[isohybrid + partition + 7] = (cylinders - 1) & 0xFF;
    5.39 +	* (unsigned long *) &bootiso[isohybrid + partition + 8] = 0;
    5.40 +	* (unsigned long *) &bootiso[isohybrid + partition + 12] = cylinders * sectors * heads;
    5.41  
    5.42  	// Install iso2exe boot sector
    5.43 -	memcpy(bootiso + 512 - 66, bootiso + 1024 - 66, 66); 
    5.44  	* (unsigned short *) (bootiso + 26) = rand();
    5.45  
    5.46 +	// read tazlito flavor data
    5.47 +	lseek(fd, 1024UL, SEEK_SET);
    5.48 +	read(fd, tazlitoinfo, sizeof(tazlitoinfo));
    5.49 +
    5.50  	// Update iso image
    5.51 +	n = (bootiso[69] + 1) * 512;
    5.52  	lseek(fd, 0UL, SEEK_SET);
    5.53 -	write(fd, bootiso, 1024);
    5.54 -	lseek(fd, 0x8400UL - BOOTISOSZ, SEEK_SET);
    5.55 -	write(fd, bootiso + 1024, BOOTISOSZ - 1024);
    5.56 +	write(fd, bootiso, n); // EXE/PE + isohybrid mbr
    5.57 +	write(fd, tazlitoinfo, ((0x8000U - BOOTISOSZ) > sizeof(tazlitoinfo)) 
    5.58 +		? sizeof(tazlitoinfo) : (0x8000U - BOOTISOSZ));
    5.59 +	write(fd, bootiso + n, BOOTISOSZ - n); // COM + rootfs + EXE/DOS 
    5.60  
    5.61  	// Compute the checksum
    5.62  	lseek(fd, 0UL, SEEK_SET);
    5.63 @@ -89,4 +96,6 @@
    5.64  	write(fd, bootiso, 512);
    5.65  nochksum:
    5.66  	close(fd);
    5.67 +	printf("Note you can create a USB key with %s.\n"
    5.68 +	       "Simply rename it to a .exe file and run it.\n", argv[1]);
    5.69  }
     6.1 --- a/syslinux/stuff/iso2exe/iso2exe.sh	Sat Mar 30 18:45:07 2013 +0000
     6.2 +++ b/syslinux/stuff/iso2exe/iso2exe.sh	Sat Mar 30 18:36:46 2013 +0100
     6.3 @@ -25,18 +25,27 @@
     6.4  	cp -a /dev/?d?* $TMP/dev
     6.5  	$0 --get init > $TMP/init.exe
     6.6  	grep -q mount.posixovl.iso2exe $TMP/init.exe &&
     6.7 -	cp /usr/sbin/mount.posixovl $TMP/bin/mount.posixovl.iso2exe
     6.8 +	cp /usr/sbin/mount.posixovl $TMP/bin/mount.posixovl.iso2exe &&
     6.9 +	echo "Store mount.posixovl..."
    6.10  	find $TMP -type f | xargs chmod +x
    6.11  	( cd $TMP ; find * | cpio -o -H newc ) | \
    6.12  		lzma e $TMP/rootfs.gz -si 2> /dev/null
    6.13  	SIZE=$(wc -c < $TMP/rootfs.gz)
    6.14  	store 24 $SIZE $1
    6.15 -	OFS=$(( 0x8000 - $SIZE ))
    6.16 +	OFS=$(( $OFS - $SIZE ))
    6.17  	printf "Adding rootfs.gz file at %04X...\n" $OFS
    6.18  	cat $TMP/rootfs.gz | ddq of=$1 bs=1 seek=$OFS conv=notrunc
    6.19  	rm -rf $TMP
    6.20  }
    6.21  
    6.22 +add_dosexe()
    6.23 +{
    6.24 +	OFS=$((0x7EE0))
    6.25 +	printf "Adding DOS/EXE at %04X...\n" $OFS
    6.26 +	$0 --get bootiso.bin 2> /dev/null | \
    6.27 +	ddq bs=1 skip=$OFS of=$1 seek=$OFS conv=notrunc
    6.28 +}
    6.29 +
    6.30  add_doscom()
    6.31  {
    6.32  	SIZE=$($0 --get boot.com | wc -c)
    6.33 @@ -48,20 +57,19 @@
    6.34  
    6.35  add_win32exe()
    6.36  {
    6.37 +	printf "Adding WIN32 file at %04X...\n" 0
    6.38 +	ddq if=/tmp/exe$$ of=$1 conv=notrunc
    6.39  	SIZE=$($0 --get win32.exe 2> /dev/null | tee /tmp/exe$$ | wc -c)
    6.40 -	if [ $SIZE -ne 0 ]; then
    6.41 -		OFS=$(( 128 + ( ($OFS - $SIZE + 128) & 0xFE00 ) ))
    6.42 -		printf "Adding WIN32 file at %04X...\n" $OFS
    6.43 -		LOC=$((0xAC+$(get 0x94 /tmp/exe$$)))
    6.44 -		for i in $(seq 1 $(get 0x86 /tmp/exe$$)); do
    6.45 -			CUR=$(get $LOC /tmp/exe$$)
    6.46 -			[ $CUR -eq 0 ] || store $LOC $(($CUR+$OFS-128)) /tmp/exe$$
    6.47 -			LOC=$(($LOC+40))
    6.48 -		done
    6.49 -		ddq if=/tmp/exe$$ of=$1 bs=1 skip=128 seek=$OFS conv=notrunc
    6.50 -		store 60 $OFS $1
    6.51 -	fi
    6.52 +	ddq if=/tmp/exe$$ of=$1 conv=notrunc
    6.53 +	printf "Adding bootiso head at %04X...\n" 0
    6.54 +	$0 --get bootiso.bin 2> /dev/null > /tmp/exe$$
    6.55 +	ddq if=/tmp/exe$$ of=$1 bs=128 count=1 conv=notrunc
    6.56 +	store 69 $(($SIZE/512)) $1 8
    6.57 +	store 510 $((0xAA55)) $1
    6.58  	rm -f /tmp/exe$$ 
    6.59 +	printf "Moving syslinux hybrid boot record at %04X ...\n" $SIZE
    6.60 +	ddq if=$2 bs=1 count=512 of=$1 seek=$SIZE conv=notrunc
    6.61 +	OFS=$(($SIZE+512))
    6.62  }
    6.63  
    6.64  add_fdbootstrap()
    6.65 @@ -77,9 +85,7 @@
    6.66  case "$1" in
    6.67  --build)
    6.68  	shift
    6.69 -	[ $(tar cf - $@ | wc -c) -gt $((32 * 1024)) ] &&
    6.70 -		echo "WARNING: The file set $@ is too large (31K max) :" &&
    6.71 -		ls -l $@
    6.72 +	ls -l $@
    6.73  	cat >> $0 <<EOM
    6.74  $(tar cf - $@ | lzma e -si -so | uuencode -m -)
    6.75  EOT
    6.76 @@ -92,20 +98,20 @@
    6.77  --array)
    6.78  	DATA=/tmp/dataiso$$
    6.79  	ddq if=/dev/zero bs=32k count=1 of=$DATA
    6.80 -	ddq if=bootiso.bin of=$DATA conv=notrunc
    6.81 -	ddq if=$2 of=$DATA bs=512 seek=1 conv=notrunc
    6.82 +	add_win32exe $DATA $2 > /dev/null
    6.83 +	HSZ=$OFS
    6.84 +	add_dosexe $DATA > /dev/null
    6.85  	add_rootfs $DATA > /dev/null
    6.86  	add_doscom $DATA > /dev/null
    6.87 -	add_win32exe $DATA > /dev/null
    6.88  	add_fdbootstrap $DATA > /dev/null
    6.89  	name=${3:-bootiso}
    6.90  	cat <<EOT
    6.91  
    6.92 -#define $(echo $name | tr '[a-z]' '[A-Z]')SZ $((0x8400 - $OFS))
    6.93 +#define $(echo $name | tr '[a-z]' '[A-Z]')SZ $((0x8000 - $OFS + $HSZ))
    6.94  
    6.95  #ifdef WIN32
    6.96  static char $name[] = {
    6.97 -$(hexdump -v -n 1024 -e '"    " 16/1 "0x%02X, "' -e '"  // %04.4_ax |" 16/1 "%_p" "| \n"' $DATA | sed 's/ 0x  ,/      /g')
    6.98 +$(hexdump -v -n $HSZ -e '"    " 16/1 "0x%02X, "' -e '"  // %04.4_ax |" 16/1 "%_p" "| \n"' $DATA | sed 's/ 0x  ,/      /g')
    6.99  $(hexdump -v -s $OFS -e '"    " 16/1 "0x%02X, "' -e '"  // %04.4_ax |" 16/1 "%_p" "| \n"' $DATA | sed 's/ 0x  ,/      /g')
   6.100  };
   6.101  #endif
   6.102 @@ -143,19 +149,21 @@
   6.103  	[ ! -s "$1" ] && echo "usage: $0 image.iso" 1>&2 && exit 1
   6.104  	case "$(get 0 $1)" in
   6.105  	23117)	echo "The file $1 is already an EXE file." 1>&2 && exit 1;;
   6.106 -	0)	[ -x /usr/bin/isohybrid ] && isohybrid $1
   6.107 +	0)	[ -x /usr/bin/isohybrid ] && isohybrid $1 && echo "Do isohybrid"
   6.108  	esac
   6.109  		
   6.110 -	echo "Moving syslinux hybrid boot record..."
   6.111 -	ddq if=$1 bs=512 count=1 | ddq of=$1 bs=512 count=1 seek=1 conv=notrunc 
   6.112 +	echo "Read hybrid & tazlito data..."
   6.113 +	ddq if=$1 bs=512 count=1 of=/tmp/hybrid$$
   6.114 +	ddq if=$1 bs=512 skip=2 count=20 of=/tmp/tazlito$$
   6.115 +	add_win32exe $1 /tmp/hybrid$$
   6.116 +	printf "Moving tazlito data record at %04X ...\n" $OFS
   6.117 +	ddq if=/tmp/tazlito$$ bs=1 count=512 of=$1 seek=$OFS conv=notrunc
   6.118 +	rm -f /tmp/tazlito$$ /tmp/hybrid$$
   6.119  	
   6.120 -	echo "Inserting EXE boot record..."
   6.121 -	$0 --get bootiso.bin | ddq of=$1 conv=notrunc
   6.122 -
   6.123  	# keep the largest room for the tazlito info file
   6.124 +	add_dosexe $1
   6.125  	add_rootfs $1
   6.126  	add_doscom $1
   6.127 -	add_win32exe $1
   6.128  	add_fdbootstrap $1
   6.129  	store 26 ${RANDOM:-0} $1
   6.130  	i=66
     7.1 --- a/syslinux/stuff/iso2exe/win32.c	Sat Mar 30 18:45:07 2013 +0000
     7.2 +++ b/syslinux/stuff/iso2exe/win32.c	Sat Mar 30 18:36:46 2013 +0100
     7.3 @@ -1,6 +1,259 @@
     7.4  #include <windows.h>
     7.5 +#include <winnt.h>
     7.6 +#include <sys/types.h>
     7.7 +#include <sys/stat.h>
     7.8 +#include <fcntl.h>
     7.9  
    7.10 -int main()
    7.11 +#define BOOTSTRAP_SECTOR_COUNT_OFFSET	28
    7.12 +
    7.13 +static int fullread(int fd, char *p, int n)
    7.14  {
    7.15 -	MessageBox(NULL,"No support for Windows yet.","Sorry",MB_OK|MB_ICONERROR);
    7.16 +	int i, j;
    7.17 +	for (i = 0; n > 0; i += j, n -= j) {
    7.18 +		j = read(fd, p + i, n);
    7.19 +		if (j <= 0) break;
    7.20 +	}
    7.21 +	return i;
    7.22  }
    7.23 +
    7.24 +static int fullwrite(int fd, char *p, int n)
    7.25 +{
    7.26 +	int i, j;
    7.27 +	for (i = 0; n > 0; i += j, n -= j) {
    7.28 +		j = write(fd, p + i, n);
    7.29 +		if (j <= 0) break;
    7.30 +	}
    7.31 +	return i;
    7.32 +}
    7.33 +
    7.34 +static void exec16bits(char *isoFileName)
    7.35 +{
    7.36 +	int fdiso, fdtmp, i;
    7.37 +	long buffer[512/4];
    7.38 +	char tmpFileName[MAX_PATH], *p;
    7.39 +
    7.40 +	strcpy(tmpFileName, isoFileName);
    7.41 +	p = strrchr(tmpFileName, '\\');
    7.42 +	if (!p++) p = tmpFileName;
    7.43 +	strcpy(p, "tazboot.exe");
    7.44 +	fdiso = open(isoFileName, O_RDONLY|O_BINARY);
    7.45 +	fdtmp = open(tmpFileName, O_WRONLY|O_BINARY|O_CREAT,0555);
    7.46 +	for (i = 0; i < 0x8000; i += sizeof(buffer)) {
    7.47 +		fullread(fdiso, (char *) buffer, sizeof(buffer));
    7.48 +		if (i == 0) buffer[15] = 0;	// kill PE header
    7.49 +		fullwrite(fdtmp, (char *) buffer, sizeof(buffer));
    7.50 +	}
    7.51 +	close(fdiso);
    7.52 +	close(fdtmp);
    7.53 +	execl(tmpFileName, isoFileName);
    7.54 +}
    7.55 +
    7.56 +static int iswinnt(void)
    7.57 +{
    7.58 +	OSVERSIONINFOA Version;
    7.59 +	Version.dwOSVersionInfoSize = sizeof(Version);
    7.60 +	return (GetVersionEx(&Version) &&
    7.61 +	    Version.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS); // not Win9x
    7.62 +}
    7.63 +
    7.64 +static int ishybrid(char *isoFileName)
    7.65 +{
    7.66 +	int fdiso;
    7.67 +	char buffer[2048];
    7.68 +	unsigned long magic = 0;
    7.69 +	
    7.70 +	fdiso = open(isoFileName, O_RDONLY|O_BINARY);
    7.71 +	if (lseek(fdiso, 17 * 2048L, SEEK_SET) != -1 &&
    7.72 +	    fullread(fdiso, buffer, 2048) == 2048 &&
    7.73 +	    strncmp(buffer+23,"EL TORITO SPECIFICATION",23) == 0) {
    7.74 +		unsigned long lba = * (unsigned long *) (buffer + 71);
    7.75 +		
    7.76 +		if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
    7.77 +		    fullread(fdiso, buffer, 2048) == 2048 &&
    7.78 +		    * (unsigned long *) (buffer + 0) == 1 &&
    7.79 +		    * (unsigned long *) (buffer + 30) == 0x88AA55) {
    7.80 +			lba = * (unsigned long *) (buffer + 40);
    7.81 +			if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
    7.82 +			    fullread(fdiso, buffer, 2048) == 2048)
    7.83 +				magic = * (unsigned long *) (buffer + 64);
    7.84 +		}
    7.85 +	}
    7.86 +	close(fdiso);
    7.87 +	return (magic == 1886961915);
    7.88 +}
    7.89 +
    7.90 +#define MODE_READ  0
    7.91 +#define MODE_WRITE 1
    7.92 +static int rdwrsector(int mode, int drive, unsigned long startingsector, 
    7.93 +		      unsigned long count, char *buffer)
    7.94 +{
    7.95 +	HANDLE hDevice;
    7.96 +	DWORD  result;
    7.97 +	char devname[sizeof("\\\\.\\PhysicalDrive0")];
    7.98 +		
    7.99 +	if (drive >= 128) {
   7.100 +		strcpy(devname, "\\\\.\\PhysicalDrive0");
   7.101 +		devname[17] += drive - 128;
   7.102 +	}
   7.103 +	else {
   7.104 +		strcpy(devname, "\\\\.\\A:");
   7.105 +		devname[4] += drive;
   7.106 +	}
   7.107 +	hDevice = CreateFile (devname, GENERIC_READ, 
   7.108 +		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
   7.109 +	if (hDevice == INVALID_HANDLE_VALUE)
   7.110 +		return -1;
   7.111 +	SetFilePointer(hDevice, (startingsector*512), NULL, FILE_BEGIN);
   7.112 +	if (mode == MODE_READ) {
   7.113 +		if (!ReadFile(hDevice, buffer, 512*count, &result, NULL))
   7.114 +			result = -1;
   7.115 +	}
   7.116 +	else {
   7.117 +		if (!WriteFile(hDevice, buffer, 512*count, &result, NULL))
   7.118 +			result = -1;
   7.119 +	}
   7.120 +	CloseHandle(hDevice);
   7.121 +	return result;
   7.122 +}
   7.123 +
   7.124 +static void rawrite(unsigned long drive, char *isoFileName)
   7.125 +{
   7.126 +	int fdiso, s, dev, isohybrid = -1;
   7.127 +	char buffer[2048];
   7.128 +	
   7.129 +	if (drive == 0) return;
   7.130 +	for (dev = 128; (drive & 1) == 0; dev++)
   7.131 +		drive >>= 1;
   7.132 +	fdiso = open(isoFileName, O_RDONLY|O_BINARY);
   7.133 +	for (s = 0;;) {
   7.134 +		int s, n = fullread(fdiso, buffer, sizeof(buffer));
   7.135 +		if (n <= 0) break;
   7.136 +		n = (n+511)/512;
   7.137 +		if (s == 0) isohybrid = buffer[69];
   7.138 +		rdwrsector(MODE_WRITE, dev, s, n, buffer);
   7.139 +		if (s == isohybrid)
   7.140 +			rdwrsector(MODE_WRITE, dev, 0, 1, buffer);
   7.141 +		s += n;
   7.142 +	}
   7.143 +	close(fdiso);
   7.144 +}
   7.145 +
   7.146 +static unsigned long drives(void)
   7.147 +{
   7.148 +	int i, mask, result;
   7.149 +	char buffer[512];
   7.150 +	for (i = result = 0, mask = 1; i < 8; i++, mask <<= 1) {
   7.151 +		if (rdwrsector(MODE_READ, i+128, 0, 1, buffer) != -1)
   7.152 +			result |= mask;
   7.153 +	}
   7.154 +	return result;
   7.155 +}
   7.156 +
   7.157 +static void writefloppy(char *isoFileName)
   7.158 +{
   7.159 +	char buffer[512];
   7.160 +	int i, n, fd;
   7.161 +
   7.162 +	buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
   7.163 +	fd = open(isoFileName, O_RDONLY|O_BINARY);
   7.164 +	if (fd != -1) {
   7.165 +		read(fd, buffer, sizeof(buffer));
   7.166 +		n = buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET];
   7.167 +		if (n != 0 &&
   7.168 +	            lseek(fd, * (unsigned long *) (buffer + 60) - (512 * n),
   7.169 +			      SEEK_SET) != -1) {
   7.170 +			for (i = 0; i < n; i++) {
   7.171 +				fullread(fd, buffer, 512);
   7.172 +				if (i == 1) strncpy(buffer, isoFileName, 512);
   7.173 +				rdwrsector(MODE_WRITE, 0, i, 1, buffer);
   7.174 +			}
   7.175 +		}
   7.176 +		close(fd);
   7.177 +	}
   7.178 +}
   7.179 +
   7.180 +//TODO #define VCPI_LINUX_LOADER The DOS/EXE loader can boot in VM86 using VCPI API
   7.181 +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   7.182 +		   LPSTR lpCmdLine, int nCmdShow)
   7.183 +{
   7.184 +	char isoFileName[MAX_PATH];
   7.185 +	char header[32];
   7.186 +	int fd;
   7.187 +	int  usbkeyicon = MB_ICONASTERISK;
   7.188 +	char *usbkeymsg = "You can either:\n\n"
   7.189 +		"- create a SliTaz USB boot key or a boot memory card.\n"
   7.190 +		"  (note that this will be read only like a CDROM.\n"
   7.191 +		"  The Slitaz utility 'tazusb' can be used later to create\n"
   7.192 +		"  a true read/write USB key).\n\n"
   7.193 +		"- create a SliTaz bootstrap floppy for the ISO image\n"
   7.194 +		"  on the hard disk.\n"
   7.195 +		"\nDo you want to create a boot key now ?";
   7.196 +	
   7.197 +	GetModuleFileName(hInstance, isoFileName, MAX_PATH);
   7.198 +	if (!iswinnt()) {
   7.199 +#ifdef VCPI_LINUX_LOADER
   7.200 +		exec16bits(isoFileName);
   7.201 +#else
   7.202 +		MessageBox(NULL,"No support for Win9x yet.\n"
   7.203 +				"Retry in DOS mode without emm386.\n",
   7.204 +			   "Sorry", MB_OK|MB_ICONERROR);
   7.205 +		exit(1);
   7.206 +#endif
   7.207 +	}
   7.208 +	if (!ishybrid(isoFileName)) {
   7.209 +		if (MessageBox(NULL,"Not an isolinux hybrid ISO.\n"
   7.210 +				    "This ISO image will not boot\n"
   7.211 +				    "from the media you will create !",
   7.212 +			   "Will not boot !", 
   7.213 +			   MB_OKCANCEL|MB_ICONWARNING) == IDCANCEL)
   7.214 +			exit(0);
   7.215 +	}
   7.216 +	header[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
   7.217 +	fd = open(isoFileName, O_RDONLY|O_BINARY);
   7.218 +	if (fd != -1) {
   7.219 +		read(fd, header, sizeof(header));
   7.220 +		close(fd);
   7.221 +	}
   7.222 +	if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] == 0) { // No floppy bootstrap available
   7.223 +		usbkeyicon = MB_ICONQUESTION;
   7.224 +		usbkeymsg = "Do you want to create a boot key ?";
   7.225 +	}
   7.226 +	if (MessageBox(NULL,usbkeymsg, "Create a boot stick ?",
   7.227 +			MB_YESNO|usbkeyicon) == IDYES) {
   7.228 +		unsigned long base, new;
   7.229 +		int retry;
   7.230 +		
   7.231 +		if (MessageBox(NULL,"Step 1: unplug the USB stick.",
   7.232 +				"Drive detection 1/2",
   7.233 +				MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
   7.234 +			exit(0);
   7.235 +		base = drives();
   7.236 +		if (MessageBox(NULL,"Step 2: plug the USB stick in.",
   7.237 +				"Drive detection 2/2",
   7.238 +				MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
   7.239 +			exit(0);
   7.240 +		retry = 0;
   7.241 +		do {
   7.242 +			Sleep(1000); // ms
   7.243 +			new = drives();
   7.244 +		} while (new == base && retry++ < 10);
   7.245 +		if (new == base) {
   7.246 +			MessageBox(NULL,"No USB stick found.","Sorry",
   7.247 +				   MB_OK|MB_ICONERROR);
   7.248 +			exit(1);
   7.249 +		}
   7.250 +		rawrite(base ^ new, isoFileName);
   7.251 +	}
   7.252 +	if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] != 0 &&
   7.253 +	    MessageBox(NULL,"Do you want to create a bootstrap floppy ?",
   7.254 +			    "Create a bootstrap floppy ?",
   7.255 +			MB_YESNO|MB_ICONQUESTION) == IDYES &&
   7.256 +	    MessageBox(NULL,"Insert a floppy disk in drive now",
   7.257 +			    "Insert floppy",
   7.258 +			MB_OKCANCEL|MB_ICONEXCLAMATION) != IDCANCEL) {
   7.259 +
   7.260 +		// Create a 9k bootstrap with vfat, ext2 & ntfs drivers
   7.261 +		// to boot the ISO image on hard disk
   7.262 +		writefloppy(isoFileName);
   7.263 +	}
   7.264 +}