Hi,

This patch fix two problem that can cause problem for grub-pc in macbook.

1, In grub-setup, we should skip the first 1024 bytes when comparing
data, as it have previously made change to the buffer with
install_dos_part and install_bsd_part, cause the comparison to fail.
This problem is not showed if the loader can be embedded in mbr.

2. Macbook will halt if we disable a20, so I add a new option
--keep-a20 to keep the a20 gate open.

With this patch, you can chainload windows with the following command:

set root=(hd0,4)
chainloader --keep-a20 +1
boot

-- 
Bean
diff --git a/include/grub/i386/pc/chainloader.h b/include/grub/i386/pc/chainloader.h
index c28a42d..b9b65ad 100644
--- a/include/grub/i386/pc/chainloader.h
+++ b/include/grub/i386/pc/chainloader.h
@@ -22,12 +22,10 @@
 #include <grub/dl.h>
 
 /* Common function for normal and rescue mode commands. */
-typedef enum
-  {
-    GRUB_CHAINLOADER_FORCE = 0x1
-  } grub_chainloader_flags_t;
+#define GRUB_CHAINLOADER_FORCE		0x1
+#define GRUB_CHAINLOADER_KEEP_A20	0x2
 
 void EXPORT_FUNC(grub_chainloader_cmd) (const char * file,
-					grub_chainloader_flags_t flags);
+					int flags);
 
 #endif /* GRUB_CHAINLOADER_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/loader.h b/include/grub/i386/pc/loader.h
index 3e03141..2405dbb 100644
--- a/include/grub/i386/pc/loader.h
+++ b/include/grub/i386/pc/loader.h
@@ -23,6 +23,6 @@
 #include <grub/cpu/loader.h>
 
 /* This is an asm part of the chainloader.  */
-void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr, int keep_a20) __attribute__ ((noreturn));
 
 #endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
index 9542978..e0edacc 100644
--- a/kern/i386/pc/startup.S
+++ b/kern/i386/pc/startup.S
@@ -594,7 +594,7 @@ FUNCTION(grub_halt)
 	
 	
 /*
- *  void grub_chainloader_real_boot (int drive, void *part_addr)
+ *  void grub_chainloader_real_boot (int drive, void *part_addr, int keep_a20)
  *
  *  This starts another boot loader.
  */
@@ -602,13 +602,19 @@ FUNCTION(grub_halt)
 FUNCTION(grub_chainloader_real_boot)
 	pushl	%edx
 	pushl	%eax
+	pushl	%ecx
 
 	call	EXT_C(grub_dl_unload_all)
 
+	popl	%ecx
+	orl	%ecx, %ecx
+	jnz	1f
+
 	/* Turn off Gate A20 */
 	xorl	%eax, %eax
 	call	EXT_C(grub_gate_a20)
 
+1:
 	/* set up to pass boot drive */
 	popl	%edx
 
diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c
index 825dbb3..fe2a932 100644
--- a/loader/i386/pc/chainloader.c
+++ b/loader/i386/pc/chainloader.c
@@ -35,11 +35,12 @@
 static grub_dl_t my_mod;
 static int boot_drive;
 static void *boot_part_addr;
+static int keep_a20;
 
 static grub_err_t
 grub_chainloader_boot (void)
 {
-  grub_chainloader_real_boot (boot_drive, boot_part_addr);
+  grub_chainloader_real_boot (boot_drive, boot_part_addr, keep_a20);
 
   /* Never reach here.  */
   return GRUB_ERR_NONE;
@@ -53,7 +54,7 @@ grub_chainloader_unload (void)
 }
 
 void
-grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
+grub_chainloader_cmd (const char *filename, int flags)
 {
   grub_file_t file = 0;
   grub_uint16_t signature;
@@ -118,6 +119,7 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
 
   boot_drive = drive;
   boot_part_addr = part_addr;
+  keep_a20 = ((flags & GRUB_CHAINLOADER_KEEP_A20) != 0);
   
   grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 1);
   return;
@@ -133,7 +135,7 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
 static void
 grub_rescue_cmd_chainloader (int argc, char *argv[])
 {
-  grub_chainloader_flags_t flags = 0;
+  int flags = 0;
 
   if (argc > 0 && grub_strcmp (argv[0], "--force") == 0)
     {
@@ -142,6 +144,13 @@ grub_rescue_cmd_chainloader (int argc, char *argv[])
       argv++;
     }
   
+  if (argc > 0 && grub_strcmp (argv[0], "--keep-a20") == 0)
+    {
+      flags |= GRUB_CHAINLOADER_KEEP_A20;
+      argc--;
+      argv++;
+    }
+
   if (argc == 0)
     grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
   else
diff --git a/loader/i386/pc/chainloader_normal.c b/loader/i386/pc/chainloader_normal.c
index 106cd56..8bae1a3 100644
--- a/loader/i386/pc/chainloader_normal.c
+++ b/loader/i386/pc/chainloader_normal.c
@@ -25,6 +25,7 @@
 static const struct grub_arg_option options[] =
   {
     {"force", 'f', 0, "skip bootsector magic number test", 0, 0},
+    {"keep-a20", 'k', 0, "keep a20 gate enabled", 0, 0},
     {0, 0, 0, 0, 0, 0}
   };
 
@@ -32,7 +33,13 @@ static grub_err_t
 chainloader_command (struct grub_arg_list *state,
 		     int argc, char **args)
 {
-  grub_chainloader_flags_t flags = state[0].set ? GRUB_CHAINLOADER_FORCE : 0;
+  int flags = 0;
+
+  if (state[0].set)
+    flags |= GRUB_CHAINLOADER_FORCE;
+
+  if (state[1].set)
+    flags |= GRUB_CHAINLOADER_KEEP_A20;
   
   if (argc == 0)
     grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
index 043484e..ecf1682 100644
--- a/util/i386/pc/grub-setup.c
+++ b/util/i386/pc/grub-setup.c
@@ -393,7 +393,7 @@ setup (const char *dir,
 		   != (grub_ssize_t) core_size)
 	    grub_util_info ("succeeded in opening the core image but cannot read %d bytes",
 			    (int) core_size);
-	  else if (memcmp (core_img, tmp_img, core_size) != 0)
+	  else if (memcmp (core_img + 1024, tmp_img + 1024, core_size - 1024) != 0)
 	    {
 #if 0
 	      FILE *dump;
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to