Exemplo n.º 1
0
/* Helper for scan_disk.  */
static int
scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
{
  const char *name = data;
  struct grub_diskfilter_vg *arr;
  grub_disk_addr_t start_sector;
  struct grub_diskfilter_pv_id id;
  grub_diskfilter_t diskfilter;

  grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n",
		name);
#ifdef GRUB_UTIL
  grub_util_info ("Scanning for DISKFILTER devices on disk %s", name);
#endif

  disk->partition = p;
  
  for (arr = array_list; arr != NULL; arr = arr->next)
    {
      struct grub_diskfilter_pv *m;
      for (m = arr->pvs; m; m = m->next)
	if (m->disk && m->disk->id == disk->id
	    && m->disk->dev->id == disk->dev->id
	    && m->part_start == grub_partition_get_start (disk->partition)
	    && m->part_size == grub_disk_get_size (disk))
	  return 0;
    }

  for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next)
    {
#ifdef GRUB_UTIL
      grub_util_info ("Scanning for %s devices on disk %s", 
		      diskfilter->name, name);
#endif
      id.uuid = 0;
      id.uuidlen = 0;
      arr = diskfilter->detect (disk, &id, &start_sector);
      if (arr &&
	  (! insert_array (disk, &id, arr, start_sector, diskfilter)))
	{
	  if (id.uuidlen)
	    grub_free (id.uuid);
	  return 0;
	}
      if (arr && id.uuidlen)
	grub_free (id.uuid);

      /* This error usually means it's not diskfilter, no need to display
	 it.  */
      if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
	grub_print_error ();

      grub_errno = GRUB_ERR_NONE;
    }

  return 0;
}
Exemplo n.º 2
0
static grub_err_t
grub_util_biosdisk_open (const char *name, grub_disk_t disk)
{
  int drive;
  struct grub_util_hostdisk_data *data;

  drive = find_grub_drive (name);
  grub_util_info ("drive = %d", drive);
  if (drive < 0)
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
		       "no mapping exists for `%s'", name);

  disk->id = drive;
  disk->data = data = xmalloc (sizeof (struct grub_util_hostdisk_data));
  data->dev = NULL;
  data->access_mode = 0;
  data->fd = GRUB_UTIL_FD_INVALID;
  data->is_disk = 0;
  data->device_map = map[drive].device_map;

  /* Get the size.  */
  {
    grub_util_fd_t fd;

    fd = grub_util_fd_open (map[drive].device, GRUB_UTIL_FD_O_RDONLY);

    if (!GRUB_UTIL_FD_IS_VALID(fd))
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"),
			 map[drive].device, grub_util_fd_strerror ());

    disk->total_sectors = grub_util_get_fd_size (fd, map[drive].device,
						 &disk->log_sector_size);
    disk->total_sectors >>= disk->log_sector_size;

#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
    {
      struct stat st;
# if GRUB_DISK_DEVS_ARE_CHAR
      if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
# else
      if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
# endif
	data->is_disk = 1;
    }
