Blob Blame History Raw
From: Paulo Flabiano Smorigo  <pfsmorigo@linux.vnet.ibm.com>
Date: Fri, 24 Feb 2012 17:26:02 -0400
Subject: [PATCH] Pull in required v2 changes for PPC
---

diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c
index 2fbe809..9e80757 100644
--- a/grub-core/kern/ieee1275/cmain.c
+++ b/grub-core/kern/ieee1275/cmain.c
@@ -60,6 +60,10 @@ grub_ieee1275_find_options (void)
   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);
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 682a8b5..13a160f 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -69,36 +69,45 @@ grub_translate_ieee1275_path (char *filepath)
 }
 
 void
-grub_machine_set_prefix (void)
+grub_machine_get_bootlocation (char **device, char **path)
 {
   char bootpath[64]; /* XXX check length */
   char *filename;
-  char *prefix;
-
-  if (grub_prefix[0])
-    {
-      grub_env_set ("prefix", grub_prefix);
-      /* Prefix is hardcoded in the core image.  */
-      return;
-    }
-
+  char *type;
+
   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);
+  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;
+
+      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 *newprefix;
       char *lastslash = grub_strrchr (filename, '\\');
 
       /* Truncate at last directory.  */
@@ -107,19 +116,9 @@ grub_machine_set_prefix (void)
 	  *lastslash = '\0';
 	  grub_translate_ieee1275_path (filename);
 
-	  newprefix = grub_xasprintf ("%s%s", prefix, filename);
-	  if (newprefix)
-	    {
-	      grub_free (prefix);
-	      prefix = newprefix;
-	    }
+	  *path = filename;
 	}
     }
-
-  grub_env_set ("prefix", prefix);
-
-  grub_free (filename);
-  grub_free (prefix);
 }
 
 /* Claim some available memory in the first /memory node. */
@@ -192,22 +191,12 @@ static void grub_claim_heap (void)
     grub_machine_mmap_iterate (heap_init);
 }
 
-static grub_uint64_t ieee1275_get_time_ms (void);
-
-void
-grub_machine_init (void)
+static void
+grub_parse_cmdline (void)
 {
-  char args[256];
   grub_ssize_t actual;
+  char args[256];
 
-  grub_ieee1275_init ();
-
-  grub_console_init_early ();
-  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)
@@ -240,6 +229,21 @@ grub_machine_init (void)
 	    }
 	}
     }
+}
+
+static grub_uint64_t ieee1275_get_time_ms (void);
+
+void
+grub_machine_init (void)
+{
+  grub_ieee1275_init ();
+
+  grub_console_init_early ();
+  grub_claim_heap ();
+  grub_console_init_lately ();
+  grub_ofdisk_init ();
+
+  grub_parse_cmdline ();
 
   grub_install_get_time_ms (ieee1275_get_time_ms);
 }
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index f5dc8ef..6aa57ea 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -27,6 +27,8 @@ enum grub_ieee1275_parse_type
 {
   GRUB_PARSE_FILENAME,
   GRUB_PARSE_PARTITION,
+  GRUB_PARSE_DEVICE,
+  GRUB_PARSE_DEVICE_TYPE
 };
 
 /* Walk children of 'devpath', calling hook for each.  */
@@ -317,14 +319,9 @@ 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))
@@ -339,49 +336,93 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype)
       goto fail;
     }
 
-  if (!grub_strcmp ("block", type))
+  switch (ptype)
     {
-      /* The syntax of the device arguments is defined in the CHRP and PReP
-         IEEE1275 bindings: "[partition][,[filename]]".  */
-      char *comma = grub_strchr (args, ',');
+    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;
 
-      if (ptype == GRUB_PARSE_FILENAME)
-	{
-	  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);
+	/* 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);
 	}
-      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>".  */
+      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_printf ("Unsupported type %s for device %s\n", type, device);
     }
 
 fail:
   grub_free (device);
-  grub_free (args);
   return ret;
 }
 
 char *
+grub_ieee1275_get_device_type (const char *path)
+{
+  return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE_TYPE);
+}
+
+char *
+grub_ieee1275_get_aliasdevname (const char *path)
+{
+  return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE);
+}
+
+char *
 grub_ieee1275_get_filename (const char *path)
 {
   return grub_ieee1275_parse_args (path, GRUB_PARSE_FILENAME);
@@ -403,10 +444,10 @@ grub_ieee1275_encode_devname (const char *path)
 	/* GRUB partition 1 is OF partition 0.  */
 	partno++;
 
-      encoding = grub_xasprintf ("(%s,%d)", device, partno);
+      encoding = grub_xasprintf ("%s,%d", device, partno);
     }
   else
