diff -Naur -X ../patch/grub.skip grub-0.97.org/stage2/asm.S grub-0.97/stage2/asm.S
--- grub-0.97.org/stage2/asm.S	Sat Dec  3 15:39:54 2005
+++ grub-0.97/stage2/asm.S	Sat Dec  3 15:41:43 2005
@@ -4232,6 +4232,14 @@
 	///* restore interrupts */
 	//sti
 
+	movl	%cs:(chain_is_winme - HMA_start + 0x10), %eax
+	testl	%eax, %eax
+	jz	1f
+	movw	$0x700,%sp	// change stack
+	call	expand_iosys
+	movw	$0x400,%sp	// change it back
+1:
+
 	movl	%cs:(chain_enable_gateA20 - HMA_start + 0x10), %eax
 	testl	%eax, %eax
 	jnz	2f
@@ -4255,6 +4263,14 @@
 	.long	0
 VARIABLE(chain_enable_gateA20)
 	.long	0
+VARIABLE(chain_is_winme)
+	.long	0
+VARIABLE(chain_expfunc_offset)
+	.word	0
+VARIABLE(chain_expfunc_segment)
+	.word	0
+VARIABLE(chain_expfunc_errmsg)
+	.string	"Invalid IO.SYS, press any key to reboot ... "
 
 	//. = HMA_start + WRAPCODEBEGIN	//. = HMA_start + 0xb0
 
@@ -4355,6 +4371,184 @@
 	//. = HMA_start + WRAPCODEBEGIN + WRAPCODESIZE
 	/* ensure this not exceed 0xc0 */
 	. = . - ((WrapCodeEnd - WrapCodeBegin) / (0xc0 + 1))