#endif

    grub_util_fd_close (fd);

    grub_util_info ("the size of %s is %" PRIuGRUB_UINT64_T,
		    name, disk->total_sectors);

    return GRUB_ERR_NONE;
  }
}
Exemplo n.º 3
0
static void
probe_partmap (grub_disk_t disk)
{
  grub_partition_t part;
  grub_disk_memberlist_t list = NULL, tmp;

  if (disk->partition == NULL)
    {
      grub_util_info ("no partition map found for %s", disk->name);
    }

  for (part = disk->partition; part; part = part->parent)
    printf ("%s ", part->partmap->name);

  if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
    grub_diskfilter_get_partmap (disk, do_print);

  /* In case of LVM/RAID, check the member devices as well.  */
  if (disk->dev->memberlist)
    {
      list = disk->dev->memberlist (disk);
    }
  while (list)
    {
      probe_partmap (list->disk);
      tmp = list->next;
      free (list);
      list = tmp;
    }
}
Exemplo n.º 4
0
void
grub_util_write_image (const char *img, size_t size, FILE *out)
{
  grub_util_info ("writing 0x%x bytes", size);
  if (fwrite (img, 1, size, out) != size)
    grub_util_error ("write failed");
}
Exemplo n.º 5
0
Arquivo: misc.c Projeto: Arvian/GRUB2
char *
grub_util_read_image (const char *path)
{
  char *img;
  FILE *fp;
  size_t size;

  grub_util_info ("reading %s", path);

  size = grub_util_get_image_size (path);
  img = (char *) xmalloc (size);

  fp = fopen (path, "rb");
  if (! fp)
    grub_util_error (_("cannot open `%s': %s"), path,
		     strerror (errno));

  if (fread (img, 1, size, fp) != size)
    grub_util_error (_("cannot read `%s': %s"), path,
		     strerror (errno));

  fclose (fp);

  return img;
}
Exemplo n.º 6
0
void
grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out)
{
  grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset);
  if (fseeko (out, offset, SEEK_SET) == -1)
    grub_util_error ("seek failed");
  if (fwrite (img, 1, size, out) != size)
    grub_util_error ("write failed");
}
Exemplo n.º 7
0
static char *
find_obppath (const char *sysfs_path_orig)
{
  char *sysfs_path, *path;
  size_t path_size = strlen (sysfs_path_orig) + sizeof ("/obppath");

  sysfs_path = xstrdup (sysfs_path_orig);
  path = xmalloc (path_size);

  while (1)
    {
      int fd;
      char *of_path;
      struct stat st;
      size_t size;

      snprintf(path, path_size, "%s/obppath", sysfs_path);
#if 0
      printf("Trying %s\n", path);
#endif

      fd = open(path, O_RDONLY);
      if (fd < 0 || fstat (fd, &st) < 0)
	{
	  snprintf(path, path_size, "%s/devspec", sysfs_path);
	  fd = open(path, O_RDONLY);
	}

      if (fd < 0 || fstat (fd, &st) < 0)
	{
	  kill_trailing_dir(sysfs_path);
	  if (!strcmp(sysfs_path, "/sys"))
	    {
	      grub_util_info (_("`obppath' not found in parent dirs of `%s',"
				" no IEEE1275 name discovery"),
			      sysfs_path_orig);
	      free (path);
	      free (sysfs_path);
	      return NULL;
	    }
	  continue;
	}
      size = st.st_size;
      of_path = xmalloc (size + MAX_DISK_CAT + 1);
      memset(of_path, 0, size + MAX_DISK_CAT + 1);
      read(fd, of_path, size);
      close(fd);

      trim_newline(of_path);
      free (path);
      free (sysfs_path);
      return of_path;
    }
}
Exemplo n.º 8
0
Arquivo: misc.c Projeto: Arvian/GRUB2
size_t
grub_util_get_image_size (const char *path)
{
  struct stat st;

  grub_util_info ("getting the size of %s", path);

  if (stat (path, &st) == -1)
    grub_util_error (_("cannot stat `%s': %s"), path, strerror (errno));

  return st.st_size;
}
Exemplo n.º 9
0
Arquivo: misc.c Projeto: Arvian/GRUB2
void
grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out,
			  const char *name)
{
  grub_util_info ("writing 0x%" PRIxGRUB_SIZE " bytes at offset 0x%llx",
		  size, (unsigned long long) offset);
  if (fseeko (out, offset, SEEK_SET) == -1)
    grub_util_error (_("cannot seek `%s': %s"),
		     name, strerror (errno));
  if (fwrite (img, 1, size, out) != size)
    grub_util_error (_("cannot write to `%s': %s"),
		     name, strerror (errno));
}
Exemplo n.º 10
0
int
main (int argc, char *argv[])
{
  const char *pkglibdir;

  grub_util_host_init (&argc, &argv);
  grub_util_disable_fd_syncs ();
  rootdir = xstrdup ("/srv/tftp");
  pkglibdir = grub_util_get_pkglibdir ();

  subdir = grub_util_path_concat (2, GRUB_BOOT_DIR_NAME, GRUB_DIR_NAME);

  argp_parse (&argp, argc, argv, 0, 0, 0);

  base = grub_util_path_concat (2, rootdir, subdir);
  /* Create the GRUB directory if it is not present.  */

  grub_install_mkdir_p (base);

  grub_install_push_module ("tftp");

  if (!grub_install_source_directory)
    {
      enum grub_install_plat plat;

      for (plat = 0; plat < GRUB_INSTALL_PLATFORM_MAX; plat++)
	if (targets[plat].mkimage_target)
	  {
	    char *platdir = grub_util_path_concat (2, pkglibdir,
						   grub_install_get_platform_name (plat));

	    grub_util_info ("Looking for `%s'", platdir);

	    if (!grub_util_is_directory (platdir))
	      {
		free (platdir);
		continue;
	      }
	    process_input_dir (platdir, plat);
	  }
    }
  else
    {
      enum grub_install_plat plat;
      plat = grub_install_get_target (grub_install_source_directory);
      process_input_dir (grub_install_source_directory, plat);
    }
  return 0;
}
Exemplo n.º 11
0
Arquivo: misc.c Projeto: Arvian/GRUB2
void
grub_util_write_image (const char *img, size_t size, FILE *out,
		       const char *name)
{
  grub_util_info ("writing 0x%" PRIxGRUB_SIZE " bytes", size);
  if (fwrite (img, 1, size, out) != size)
    {
      if (!name)
	grub_util_error (_("cannot write to the stdout: %s"),
			 strerror (errno));
      else
	grub_util_error (_("cannot write to `%s': %s"),
			 name, strerror (errno));
    }
}
Exemplo n.º 12
0
void
grub_util_load_image (const char *path, char *buf)
{
  FILE *fp;
  size_t size;

  grub_util_info ("reading %s", path);

  size = grub_util_get_image_size (path);

  fp = fopen (path, "rb");
  if (! fp)
    grub_util_error ("cannot open %s", path);

  if (fread (buf, 1, size, fp) != size)
    grub_util_error ("cannot read %s", path);

  fclose (fp);
}
Exemplo n.º 13
0
static grub_uint64_t
grub_util_get_fd_size_volume (grub_util_fd_t fd __attribute__ ((unused)),
			      const char *dev,
			      unsigned *log_secsize)
{
  struct DriveGeometry *geo;
  LONG err;
  unsigned sector_size, log_sector_size;

  if (!bounce)
    bounce = AllocVec (BOUNCE_SIZE, MEMF_PUBLIC | MEMF_CLEAR);
  if (!bounce)
    grub_util_error ("out of memory");

  fd->ioreq->iotd_Req.io_Command = TD_GETGEOMETRY;
  fd->ioreq->iotd_Req.io_Length = sizeof (*geo);
  fd->ioreq->iotd_Req.io_Data = bounce;
  fd->ioreq->iotd_Req.io_Offset = 0;
  fd->ioreq->iotd_Req.io_Actual = 0;
  err = DoIO ((struct IORequest *) fd->ioreq);
  if (err)
    {
      grub_util_info ("I/O failed with error %d, IoErr=%d", (int)err, (int) IoErr ());
      return -1;
    }

  geo = (struct DriveGeometry *) bounce;

  sector_size = geo->dg_SectorSize;

  if (sector_size & (sector_size - 1) || !sector_size)
    return -1;

  for (log_sector_size = 0;
       (1 << log_sector_size) < sector_size;
       log_sector_size++);

  if (log_secsize)
    *log_secsize = log_sector_size;

  return (grub_uint64_t) geo->dg_TotalSectors * (grub_uint64_t) geo->dg_SectorSize;
}
Exemplo n.º 14
0
char *
grub_util_read_image (const char *path)
{
  char *img;
  FILE *fp;
  size_t size;

  grub_util_info ("reading %s", path);

  size = grub_util_get_image_size (path);
  img = (char *) xmalloc (size);

  fp = fopen (path, "rb");
  if (! fp)
    grub_util_error ("cannot open %s", path);

  grub_util_read_at (img, size, 0, fp);

  fclose (fp);

  return img;
}
Exemplo n.º 15
0
Arquivo: ldm.c Projeto: flihp/grub2
static struct grub_diskfilter_vg * 
grub_ldm_detect (grub_disk_t disk,
		 struct grub_diskfilter_pv_id *id,
		 grub_disk_addr_t *start_sector)
{
  grub_err_t err;
  struct grub_ldm_label label;
  struct grub_diskfilter_vg *vg;

#ifdef GRUB_UTIL
  grub_util_info ("scanning %s for LDM", disk->name);
#endif

  {
    int i;
    int has_ldm = msdos_has_ldm_partition (disk);
    for (i = 0; i < 3; i++)
      {
	grub_disk_addr_t sector = LDM_LABEL_SECTOR;
	switch (i)
	  {
	  case 0:
	    if (!has_ldm)
	      continue;
	    sector = LDM_LABEL_SECTOR;
	    break;
	  case 1:
	    /* LDM is never inside a partition.  */
	    if (!has_ldm || disk->partition)
	      continue;
	    sector = grub_disk_get_size (disk);
	    if (sector == GRUB_DISK_SIZE_UNKNOWN)
	      continue;
	    sector--;
	    break;
	    /* FIXME: try the third copy.  */
	  case 2:
	    sector = gpt_ldm_sector (disk);
	    if (!sector)
	      continue;
	    break;
	  }
	err = grub_disk_read (disk, sector, 0,
			      sizeof(label), &label);
	if (err)
	  return NULL;
	if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0
	    && grub_be_to_cpu16 (label.ver_major) == 0x02
	    && grub_be_to_cpu16 (label.ver_minor) >= 0x0b
	    && grub_be_to_cpu16 (label.ver_minor) <= 0x0c)
	  break;
      }

    /* Return if we didn't find a label. */
    if (i == 3)
      {
#ifdef GRUB_UTIL
	grub_util_info ("no LDM signature found");
#endif
	return NULL;
      }
  }

  id->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
  if (!id->uuid)
    return NULL;
  grub_memcpy (id->uuid, label.disk_guid, LDM_GUID_STRLEN);
  id->uuid[LDM_GUID_STRLEN] = 0;
  id->uuidlen = grub_strlen ((char *) id->uuid);
  *start_sector = grub_be_to_cpu64 (label.pv_start);

  {
    grub_size_t s;
    for (s = 0; s < LDM_GUID_STRLEN && label.group_guid[s]; s++);
    vg = grub_diskfilter_get_vg_by_uuid (s, label.group_guid);
    if (! vg)
      vg = make_vg (disk, &label);
  }

  if (!vg)
    {
      grub_free (id->uuid);
      return NULL;
    }
  return vg;
}
Exemplo n.º 16
0
static void
probe (const char *path, char **device_names, char delim)
{
  char **drives_names = NULL;
  char **curdev, **curdrive;
  char *grub_path = NULL;
  int ndev = 0;

  if (path != NULL)
    {
      grub_path = canonicalize_file_name (path);
      if (! grub_path)
	grub_util_error (_("failed to get canonical path of `%s'"), path);
      device_names = grub_guess_root_devices (grub_path);
      free (grub_path);
    }

  if (! device_names)
    grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path);

  if (print == PRINT_DEVICE)
    {
      for (curdev = device_names; *curdev; curdev++)
	{
	  printf ("%s", *curdev);
	  putchar (delim);
	}
      return;
    }

  if (print == PRINT_DISK)
    {
      for (curdev = device_names; *curdev; curdev++)
	{
	  char *disk;
	  disk = grub_util_get_os_disk (*curdev);
	  if (!disk)
	    {
	      grub_print_error ();
	      continue;
	    }
	  printf ("%s", disk);
	  putchar (delim);
	}
      return;
    }

  for (curdev = device_names; *curdev; curdev++)
    {
      grub_util_pull_device (*curdev);
      ndev++;
    }
  
  drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1)); 

  for (curdev = device_names, curdrive = drives_names; *curdev; curdev++,
       curdrive++)
    {
      *curdrive = grub_util_get_grub_dev (*curdev);
      if (! *curdrive)
	grub_util_error (_("cannot find a GRUB drive for %s.  Check your device.map"),
			 *curdev);
    }
  *curdrive = 0;

  if (print == PRINT_DRIVE)
    {
      for (curdrive = drives_names; *curdrive; curdrive++)
	{
	  printf ("(%s)", *curdrive);
	  putchar (delim);
	}
      goto end;
    }

  if (print == PRINT_ZERO_CHECK)
    {
      for (curdev = drives_names; *curdev; curdev++)
	{
	  grub_device_t dev = NULL;
	  grub_uint32_t buffer[32768];
	  grub_disk_addr_t addr;
	  grub_disk_addr_t dsize;

	  grub_util_info ("opening %s", *curdev);
	  dev = grub_device_open (*curdev);
	  if (! dev || !dev->disk)
	    grub_util_error ("%s", grub_errmsg);

	  dsize = grub_disk_get_size (dev->disk);
	  for (addr = 0; addr < dsize;
	       addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
	    {
	      grub_size_t sz = sizeof (buffer);
	      grub_uint32_t *ptr;

	      if (sizeof (buffer) / GRUB_DISK_SECTOR_SIZE > dsize - addr)
		sz = (dsize - addr) * GRUB_DISK_SECTOR_SIZE;
	      grub_disk_read (dev->disk, addr, 0, sz, buffer);

	      for (ptr = buffer; ptr < buffer + sz / sizeof (*buffer); ptr++)
		if (*ptr)
		  {
		    grub_printf ("false\n");
		    grub_device_close (dev);
		    goto end;
		  }
	    }

	  grub_device_close (dev);
	}
      grub_printf ("true\n");
    }

  if (print == PRINT_FS || print == PRINT_FS_UUID
      || print == PRINT_FS_LABEL)
    {
      grub_device_t dev = NULL;
      grub_fs_t fs;

      grub_util_info ("opening %s", drives_names[0]);
      dev = grub_device_open (drives_names[0]);
      if (! dev)
	grub_util_error ("%s", grub_errmsg);
      
      fs = grub_fs_probe (dev);
      if (! fs)
	grub_util_error ("%s", grub_errmsg);

      if (print == PRINT_FS)
	{
	  printf ("%s", fs->name);
	  putchar (delim);
	}
      else if (print == PRINT_FS_UUID)
	{
	  char *uuid;
	  if (! fs->uuid)
	    grub_util_error (_("%s does not support UUIDs"), fs->name);

	  if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE)
	    grub_util_error ("%s", grub_errmsg);

	  printf ("%s", uuid);
	  putchar (delim);
	}
      else if (print == PRINT_FS_LABEL)
	{
	  char *label;
	  if (! fs->label)
	    grub_util_error (_("filesystem `%s' does not support labels"),
			     fs->name);

	  if (fs->label (dev, &label) != GRUB_ERR_NONE)
	    grub_util_error ("%s", grub_errmsg);

	  printf ("%s", label);
	  putchar (delim);
	}
      grub_device_close (dev);
      goto end;
    }

  for (curdrive = drives_names, curdev = device_names; *curdrive;
       curdrive++, curdev++)
    {
      grub_device_t dev = NULL;

      grub_util_info ("opening %s", *curdrive);
      dev = grub_device_open (*curdrive);
      if (! dev)
	grub_util_error ("%s", grub_errmsg);

      if (print == PRINT_HINT_STR)
	{
	  const char *osdev = grub_util_biosdisk_get_osdev (dev->disk);
	  const char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0;
	  char *biosname, *bare, *efi;
	  const char *map;

	  if (ofpath)
	    {
	      char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/"));
	      char *p;
	      p = grub_stpcpy (tmp, "ieee1275/");
	      strcpy (p, ofpath);
	      printf ("--hint-ieee1275='");
	      print_full_name (tmp, dev);
	      printf ("' ");
	      free (tmp);
	    }

	  biosname = guess_bios_drive (*curdev);
	  if (biosname)
	    {
	      printf ("--hint-bios=");
	      print_full_name (biosname, dev);
	      printf (" ");
	    }
	  free (biosname);

	  efi = guess_efi_drive (*curdev);
	  if (efi)
	    {
	      printf ("--hint-efi=");
	      print_full_name (efi, dev);
	      printf (" ");
	    }
	  free (efi);

	  bare = guess_baremetal_drive (*curdev);
	  if (bare)
	    {
	      printf ("--hint-baremetal=");
	      print_full_name (bare, dev);
	      printf (" ");
	    }
	  free (bare);

	  /* FIXME: Add ARC hint.  */

	  map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
	  if (map)
	    {
	      printf ("--hint='");
	      print_full_name (map, dev);
	      printf ("' ");
	    }
	  if (curdrive[1])
	    printf (" ");
	  else
	    printf ("\n");

	  grub_device_close (dev);
	  continue;
	}
      
      if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT
	   || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT
	   || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT)
	  && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID)
	{
	  print_full_name (dev->disk->name, dev);
	  putchar (delim);
	  continue;
	}

      if (print == PRINT_COMPATIBILITY_HINT)
	{
	  const char *map;
	  char *biosname;
	  map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
	  if (map)
	    {
	      print_full_name (map, dev);
	      putchar (delim);
	      grub_device_close (dev);
	      /* Compatibility hint is one device only.  */
	      break;
	    }
	  biosname = guess_bios_drive (*curdev);
	  if (biosname)
	    {
	      print_full_name (biosname, dev);
	      putchar (delim);
	    }
	  free (biosname);
	  grub_device_close (dev);
	  /* Compatibility hint is one device only.  */
	  if (biosname)
	    break;
	  continue;
	}

      if (print == PRINT_BIOS_HINT)
	{
	  char *biosname;
	  biosname = guess_bios_drive (*curdev);
	  if (biosname)
	    {
	      print_full_name (biosname, dev);
	      putchar (delim);
	    }
	  free (biosname);
	  grub_device_close (dev);
	  continue;
	}
      if (print == PRINT_IEEE1275_HINT)
	{
	  const char *osdev = grub_util_biosdisk_get_osdev (dev->disk);
	  const char *ofpath = grub_util_devname_to_ofpath (osdev);
	  const char *map;

	  map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
	  if (map)
	    {
	      print_full_name (map, dev);
	      putchar (delim);
	    }

	  if (ofpath)
	    {
	      char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/"));
	      char *p;
	      p = grub_stpcpy (tmp, "ieee1275/");
	      strcpy (p, ofpath);
	      print_full_name (tmp, dev);
	      free (tmp);
	      putchar (delim);
	    }

	  grub_device_close (dev);
	  continue;
	}
      if (print == PRINT_EFI_HINT)
	{
	  char *biosname;
	  const char *map;
	  biosname = guess_efi_drive (*curdev);

	  map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
	  if (map)
	    {
	      print_full_name (map, dev);
	      putchar (delim);
	    }
	  if (biosname)
	    {
	      print_full_name (biosname, dev);
	      putchar (delim);
	    }

	  free (biosname);
	  grub_device_close (dev);
	  continue;
	}

      if (print == PRINT_BAREMETAL_HINT)
	{
	  char *biosname;
	  const char *map;

	  biosname = guess_baremetal_drive (*curdev);

	  map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
	  if (map)
	    {
	      print_full_name (map, dev);
	      putchar (delim);
	    }
	  if (biosname)
	    {
	      print_full_name (biosname, dev);
	      putchar (delim);
	    }

	  free (biosname);
	  grub_device_close (dev);
	  continue;
	}

      if (print == PRINT_ARC_HINT)
	{
	  const char *map;

	  map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
	  if (map)
	    {
	      print_full_name (map, dev);
	      putchar (delim);
	    }

	  /* FIXME */
	  grub_device_close (dev);
	  continue;
	}

      if (print == PRINT_ABSTRACTION)
	{
	  probe_abstraction (dev->disk);
	  putchar (delim);
	  grub_device_close (dev);
	  continue;
	}

      if (print == PRINT_CRYPTODISK_UUID)
	{
	  probe_cryptodisk_uuid (dev->disk);
	  putchar (delim);
	  grub_device_close (dev);
	  continue;
	}

      if (print == PRINT_PARTMAP)
	{
	  /* Check if dev->disk itself is contained in a partmap.  */
	  probe_partmap (dev->disk);
	  putchar (delim);
	  grub_device_close (dev);
	  continue;
	}

      if (print == PRINT_MSDOS_PARTTYPE)
	{
	  if (dev->disk->partition
	      && strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
	    printf ("%02x", dev->disk->partition->msdostype);

	  putchar (delim);
	  grub_device_close (dev);
	  continue;
	}

      if (print == PRINT_GPT_PARTTYPE)
	{
          if (dev->disk->partition
	      && strcmp (dev->disk->partition->partmap->name, "gpt") == 0)
            {
              struct grub_gpt_partentry gptdata;
              grub_partition_t p = dev->disk->partition;
              dev->disk->partition = dev->disk->partition->parent;

              if (grub_disk_read (dev->disk, p->offset, p->index,
                                  sizeof (gptdata), &gptdata) == 0)
                {
                  grub_gpt_part_type_t gpttype;
                  gpttype.data1 = grub_le_to_cpu32 (gptdata.type.data1);
                  gpttype.data2 = grub_le_to_cpu16 (gptdata.type.data2);
                  gpttype.data3 = grub_le_to_cpu16 (gptdata.type.data3);
                  grub_memcpy (gpttype.data4, gptdata.type.data4, 8);

                  grub_printf ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
                               gpttype.data1, gpttype.data2,
                               gpttype.data3, gpttype.data4[0], 
                               gpttype.data4[1], gpttype.data4[2],
                               gpttype.data4[3], gpttype.data4[4],
                               gpttype.data4[5], gpttype.data4[6],
                               gpttype.data4[7]);
                }
              dev->disk->partition = p;
            }
          putchar (delim);
          grub_device_close (dev);
          continue;
        }
    }

 end:
  for (curdrive = drives_names; *curdrive; curdrive++)
    free (*curdrive);
  free (drives_names);
}
Exemplo n.º 17
0
char *
grub_find_device (const char *dir, dev_t dev)
{
  DIR *dp;
  char *saved_cwd;
  struct dirent *ent;

  if (! dir)
    dir = "/dev";

  dp = opendir (dir);
  if (! dp)
    return 0;

  saved_cwd = xgetcwd ();

  grub_util_info ("changing current directory to %s", dir);
  if (chdir (dir) < 0)
    {
      free (saved_cwd);
      closedir (dp);
      return 0;
    }

  while ((ent = readdir (dp)) != 0)
    {
      struct stat st;

      /* Avoid:
	 - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
	 - dotdirs (like "/dev/.static") since they could contain duplicates.  */
      if (ent->d_name[0] == '.')
	continue;

      if (lstat (ent->d_name, &st) < 0)
	/* Ignore any error.  */
	continue;

      if (S_ISLNK (st.st_mode)) {
#ifdef __linux__
	if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) {
	  /* Follow symbolic links under /dev/mapper/; the canonical name
	     may be something like /dev/dm-0, but the names under
	     /dev/mapper/ are more human-readable and so we prefer them if
	     we can get them.  */
	  if (stat (ent->d_name, &st) < 0)
	    continue;
	} else
#endif /* __linux__ */
	/* Don't follow other symbolic links.  */
	continue;
      }

      if (S_ISDIR (st.st_mode))
	{
	  /* Find it recursively.  */
	  char *res;

	  res = grub_find_device (ent->d_name, dev);

	  if (res)
	    {
	      if (chdir (saved_cwd) < 0)
		grub_util_error ("%s",
				 _("cannot restore the original directory"));

	      free (saved_cwd);
	      closedir (dp);
	      return res;
	    }
	}

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
      if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
#else
      if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
#endif
	{
#ifdef __linux__
	  /* Skip device names like /dev/dm-0, which are short-hand aliases
	     to more descriptive device names, e.g. those under /dev/mapper */
	  if (ent->d_name[0] == 'd' &&
	      ent->d_name[1] == 'm' &&
	      ent->d_name[2] == '-' &&
	      ent->d_name[3] >= '0' &&
	      ent->d_name[3] <= '9')
	    continue;
#endif

	  /* Found!  */
	  char *res;
	  char *cwd;

	  cwd = xgetcwd ();
	  res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
	  sprintf (res, 
#if defined(__NetBSD__) || defined(__OpenBSD__)
		   /* Convert this block device to its character (raw) device.  */
		   "%s/r%s",
#else
		   /* Keep the device name as it is.  */
		   "%s/%s",
#endif
		   cwd, ent->d_name);
	  strip_extra_slashes (res);
	  free (cwd);

	  /* /dev/root is not a real block device keep looking, takes care
	     of situation where root filesystem is on the same partition as
	     grub files */

	  if (strcmp(res, "/dev/root") == 0)
	    {
	      free (res);
	      continue;
	    }

	  if (chdir (saved_cwd) < 0)
	    grub_util_error ("%s", _("cannot restore the original directory"));

	  free (saved_cwd);
	  closedir (dp);
	  return res;
	}
    }

  if (chdir (saved_cwd) < 0)
    grub_util_error ("%s", _("cannot restore the original directory"));

  free (saved_cwd);
  closedir (dp);
  return 0;
}
Exemplo n.º 18
0
static void
read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
{
  static char buf[BUF_SIZE];
  grub_file_t file;
  grub_off_t ofs, len;

  if ((pathname[0] == '-') && (pathname[1] == 0))
    {
      grub_device_t dev;

      dev = grub_device_open (0);
      if ((! dev) || (! dev->disk))
        grub_util_error (_("can\'t open device"));

      grub_util_info ("total sectors : %lld",
                      (unsigned long long) dev->disk->total_sectors);

      if (! leng)
        leng = (dev->disk->total_sectors << GRUB_DISK_SECTOR_BITS) - skip;

      while (leng)
        {
          grub_size_t len;

          len = (leng > BUF_SIZE) ? BUF_SIZE : leng;

          if (grub_disk_read (dev->disk, 0, skip, len, buf))
            grub_util_error (_("disk read fails at offset %lld, length %d"),
                             skip, len);

          if (hook (skip, buf, len))
            break;

          skip += len;
          leng -= len;
        }

      grub_device_close (dev);
      return;
    }

  grub_file_filter_disable_compression ();
  file = grub_file_open (pathname);
  if (!file)
    {
      grub_util_error (_("cannot open file %s:%s"), pathname,
		       grub_errmsg);
      return;
    }

  grub_util_info ("file size : %lld", (unsigned long long) file->size);

  if (skip > file->size)
    {
      grub_util_error (_("invalid skip value %lld"), (unsigned long long) skip);
      return;
    }

  ofs = skip;
  len = file->size - skip;
  if ((leng) && (leng < len))
    len = leng;

  file->offset = skip;

  while (len)
    {
      grub_ssize_t sz;

      sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len);
      if (sz < 0)
	{
	  grub_util_error (_("read error at offset %llu: %s"), ofs,
			   grub_errmsg);
	  break;
	}

      if ((sz == 0) || (hook (ofs, buf, sz)))
	break;

      ofs += sz;
      len -= sz;
    }

  grub_file_close (file);
}
Exemplo n.º 19
0
static int
grub_util_is_imsm (const char *os_dev)
{
  int retry;
  int is_imsm = 0;
  int container_seen = 0;
  const char *dev = os_dev;

  do
    {
      const char *argv[5];
      int fd;
      pid_t pid;
      FILE *mdadm;
      char *buf = NULL;
      size_t len = 0;

      retry = 0; /* We'll do one more pass if device is part of container */

      argv[0] = "mdadm";
      argv[1] = "--detail";
      argv[2] = "--export";
      argv[3] = dev;
      argv[4] = NULL;

      pid = grub_util_exec_pipe (argv, &fd);

      if (!pid)
	{
	  if (dev != os_dev)
	    free ((void *) dev);
	  return 0;
	}

      /* Parent.  Read mdadm's output.  */
      mdadm = fdopen (fd, "r");
      if (! mdadm)
	{
	  grub_util_warn (_("Unable to open stream from %s: %s"),
			  "mdadm", strerror (errno));
	  close (fd);
	  waitpid (pid, NULL, 0);
	  if (dev != os_dev)
	    free ((void *) dev);
	  return 0;
	}

      while (getline (&buf, &len, mdadm) > 0)
	{
	  if (strncmp (buf, "MD_CONTAINER=", sizeof ("MD_CONTAINER=") - 1) == 0
	      && !container_seen)
	    {
	      char *newdev, *ptr;
	      newdev = xstrdup (buf + sizeof ("MD_CONTAINER=") - 1);
	      ptr = newdev + strlen (newdev) - 1;
	      for (; ptr >= newdev && (*ptr == '\n' || *ptr == '\r'); ptr--);
	      ptr[1] = 0;
	      grub_util_info ("Container of %s is %s", dev, newdev);
	      dev = newdev;
	      container_seen = retry = 1;
	      break;
	    }
	  if (strncmp (buf, "MD_METADATA=imsm",
		       sizeof ("MD_METADATA=imsm") - 1) == 0)
	    {
	      is_imsm = 1;
	      grub_util_info ("%s is imsm", dev);	      
	      break;
	    }
	}

      free (buf);
      close (fd);
      waitpid (pid, NULL, 0);
    }
  while (retry);

  if (dev != os_dev)
    free ((void *) dev);
  return is_imsm;
}
Exemplo n.º 20
0
/* This function never prints trailing slashes (so that its output
   can be appended a slash unconditionally).  */