-    encoding = grub_xasprintf ("(%s)", device);
+    encoding = grub_xasprintf ("%s", device);
 
   grub_free (partition);
   grub_free (device);
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index da71232..6820f4c 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -129,27 +129,74 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
   return grub_strdup (val);
 }
 
-/* Set the root device according to the dl prefix.  */
 static void
-grub_set_root_dev (void)
+grub_set_prefix_and_root (void)
 {
-  const char *prefix;
+  char *device = NULL;
+  char *path = NULL;
+  char *fwdevice = NULL;
+  char *fwpath = NULL;
 
   grub_register_variable_hook ("root", 0, grub_env_write_root);
 
-  prefix = grub_env_get ("prefix");
-
-  if (prefix)
+  {
+    char *pptr = NULL;
+    if (grub_prefix[0] == '(')
+      {
+	pptr = grub_strrchr (grub_prefix, ')');
+	if (pptr)
+	  {
+	    device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1);
+	    pptr++;
+	  }
+      }
+    if (!pptr)
+      pptr = grub_prefix;
+    if (pptr[0])
+      path = grub_strdup (pptr);
+  }
+  if ((!device || device[0] == ',' || !device[0]) || !path)
+    grub_machine_get_bootlocation (&fwdevice, &fwpath);
+
+  if (!device && fwdevice)
+    device = fwdevice;
+  else if (fwdevice && (device[0] == ',' || !device[0]))
     {
-      char *dev;
+      /* We have a partition, but still need to fill in the drive.  */
+      char *comma, *new_device;
+
+      comma = grub_strchr (fwdevice, ',');
+      if (comma)
+	{
+	  char *drive = grub_strndup (fwdevice, comma - fwdevice);
+	  new_device = grub_xasprintf ("%s%s", drive, device);
+	  grub_free (drive);
+	}
+      else
+	new_device = grub_xasprintf ("%s%s", fwdevice, device);
 
-      dev = grub_file_get_device_name (prefix);
-      if (dev)
+      grub_free (fwdevice);
+      grub_free (device);
+      device = new_device;
+    }
+  if (fwpath && !path)
+    path = fwpath;
+  if (device)
+    {
+      char *prefix;
+
+      prefix = grub_xasprintf ("(%s)%s", device, path ? : "");
+      if (prefix)
 	{
-	  grub_env_set ("root", dev);
-	  grub_free (dev);
+	  grub_env_set ("prefix", prefix);
+	  grub_free (prefix);
 	}
+      grub_env_set ("root", device);
     }
+
+  grub_free (device);
+  grub_free (path);
+  grub_print_error ();
 }
 
 /* Load the normal mode module and execute the normal mode if possible.  */
@@ -159,7 +206,7 @@ grub_load_normal_mode (void)
   /* Load the module.  */
   grub_dl_load ("normal");
 
-  /* Something went wrong.  Print errors here to let user know why we're entering rescue mode.  */
+  /* Print errors if any.  */
   grub_print_error ();
   grub_errno = 0;
 
@@ -187,8 +234,7 @@ grub_main (void)
 
   /* It is better to set the root device as soon as possible,
      for convenience.  */
-  grub_machine_set_prefix ();
-  grub_set_root_dev ();
+  grub_set_prefix_and_root ();
   grub_env_export ("root");
   grub_env_export ("prefix");
 
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index 4c56cc2..fc977f5 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -195,7 +195,8 @@ char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path);
 int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook)
 						(struct grub_ieee1275_devalias *
 						 alias));
-
+char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path);
 char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path);
+char *EXPORT_FUNC(grub_ieee1275_get_device_type) (const char *path);
 
 #endif /* ! GRUB_IEEE1275_HEADER */
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index 2ecc73d..09839de 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -84,7 +84,8 @@ void grub_machine_init (void);
 void EXPORT_FUNC(grub_machine_fini) (void);
 
 /* The machine-specific prefix initialization.  */
-void grub_machine_set_prefix (void);
+void
+grub_machine_get_bootlocation (char **device, char **path);
 
 /* Register all the exported symbols. This is automatically generated.  */
 void grub_register_exported_symbols (void);
diff --git a/util/grub-install.in b/util/grub-install.in
index ff8bea8..cbf1e1e 100644
--- a/util/grub-install.in
+++ b/util/grub-install.in
@@ -271,7 +271,8 @@ if test "x$install_device" = x && ([ "${target_cpu}-${platform}" = "i386-pc" ] \
 fi
 
 if ! ([ "${target_cpu}-${platform}" = "i386-pc" ] \
-    || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then
+    || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] \
+    || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]); then
     install_device=
 fi
 
