Description: Add SPARC64 support
Author: Eric Snowberg <eric.snowberg@oracle.com>
Last-Update: 2017-01-22

Index: grub2-2.02~beta3/grub-core/disk/ieee1275/ofdisk.c
===================================================================
--- grub2-2.02~beta3.orig/grub-core/disk/ieee1275/ofdisk.c
+++ grub2-2.02~beta3/grub-core/disk/ieee1275/ofdisk.c
@@ -22,8 +22,10 @@
 #include <grub/mm.h>
 #include <grub/ieee1275/ieee1275.h>
 #include <grub/ieee1275/ofdisk.h>
+#include <grub/scsicmd.h>
 #include <grub/i18n.h>
 #include <grub/time.h>
+#include <grub/list.h>
 
 static char *last_devpath;
 static grub_ieee1275_ihandle_t last_ihandle;
@@ -35,7 +37,9 @@ struct ofdisk_hash_ent
   char *grub_devpath;
   int is_boot;
   int is_removable;
-  int block_size_fails;
+  int block_size_retries;
+  grub_uint32_t block_size;
+  grub_ieee1275_ihandle_t ihandle;
   /* Pointer to shortest available name on nodes representing canonical names,
      otherwise NULL.  */
   const char *shortest;
@@ -43,13 +47,51 @@ struct ofdisk_hash_ent
   struct ofdisk_hash_ent *next;
 };
 
+struct ofdisk_hba_ent
+{
+  struct ofdisk_hba_ent *next;
+  struct ofdisk_hba_ent **prev;
+  grub_ieee1275_ihandle_t ihandle;
+  char *path;
+};
+
+static grub_err_t
+grub_ofdisk_get_block_size (grub_uint32_t *block_size,
+                            struct ofdisk_hash_ent *op);
+
+static grub_err_t
+grub_ofdisk_open_real (grub_disk_t disk);
+
 static grub_err_t
-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
-			    struct ofdisk_hash_ent *op);
+sparc_disk_present (const char *path);
+
+static char *
+get_hbaname_from_path (const char *path);
+
+static char *
+get_diskname_from_path (const char *path);
+
+static struct ofdisk_hba_ent *
+ofdisk_hba_find (const char *devpath);
+
+static grub_ieee1275_ihandle_t
+ofdisk_hba_open (const char *hba_name);
 
 #define OFDISK_HASH_SZ	8
 static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ];
 
+static struct ofdisk_hba_ent *ofdisk_hba_ents = NULL;
+
+static struct grub_scsi_test_unit_ready ofdisk_tur =
+{
+  .opcode = grub_scsi_cmd_test_unit_ready,
+  .lun = 0,
+  .reserved1 = 0,
+  .reserved2 = 0,
+  .reserved3 = 0,
+  .control = 0,
+};
+
 static int
 ofdisk_hash_fn (const char *devpath)
 {
@@ -74,7 +116,7 @@ ofdisk_hash_find (const char *devpath)
 }
 
 static struct ofdisk_hash_ent *
