From f8111d3b544dbea7b5fa7c8e6dae26bf72875e8a Mon Sep 17 00:00:00 2001 From: okuji Date: Tue, 10 Dec 2002 17:30:29 +0000 Subject: [PATCH] 2002-12-11 Yoshinori K. Okuji Add a workaround for buggy BIOSes which don't pass boot drive correctly. The idea is that GRUB forces the fixed disk flag when booted from a hard disk. When BIOS loads GRUB directly, the boot drive must be either of 0x00 and 0x80, so this should work, if those BIOSes always pass zero to %dl. AFAIK, this assumption is always correct. * stage2/builtins.c (install_func): Store the fixed disk flag of the destination drive in BOOT_DRIVE_MASK in Stage 1. * stage1/stage1.h (STAGE1_BOOT_DRIVE_MASK): New macro. * stage1/stage1.S (boot_drive_mask): New variable. It is or'ed to %dl. --- ChangeLog | 17 +++++++++++++++++ stage1/stage1.S | 11 ++++++++++- stage1/stage1.h | 5 ++++- stage2/builtins.c | 6 ++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 182bc7957..7bb210ccf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2002-12-11 Yoshinori K. Okuji + + Add a workaround for buggy BIOSes which don't pass boot drive + correctly. The idea is that GRUB forces the fixed disk flag + when booted from a hard disk. When BIOS loads GRUB directly, + the boot drive must be either of 0x00 and 0x80, so this should + work, if those BIOSes always pass zero to %dl. AFAIK, this + assumption is always correct. + + * stage2/builtins.c (install_func): Store the fixed disk flag of + the destination drive in BOOT_DRIVE_MASK in Stage 1. + + * stage1/stage1.h (STAGE1_BOOT_DRIVE_MASK): New macro. + + * stage1/stage1.S (boot_drive_mask): New variable. It is or'ed + to %dl. + 2002-12-09 Yoshinori K. Okuji * stage2/char_io.c (init_page): Change the software name from diff --git a/stage1/stage1.S b/stage1/stage1.S index 08c76d693..cb41fe6bf 100644 --- a/stage1/stage1.S +++ b/stage1/stage1.S @@ -1,7 +1,7 @@ /* -*-Asm-*- */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -107,6 +107,15 @@ after_BPB: /* general setup */ cli /* we're not safe here! */ + /* + * This is a workaround for buggy BIOSes which don't pass boot + * drive correctly. If GRUB is installed into a HDD, do + * "orb $0x80, %dl", otherwise "orb $0x00, %dl" (i.e. nop). + */ + .byte 0x80, 0xca +boot_drive_mask: + .byte 0x00 + /* * ljmp to the next instruction because some bogus BIOSes * jump to 07C0:0000 instead of 0000:7C00. diff --git a/stage1/stage1.h b/stage1/stage1.h index 370009063..402a3663e 100644 --- a/stage1/stage1.h +++ b/stage1/stage1.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999, 2000 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,6 +51,9 @@ /* The offset of STAGE2_SEGMENT. */ #define STAGE1_STAGE2_SEGMENT 0x48 +/* The offset of BOOT_DRIVE_MASK. */ +#define STAGE1_BOOT_DRIVE_MASK 0x4d + /* The offset of a magic number used by Windows NT. */ #define STAGE1_WINDOWS_NT_MAGIC 0x1b8 diff --git a/stage2/builtins.c b/stage2/builtins.c index b9e4ada95..68fbca8e8 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -1916,6 +1916,12 @@ install_func (char *arg, int flags) /* Set the "force LBA" flag. */ *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba; + + /* Set the boot drive mask. This is a workaround for buggy BIOSes which + don't pass boot drive correctly. Instead, they pass 0x00 even when + booted from 0x80. */ + *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE_MASK)) + = (dest_drive & BIOS_FLAG_FIXED_DISK); /* Read the first sector of Stage 2. */ disk_read_hook = disk_read_savesect_func;