dcavalca / rpms / grub2

Forked from rpms/grub2 3 years ago
Clone

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

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