nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone

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

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