Exemple #1
0
static int
fill_alias (struct grub_ieee1275_devalias *alias)
{
  grub_ssize_t actual;

  if (grub_ieee1275_get_property (alias->phandle, "device_type", alias->type,
				  IEEE1275_MAX_PROP_LEN, &actual))
    alias->type[0] = 0;

  if (alias->parent_dev == alias->phandle)
    return 0;

  if (grub_ieee1275_package_to_path (alias->phandle, alias->path,
				     IEEE1275_MAX_PATH_LEN, &actual))
    return 0;

  if (grub_strcmp (alias->parent_path, alias->path) == 0)
    return 0;

  if (grub_ieee1275_get_property (alias->phandle, "name", alias->name,
				  IEEE1275_MAX_PROP_LEN, &actual))
    return 0;
  grub_dprintf ("devalias", "device path=%s\n", alias->path);
  return 1;
}
Exemple #2
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 #3
0
void
grub_machine_set_prefix (void)
{
#ifndef __i386__
  char bootpath[64]; /* XXX check length */
  char *filename;
  char *prefix;
#endif

  if (grub_prefix[0])
    {
      grub_env_set ("prefix", grub_prefix);
      /* Prefix is hardcoded in the core image.  */
      return;
    }

#ifdef __i386__
  grub_env_set ("prefix", "(sd,1)/");
#else
  if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
				  sizeof (bootpath), 0))
    {
      /* Should never happen.  */
      grub_printf ("/chosen/bootpath property missing!\n");
      grub_env_set ("prefix", "");
      return;
    }

  /* Transform an OF device path to a GRUB path.  */

  prefix = grub_ieee1275_encode_devname (bootpath);

  filename = grub_ieee1275_get_filename (bootpath);
  if (filename)
    {
      char *newprefix;
      char *lastslash = grub_strrchr (filename, '\\');

      /* Truncate at last directory.  */
      if (lastslash)
        {
	  *lastslash = '\0';
	  grub_translate_ieee1275_path (filename);

	  newprefix = grub_xasprintf ("%s%s", prefix, filename);
	  if (newprefix)
	    {
	      grub_free (prefix);
	      prefix = newprefix;
	    }
	}
    }

  grub_env_set ("prefix", prefix);

  grub_free (filename);
  grub_free (prefix);
