diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c
index ddcc666..26997a0 100644
--- a/disk/i386/pc/biosdisk.c
+++ b/disk/i386/pc/biosdisk.c
@@ -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>
@@ -26,15 +27,12 @@
 #include <grub/err.h>
 #include <grub/term.h>
 
-static int cd_start = GRUB_BIOSDISK_MACHINE_CDROM_START;
-static int cd_count = 0;
-
 static int
 grub_biosdisk_get_drive (const char *name)
 {
   unsigned long drive;
 
-  if ((name[0] != 'f' && name[0] != 'h' && name[0] != 'c') || name[1] != 'd')
+  if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
     goto fail;
     
   drive = grub_strtoul (name + 2, 0, 10);
@@ -43,8 +41,6 @@ grub_biosdisk_get_drive (const char *name)
 
   if (name[0] == 'h')
     drive += 0x80;
-  else if (name[0] == 'c')
-    drive += cd_start;
   
   return (int) drive ;
 
@@ -58,10 +54,7 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
 {
   char name[10];
 
-  if (drive >= cd_start)
-    grub_sprintf (name, "cd%d", drive - cd_start);
-  else
-    grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
+  grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
   return hook (name);
 }
 
@@ -78,7 +71,8 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
       return 1;
   
   /* For hard disks, attempt to read the MBR.  */
-  for (drive = 0x80; drive < 0x90; drive++)
+  for (drive = 0x80;
+       drive < GRUB_BIOSDISK_MACHINE_CDROM_START;  drive++)
     {
       if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
 				     GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
@@ -91,9 +85,30 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
 	return 1;
     }
 
-  for (drive = cd_start; drive < cd_start + cd_count; drive++)
-    if (grub_biosdisk_call_hook (hook, drive))
-      return 1;
+  if (grub_boot_drive >= GRUB_BIOSDISK_MACHINE_CDROM_START)
+    for (drive = grub_boot_drive;
+         drive < GRUB_BIOSDISK_MACHINE_CDROM_END; drive++)
+      {
+        struct grub_biosdisk_dap *dap;
+
+        dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+                                            + (4 << GRUB_DISK_SECTOR_BITS));
+
+        dap->length = sizeof (*dap);
+        dap->reserved = 0;
+        dap->blocks = 1;
+        dap->buffer = GRUB_MEMORY_MACHINE_SCRATCH_SEG << 16;
+        dap->block = 0;
+
+        if (grub_biosdisk_rw_int13_extensions (0x42, drive, dap))
+          {
+            grub_dprintf ("disk", "Read error when probing cd 0x%2x\n", drive);
+            break;
+          }
+
+        if (grub_biosdisk_call_hook (hook, drive))
+          return 1;
+      }
 
   return 0;
 }
@@ -109,7 +124,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
   if (drive < 0)
     return grub_errno;
 
-  disk->has_partitions = ((drive & 0x80) && (drive < cd_start));
+  disk->has_partitions = ((drive & 0x80) != 0);
   disk->id = drive;
   
   data = (struct grub_biosdisk_data *) grub_malloc (sizeof (*data));
@@ -119,42 +134,54 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
   data->drive = drive;
   data->flags = 0;
 