char *
make_system_path_relative_to_its_root (const char *path)
{
  struct stat st;
  char *p, *buf, *buf2, *buf3;
  uintptr_t offset = 0;
  dev_t num;
  size_t len;

  /* canonicalize.  */
  p = canonicalize_file_name (path);

  if (p == NULL)
    grub_util_error ("failed to get canonical path of %s", path);

  len = strlen (p) + 1;
  buf = xstrdup (p);
  free (p);

  if (stat (buf, &st) < 0)
    grub_util_error ("cannot stat %s: %s", buf, strerror (errno));

  buf2 = xstrdup (buf);
  num = st.st_dev;

  /* This loop sets offset to the number of chars of the root
     directory we're inspecting.  */
  while (1)
    {
      p = strrchr (buf, '/');
      if (p == NULL)
	/* This should never happen.  */
	grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)");
      if (p != buf)
	*p = 0;
      else
	*++p = 0;

      if (stat (buf, &st) < 0)
	grub_util_error ("cannot stat %s: %s", buf, strerror (errno));

      /* buf is another filesystem; we found it.  */
      if (st.st_dev != num)
	{
	  /* offset == 0 means path given is the mount point.
	     This works around special-casing of "/" in Un*x.  This function never
	     prints trailing slashes (so that its output can be appended a slash
	     unconditionally).  Each slash in is considered a preceding slash, and
	     therefore the root directory is an empty string.  */
	  if (offset == 0)
	    {
	      free (buf);
	      free (buf2);
	      return xstrdup ("");
	    }
	  else
	    break;
	}

      offset = p - buf;
      /* offset == 1 means root directory.  */
      if (offset == 1)
	{
	  /* Include leading slash.  */
	  offset = 0;
	  break;
	}
    }
  free (buf);
  buf3 = xstrdup (buf2 + offset);
  free (buf2);

