Exemple #1
0
/* These three functions are quite different among OSes.  */
static void
get_floppy_disk_name (char *name, int unit)
{
#if defined(__linux__)
  /* GNU/Linux */
  if (have_devfs ())
    sprintf (name, "/dev/floppy/%d", unit);
  else
    sprintf (name, "/dev/fd%d", unit);
#elif defined(__GNU__)
  /* GNU/Hurd */
  sprintf (name, "/dev/fd%d", unit);
#elif defined(__FreeBSD_kernel__)
  /* kFreeBSD */
  if (get_kfreebsd_version () >= 400000)
    sprintf (name, "/dev/fd%d", unit);
  else
    sprintf (name, "/dev/rfd%d", unit);
#elif defined(__NetBSD__)
  /* NetBSD */
  /* opendisk() doesn't work for floppies.  */
  sprintf (name, "/dev/rfd%da", unit);
#elif defined(__OpenBSD__)
  /* OpenBSD */
  sprintf (name, "/dev/rfd%dc", unit);
#elif defined(__QNXNTO__)
  /* QNX RTP */
  sprintf (name, "/dev/fd%d", unit);
#else
# warning "BIOS floppy drives cannot be guessed in your operating system."
  /* Set NAME to a bogus string.  */
  *name = 0;
#endif
}
Exemple #2
0
static void
get_scsi_disk_name (char *name, int unit)
{
#if defined(__linux__)
  /* GNU/Linux */
  sprintf (name, "/dev/sd%c", unit + 'a');
#elif defined(__GNU__)
  /* GNU/Hurd */
  sprintf (name, "/dev/sd%d", unit);
#elif defined(__FreeBSD_kernel__)
  /* kFreeBSD */
  if (get_kfreebsd_version () >= 400000)
    sprintf (name, "/dev/da%d", unit);
  else
    sprintf (name, "/dev/rda%d", unit);
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
  /* NetBSD */
  char shortname[16];
  int fd;

  sprintf (shortname, "sd%d", unit);
  fd = opendisk (shortname, O_RDONLY, name,
		 16,	/* length of NAME */
		 0	/* char device */
		 );
  close (fd);
#elif defined(__OpenBSD__)
  /* OpenBSD */
  sprintf (name, "/dev/rsd%dc", unit);
#elif defined(__QNXNTO__)
  /* QNX RTP */
  /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
     disable the detection of SCSI disks here.  */
  *name = 0;
#elif defined(__CYGWIN__)
  /* Cygwin emulates all disks as /dev/sdX.  */
  sprintf (name, "/dev/sd%c", unit + 'a');
#elif defined(__MINGW32__)
  (void) unit;
  *name = 0;
#else
# warning "BIOS SCSI drives cannot be guessed in your operating system."
  /* Set NAME to a bogus string.  */
  *name = 0;
#endif
}
Exemple #3
0
static void
get_ide_disk_name (char *name, int unit)
{
#if defined(__linux__)
  /* GNU/Linux */
  sprintf (name, "/dev/hd%c", unit + 'a');
#elif defined(__GNU__)
  /* GNU/Hurd */
  sprintf (name, "/dev/hd%d", unit);
#elif defined(__FreeBSD_kernel__)
  /* kFreeBSD */
  if (get_kfreebsd_version () >= 400000)
    sprintf (name, "/dev/ad%d", unit);
  else
    sprintf (name, "/dev/rwd%d", unit);
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
  /* NetBSD */
  char shortname[16];
  int fd;

  sprintf (shortname, "wd%d", unit);
  fd = opendisk (shortname, O_RDONLY, name,
		 16,	/* length of NAME */
		 0	/* char device */
		 );
  close (fd);
#elif defined(__OpenBSD__)
  /* OpenBSD */
  sprintf (name, "/dev/rwd%dc", unit);
#elif defined(__QNXNTO__)
  /* QNX RTP */
  /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
     contain SCSI disks.  */
  sprintf (name, "/dev/hd%d", unit);
#elif defined(__CYGWIN__)
  /* Cygwin emulates all disks as /dev/sdX.  */
  (void) unit;
  *name = 0;
#elif defined(__MINGW32__)
  sprintf (name, "//./PHYSICALDRIVE%d", unit);
#else
# warning "BIOS IDE drives cannot be guessed in your operating system."
  /* Set NAME to a bogus string.  */
  *name = 0;
#endif
}
Exemple #4
0
void
grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
			   int floppy_disks)
{
  int i;

  clear_seen_devices ();

  /* Floppies.  */
  for (i = 0; i < floppy_disks; i++)
    {
      char name[16];
      struct stat st;

      get_floppy_disk_name (name, i);
      if (stat (name, &st) < 0)
	break;
      /* In floppies, write the map, whether check_device_readable_unique
         succeeds or not, because the user just may not insert floppies.  */
      if (hook (name, 1))
	goto out;
    }

#ifdef __linux__
  {
    DIR *dir = opendir ("/dev/disk/by-id");

    if (dir)
      {
	struct dirent *entry;
	struct device *devs;
	size_t devs_len = 0, devs_max = 1024, i;

	devs = xmalloc (devs_max * sizeof (*devs));

	/* Dump all the directory entries into names, resizing if
	   necessary.  */
	for (entry = readdir (dir); entry; entry = readdir (dir))
	  {
	    /* Skip current and parent directory entries.  */
	    if (strcmp (entry->d_name, ".") == 0 ||
		strcmp (entry->d_name, "..") == 0)
	      continue;
	    /* Skip partition entries.  */
	    if (strstr (entry->d_name, "-part"))
	      continue;
	    /* Skip device-mapper entries; we'll handle the ones we want
	       later.  */
	    if (strncmp (entry->d_name, "dm-", sizeof ("dm-") - 1) == 0)
	      continue;
	    /* Skip RAID entries; they are handled by upper layers.  */
	    if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0)
	      continue;
	    if (devs_len >= devs_max)
	      {
		devs_max *= 2;
		devs = xrealloc (devs, devs_max * sizeof (*devs));
	      }
	    devs[devs_len].stable =
	      xasprintf ("/dev/disk/by-id/%s", entry->d_name);
	    devs[devs_len].kernel =
	      canonicalize_file_name (devs[devs_len].stable);
	    devs_len++;
	  }

	qsort (devs, devs_len, sizeof (*devs), &compare_devices);

	closedir (dir);

	/* Now add all the devices in sorted order.  */
	for (i = 0; i < devs_len; ++i)
	  {
	    if (check_device_readable_unique (devs[i].stable))
	      {
		if (hook (devs[i].stable, 0))
		  goto out;
	      }
	    free (devs[i].stable);
	    free (devs[i].kernel);
	  }
	free (devs);
      }
  }

  if (have_devfs ())
    {
      i = 0;
      while (1)
	{
	  char discn[32];
	  char name[PATH_MAX];
	  struct stat st;

	  /* Linux creates symlinks "/dev/discs/discN" for convenience.
	     The way to number disks is the same as GRUB's.  */
	  sprintf (discn, "/dev/discs/disc%d", i++);
	  if (stat (discn, &st) < 0)
	    break;

	  if (realpath (discn, name))
	    {
	      strcat (name, "/disc");
	      if (hook (name, 0))
		goto out;
	    }
	}
      goto out;
    }
