Beispiel #1
0
static int
grub_biosdisk_iterate (int (*hook) (const char *name))
{
  int drive;
  int num_floppies;

  /* For hard disks, attempt to read the MBR.  */
  for (drive = 0x80; drive < 0x90; drive++)
    {
      if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
				     GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
	{
	  grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
	  break;
	}

      if (grub_biosdisk_call_hook (hook, drive))
	return 1;
    }

  if (cd_drive)
    {
      if (grub_biosdisk_call_hook (hook, cd_drive))
      return 1;
    }

  /* For floppy disks, we can get the number safely.  */
  num_floppies = grub_biosdisk_get_num_floppies ();
  for (drive = 0; drive < num_floppies; drive++)
    if (grub_biosdisk_call_hook (hook, drive))
      return 1;

  return 0;
}
Beispiel #2
0
static struct grub_biosdisk_data *
get_drive_geom (int drive)
{
  int i;
  struct grub_biosdisk_data *data = grub_biosdisk_geom;
  grub_uint64_t total_sectors = 0;
  unsigned long cylinders;
  int is_fb = 0;
  struct fb_mbr *m;

  for (i = 0; i < grub_biosdisk_num; i++, data++)
    if (data->drive == drive)
      return data;

  m = (struct fb_mbr *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
  if (drive != cd_drive)
    {
      if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
				     GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
	return 0;
      is_fb = ((m->fb_magic == FB_MAGIC_LONG) && (m->end_magic == 0xaa55));
    }
  else
    is_fb = 0;

  if ((grub_biosdisk_num & (DISK_NUM_INC - 1)) == 0)
    {
      grub_biosdisk_geom = grub_realloc (grub_biosdisk_geom,
					 (grub_biosdisk_num + DISK_NUM_INC) *
					 sizeof (*data));
      if (! grub_biosdisk_geom)
	return 0;
    }

  data = &grub_biosdisk_geom[grub_biosdisk_num++];
  grub_memset (data, 0, sizeof (*data));
  data->drive = drive;

  if (drive == cd_drive)
    {
      data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
      data->max_sectors = data->sectors = 32;
      data->total_sectors = GRUB_ULONG_MAX;  /* TODO: get the correct size.  */
      return data;
    }

  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 + 512);

	  /* 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->cylinders == 65535)
		total_sectors = GRUB_ULONG_MAX;
	      else 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;
	    }
	}

      data->sectors = 63;
      data->heads = 255;
      cylinders = 0;
      grub_biosdisk_get_diskinfo_standard (drive, &cylinders,
					   &data->heads, &data->sectors);
    }
  else
    {
      grub_uint16_t t;

      t = *((grub_uint16_t *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 0x18));
      data->sectors = ((t > 0) && (t <= 63)) ? t : 18;
      t = *((grub_uint16_t *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 0x1a));
      data->heads = ((t > 0) && (t <= 255)) ? t : 2;
      cylinders = 1024;
    }

  data->max_sectors = 63;
  if (is_fb)
    {
      grub_uint16_t ofs = m->lba;

      data->max_sectors = m->max_sec;
      if (data->max_sectors >= 0x80)
	{
	  data->max_sectors &= 0x7f;
	  data->flags &= ~GRUB_BIOSDISK_FLAG_LBA;
	}

      if (! (data->flags & GRUB_BIOSDISK_FLAG_LBA))
	{
	  grub_uint16_t lba;

	  if (grub_biosdisk_rw_standard (0x02, drive,
					 0, 1, 1, 1,
					 GRUB_MEMORY_MACHINE_SCRATCH_SEG))
	    goto next;

	  lba = m->end_magic;
	  if (lba == 0xaa55)
	    {
	      if (m->fb_magic != FB_MAGIC_LONG)
		goto next;
	      else
		lba = m->lba;
	    }

	  data->sectors = lba - ofs;

	  if (grub_biosdisk_rw_standard (0x02, drive,
					 1, 0, 1, 1,
					 GRUB_MEMORY_MACHINE_SCRATCH_SEG))
	    goto next;

	  lba = m->end_magic;
	  if (lba == 0xaa55)
	    goto next;

	  data->heads = (lba - ofs) / data->sectors;
	}

      data->flags |= GRUB_BIOSDISK_FLAG_FB;
    }

  if ((data->flags & GRUB_BIOSDISK_FLAG_LBA) &&
      (data->max_sectors == 63))
    data->max_sectors = GRUB_BIOSDISK_MAX_SECTORS;

 next:
  cylinders *= data->heads * data->sectors;
  if (total_sectors < cylinders)
    total_sectors = cylinders;

  data->total_sectors = total_sectors;
  return data;
}