Blame SOURCES/0008-IBM-client-architecture-CAS-reboot-support.patch

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