#ifdef __CYGWIN__
  if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
    {
      /* Reached some mount point not below /cygdrive.
	 GRUB does not know Cygwin's emulated mounts,
	 convert to Win32 path.  */
      grub_util_info ("Cygwin path = %s\n", buf3);
      char * temp = get_win32_path (buf3);
      free (buf3);
      buf3 = temp;
    }
#endif

  /* Remove trailing slashes, return empty string if root directory.  */
  len = strlen (buf3);
  while (len > 0 && buf3[len - 1] == '/')
    {
      buf3[len - 1] = '\0';
      len--;
    }

  return buf3;
}
Exemplo n.º 21
0
static struct grub_diskfilter_vg * 
grub_lvm_detect (grub_disk_t disk,
		 struct grub_diskfilter_pv_id *id,
		 grub_disk_addr_t *start_sector)
{
  grub_err_t err;
  grub_uint64_t mda_offset, mda_size;
  char buf[GRUB_LVM_LABEL_SIZE];
  char vg_id[GRUB_LVM_ID_STRLEN+1];
  char pv_id[GRUB_LVM_ID_STRLEN+1];
  char *metadatabuf, *p, *q, *vgname;
  struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
  struct grub_lvm_pv_header *pvh;
  struct grub_lvm_disk_locn *dlocn;
  struct grub_lvm_mda_header *mdah;
  struct grub_lvm_raw_locn *rlocn;
  unsigned int i, j, vgname_len;
  struct grub_diskfilter_vg *vg;
  struct grub_diskfilter_pv *pv;

  /* Search for label. */
  for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
    {
      err = grub_disk_read (disk, i, 0, sizeof(buf), buf);
      if (err)
	goto fail;

      if ((! grub_strncmp ((char *)lh->id, GRUB_LVM_LABEL_ID,
			   sizeof (lh->id)))
	  && (! grub_strncmp ((char *)lh->type, GRUB_LVM_LVM2_LABEL,
			      sizeof (lh->type))))
	break;
    }

  /* Return if we didn't find a label. */
  if (i == GRUB_LVM_LABEL_SCAN_SECTORS)
    {
#ifdef GRUB_UTIL
      grub_util_info ("no LVM signature found");
#endif
      goto fail;
    }

  pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl));

  for (i = 0, j = 0; i < GRUB_LVM_ID_LEN; i++)
    {
      pv_id[j++] = pvh->pv_uuid[i];
      if ((i != 1) && (i != 29) && (i % 4 == 1))
	pv_id[j++] = '-';
    }
  pv_id[j] = '\0';

  dlocn = pvh->disk_areas_xl;

  dlocn++;
  /* Is it possible to have multiple data/metadata areas? I haven't
     seen devices that have it. */
  if (dlocn->offset)
    {
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		  "we don't support multiple LVM data areas");

