Exemple #1
0
/* Convert a device name from IEEE1275 syntax to GRUB syntax.  */
char *
grub_ieee1275_encode_devname (const char *path)
{
  char *device = grub_ieee1275_get_devname (path);
  char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION);
  char *encoding;

  if (partition && partition[0])
    {
      unsigned int partno = grub_strtoul (partition, 0, 0);

      if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS))
	/* GRUB partition 1 is OF partition 0.  */
	partno++;

      encoding = grub_xasprintf ("(%s,%d)", device, partno);
    }
  else
    encoding = grub_xasprintf ("(%s)", device);

  grub_free (partition);
  grub_free (device);

  return encoding;
}
Exemple #2
0
/* Convert a device name from IEEE1275 syntax to GRUB syntax.  */
char *
grub_ieee1275_encode_devname (const char *path)
{
  char *device = grub_ieee1275_get_devname (path);
  char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION);
  char *encoding;

  if (partition)
    {
      unsigned int partno = grub_strtoul (partition, 0, 0);

      if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS))
	/* GRUB partition 1 is OF partition 0.  */
	partno++;

      /* Assume partno will require less than five bytes to encode.  */
      encoding = grub_malloc (grub_strlen (device) + 3 + 5);
      grub_sprintf (encoding, "(%s,%d)", device, partno);
    }
  else
    {
      encoding = grub_malloc (grub_strlen (device) + 2);
      grub_sprintf (encoding, "(%s)", device);
    }

  grub_free (partition);
  grub_free (device);

  return encoding;
}
Exemple #3
0
static char *
compute_dev_path (const char *name)
{
  char *devpath = grub_malloc (grub_strlen (name) + 3);
  char *p, c;

  if (!devpath)
    return NULL;

  /* Un-escape commas. */
  p = devpath;
  while ((c = *name++) != '\0')
    {
      if (c == '\\' && *name == ',')
	{
	  *p++ = ',';
	  name++;
	}
      else
	*p++ = c;
    }

  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
    {
      *p++ = ':';
      *p++ = '0';
    }
  *p++ = '\0';

  return devpath;
}
Exemple #4
0
/* Helper for grub_claim_heap.  */
static int
heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
	   void *data)
{
  unsigned long *total = data;

  if (type != GRUB_MEMORY_AVAILABLE)
    return 0;

  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM))
    {
      if (addr + len <= 0x180000)
	return 0;

      if (addr < 0x180000)
	{
	  len = addr + len - 0x180000;
	  addr = 0x180000;
	}
    }
  len -= 1; /* Required for some firmware.  */

  /* Never exceed HEAP_MAX_SIZE  */
  if (*total + len > HEAP_MAX_SIZE)
    len = HEAP_MAX_SIZE - *total;

  /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */
  if ((addr < HEAP_MAX_ADDR) &&				/* if it's too late, don't bother */
      (addr + len > HEAP_MAX_ADDR) &&				/* if it wasn't available anyway, don't bother */
      (*total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE))	/* only limit ourselves when we can afford to */
     len = HEAP_MAX_ADDR - addr;

  /* In theory, firmware should already prevent this from happening by not
     listing our own image in /memory/available.  The check below is intended
     as a safeguard in case that doesn't happen.  However, it doesn't protect
     us from corrupting our module area, which extends up to a
     yet-undetermined region above _end.  */
  if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start))
    {
      grub_printf ("Warning: attempt to claim over our own code!\n");
      len = 0;
    }

  if (len)
    {
      grub_err_t err;
      /* Claim and use it.  */
      err = grub_claimmap (addr, len);
      if (err)
	return err;
      grub_mm_init_region ((void *) (grub_addr_t) addr, len);
    }

  *total += len;
  if (*total >= HEAP_MAX_SIZE)
    return 1;

  return 0;
}
Exemple #5
0
static int
grub_ofdisk_iterate (int (*hook) (const char *name),
		     grub_disk_pull_t pull)
{
  unsigned i;

  if (pull != GRUB_DISK_PULL_NONE)
    return 0;

  scan ();
  
  for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
    {
      static struct ofdisk_hash_ent *ent;
      for (ent = ofdisk_hash[i]; ent; ent = ent->next)
	{
	  if (!ent->shortest)
	    continue;
	  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
	    {
	      grub_ieee1275_phandle_t dev;
	      char tmp[8];

	      if (grub_ieee1275_finddevice (ent->devpath, &dev))
		{
		  grub_dprintf ("disk", "finddevice (%s) failed\n",
				ent->devpath);
		  continue;
		}

	      if (grub_ieee1275_get_property (dev, "iconname", tmp,
					      sizeof tmp, 0))
		{
		  grub_dprintf ("disk", "get iconname failed\n");
		  continue;
		}

	      if (grub_strcmp (tmp, "sdmmc") != 0)
		{
		  grub_dprintf ("disk", "device is not an SD card\n");
		  continue;
		}
	    }

	  if (grub_strncmp (ent->shortest, "cdrom", 5) == 0)
	    continue;

	  {
	    char buffer[sizeof ("ieee1275/") + grub_strlen (ent->shortest)];
	    char *ptr;
	    ptr = grub_stpcpy (buffer, "ieee1275/");
	    grub_strcpy (ptr, ent->shortest);
	    if (hook (buffer))
	      return 1;
	  }
	}
    }	  
  return 0;
}
Exemple #6
0
static void 
grub_claim_heap (void)
{
  unsigned long total = 0;

  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM))
    heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN,
	       1, &total);
  else
    grub_machine_mmap_iterate (heap_init, &total);
}
Exemple #7
0
static struct ofdisk_hash_ent *
ofdisk_hash_add_real (char *devpath)
{
  struct ofdisk_hash_ent *p;
  struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
  const char *iptr;
  char *optr;

  p = grub_zalloc (sizeof (*p));
  if (!p)
    return NULL;

  p->devpath = devpath;

  p->grub_devpath = grub_malloc (sizeof ("ieee1275/")
				 + 2 * grub_strlen (p->devpath));

  if (!p->grub_devpath)
    {
      grub_free (p);
      return NULL;
    }

  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
    {
      p->open_path = grub_malloc (grub_strlen (p->devpath) + 3);
      if (!p->open_path)
	{
	  grub_free (p->grub_devpath);
	  grub_free (p);
	  return NULL;
	}
      optr = grub_stpcpy (p->open_path, p->devpath);
      *optr++ = ':';
      *optr++ = '0';
      *optr = '\0';
    }
  else
    p->open_path = p->devpath;

  optr = grub_stpcpy (p->grub_devpath, "ieee1275/");
  for (iptr = p->devpath; *iptr; )
    {
      if (*iptr == ',')
	*optr++ = '\\';
      *optr++ = *iptr++;
    }
  *optr = 0;

  p->next = *head;
  *head = p;
  return p;
}
Exemple #8
0
static int
grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
		     grub_disk_pull_t pull)
{
  unsigned i;

  if (pull != GRUB_DISK_PULL_NONE)
    return 0;

  scan ();
  
  for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
    {
      static struct ofdisk_hash_ent *ent;
      for (ent = ofdisk_hash[i]; ent; ent = ent->next)
	{
	  if (!ent->shortest)
	    continue;
	  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
	    {
	      grub_ieee1275_phandle_t dev;
	      char tmp[8];

	      if (grub_ieee1275_finddevice (ent->devpath, &dev))
		{
		  grub_dprintf ("disk", "finddevice (%s) failed\n",
				ent->devpath);
		  continue;
		}

	      if (grub_ieee1275_get_property (dev, "iconname", tmp,
					      sizeof tmp, 0))
		{
		  grub_dprintf ("disk", "get iconname failed\n");
		  continue;
		}

	      if (grub_strcmp (tmp, "sdmmc") != 0)
		{
		  grub_dprintf ("disk", "device is not an SD card\n");
		  continue;
		}
	    }

	  if (!ent->is_boot && ent->is_removable)
	    continue;

	  if (hook (ent->grub_shortest, hook_data))
	    return 1;
	}
    }	  
  return 0;
}
Exemple #9
0
static void
scan (void)
{
  auto int dev_iterate_real (struct grub_ieee1275_devalias *alias,
			     int use_name);

  int dev_iterate_real (struct grub_ieee1275_devalias *alias, int use_name)
    {
      struct ofdisk_hash_ent *op;


      if (grub_strcmp (alias->type, "block") != 0)
	return 0;

      grub_dprintf ("disk", "disk name = %s, path = %s\n", alias->name,
		    alias->path);

      op = ofdisk_hash_find (alias->path);
      if (!op)
	{
	  char *name = grub_strdup (use_name ? alias->name : alias->path);
	  char *can = grub_strdup (alias->path);
	  if (!name || !can)
	    {
	      grub_errno = GRUB_ERR_NONE;
	      grub_free (name);
	      grub_free (can);
	      return 0;
	    }
	  op = ofdisk_hash_add (name, can);
	}
      return 0;
    }

  auto int dev_iterate_alias (struct grub_ieee1275_devalias *alias);
  int dev_iterate_alias (struct grub_ieee1275_devalias *alias)
  {
    return dev_iterate_real (alias, 1);
  }

  auto int dev_iterate (struct grub_ieee1275_devalias *alias);
  int dev_iterate (struct grub_ieee1275_devalias *alias)
  {
    return dev_iterate_real (alias, 0);
  }

  grub_devalias_iterate (dev_iterate_alias);
  if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS))
    grub_ieee1275_devices_iterate (dev_iterate);
}
Exemple #10
0
int
grub_claimmap (grub_addr_t addr, grub_size_t size)
{
  if (grub_ieee1275_claim (addr, size, 0, 0))
    return -1;

  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE)
      && grub_map (addr, addr, size, 0x00))
    {
      grub_printf ("map failed: address 0x%x, size 0x%x\n", addr, size);
      grub_ieee1275_release (addr, size);
      return -1;
    }

  return 0;
}
Exemple #11
0
static grub_err_t
grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
		  grub_size_t size, char *buf)
{
  grub_ssize_t status, actual;
  unsigned long long pos;

  if (disk->data != last_devpath)
    {
      if (last_ihandle)
	grub_ieee1275_close (last_ihandle);
      last_ihandle = 0;
      last_devpath = NULL;

      if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
	{
	  char name2[grub_strlen (disk->data) + 3];
	  char *p;
	  
	  grub_strcpy (name2, disk->data);
	  p = name2 + grub_strlen (name2);
	  *p++ = ':';
	  *p++ = '0';
	  *p = 0;
	  grub_ieee1275_open (name2, &last_ihandle);
	}
      else
	grub_ieee1275_open (disk->data, &last_ihandle);
      if (! last_ihandle)
	return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
      last_devpath = disk->data;      
    }

  pos = sector * 512UL;

  grub_ieee1275_seek (last_ihandle, pos, &status);
  if (status < 0)
    return grub_error (GRUB_ERR_READ_ERROR,
		       "seek error, can't seek block %llu",
		       (long long) sector);
  grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual);
  if (actual != (grub_ssize_t) (size * 512UL))
    return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu",
		       (long long) sector);

  return 0;
}
Exemple #12
0
grub_err_t
grub_claimmap (grub_addr_t addr, grub_size_t size)
{
  if (grub_ieee1275_claim (addr, size, 0, 0))
    return -1;

  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE)
      && grub_ieee1275_map (addr, addr, size, 0x00))
    {
      grub_error (GRUB_ERR_OUT_OF_MEMORY, "map failed: address 0x%llx, size 0x%llx\n",
		  (long long) addr, (long long) size);
      grub_ieee1275_release (addr, size);
      return grub_errno;
    }

  return GRUB_ERR_NONE;
}
Exemple #13
0
static int
grub_ofdisk_iterate (int (*hook) (const char *name))
{
    auto int dev_iterate (struct grub_ieee1275_devalias *alias);

    int dev_iterate (struct grub_ieee1275_devalias *alias)
    {
        int ret = 0;

        grub_dprintf ("disk", "disk name = %s\n", alias->name);

        if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
        {
            grub_ieee1275_phandle_t dev;
            char tmp[8];

            if (grub_ieee1275_finddevice (alias->path, &dev))
            {
                grub_dprintf ("disk", "finddevice (%s) failed\n", alias->path);
                return 0;
            }

            if (grub_ieee1275_get_property (dev, "iconname", tmp,
                                            sizeof tmp, 0))
            {
                grub_dprintf ("disk", "get iconname failed\n");
                return 0;
            }

            if (grub_strcmp (tmp, "sdmmc"))
            {
                grub_dprintf ("disk", "device is not an SD card\n");
                return 0;
            }
        }

        if (! grub_strcmp (alias->type, "block") &&
                grub_strncmp (alias->name, "cdrom", 5))
            ret = hook (alias->name);
        return ret;
    }
Exemple #14
0
static grub_err_t
grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
{
  grub_ssize_t status;
  unsigned long long pos;

  if (disk->data != last_devpath)
    {
      if (last_ihandle)
	grub_ieee1275_close (last_ihandle);
      last_ihandle = 0;
      last_devpath = NULL;

      if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
	{
	  char name2[grub_strlen (disk->data) + 3];
	  char *p;
	  
	  grub_strcpy (name2, disk->data);
	  p = name2 + grub_strlen (name2);
	  *p++ = ':';
	  *p++ = '0';
	  *p = 0;
	  grub_ieee1275_open (name2, &last_ihandle);
	}
      else
	grub_ieee1275_open (disk->data, &last_ihandle);
      if (! last_ihandle)
	return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
      last_devpath = disk->data;      
    }

  pos = sector << GRUB_DISK_SECTOR_BITS;

  grub_ieee1275_seek (last_ihandle, pos, &status);
  if (status < 0)
    return grub_error (GRUB_ERR_READ_ERROR,
		       "seek error, can't seek block %llu",
		       (long long) sector);
  return 0;
}
Exemple #15
0
/* Claim some available memory in the first /memory node. */
static void grub_claim_heap (void)
{
  unsigned long total = 0;

  auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type);
  int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type)
  {
    if (type != 1)
      return 0;

    if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM))
      {
	if (addr + len <= 0x180000)
	  return 0;

	if (addr < 0x180000)
	  {
	    len = addr + len - 0x180000;
	    addr = 0x180000;
	  }
      }
    len -= 1; /* Required for some firmware.  */

    /* Never exceed HEAP_MAX_SIZE  */
    if (total + len > HEAP_MAX_SIZE)
      len = HEAP_MAX_SIZE - total;

    /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */
    if ((addr < HEAP_MAX_ADDR) &&				/* if it's too late, don't bother */
        (addr + len > HEAP_MAX_ADDR) &&				/* if it wasn't available anyway, don't bother */
        (total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE))	/* only limit ourselves when we can afford to */
       len = HEAP_MAX_ADDR - addr;

    /* In theory, firmware should already prevent this from happening by not
       listing our own image in /memory/available.  The check below is intended
       as a safeguard in case that doesn't happen.  However, it doesn't protect
       us from corrupting our module area, which extends up to a
       yet-undetermined region above _end.  */
    if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start))
      {
        grub_printf ("Warning: attempt to claim over our own code!\n");
        len = 0;
      }

    if (len)
      {
	/* Claim and use it.  */
	if (grub_claimmap (addr, len) < 0)
	  return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			     "failed to claim heap at 0x%llx, len 0x%llx",
			     addr, len);
	grub_mm_init_region ((void *) (grub_addr_t) addr, len);
      }

    total += len;
    if (total >= HEAP_MAX_SIZE)
      return 1;

    return 0;
  }

  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
    heap_init (HEAP_MAX_ADDR - HEAP_MIN_SIZE, HEAP_MIN_SIZE, 1);
  else
    grub_machine_mmap_iterate (heap_init);
}
Exemple #16
0
static void
dev_iterate (const struct grub_ieee1275_devalias *alias)
{
  if (grub_strcmp (alias->type, "vscsi") == 0)
    {
      static grub_ieee1275_ihandle_t ihandle;
      struct set_color_args
      {
	struct grub_ieee1275_common_hdr common;
	grub_ieee1275_cell_t method;
	grub_ieee1275_cell_t ihandle;
	grub_ieee1275_cell_t catch_result;
	grub_ieee1275_cell_t nentries;
	grub_ieee1275_cell_t table;
      }
      args;
      char *buf, *bufptr;
      unsigned i;

      if (grub_ieee1275_open (alias->path, &ihandle))
	return;
    
      INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
      args.method = (grub_ieee1275_cell_t) "vscsi-report-luns";
      args.ihandle = ihandle;
      args.table = 0;
      args.nentries = 0;

      if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch_result)
	{
	  grub_ieee1275_close (ihandle);
	  return;
	}

      buf = grub_malloc (grub_strlen (alias->path) + 32);
      if (!buf)
	return;
      bufptr = grub_stpcpy (buf, alias->path);

      for (i = 0; i < args.nentries; i++)
	{
	  grub_uint64_t *ptr;

	  ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i);
	  while (*ptr)
	    {
	      grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++);
	      dev_iterate_real (buf, buf);
	    }
	}
      grub_ieee1275_close (ihandle);
      grub_free (buf);
      return;
    }

  if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
      && grub_strcmp (alias->type, "block") == 0)
    {
      dev_iterate_real (alias->path, alias->path);
      return;
    }

  {
    struct grub_ieee1275_devalias child;

    FOR_IEEE1275_DEVCHILDREN(alias->path, child)
      dev_iterate (&child);
  }
}
Exemple #17
0
static void
dev_iterate (const struct grub_ieee1275_devalias *alias)
{
  if (grub_strcmp (alias->type, "vscsi") == 0)
    {
      static grub_ieee1275_ihandle_t ihandle;
      struct set_color_args
      {
	struct grub_ieee1275_common_hdr common;
	grub_ieee1275_cell_t method;
	grub_ieee1275_cell_t ihandle;
	grub_ieee1275_cell_t catch_result;
	grub_ieee1275_cell_t nentries;
	grub_ieee1275_cell_t table;
      }
      args;
      char *buf, *bufptr;
      unsigned i;

      if (grub_ieee1275_open (alias->path, &ihandle))
	return;

      /* This method doesn't need memory allocation for the table. Open
         firmware takes care of all memory management and the result table
         stays in memory and is never freed. */
      INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
      args.method = (grub_ieee1275_cell_t) "vscsi-report-luns";
      args.ihandle = ihandle;
      args.table = 0;
      args.nentries = 0;

      if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch_result)
	{
	  grub_ieee1275_close (ihandle);
	  return;
	}

      buf = grub_malloc (grub_strlen (alias->path) + 32);
      if (!buf)
	return;
      bufptr = grub_stpcpy (buf, alias->path);

      for (i = 0; i < args.nentries; i++)
	{
	  grub_uint64_t *ptr;

	  ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i);
	  while (*ptr)
	    {
	      grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++);
	      dev_iterate_real (buf, buf);
	    }
	}
      grub_ieee1275_close (ihandle);
      grub_free (buf);
      return;
    }
  else if (grub_strcmp (alias->type, "sas_ioa") == 0)
    {
      /* The method returns the number of disks and a table where
       * each ID is 64-bit long. Example of sas paths:
       *  /pci@80000002000001f/pci1014,034A@0/sas/disk@c05db70800
       *  /pci@80000002000001f/pci1014,034A@0/sas/disk@a05db70800
       *  /pci@80000002000001f/pci1014,034A@0/sas/disk@805db70800 */

      struct sas_children
        {
          struct grub_ieee1275_common_hdr common;
          grub_ieee1275_cell_t method;
          grub_ieee1275_cell_t ihandle;
          grub_ieee1275_cell_t max;
          grub_ieee1275_cell_t table;
          grub_ieee1275_cell_t catch_result;
          grub_ieee1275_cell_t nentries;
        }
      args;
      char *buf, *bufptr;
      unsigned i;
      grub_uint64_t *table;
      grub_uint16_t table_size;
      grub_ieee1275_ihandle_t ihandle;

      buf = grub_malloc (grub_strlen (alias->path) +
                         sizeof ("/disk@7766554433221100"));
      if (!buf)
        return;
      bufptr = grub_stpcpy (buf, alias->path);

      /* Power machines documentation specify 672 as maximum SAS disks in
         one system. Using a slightly larger value to be safe. */
      table_size = 768;
      table = grub_malloc (table_size * sizeof (grub_uint64_t));

      if (!table)
        {
          grub_free (buf);
          return;
        }

      if (grub_ieee1275_open (alias->path, &ihandle))
        {
          grub_free (buf);
          grub_free (table);
          return;
        }

      INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
      args.method = (grub_ieee1275_cell_t) "get-sas-children";
      args.ihandle = ihandle;
      args.max = table_size;
      args.table = (grub_ieee1275_cell_t) table;
      args.catch_result = 0;
      args.nentries = 0;

      if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
        {
          grub_ieee1275_close (ihandle);
          grub_free (table);
          grub_free (buf);
          return;
        }

      for (i = 0; i < args.nentries; i++)
        {
          grub_snprintf (bufptr, sizeof ("/disk@7766554433221100"),
                        "/disk@%" PRIxGRUB_UINT64_T, table[i]);
          dev_iterate_real (buf, buf);
        }

      grub_ieee1275_close (ihandle);
      grub_free (table);
      grub_free (buf);
    }

  if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
      && grub_strcmp (alias->type, "block") == 0)
    {
      dev_iterate_real (alias->path, alias->path);
      return;
    }

  {
    struct grub_ieee1275_devalias child;

    FOR_IEEE1275_DEVCHILDREN(alias->path, child)
      dev_iterate (&child);
  }
}
Exemple #18
0
static void
scan (void)
{
  auto int dev_iterate_real (const char *name, const char *path);

  int dev_iterate_real (const char *name, const char *path)
    {
      struct ofdisk_hash_ent *op;

      grub_dprintf ("disk", "disk name = %s, path = %s\n", name,
		    path);

      op = ofdisk_hash_find (path);
      if (!op)
	{
	  char *name_dup = grub_strdup (name);
	  char *can = grub_strdup (path);
	  if (!name_dup || !can)
	    {
	      grub_errno = GRUB_ERR_NONE;
	      grub_free (name_dup);
	      grub_free (can);
	      return 0;
	    }
	  op = ofdisk_hash_add (name_dup, can);
	}
      return 0;
    }

  auto int dev_iterate_alias (struct grub_ieee1275_devalias *alias);
  int dev_iterate_alias (struct grub_ieee1275_devalias *alias)
  {
    if (grub_strcmp (alias->type, "block") != 0)
      return 0;
    return dev_iterate_real (alias->name, alias->path);
  }

  auto int dev_iterate (struct grub_ieee1275_devalias *alias);
  int dev_iterate (struct grub_ieee1275_devalias *alias)
  {
    if (grub_strcmp (alias->type, "vscsi") == 0)
      {
	static grub_ieee1275_ihandle_t ihandle;
	struct set_color_args
	{
	  struct grub_ieee1275_common_hdr common;
	  grub_ieee1275_cell_t method;
	  grub_ieee1275_cell_t ihandle;
	  grub_ieee1275_cell_t catch_result;
	  grub_ieee1275_cell_t nentries;
	  grub_ieee1275_cell_t table;
	}
	args;
	char *buf, *bufptr;
	unsigned i;

	if (grub_ieee1275_open (alias->path, &ihandle))
	  return 0;
    
	INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
	args.method = (grub_ieee1275_cell_t) "vscsi-report-luns";
	args.ihandle = ihandle;
	args.table = 0;
	args.nentries = 0;

	if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
	  {
	    grub_ieee1275_close (ihandle);
	    return 0;
	  }

	buf = grub_malloc (grub_strlen (alias->path) + 32);
	if (!buf)
	  return 0;
	bufptr = grub_stpcpy (buf, alias->path);

	for (i = 0; i < args.nentries; i++)
	  {
	    grub_uint64_t *ptr;

	    ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i);
	    while (*ptr)
	      {
		grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++);
		if (dev_iterate_real (buf, buf))
		  return 1;
	      }
	  }
	grub_ieee1275_close (ihandle);
	grub_free (buf);
	return 0;
      }

    if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
	&& grub_strcmp (alias->type, "block") == 0)
      return dev_iterate_real (alias->path, alias->path);

    return grub_children_iterate (alias->path, dev_iterate);
  }

  grub_devalias_iterate (dev_iterate_alias);
  grub_children_iterate ("/", dev_iterate);
}