#endif
}
Exemple #4
0
/* Walk children of 'devpath', calling hook for each.  */
grub_err_t
grub_children_iterate (char *devpath,
		  int (*hook) (struct grub_ieee1275_devalias *alias))
{
  grub_ieee1275_phandle_t dev;
  grub_ieee1275_phandle_t child;

  if (grub_ieee1275_finddevice (devpath, &dev))
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Unknown device");

  if (grub_ieee1275_child (dev, &child))
    return grub_error (GRUB_ERR_BAD_DEVICE, "Device has no children");

  do
    {
      /* XXX: Don't use hardcoded path lengths.  */
      char childtype[64];
      char childpath[64];
      char childname[64];
      char fullname[64];
      struct grub_ieee1275_devalias alias;
      int actual;

      if (grub_ieee1275_get_property (child, "device_type", &childtype,
				      sizeof childtype, &actual))
	continue;

      if (grub_ieee1275_package_to_path (child, childpath, sizeof childpath,
					 &actual))
	continue;

      if (grub_ieee1275_get_property (child, "name", &childname,
				      sizeof childname, &actual))
	continue;

      grub_sprintf (fullname, "%s/%s", devpath, childname);

      alias.type = childtype;
      alias.path = childpath;
      alias.name = fullname;
      hook (&alias);
    }
  while (grub_ieee1275_peer (child, &child));

  return 0;
}
Exemple #5
0
static grub_err_t
grub_ofdisk_open (const char *name, grub_disk_t disk)
{
  grub_ieee1275_phandle_t dev;
  char *devpath;
  /* XXX: This should be large enough for any possible case.  */
  char prop[64];
  grub_ssize_t actual;

  if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
			 "not IEEE1275 device");
  devpath = compute_dev_path (name + sizeof ("ieee1275/") - 1);
  if (! devpath)
    return grub_errno;

  grub_dprintf ("disk", "Opening `%s'.\n", devpath);

  if (grub_ieee1275_finddevice (devpath, &dev))
    {
      grub_free (devpath);
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
			 "can't read device properties");
    }

  if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
				  &actual))
    {
      grub_free (devpath);
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
    }

  if (grub_strcmp (prop, "block"))
    {
      grub_free (devpath);
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
    }

  /* XXX: There is no property to read the number of blocks.  There
     should be a property `#blocks', but it is not there.  Perhaps it
     is possible to use seek for this.  */
  disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;

  {
    struct ofdisk_hash_ent *op;
    op = ofdisk_hash_find (devpath);
    if (!op)
      op = ofdisk_hash_add (devpath, NULL);
    else
      grub_free (devpath);
    if (!op)
      return grub_errno;
    disk->id = (unsigned long) op;
    disk->data = op->devpath;
  }

  return 0;
}
Exemple #6
0
static void
grub_ieee1275_net_config_real (const char *devpath, char **device, char **path)
{
  struct grub_net_card *card;

  /* FIXME: Check that it's the right card.  */
  FOR_NET_CARDS (card)
  {
    char *bootp_response;
    char *cardpath;
    char *canon;

    grub_ssize_t size = -1;
    unsigned int i;

    if (card->driver != &ofdriver)
      continue;

    cardpath = ((struct grub_ofnetcard_data *) card->data)->path;
    canon = grub_ieee1275_canonicalise_devname (cardpath);
    if (grub_strcmp (devpath, canon) != 0)
      {
	grub_free (canon);
	continue;
      }
    grub_free (canon);

    for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
      if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
					     bootp_response_properties[i].name,
					     &size) >= 0)
	break;

    if (size < 0)
      return;

    bootp_response = grub_malloc (size);
    if (!bootp_response)
      {
	grub_print_error ();
	return;
      }
    if (grub_ieee1275_get_property (grub_ieee1275_chosen,
				    bootp_response_properties[i].name,
				    bootp_response, size, 0) < 0)
      return;

    grub_net_configure_by_dhcp_ack (card->name, card, 0,
				    (struct grub_net_bootp_packet *)
				    &bootp_response
				    + bootp_response_properties[i].offset,
				    size - bootp_response_properties[i].offset,
				    1, device, path);
    return;
  }
}
Exemple #7
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 #8
0
void
grub_machine_init (void)
{
  char args[256];
  grub_ssize_t actual;

  grub_ieee1275_init ();

  grub_console_init_early ();
#ifdef __i386__
  grub_get_extended_memory ();
#endif
  grub_claim_heap ();
  grub_console_init_lately ();
  grub_ofdisk_init ();

  /* Process commandline.  */
  if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
				  sizeof args, &actual) == 0
      && actual > 1)
    {
      int i = 0;

      while (i < actual)
	{
	  char *command = &args[i];
	  char *end;
	  char *val;

	  end = grub_strchr (command, ';');
	  if (end == 0)
	    i = actual; /* No more commands after this one.  */
	  else
	    {
	      *end = '\0';
	      i += end - command + 1;
	      while (grub_isspace(args[i]))
		i++;
	    }

	  /* Process command.  */
	  val = grub_strchr (command, '=');
	  if (val)
	    {
	      *val = '\0';
	      grub_env_set (command, val + 1);
	    }
	}
    }

  grub_install_get_time_ms (ieee1275_get_time_ms);
}
Exemple #9
0
int
grub_ieee1275_get_integer_property (grub_ieee1275_phandle_t phandle,
				    const char *property, grub_uint32_t *buf,
				    grub_size_t size, grub_ssize_t *actual)
{
  int ret;
  ret = grub_ieee1275_get_property (phandle, property, (void *) buf, size, actual);
#ifndef GRUB_CPU_WORDS_BIGENDIAN
  /* Integer properties are always in big endian.  */
  if (ret == 0)
    {
      unsigned int i;
      size /= sizeof (grub_uint32_t);
      for (i = 0; i < size; i++)
	buf[i] = grub_be_to_cpu32 (buf[i]);
    }
#endif
  return ret;
}
Exemple #10
0
void
grub_machine_set_prefix (void)
{
  if (grub_prefix[0] != '(')
    {
      char bootpath[IEEE1275_MAX_PATH_LEN];
      char *prefix, *path, *colon;
      grub_ssize_t actual;

      if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath",
				      &bootpath, sizeof (bootpath), &actual))
	{
	  /* Should never happen.  */
	  grub_printf ("/chosen/bootpath property missing!\n");
	  grub_env_set ("prefix", "");
	  return;
	}

      /* Transform an OF device path to a GRUB path.  */
      colon = grub_strchr (bootpath, ':');
      if (colon)
	{
	  char *part = colon + 1;

	  /* Consistently provide numbered partitions to GRUB.
	     OpenBOOT traditionally uses alphabetical partition
	     specifiers.  */
	  if (part[0] >= 'a' && part[0] <= 'z')
	    part[0] = '1' + (part[0] - 'a');
	}
      prefix = grub_ieee1275_encode_devname (bootpath);

      path = grub_xasprintf("%s%s", prefix, grub_prefix);

      grub_strcpy (grub_prefix, path);

      grub_free (path);
      grub_free (prefix);
    }

  grub_env_set ("prefix", grub_prefix);
}
Exemple #11
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 #12
0
int
grub_ieee1275_alloc_physmem (grub_addr_t *paddr, grub_size_t size,
			     grub_uint32_t align)
{
  grub_uint32_t memory_ihandle;
  struct alloc_physmem_args
  {
    struct grub_ieee1275_common_hdr common;
    grub_ieee1275_cell_t method;
    grub_ieee1275_cell_t ihandle;
    grub_ieee1275_cell_t align;
    grub_ieee1275_cell_t size;
    grub_ieee1275_cell_t catch_result;
    grub_ieee1275_cell_t phys_high;
    grub_ieee1275_cell_t phys_low;
  }
  args;
  grub_ssize_t actual = 0;

  grub_ieee1275_get_property (grub_ieee1275_chosen, "memory",
			      &memory_ihandle, sizeof (memory_ihandle),
			      &actual);
  if (actual != sizeof (memory_ihandle))
    return -1;

  if (!align)
    align = 1;

  INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 3);
  args.method = (grub_ieee1275_cell_t) "claim";
  args.ihandle = memory_ihandle;
  args.align = (align ? align : 1);
  args.size = size;
  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
    return -1;

  *paddr = args.phys_low;

  return args.catch_result;
}
Exemple #13
0
static void
grub_parse_cmdline (void)
{
  grub_ssize_t actual;
  char args[256];

  if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
				  sizeof args, &actual) == 0
      && actual > 1)
    {
      int i = 0;

      while (i < actual)
	{
	  char *command = &args[i];
	  char *end;
	  char *val;

	  end = grub_strchr (command, ';');
	  if (end == 0)
	    i = actual; /* No more commands after this one.  */
	  else
	    {
	      *end = '\0';
	      i += end - command + 1;
	      while (grub_isspace(args[i]))
		i++;
	    }

	  /* Process command.  */
	  val = grub_strchr (command, '=');
	  if (val)
	    {
	      *val = '\0';
	      grub_env_set (command, val + 1);
	    }
	}
    }
}
Exemple #14
0
static void
insert_bootpath (void)
{
  char *bootpath;
  grub_ssize_t bootpath_size;
  char *type;

  if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
					 &bootpath_size)
      || bootpath_size <= 0)
    {
      /* Should never happen.  */
      grub_printf ("/chosen/bootpath property missing!\n");
      return;
    }

  bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
  if (! bootpath)
    {
      grub_print_error ();
      return;
    }
  grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
                              (grub_size_t) bootpath_size + 1, 0);
  bootpath[bootpath_size] = '\0';

  /* Transform an OF device path to a GRUB path.  */

  type = grub_ieee1275_get_device_type (bootpath);
  if (!(type && grub_strcmp (type, "network") == 0))
    {
      struct ofdisk_hash_ent *op;
      char *device = grub_ieee1275_get_devname (bootpath);
      op = ofdisk_hash_add (device, NULL);
      op->is_boot = 1;
    }
  grub_free (type);
  grub_free (bootpath);
}
Exemple #15
0
/* Walk children of 'devpath', calling hook for each.  */
int
grub_children_iterate (char *devpath,
		       int (*hook) (struct grub_ieee1275_devalias *alias,
				    void *closure),
		       void *closure)
{
  grub_ieee1275_phandle_t dev;
  grub_ieee1275_phandle_t child;
  char *childtype, *childpath;
  char *childname;
  int ret = 0;

  if (grub_ieee1275_finddevice (devpath, &dev))
    return 0;

  if (grub_ieee1275_child (dev, &child))
    return 0;

  childtype = grub_malloc (IEEE1275_MAX_PROP_LEN);
  if (!childtype)
    return 0;
  childpath = grub_malloc (IEEE1275_MAX_PATH_LEN);
  if (!childpath)
    {
      grub_free (childtype);
      return 0;
    }
  childname = grub_malloc (IEEE1275_MAX_PROP_LEN);
  if (!childname)
    {
      grub_free (childpath);
      grub_free (childtype);
      return 0;
    }

  do
    {
      struct grub_ieee1275_devalias alias;
      grub_ssize_t actual;

      if (grub_ieee1275_get_property (child, "device_type", childtype,
				      IEEE1275_MAX_PROP_LEN, &actual))
	childtype[0] = 0;

      if (dev == child)
	continue;

      if (grub_ieee1275_package_to_path (child, childpath,
					 IEEE1275_MAX_PATH_LEN, &actual))
	continue;

      if (grub_strcmp (devpath, childpath) == 0)
	continue;

      if (grub_ieee1275_get_property (child, "name", childname,
				      IEEE1275_MAX_PROP_LEN, &actual))
	continue;

      alias.type = childtype;
      alias.path = childpath;
      alias.name = childname;
      ret = hook (&alias, closure);
      if (ret)
	break;
    }
  while (grub_ieee1275_peer (child, &child) != -1);

  grub_free (childname);
  grub_free (childpath);
  grub_free (childtype);

  return ret;
}
Exemple #16
0
static void
grub_ieee1275_find_options (void)
{
    grub_ieee1275_phandle_t root;
    grub_ieee1275_phandle_t options;
    grub_ieee1275_phandle_t openprom;
    grub_ieee1275_phandle_t bootrom;
    int rc;
    grub_uint32_t realmode = 0;
    char tmp[32];
    int is_smartfirmware = 0;
    int is_olpc = 0;
    int is_qemu = 0;

#ifdef __sparc__
    grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
#endif

    grub_ieee1275_finddevice ("/", &root);
    grub_ieee1275_finddevice ("/options", &options);
    grub_ieee1275_finddevice ("/openprom", &openprom);

    rc = grub_ieee1275_get_integer_property (options, "real-mode?", &realmode,
            sizeof realmode, 0);
    if (((rc >= 0) && realmode) || (grub_ieee1275_mmu == 0))
        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_REAL_MODE);

    rc = grub_ieee1275_get_property (openprom, "CodeGen-copyright",
                                     tmp,	sizeof (tmp), 0);
    if (rc >= 0 && !grub_strncmp (tmp, SF, sizeof (SF) - 1))
        is_smartfirmware = 1;

    rc = grub_ieee1275_get_property (root, "architecture",
                                     tmp,	sizeof (tmp), 0);
    if (rc >= 0 && !grub_strcmp (tmp, "OLPC"))
        is_olpc = 1;

    rc = grub_ieee1275_get_property (root, "model",
                                     tmp,	sizeof (tmp), 0);
    if (rc >= 0 && !grub_strcmp (tmp, "Emulated PC"))
        is_qemu = 1;

    if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0)
        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS);

    if (grub_strncmp (tmp, "PowerMac", sizeof ("PowerMac") - 1) == 0)
        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS);

    if (is_smartfirmware)
    {
        /* Broken in all versions */
        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT);

        /* There are two incompatible ways of checking the version number.  Try
           both. */
        rc = grub_ieee1275_get_property (openprom, "SmartFirmware-version",
                                         tmp, sizeof (tmp), 0);
        if (rc < 0)
            rc = grub_ieee1275_get_property (openprom, "firmware-version",
                                             tmp, sizeof (tmp), 0);
        if (rc >= 0)
        {
            /* It is tempting to implement a version parser to set the flags for
               e.g. 1.3 and below.  However, there's a special situation here.
               3rd party updates which fix the partition bugs are common, and for
               some reason their fixes aren't being merged into trunk.  So for
               example we know that 1.2 and 1.3 are broken, but there's 1.2.99
               and 1.3.99 which are known good (and applying this workaround
               would cause breakage). */
            if (!grub_strcmp (tmp, "1.0")
                    || !grub_strcmp (tmp, "1.1")
                    || !grub_strcmp (tmp, "1.2")
                    || !grub_strcmp (tmp, "1.3"))
            {
                grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0);
                grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS);
            }
        }
    }

    if (is_olpc)
    {
        /* OLPC / XO laptops have three kinds of storage devices:

        - NAND flash.  These are accessible via OFW callbacks, but:
           - Follow strange semantics, imposed by hardware constraints.
           - Its ABI is undocumented, and not stable.
           They lack "device_type" property, which conveniently makes GRUB
           skip them.

         - USB drives.  Not accessible, because OFW shuts down the controller
           in order to prevent collisions with applications accessing it
           directly.  Even worse, attempts to access it will NOT return
           control to the caller, so we have to avoid probing them.

         - SD cards.  These work fine.

         To avoid breakage, we only need to skip USB probing.  However,
         since detecting SD cards is more reliable, we do that instead.
            */

        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY);
        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF);
    }

    if (is_qemu)
    {
        /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB.  */
        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM);

        grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF);
    }

    if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom))
    {
        rc = grub_ieee1275_get_property (bootrom, "model", tmp, sizeof (tmp), 0);
        if (rc >= 0 && !grub_strncmp (tmp, OHW, sizeof (OHW) - 1))
        {
            grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT);
            grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS);
            grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET);
            grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM);
            grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_ANSI);
        }
    }
}
Exemple #17
0
static char *
grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
{
  char type[64]; /* XXX check size.  */
  char *device = grub_ieee1275_get_devname (path);
  char *ret = 0;
  grub_ieee1275_phandle_t dev;

  /* We need to know what type of device it is in order to parse the full
     file path properly.  */
  if (grub_ieee1275_finddevice (device, &dev))
    {
      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "device %s not found", device);
      goto fail;
    }
  if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0))
    {
      grub_error (GRUB_ERR_UNKNOWN_DEVICE,
		  "device %s lacks a device_type property", device);
      goto fail;
    }

  switch (ptype)
    {
    case GRUB_PARSE_DEVICE:
      ret = grub_strdup (device);
      break;
    case GRUB_PARSE_DEVICE_TYPE:
      ret = grub_strdup (type);
      break;
    case GRUB_PARSE_FILENAME:
      {
	char *comma;
	char *args;

	if (grub_strcmp ("block", type) != 0)
	  goto unknown;

	args = grub_ieee1275_get_devargs (path);
	if (!args)
	  /* Shouldn't happen.  */
	  return 0;

	/* The syntax of the device arguments is defined in the CHRP and PReP
	   IEEE1275 bindings: "[partition][,[filename]]".  */
	comma = grub_strchr (args, ',');

	if (comma)
	  {
	    char *filepath = comma + 1;
	    
	    /* Make sure filepath has leading backslash.  */
	    if (filepath[0] != '\\')
	      ret = grub_xasprintf ("\\%s", filepath);
	    else
	      ret = grub_strdup (filepath);
	    }
	grub_free (args);
	}
      break;
    case GRUB_PARSE_PARTITION:
      {
	char *comma;
	char *args;

	if (grub_strcmp ("block", type) != 0)
	  goto unknown;

	args = grub_ieee1275_get_devargs (path);
	if (!args)
	  /* Shouldn't happen.  */
	  return 0;

	comma = grub_strchr (args, ',');
	if (!comma)
	  ret = grub_strdup (args);
	else
	  ret = grub_strndup (args, (grub_size_t)(comma - args));
	/* Consistently provide numbered partitions to GRUB.
	   OpenBOOT traditionally uses alphabetical partition
	   specifiers.  */
	if (ret[0] >= 'a' && ret[0] <= 'z')
	    ret[0] = '1' + (ret[0] - 'a');
	grub_free (args);
      }
      break;
    default:
    unknown:
      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
		  "unsupported type %s for device %s", type, device);
    }