@@ -522,11 +523,11 @@ if [ "x${devabstraction_module}" = "x" ] ; then
     # Strip partition number
     grub_partition="`echo "${grub_drive}" | sed -e 's/^[^,]*[,)]//; s/)$//'`"
     grub_drive="`echo "${grub_drive}" | sed -e s/,[a-z0-9,]*//g`"
-    if [ "$disk_module" = ata ] || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]) ; then
+    if [ "$disk_module" = ata ] || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${platform}" != x"ieee1275" ]); then
         # generic method (used on coreboot and ata mod)
         uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`"
         if [ "x${uuid}" = "x" ] ; then
-          if [ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]; then
+          if [ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${platform}" != x"ieee1275" ]; then
              echo "UUID needed with $platform, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
           elif [ "$disk_module" = ata ]; then
              echo "UUID needed with ata mod, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
@@ -540,11 +541,12 @@ if [ "x${devabstraction_module}" = "x" ] ; then
 	echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg"
 	config_opt="-c ${grubdir}/load.cfg "
         modules="$modules search_fs_uuid"
-    elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ]; then
+    else
         # we need to hardcode the partition number in the core image's prefix.
 	if [ x"$grub_partition" = x ]; then
             prefix_drive="()"
 	else
+            # Comma is already there
             prefix_drive="(,$grub_partition)"
 	fi
     fi
@@ -612,6 +614,30 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla
 
         # Point boot-device at the new grub install
 	boot_device="$ofpath:$partno,"`"$grub_mkrelpath" "${grubdir}/core.${imgext}" | sed 's,/,\\\\,g'`
+
+        # If a install device is defined, copy the core.elf to PReP partition.
+	if  [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ] \
+	    && [ -n "${install_device}" ]; then
+            if [ "$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t msdos_parttype)" != "41" ]; then
+		echo "The chosen partition is not a PReP partition."
+		exit 1
+            fi
+
+            # Check if device is with an ELF within or is blank
+            if [ "$(file -s "${install_device}" -b | awk '{ print $1 }')" = ELF ] || cmp -s -n $(blockdev --getsize64 ${install_device}) /dev/zero ${install_device} ; then
+            # Change boot device to the harddisk root
+		boot_device="$ofpath"
+		dd if="${grubdir}/core.${imgext}" of="${install_device}" status=noxfer || {
+		    echo "Failed to copy Grub to the PReP partition."
+		    exit 1
+		}
+            else
+		echo "The PReP partition is not empty. If you are sure you want to use it, run dd to clear it:"
+		echo "  dd if=/dev/zero of=${install_device}"
+		exit 1
+            fi
+	fi
+
 	"$nvsetenv" boot-device "$boot_device" || {
 	    echo "$nvsetenv failed."
 	    echo "You will have to set boot-device manually.  At the Open Firmware prompt, type:"
diff --git a/util/grub-probe.c b/util/grub-probe.c
index 0d5dac9..3512a79 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -54,6 +54,7 @@ enum {
   PRINT_DEVICE,
   PRINT_PARTMAP,
   PRINT_ABSTRACTION,
+  PRINT_MSDOS_PARTTYPE
 };
 
 int print = PRINT_FS;
@@ -221,6 +222,17 @@ probe (const char *path, char *device_name)
 	  free (list);
 	  list = tmp;
 	}
+      printf ("\n");
+      goto end;
+    }
+
+  if (print == PRINT_MSDOS_PARTTYPE)
+    {
+      if (dev->disk->partition
+	  && strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
+        printf ("%02x", dev->disk->partition->msdostype);
+
+      printf ("\n");
       goto end;
     }
 
@@ -289,7 +301,7 @@ Probe device information for a given path (or device, if the -d option is given)
 \n\
   -d, --device              given argument is a system device, not a path\n\
   -m, --device-map=FILE     use FILE as the device map [default=%s]\n\
-  -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction)\n\
+  -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|msdos_parttype)\n\
                             print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\
   -h, --help                display this message and exit\n\
   -V, --version             print version information and exit\n\
@@ -348,6 +360,8 @@ main (int argc, char *argv[])
 	      print = PRINT_PARTMAP;
 	    else if (!strcmp (optarg, "abstraction"))
 	      print = PRINT_ABSTRACTION;
+	    else if (!strcmp (optarg, "msdos_parttype"))
+	      print = PRINT_MSDOS_PARTTYPE;
 	    else
 	      usage (1);
 	    break;