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