[Skiboot] [PATCH v2 5/5] external/opal-prd: Add 'run' option to execute HBRT commands
Neelesh Gupta
neelegup at linux.vnet.ibm.com
Tue Aug 25 05:20:37 AEST 2015
From: Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>
opal-prd client to accept run command and pass it as-is to hbrt.
Example:
opal-prd -d run test hbrt -t 1 -c "good cmd"
argv[0] = test
argv[1] = hbrt
argv[2] = -t
argv[3] = 1
argv[4] = -c
argv[5] = good cmd
Above argc/argv passed to hbrt->run_command() and result out string
sent to the console.
Signed-off-by: Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>
Signed-off-by: Neelesh Gupta <neelegup at linux.vnet.ibm.com>
---
external/opal-prd/hostboot-interface.h | 11 +++
external/opal-prd/opal-prd.c | 117 ++++++++++++++++++++++++++++++++
external/opal-prd/thunk.S | 1
3 files changed, 129 insertions(+)
diff --git a/external/opal-prd/hostboot-interface.h b/external/opal-prd/hostboot-interface.h
index 7ab928f..dc571f3 100644
--- a/external/opal-prd/hostboot-interface.h
+++ b/external/opal-prd/hostboot-interface.h
@@ -456,6 +456,17 @@ struct runtime_interfaces {
int (*htmgt_pass_thru)(uint16_t i_cmdLength, uint8_t *i_cmdData,
uint16_t *o_rspLength, uint8_t *o_rspData);
+ /**
+ * @brief Execute an arbitrary command inside hostboot runtime
+ * @param[in] Number of arguments (standard C args)
+ * @param[in] Array of argument values (standard C args)
+ * @param[out] Response message (NULL terminated), memory allocated
+ * by hbrt, if o_outString is NULL then no response will
+ * be sent
+ * @return 0 on success, else error code
+ */
+ int (*run_command)(int argc, const char **argv, char **o_outString);
+
/* Reserve some space for future growth. */
void (*reserved[32])(void);
};
diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
index 9b9e213..e704199 100644
--- a/external/opal-prd/opal-prd.c
+++ b/external/opal-prd/opal-prd.c
@@ -86,6 +86,7 @@ enum control_msg_type {
CONTROL_MSG_TEMP_OCC_ERROR = 0x03,
CONTROL_MSG_ATTR_OVERRIDE = 0x10,
CONTROL_MSG_HTMGT_PASSTHRU = 0x20,
+ CONTROL_MSG_RUN_CMD = 0x30,
};
struct control_msg {
@@ -227,6 +228,7 @@ extern void call_process_occ_reset(uint64_t i_chipId);
extern int call_htmgt_pass_thru(uint16_t i_cmdLength, uint8_t *i_cmdData,
uint16_t *o_rspLength, uint8_t *o_rspData);
extern int call_apply_attr_override(uint8_t *i_data, size_t size);
+extern int call_run_command(int argc, const char **argv, char **o_outString);
void hservice_puts(const char *str)
{
@@ -1115,6 +1117,57 @@ static void handle_prd_control_htmgt_passthru(struct control_msg *send_msg,
}
}
+static void handle_prd_control_run_cmd(struct control_msg *send_msg,
+ struct control_msg *recv_msg)
+{
+ char *runcmd_output, *s;
+ const char **argv;
+ int i, argc;
+ size_t size;
+
+ if (!hservice_runtime->run_command) {
+ pr_log_nocall("run_command");
+ return;
+ }
+
+ argc = recv_msg->argc;
+ pr_debug("CTRL: run_command, argc:%d\n", argc);
+
+ argv = malloc(argc * sizeof(*argv));
+ if (!argv) {
+ pr_log(LOG_ERR, "CTRL: argv buffer malloc failed: %m");
+ return;
+ }
+
+ s = (char *)recv_msg->data;
+ for (i = 0; i < argc; i++) {
+ argv[i] = (char *)htobe64((uint64_t)&s[size]);
+ size += (strlen(&s[size]) + 1);
+ }
+
+ /* Call HBRT */
+ send_msg->response = call_run_command(argc, argv, &runcmd_output);
+ runcmd_output = (char *)be64toh((uint64_t)runcmd_output);
+ free(argv);
+
+ s = (char *)send_msg->data;
+ if (runcmd_output) {
+ size = strlen(runcmd_output);
+ if (size >= MAX_CONTROL_MSG_BUF) {
+ pr_log(LOG_WARNING, "CTRL: output message truncated");
+ runcmd_output[MAX_CONTROL_MSG_BUF] = '\0';
+ size = MAX_CONTROL_MSG_BUF;
+ }
+
+ strcpy(s, runcmd_output);
+ send_msg->data_len = size + 1;
+ free(runcmd_output);
+ } else {
+ strcpy(s, "Null");
+ send_msg->data_len = strlen("Null") + 1;
+ }
+}
+
static void handle_prd_control(struct opal_prd_ctx *ctx, int fd)
{
struct control_msg msg, *recv_msg, *send_msg;
@@ -1181,6 +1234,9 @@ static void handle_prd_control(struct opal_prd_ctx *ctx, int fd)
case CONTROL_MSG_HTMGT_PASSTHRU:
handle_prd_control_htmgt_passthru(send_msg, recv_msg);
break;
+ case CONTROL_MSG_RUN_CMD:
+ handle_prd_control_run_cmd(send_msg, recv_msg);
+ break;
default:
pr_log(LOG_WARNING, "CTRL: Unknown control message action %d",
recv_msg->type);
@@ -1589,6 +1645,53 @@ static int send_htmgt_passthru(struct opal_prd_ctx *ctx, int argc, char *argv[])
return rc;
}
+static int send_run_command(struct opal_prd_ctx *ctx, int argc, char *argv[])
+{
+ struct control_msg *send_msg, *recv_msg = NULL;
+ uint32_t size = 0;
+ int rc, i;
+ char *s;
+
+ if (ctx->debug) {
+ pr_debug("CTRL: run command arguments:");
+ for (i=0; i < argc; i++)
+ pr_debug("argv[%d] = %s", i, argv[i]);
+ }
+
+ for (i = 0; i < argc; i++)
+ size += (strlen(argv[i]) + 1);
+
+ send_msg = malloc(sizeof(*send_msg) + size);
+ if (!send_msg) {
+ pr_log(LOG_ERR, "CTRL: msg buffer malloc failed: %m");
+ return -1;
+ }
+
+ /* Setup message */
+ send_msg->type = CONTROL_MSG_RUN_CMD;
+ send_msg->argc = argc;
+ send_msg->data_len = size;
+ s = (char *)send_msg->data;
+ for (i = 0; i < argc; i++) {
+ strcpy(s, argv[i]);
+ s = s + strlen(argv[i]) + 1;
+ }
+
+ rc = send_prd_control(send_msg, &recv_msg);
+ free(send_msg);
+ if (recv_msg) {
+ if (!rc)
+ pr_log(LOG_INFO, "Received: %s", recv_msg->data);
+
+ if (recv_msg->response || ctx->debug)
+ pr_debug("CTRL: run command returned status %d",
+ recv_msg->response);
+ free(recv_msg);
+ }
+
+ return rc;
+}
+
static void usage(const char *progname)
{
printf("Usage:\n");
@@ -1598,6 +1701,7 @@ static void usage(const char *progname)
printf("\t%s htmgt-passthru <1st-byte> <2nd byte>..<nth byte>\n",
progname);
printf("\t%s override <binary-blob>\n", progname);
+ printf("\t%s run [arg 0] [arg 1]..[arg n]\n", progname);
printf("\n");
printf("Options:\n"
"\t--debug verbose logging for debug information\n"
@@ -1629,6 +1733,7 @@ enum action {
ACTION_OCC_CONTROL,
ACTION_ATTR_OVERRIDE,
ACTION_HTMGT_PASSTHRU,
+ ACTION_RUN_COMMAND,
};
static int parse_action(const char *str, enum action *action)
@@ -1647,6 +1752,9 @@ static int parse_action(const char *str, enum action *action)
} else if (!strcmp(str, "htmgt-passthru")) {
*action = ACTION_HTMGT_PASSTHRU;
rc = 0;
+ } else if (!strcmp(str, "run")) {
+ *action = ACTION_RUN_COMMAND;
+ return 0;
} else {
pr_log(LOG_ERR, "CTRL: unknown argument '%s'", str);
rc = -1;
@@ -1743,6 +1851,15 @@ int main(int argc, char *argv[])
rc = send_htmgt_passthru(ctx, argc - optind - 1,
&argv[optind + 1]);
break;
+ case ACTION_RUN_COMMAND:
+ if (optind + 1 >= argc) {
+ pr_log(LOG_ERR, "CTRL: run command requires "
+ "argument(s)");
+ return EXIT_FAILURE;
+ }
+
+ rc = send_run_command(ctx, argc - optind - 1, &argv[optind + 1]);
+ break;
default:
break;
}
diff --git a/external/opal-prd/thunk.S b/external/opal-prd/thunk.S
index 3c1a4f3..f259ba2 100644
--- a/external/opal-prd/thunk.S
+++ b/external/opal-prd/thunk.S
@@ -92,6 +92,7 @@ call_##name: ;\
CALL_THUNK(enable_occ_actuation, 11)
CALL_THUNK(apply_attr_override, 12)
CALL_THUNK(htmgt_pass_thru, 13)
+ CALL_THUNK(run_command, 14)
.globl call_hbrt_init
call_hbrt_init:
More information about the Skiboot
mailing list