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

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