+
+// Expand IO.SYS (ME only)
+
+expand_iosys:
+	pushal
+	pushw	%ds
+	pushw	%es
+	
+	// AX is the boot code length (in segments)
+	movl	%cs:(chain_load_length - HMA_start + 0x10), %eax
+	addl	$0xF, %eax
+	shrl	$4, %eax
+
+	
+	// Move the boot code to the end of memory
+	movw	0x413, %bx
+	shlw	$6, %bx
+	movw	%cs:(chain_load_segment - HMA_start + 0x10), %dx
+	addw	%ax, %dx
+
+	cld
+
+1:
+	movw	$0x400, %cx
+	cmpw	%ax, %cx
+	jbe	2f
+	movw	%ax, %cx
+
+2:
+	subw	%cx, %dx
+	subw	%cx, %bx
+	subw	%cx, %ax
+	movw	%bx, %es
+	movw	%dx, %ds
+	xorw	%si, %si
+	xorw	%di, %di
+	shlw	$2, %cx
+	rep	movsl
+	orw	%ax, %ax
+	jnz	1b
+
+	pushw	%es
+	popw	%ds
+
+	movw	$2, %si
+
+	// Move boot code to the top of memory
+	
+	pushw	%ds
+	pushw	%si
+
+1:
+	lodsb
+	movb	%al, %bl
+	lodsw
+	testw	%ax, %ax
+	jz	3f
+	orb	%bl, %bl
+	jz	2f
+	addw	$2, %ax
+2:
+	addw	%ax, %si
+	movw	%si, %ax
+	andw	$0xF, %si
+	shrw	$4, %ax
+	movw	%ds, %di
+	addw	%ax, %di
+	movw	%di, %ds
+	jmp	1b
+3:
+
+	movw	%si, %ax
+	add	$0xF, %ax
+	shrw	$4, %ax
+	movw	%ds, %si
+	addw	%ax, %si
+	movw	%si, %ds
+	xorl	%esi, %esi
+	lodsw
+	cmp	$0x4D43, %ax		// Marker 'CM'
+	jnz	expand_error
+	movw	%ds, %cs:(chain_expfunc_segment - HMA_start + 0x10)
+	movw	%ax, %es
+	lodsw
+	movw	%ax, %cs:(chain_expfunc_offset - HMA_start + 0x10)
+	popw	%si
+	popw	%ds
+	movw	%cs:(chain_load_segment - HMA_start + 0x10), %ax
+	movw	%ax, %es
+	xorl	%edi, %edi
+
+	// Move data back to 70:00
+
+expand_begin:
+	lodsb
+	movb	%al, %bl
+	lodsw
+	orb	%bl, %bl
+	jnz	expand_call
+	test	%ax, %ax
+	jz	expand_done
+	movw	%ax, %cx
+	rep	movsb
+
+expand_next:
+	movw	%si, %ax	// Normalize ds:si and es:di
+	shrw	$4, %si
+	andw	$0xF, %ax
+	xchgw	%si, %ax
+	movw	%ds, %bx
+	addw	%ax, %bx
+	movw	%bx, %ds
+	movw	%di, %ax
+	shrw	$4, %di
+	andw	$0xF, %ax
+	xchgw	%di, %ax
+	movw	%es, %bx
+	addw	%ax, %bx
+	movw	%bx, %es
+	jmp	expand_begin
+	
+expand_done:
+	addw	$0xF, %di
+	shrw	$4, %di
+	movw	%es, %ax
+	addw	%ax, %di
+	subw	%cs:(chain_load_segment - HMA_start + 0x10), %di
+
+	popw	%es
+	popw	%ds
+
+	movw	%sp, %bp
+	movw	%di, (%bp)	// di is the total number of bytes
+	popal
+	ret
+
+expand_error:
+	pushw	%cs
+	popw	%ds
+	movw	$(chain_expfunc_errmsg - HMA_start + 0x10), %si
+	movb	$0xE, %ah
+	movw	$7, %bx
+1:
+	lodsb
+	orb	%al, %al
+	jz	2f
+	int	$0x10
+	jmp	1b
+2:
+	xorb	%ah, %ah
+	int	$0x16
+	int	$0x19
+
+expand_call:
+	movw	%ax, %cx
+	lodsw
+	movw	%ax, %dx
+	shrw	$9, %ax
+	andw	$0x1FF, %dx
+	jz	1f
+	incw	%ax
+1:
+	movw	%ax, %dx
+	pushw	%si
+	pushw	%cx
+	lodsw
+	cmpw	$0x5344,%ax
+	jnz	expand_error
+	lodsw
+	lodsw
+	movw	%dx, %cx
+	subw	%dx, %dx
+	lcall	%cs:*(chain_expfunc_offset - HMA_start + 0x10)
+	jc	expand_error
+	popw	%cx
+	popw	%si
+	addw	%cx, %si
+	jmp	expand_next
 
 	/* ensure this not exceed 0xfff0, i.e., (64K -16bytes) */
 	. = . - ((. - HMA_start) / 0xfff1)
diff -Naur -X ../patch/grub.skip grub-0.97.org/stage2/builtins.c grub-0.97/stage2/builtins.c
--- grub-0.97.org/stage2/builtins.c	Sat Dec  3 15:39:54 2005
+++ grub-0.97/stage2/builtins.c	Sat Dec  3 15:42:36 2005
@@ -989,10 +989,12 @@
     }
   else
   if (*(short *)BOOTSEC_LOCATION == 0x5A4D && filemax > 0x10000 &&
-       (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET)) == 0 /* != BOOTSEC_SIGNATURE */ && (*(long *)(BOOTSEC_LOCATION + 0xA2)) == 0 ))
+       (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET)) == 0 )) // /* != BOOTSEC_SIGNATURE */ && (*(long *)(BOOTSEC_LOCATION + 0xA2)) == 0 ))
     {
-
       int err;
+#ifndef GRUB_UTIL
+      extern int chain_is_winme;
+#endif
       
       /* Read the second sector.  */
       if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)
@@ -1007,7 +1007,7 @@
       filepos += 0x200;	/* skip the third sector */
       
       /* Read the fourth sector.  */
-      if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)
+      if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE+2) != SECTOR_SIZE+2)
       {
 	grub_close ();
 	kernel_type = KERNEL_TYPE_NONE;
@@ -1015,6 +1015,11 @@
       }
 
       err |= (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET)) != 0x534D);
+
+#ifndef GRUB_UTIL
+      if ((! err) && (*((unsigned short *) (BOOTSEC_LOCATION + SECTOR_SIZE)) == 0x4D43))
+        chain_is_winme=1;
+#endif
 
       if (! err)
       {