#endif /* __linux__ */

  /* IDE disks.  */
  for (i = 0; i < 96; i++)
    {
      char name[16];

      get_ide_disk_name (name, i);
      if (check_device_readable_unique (name))
	{
	  if (hook (name, 0))
	    goto out;
	}
    }

#ifdef __FreeBSD_kernel__
  /* IDE disks using ATA Direct Access driver.  */
  if (get_kfreebsd_version () >= 800000)
    for (i = 0; i < 96; i++)
      {
	char name[16];

	get_ada_disk_name (name, i);
	if (check_device_readable_unique (name))
	  {
	    if (hook (name, 0))
	      goto out;
	  }
      }

  /* ATARAID disks.  */
  for (i = 0; i < 8; i++)
    {
      char name[20];

      get_ataraid_disk_name (name, i);
      if (check_device_readable_unique (name))
	{
	  if (hook (name, 0))
	    goto out;
        }
    }
#endif

#ifdef __linux__
  /* Virtio disks.  */
  for (i = 0; i < 26; i++)
    {
      char name[16];

      get_virtio_disk_name (name, i);
      if (check_device_readable_unique (name))
	{
	  if (hook (name, 0))
	    goto out;
	}
    }

  /* ATARAID disks.  */
  for (i = 0; i < 8; i++)
    {
      char name[20];

      get_ataraid_disk_name (name, i);
      if (check_device_readable_unique (name))
	{
	  if (hook (name, 0))
	    goto out;
        }
    }

  /* Xen virtual block devices.  */
  for (i = 0; i < 26; i++)
    {
      char name[16];

      get_xvd_disk_name (name, i);
      if (check_device_readable_unique (name))
	{
	  if (hook (name, 0))
	    goto out;
	}
    }
#endif /* __linux__ */

  /* The rest is SCSI disks.  */
  for (i = 0; i < 48; i++)
    {
      char name[16];

      get_scsi_disk_name (name, i);
      if (check_device_readable_unique (name))
	{
	  if (hook (name, 0))
	    goto out;
	}
    }

