示例#1
0
static struct grub_archelp_data *
grub_cbfs_mount (grub_disk_t disk)
{
  struct cbfs_file hd;
  struct grub_archelp_data *data = NULL;
  grub_uint32_t ptr;
  grub_off_t header_off;
  struct cbfs_header head;

  if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN)
    goto fail;

  if (grub_disk_read (disk, grub_disk_get_size (disk) - 1,
		      GRUB_DISK_SECTOR_SIZE - sizeof (ptr),
		      sizeof (ptr), &ptr))
    goto fail;

  ptr = grub_cpu_to_le32 (ptr);
  header_off = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
    + (grub_int32_t) ptr;

  if (grub_disk_read (disk, 0, header_off,
		      sizeof (head), &head))
    goto fail;

  if (!validate_head (&head))
    goto fail;

  data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data));
  if (!data)
    goto fail;

  data->cbfs_start = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
    - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset));
  data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
    - grub_be_to_cpu32 (head.bootblocksize);
  data->cbfs_align = grub_be_to_cpu32 (head.align);

  if (data->cbfs_start >= (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
    goto fail;
  if (data->cbfs_end > (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
    data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS);

  data->next_hofs = data->cbfs_start;

  if (grub_disk_read (disk, 0, data->cbfs_start, sizeof (hd), &hd))
    goto fail;

  if (grub_memcmp (hd.magic, CBFS_FILE_MAGIC, sizeof (CBFS_FILE_MAGIC) - 1))
    goto fail;

  data->disk = disk;

  return data;

fail:
  grub_free (data);
  grub_error (GRUB_ERR_BAD_FS, "not a cbfs filesystem");
  return 0;
}
示例#2
0
static grub_err_t
grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array)
{
  grub_disk_addr_t sector;
  struct grub_nv_super sb;

  if (disk->partition)
    return grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");

  sector = grub_disk_get_size (disk) - 2;

  if (grub_disk_read (disk, sector, 0, sizeof (sb), &sb))
    return grub_errno;

  if (grub_memcmp (sb.vendor, NV_ID_STRING, 6))
    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");

  if (sb.version != NV_VERSION)
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
                       "unknown version: %d.%d", sb.version);

  switch (sb.array.raid_level)
    {
    case NV_LEVEL_0:
      array->level = 0;
      array->disk_size = sb.capacity / sb.array.total_volumes;
      break;

    case NV_LEVEL_1:
      array->level = 1;
      array->disk_size = sb.capacity;
      break;

    case NV_LEVEL_5:
      array->level = 5;
      array->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
      array->disk_size = sb.capacity / (sb.array.total_volumes - 1);
      break;

    default:
      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
                         "unsupported RAID level: %d", sb.array.raid_level);
    }

  array->number = 0;
  array->total_devs = sb.array.total_volumes;
  array->chunk_size = sb.array.stripe_block_size;
  array->disk_offset = 0;
  array->index = sb.unit_number;
  array->uuid_len = sizeof (sb.array.signature);
  array->uuid = grub_malloc (sizeof (sb.array.signature));
  if (! array->uuid)
    return grub_errno;

  grub_memcpy (array->uuid, (char *) &sb.array.signature,
               sizeof (sb.array.signature));

  return 0;
}
示例#3
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;
}
示例#4
0
文件: ldm.c 项目: flihp/grub2
int
grub_util_is_ldm (grub_disk_t disk)
{
  int i;
  int has_ldm = msdos_has_ldm_partition (disk);
  for (i = 0; i < 3; i++)
    {
      grub_disk_addr_t sector = LDM_LABEL_SECTOR;
      grub_err_t err;
      struct grub_ldm_label label;

      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)
	{
	  grub_errno = GRUB_ERR_NONE;
	  return 0;
	}
      /* This check is more relaxed on purpose.  */
      if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0)
	return 1;
    }

  return 0;
}
示例#5
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);
}
示例#6
0
static struct grub_diskfilter_vg *
grub_mdraid_detect (grub_disk_t disk,
		    struct grub_diskfilter_pv_id *id,
		    grub_disk_addr_t *start_sector)
{
  grub_uint64_t size;
  grub_uint8_t minor_version;

  size = grub_disk_get_size (disk);

  /* Check for an 1.x superblock.
   * It's always aligned to a 4K boundary
   * and depending on the minor version it can be:
   * 0: At least 8K, but less than 12K, from end of device
   * 1: At start of device
   * 2: 4K from start of device.
   */

  for (minor_version = 0; minor_version < 3; ++minor_version)
    {
      grub_disk_addr_t sector = 0;
      struct grub_raid_super_1x sb;
      grub_uint16_t role;
      grub_uint32_t level;
      struct grub_diskfilter_vg *array;
      char *uuid;
	
      if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0)
	continue;
	
      switch (minor_version)
	{
	case 0:
	  sector = (size - 8 * 2) & ~(4 * 2 - 1);
	  break;
	case 1:
	  sector = 0;
	  break;
	case 2:
	  sector = 4 * 2;
	  break;
	}

      if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
			  &sb))
	return NULL;

      if (sb.magic != grub_cpu_to_le32_compile_time (SB_MAGIC)
	  || grub_le_to_cpu64 (sb.super_offset) != sector)
	continue;

      if (sb.major_version != grub_cpu_to_le32_compile_time (1))
	/* Unsupported version.  */
	return NULL;

      level = grub_le_to_cpu32 (sb.level);

      /* Multipath.  */
      if ((int) level == -4)
	level = 1;

      if (level != 0 && level != 1 && level != 4 &&
	  level != 5 && level != 6 && level != 10)
	{
	  grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		      "Unsupported RAID level: %d", sb.level);
	  return NULL;
	}

      if (grub_le_to_cpu32 (sb.dev_number) >=
	  grub_le_to_cpu32 (sb.max_dev))
	/* Spares aren't implemented.  */
	return NULL;

      if (grub_disk_read (disk, sector, 
			  (char *) &sb.dev_roles[grub_le_to_cpu32 (sb.dev_number)]
			  - (char *) &sb,
			  sizeof (role), &role))
	return NULL;

      if (grub_le_to_cpu16 (role)
	  >= grub_le_to_cpu32 (sb.raid_disks))
	/* Spares aren't implemented.  */
	return NULL;

      id->uuidlen = 0;
      id->id = grub_le_to_cpu16 (role);

      uuid = grub_malloc (16);
      if (!uuid)
	return NULL;

      grub_memcpy (uuid, sb.set_uuid, 16);

      *start_sector = grub_le_to_cpu64 (sb.data_offset);

      array = grub_diskfilter_make_raid (16, uuid,
					 grub_le_to_cpu32 (sb.raid_disks),
					 sb.set_name,
					 (sb.size)
					 ? grub_le_to_cpu64 (sb.size) 
					 : grub_le_to_cpu64 (sb.data_size),
					 grub_le_to_cpu32 (sb.chunksize),
					 grub_le_to_cpu32 (sb.layout),
					 grub_le_to_cpu32 (sb.level));

      return array;
    }

  /* not 1.x raid.  */
  return NULL;
}
示例#7
0
文件: ldm.c 项目: 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;
}
示例#8
0
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
		    grub_disk_addr_t *start_sector)
{
  grub_disk_addr_t sector = 0;
  grub_uint64_t size;
  struct grub_raid_super_1x sb;
  grub_uint8_t minor_version;

  /* The sector where the mdraid 0.90 superblock is stored, if available.  */
  size = grub_disk_get_size (disk);

  /* Check for an 1.x superblock.
   * It's always aligned to a 4K boundary
   * and depending on the minor version it can be:
   * 0: At least 8K, but less than 12K, from end of device
   * 1: At start of device
   * 2: 4K from start of device.
   */

  for (minor_version = 0; minor_version < 3; ++minor_version)
    {
      if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0)
	continue;
	
      switch (minor_version)
	{
	case 0:
	  sector = (size - 8 * 2) & ~(4 * 2 - 1);
	  break;
	case 1:
	  sector = 0;
	  break;
	case 2:
	  sector = 4 * 2;
	  break;
	}

      if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
			  &sb))
	return grub_errno;

      if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
	  || grub_le_to_cpu64 (sb.super_offset) != sector)
	continue;

      {
	grub_uint64_t sb_size;
	struct grub_raid_super_1x *real_sb;
	grub_uint32_t level;

	if (grub_le_to_cpu32 (sb.major_version) != 1)
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
			     "Unsupported RAID version: %d",
			     grub_le_to_cpu32 (sb.major_version));

	level = grub_le_to_cpu32 (sb.level);

	/* Multipath.  */
	if ((int) level == -4)
	  level = 1;

	if (level != 0 && level != 1 && level != 4 &&
	    level != 5 && level != 6 && level != 10)
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
			     "Unsupported RAID level: %d", sb.level);

	/* 1.x superblocks don't have a fixed size on disk.  So we have to
	   read it again now that we now the max device count.  */
	sb_size = sizeof (struct grub_raid_super_1x) 
	  + 2 * grub_le_to_cpu32 (sb.max_dev);
	real_sb = grub_malloc (sb_size);
	if (! real_sb)
	  return grub_errno;

	if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
	  {
	    grub_free (real_sb);
	    return grub_errno;
	  }

	array->name = grub_strdup (real_sb->set_name);
	if (! array->name)
	  {
	    grub_free (real_sb);
	    return grub_errno;
	  }

	array->number = 0;
	array->level = grub_le_to_cpu32 (real_sb->level);
	array->layout = grub_le_to_cpu32 (real_sb->layout);
	array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
	array->disk_size = grub_le_to_cpu64 (real_sb->size);
	array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);

	if (grub_le_to_cpu32 (real_sb->dev_number) >=
	    grub_le_to_cpu32 (real_sb->max_dev))
	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
			     "spares aren't implemented");

	array->index = grub_le_to_cpu16
	  (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
	array->uuid_len = 16;
	array->uuid = grub_malloc (16);
	if (!array->uuid)
	  {
	    grub_free (real_sb);
	    return grub_errno;
	  }

	grub_memcpy (array->uuid, real_sb->set_uuid, 16);
	
	*start_sector = grub_le_to_cpu64 (real_sb->data_offset);

	grub_free (real_sb);
	return 0;
      }
    }

  return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid");
}
示例#9
0
static struct grub_diskfilter_vg *
grub_dmraid_nv_detect (grub_disk_t disk,
			struct grub_diskfilter_pv_id *id,
                        grub_disk_addr_t *start_sector)
{
  grub_disk_addr_t sector;
  struct grub_nv_super sb;
  int level;
  grub_uint64_t disk_size;
  char *uuid;

  if (disk->partition)
    /* Skip partition.  */
    return NULL;

  sector = grub_disk_get_size (disk);
  if (sector == GRUB_DISK_SIZE_UNKNOWN)
    /* Not raid.  */
    return NULL;
  sector -= 2;
  if (grub_disk_read (disk, sector, 0, sizeof (sb), &sb))
    return NULL;

  if (grub_memcmp (sb.vendor, NV_ID_STRING, 6))
    /* Not raid.  */
    return NULL;

  if (sb.version != NV_VERSION)
    {
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		  "unknown version: %d.%d", sb.version);
      return NULL;
    }

  switch (sb.array.raid_level)
    {
    case NV_LEVEL_0:
      level = 0;
      disk_size = sb.capacity / sb.array.total_volumes;
      break;

    case NV_LEVEL_1:
      level = 1;
      disk_size = sb.capacity;
      break;

    case NV_LEVEL_5:
      level = 5;
      disk_size = sb.capacity / (sb.array.total_volumes - 1);
      break;

    default:
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		  "unsupported RAID level: %d", sb.array.raid_level);
      return NULL;
    }

  uuid = grub_malloc (sizeof (sb.array.signature));
  if (! uuid)
    return NULL;

  grub_memcpy (uuid, (char *) &sb.array.signature,
               sizeof (sb.array.signature));

  id->uuidlen = 0;
  id->id = sb.unit_number;

  *start_sector = 0;

  return grub_diskfilter_make_raid (sizeof (sb.array.signature),
				    uuid, sb.array.total_volumes,
				    NULL, disk_size,
				    sb.array.stripe_block_size,
				    GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC,
				    level);
}