#ifdef GRUB_UTIL
      grub_util_info ("we don't support multiple LVM data areas\n");
#endif
      goto fail;
    }

  dlocn++;
  mda_offset = grub_le_to_cpu64 (dlocn->offset);
  mda_size = grub_le_to_cpu64 (dlocn->size);

  /* It's possible to have multiple copies of metadata areas, we just use the
     first one.  */

  /* Allocate buffer space for the circular worst-case scenario. */
  metadatabuf = grub_malloc (2 * mda_size);
  if (! metadatabuf)
    goto fail;

  err = grub_disk_read (disk, 0, mda_offset, mda_size, metadatabuf);
  if (err)
    goto fail2;

  mdah = (struct grub_lvm_mda_header *) metadatabuf;
  if ((grub_strncmp ((char *)mdah->magic, GRUB_LVM_FMTT_MAGIC,
		     sizeof (mdah->magic)))
      || (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION))
    {
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		  "unknown LVM metadata header");
#ifdef GRUB_UTIL
      grub_util_info ("unknown LVM metadata header\n");
#endif
      goto fail2;
    }

  rlocn = mdah->raw_locns;
  if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) >
      grub_le_to_cpu64 (mdah->size))
    {
      /* Metadata is circular. Copy the wrap in place. */
      grub_memcpy (metadatabuf + mda_size,
		   metadatabuf + GRUB_LVM_MDA_HEADER_SIZE,
		   grub_le_to_cpu64 (rlocn->offset) +
		   grub_le_to_cpu64 (rlocn->size) -
		   grub_le_to_cpu64 (mdah->size));
    }
  p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);

  while (*q != ' ' && q < metadatabuf + mda_size)
    q++;

  if (q == metadatabuf + mda_size)
    {
#ifdef GRUB_UTIL
      grub_util_info ("error parsing metadata\n");
#endif
      goto fail2;
    }

  vgname_len = q - p;
  vgname = grub_malloc (vgname_len + 1);
  if (!vgname)
    goto fail2;

  grub_memcpy (vgname, p, vgname_len);
  vgname[vgname_len] = '\0';

  p = grub_strstr (q, "id = \"");
  if (p == NULL)
    {
#ifdef GRUB_UTIL
      grub_util_info ("couldn't find ID\n");
#endif
      goto fail3;
    }
  p += sizeof ("id = \"") - 1;
  grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN);
  vg_id[GRUB_LVM_ID_STRLEN] = '\0';

  vg = grub_diskfilter_get_vg_by_uuid (GRUB_LVM_ID_STRLEN, vg_id);

  if (! vg)
    {
      /* First time we see this volume group. We've to create the
	 whole volume group structure. */
      vg = grub_malloc (sizeof (*vg));
      if (! vg)
	goto fail3;
      vg->name = vgname;
      vg->uuid = grub_malloc (GRUB_LVM_ID_STRLEN);
      if (! vg->uuid)
	goto fail3;
      grub_memcpy (vg->uuid, vg_id, GRUB_LVM_ID_STRLEN);
      vg->uuid_len = GRUB_LVM_ID_STRLEN;

      vg->extent_size = grub_lvm_getvalue (&p, "extent_size = ");
      if (p == NULL)
	{
#ifdef GRUB_UTIL
	  grub_util_info ("unknown extent size\n");
#endif
	  goto fail4;
	}

      vg->lvs = NULL;
      vg->pvs = NULL;

      p = grub_strstr (p, "physical_volumes {");
      if (p)
	{
	  p += sizeof ("physical_volumes {") - 1;

	  /* Add all the pvs to the volume group. */
	  while (1)
	    {
	      int s;
	      while (grub_isspace (*p))
		p++;

	      if (*p == '}')
		break;

	      pv = grub_zalloc (sizeof (*pv));
	      q = p;
	      while (*q != ' ')
		q++;

	      s = q - p;
	      pv->name = grub_malloc (s + 1);
	      grub_memcpy (pv->name, p, s);
	      pv->name[s] = '\0';

	      p = grub_strstr (p, "id = \"");
	      if (p == NULL)
		goto pvs_fail;
	      p += sizeof("id = \"") - 1;

	      pv->id.uuid = grub_malloc (GRUB_LVM_ID_STRLEN);
	      if (!pv->id.uuid)
		goto pvs_fail;
	      grub_memcpy (pv->id.uuid, p, GRUB_LVM_ID_STRLEN);
	      pv->id.uuidlen = GRUB_LVM_ID_STRLEN;

	      pv->start_sector = grub_lvm_getvalue (&p, "pe_start = ");
	      if (p == NULL)
		{
#ifdef GRUB_UTIL
		  grub_util_info ("unknown pe_start\n");
#endif
		  goto pvs_fail;
		}

	      p = grub_strchr (p, '}');
	      if (p == NULL)
		{
#ifdef GRUB_UTIL
		  grub_util_info ("error parsing pe_start\n");
#endif
		  goto pvs_fail;
		}
	      p++;

	      pv->disk = NULL;
	      pv->next = vg->pvs;
	      vg->pvs = pv;

	      continue;
	    pvs_fail:
	      grub_free (pv->name);
	      grub_free (pv);
	      goto fail4;
	    }
	}

      p = grub_strstr (p, "logical_volumes");
      if (p)
	{
	  p += sizeof ("logical_volumes = ") - 1;

	  /* And add all the lvs to the volume group. */
	  while (1)
	    {
	      int s;
	      int skip_lv = 0;
	      struct grub_diskfilter_lv *lv;
	      struct grub_diskfilter_segment *seg;
	      int is_pvmove;

	      while (grub_isspace (*p))
		p++;

	      if (*p == '}')
		break;

	      lv = grub_zalloc (sizeof (*lv));

	      q = p;
	      while (*q != ' ')
		q++;

	      s = q - p;
	      lv->name = grub_strndup (p, s);
	      if (!lv->name)
		goto lvs_fail;

	      {
		const char *iptr;
		char *optr;
		lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len
					    + 1 + 2 * s + 1);
		if (!lv->fullname)
		  goto lvs_fail;

		grub_memcpy (lv->fullname, "lvm/", sizeof ("lvm/") - 1);
		optr = lv->fullname + sizeof ("lvm/") - 1;
		for (iptr = vgname; iptr < vgname + vgname_len; iptr++)
		  {
		    *optr++ = *iptr;
		    if (*iptr == '-')
		      *optr++ = '-';
		  }
		*optr++ = '-';
		for (iptr = p; iptr < p + s; iptr++)
		  {
		    *optr++ = *iptr;
		    if (*iptr == '-')
		      *optr++ = '-';
		  }
		*optr++ = 0;
		lv->idname = grub_malloc (sizeof ("lvmid/")
					  + 2 * GRUB_LVM_ID_STRLEN + 1);
		if (!lv->idname)
		  goto lvs_fail;
		grub_memcpy (lv->idname, "lvmid/",
			     sizeof ("lvmid/") - 1);
		grub_memcpy (lv->idname + sizeof ("lvmid/") - 1,
			     vg_id, GRUB_LVM_ID_STRLEN);
		lv->idname[sizeof ("lvmid/") - 1 + GRUB_LVM_ID_STRLEN] = '/';

		p = grub_strstr (q, "id = \"");
		if (p == NULL)
		  {
#ifdef GRUB_UTIL
		    grub_util_info ("couldn't find ID\n");
#endif
		    goto lvs_fail;
		  }
		p += sizeof ("id = \"") - 1;
		grub_memcpy (lv->idname + sizeof ("lvmid/") - 1
			     + GRUB_LVM_ID_STRLEN + 1,
			     p, GRUB_LVM_ID_STRLEN);
		lv->idname[sizeof ("lvmid/") - 1 + 2 * GRUB_LVM_ID_STRLEN + 1] = '\0';
	      }

	      lv->size = 0;

	      lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE");
	      is_pvmove = grub_lvm_check_flag (p, "status", "PVMOVE");

	      lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
	      if (p == NULL)
		{
#ifdef GRUB_UTIL
		  grub_util_info ("unknown segment_count\n");
#endif
		  goto lvs_fail;
		}
	      lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count);
	      seg = lv->segments;

	      for (i = 0; i < lv->segment_count; i++)
		{

		  p = grub_strstr (p, "segment");
		  if (p == NULL)
		    {
#ifdef GRUB_UTIL
		      grub_util_info ("unknown segment\n");
#endif
		      goto lvs_segment_fail;
		    }

		  seg->start_extent = grub_lvm_getvalue (&p, "start_extent = ");
		  if (p == NULL)
		    {
#ifdef GRUB_UTIL
		      grub_util_info ("unknown start_extent\n");
#endif
		      goto lvs_segment_fail;
		    }
		  seg->extent_count = grub_lvm_getvalue (&p, "extent_count = ");
		  if (p == NULL)
		    {
#ifdef GRUB_UTIL
		      grub_util_info ("unknown extent_count\n");
#endif
		      goto lvs_segment_fail;
		    }

		  p = grub_strstr (p, "type = \"");
		  if (p == NULL)
		    goto lvs_segment_fail;
		  p += sizeof("type = \"") - 1;

		  lv->size += seg->extent_count * vg->extent_size;

		  if (grub_memcmp (p, "striped\"",
				   sizeof ("striped\"") - 1) == 0)
		    {
		      struct grub_diskfilter_node *stripe;

		      seg->type = GRUB_DISKFILTER_STRIPED;
		      seg->node_count = grub_lvm_getvalue (&p, "stripe_count = ");
		      if (p == NULL)
			{
#ifdef GRUB_UTIL
			  grub_util_info ("unknown stripe_count\n");
#endif
			  goto lvs_segment_fail;
			}

		      if (seg->node_count != 1)
			seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");

		      seg->nodes = grub_zalloc (sizeof (*stripe)
						* seg->node_count);
		      stripe = seg->nodes;

		      p = grub_strstr (p, "stripes = [");
		      if (p == NULL)
			{
#ifdef GRUB_UTIL
			  grub_util_info ("unknown stripes\n");
#endif
			  goto lvs_segment_fail2;
			}
		      p += sizeof("stripes = [") - 1;

		      for (j = 0; j < seg->node_count; j++)
			{
			  p = grub_strchr (p, '"');
			  if (p == NULL)
			    continue;
			  q = ++p;
			  while (*q != '"')
			    q++;

			  s = q - p;

			  stripe->name = grub_malloc (s + 1);
			  if (stripe->name == NULL)
			    goto lvs_segment_fail2;

			  grub_memcpy (stripe->name, p, s);
			  stripe->name[s] = '\0';

			  p = q + 1;

			  stripe->start = grub_lvm_getvalue (&p, ",")
			    * vg->extent_size;
			  if (p == NULL)
			    continue;

			  stripe++;
			}
		    }
		  else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
			   == 0)
		    {
		      seg->type = GRUB_DISKFILTER_MIRROR;
		      seg->node_count = grub_lvm_getvalue (&p, "mirror_count = ");
		      if (p == NULL)
			{
#ifdef GRUB_UTIL
			  grub_util_info ("unknown mirror_count\n");
#endif
			  goto lvs_segment_fail;
			}

		      seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
						* seg->node_count);

		      p = grub_strstr (p, "mirrors = [");
		      if (p == NULL)
			{
#ifdef GRUB_UTIL
			  grub_util_info ("unknown mirrors\n");
#endif
			  goto lvs_segment_fail2;
			}
		      p += sizeof("mirrors = [") - 1;

		      for (j = 0; j < seg->node_count; j++)
			{
			  char *lvname;

			  p = grub_strchr (p, '"');
			  if (p == NULL)
			    continue;
			  q = ++p;
			  while (*q != '"')
			    q++;

			  s = q - p;

			  lvname = grub_malloc (s + 1);
			  if (lvname == NULL)
			    goto lvs_segment_fail2;

			  grub_memcpy (lvname, p, s);
			  lvname[s] = '\0';
			  seg->nodes[j].name = lvname;
			  p = q + 1;
			}
		      /* Only first (original) is ok with in progress pvmove.  */
		      if (is_pvmove)
			seg->node_count = 1;
		    }
		  else if (grub_memcmp (p, "raid", sizeof ("raid") - 1)
			   == 0 && (p[sizeof ("raid") - 1] >= '4'
				    && p[sizeof ("raid") - 1] <= '6')
			   && p[sizeof ("raidX") - 1] == '"')
		    {
		      switch (p[sizeof ("raid") - 1])
			{
			case '4':
			  seg->type = GRUB_DISKFILTER_RAID4;
			  seg->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
			  break;
			case '5':
			  seg->type = GRUB_DISKFILTER_RAID5;
			  seg->layout = GRUB_RAID_LAYOUT_LEFT_SYMMETRIC;
			  break;
			case '6':
			  seg->type = GRUB_DISKFILTER_RAID6;
			  seg->layout = (GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC
					 | GRUB_RAID_LAYOUT_MUL_FROM_POS);
			  break;
			}
		      seg->node_count = grub_lvm_getvalue (&p, "device_count = ");

		      if (p == NULL)
			{
#ifdef GRUB_UTIL
			  grub_util_info ("unknown device_count\n");
#endif
			  goto lvs_segment_fail;
			}

		      seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
		      if (p == NULL)
			{
#ifdef GRUB_UTIL
			  grub_util_info ("unknown stripe_size\n");
#endif
			  goto lvs_segment_fail;
			}


		      seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
						* seg->node_count);

		      p = grub_strstr (p, "raids = [");
		      if (p == NULL)
			{
#ifdef GRUB_UTIL
			  grub_util_info ("unknown mirrors\n");
#endif
			  goto lvs_segment_fail2;
			}
		      p += sizeof("raids = [") - 1;

		      for (j = 0; j < seg->node_count; j++)
			{
			  char *lvname;

			  p = grub_strchr (p, '"');
			  p = p ? grub_strchr (p + 1, '"') : 0;
			  p = p ? grub_strchr (p + 1, '"') : 0;
			  if (p == NULL)
			    continue;
			  q = ++p;
			  while (*q != '"')
			    q++;

			  s = q - p;

			  lvname = grub_malloc (s + 1);
			  if (lvname == NULL)
			    goto lvs_segment_fail2;

			  grub_memcpy (lvname, p, s);
			  lvname[s] = '\0';
			  seg->nodes[j].name = lvname;
			  p = q + 1;
			}
		      if (seg->type == GRUB_DISKFILTER_RAID4)
			{
			  char *tmp;
			  tmp = seg->nodes[0].name;
			  grub_memmove (seg->nodes, seg->nodes + 1,
					sizeof (seg->nodes[0])
					* (seg->node_count - 1));
			  seg->nodes[seg->node_count - 1].name = tmp;
			}
		    }
		  else
		    {
#ifdef GRUB_UTIL
		      char *p2;
		      p2 = grub_strchr (p, '"');
		      if (p2)
			*p2 = 0;
		      grub_util_info ("unknown LVM type %s\n", p);
		      if (p2)
			*p2 ='"';
#endif
		      /* Found a non-supported type, give up and move on. */
		      skip_lv = 1;
		      break;
		    }

		  seg++;

		  continue;
		lvs_segment_fail2:
		  grub_free (seg->nodes);
		lvs_segment_fail:
		  goto fail4;
		}

	      if (p != NULL)
		p = grub_strchr (p, '}');
	      if (p == NULL)
		goto lvs_fail;
	      p += 3;

	      if (skip_lv)
		{
		  grub_free (lv->name);
		  grub_free (lv);
		  continue;
		}

	      lv->vg = vg;
	      lv->next = vg->lvs;
	      vg->lvs = lv;

	      continue;
	    lvs_fail:
	      grub_free (lv->name);
	      grub_free (lv);
	      goto fail4;
	    }
	}

      /* Match lvs.  */
      {
	struct grub_diskfilter_lv *lv1;
	struct grub_diskfilter_lv *lv2;
	for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
	  for (i = 0; i < lv1->segment_count; i++)
	    for (j = 0; j < lv1->segments[i].node_count; j++)
	      {
		if (vg->pvs)
		  for (pv = vg->pvs; pv; pv = pv->next)
		    {
		      if (! grub_strcmp (pv->name,
					 lv1->segments[i].nodes[j].name))
			{
			  lv1->segments[i].nodes[j].pv = pv;
			  break;
			}
		    }
		if (lv1->segments[i].nodes[j].pv == NULL)
		  for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
		    if (grub_strcmp (lv2->name,
				     lv1->segments[i].nodes[j].name) == 0)
		      lv1->segments[i].nodes[j].lv = lv2;
	      }
	
      }
      if (grub_diskfilter_vg_register (vg))
	goto fail4;
    }
  else
    {
      grub_free (vgname);
    }

  id->uuid = grub_malloc (GRUB_LVM_ID_STRLEN);
  if (!id->uuid)
    goto fail4;
  grub_memcpy (id->uuid, pv_id, GRUB_LVM_ID_STRLEN);
  id->uuidlen = GRUB_LVM_ID_STRLEN;
  grub_free (metadatabuf);
  *start_sector = -1;
  return vg;

  /* Failure path.  */
 fail4:
  grub_free (vg);
 fail3:
  grub_free (vgname);

 fail2:
  grub_free (metadatabuf);
 fail:
  return NULL;
}
Exemplo n.º 22
0
int
main (int argc, char *argv[])
{
  char *root_dev = 0;
  char *dir = DEFAULT_DIRECTORY;
  char *dev_map = DEFAULT_DEVICE_MAP;
  volatile int hold = 0;
  int opt;

  set_program_name (argv[0]);

  grub_util_init_nls ();

  while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1)
    switch (opt)
      {
      case 'r':
        root_dev = optarg;
        break;
      case 'd':
        dir = optarg;
        break;
      case 'm':
        dev_map = optarg;
        break;
      case 'v':
        verbosity++;
        break;
      case 'H':
        hold = (optarg ? atoi (optarg) : -1);
        break;
      case 'h':
        return usage (0);
      case 'V':
        printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
        return 0;
      default:
        return usage (1);
      }

  if (optind < argc)
    {
      fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind]);
      return usage (1);
    }

  /* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */
  if (hold && verbosity > 0)
    printf ("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n",
            program_name, (int) getpid ());
  while (hold)
    {
      if (hold > 0)
        hold--;

      sleep (1);
    }

  signal (SIGINT, SIG_IGN);
  grub_console_init ();

  /* XXX: This is a bit unportable.  */
  grub_util_biosdisk_init (dev_map);

  grub_init_all ();

  /* Make sure that there is a root device.  */
  if (! root_dev)
    {
      char *device_name = grub_guess_root_device (dir);
      if (! device_name)
        grub_util_error ("cannot find a device for %s", dir);

      root_dev = grub_util_get_grub_dev (device_name);
      if (! root_dev)
	{
	  grub_util_info ("guessing the root device failed, because of `%s'",
			  grub_errmsg);
	  grub_util_error ("cannot guess the root device. Specify the option `--root-device'");
	}
    }

  dir = grub_get_prefix (dir);
  prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1);
  sprintf (prefix, "(%s)%s", root_dev, dir);
  free (dir);

  /* Start GRUB!  */
  if (setjmp (main_env) == 0)
    grub_main ();

  grub_fini_all ();

  grub_machine_fini ();

  return 0;
}
Exemplo n.º 23
0
/* Relocate symbols; note that this function overwrites the symbol table.
   Return the address of a start symbol.  */