#ifdef __linux__
  /* This is for DAC960 - we have
     /dev/rd/c<controller>d<logical drive>p<partition>.

     DAC960 driver currently supports up to 8 controllers, 32 logical
     drives, and 7 partitions.  */
  {
    int controller, drive;

    for (controller = 0; controller < 8; controller++)
      {
	for (drive = 0; drive < 15; drive++)
	  {
	    char name[24];

	    get_dac960_disk_name (name, controller, drive);
	    if (check_device_readable_unique (name))
	      {
		if (hook (name, 0))
		  goto out;
	      }
	  }
      }
  }

  /* This is for Mylex Acceleraid - we have
     /dev/rd/c<controller>d<logical drive>p<partition>.  */
  {
    int controller, drive;

    for (controller = 0; controller < 8; controller++)
      {
	for (drive = 0; drive < 15; drive++)
	  {
	    char name[24];

	    get_acceleraid_disk_name (name, controller, drive);
	    if (check_device_readable_unique (name))
	      {
		if (hook (name, 0))
		  goto out;
	      }
	  }
      }
  }

  /* This is for CCISS - we have
     /dev/cciss/c<controller>d<logical drive>p<partition>.  */
  {
    int controller, drive;

    for (controller = 0; controller < 3; controller++)
      {
	for (drive = 0; drive < 16; drive++)
	  {
	    char name[24];

	    get_cciss_disk_name (name, controller, drive);
	    if (check_device_readable_unique (name))
	      {
		if (hook (name, 0))
		  goto out;
	      }
	  }
      }
  }

  /* This is for Compaq Intelligent Drive Array - we have
     /dev/ida/c<controller>d<logical drive>p<partition>.  */
  {
    int controller, drive;

    for (controller = 0; controller < 3; controller++)
      {
	for (drive = 0; drive < 16; drive++)
	  {
	    char name[24];

	    get_ida_disk_name (name, controller, drive);
	    if (check_device_readable_unique (name))
	      {
		if (hook (name, 0))
		  goto out;
	      }
	  }
      }
  }

  /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
  {
    char unit;

    for (unit = 'a'; unit < 'f'; unit++)
      {
	char name[24];

	get_i2o_disk_name (name, unit);
	if (check_device_readable_unique (name))
	  {
	    if (hook (name, 0))
	      goto out;
	  }
      }
  }

  /* MultiMediaCard (MMC).  */
  for (i = 0; i < 10; i++)
    {
      char name[16];

      get_mmc_disk_name (name, i);
      if (check_device_readable_unique (name))
	{
	  if (hook (name, 0))
	    goto out;
	}
    }

# ifdef HAVE_DEVICE_MAPPER
#  define dmraid_check(cond, ...) \
  if (! (cond)) \
    { \
      grub_dprintf ("deviceiter", __VA_ARGS__); \
      goto dmraid_end; \
    }

  /* DM-RAID.  */
  if (grub_device_mapper_supported ())
    {
      struct dm_tree *tree = NULL;
      struct dm_task *task = NULL;
      struct dm_names *names = NULL;
      unsigned int next = 0;
      void *top_handle, *second_handle;
      struct dm_tree_node *root, *top, *second;

      /* Build DM tree for all devices.  */
      tree = dm_tree_create ();
      dmraid_check (tree, "dm_tree_create failed\n");
      task = dm_task_create (DM_DEVICE_LIST);
      dmraid_check (task, "dm_task_create failed\n");
      dmraid_check (dm_task_run (task), "dm_task_run failed\n");
      names = dm_task_get_names (task);
      dmraid_check (names, "dm_task_get_names failed\n");
      dmraid_check (names->dev, "No DM devices found\n");
      do
	{
	  names = (void *) names + next;
	  dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev),
					 MINOR (names->dev)),
			   "dm_tree_add_dev (%s) failed\n", names->name);
	  next = names->next;
	}
      while (next);

      /* Walk the second-level children of the inverted tree; that is, devices
	 which are directly composed of non-DM devices such as hard disks.
	 This class includes all DM-RAID disks and excludes all DM-RAID
	 partitions.  */
      root = dm_tree_find_node (tree, 0, 0);
      top_handle = NULL;
      top = dm_tree_next_child (&top_handle, root, 1);
      while (top)
	{
	  second_handle = NULL;
	  second = dm_tree_next_child (&second_handle, top, 1);
	  while (second)
	    {
	      const char *node_name, *node_uuid;
	      char *name;

	      node_name = dm_tree_node_get_name (second);
	      dmraid_check (node_name, "dm_tree_node_get_name failed\n");
	      node_uuid = dm_tree_node_get_uuid (second);
	      dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n");
	      if (strncmp (node_uuid, "DMRAID-", 7) != 0)
		{
		  grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name);
		  goto dmraid_next_child;
		}

	      name = xasprintf ("/dev/mapper/%s", node_name);
	      if (check_device_readable_unique (name))
		{
		  if (hook (name, 0))
		    {
		      free (name);
		      if (task)
			dm_task_destroy (task);
		      if (tree)
			dm_tree_free (tree);
		      goto out;
		    }
		}
	      free (name);

dmraid_next_child:
	      second = dm_tree_next_child (&second_handle, top, 1);
	    }
	  top = dm_tree_next_child (&top_handle, root, 1);
	}

