diff -NaurbB -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 10 03:57:03 2005
+++ grub-0.97/stage2/builtins.c	Sat Dec 10 06:59:09 2005
@@ -327,6 +327,186 @@
   "Print the blocklist notation of the file FILE."
 };
 
+// The following routines are used to decompress IO.SYS from WinME
+
+static int ibuf_pos;
+static char *ibuf_ptr,*obuf_ptr;
+static unsigned short ibuf_tab[16];
+
+void ibuf_init(char* buf);
+unsigned short ibuf_read(int nbits);
+int expand_block(int nsec);
+long expand_file(char* src,char* dst);
+
+void ibuf_init(char* buf)
+{
+  int i;
+
+  ibuf_ptr=buf;
+  ibuf_pos=0;
+
+  // ibuf_tab[i]=(1<<(i+1))-1
+  ibuf_tab[0]=1;
+  for (i=1;i<16;i++)
+    ibuf_tab[i]=ibuf_tab[i-1]*2+1;
+}
+
+unsigned short ibuf_read(int nbits)
+{
+  unsigned short res;
+
+  res=(unsigned short)((*((unsigned long*)ibuf_ptr)>>ibuf_pos) & ibuf_tab[nbits-1]);
+  ibuf_pos+=nbits;
+  if (ibuf_pos>=8)
+    {
+      ibuf_ptr+=(ibuf_pos>>3);
+      ibuf_pos&=7;
+    }
+  return res;
+}
+
+#define obuf_init(buf)		obuf_ptr=buf
+#define obuf_putc(ch)		*(obuf_ptr++)=ch
+#define obuf_copy(ofs,len)	do { for (;len>0;obuf_ptr++,len--) *(obuf_ptr)=*(obuf_ptr-ofs); } while (0)
+// Don't use memcpy, otherwise we could be screwed !
+
+int expand_block(int nsec)
+{
+  while (nsec>0)
+    {
+      int cnt;
+
+      cnt=0x200;
+      while (1)
+        {
+          int flg,ofs,bts,bse,del,len;
+
+          flg=ibuf_read(2);
+
+          if (flg==0) ofs=ibuf_read(6); else
+            if (flg==3)
+              {
+                if (ibuf_read(1))
+                  {
+                    ofs=ibuf_read(12)+0x140;
+                    if (ofs==0x113F)
+                      break;
+                  }
+                else
+                  ofs=ibuf_read(8)+0x40;
+              } else
+                {
+                  char ch;
+
+                  cnt--;
+                  if (cnt<0)
+                    {
+                      grub_putstr("Data corrupted");
+                      return 1;
+                    }
+                  ch=ibuf_read(7);
+                  if (flg & 1)
+                    ch|=0x80;
+                  obuf_putc(ch);
+                  continue;
+                }
+          if (ofs==0)
+            {
+              grub_putstr("Data corrupted");
+              return 1;
+            }
+          bse=2;
+          del=0;
+          for (bts=0;bts<9;bts++)
+            {
+              if (ibuf_read(1))
+                break;
+              bse+=del+1;
+              del=del*2+1;
+            }
+          if (bts==9)
+            {
+              grub_putstr("Data corrupted");
+              return 1;
+            }
+          len=(bts)?bse+ibuf_read(bts):bse;
+          if ((cnt=cnt-len)<0)
+            {
+              grub_putstr("Data corrupted");
+              return 1;
+            }
+          obuf_copy(ofs,len);
+        }
+      nsec--;
+      if ((cnt) && (nsec))
+        {
+          grub_putstr("Data corrupted");
+          return 1;
+        }
+    }
+  return 0;
+}
+
+long expand_file(char* src,char* dst)
+{
+  ibuf_init(src);
+  obuf_init(dst);
+
+  if (ibuf_read(16)!=0x4D43)
+    {
+      grub_putstr("First CM signature not found");
+      return -1;
+    }
+  while (1)
+    {
+      unsigned short flg,len;
+
+      flg=ibuf_read(8);
+      len=ibuf_read(16);
+      if (len==0)
+        {
+          int n;
+
+          n=(ibuf_ptr-src) & 0xF;
+          if ((n) || (ibuf_pos))
+            {
+              ibuf_ptr+=16-n;
+              ibuf_pos=0;
+            }
+          if (ibuf_read(16)!=0x4D43)
+            {
+              grub_putstr("Second CM signature not found");
+              return -1;
+            }
+          return obuf_ptr-dst;
+        }
+      if (flg==0)
+        {
+          memcpy(obuf_ptr,ibuf_ptr,len);
+          ibuf_ptr+=len;
+          obuf_ptr+=len;
+        }
+      else
+        {
+          char* save_ptr;
+          unsigned short sec;
+
+          sec=(ibuf_read(16)+511)>>9;
+          save_ptr=ibuf_ptr;
+          if (ibuf_read(16)!=0x5344)
+            {
+              grub_putstr("0x5344 signature not found");
+              return -1;
+            }
+          ibuf_read(16);
+          if (expand_block(sec))
+            return -1;
+          ibuf_ptr=save_ptr+len;
+          ibuf_pos=0;
+        }
+    }
+}
+
 /* boot */
 static int
 boot_func (char *arg, int flags)
@@ -550,6 +730,24 @@
 		    return 1;
 		  }
 		grub_close ();
+
+		// Not a very neat way to test WinME, works anyway
+		if ((*(unsigned short*)0x110000==0x4D43) &&
+		    ((*(char*)0x110002==0) || (*(unsigned short*)0x110000==0x4D43)) &&
+		    (chainloader_skip_length==0x800))
+		  {
+		    unsigned long len;
+		    len=expand_file((char*)0x110000,(char*)0x1B0000);
+		    if (len==0)
+		      {
+		        kernel_type = KERNEL_TYPE_NONE;
+			if (errnum ==ERR_NONE)
+			  errnum = ERR_EXEC_FORMAT;
+			return 1;
+		      }
+		    grub_memmove((char*)0x110000,(char*)0x1B0000,len);
+		    chainloader_load_length=read_length=len;
+		  }
 	    }
 		
 		if (chainloader_load_length == -1 || chainloader_load_length > read_length)
@@ -989,7 +1187,7 @@
     }
   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;
@@ -1026,11 +1224,27 @@
 		chainloader_load_length = filemax;
 	if (chainloader_skip_length == 0)
 		chainloader_skip_length = 0x0800;
+
+	// Input parameter for SYSINIT
+	// BX,AX: Start sector for the data area of FAT. It doesn't needs to
+	//        be set. However, we should at least clear BX, otherwise,
+	//        it would have some minor problem when booting WinME.
+	// DI:    Length of the boot code, don't need to be set.
+	// BP:    0x7C00, boot sector pointer, don't need to be set.
+	// DH:    Media ID (BS[0x15]) , 0xF0 for floppy, 0xF8 for harddisk
+	// DL:    Drive number (BS[0x40] for FAT32)
+
 	if (! chainloader_edx_set)
 	{
-		chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00);
+		//chainloader_edx = current_drive | ((current_partition >> 8) & 0xFF00);
+		chainloader_edx = current_drive | 0xF000 | ((current_drive & 0x80)<<4);
 		chainloader_edx_set = 1;
 	}
+	if (! chainloader_ebx_set)
+	{
+		chainloader_ebx = 0;
+		chainloader_ebx_set = 1;
+	}
 	    
 	grub_printf("Will boot MS-DOS 7.x from drive=0x%x\n", (chainloader_edx & 0x80));
       }