fail:
  grub_free (device);
  return ret;
}
Exemple #18
0
/* Iterate through all device aliases.  This function can be used to
   find a device of a specific type.  */
grub_err_t
grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias))
{
  grub_ieee1275_phandle_t aliases;
  char aliasname[32];
  int actual;
  struct grub_ieee1275_devalias alias;

  if (grub_ieee1275_finddevice ("/aliases", &aliases))
    return -1;

  /* Find the first property.  */
  aliasname[0] = '\0';

  while (grub_ieee1275_next_property (aliases, aliasname, aliasname))
    {
      grub_ieee1275_phandle_t dev;
      grub_ssize_t pathlen;
      char *devpath;
      /* XXX: This should be large enough for any possible case.  */
      char devtype[64];

      grub_dprintf ("devalias", "devalias name = %s\n", aliasname);

      grub_ieee1275_get_property_length (aliases, aliasname, &pathlen);

      /* The property `name' is a special case we should skip.  */
      if (!grub_strcmp (aliasname, "name"))
	continue;

      devpath = grub_malloc (pathlen);
      if (! devpath)
	return grub_errno;

      if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen,
				      &actual))
	{
	  grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
	  goto nextprop;
	}

      if (grub_ieee1275_finddevice (devpath, &dev))
	{
	  grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath);
	  goto nextprop;
	}

      if (grub_ieee1275_get_property (dev, "device_type", devtype,
				      sizeof devtype, &actual))
	{
	  /* NAND device don't have device_type property.  */
          devtype[0] = 0;
	}

      alias.name = aliasname;
      alias.path = devpath;
      alias.type = devtype;
      hook (&alias);