dmraid_end:
      if (task)
	dm_task_destroy (task);
      if (tree)
	dm_tree_free (tree);
    }
# endif /* HAVE_DEVICE_MAPPER */
#endif /* __linux__ */

out:
  clear_seen_devices ();
}
Exemple #5
0
/* Get the geometry of a drive DRIVE.  */
void
get_drive_geometry (struct geometry *geom, char **map, int drive)
{
  int fd;

  if (geom->flags == -1)
    {
      fd = open (map[drive], O_RDONLY);
      assert (fd >= 0);
    }
  else
    fd = geom->flags;

  /* XXX This is the default size.  */
  geom->sector_size = SECTOR_SIZE;
  
#if defined(__linux__)
  /* Linux */
  {
    struct hd_geometry hdg;
    unsigned long nr;
    
    if (ioctl (fd, HDIO_GETGEO, &hdg))
      goto fail;

    if (ioctl (fd, BLKGETSIZE, &nr))
      goto fail;
    
    /* Got the geometry, so save it. */
    geom->cylinders = hdg.cylinders;
    geom->heads = hdg.heads;
    geom->sectors = hdg.sectors;
    geom->total_sectors = nr;
    geom->sector_size = SECTOR_SIZE;
    
    goto success;
  }

#elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
# if defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version >= 500040
  /* kFreeBSD version 5 or later */
  if (get_kfreebsd_version () >= 500040)
  {
    unsigned int sector_size;
    off_t media_size;
    unsigned int tmp;
    
    if(ioctl (fd, DIOCGSECTORSIZE, &sector_size) != 0)
      sector_size = 512;
    
    if (ioctl (fd, DIOCGMEDIASIZE, &media_size) != 0)
      goto fail;

    geom->total_sectors = media_size / sector_size;
    
    if (ioctl (fd, DIOCGFWSECTORS, &tmp) == 0)
      geom->sectors = tmp;
    else
      geom->sectors = 63;
    if (ioctl (fd, DIOCGFWHEADS, &tmp) == 0)
      geom->heads = tmp;
    else if (geom->total_sectors <= 63 * 1 * 1024)
      geom->heads = 1;
    else if (geom->total_sectors <= 63 * 16 * 1024)
      geom->heads = 16;
    else
      geom->heads = 255;

    geom->cylinders = (geom->total_sectors
			   / geom->heads
			   / geom->sectors);
    
    goto success;
  }
  else
#endif /* defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version >= 500040 */

  /* kFreeBSD < 5, NetBSD or OpenBSD */
  {
    struct disklabel hdg;
    if (ioctl (fd, DIOCGDINFO, &hdg))
      goto fail;
    
    geom->cylinders = hdg.d_ncylinders;
    geom->heads = hdg.d_ntracks;
    geom->sectors = hdg.d_nsectors;
    geom->total_sectors = hdg.d_secperunit;
    geom->sector_size = SECTOR_SIZE;

    goto success;
  }
  
#else
  /* Notably, defined(__GNU__) */
# warning "Automatic detection of geometries will be performed only \
partially. This is not fatal."
#endif

 fail:
  {
    struct stat st;

    /* FIXME: It would be nice to somehow compute fake C/H/S settings,
       given a proper st_blocks size. */
    if (drive & 0x80)
      {
	geom->cylinders = DEFAULT_HD_CYLINDERS;
	geom->heads = DEFAULT_HD_HEADS;
	geom->sectors = DEFAULT_HD_SECTORS;
      }
    else
      {
	geom->cylinders = DEFAULT_FD_CYLINDERS;
	geom->heads = DEFAULT_FD_HEADS;
	geom->sectors = DEFAULT_FD_SECTORS;
      }

    /* Set the total sectors properly, if we can. */
    if (! fstat (fd, &st) && st.st_size)
      geom->total_sectors = st.st_size >> SECTOR_BITS;
    else
      geom->total_sectors = geom->cylinders * geom->heads * geom->sectors;

    geom->sector_size = SECTOR_SIZE;
  }