Пример #1
0
static grub_err_t
grub_biosdisk_open (const char *name, grub_disk_t disk)
{
  int drive;
  struct grub_biosdisk_data *data;

  drive = (! grub_strcmp (name, "boot")) ? grub_boot_drive :
    grub_biosdisk_get_drive (name);
  if (drive < 0)
    return grub_errno;

  data = get_drive_geom (drive);
  if (! data)
    return grub_error (GRUB_ERR_BAD_DEVICE, "invalid drive");

  disk->has_partitions = (drive != cd_drive);
  disk->id = drive;
  disk->total_sectors = data->total_sectors;
  disk->data = data;

  return GRUB_ERR_NONE;
}
Пример #2
0
static grub_err_t
grub_biosdisk_open (const char *name, grub_disk_t disk)
{
  grub_uint64_t total_sectors = 0;
  int drive;
  struct grub_biosdisk_data *data;

  drive = grub_biosdisk_get_drive (name);
  if (drive < 0)
    return grub_errno;

  disk->has_partitions = ((drive & 0x80) && (drive != cd_drive));
  disk->id = drive;

  data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data));
  if (! data)
    return grub_errno;

  data->drive = drive;

  if ((cd_drive) && (drive == cd_drive))
    {
      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
      data->sectors = 32;
      total_sectors = GRUB_ULONG_MAX;  /* 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;
	    }
	}
    }

  if (! (data->flags & GRUB_BIOSDISK_FLAG_CDROM))
    {
      if (grub_biosdisk_get_diskinfo_standard (drive,
					       &data->cylinders,
					       &data->heads,
					       &data->sectors) != 0)
        {
	  if (total_sectors && (data->flags & GRUB_BIOSDISK_FLAG_LBA))
	    {
	      data->sectors = 63;
	      data->heads = 255;
	      data->cylinders
		= grub_divmod64 (total_sectors
				 + data->heads * data->sectors - 1,
				 data->heads * data->sectors, 0);
	    }
	  else
	    {
	      grub_free (data);
	      return grub_error (GRUB_ERR_BAD_DEVICE, "%s cannot get C/H/S values", disk->name);
	    }
        }

      if (! total_sectors)
        total_sectors = data->cylinders * data->heads * data->sectors;
    }

  disk->total_sectors = total_sectors;
  disk->data = data;

  return GRUB_ERR_NONE;
}