-ofdisk_hash_add_real (char *devpath)
+ofdisk_hash_add_real (const char *devpath)
 {
   struct ofdisk_hash_ent *p;
   struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
@@ -85,13 +127,20 @@ ofdisk_hash_add_real (char *devpath)
   if (!p)
     return NULL;
 
-  p->devpath = devpath;
+  p->devpath = grub_strdup (devpath);
+
+  if (!p->devpath)
+    {
+      grub_free (p);
+      return NULL;
+    }
 
   p->grub_devpath = grub_malloc (sizeof ("ieee1275/")
 				 + 2 * grub_strlen (p->devpath));
 
   if (!p->grub_devpath)
     {
+      grub_free (p->devpath);
       grub_free (p);
       return NULL;
     }
@@ -101,6 +150,7 @@ ofdisk_hash_add_real (char *devpath)
       p->open_path = grub_malloc (grub_strlen (p->devpath) + 3);
       if (!p->open_path)
 	{
+          grub_free (p->devpath);
 	  grub_free (p->grub_devpath);
 	  grub_free (p);
 	  return NULL;
@@ -140,7 +190,7 @@ check_string_removable (const char *str)
 }
 
 static struct ofdisk_hash_ent *
-ofdisk_hash_add (char *devpath, char *curcan)
+ofdisk_hash_add (const char *devpath, const char *curcan)
 {
   struct ofdisk_hash_ent *p, *pcan;
 
@@ -160,8 +210,6 @@ ofdisk_hash_add (char *devpath, char *cu
   pcan = ofdisk_hash_find (curcan);
   if (!pcan)
     pcan = ofdisk_hash_add_real (curcan);
-  else
-    grub_free (curcan);
 
   if (check_string_removable (devpath) || check_string_removable (curcan))
     pcan->is_removable = 1;
@@ -191,18 +239,7 @@ dev_iterate_real (const char *name, cons
 
   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;
-	}
-      op = ofdisk_hash_add (name_dup, can);
-    }
+    op = ofdisk_hash_add (name, path);
   return;
 }
 
@@ -339,10 +376,156 @@ dev_iterate (const struct grub_ieee1275_
       grub_free (table);
       grub_free (buf);
     }
+  else if (grub_strcmp (alias->type, "scsi-2") == 0)
+    {
+      grub_ieee1275_ihandle_t ihandle;
+      grub_ssize_t result;
+      char *buf, *bufptr;
+      grub_uint8_t tgt;
+
+      buf = grub_malloc (grub_strlen (alias->path) +
+                         sizeof ("/disk@00"));
+      if (!buf)
+        return;
+
+      bufptr = grub_stpcpy (buf, alias->path);
+      ihandle = ofdisk_hba_open (alias->path);
+
+      if (ihandle == 0)
+        {
+          grub_free (buf);
+          return;
+        }
+
+      for (tgt = 0; tgt <= 0xf; tgt++)
+        {
+          if (grub_ieee1275_set_address(ihandle, tgt, 0) == 0)
+            if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur,
+                                               &result) == 0)
+              if (result == 0)
+                {
+                  grub_snprintf (bufptr, sizeof ("/disk@00"),
+                                 "/disk@%" PRIxGRUB_UINT32_T, tgt);
+                  dev_iterate_real (buf, buf);
+                }
+        }
+
+      grub_free (buf);
+      return;
+    }
+  else if (grub_strcmp (alias->type, "scsi-sas") == 0)
+    {
+      grub_ieee1275_ihandle_t ihandle;
+      grub_uint32_t address_cells = 2;
+      grub_ieee1275_phandle_t root;
+      grub_ssize_t result;
+      char *buf, *bufptr;
+
+      buf = grub_malloc (grub_strlen (alias->path) +
+                         sizeof ("/disk@p1100"));
+
+      if (!buf)
+        return;
+
+      bufptr = grub_stpcpy (buf, alias->path);
+      bufptr = grub_stpcpy (bufptr, "/disk@");
+      ihandle = ofdisk_hba_open (alias->path);
+
+      if (ihandle == 0)
+        {
+          grub_free (buf);
+          return;
+        }
+
+      grub_ieee1275_finddevice (alias->path, &root);
+      grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
+                                          sizeof address_cells, 0);
+      if (address_cells == 2)
+        {
+          grub_uint8_t tgt;
+
+          for (tgt = 0; tgt < 0xf; tgt++)
+            {
+              if (grub_ieee1275_set_address(ihandle, tgt, 0) == 0)
+                if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur,
+                                                   &result) == 0)
+                  if (result == 0)
+                    {
+                      grub_snprintf (bufptr, sizeof ("p1100"),
+                                     "%" PRIxGRUB_UINT32_T, tgt);
+                      dev_iterate_real (buf, buf);
+                    }
+            }
+        }
+      else if (address_cells == 4)
+        {
+          grub_uint16_t exp;
+          grub_uint8_t phy;
+
+          for (exp = 0; exp <= 0x100; exp+=0x100)
+            for (phy = 0; phy < 0xff; phy++)
+              {
+                grub_snprintf (bufptr, sizeof ("p1100"),
+                               "p%" PRIxGRUB_UINT32_T, exp | phy);
+                if (grub_ieee1275_set_sas_address (ihandle, bufptr, 0) == 0)
+                  if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur,
+                                                     &result) == 0)
+                    if (result == 0)
+                      dev_iterate_real (buf, buf);
+              }
+        }
+      grub_free (buf);
+      return;
+    }
+  else if (grub_strcmp (alias->type, "nvme") == 0)
+    {
+      char *buf;
+
+      buf = grub_malloc (IEEE1275_MAX_PATH_LEN);
+
+      if (!buf)
+        return;
+
+      grub_snprintf (buf, IEEE1275_MAX_PATH_LEN, "%s/disk@1", alias->path);
+      dev_iterate_real (buf, buf);
+      grub_free (buf);
+      return;
+    }
+  else if (grub_strcmp (alias->type, "scsi-usb") == 0)
+    {
+      grub_ieee1275_ihandle_t ihandle;
+      grub_ssize_t result;
+
+      ihandle = ofdisk_hba_open (alias->path);
+
+      if (ihandle == 0)
+        return;
 
+      if (grub_ieee1275_set_address (ihandle, 0, 0) == 0)
+        if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur, &result) == 0)
+          if (result == 0)
+            {
+              char *buf, *bufptr;
+
+              buf = grub_malloc (grub_strlen (alias->path) +
+                                 sizeof ("/disk@0"));
+
+              if (!buf)
+                return;
+
+              bufptr = grub_stpcpy (buf, alias->path);
+              grub_snprintf (bufptr, sizeof ("/disk@0"), "/disk@0");
+              dev_iterate_real (buf, buf);
+              grub_free (buf);
+            }
+      return;
+    }
   if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
       && grub_strcmp (alias->type, "block") == 0)
     {
+      if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_IGNORE_REBOOT_DEV)
+          && grub_strstr (alias->path, "reboot-memory"))
+        return;
       dev_iterate_real (alias->path, alias->path);
       return;
     }
@@ -363,6 +546,9 @@ scan (void)
     {
       if (grub_strcmp (alias.type, "block") != 0)
 	continue;
+      if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VALIDATE_DEV_ALIASES) &&
+          sparc_disk_present (alias.path) == 0)
+        continue;
       dev_iterate_real (alias.name, alias.path);
     }
 
@@ -451,6 +637,46 @@ compute_dev_path (const char *name)
   return devpath;
 }
 
