grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Ensure boot CD can be accessed


From: Christian Franke
Subject: Re: [PATCH] Ensure boot CD can be accessed
Date: Fri, 15 Feb 2008 22:13:39 +0100
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071128 SeaMonkey/1.1.7

Christian Franke wrote:
...
New patch below.


Further testing outdated this patch. The boot CD appeared under the following drive numbers:

0x82 (old Toshiba Laptop with unknown BIOS)
0x9f (PC with Phoenix-Award BIOS, VMware)
0xe0 (VirtualBox)
0xef (PC with AMI BIOS, VirtualPC)

Current CVS would only work for 0xe0, with the previous patch it works for all >= 0x9f.

This new patch also handles the case that the CD appears under the legacy controller drive number (0x82 = secondary master). It is accessed as "hd2" in this case.

Christian

2008-02-15  Christian Franke  <address@hidden>

        * disk/i386/pc/biosdisk.c: Include <grub/machine/kernel.h>.
        (grub_biosdisk_iterate): Always list boot drive.
        (grub_biosdisk_open): Assume CD if get diskinfo fails for boot drive
        not detected as CD before.
        (GRUB_MOD_INIT): Make boot CD accessible even if BIOS does not report
        INT13 Extensions for boot drive. Start CD scanning from
        grub_boot_drive + 1.
        * include/grub/i386/pc/biosdisk.h (GRUB_BIOSDISK_MACHINE_CDROM_START):
        Change from 0xe0 to 0x9f to cover more BIOS variants.
        * include/grub/i386/pc/kernel.h (grub_boot_drive): Add EXPORT_VAR.
        * kern/i386/pc/init.c (make_install_device): Always set boot CD device
        name to "(cd0)". Patch was provided by Bean.


diff -rup --exclude CVS grub2.orig/disk/i386/pc/biosdisk.c 
grub2/disk/i386/pc/biosdisk.c
--- grub2.orig/disk/i386/pc/biosdisk.c  2008-02-03 20:29:51.500000000 +0100
+++ grub2/disk/i386/pc/biosdisk.c       2008-02-15 21:16:56.921875000 +0100
@@ -18,6 +18,7 @@
 
 #include <grub/machine/biosdisk.h>
 #include <grub/machine/memory.h>
+#include <grub/machine/kernel.h>
 #include <grub/disk.h>
 #include <grub/dl.h>
 #include <grub/mm.h>