static Elf_Addr
SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
                           Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
                           Elf_Half section_entsize, Elf_Half num_sections,
                           void *jumpers, Elf_Addr jumpers_addr,
                           struct image_target_desc *image_target)
{
    Elf_Word symtab_size, sym_size, num_syms;
    Elf_Off symtab_offset;
    Elf_Addr start_address = 0;
    Elf_Sym *sym;
    Elf_Word i;
    Elf_Shdr *strtab_section;
    const char *strtab;
    grub_uint64_t *jptr = jumpers;

    strtab_section
        = (Elf_Shdr *) ((char *) sections
                        + (grub_target_to_host32 (symtab_section->sh_link)
                           * section_entsize));
    strtab = (char *) e + grub_target_to_host (strtab_section->sh_offset);

    symtab_size = grub_target_to_host (symtab_section->sh_size);
    sym_size = grub_target_to_host (symtab_section->sh_entsize);
    symtab_offset = grub_target_to_host (symtab_section->sh_offset);
    num_syms = symtab_size / sym_size;

    for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
            i < num_syms;
            i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
    {
        Elf_Section cur_index;
        const char *name;

        name = strtab + grub_target_to_host32 (sym->st_name);

        cur_index = grub_target_to_host16 (sym->st_shndx);
        if (cur_index == STN_ABS)
        {
            continue;
        }
        else if ((cur_index == STN_UNDEF))
        {
            if (sym->st_name)
                grub_util_error ("undefined symbol %s", name);
            else
                continue;
        }
        else if (cur_index >= num_sections)
            grub_util_error ("section %d does not exist", cur_index);

        sym->st_value = (grub_target_to_host (sym->st_value)
                         + section_addresses[cur_index]);

        if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
                == STT_FUNC)
        {
            *jptr = sym->st_value;
            sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
            jptr++;
            *jptr = 0;
            jptr++;
        }
        grub_util_info ("locating %s at 0x%llx (0x%llx)", name,
                        (unsigned long long) sym->st_value,
                        (unsigned long long) section_addresses[cur_index]);

