diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index ddcc666..2deb81d 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,17 @@ #include #include -static int cd_start = GRUB_BIOSDISK_MACHINE_CDROM_START; -static int cd_count = 0; +int cd_drive = 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 (! grub_strcmp (name, "cd0")) + return cd_drive; + + if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd') goto fail; drive = grub_strtoul (name + 2, 0, 10); @@ -43,8 +46,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,9 +59,6 @@ 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)); return hook (name); } @@ -91,10 +89,15 @@ 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)) + if (cd_drive) + { + if (grub_biosdisk_call_hook (hook, cd_drive)) return 1; + if (hook("cd0")) + return 1; + } + return 0; } @@ -109,7 +112,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) && (drive != cd_drive)); disk->id = drive; data = (struct grub_biosdisk_data *) grub_malloc (sizeof (*data)); @@ -119,7 +122,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) data->drive = drive; data->flags = 0; - if (drive >= cd_start) + if ((cd_drive) && (drive == cd_drive)) { data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM; data->sectors = 32; @@ -154,7 +157,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) } } - if (drive < cd_start) + if (! (data->flags & GRUB_BIOSDISK_FLAG_CDROM)) { if (grub_biosdisk_get_diskinfo_standard (drive, &data->cylinders, @@ -364,7 +367,8 @@ grub_disk_biosdisk_fini (void) GRUB_MOD_INIT(biosdisk) { - int drive, found = 0; + struct grub_biosdisk_cdrp *cdrp + = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; if (grub_disk_firmware_is_tainted) { @@ -373,25 +377,14 @@ 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; - } - } + grub_memset (cdrp, 0, sizeof (*cdrp)); + cdrp->size = sizeof (*cdrp); + if ((! grub_biosdisk_get_cdinfo_int13_extensions (grub_boot_drive, cdrp)) && + ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK) + == GRUB_BIOSDISK_CDTYPE_NO_EMUL)) + cd_drive = cdrp->drive_no; - cd_count = found; + grub_disk_dev_register (&grub_biosdisk_dev); } GRUB_MOD_FINI(biosdisk) diff --git a/include/grub/i386/pc/biosdisk.h b/include/grub/i386/pc/biosdisk.h index 770f942..d1107a6 100644 --- a/include/grub/i386/pc/biosdisk.h +++ b/include/grub/i386/pc/biosdisk.h @@ -25,8 +25,13 @@ #define GRUB_BIOSDISK_FLAG_LBA 1 #define GRUB_BIOSDISK_FLAG_CDROM 2 -#define GRUB_BIOSDISK_MACHINE_CDROM_START 0xe0 -#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_HARDDISK 4 + +#define GRUB_BIOSDISK_CDTYPE_MASK 0xF struct grub_biosdisk_data { @@ -74,6 +79,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 +112,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..757f5d5 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); diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index bf3d4ee..35b19fd 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 */