On Wed, Mar 12, 2008 at 5:10 AM, Christian Franke <[EMAIL PROTECTED]> wrote: > Bean wrote: > > ... > > > > > After some testing, i think the new version has some compatible issue, > > i remember Christian Franke reports that some bios doesn't support int > > 42 for cdrom, so grub_biosdisk_check_int13_extensions will fail. Would > > someone check if func 4b01 (the first patch cd.diff) works in such > > situation ? > > > > > > cd.diff works on this specific PC (Asus A8N, Phonix-Award BIOS), CD > appears as hd31. > > BTW: grub_biosdisk_iterate should IMO always expose the boot_drive (see > my latest patch). > With current CVS and cd.diff, the boot_drive would not be visible in > 'ls' if e.g 0x80=HDD, 0x82=boot CD (as seen on some old Laptop).
Thanks for the tip, please test the new patch, it start scanning for cdrom if the boot drive is larger than the last harddisk. BTW, i have a small question, if there is more than one cdrom, would bios export all of them, or just the boot one ? -- Bean
diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index ddcc666..75b8845 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 >= drive) + 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..cba09d2 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..757f5d5 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..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 */
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel