dcavalca / rpms / grub2

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