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
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel