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

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