@@ -91,6 +92,11 @@ grub_biosdisk_iterate (int (*hook) (cons
        return 1;
     }
 
+  /* List boot drive as hard disk if not detected as hard disk or CD.  */
+  if (drive <= grub_boot_drive && grub_boot_drive < cd_start)
+    if (grub_biosdisk_call_hook (hook, grub_boot_drive))
+      return 1;
+
   for (drive = cd_start; drive < cd_start + cd_count; drive++)
     if (grub_biosdisk_call_hook (hook, drive))
       return 1;
@@ -119,12 +125,11 @@ grub_biosdisk_open (const char *name, gr
   data->drive = drive;
   data->flags = 0;
 
-  if (drive >= cd_start)
-    {
-      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
-      data->sectors = 32;
-      total_sectors = 9000000;  /* TODO: get the correct size.  */
-    }
+  int is_cd = 0;
+
+  if (cd_start <= drive && drive < cd_start + cd_count)
+    /* INT13 Extensions or boot CD detected during init.  */
+    is_cd = 1;
   else if (drive & 0x80)
     {
       /* HDD */
@@ -154,19 +159,32 @@ grub_biosdisk_open (const char *name, gr
        }
     }
 
-  if (drive < cd_start)
+  if (! is_cd)
     {
-      if (grub_biosdisk_get_diskinfo_standard (drive,
-                                              &data->cylinders,
-                                              &data->heads,
-                                              &data->sectors) != 0)
+      if (! grub_biosdisk_get_diskinfo_standard (drive,
+                                                &data->cylinders,
+                                                &data->heads,
+                                                &data->sectors))
+       {
+         if (! total_sectors)
+           total_sectors = data->cylinders * data->heads * data->sectors;
+       }
+      else if (drive == grub_boot_drive)
+       /* Some old BIOSes return a legacy controller drive number
+          for the boot CD.  Ensure that the boot CD can be accessed.  */
+       is_cd = 1;
+      else
         {
           grub_free (data);
           return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get C/H/S values");
         }
+    }
 
-      if (! total_sectors)
-        total_sectors = data->cylinders * data->heads * data->sectors;
+  if (is_cd)
+    {
+      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
+      data->sectors = 32;
+      total_sectors = 9000000;  /* TODO: get the correct size.  */
     }
 
   disk->total_sectors = total_sectors;
@@ -364,7 +382,8 @@ grub_disk_biosdisk_fini (void)
 
 GRUB_MOD_INIT(biosdisk)
 {
-  int drive, found = 0;
+  int drive = GRUB_BIOSDISK_MACHINE_CDROM_START;
+  int found = 0;
 
   if (grub_disk_firmware_is_tainted)
     {
@@ -375,8 +394,17 @@ GRUB_MOD_INIT(biosdisk)
 
   grub_disk_dev_register (&grub_biosdisk_dev);
 
-  for (drive = GRUB_BIOSDISK_MACHINE_CDROM_START;
-       drive < GRUB_BIOSDISK_MACHINE_CDROM_END; drive++)
+  /* Some BIOSes do not report INT13 Extensions for the
+     boot CD.  Ensure that the boot CD can be accessed.  */
+  if (GRUB_BIOSDISK_MACHINE_CDROM_START <= grub_boot_drive
+      && grub_boot_drive < GRUB_BIOSDISK_MACHINE_CDROM_END)
+    {
+      cd_start = grub_boot_drive;
+      drive = grub_boot_drive + 1;
+      found = 1;
+    }
+
+  for ( ; drive < GRUB_BIOSDISK_MACHINE_CDROM_END; drive++)
     {
       if (grub_biosdisk_check_int13_extensions (drive))
         {
diff -rup --exclude CVS grub2.orig/include/grub/i386/pc/biosdisk.h 
grub2/include/grub/i386/pc/biosdisk.h
--- grub2.orig/include/grub/i386/pc/biosdisk.h  2008-02-03 20:29:52.187500000 
+0100
+++ grub2/include/grub/i386/pc/biosdisk.h       2008-02-09 15:55:04.713289500 
+0100
@@ -25,7 +25,7 @@
 #define GRUB_BIOSDISK_FLAG_LBA 1
 #define GRUB_BIOSDISK_FLAG_CDROM 2
 
-#define GRUB_BIOSDISK_MACHINE_CDROM_START      0xe0
+#define GRUB_BIOSDISK_MACHINE_CDROM_START      0x9f
 #define GRUB_BIOSDISK_MACHINE_CDROM_END                0xf0
 
 struct grub_biosdisk_data
diff -rup --exclude CVS grub2.orig/include/grub/i386/pc/kernel.h 
grub2/include/grub/i386/pc/kernel.h
--- grub2.orig/include/grub/i386/pc/kernel.h    2008-02-03 20:29:52.375000000 
+0100
+++ grub2/include/grub/i386/pc/kernel.h 2008-02-10 00:16:43.812500000 +0100
@@ -71,7 +71,7 @@ extern grub_int32_t grub_memdisk_image_s
 extern char grub_prefix[];
 
 /* The boot BIOS drive number.  */
-extern grub_int32_t grub_boot_drive;
+extern grub_int32_t EXPORT_VAR(grub_boot_drive);
 
 /* The root BIOS drive number.  */
 extern grub_int32_t grub_root_drive;
diff -rup --exclude CVS grub2.orig/kern/i386/pc/init.c grub2/kern/i386/pc/init.c
--- grub2.orig/kern/i386/pc/init.c      2008-02-03 20:29:53.125000000 +0100
+++ grub2/kern/i386/pc/init.c   2008-02-10 15:05:40.140625000 +0100
@@ -77,9 +77,9 @@ make_install_device (void)
       if (grub_root_drive == 0xFF)
         grub_root_drive = grub_boot_drive;
       
-      if (grub_root_drive >= GRUB_BIOSDISK_MACHINE_CDROM_START)
-        grub_sprintf (dev, "(cd%u",
-                     grub_root_drive - GRUB_BIOSDISK_MACHINE_CDROM_START);
+      if ((grub_root_drive >= GRUB_BIOSDISK_MACHINE_CDROM_START) &&
+          (grub_root_drive < GRUB_BIOSDISK_MACHINE_CDROM_END))
+       grub_strcpy (dev, "(cd0");
       else
         grub_sprintf (dev, "(%cd%u",
                      (grub_root_drive & 0x80) ? 'h' : 'f',

reply via email to

[Prev in Thread] Current Thread [Next in Thread]