        if (! start_address)
            if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
                start_address = sym->st_value;
    }

    return start_address;
}
Exemplo n.º 24
0
void
grub_install_get_blocklist (grub_device_t root_dev,
			    const char *core_path, const char *core_img,
			    size_t core_size,
			    void (*callback) (grub_disk_addr_t sector,
					      unsigned offset,
					      unsigned length,
					      void *data),
			    void *hook_data)
{
  int i;
  char *tmp_img;
  char *core_path_dev;

  core_path_dev = grub_make_system_path_relative_to_its_root (core_path);

  /* Make sure that GRUB reads the identical image as the OS.  */
  tmp_img = xmalloc (core_size);

  for (i = 0; i < MAX_TRIES; i++)
    {
      grub_file_t file;

      grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB")
		      : _("attempting to read the core image `%s' from GRUB again"),
		      core_path_dev);

      grub_disk_cache_invalidate_all ();

      grub_file_filter_disable_compression ();
      file = grub_file_open (core_path_dev);
      if (file)
	{
	  if (grub_file_size (file) != core_size)
	    grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)",
			    (int) grub_file_size (file), (int) core_size);
	  else if (grub_file_read (file, tmp_img, core_size)
		   != (grub_ssize_t) core_size)
	    grub_util_info ("succeeded in opening the core image but cannot read %d bytes",
			    (int) core_size);
	  else if (memcmp (core_img, tmp_img, core_size) != 0)
	    {
#if 0
	      FILE *dump;
	      FILE *dump2;

	      dump = fopen ("dump.img", "wb");
	      if (dump)
		{
		  fwrite (tmp_img, 1, core_size, dump);
		  fclose (dump);
		}

	      dump2 = fopen ("dump2.img", "wb");
	      if (dump2)
		{
		  fwrite (core_img, 1, core_size, dump2);
		  fclose (dump2);
		}

#endif
	      grub_util_info ("succeeded in opening the core image but the data is different");
	    }
	  else
	    {
	      grub_file_close (file);
	      break;
	    }

	  grub_file_close (file);
	}
      else
	grub_util_info ("couldn't open the core image");

      if (grub_errno)
	grub_util_info ("error message = %s", grub_errmsg);

      grub_errno = GRUB_ERR_NONE;
      grub_util_biosdisk_flush (root_dev->disk);
      sleep (1);
    }

  if (i == MAX_TRIES)
    grub_util_error (_("cannot read `%s' correctly"), core_path_dev);

  grub_file_t file;
  /* Now read the core image to determine where the sectors are.  */
  grub_file_filter_disable_compression ();
  file = grub_file_open (core_path_dev);
  if (! file)
    grub_util_error ("%s", grub_errmsg);

  file->read_hook = callback;
  file->read_hook_data = hook_data;
  if (grub_file_read (file, tmp_img, core_size) != (grub_ssize_t) core_size)
    grub_util_error ("%s", _("failed to read the sectors of the core image"));

  grub_file_close (file);
  free (tmp_img);

  free (core_path_dev);
}
Exemplo n.º 25
0
static void
read_device_map (const char *dev_map)
{
  FILE *fp;
  char buf[1024];	/* XXX */
  int lineno = 0;

  if (dev_map[0] == '\0')
    {
      grub_util_info ("no device.map");
      return;
    }

  fp = grub_util_fopen (dev_map, "r");
  if (! fp)
    {
      grub_util_info (_("cannot open `%s': %s"), dev_map, strerror (errno));
      return;
    }

  while (fgets (buf, sizeof (buf), fp))
    {
      char *p = buf;
      char *e;
      char *drive_e, *drive_p;
      int drive;

      lineno++;

      /* Skip leading spaces.  */
      while (*p && grub_isspace (*p))
	p++;

      /* If the first character is `#' or NUL, skip this line.  */
      if (*p == '\0' || *p == '#')
	continue;

      if (*p != '(')
	{
	  char *tmp;
	  tmp = xasprintf (_("missing `%c' symbol"), '(');
	  grub_util_error ("%s:%d: %s", dev_map, lineno, tmp);
	}

      p++;
      /* Find a free slot.  */
      drive = find_free_slot ();
      if (drive < 0)
	grub_util_error ("%s:%d: %s", dev_map, lineno, _("device count exceeds limit"));

      e = p;
      p = strchr (p, ')');
      if (! p)
	{
	  char *tmp;
	  tmp = xasprintf (_("missing `%c' symbol"), ')');
	  grub_util_error ("%s:%d: %s", dev_map, lineno, tmp);
	}

      map[drive].drive = 0;
      if ((e[0] == 'f' || e[0] == 'h' || e[0] == 'c') && e[1] == 'd')
	{
	  char *ptr;
	  for (ptr = e + 2; ptr < p; ptr++)
	    if (!grub_isdigit (*ptr))
	      break;
	  if (ptr == p)
	    {
	      map[drive].drive = xmalloc (p - e + sizeof ('\0'));
	      strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
	      map[drive].drive[p - e] = '\0';
	    }
	  if (*ptr == ',')
	    {
	      *p = 0;

	      /* TRANSLATORS: Only one entry is ignored. However the suggestion
		 is to correct/delete the whole file.
		 device.map is a file indicating which
		 devices are available at boot time. Fedora populated it with
		 entries like (hd0,1) /dev/sda1 which would mean that every
		 partition is a separate disk for BIOS. Such entries were
		 inactive in GRUB due to its bug which is now gone. Without
		 this additional check these entries would be harmful now.
	      */
	      grub_util_warn (_("the device.map entry `%s' is invalid. "
				"Ignoring it. Please correct or "
				"delete your device.map"), e);
	      continue;
	    }
	}
      drive_e = e;
      drive_p = p;
      map[drive].device_map = 1;

      p++;
      /* Skip leading spaces.  */
      while (*p && grub_isspace (*p))
	p++;

      if (*p == '\0')
	grub_util_error ("%s:%d: %s", dev_map, lineno, _("filename expected"));

      /* NUL-terminate the filename.  */
      e = p;
      while (*e && ! grub_isspace (*e))
	e++;
      *e = '\0';

      if (!grub_util_check_file_presence (p))
	{
	  free (map[drive].drive);
	  map[drive].drive = NULL;
	  grub_util_info ("Cannot stat `%s', skipping", p);
	  continue;
	}

      /* On Linux, the devfs uses symbolic links horribly, and that
	 confuses the interface very much, so use realpath to expand
	 symbolic links.  */
      map[drive].device = canonicalize_file_name (p);
      if (! map[drive].device)
	map[drive].device = xstrdup (p);
      
      if (!map[drive].drive)
	{
	  char c;
	  map[drive].drive = xmalloc (sizeof ("hostdisk/") + strlen (p));
	  memcpy (map[drive].drive, "hostdisk/", sizeof ("hostdisk/") - 1);
	  strcpy (map[drive].drive + sizeof ("hostdisk/") - 1, p);
	  c = *drive_p;
	  *drive_p = 0;
	  /* TRANSLATORS: device.map is a filename. Not to be translated.
	     device.map specifies disk correspondance overrides. Previously
	     one could create any kind of device name with this. Due to
	     some problems we decided to limit it to just a handful
	     possibilities.  */
	  grub_util_warn (_("the drive name `%s' in device.map is incorrect. "
			    "Using %s instead. "
			    "Please use the form [hfc]d[0-9]* "
			    "(E.g. `hd0' or `cd')"),
			  drive_e, map[drive].drive);
	  *drive_p = c;
	}

      grub_util_info ("adding `%s' -> `%s' from device.map", map[drive].drive,
		      map[drive].device);

      grub_hostdisk_flush_initial_buffer (map[drive].device);
    }

  fclose (fp);
}