-  if (drive >= cd_start)
+  if (drive & 0x80)
     {
-      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
-      data->sectors = 32;
-      total_sectors = 9000000;  /* TODO: get the correct size.  */
-    }
-  else if (drive & 0x80)
-    {
-      /* HDD */
-      int version;
-      
-      version = grub_biosdisk_check_int13_extensions (drive);
-      if (version)
-	{
-	  struct grub_biosdisk_drp *drp
-	    = (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
-
-	  /* Clear out the DRP.  */
-	  grub_memset (drp, 0, sizeof (*drp));
-	  drp->size = sizeof (*drp);
-	  if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp))
-	    {
-	      data->flags = GRUB_BIOSDISK_FLAG_LBA;
-
-	      if (drp->total_sectors)
-		total_sectors = drp->total_sectors;
-	      else
-                /* Some buggy BIOSes doesn't return the total sectors
-                   correctly but returns zero. So if it is zero, compute
-                   it by C/H/S returned by the LBA BIOS call.  */
-                total_sectors = drp->cylinders * drp->heads * drp->sectors;
-	    }
-	}
+      struct grub_biosdisk_cdrp *cdrp
+        = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+      grub_memset (cdrp, 0, sizeof (*cdrp));
+      cdrp->size = sizeof (*cdrp);
+      if ((! grub_biosdisk_get_cdinfo_int13_extensions (drive, cdrp)) &&
+          (cdrp->drive_no == drive) &&
+          ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
+           == GRUB_BIOSDISK_CDTYPE_NO_EMUL))
+        {
+          disk->has_partitions = 0;
+          data->flags = (GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM);
+          data->sectors = 32;
+          total_sectors = 9000000;  /* TODO: get the correct size.  */
+        }
+      else
+        {
+          /* HDD */
+          int version;
+
+          version = grub_biosdisk_check_int13_extensions (drive);
+          if (version)
+            {
+              struct grub_biosdisk_drp *drp
+                    = (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+              /* Clear out the DRP.  */
+              grub_memset (drp, 0, sizeof (*drp));
+              drp->size = sizeof (*drp);
+              if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp))
+                {
+                  data->flags = GRUB_BIOSDISK_FLAG_LBA;
+
+                  if (drp->total_sectors)
+                    total_sectors = drp->total_sectors;
+                  else
+                    /* Some buggy BIOSes doesn't return the total sectors
+                       correctly but returns zero. So if it is zero, compute
+                       it by C/H/S returned by the LBA BIOS call.  */
+                    total_sectors = drp->cylinders * drp->heads * drp->sectors;
+                }
+            }
+        }
     }
 
