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