nextprop:
      grub_free (devpath);
    }

  return 0;
}
Exemple #19
0
void
grub_machine_get_bootlocation (char **device, char **path)
{
  char *bootpath;
  grub_ssize_t bootpath_size;
  char *filename;
  char *type;

  if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath",
					 &bootpath_size)
      || bootpath_size <= 0)
    {
      /* Should never happen.  */
      grub_printf ("/chosen/bootpath property missing!\n");
      return;
    }

  bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
  if (! bootpath)
    {
      grub_print_error ();
      return;
    }
  grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath,
                              (grub_size_t) bootpath_size + 1, 0);
  bootpath[bootpath_size] = '\0';

  /* Transform an OF device path to a GRUB path.  */

  type = grub_ieee1275_get_device_type (bootpath);
  if (type && grub_strcmp (type, "network") == 0)
    {
      char *dev, *canon;
      char *ptr;
      dev = grub_ieee1275_get_aliasdevname (bootpath);
      canon = grub_ieee1275_canonicalise_devname (dev);
      ptr = canon + grub_strlen (canon) - 1;
      while (ptr > canon && (*ptr == ',' || *ptr == ':'))
	ptr--;
      ptr++;
      *ptr = 0;

      if (grub_ieee1275_net_config)
	grub_ieee1275_net_config (canon, device, path, bootpath);
      grub_free (dev);
      grub_free (canon);
    }
  else
    *device = grub_ieee1275_encode_devname (bootpath);
  grub_free (type);

  filename = grub_ieee1275_get_filename (bootpath);
  if (filename)
    {
      char *lastslash = grub_strrchr (filename, '\\');

      /* Truncate at last directory.  */
      if (lastslash)
        {
	  *lastslash = '\0';
	  grub_translate_ieee1275_path (filename);

	  *path = filename;
	}
    }
  grub_free (bootpath);
}
Exemple #20
0
static char *
grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
{
  char type[64]; /* XXX check size.  */
  char *device = grub_ieee1275_get_devname (path);
  char *args = grub_ieee1275_get_devargs (path);
  char *ret = 0;
  grub_ieee1275_phandle_t dev;

  if (!args)
    /* Shouldn't happen.  */
    return 0;

  /* We need to know what type of device it is in order to parse the full
     file path properly.  */
  if (grub_ieee1275_finddevice (device, &dev))
    {
      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device);
      goto fail;
    }
  if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0))
    {
      grub_error (GRUB_ERR_UNKNOWN_DEVICE,
		  "Device %s lacks a device_type property\n", device);
      goto fail;
    }

  if (!grub_strcmp ("block", type))
    {
      /* The syntax of the device arguments is defined in the CHRP and PReP
         IEEE1275 bindings: "[partition][,[filename]]".  */
      char *comma = grub_strchr (args, ',');

      if (ptype == GRUB_PARSE_FILENAME)
	{
	  if (comma)
	    {
	      char *filepath = comma + 1;

	      ret = grub_malloc (grub_strlen (filepath) + 1);
	      /* Make sure filepath has leading backslash.  */
	      if (filepath[0] != '\\')
		grub_sprintf (ret, "\\%s", filepath);
	      else
		grub_strcpy (ret, filepath);
	    }
	}
      else if (ptype == GRUB_PARSE_PARTITION)
        {
	  if (!comma)
	    ret = grub_strdup (args);
	  else
	    ret = grub_strndup (args, (grub_size_t)(comma - args));
	}
    }
  else
    {
      /* XXX Handle net devices by configuring & registering a grub_net_dev
	 here, then return its name?
	 Example path: "net:<server ip>,<file name>,<client ip>,<gateway
	 ip>,<bootp retries>,<tftp retries>".  */
      grub_printf ("Unsupported type %s for device %s\n", type, device);
    }

