a5bd9f6
From 057b6211bfba83caa9af3276fbbf8902cd1082a2 Mon Sep 17 00:00:00 2001
f2e5630
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
f2e5630
Date: Thu, 20 Sep 2012 18:07:39 -0300
a5bd9f6
Subject: [PATCH 354/364] IBM client architecture (CAS) reboot support
f2e5630
f2e5630
This is an implementation of IBM client architecture (CAS) reboot for GRUB.
f2e5630
f2e5630
There are cases where the POWER firmware must reboot in order to support
f2e5630
specific features requested by a kernel. The kernel calls
f2e5630
ibm,client-architecture-support and it may either return or reboot with the new
f2e5630
feature set. eg:
f2e5630
f2e5630
Calling ibm,client-architecture-support.../
f2e5630
Elapsed time since release of system processors: 70959 mins 50 secs
f2e5630
Welcome to GRUB!
f2e5630
f2e5630
Instead of return to the GRUB menu, it will check if the flag for CAS reboot is
f2e5630
set. If so, grub will automatically boot the last booted kernel using the same
f2e5630
parameters
f2e5630
---
a5bd9f6
 grub-core/kern/ieee1275/openfw.c | 63 ++++++++++++++++++++++++++++++++++++++++
a5bd9f6
 grub-core/normal/main.c          | 19 ++++++++++++
a5bd9f6
 grub-core/script/execute.c       |  7 +++++
a5bd9f6
 include/grub/ieee1275/ieee1275.h |  2 ++
f2e5630
 4 files changed, 91 insertions(+)
f2e5630
f2e5630
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
a5bd9f6
index 07c90f7..09e9e57 100644
f2e5630
--- a/grub-core/kern/ieee1275/openfw.c
f2e5630
+++ b/grub-core/kern/ieee1275/openfw.c
a5bd9f6
@@ -561,3 +561,66 @@ grub_ieee1275_canonicalise_devname (const char *path)
f2e5630
   return NULL;
f2e5630
 }
f2e5630
 
f2e5630
+/* Check if it's a CAS reboot. If so, set the script to be executed.  */
f2e5630
+int
f2e5630
+grub_ieee1275_cas_reboot (char *script)
f2e5630
+{
f2e5630
+  grub_uint32_t ibm_ca_support_reboot;
f2e5630
+  grub_uint32_t ibm_fw_nbr_reboots;
f2e5630
+  char property_value[10];
f2e5630
+  grub_ssize_t actual;
f2e5630
+  grub_ieee1275_ihandle_t options;
f2e5630
+
f2e5630
+  if (grub_ieee1275_finddevice ("/options", &options) < 0)
f2e5630
+    return -1;
f2e5630
+
f2e5630
+  /* Check two properties, one is enough to get cas reboot value */
f2e5630
+  ibm_ca_support_reboot = 0;
f2e5630
+  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen,
f2e5630
+                                          "ibm,client-architecture-support-reboot",
f2e5630
+                                          &ibm_ca_support_reboot,
f2e5630
+                                          sizeof (ibm_ca_support_reboot),
f2e5630
+                                          &actual) >= 0)
f2e5630
+    grub_dprintf("ieee1275", "ibm,client-architecture-support-reboot: %u\n",
f2e5630
+                 ibm_ca_support_reboot);
f2e5630
+
f2e5630
+  ibm_fw_nbr_reboots = 0;
f2e5630
+  if (grub_ieee1275_get_property (options, "ibm,fw-nbr-reboots",
f2e5630
+                                  property_value, sizeof (property_value),
f2e5630
+                                  &actual) >= 0)
f2e5630
+    {
f2e5630
+      property_value[sizeof (property_value) - 1] = 0;
f2e5630
+      ibm_fw_nbr_reboots = (grub_uint8_t) grub_strtoul (property_value, 0, 10);
f2e5630
+      grub_dprintf("ieee1275", "ibm,fw-nbr-reboots: %u\n", ibm_fw_nbr_reboots);
f2e5630
+    }
f2e5630
+
f2e5630
+  if (ibm_ca_support_reboot || ibm_fw_nbr_reboots)
f2e5630
+    {
f2e5630
+      if (! grub_ieee1275_get_property_length (options, "boot-last-label", &actual))
f2e5630
+        {
f2e5630
+          if (actual > 1024)
f2e5630
+            script = grub_realloc (script, actual + 1);
f2e5630
+          grub_ieee1275_get_property (options, "boot-last-label", script, actual,
f2e5630
+                                      &actual);
f2e5630
+          return 0;
f2e5630
+        }
f2e5630
+    }
f2e5630
+
f2e5630
+  grub_ieee1275_set_boot_last_label ("");
f2e5630
+
f2e5630
+  return -1;
f2e5630
+}
f2e5630
+
f2e5630
+int grub_ieee1275_set_boot_last_label (const char *text)
f2e5630
+{
f2e5630
+  grub_ieee1275_ihandle_t options;
f2e5630
+  grub_ssize_t actual;
f2e5630
+
f2e5630
+  grub_dprintf("ieee1275", "set boot_last_label (size: %u)\n", grub_strlen(text));
f2e5630
+  if (! grub_ieee1275_finddevice ("/options", &options) &&
f2e5630
+      options != (grub_ieee1275_ihandle_t) -1)
f2e5630
+    grub_ieee1275_set_property (options, "boot-last-label", text,
f2e5630
+                                grub_strlen (text), &actual);
f2e5630
+  return 0;
f2e5630
+}
f2e5630
+
f2e5630
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
a5bd9f6
index ea8cd53..1f14826 100644
f2e5630
--- a/grub-core/normal/main.c
f2e5630
+++ b/grub-core/normal/main.c
f2e5630
@@ -32,6 +32,9 @@
f2e5630
 #include <grub/i18n.h>
f2e5630
 #include <grub/charset.h>
f2e5630
 #include <grub/script_sh.h>
f2e5630
+#ifdef GRUB_MACHINE_IEEE1275
f2e5630
+#include <grub/ieee1275/ieee1275.h>
f2e5630
+#endif
f2e5630
 
f2e5630
 GRUB_MOD_LICENSE ("GPLv3+");
f2e5630
 
a5bd9f6
@@ -302,6 +305,22 @@ grub_normal_execute (const char *config, int nested, int batch)
f2e5630
     {
f2e5630
       menu = read_config_file (config);
f2e5630
 
f2e5630
+#ifdef GRUB_MACHINE_IEEE1275
f2e5630
+      int boot;
f2e5630
+      boot = 0;
f2e5630
+      char *script;
f2e5630
+      script = grub_malloc (1024);
f2e5630
+      if (! grub_ieee1275_cas_reboot (script))
f2e5630
+        {
f2e5630
+          char *dummy[1] = { NULL };
f2e5630
+          if (! grub_script_execute_sourcecode (script, 0, dummy))
f2e5630
+            boot = 1;
f2e5630
+        }
f2e5630
+      grub_free (script);
f2e5630
+      if (boot)
f2e5630
+        grub_command_execute ("boot", 0, 0);
f2e5630
+#endif
f2e5630
+
f2e5630
       /* Ignore any error.  */
f2e5630
       grub_errno = GRUB_ERR_NONE;
f2e5630
     }
f2e5630
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
a5bd9f6
index 686e1fa..7dcdab7 100644
f2e5630
--- a/grub-core/script/execute.c
f2e5630
+++ b/grub-core/script/execute.c
f2e5630
@@ -27,6 +27,9 @@
f2e5630
 #include <grub/normal.h>
f2e5630
 #include <grub/extcmd.h>
f2e5630
 #include <grub/i18n.h>
f2e5630
+#ifdef GRUB_MACHINE_IEEE1275
f2e5630
+#include <grub/ieee1275/ieee1275.h>
f2e5630
+#endif
f2e5630
 
f2e5630
 /* Max digits for a char is 3 (0xFF is 255), similarly for an int it
f2e5630
    is sizeof (int) * 3, and one extra for a possible -ve sign.  */
a5bd9f6
@@ -872,6 +875,10 @@ grub_script_execute_sourcecode (const char *source, int argc, char **args)
f2e5630
   old_scope = scope;
f2e5630
   scope = &new_scope;
f2e5630
 
f2e5630
+#ifdef GRUB_MACHINE_IEEE1275
f2e5630
+  grub_ieee1275_set_boot_last_label (source);
f2e5630
+#endif
f2e5630
+
f2e5630
   while (source)
f2e5630
     {
f2e5630
       char *line;
f2e5630
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
a5bd9f6
index 1b240d3..eabbe9b 100644
f2e5630
--- a/include/grub/ieee1275/ieee1275.h
f2e5630
+++ b/include/grub/ieee1275/ieee1275.h
a5bd9f6
@@ -227,6 +227,8 @@ int EXPORT_FUNC(grub_ieee1275_devalias_next) (struct grub_ieee1275_devalias *ali
a5bd9f6
 void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *alias);
a5bd9f6
 void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath,
a5bd9f6
 						struct grub_ieee1275_devalias *alias);
f2e5630
+int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script);
f2e5630
+int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text);
f2e5630
 
a5bd9f6
 #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));)
a5bd9f6
 
f2e5630
-- 
a5bd9f6
1.8.1.4
f2e5630