+static char *
+get_hbaname_from_path (const char *path)
+{
+  char *sptr, *hba_name;
+
+  hba_name = grub_strdup (path);
+
+  if (!hba_name)
+    return NULL;
+
+  sptr = grub_strstr (hba_name, "/disk@");
+
+  if (!sptr)
+    return NULL;
+
+  *sptr = '\0';
+
+  return hba_name;
+}
+
+static char *
+get_diskname_from_path (const char *path)
+{
+  const char *disk_dev = "/disk@";
+  char *sptr, *disk_name;
+
+  sptr = grub_strstr (path, disk_dev);
+
+  if (!sptr)
+    return NULL;
+
+  disk_name = grub_strdup (sptr + grub_strlen (disk_dev));
+  sptr = grub_strstr (disk_name, ":");
+
+  if (sptr)
+    *sptr = '\0';
+
+  return disk_name;
+}
+
 static grub_err_t
 grub_ofdisk_open (const char *name, grub_disk_t disk)
 {
@@ -508,8 +734,14 @@ grub_ofdisk_open (const char *name, grub
       }
     disk->id = (unsigned long) op;
     disk->data = op->open_path;
+    err = grub_ofdisk_open_real (disk);
+    if (err)
+      {
+        grub_free (devpath);
+        return err;
+      }
 
-    err = grub_ofdisk_get_block_size (devpath, &block_size, op);
+    err = grub_ofdisk_get_block_size (&block_size, op);
     if (err)
       {
         grub_free (devpath);
@@ -534,7 +766,7 @@ grub_ofdisk_close (grub_disk_t disk)
 {
   if (disk->data == last_devpath)
     {
-      if (last_ihandle)
+      if (! (grub_ieee1275_test_flag(GRUB_IEEE1275_FLAG_CACHE_OPEN)) && last_ihandle)
 	grub_ieee1275_close (last_ihandle);
       last_ihandle = 0;
       last_devpath = NULL;
@@ -547,17 +779,13 @@ grub_ofdisk_prepare (grub_disk_t disk, g
 {
   grub_ssize_t status;
   unsigned long long pos;
+  grub_err_t err;
 
   if (disk->data != last_devpath)
     {
-      if (last_ihandle)
-	grub_ieee1275_close (last_ihandle);
-      last_ihandle = 0;
-      last_devpath = NULL;
-
-      grub_ieee1275_open (disk->data, &last_ihandle);
-      if (! last_ihandle)
-	return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
+      err = grub_ofdisk_open_real (disk);
+      if (err)
+        return err;
       last_devpath = disk->data;      
     }
 
@@ -658,6 +886,7 @@ insert_bootpath (void)
       char *device = grub_ieee1275_get_devname (bootpath);
       op = ofdisk_hash_add (device, NULL);
       op->is_boot = 1;
+      grub_free (device);
     }
   grub_free (type);
   grub_free (bootpath);
@@ -685,8 +914,7 @@ grub_ofdisk_init (void)
 }
 
 static grub_err_t
-grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size,
-			    struct ofdisk_hash_ent *op)
+grub_ofdisk_get_block_size (grub_uint32_t *block_size, struct ofdisk_hash_ent *op)
 {
   struct size_args_ieee1275
     {
@@ -698,20 +926,15 @@ grub_ofdisk_get_block_size (const char *
       grub_ieee1275_cell_t size2;
     } args_ieee1275;
 
-  if (last_ihandle)
-    grub_ieee1275_close (last_ihandle);
-
-  last_ihandle = 0;
-  last_devpath = NULL;
-
-  grub_ieee1275_open (device, &last_ihandle);
-  if (! last_ihandle)
-    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
+  if ((op->block_size_retries >= 2) || (op->block_size > 0))
+    {
+      *block_size = op->block_size;
+      return GRUB_ERR_NONE;
+    }
 
   *block_size = 0;
 
-  if (op->block_size_fails >= 2)
-    return GRUB_ERR_NONE;
+  op->block_size_retries++;
 
   INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2);
   args_ieee1275.method = (grub_ieee1275_cell_t) "block-size";
@@ -719,23 +942,193 @@ grub_ofdisk_get_block_size (const char *
   args_ieee1275.result = 1;
 
   if (IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1)
-    {
-      grub_dprintf ("disk", "can't get block size: failed call-method\n");
-      op->block_size_fails++;
-    }
+    grub_dprintf ("disk", "can't get block size: failed call-method\n");
   else if (args_ieee1275.result)
-    {
-      grub_dprintf ("disk", "can't get block size: %lld\n",
-		    (long long) args_ieee1275.result);
-      op->block_size_fails++;
-    }
+    grub_dprintf ("disk", "can't get block size: %lld\n",
+		 (long long) args_ieee1275.result);
   else if (args_ieee1275.size1
 	   && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1))
 	   && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384)
     {
-      op->block_size_fails = 0;
+      op->block_size = args_ieee1275.size1;
       *block_size = args_ieee1275.size1;
     }
 
   return 0;
 }
+
+static grub_err_t
+grub_ofdisk_open_real (grub_disk_t disk)
+{
+  struct ofdisk_hash_ent *op = (struct ofdisk_hash_ent *)disk->id;
+
+  if (!op)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "BUG: can't open device ");
+
+  if (grub_ieee1275_test_flag(GRUB_IEEE1275_FLAG_CACHE_OPEN) && op->ihandle)
+    {
+      last_ihandle = op->ihandle;
+      last_devpath = disk->data;
+      return 0;
+    }
+
+  if (last_ihandle)
+    grub_ieee1275_close (last_ihandle);
+
+  last_ihandle = 0;
+  last_devpath = NULL;
+
+  grub_ieee1275_open (disk->data, &last_ihandle);
+  if (! last_ihandle)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
+
+  op->ihandle = last_ihandle;
+  last_devpath = disk->data;
+  return 0;
+}
+
+static struct ofdisk_hba_ent *
+ofdisk_hba_find (const char *devpath)
+{
+  struct ofdisk_hba_ent *dev = NULL;
+
+  FOR_LIST_ELEMENTS (dev, ofdisk_hba_ents)
+    if (grub_strcmp (dev->path, devpath) == 0)
+      break;
+
+  return dev;
+}
+
+static struct ofdisk_hba_ent *
+ofdisk_hba_add (const char *devpath, grub_ieee1275_ihandle_t ihandle)
+{
+  struct ofdisk_hba_ent *dev;
+
+  dev = grub_zalloc (sizeof (struct ofdisk_hba_ent));
+
+  if (!dev)
+    return NULL;
+
+  dev->path = grub_strdup (devpath);
+
+  if (!dev->path)
+    {
+      grub_free (dev);
+      return NULL;
+    }
+
+  dev->ihandle = ihandle;
+  grub_list_push (GRUB_AS_LIST_P (&ofdisk_hba_ents), GRUB_AS_LIST (dev));
+
+  return dev;
+}
+
+static grub_ieee1275_ihandle_t
+ofdisk_hba_open (const char *hba_name)
+{
+  grub_ieee1275_ihandle_t ihandle;
+  struct ofdisk_hba_ent *dev;
+
+  dev = ofdisk_hba_find (hba_name);
+
+  if (dev)
+    ihandle = dev->ihandle;
+  else if (grub_ieee1275_open (hba_name, &ihandle))
+    ihandle = 0;
+  else
+    {
+      dev = ofdisk_hba_add (hba_name, ihandle);
+
+      if (!dev)
+        ihandle = 0;
+    }
+
+  return ihandle;
+}
+
+static grub_err_t
+sparc_disk_present (const char *full_path)
+{
+  char *disk_name = get_diskname_from_path (full_path);
+  char *hba_name = get_hbaname_from_path (full_path);
+  char *lun_name = NULL, *sptr = NULL, *device_type = 0;
+  grub_ieee1275_ihandle_t ihandle;
+  /* Per SPARC SCSI binding spec, default to 2 for legacy devices that may
+     not have this property */
+  grub_uint32_t address_cells = 2;
+  grub_ieee1275_phandle_t root;
+  grub_uint64_t lun = 0;
+  grub_ssize_t result;
+  grub_err_t rval = GRUB_ERR_NONE;
+
+  if ((!hba_name) || (!disk_name))
+    {
+      grub_free (hba_name);
+      grub_free (disk_name);
+      return GRUB_ERR_NONE;
+    }
+
+  ihandle = ofdisk_hba_open (hba_name);
+
+  if (ihandle == 0)
+    {
+      grub_free (hba_name);
+      grub_free (disk_name);
+      return GRUB_ERR_NONE;
+    }
+
+  sptr = grub_strstr (disk_name, ",");
+
+  if (sptr)
+    {
+      lun_name = grub_strdup (sptr + 1);
+      *sptr = '\0';
+      lun = grub_strtoull (lun_name, 0, 16);
+    }
+
+  grub_ieee1275_finddevice (hba_name, &root);
+  grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
+                                      sizeof address_cells, 0);
+  device_type = grub_ieee1275_get_device_type (hba_name);
+
+  if ((grub_strcmp (device_type, "scsi-2") == 0) ||
+      (grub_strcmp (device_type, "scsi-sas") == 0))
+    {
+      if (address_cells == 4)
+        {
+          if (grub_ieee1275_set_sas_address (ihandle, disk_name, lun) == 0)
+            if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur,
+                                               &result) == 0)
+              if (result == 0)
+                rval = GRUB_ERR_BAD_DEVICE;
+        }
+      else if ((address_cells == 2) && (grub_isxdigit (*disk_name)))
+        {
+          grub_uint32_t tgt;
+          tgt = grub_strtol (disk_name, 0, 16);
+          if (tgt <= 0xff)
+            if (grub_ieee1275_set_address (ihandle, tgt, lun) == 0)
+              if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur,
+                                                 &result) == 0)
+                if (result == 0)
+                  rval = GRUB_ERR_BAD_DEVICE;
+        }
+    }
+  else if (grub_strcmp (device_type, "scsi-usb") == 0)
+    {
+      if (grub_ieee1275_set_address (ihandle, 0, 0) == 0)
+        if (grub_ieee1275_no_data_command (ihandle, &ofdisk_tur, &result) == 0)
+          if (result == 0)
+            rval = GRUB_ERR_BAD_DEVICE;
+    }
+  else
+    {
+      /* ieee1275_finddevice would validate these already */
+      rval = GRUB_ERR_BAD_DEVICE;
+    }
+
+  grub_free (hba_name);
+  grub_free (disk_name);
+  return rval;
+}
+
Index: grub2-2.02~beta3/grub-core/kern/ieee1275/cmain.c
===================================================================
--- grub2-2.02~beta3.orig/grub-core/kern/ieee1275/cmain.c
+++ grub2-2.02~beta3/grub-core/kern/ieee1275/cmain.c
@@ -108,6 +108,14 @@ grub_ieee1275_find_options (void)
   if (rc >= 0)
     {
       char *ptr;
+
+      if (grub_strncmp (tmp, "sun4v", 5) == 0)
+	{
+	  grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CACHE_OPEN);
+	  grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_VALIDATE_DEV_ALIASES);
+	  grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_IGNORE_REBOOT_DEV);
+	}
+
       for (ptr = tmp; ptr - tmp < actual; ptr += grub_strlen (ptr) + 1)
 	{
 	  if (grub_memcmp (ptr, "MacRISC", sizeof ("MacRISC") - 1) == 0
Index: grub2-2.02~beta3/grub-core/kern/ieee1275/ieee1275.c
===================================================================
--- grub2-2.02~beta3.orig/grub-core/kern/ieee1275/ieee1275.c
+++ grub2-2.02~beta3/grub-core/kern/ieee1275/ieee1275.c
@@ -607,3 +607,91 @@ grub_ieee1275_milliseconds (grub_uint32_
   *msecs = args.msecs;
   return 0;
 }
+
+int
+grub_ieee1275_set_address (grub_ieee1275_ihandle_t ihandle,
+                           grub_uint32_t target, grub_uint32_t lun)
+{
+  struct set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t tgt;
+    grub_ieee1275_cell_t lun;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
+
+  /* IEEE Standard for Boot (Initialization Configuration)
+     Firmware: Core Requirements and Practices
+     E.3.2.2 Bus-specific methods for bus nodes
+
+     A package implementing the scsi-2 device type shall implement the
+     following bus-specific method:
+
+     set-address ( unit# target# -- )
+     Sets the SCSI target number (0x0..0xf) and unit number (0..7) to which
+     subsequent commands apply.
+  */
+  args.method = (grub_ieee1275_cell_t) "set-address";
+  args.ihandle = ihandle;
+  args.tgt = target;
+  args.lun = lun;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
+
+int
+grub_ieee1275_no_data_command (grub_ieee1275_ihandle_t ihandle,
+                               const void *cmd_addr, grub_ssize_t *result)
+{
+  struct set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t cmd_addr;
+    grub_ieee1275_cell_t error;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
+  /* IEEE 1275-1994 Standard for Boot (Initialization Configuration)
+     Firmware: Core Requirements and Practices
+
+     E.3.2.2 Bus-specific methods for bus nodes
+
+     A package implementing the scsi-2 device type shall implement the
+     following bus-specific method:
+
+     no-data-command ( cmd-addr -- error? )
+     Executes a simple SCSI command, automatically retrying under
+     certain conditions.  cmd-addr is the address of a 6-byte command buffer
+     containing an SCSI command that does not have a data transfer phase.
+     Executes the command, retrying indefinitely with the same retry criteria
+     as retry-command.
+
+     error? is nonzero if an error occurred, zero otherwise.
+     NOTE no-data-command is a convenience function. It provides
+     no capabilities that are not present in retry-command, but for
+     those commands that meet its restrictions, it is easier to use.
+   */
+  args.method = (grub_ieee1275_cell_t) "no-data-command";
+  args.ihandle = ihandle;
+  args.cmd_addr = (grub_ieee1275_cell_t) cmd_addr;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  if (result)
+    *result = args.error;
+
+  return args.catch_result;
+}
Index: grub2-2.02~beta3/grub-core/kern/parser.c
===================================================================
--- grub2-2.02~beta3.orig/grub-core/kern/parser.c
+++ grub2-2.02~beta3/grub-core/kern/parser.c
@@ -30,7 +30,6 @@ static struct grub_parser_state_transiti
   {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_QUOTE, '\'', 0},
   {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_DQUOTE, '\"', 0},
   {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_VAR, '$', 0},
-  {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_ESC, '\\', 0},
 
   {GRUB_PARSER_STATE_ESC, GRUB_PARSER_STATE_TEXT, 0, 1},
 
Index: grub2-2.02~beta3/grub-core/kern/sparc64/ieee1275/ieee1275.c
===================================================================
--- grub2-2.02~beta3.orig/grub-core/kern/sparc64/ieee1275/ieee1275.c
+++ grub2-2.02~beta3/grub-core/kern/sparc64/ieee1275/ieee1275.c
@@ -18,6 +18,7 @@
 
 #include <grub/ieee1275/ieee1275.h>
 #include <grub/types.h>
+#include <grub/misc.h>
 
 /* Sun specific ieee1275 interfaces used by GRUB.  */
 
@@ -89,3 +90,113 @@ grub_ieee1275_alloc_physmem (grub_addr_t
 
   return args.catch_result;
 }
+
+int
+grub_ieee1275_set_sas_address (grub_ieee1275_ihandle_t ihandle,
+                               const char *disk_name,
+                               grub_uint64_t lun)
+{
+  struct dev_set_address
+  {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_cell_t ihandle;
+    grub_ieee1275_cell_t tgt_h;
+    grub_ieee1275_cell_t tgt_l;
+    grub_ieee1275_cell_t lun_h;
+    grub_ieee1275_cell_t lun_l;
+    grub_ieee1275_cell_t catch_result;
+  }
+  args;
+
+  grub_uint32_t sas_phy = 0, tgt = 0;
+  grub_uint64_t wwn = 0;
+
+  if (disk_name == 0)
+    return -1;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
+  args.method = (grub_ieee1275_cell_t) "set-address";
+  args.ihandle = ihandle;
+  args.lun_l = lun & 0xffffffff;
+  args.lun_h = lun >> 32;
+
+  /* PHY addressing */
+  if (*disk_name == 'p')
+    {
+      /*         Bit #   33222222 22221111 11111100 00000000
+                         10987654 32109876 54321098 76543210
+
+         sas.hi cell:    00000000 00000000 00000000 00000000
+         sas.lo cell:    00000000 00000001 jjjjjjjj iiiiiiii
+         lun.hi cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+         lun.lo cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+
+         00..00          Bits with the value zero
+         ii..ii          8-bit unsigned number phy identifier in the range
+                         of 0..FE .
+         jj..jj          Expander identifier. Either zero (indicating the PHY number
+                         iiiiiiii is on the SAS adapter itself) or identifies the PHY
+                         connecting to the expander, in which case iiiiiiii identifies
+                         a PHY on a SAS expander. In the non-zero case, jjjjjjjj is an
+                         8-bit unsigned number of the PHY plus one, in the range 1..FF
+         uu..uu          64-bit unsigned number logical unit number
+      */
+      sas_phy = grub_strtoul (disk_name + 1, 0, 16);
+      args.tgt_l = 0x10000 | sas_phy;
+      args.tgt_h = 0;
+    }
+  /* WWN addressing */
+  else if ((*disk_name =='w') && (*(disk_name + 1) == '5'))
+    {
+      /*          Bit #   33222222 22221111 11111100 00000000
+                          10987654 32109876 54321098 76543210
+
+          sas.hi cell:    0101vvvv vvvvvvvv vvvvvvvv vvvvssss
+          sas.lo cell:    ssssssss ssssssss ssssssss ssssssss
+          lun.hi cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+          lun.lo cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+
+          0101            The value "5" in the high-order NAA nibble
+          vv..vv          24-bit IEEE Organization ID
+          ss..ss          36-bit unsigned device serial number
+          uu..uu          64-bit unsigned number logical unit number
+      */
+      wwn = grub_strtoull (disk_name + 1, 0, 16);
+      args.tgt_l = wwn & 0xffffffff;
+      args.tgt_h = wwn >> 32;
+    }
+   /* Target LUN addressing */
+   else if (grub_isxdigit (*disk_name))
+    {
+      /* Deprecated
+                  Bit #   33222222 22221111 11111100 00000000
+                          10987654 32109876 54321098 76543210
+
+          sas.hi cell:    00000000 00000000 00000000 00000000
+          sas.lo cell:    00000000 00000000 00000000 tttttttt
+          lun.hi cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+          lun.lo cell:    uuuuuuuu uuuuuuuu uuuuuuuu uuuuuuuu
+
+          00..00          Bits with the value zero
+          tt..tt          8-bit unsigned number target identifier in the range
+                          of 0..FF
+          uu..uu          64-bit unsigned number logical unit number
+      */
+      tgt = grub_strtol (disk_name, 0, 16);
+      if (tgt <= 0xff)
+        {
+          args.tgt_l = tgt;
+          args.tgt_h = 0;
+        }
+      else
+        return -1;
+    }
+  else
+    return -1;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
Index: grub2-2.02~beta3/grub-core/osdep/linux/blocklist.c
===================================================================
--- grub2-2.02~beta3.orig/grub-core/osdep/linux/blocklist.c
+++ grub2-2.02~beta3/grub-core/osdep/linux/blocklist.c
@@ -58,6 +58,11 @@ grub_install_get_blocklist (grub_device_
   struct fiemap fie1;
   int fd;
 
+#ifdef __sparc__
+  if (grub_strstr (container->partmap->name, "gpt"))
+    container_start = 0;
+#endif
+
   /* Write the first two sectors of the core image onto the disk.  */
   grub_util_info ("opening the core image `%s'", core_path);
   fd = open (core_path, O_RDONLY);
Index: grub2-2.02~beta3/grub-core/osdep/linux/ofpath.c
===================================================================
--- grub2-2.02~beta3.orig/grub-core/osdep/linux/ofpath.c
+++ grub2-2.02~beta3/grub-core/osdep/linux/ofpath.c
@@ -38,6 +38,42 @@
 #include <errno.h>
 #include <ctype.h>
 
+typedef enum
+  {
+    GRUB_OFPATH_SPARC_PHY_ADDR = 1,
+    GRUB_OFPATH_SPARC_TGT_LUN,
+  } ofpath_sparc_addressing;
+
+struct ofpath_sparc_hba
+{
+  grub_uint32_t device_id;
+  ofpath_sparc_addressing addressing;
+};
+
+static struct ofpath_sparc_hba sparc_lsi_hba[] = {
+  /* Rhea, Jasper 320, LSI53C1020/1030 */
+  {0x30, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* SAS-1068E */
+  {0x50, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* SAS-1064E */
+  {0x56, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Pandora SAS-1068E */
+  {0x58, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Aspen, Invader, LSI SAS-3108 */
+  {0x5d, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Niwot, SAS 2108 */
+  {0x79, GRUB_OFPATH_SPARC_TGT_LUN},
+  /* Erie, Falcon, LSI SAS 2008 */
+  {0x72, GRUB_OFPATH_SPARC_PHY_ADDR},
+  /* LSI WarpDrive 6203 */
+  {0x7e, GRUB_OFPATH_SPARC_PHY_ADDR},
+  /* LSI SAS 2308 */
+  {0x87, GRUB_OFPATH_SPARC_PHY_ADDR},
+  /* LSI SAS 3008 */
+  {0x97, GRUB_OFPATH_SPARC_PHY_ADDR},
+  {0, 0}
+};
+
 #ifdef OFPATH_STANDALONE
 #define xmalloc malloc
 void
@@ -307,6 +343,49 @@ of_path_of_ide(const char *sys_devname _
   return ret;
 }
 
+static char *
+of_path_of_nvme(const char *sys_devname __attribute__((unused)),
+	        const char *device,
+	        const char *devnode __attribute__((unused)),
+	        const char *devicenode)
+{
+  char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
+  const char *digit_string, *part_end;
+
+  digit_string = trailing_digits (device);
+  part_end = devicenode + strlen (devicenode) - 1;
+
+  if ((digit_string != '\0') && (*part_end == 'p'))
+    {
+      /* We have a partition number, strip it off */
+      int part;
+      char *nvmedev, *end;
+
+      nvmedev = strdup (devicenode);
+
+      if (nvmedev == NULL)
+        return NULL;
+
+      end = nvmedev + strlen (nvmedev) - 1;
+      *end = '\0'; /* remove the p */
+      sscanf (digit_string, "%d", &part);
+      snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+      sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+      free (nvmedev);
+    }
+  else
+    {
+      /* We do not have the parition */
+      snprintf (disk, sizeof (disk), "/disk@1");
+      sysfs_path = block_device_get_sysfs_path_and_link (device);
+    }
+
+  of_path = find_obppath (sysfs_path);
+  free (sysfs_path);
+  strcat (of_path, disk);
+  return of_path;
+}
+
 static int
 vendor_is_ATA(const char *path)
 {
@@ -336,6 +415,85 @@ vendor_is_ATA(const char *path)
 }
 
 static void
+check_hba_identifiers(const char *sysfs_path, int *vendor, int *device_id)
+{
+  char *ed = strstr (sysfs_path, "host");
+  size_t path_size;
+  char *p = NULL, *path = NULL;
+  char buf[8];
+  int fd;
+
+  if (!ed)
+    return;
+
+  p = xstrdup (sysfs_path);
+  ed = strstr (p, "host");
+
+  if (!ed)
+    {
+      free (p);
+      return;
+    }
+  *ed = '\0';
+
+  path_size = (strlen (p) + sizeof("vendor"));
+  path = xmalloc (path_size);
+
+  if (!path)
+    {
+      free (p);
+      return;
+    }
+
+  snprintf (path, path_size, "%svendor", p);
+  fd = open (path, O_RDONLY);
+
+  if (fd < 0)
+    {
+      free (p);
+      free (path);
+      return;
+    }
+
+  memset (buf, 0, sizeof (buf));
+
+  if (read (fd, buf, sizeof (buf) - 1) < 0)
+    {
+      close (fd);
+      free (p);
+      free (path);
+      return;
+    }
+
+  close (fd);
+  sscanf (buf, "%x", vendor);
+  snprintf (path, path_size, "%sdevice", p);
+  fd = open (path, O_RDONLY);
+
+  if (fd < 0)
+    {
+      free (p);
+      free (path);
+      return;
+    }
+
+  memset (buf, 0, sizeof (buf));
+
+  if (read (fd, buf, sizeof (buf) - 1) < 0)
+    {
+      close (fd);
+      free (p);
+      free (path);
+      return;
+    }
+
+  close (fd);
+  sscanf (buf, "%x", device_id);
+  free (path);
+  free (p);
+}
+
+static void
 check_sas (const char *sysfs_path, int *tgt, unsigned long int *sas_address)
 {
   char *ed = strstr (sysfs_path, "end_device");
@@ -413,9 +571,11 @@ of_path_of_scsi(const char *sys_devname
     }
 
   of_path = find_obppath(sysfs_path);
-  free (sysfs_path);
   if (!of_path)
-    return NULL;
+    {
+      free (sysfs_path);
+      return NULL;
+    }
 
   if (strstr (of_path, "qlc"))
     strcat (of_path, "/fp@0,0");
@@ -444,6 +604,44 @@ of_path_of_scsi(const char *sys_devname
     }
   else
     {
+      ofpath_sparc_addressing addressing = GRUB_OFPATH_SPARC_TGT_LUN;
+      int vendor = 0, device_id = 0;
+      char *optr = disk;
+
+      check_hba_identifiers (sysfs_path, &vendor, &device_id);
+
+      /* Over time different OF addressing schemes have been supported */
+      /* There is no generic addressing scheme that works across */
+      /* every HBA */
+      if (vendor == 0x1000) /* LSI Logic Vendor ID */
+        {
+          struct ofpath_sparc_hba *lsi_hba;
+
+          for (lsi_hba = sparc_lsi_hba; lsi_hba->device_id; lsi_hba++)
+            if (lsi_hba->device_id == device_id)
+              {
+                addressing = lsi_hba->addressing;
+                break;
+              }
+        }
+
+      if (addressing == GRUB_OFPATH_SPARC_PHY_ADDR)
+        optr += snprintf (disk, sizeof (disk), "/%s@p%x", disk_name, tgt);
+      else
+        optr += snprintf (disk, sizeof (disk), "/%s@%x", disk_name, tgt);
+
+      if (lun)
+        optr += snprintf (optr, sizeof (disk) - (optr - disk - 1), ",%x", lun);
+
+      if (*digit_string != '\0')
+        {
+          int part;
+
+          sscanf (digit_string, "%d", &part);
+          snprintf (optr, sizeof (disk) - (optr - disk - 1), ":%c", 'a'
+                    + (part - 1));
+        }
+#else
       if (lun == 0)
         {
           int sas_id = 0;
@@ -492,6 +690,7 @@ of_path_of_scsi(const char *sys_devname
 	  free (lunstr);
         }
     }
+  free (sysfs_path);
   strcat(of_path, disk);
   return of_path;
 }
@@ -537,6 +736,9 @@ grub_util_devname_to_ofpath (const char
     /* All the models I've seen have a devalias "floppy".
        New models have no floppy at all. */
     ofpath = xstrdup ("floppy");
+  else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
+           && device[3] == 'e')
+    ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
   else
     {
       grub_util_warn (_("unknown device type %s"), device);
Index: grub2-2.02~beta3/include/grub/emu/getroot.h
===================================================================
--- grub2-2.02~beta3.orig/include/grub/emu/getroot.h
+++ grub2-2.02~beta3/include/grub/emu/getroot.h
@@ -100,5 +100,7 @@ grub_util_guess_baremetal_drive (const c
 void
 grub_util_fprint_full_disk_name (FILE *f,
 				 const char *drive, grub_device_t dev);
+char *
+escape_of_path (const char *orig_path);
 
 #endif /* ! GRUB_UTIL_GETROOT_HEADER */
Index: grub2-2.02~beta3/include/grub/ieee1275/ieee1275.h
===================================================================
--- grub2-2.02~beta3.orig/include/grub/ieee1275/ieee1275.h
+++ grub2-2.02~beta3/include/grub/ieee1275/ieee1275.h
@@ -146,6 +146,12 @@ enum grub_ieee1275_flag
   GRUB_IEEE1275_FLAG_BROKEN_REPEAT,
 
   GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN,
+
+  GRUB_IEEE1275_FLAG_CACHE_OPEN,
+
+  GRUB_IEEE1275_FLAG_VALIDATE_DEV_ALIASES,
+
+  GRUB_IEEE1275_FLAG_IGNORE_REBOOT_DEV,
 };
 
 extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag);
@@ -211,6 +217,13 @@ int EXPORT_FUNC(grub_ieee1275_set_color)
 					  int index, int r, int g, int b);
 int EXPORT_FUNC(grub_ieee1275_milliseconds) (grub_uint32_t *msecs);
 
+int EXPORT_FUNC(grub_ieee1275_set_address) (grub_ieee1275_ihandle_t ihandle,
+                                            grub_uint32_t target,
+                                            grub_uint32_t lun);
+
+int EXPORT_FUNC(grub_ieee1275_no_data_command) (grub_ieee1275_ihandle_t ihandle,
+                                                const void *cmd_addr,
+                                                grub_ssize_t *result);
 
 grub_err_t EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
 
@@ -234,6 +247,14 @@ int EXPORT_FUNC(grub_ieee1275_devalias_n
 void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *alias);
 void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath,
 						struct grub_ieee1275_devalias *alias);
+extern int EXPORT_FUNC(grub_ieee1275_claim_vaddr) (grub_addr_t vaddr,
+						   grub_size_t size);
+extern int EXPORT_FUNC(grub_ieee1275_alloc_physmem) (grub_addr_t *paddr,
+						     grub_size_t size,
+						     grub_uint32_t align);
+extern int EXPORT_FUNC(grub_ieee1275_set_sas_address) (grub_uint32_t ihandle,
+                                                       const char *disk_name,
+                                                       grub_uint64_t lun);
 
 #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));)
 
Index: grub2-2.02~beta3/include/grub/sparc64/ieee1275/ieee1275.h
===================================================================
--- grub2-2.02~beta3.orig/include/grub/sparc64/ieee1275/ieee1275.h
+++ grub2-2.02~beta3/include/grub/sparc64/ieee1275/ieee1275.h
@@ -21,6 +21,7 @@
 #define GRUB_IEEE1275_MACHINE_HEADER	1
 
 #include <grub/types.h>
+#include <grub/ieee1275/ieee1275.h>
 
 #define GRUB_IEEE1275_CELL_SIZEOF 8
 typedef grub_uint64_t grub_ieee1275_cell_t;
@@ -37,12 +38,6 @@ typedef grub_uint64_t grub_ieee1275_cell
 #define IEEE1275_MAP_DEFAULT	(IEEE1275_MAP_WRITE | IEEE1275_MAP_READ | \
 				 IEEE1275_MAP_EXEC | IEEE1275_MAP_CACHED)
 
-extern int EXPORT_FUNC(grub_ieee1275_claim_vaddr) (grub_addr_t vaddr,
-						   grub_size_t size);
-extern int EXPORT_FUNC(grub_ieee1275_alloc_physmem) (grub_addr_t *paddr,
-						     grub_size_t size,
-						     grub_uint32_t align);
-
 extern grub_addr_t EXPORT_VAR (grub_ieee1275_original_stack);
 
 #endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
Index: grub2-2.02~beta3/util/grub-install.c
===================================================================
--- grub2-2.02~beta3.orig/util/grub-install.c
+++ grub2-2.02~beta3/util/grub-install.c
@@ -1494,6 +1494,7 @@ main (int argc, char *argv[])
 	  || grub_drives[1]
 	  || (!install_drive
 	      && platform != GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275)
+	  || (platform == GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275)
 	  || (install_drive && !is_same_disk (grub_drives[0], install_drive))
 	  || !have_bootdev (platform)
 	  || uefi_secure_boot)
@@ -1586,6 +1587,18 @@ main (int argc, char *argv[])
 		    g = grub_util_guess_efi_drive (*curdev);
 		    break;
 		  case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
+		    {
+		      char *dname;
+		      const char *ofpath = grub_util_devname_to_ofpath (*curdev);
+		      g = xasprintf ("ieee1275/%s", ofpath);
+		      dname = escape_of_path (g);
+		      fprintf (load_cfg_f, "%s ", dname);
+		      free (dname);
+		      free (g);
+		      g = NULL;
+		      break;
+		    }
+
 		  case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
 		  case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
 		    {
@@ -1616,6 +1629,7 @@ main (int argc, char *argv[])
 		{
 		  grub_util_fprint_full_disk_name (load_cfg_f, g, dev);
 		  fprintf (load_cfg_f, " ");
+		  free (g);
 		}
 	      if (dev != grub_dev)
 		grub_device_close (dev);
Index: grub2-2.02~beta3/util/ieee1275/grub-ofpathname.c
===================================================================
--- grub2-2.02~beta3.orig/util/ieee1275/grub-ofpathname.c
+++ grub2-2.02~beta3/util/ieee1275/grub-ofpathname.c
@@ -46,7 +46,9 @@ int main(int argc, char **argv)
     }
 
   of_path = grub_util_devname_to_ofpath (argv[1]);
-  printf("%s\n", of_path);
+
+  if (of_path)
+    printf ("%s\n", of_path);
 
   free (of_path);
 
Index: grub2-2.02~beta3/util/probe.c
===================================================================
--- grub2-2.02~beta3.orig/util/probe.c
+++ grub2-2.02~beta3/util/probe.c
@@ -44,7 +44,7 @@
 /* Since OF path names can have "," characters in them, and GRUB
    internally uses "," to indicate partitions (unlike OF which uses
    ":" for this purpose) we escape such commas.  */
-static char *
+char *
 escape_of_path (const char *orig_path)
 {
   char *new_path, *d, c;
Index: grub2-2.02~beta3/util/setup.c
===================================================================
--- grub2-2.02~beta3.orig/util/setup.c
+++ grub2-2.02~beta3/util/setup.c
@@ -729,15 +729,21 @@ unable_to_embed:
   {
     char *buf, *ptr = core_img;
     size_t len = core_size;
-    grub_uint64_t blk;
+    grub_uint64_t blk, offset = 0;
     grub_partition_t container = core_dev->disk->partition;
     grub_err_t err;
 
     core_dev->disk->partition = 0;
+#ifdef GRUB_SETUP_SPARC64
+    {
+      if (grub_strstr (container->partmap->name, "gpt"))
+        offset = grub_partition_get_start (container);
+    }
+#endif
 
     buf = xmalloc (core_size);
     blk = bl.first_sector;
-    err = grub_disk_read (core_dev->disk, blk, 0, GRUB_DISK_SECTOR_SIZE, buf);
+    err = grub_disk_read (core_dev->disk, blk + offset, 0, GRUB_DISK_SECTOR_SIZE, buf);
     if (err)
       grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
 		       grub_errmsg);
@@ -756,7 +762,7 @@ unable_to_embed:
 	if (cur > len)
 	  cur = len;
 
-	err = grub_disk_read (core_dev->disk, blk, 0, cur, buf);
+	err = grub_disk_read (core_dev->disk, blk + offset, 0, cur, buf);
 	if (err)
 	  grub_util_error (_("cannot read `%s': %s"), core_dev->disk->name,
 			   grub_errmsg);
