|
|
a3f743 |
From ca5cc560f60ebe601b5219699f56f99938895b4b Mon Sep 17 00:00:00 2001
|
|
|
a3f743 |
From: Jim Mankovich <jmank@hp.com>
|
|
|
a3f743 |
Date: Tue, 11 Mar 2014 10:26:43 -0600
|
|
|
a3f743 |
Subject: [PATCH] Add options to chassis bootparam set bootflag
|
|
|
a3f743 |
|
|
|
a3f743 |
|
|
|
a3f743 |
Signed-off-by: Jim Mankovich <jmank@hp.com>
|
|
|
a3f743 |
---
|
|
|
a3f743 |
doc/ipmitool.1 | 39 ++++++++-
|
|
|
a3f743 |
lib/ipmi_chassis.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++----
|
|
|
a3f743 |
2 files changed, 255 insertions(+), 17 deletions(-)
|
|
|
a3f743 |
|
|
|
a3f743 |
diff --git a/doc/ipmitool.1 b/doc/ipmitool.1
|
|
|
a3f743 |
index a73d564..b35eff8 100644
|
|
|
a3f743 |
--- a/doc/ipmitool.1
|
|
|
a3f743 |
+++ b/doc/ipmitool.1
|
|
|
a3f743 |
@@ -2309,14 +2309,16 @@ Get boot parameter. Currently supported values for <\fBparam #\fR> are:
|
|
|
a3f743 |
.br
|
|
|
a3f743 |
|
|
|
a3f743 |
.TP
|
|
|
a3f743 |
-\fIset\fP <\fBoption\fR> [\fBvalue ...\fR]
|
|
|
a3f743 |
+\fIset\fP <\fBdevice\fR> [<\fIoptions\fP=\fBhelp,...\fR>]
|
|
|
a3f743 |
.br
|
|
|
a3f743 |
|
|
|
a3f743 |
-Set boot parameter.
|
|
|
a3f743 |
+Set boot device parameter used for next boot. Various options may be used
|
|
|
a3f743 |
+to change when the the next boot device is cleared.
|
|
|
a3f743 |
+Run \fI"options=help"\fP for a list of available bootparam set device options.
|
|
|
a3f743 |
|
|
|
a3f743 |
.RS
|
|
|
a3f743 |
.TP
|
|
|
a3f743 |
-Currently supported values for \fB<option>\fR are:
|
|
|
a3f743 |
+Currently supported bootparam \fBdevice\fR settings are:
|
|
|
a3f743 |
.TP
|
|
|
a3f743 |
\fIforce_pxe\fP
|
|
|
a3f743 |
.br
|
|
|
a3f743 |
@@ -2349,6 +2351,37 @@ Force boot from CD/DVD
|
|
|
a3f743 |
Force boot into BIOS setup
|
|
|
a3f743 |
|
|
|
a3f743 |
.RE
|
|
|
a3f743 |
+.RS
|
|
|
a3f743 |
+.TP
|
|
|
a3f743 |
+Currently supported bootparam \fBoptions\fR settings are associated with BMC Boot Valid Bit Clearing and are as follows: Any option can be prefixed with "no-" to invert the sense of the operation.
|
|
|
a3f743 |
+.TP
|
|
|
a3f743 |
+\fIPEF\fP
|
|
|
a3f743 |
+.br
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+Clear valid bit on reset/power cycle caused by PEF
|
|
|
a3f743 |
+.TP
|
|
|
a3f743 |
+\fItimeout\fP
|
|
|
a3f743 |
+.br
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+Automatically clear boot flag valid bit if Chassis Control command is
|
|
|
a3f743 |
+not received within 60 seconds.
|
|
|
a3f743 |
+.TP
|
|
|
a3f743 |
+\fIwatchdog\fP
|
|
|
a3f743 |
+.br
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+Clear valid bit on reset/power cycle caused by watchdog timeout
|
|
|
a3f743 |
+.TP
|
|
|
a3f743 |
+\fIreset\fP
|
|
|
a3f743 |
+.br
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+Clear valid bit on push button reset / soft-reset
|
|
|
a3f743 |
+.TP
|
|
|
a3f743 |
+\fIpower\fP
|
|
|
a3f743 |
+.br
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+Clear valid bit on power up via power push button or wake event
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+.RE
|
|
|
a3f743 |
.RE
|
|
|
a3f743 |
.RE
|
|
|
a3f743 |
.RE
|
|
|
a3f743 |
diff --git a/lib/ipmi_chassis.c b/lib/ipmi_chassis.c
|
|
|
a3f743 |
index 2d47974..d4e88ee 100644
|
|
|
a3f743 |
--- a/lib/ipmi_chassis.c
|
|
|
a3f743 |
+++ b/lib/ipmi_chassis.c
|
|
|
a3f743 |
@@ -755,6 +755,193 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
|
|
|
a3f743 |
}
|
|
|
a3f743 |
|
|
|
a3f743 |
static int
|
|
|
a3f743 |
+get_bootparam_options(char *optstring,
|
|
|
a3f743 |
+ unsigned char *set_flag, unsigned char *clr_flag)
|
|
|
a3f743 |
+{
|
|
|
a3f743 |
+ char *token;
|
|
|
a3f743 |
+ char *saveptr = NULL;
|
|
|
a3f743 |
+ int optionError = 0;
|
|
|
a3f743 |
+ *set_flag = 0;
|
|
|
a3f743 |
+ *clr_flag = 0;
|
|
|
a3f743 |
+ static struct {
|
|
|
a3f743 |
+ char *name;
|
|
|
a3f743 |
+ unsigned char value;
|
|
|
a3f743 |
+ char *desc;
|
|
|
a3f743 |
+ } options[] = {
|
|
|
a3f743 |
+ {"PEF", 0x10,
|
|
|
a3f743 |
+ "Clear valid bit on reset/power cycle cause by PEF"},
|
|
|
a3f743 |
+ {"timeout", 0x08,
|
|
|
a3f743 |
+ "Automatically clear boot flag valid bit on timeout"},
|
|
|
a3f743 |
+ {"watchdog", 0x04,
|
|
|
a3f743 |
+ "Clear valid bit on reset/power cycle cause by watchdog"},
|
|
|
a3f743 |
+ {"reset", 0x02,
|
|
|
a3f743 |
+ "Clear valid bit on push button reset/soft reset"},
|
|
|
a3f743 |
+ {"power", 0x01,
|
|
|
a3f743 |
+ "Clear valid bit on power up via power push button or wake event"},
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ {NULL} /* End marker */
|
|
|
a3f743 |
+ }, *op;
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ if (strncmp(optstring, "options=", 8) != 0) {
|
|
|
a3f743 |
+ lprintf(LOG_ERR, "No options= keyword found \"%s\"", optstring);
|
|
|
a3f743 |
+ return -1;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ token = strtok_r(optstring + 8, ",", &saveptr);
|
|
|
a3f743 |
+ while (token != NULL) {
|
|
|
a3f743 |
+ int setbit = 0;
|
|
|
a3f743 |
+ if (strcmp(token, "help") == 0) {
|
|
|
a3f743 |
+ optionError = 1;
|
|
|
a3f743 |
+ break;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ if (strncmp(token, "no-", 3) == 0) {
|
|
|
a3f743 |
+ setbit = 1;
|
|
|
a3f743 |
+ token += 3;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ for (op = options; op->name != NULL; ++op) {
|
|
|
a3f743 |
+ if (strncmp(token, op->name, strlen(op->name)) == 0) {
|
|
|
a3f743 |
+ if (setbit) {
|
|
|
a3f743 |
+ *set_flag |= op->value;
|
|
|
a3f743 |
+ } else {
|
|
|
a3f743 |
+ *clr_flag |= op->value;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ break;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ if (op->name == NULL) {
|
|
|
a3f743 |
+ /* Option not found */
|
|
|
a3f743 |
+ optionError = 1;
|
|
|
a3f743 |
+ if (setbit) {
|
|
|
a3f743 |
+ token -=3;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ lprintf(LOG_ERR, "Invalid option: %s", token);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ token = strtok_r(NULL, ",", &saveptr);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ if (optionError) {
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " Legal options are:");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " %-8s: print this message", "help");
|
|
|
a3f743 |
+ for (op = options; op->name != NULL; ++op) {
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " %-8s: %s", op->name, op->desc);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " Any Option may be prepended with no-"
|
|
|
a3f743 |
+ " to invert sense of operation\n");
|
|
|
a3f743 |
+ return (-1);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ return (0);
|
|
|
a3f743 |
+}
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+static int
|
|
|
a3f743 |
+ipmi_chassis_get_bootvalid(struct ipmi_intf * intf)
|
|
|
a3f743 |
+{
|
|
|
a3f743 |
+ struct ipmi_rs * rsp;
|
|
|
a3f743 |
+ struct ipmi_rq req;
|
|
|
a3f743 |
+ uint8_t msg_data[3];
|
|
|
a3f743 |
+ uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID;
|
|
|
a3f743 |
+ memset(msg_data, 0, 3);
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ msg_data[0] = param_id & 0x7f;
|
|
|
a3f743 |
+ msg_data[1] = 0;
|
|
|
a3f743 |
+ msg_data[2] = 0;
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ memset(&req, 0, sizeof(req));
|
|
|
a3f743 |
+ req.msg.netfn = IPMI_NETFN_CHASSIS;
|
|
|
a3f743 |
+ req.msg.cmd = 0x9;
|
|
|
a3f743 |
+ req.msg.data = msg_data;
|
|
|
a3f743 |
+ req.msg.data_len = 3;
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ rsp = intf->sendrecv(intf, &req;;
|
|
|
a3f743 |
+ if (rsp == NULL) {
|
|
|
a3f743 |
+ lprintf(LOG_ERR,
|
|
|
a3f743 |
+ "Error Getting Chassis Boot Parameter %d", param_id);
|
|
|
a3f743 |
+ return -1;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ if (rsp->ccode > 0) {
|
|
|
a3f743 |
+ lprintf(LOG_ERR, "Get Chassis Boot Parameter %d failed: %s",
|
|
|
a3f743 |
+ param_id, val2str(rsp->ccode, completion_code_vals));
|
|
|
a3f743 |
+ return -1;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ if (verbose > 2)
|
|
|
a3f743 |
+ printbuf(rsp->data, rsp->data_len, "Boot Option");
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ return(rsp->data[2]);
|
|
|
a3f743 |
+}
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+static int
|
|
|
a3f743 |
+ipmi_chassis_set_bootvalid(struct ipmi_intf *intf, uint8_t set_flag, uint8_t clr_flag)
|
|
|
a3f743 |
+{
|
|
|
a3f743 |
+ int bootvalid;
|
|
|
a3f743 |
+ uint8_t flags[5];
|
|
|
a3f743 |
+ int rc = 0;
|
|
|
a3f743 |
+ int use_progress = 1;
|
|
|
a3f743 |
+ uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID;
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ if (use_progress) {
|
|
|
a3f743 |
+ /* set set-in-progress flag */
|
|
|
a3f743 |
+ memset(flags, 0, 5);
|
|
|
a3f743 |
+ flags[0] = 0x01;
|
|
|
a3f743 |
+ rc = ipmi_chassis_set_bootparam(intf,
|
|
|
a3f743 |
+ IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1);
|
|
|
a3f743 |
+ if (rc < 0)
|
|
|
a3f743 |
+ use_progress = 0;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ memset(flags, 0, 5);
|
|
|
a3f743 |
+ flags[0] = 0x01;
|
|
|
a3f743 |
+ flags[1] = 0x01;
|
|
|
a3f743 |
+ rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
|
|
|
a3f743 |
+ flags, 2);
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ if (rc < 0) {
|
|
|
a3f743 |
+ if (use_progress) {
|
|
|
a3f743 |
+ /* set-in-progress = set-complete */
|
|
|
a3f743 |
+ memset(flags, 0, 5);
|
|
|
a3f743 |
+ ipmi_chassis_set_bootparam(intf,
|
|
|
a3f743 |
+ IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
|
|
|
a3f743 |
+ flags, 1);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ return -1;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ bootvalid = ipmi_chassis_get_bootvalid(intf);
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ if (bootvalid < 0) {
|
|
|
a3f743 |
+ if (use_progress) {
|
|
|
a3f743 |
+ /* set-in-progress = set-complete */
|
|
|
a3f743 |
+ memset(flags, 0, 5);
|
|
|
a3f743 |
+ ipmi_chassis_set_bootparam(intf,
|
|
|
a3f743 |
+ IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
|
|
|
a3f743 |
+ flags, 1);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ return -1;
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ flags[0] = (bootvalid & ~clr_flag) | set_flag;
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ rc = ipmi_chassis_set_bootparam(intf, param_id, flags, 1);
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ if (rc == 0) {
|
|
|
a3f743 |
+ if (use_progress) {
|
|
|
a3f743 |
+ /* set-in-progress = commit-write */
|
|
|
a3f743 |
+ memset(flags, 0, 5);
|
|
|
a3f743 |
+ flags[0] = 0x02;
|
|
|
a3f743 |
+ ipmi_chassis_set_bootparam(intf,
|
|
|
a3f743 |
+ IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
|
|
|
a3f743 |
+ flags, 1);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ if (use_progress) {
|
|
|
a3f743 |
+ /* set-in-progress = set-complete */
|
|
|
a3f743 |
+ memset(flags, 0, 5);
|
|
|
a3f743 |
+ ipmi_chassis_set_bootparam(intf,
|
|
|
a3f743 |
+ IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
|
|
|
a3f743 |
+ flags, 1);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+ return rc;
|
|
|
a3f743 |
+}
|
|
|
a3f743 |
+
|
|
|
a3f743 |
+static int
|
|
|
a3f743 |
ipmi_chassis_set_bootdev(struct ipmi_intf * intf, char * arg, uint8_t *iflags)
|
|
|
a3f743 |
{
|
|
|
a3f743 |
uint8_t flags[5];
|
|
|
a3f743 |
@@ -946,6 +1133,23 @@ ipmi_power_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
|
a3f743 |
return rc;
|
|
|
a3f743 |
}
|
|
|
a3f743 |
|
|
|
a3f743 |
+void
|
|
|
a3f743 |
+ipmi_chassis_set_bootflag_help()
|
|
|
a3f743 |
+{
|
|
|
a3f743 |
+ unsigned char set_flag;
|
|
|
a3f743 |
+ unsigned char clr_flag;
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, "bootparam set bootflag <device> [options=...]");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " Legal devices are:");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " none : No override");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " force_pxe : Force PXE boot");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " force_disk : Force boot from default Hard-drive");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " force_safe : Force boot from default Hard-drive, request Safe Mode");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " force_diag : Force boot from Diagnostic Partition");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " force_cdrom : Force boot from CD/DVD");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, " force_bios : Force boot into BIOS Setup");
|
|
|
a3f743 |
+ get_bootparam_options("options=help", &set_flag, &clr_flag);
|
|
|
a3f743 |
+}
|
|
|
a3f743 |
+
|
|
|
a3f743 |
int
|
|
|
a3f743 |
ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
|
a3f743 |
{
|
|
|
a3f743 |
@@ -1036,26 +1240,27 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
|
a3f743 |
else if (strncmp(argv[0], "bootparam", 9) == 0) {
|
|
|
a3f743 |
if ((argc < 3) || (strncmp(argv[1], "help", 4) == 0)) {
|
|
|
a3f743 |
lprintf(LOG_NOTICE, "bootparam get <param #>");
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, "bootparam set bootflag <flag>");
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, " force_pxe : Force PXE boot");
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, " force_disk : Force boot from default Hard-drive");
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, " force_safe : Force boot from default Hard-drive, request Safe Mode");
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, " force_diag : Force boot from Diagnostic Partition");
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, " force_cdrom : Force boot from CD/DVD");
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, " force_bios : Force boot into BIOS Setup");
|
|
|
a3f743 |
+ ipmi_chassis_set_bootflag_help();
|
|
|
a3f743 |
}
|
|
|
a3f743 |
else {
|
|
|
a3f743 |
if (strncmp(argv[1], "get", 3) == 0) {
|
|
|
a3f743 |
rc = ipmi_chassis_get_bootparam(intf, argv[2]);
|
|
|
a3f743 |
}
|
|
|
a3f743 |
else if (strncmp(argv[1], "set", 3) == 0) {
|
|
|
a3f743 |
- if (argc < 4) {
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, "bootparam set <option> [value ...]");
|
|
|
a3f743 |
+ unsigned char set_flag=0;
|
|
|
a3f743 |
+ unsigned char clr_flag=0;
|
|
|
a3f743 |
+ if (strncmp(argv[2], "help", 4) == 0 ||
|
|
|
a3f743 |
+ argc < 4 || (argc >= 4 &&
|
|
|
a3f743 |
+ strncmp(argv[2], "bootflag", 8) != 0)) {
|
|
|
a3f743 |
+ ipmi_chassis_set_bootflag_help();
|
|
|
a3f743 |
} else {
|
|
|
a3f743 |
- if (strncmp(argv[2], "bootflag", 8) == 0)
|
|
|
a3f743 |
- rc = ipmi_chassis_set_bootdev(intf, argv[3], NULL);
|
|
|
a3f743 |
- else
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, "bootparam set <option> [value ...]");
|
|
|
a3f743 |
+ if (argc == 5) {
|
|
|
a3f743 |
+ get_bootparam_options(argv[4], &set_flag, &clr_flag);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
+ rc = ipmi_chassis_set_bootdev(intf, argv[3], NULL);
|
|
|
a3f743 |
+ if (argc == 5 && (set_flag != 0 || clr_flag != 0)) {
|
|
|
a3f743 |
+ rc = ipmi_chassis_set_bootvalid(intf, set_flag, clr_flag);
|
|
|
a3f743 |
+ }
|
|
|
a3f743 |
}
|
|
|
a3f743 |
}
|
|
|
a3f743 |
else
|
|
|
a3f743 |
@@ -1166,7 +1371,7 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
|
a3f743 |
token = strtok_r(NULL, ",", &saveptr);
|
|
|
a3f743 |
}
|
|
|
a3f743 |
if (optionError) {
|
|
|
a3f743 |
- lprintf(LOG_NOTICE, "Legal options are:");
|
|
|
a3f743 |
+ lprintf(LOG_NOTICE, "Legal options settings are:");
|
|
|
a3f743 |
lprintf(LOG_NOTICE, "\thelp:\tprint this message");
|
|
|
a3f743 |
for (op = options; op->name != NULL; ++op) {
|
|
|
a3f743 |
lprintf(LOG_NOTICE, "\t%s:\t%s", op->name, op->desc);
|
|
|
a3f743 |
--
|
|
|
a3f743 |
1.7.9.5
|
|
|
a3f743 |
|