diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index ddcc666..3efe7cb 100644 --- a/disk/i386/pc/biosdisk.c +++ b/disk/i386/pc/biosdisk.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -26,15 +27,12 @@ #include #include -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,43 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) 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. */ - } - else if (drive & 0x80) + 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 + { + 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 (drp->bytes_per_sector == (GRUB_DISK_SECTOR_SIZE << 2)) + { + data->flags |= GRUB_BIOSDISK_FLAG_CDROM; + data->sectors = 32; + total_sectors = 9000000; + } + } + } } - if (drive < cd_start) + if (! (data->flags & GRUB_BIOSDISK_FLAG_CDROM)) { if (grub_biosdisk_get_diskinfo_standard (drive, &data->cylinders, @@ -364,8 +380,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 +388,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/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 #include #include -#include #include #include #include @@ -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);