fail:
  grub_free (device);
  grub_free (args);
  return ret;
}
Exemple #21
0
grub_err_t
grub_machine_mmap_iterate (int (*hook) (grub_uint64_t, grub_uint64_t,
					grub_uint32_t, void *closure),
			   void *closure)
{
  grub_ieee1275_phandle_t root;
  grub_ieee1275_phandle_t memory;
  grub_uint32_t available[32];
  grub_ssize_t available_size;
  grub_uint32_t address_cells = 1;
  grub_uint32_t size_cells = 1;
  char copyright[128];
  int i;

  /* Determine the format of each entry in `available'.  */
  grub_ieee1275_finddevice ("/", &root);
  grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
				      sizeof address_cells, 0);
  grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells,
				      sizeof size_cells, 0);

  grub_ieee1275_get_property (root, "copyright", copyright,
			      sizeof copyright, 0);

  if (size_cells > address_cells)
    address_cells = size_cells;

  /* Apple ppc g4, g5 /memory/available[] uses 32bit offset and size,
     including for >4GB fitted RAM,
     and does not use root cell sizes. Maybe some other ieee1275 Apple
     uses 64bit offset and size? */
  if (grub_strstr (copyright, "Apple"))
    address_cells = size_cells;

  /* Load `/memory/available'.  */
  if (grub_ieee1275_finddevice ("/memory", &memory))
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
		       "couldn't find /memory node");
  if (grub_ieee1275_get_integer_property (memory, "available", available,
					  sizeof available, &available_size))
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
		       "couldn't examine /memory/available property");

  /* Decode each entry and call `hook'.  */
  i = 0;
  available_size /= sizeof (grub_uint32_t);
  while (i < available_size)
    {
      grub_uint64_t address;
      grub_uint64_t size;

      address = available[i++];
      if (address_cells == 2)
	address = (address << 32) | available[i++];

      size = available[i++];
      if (size_cells == 2)
	size = (size << 32) | available[i++];

      if (hook (address, size, GRUB_MACHINE_MEMORY_AVAILABLE, closure))
	break;
    }

  return grub_errno;
}
Exemple #22
0
static grub_err_t
grub_ofdisk_open (const char *name, grub_disk_t disk)
{
  grub_ieee1275_phandle_t dev;
  grub_ieee1275_ihandle_t dev_ihandle = 0;
  struct ofdisk_hash_ent *op;
  char *devpath;
  /* XXX: This should be large enough for any possible case.  */
  char prop[64];
  grub_ssize_t actual;

  devpath = compute_dev_path (name);
  if (! devpath)
    return grub_errno;

  op = ofdisk_hash_find (devpath);
  if (!op)
    op = ofdisk_hash_add (devpath);

  grub_free (devpath);
  if (!op)
    return grub_errno;

  if (op->dev_ihandle)
    {
      op->refs++;

      /* XXX: There is no property to read the number of blocks.  There
	 should be a property `#blocks', but it is not there.  Perhaps it
	 is possible to use seek for this.  */
      disk->total_sectors = 0xFFFFFFFFUL;

      disk->id = (unsigned long) op;

      /* XXX: Read this, somehow.  */
      disk->has_partitions = 1;
      disk->data = op;
      return 0;
    }

  grub_dprintf ("disk", "Opening `%s'.\n", op->devpath);

  if (grub_ieee1275_finddevice (op->devpath, &dev))
    {
      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties");
      goto fail;
    }

  if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
				  &actual))
    {
      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
      goto fail;
    }

  if (grub_strcmp (prop, "block"))
    {
      grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
      goto fail;
    }

  grub_ieee1275_open (op->devpath, &dev_ihandle);
  if (! dev_ihandle)
    {
      grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
      goto fail;
    }

  grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op->devpath,
		(void *) (unsigned long) dev_ihandle);

  op->dev_ihandle = dev_ihandle;
  op->refs++;

  /* XXX: There is no property to read the number of blocks.  There
     should be a property `#blocks', but it is not there.  Perhaps it
     is possible to use seek for this.  */
  disk->total_sectors = 0xFFFFFFFFUL;

  disk->id = (unsigned long) op;

  /* XXX: Read this, somehow.  */
  disk->has_partitions = 1;
  disk->data = op;
  return 0;

 fail:
  if (dev_ihandle)
    grub_ieee1275_close (dev_ihandle);
  return grub_errno;
}
Exemple #23
0
static void
grub_ofnet_findcards (void)
{
  auto int search_net_devices (struct grub_ieee1275_devalias *alias);

  int search_net_devices (struct grub_ieee1275_devalias *alias)
  {
    if (!grub_strcmp (alias->type, "network"))
      {
	struct grub_ofnetcard_data *ofdata;
	struct grub_net_card *card;
	grub_ieee1275_phandle_t devhandle;
	grub_net_link_level_address_t lla;
	char *shortname;

	ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data));
	if (!ofdata)
	  {
	    grub_print_error ();
	    return 1;
	  }
	card = grub_zalloc (sizeof (struct grub_net_card));
	if (!card)
	  {
	    grub_free (ofdata);
	    grub_print_error ();
	    return 1;
	  }

	ofdata->path = grub_strdup (alias->path);

	grub_ieee1275_finddevice (ofdata->path, &devhandle);

	if (grub_ieee1275_get_integer_property
	    (devhandle, "max-frame-size", &(ofdata->mtu),
	     sizeof (ofdata->mtu), 0))
	  {
	    ofdata->mtu = 1500;
	  }

	if (grub_ieee1275_get_property (devhandle, "mac-address",
					&(lla.mac), 6, 0)
	    && grub_ieee1275_get_property (devhandle, "local-mac-address",
					   &(lla.mac), 6, 0))
	  {
	    grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address.");
	    grub_print_error ();
	    return 0;
	  }

	lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
	card->default_address = lla;

	card->driver = NULL;
	card->data = ofdata;
	card->flags = 0;
	shortname = find_alias (alias->path);
	card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path);
	card->idle_poll_delay_ms = 1;
	grub_free (shortname);

	card->driver = &ofdriver;
	grub_net_card_register (card);
	return 0;
      }
    return 0;
  }

  /* Look at all nodes for devices of the type network.  */
  grub_ieee1275_devices_iterate (search_net_devices);
}
Exemple #24
0
/* Iterate through all device aliases.  This function can be used to
   find a device of a specific type.  */
