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