-  if (drive < cd_start)
+  if (! (data->flags & GRUB_BIOSDISK_FLAG_CDROM))
     {
       if (grub_biosdisk_get_diskinfo_standard (drive,
 					       &data->cylinders,
@@ -364,8 +391,6 @@ grub_disk_biosdisk_fini (void)
 
 GRUB_MOD_INIT(biosdisk)
 {
-  int drive, found = 0;
-
   if (grub_disk_firmware_is_tainted)
     {
       grub_printf ("Firmware is marked as tainted, refusing to initialize.\n");
@@ -374,24 +399,6 @@ GRUB_MOD_INIT(biosdisk)
   grub_disk_firmware_fini = grub_disk_biosdisk_fini;
 
   grub_disk_dev_register (&grub_biosdisk_dev);
-
-  for (drive = GRUB_BIOSDISK_MACHINE_CDROM_START;
-       drive < GRUB_BIOSDISK_MACHINE_CDROM_END; drive++)
-    {
-      if (grub_biosdisk_check_int13_extensions (drive))
-        {
-	  if (! found)
-	    cd_start = drive;
-	  found++;
-	}
-      else
-        {
-	  if (found)
-            break;
-	}
-    }
-
-  cd_count = found;
 }
 
 GRUB_MOD_FINI(biosdisk)
diff --git a/include/grub/i386/pc/biosdisk.h b/include/grub/i386/pc/biosdisk.h
index 770f942..848840e 100644
--- a/include/grub/i386/pc/biosdisk.h
+++ b/include/grub/i386/pc/biosdisk.h
@@ -25,9 +25,18 @@
 #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
 
+#define GRUB_BIOSDISK_CDTYPE_NO_EMUL	0
+#define GRUB_BIOSDISK_CDTYPE_1_2_M	1
+#define GRUB_BIOSDISK_CDTYPE_1_44_M	2
+#define GRUB_BIOSDISK_CDTYPE_2_88_M	3
+#define GRUB_BIOSDISK_CDTYPE_2_88_M	3
+#define GRUB_BIOSDISK_CDTYPE_HARDDISK	4
+
+#define GRUB_BIOSDISK_CDTYPE_MASK	0xF
+
 struct grub_biosdisk_data
 {
   int drive;
@@ -74,6 +83,23 @@ struct grub_biosdisk_drp
   grub_uint8_t dummy[16];
 } __attribute__ ((packed));
 
+struct grub_biosdisk_cdrp
+{
+  grub_uint8_t size;
+  grub_uint8_t media_type;
+  grub_uint8_t drive_no;
+  grub_uint8_t controller_no;
+  grub_uint32_t image_lba;
+  grub_uint16_t device_spec;
+  grub_uint16_t cache_seg;
+  grub_uint16_t load_seg;
+  grub_uint16_t length_sec512;
+  grub_uint8_t cylinders;
+  grub_uint8_t sectors;
+  grub_uint8_t heads;
+  grub_uint8_t dummy[16];
+} __attribute__ ((packed));
+
 /* Disk Address Packet.  */
 struct grub_biosdisk_dap
 {
@@ -90,6 +116,8 @@ int EXPORT_FUNC(grub_biosdisk_rw_standard) (int ah, int drive, int coff, int hof
 int EXPORT_FUNC(grub_biosdisk_check_int13_extensions) (int drive);
 int EXPORT_FUNC(grub_biosdisk_get_diskinfo_int13_extensions) (int drive,
            void *drp);
+int EXPORT_FUNC(grub_biosdisk_get_cdinfo_int13_extensions) (int drive,
+           void *cdrp);
 int EXPORT_FUNC(grub_biosdisk_get_diskinfo_standard) (int drive,
 					 unsigned long *cylinders,
 					 unsigned long *heads,
diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
index 848dad1..43a8d5b 100644
--- a/include/grub/i386/pc/kernel.h
+++ b/include/grub/i386/pc/kernel.h
@@ -71,7 +71,7 @@ extern grub_int32_t grub_memdisk_image_size;
 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 --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
index 7237492..525b667 100644
--- a/kern/i386/pc/init.c
+++ b/kern/i386/pc/init.c
@@ -22,7 +22,6 @@
 #include <grub/machine/memory.h>
 #include <grub/machine/console.h>
 #include <grub/machine/kernel.h>
-#include <grub/machine/biosdisk.h>
 #include <grub/types.h>
 #include <grub/err.h>
 #include <grub/dl.h>
@@ -77,13 +76,8 @@ 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);
-      else
-        grub_sprintf (dev, "(%cd%u",
-		      (grub_root_drive & 0x80) ? 'h' : 'f',
-		      grub_root_drive & 0x7f);
+      grub_sprintf (dev, "(%cd%u", (grub_root_drive & 0x80) ? 'h' : 'f',
+                    grub_root_drive & 0x7f);
       
       if (grub_install_dos_part >= 0)
 	grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 1);
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
index bf3d4ee..2994ee2 100644
--- a/kern/i386/pc/startup.S
+++ b/kern/i386/pc/startup.S
@@ -780,6 +780,17 @@ FUNCTION(grub_biosdisk_check_int13_extensions)
 
 
 /*
+ *   int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp)
+ *
+ *   Return the cdrom information of DRIVE in CDRP. If an error occurs,
+ *   then return non-zero, otherwise zero.
+ */
+
+FUNCTION(grub_biosdisk_get_cdinfo_int13_extensions)
+	movw	$0x4B01, %cx
+	jmp	1f
+
+/*
  *   int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
  *
  *   Return the geometry of DRIVE in a drive parameters, DRP. If an error
@@ -787,6 +798,8 @@ FUNCTION(grub_biosdisk_check_int13_extensions)
  */
 
 FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions)
+	movb	$0x48, %ch
+1:
 	pushl	%ebp
 	pushl	%ebx
 	pushl	%esi
@@ -802,7 +815,7 @@ FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions)
 	call	prot_to_real
 
 	.code16
-	movb	$0x48, %ah
+	movw	%cx, %ax
 	movw	%bx, %ds
 	int	$0x13		/* do the operation */
 	movb	%ah, %bl	/* save return value in %bl */