int
grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias,
				    void *closure), void *closure)
{
  grub_ieee1275_phandle_t aliases;
  char *aliasname, *devtype;
  grub_ssize_t actual;
  struct grub_ieee1275_devalias alias;
  int ret = 0;

  if (grub_ieee1275_finddevice ("/aliases", &aliases))
    return 0;

  aliasname = grub_malloc (IEEE1275_MAX_PROP_LEN);
  if (!aliasname)
    return 0;
  devtype = grub_malloc (IEEE1275_MAX_PROP_LEN);
  if (!devtype)
    {
      grub_free (aliasname);
      return 0;
    }

  /* Find the first property.  */
  aliasname[0] = '\0';

  while (grub_ieee1275_next_property (aliases, aliasname, aliasname) > 0)
    {
      grub_ieee1275_phandle_t dev;
      grub_ssize_t pathlen;
      char *devpath;

      if (! aliasname[0])
	break;

      grub_dprintf ("devalias", "devalias name = %s\n", aliasname);

      grub_ieee1275_get_property_length (aliases, aliasname, &pathlen);

      /* The property `name' is a special case we should skip.  */
      if (!grub_strcmp (aliasname, "name"))
	continue;

      /* Sun's OpenBoot often doesn't zero terminate the device alias
	 strings, so we will add a NULL byte at the end explicitly.  */
      pathlen += 1;

      devpath = grub_malloc (pathlen);
      if (! devpath)
	{
	  grub_free (devtype);
	  grub_free (aliasname);
	  return 0;
	}

      if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen,
				      &actual))
	{
	  grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname);
	  goto nextprop;
	}
      devpath [actual] = '\0';

      if (grub_ieee1275_finddevice (devpath, &dev))
	{
	  grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath);
	  goto nextprop;
	}

      if (grub_ieee1275_get_property (dev, "device_type", devtype,
				      IEEE1275_MAX_PROP_LEN, &actual))
	{
	  /* NAND device don't have device_type property.  */
          devtype[0] = 0;
	}

      alias.name = aliasname;
      alias.path = devpath;
      alias.type = devtype;
      ret = hook (&alias, closure);

nextprop:
      grub_free (devpath);
      if (ret)
	break;
    }

  grub_free (devtype);
  grub_free (aliasname);
  return ret;
}