2008-01-31 Bean <bean123ch@gmail.com>
* conf/i386-pc.rmk (pkglib_IMAGES): Add cdboot.img. (cdboot_img_SOURCES): New variable. (cdboot_img_ASFLAGS): New variable. (cdboot_img_LDFLAGS): New variable. * boot/i386/pc/cdboot.S: New file. * disk/i386/pc/biosdisk.c (cd_start): New variable. (cd_count): Likewise. (grub_biosdisk_get_drive): Add support for cd device. (grub_biosdisk_call_hook): Likewise. (grub_biosdisk_iterate): Likewise. (grub_biosdisk_open): Likewise. (GRUB_BIOSDISK_CDROM_RETRY_COUNT): New macro. (grub_biosdisk_rw): Support reading from cd device. (GRUB_MOD_INIT): Iterate cd devices. * include/grub/i386/pc/biosdisk.h (GRUB_BIOSDISK_FLAG_CDROM): New macro. (GRUB_BIOSDISK_MACHINE_CDROM_START): Likewise. (GRUB_BIOSDISK_MACHINE_CDROM_END): Likewise. * kern/i386/pc/init.c (make_install_device): Check for cd device.
This commit is contained in:
parent
4020aa53c0
commit
9be665dd11
7 changed files with 317 additions and 26 deletions
|
@ -26,12 +26,15 @@
|
|||
#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[1] != 'd')
|
||||
if ((name[0] != 'f' && name[0] != 'h' && name[0] != 'c') || name[1] != 'd')
|
||||
goto fail;
|
||||
|
||||
drive = grub_strtoul (name + 2, 0, 10);
|
||||
|
@ -40,6 +43,8 @@ grub_biosdisk_get_drive (const char *name)
|
|||
|
||||
if (name[0] == 'h')
|
||||
drive += 0x80;
|
||||
else if (name[0] == 'c')
|
||||
drive += cd_start;
|
||||
|
||||
return (int) drive ;
|
||||
|
||||
|
@ -53,7 +58,10 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
|
|||
{
|
||||
char name[10];
|
||||
|
||||
grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -82,7 +90,11 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
|
|||
if (grub_biosdisk_call_hook (hook, drive))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
for (drive = cd_start; drive < cd_start + cd_count; drive++)
|
||||
if (grub_biosdisk_call_hook (hook, drive))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -97,7 +109,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
if (drive < 0)
|
||||
return grub_errno;
|
||||
|
||||
disk->has_partitions = (drive & 0x80);
|
||||
disk->has_partitions = ((drive & 0x80) && (drive < cd_start));
|
||||
disk->id = drive;
|
||||
|
||||
data = (struct grub_biosdisk_data *) grub_malloc (sizeof (*data));
|
||||
|
@ -106,8 +118,14 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
|
||||
data->drive = drive;
|
||||
data->flags = 0;
|
||||
|
||||
if (drive & 0x80)
|
||||
|
||||
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)
|
||||
{
|
||||
/* HDD */
|
||||
int version;
|
||||
|
@ -136,17 +154,20 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
}
|
||||
}
|
||||
|
||||
if (grub_biosdisk_get_diskinfo_standard (drive,
|
||||
&data->cylinders,
|
||||
&data->heads,
|
||||
&data->sectors) != 0)
|
||||
if (drive < cd_start)
|
||||
{
|
||||
grub_free (data);
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get C/H/S values");
|
||||
}
|
||||
if (grub_biosdisk_get_diskinfo_standard (drive,
|
||||
&data->cylinders,
|
||||
&data->heads,
|
||||
&data->sectors) != 0)
|
||||
{
|
||||
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 (! total_sectors)
|
||||
total_sectors = data->cylinders * data->heads * data->sectors;
|
||||
}
|
||||
|
||||
disk->total_sectors = total_sectors;
|
||||
disk->data = data;
|
||||
|
@ -164,6 +185,8 @@ grub_biosdisk_close (grub_disk_t disk)
|
|||
#define GRUB_BIOSDISK_READ 0
|
||||
#define GRUB_BIOSDISK_WRITE 1
|
||||
|
||||
#define GRUB_BIOSDISK_CDROM_RETRY_COUNT 3
|
||||
|
||||
static grub_err_t
|
||||
grub_biosdisk_rw (int cmd, grub_disk_t disk,
|
||||
grub_disk_addr_t sector, grub_size_t size,
|
||||
|
@ -184,13 +207,31 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
|
|||
dap->buffer = segment << 16; /* The format SEGMENT:ADDRESS. */
|
||||
dap->block = sector;
|
||||
|
||||
if (grub_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap))
|
||||
{
|
||||
/* Fall back to the CHS mode. */
|
||||
data->flags &= ~GRUB_BIOSDISK_FLAG_LBA;
|
||||
disk->total_sectors = data->cylinders * data->heads * data->sectors;
|
||||
return grub_biosdisk_rw (cmd, disk, sector, size, segment);
|
||||
if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cmd)
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
|
||||
|
||||
dap->blocks = (dap->blocks + 3) >> 2;
|
||||
dap->block >>= 2;
|
||||
|
||||
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
|
||||
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
|
||||
break;
|
||||
|
||||
if (i == GRUB_BIOSDISK_CDROM_RETRY_COUNT)
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "cdrom read error");
|
||||
}
|
||||
else
|
||||
if (grub_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap))
|
||||
{
|
||||
/* Fall back to the CHS mode. */
|
||||
data->flags &= ~GRUB_BIOSDISK_FLAG_LBA;
|
||||
disk->total_sectors = data->cylinders * data->heads * data->sectors;
|
||||
return grub_biosdisk_rw (cmd, disk, sector, size, segment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -323,6 +364,8 @@ 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");
|
||||
|
@ -331,6 +374,24 @@ 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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue