2ae5c1
From 93a6fae012cadae03cbf81ebf82ae17894026e2c Mon Sep 17 00:00:00 2001
f4c76c
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
f4c76c
Date: Thu, 20 Sep 2012 18:07:39 -0300
2ae5c1
Subject: [PATCH 07/85] IBM client architecture (CAS) reboot support
f4c76c
f4c76c
This is an implementation of IBM client architecture (CAS) reboot for GRUB.
f4c76c
f4c76c
There are cases where the POWER firmware must reboot in order to support
f4c76c
specific features requested by a kernel. The kernel calls
f4c76c
ibm,client-architecture-support and it may either return or reboot with the new
f4c76c
feature set. eg:
f4c76c
f4c76c
Calling ibm,client-architecture-support.../
f4c76c
Elapsed time since release of system processors: 70959 mins 50 secs
f4c76c
Welcome to GRUB!
f4c76c
f4c76c
Instead of return to the GRUB menu, it will check if the flag for CAS reboot is
f4c76c
set. If so, grub will automatically boot the last booted kernel using the same
f4c76c
parameters
f4c76c
---
f4c76c
 grub-core/kern/ieee1275/openfw.c | 62 ++++++++++++++++++++++++++++++++++++++++
f4c76c
 grub-core/normal/main.c          | 19 ++++++++++++
f4c76c
 grub-core/script/execute.c       |  7 +++++
f4c76c
 include/grub/ieee1275/ieee1275.h |  2 ++
f4c76c
 4 files changed, 90 insertions(+)
f4c76c
f4c76c
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
2ae5c1
index 5c12157..81276fa 100644
f4c76c
--- a/grub-core/kern/ieee1275/openfw.c
f4c76c
+++ b/grub-core/kern/ieee1275/openfw.c
2ae5c1
@@ -591,3 +591,65 @@ grub_ieee1275_canonicalise_devname (const char *path)
f4c76c
   return NULL;
f4c76c
 }
f4c76c
 
f4c76c
+/* Check if it's a CAS reboot. If so, set the script to be executed.  */
f4c76c
+int
f4c76c
+grub_ieee1275_cas_reboot (char *script)
f4c76c
+{
f4c76c
+  grub_uint32_t ibm_ca_support_reboot;
f4c76c
+  grub_uint32_t ibm_fw_nbr_reboots;
f4c76c
+  char property_value[10];
f4c76c
+  grub_ssize_t actual;
f4c76c
+  grub_ieee1275_ihandle_t options;
f4c76c
+
f4c76c
+  if (grub_ieee1275_finddevice ("/options", &options) < 0)
f4c76c
+    return -1;
f4c76c
+
f4c76c
+  /* Check two properties, one is enough to get cas reboot value */
f4c76c
+  ibm_ca_support_reboot = 0;
f4c76c
+  if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen,
f4c76c
+                                          "ibm,client-architecture-support-reboot",
f4c76c
+                                          &ibm_ca_support_reboot,
f4c76c
+                                          sizeof (ibm_ca_support_reboot),
f4c76c
+                                          &actual) >= 0)
f4c76c
+    grub_dprintf("ieee1275", "ibm,client-architecture-support-reboot: %u\n",
f4c76c
+                 ibm_ca_support_reboot);
f4c76c
+
f4c76c
+  ibm_fw_nbr_reboots = 0;
f4c76c
+  if (grub_ieee1275_get_property (options, "ibm,fw-nbr-reboots",
f4c76c
+                                  property_value, sizeof (property_value),
f4c76c
+                                  &actual) >= 0)
f4c76c
+    {
f4c76c
+      property_value[sizeof (property_value) - 1] = 0;
f4c76c
+      ibm_fw_nbr_reboots = (grub_uint8_t) grub_strtoul (property_value, 0, 10);
f4c76c
+      grub_dprintf("ieee1275", "ibm,fw-nbr-reboots: %u\n", ibm_fw_nbr_reboots);
f4c76c
+    }
f4c76c
+
f4c76c
+  if (ibm_ca_support_reboot || ibm_fw_nbr_reboots)
f4c76c
+    {
f4c76c
+      if (! grub_ieee1275_get_property_length (options, "boot-last-label", &actual))
f4c76c
+        {
f4c76c
+          if (actual > 1024)
f4c76c
+            script = grub_realloc (script, actual + 1);
f4c76c
+          grub_ieee1275_get_property (options, "boot-last-label", script, actual,
f4c76c
+                                      &actual);
f4c76c
+          return 0;
f4c76c
+        }
f4c76c
+    }
f4c76c
+
f4c76c
+  grub_ieee1275_set_boot_last_label ("");
f4c76c
+
f4c76c
+  return -1;
f4c76c
+}
f4c76c
+
f4c76c
+int grub_ieee1275_set_boot_last_label (const char *text)
f4c76c
+{
f4c76c
+  grub_ieee1275_ihandle_t options;
f4c76c
+  grub_ssize_t actual;
f4c76c
+
f4c76c
+  grub_dprintf("ieee1275", "set boot_last_label (size: %u)\n", grub_strlen(text));
f4c76c
+  if (! grub_ieee1275_finddevice ("/options", &options) &&
f4c76c
+      options != (grub_ieee1275_ihandle_t) -1)
f4c76c
+    grub_ieee1275_set_property (options, "boot-last-label", text,
f4c76c
+                                grub_strlen (text), &actual);
f4c76c
+  return 0;
f4c76c
+}
f4c76c
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
d9747d
index 78a70a8..249e19b 100644
f4c76c
--- a/grub-core/normal/main.c
f4c76c
+++ b/grub-core/normal/main.c
f4c76c
@@ -33,6 +33,9 @@
f4c76c
 #include <grub charset.h="">
f4c76c
 #include <grub script_sh.h="">
f4c76c
 #include <grub bufio.h="">
f4c76c
+#ifdef GRUB_MACHINE_IEEE1275
f4c76c
+#include <grub ieee1275="" ieee1275.h="">
f4c76c
+#endif
f4c76c
 
f4c76c
 GRUB_MOD_LICENSE ("GPLv3+");
f4c76c
 
f4c76c
@@ -275,6 +278,22 @@ grub_normal_execute (const char *config, int nested, int batch)
f4c76c
     {
f4c76c
       menu = read_config_file (config);
f4c76c
 
f4c76c
+#ifdef GRUB_MACHINE_IEEE1275
f4c76c
+      int boot;
f4c76c
+      boot = 0;
f4c76c
+      char *script;
f4c76c
+      script = grub_malloc (1024);
f4c76c
+      if (! grub_ieee1275_cas_reboot (script))
f4c76c
+        {
f4c76c
+          char *dummy[1] = { NULL };
b9efc5
+          if (! grub_script_execute_sourcecode (script))
f4c76c
+            boot = 1;
f4c76c
+        }
f4c76c
+      grub_free (script);
f4c76c
+      if (boot)
f4c76c
+        grub_command_execute ("boot", 0, 0);
f4c76c
+#endif
f4c76c
+
f4c76c
       /* Ignore any error.  */
f4c76c
       grub_errno = GRUB_ERR_NONE;
f4c76c
     }
f4c76c
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
d9747d
index a8502d9..ab78ca8 100644
f4c76c
--- a/grub-core/script/execute.c
f4c76c
+++ b/grub-core/script/execute.c
f4c76c
@@ -27,6 +27,9 @@
f4c76c
 #include <grub normal.h="">
f4c76c
 #include <grub extcmd.h="">
f4c76c
 #include <grub i18n.h="">
f4c76c
+#ifdef GRUB_MACHINE_IEEE1275
f4c76c
+#include <grub ieee1275="" ieee1275.h="">
f4c76c
+#endif
f4c76c
 
f4c76c
 /* Max digits for a char is 3 (0xFF is 255), similarly for an int it
f4c76c
    is sizeof (int) * 3, and one extra for a possible -ve sign.  */
d9747d
@@ -877,6 +880,10 @@ grub_script_execute_sourcecode (const char *source)
f4c76c
   grub_err_t ret = 0;
f4c76c
   struct grub_script *parsed_script;
f4c76c
 
f4c76c
+#ifdef GRUB_MACHINE_IEEE1275
f4c76c
+  grub_ieee1275_set_boot_last_label (source);
f4c76c
+#endif
f4c76c
+
f4c76c
   while (source)
f4c76c
     {
f4c76c
       char *line;
f4c76c
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
2ae5c1
index 6d4e7d5..6a21f5d 100644
f4c76c
--- a/include/grub/ieee1275/ieee1275.h
f4c76c
+++ b/include/grub/ieee1275/ieee1275.h
f4c76c
@@ -234,6 +234,8 @@ int EXPORT_FUNC(grub_ieee1275_devalias_next) (struct grub_ieee1275_devalias *ali
f4c76c
 void EXPORT_FUNC(grub_ieee1275_children_peer) (struct grub_ieee1275_devalias *alias);
f4c76c
 void EXPORT_FUNC(grub_ieee1275_children_first) (const char *devpath,
f4c76c
 						struct grub_ieee1275_devalias *alias);
f4c76c
+int EXPORT_FUNC(grub_ieee1275_cas_reboot) (char *script);
f4c76c
+int EXPORT_FUNC(grub_ieee1275_set_boot_last_label) (const char *text);
2ae5c1
 int EXPORT_FUNC(grub_ieee1275_parse_net_options) (const char *path);
f4c76c
 
f4c76c
 #define FOR_IEEE1275_DEVALIASES(alias) for (grub_ieee1275_devalias_init_iterator (&(alias)); grub_ieee1275_devalias_next (&(alias));)
f4c76c
-- 
b9efc5
2.5.0
f4c76c