Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
void
grub_ieee1275_init (void)
{
    grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen);

    if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, "mmu", &grub_ieee1275_mmu,
                                            sizeof grub_ieee1275_mmu, 0) < 0)
        grub_ieee1275_mmu = 0;

    grub_ieee1275_find_options ();
}
Exemplo n.º 4
0
Arquivo: ofdisk.c Projeto: flihp/grub2
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;
}
Exemplo n.º 5
0
Arquivo: openfw.c Projeto: flihp/grub2
void
grub_ieee1275_children_first (const char *devpath,
			      struct grub_ieee1275_devalias *alias)
{
  grub_ieee1275_phandle_t dev;

  grub_dprintf ("devalias", "iterating children of %s\n",
		devpath);

  alias->name = 0;
  alias->path = 0;
  alias->parent_path = 0;
  alias->type = 0;

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

  if (grub_ieee1275_child (dev, &alias->phandle))
    return;

  alias->type = grub_malloc (IEEE1275_MAX_PROP_LEN);
  if (!alias->type)
    return;
  alias->path = grub_malloc (IEEE1275_MAX_PATH_LEN);
  if (!alias->path)
    {
      grub_free (alias->type);
      return;
    }
  alias->parent_path = grub_strdup (devpath);
  if (!alias->parent_path)
    {
      grub_free (alias->path);
      grub_free (alias->type);
      return;
    }

  alias->name = grub_malloc (IEEE1275_MAX_PROP_LEN);
  if (!alias->name)
    {
      grub_free (alias->path);
      grub_free (alias->type);
      grub_free (alias->parent_path);
      return;
    }
  if (!fill_alias (alias))
    grub_ieee1275_children_peer (alias);
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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;
    }
Exemplo n.º 8
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;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
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);
        }
    }
}
Exemplo n.º 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;
}
Exemplo n.º 16
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);
}
Exemplo n.º 17
0
static grub_err_t
grub_video_ieee1275_setup (unsigned int width, unsigned int height,
			   unsigned int mode_type __attribute__ ((unused)),
			   unsigned int mode_mask __attribute__ ((unused)))
{
  grub_uint32_t current_width, current_height, address;
  grub_err_t err;
  grub_ieee1275_phandle_t dev;

  if (!display)
    return grub_error (GRUB_ERR_IO, "Couldn't find display device.");

  if (grub_ieee1275_finddevice (display, &dev))
    return grub_error (GRUB_ERR_IO, "Couldn't open display device.");

  if (grub_ieee1275_get_integer_property (dev, "width", &current_width,
					  sizeof (current_width), 0))
    return grub_error (GRUB_ERR_IO, "Couldn't retrieve display width.");

  if (grub_ieee1275_get_integer_property (dev, "height", &current_height,
					  sizeof (current_width), 0))
    return grub_error (GRUB_ERR_IO, "Couldn't retrieve display height.");

  if ((width == current_width && height == current_height)
      || (width == 0 && height == 0))
    {
      grub_dprintf ("video", "IEEE1275: keeping current mode %dx%d\n",
		    current_width, current_height);
    }
  else
    {
      grub_dprintf ("video", "IEEE1275: Setting mode %dx%d\n", width, height);
      /* TODO. */
      return grub_error (GRUB_ERR_IO, "can't set mode %dx%d", width, height);
    }
  
  err = grub_video_ieee1275_fill_mode_info (dev, &framebuffer.mode_info);
  if (err)
    {
      grub_dprintf ("video", "IEEE1275: couldn't fill mode info\n");
      return err;
    }

  if (grub_ieee1275_get_integer_property (dev, "address", (void *) &address,
					  sizeof (address), 0))
    return grub_error (GRUB_ERR_IO, "Couldn't retrieve display address.");

  /* For some reason sparc64 uses 32-bit pointer too.  */
  framebuffer.ptr = (void *) (grub_addr_t) address;

  grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
				   grub_video_fbstd_colors);

  grub_dprintf ("video", "IEEE1275: initialising FB @ %p %dx%dx%d\n",
		framebuffer.ptr, framebuffer.mode_info.width,
		framebuffer.mode_info.height, framebuffer.mode_info.bpp);
  
  err = grub_video_fb_create_render_target_from_pointer 
    (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);

  if (err)
    {
      grub_dprintf ("video", "IEEE1275: Couldn't create FB target\n");
      return err;
    }
  
  err = grub_video_fb_set_active_render_target (framebuffer.render_target);
  
  if (err)
    {
      grub_dprintf ("video", "IEEE1275: Couldn't set FB target\n");
      return err;
    }
  
  err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
				   grub_video_fbstd_colors);

  if (err)
    grub_dprintf ("video", "IEEE1275: Couldn't set palette\n");
  else
    grub_dprintf ("video", "IEEE1275: Success\n");
  
  return err;
}