From patchwork Wed Aug 12 16:06:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neelesh Gupta X-Patchwork-Id: 506691 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6912E14018C for ; Thu, 13 Aug 2015 02:07:32 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 436591A1DF9 for ; Thu, 13 Aug 2015 02:07:32 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e23smtp03.au.ibm.com (e23smtp03.au.ibm.com [202.81.31.145]) (using TLSv1 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id F35471A1DB3 for ; Thu, 13 Aug 2015 02:07:28 +1000 (AEST) Received: from /spool/local by e23smtp03.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 13 Aug 2015 02:07:27 +1000 Received: from d23dlp03.au.ibm.com (202.81.31.214) by e23smtp03.au.ibm.com (202.81.31.209) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 13 Aug 2015 02:07:26 +1000 X-Helo: d23dlp03.au.ibm.com X-MailFrom: neelegup@linux.vnet.ibm.com X-RcptTo: skiboot@lists.ozlabs.org Received: from d23relay10.au.ibm.com (d23relay10.au.ibm.com [9.190.26.77]) by d23dlp03.au.ibm.com (Postfix) with ESMTP id BEC663578055 for ; Thu, 13 Aug 2015 02:07:25 +1000 (EST) Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay10.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t7CG7HDY49938494 for ; Thu, 13 Aug 2015 02:07:25 +1000 Received: from d23av01.au.ibm.com (localhost [127.0.0.1]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t7CG6rL2015541 for ; Thu, 13 Aug 2015 02:06:53 +1000 Received: from localhost.localdomain ([9.124.88.220]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t7CG6nl6015321; Thu, 13 Aug 2015 02:06:50 +1000 From: Neelesh Gupta To: skiboot@lists.ozlabs.org Date: Wed, 12 Aug 2015 21:36:32 +0530 Message-ID: <20150812160621.28758.3965.stgit@localhost.localdomain> In-Reply-To: <20150812155923.28758.96941.stgit@localhost.localdomain> References: <20150812155923.28758.96941.stgit@localhost.localdomain> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15081216-0009-0000-0000-000001E3FD52 Subject: [Skiboot] [PATCH v1 5/5] external/opal-prd: opal-prd to support htmgt passthru and attribute override X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dcrowell@us.ibm.com, whs@us.ibm.com, cjcain@us.ibm.com Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This patch adds the support for htmgt passthru and attribute override commands. The command format would like something as below: # opal-prd occ passthru 0x10 0x11 0xac It will pass the arguments after 'passthru' in an array as input data to hbrt->htmgt_pass_thru(). The HBRT will return the output data to a buffer provided by 'opal-prd' of maximum length 256 bytes. # opal-prd override It will read the contents of the binary blob into a buffer and invoke hbrt->apply_attr_override() with the buffer and size as the input to the interface. Signed-off-by: Neelesh Gupta --- external/opal-prd/hostboot-interface.h | 35 +++++ external/opal-prd/opal-prd.c | 215 ++++++++++++++++++++++++++++---- external/opal-prd/thunk.S | 2 3 files changed, 228 insertions(+), 24 deletions(-) diff --git a/external/opal-prd/hostboot-interface.h b/external/opal-prd/hostboot-interface.h index d186819..31aa6eb 100644 --- a/external/opal-prd/hostboot-interface.h +++ b/external/opal-prd/hostboot-interface.h @@ -422,6 +422,41 @@ struct runtime_interfaces { int (*enable_occ_actuation)(bool i_occActivation); /** + * @brief Apply a set of attribute overrides + * + * @param[in] pointer to binary override data + * @param[in] length of override data (bytes) + * @returns 0 on success, or return code if the command failed + * + * @platform OpenPower + */ + int (*apply_attr_override)(uint8_t *i_data, size_t size); + + /** + * @brief Send a pass-through command to HTMGT + * + * @details This is a blocking call that will send a command to + * HTMGT. + * + * @note If o_rspLength is returned with a non-zero value, the + * data at the o_rspData should be dumped to stdout in a + * hex dump format. + * @note The maximum response data returned will be 4096 bytes + * + * @param[in] i_cmdLength number of bytes in pass-thru command data + * @param[in] *i_cmdData pointer to pass-thru command data + * @param[out] *o_rspLength pointer to number of bytes returned in + * o_rspData + * @param[out] *o_rspData pointer to a 4096 byte buffer that will + * contain the response data from the command + * + * @returns 0 on success, or return code if the command failed + * @platform OpenPower + */ + 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) diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c index 4624996..83edbf6 100644 --- a/external/opal-prd/opal-prd.c +++ b/external/opal-prd/opal-prd.c @@ -83,7 +83,9 @@ enum control_msg_type { CONTROL_MSG_DISABLE_OCCS = 0x01, CONTROL_MSG_TEMP_OCC_RESET = 0x02, CONTROL_MSG_TEMP_OCC_ERROR = 0x03, + CONTROL_MSG_HTMGT_PASSTHRU = 0x04, CONTROL_MSG_RUN_CMD = 0x10, + CONTROL_MSG_ATTR_OVERRIDE = 0x20, }; @@ -186,6 +188,22 @@ static void pr_log_nocall(const char *name) pr_log(LOG_WARNING, "HBRT: Call %s not provided", name); } +static void pr_log_stream(const uint8_t *data, uint32_t len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i % 16 == 0) + printf("\n"); + else if(i % 4 == 0) + printf(" "); + + printf("%02x", data[i]); + } + + printf("\n"); +} + static void pr_log_daemon_init(void) { if (ctx->use_syslog) { @@ -208,6 +226,9 @@ extern int call_enable_attns(void); extern int call_enable_occ_actuation(bool i_occActivation); extern void call_process_occ_reset(uint64_t i_chipId); extern int call_run_command(int argc, const char **argv, char **o_outString); +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); void hservice_puts(const char *str) { @@ -1066,7 +1087,7 @@ static void handle_prd_control_run_cmd(struct control_msg *send_msg, char *runcmd_output, *s; const char **argv; int i, argc; - size_t size; + size_t size = 0; if (!hservice_runtime->run_command) { pr_log_nocall("run_command"); @@ -1111,6 +1132,44 @@ static void handle_prd_control_run_cmd(struct control_msg *send_msg, } } +static void handle_prd_control_htmgt_passthru(struct control_msg *send_msg, + struct control_msg *recv_msg) +{ + uint16_t rsp_len; + + + if (!hservice_runtime->htmgt_pass_thru) { + pr_log_nocall("htmgt_pass_thru"); + return; + } + + pr_debug("CTRL: calling htmgt_pass_thru"); + send_msg->response = call_htmgt_pass_thru(recv_msg->data_len, + recv_msg->data, &rsp_len, + send_msg->data); + send_msg->data_len = be16toh(rsp_len); + if (send_msg->data_len > MAX_CONTROL_MSG_BUF) { + pr_log(LOG_ERR, "CTRL: response buffer overrun, data len: %d", + send_msg->data_len); + send_msg->data_len = MAX_CONTROL_MSG_BUF; + } + +} + +static void handle_prd_control_attr_override(struct control_msg *send_msg, + struct control_msg *recv_msg) +{ + if (!hservice_runtime->apply_attr_override) { + pr_log_nocall("apply_attr_override"); + return; + } + + pr_debug("CTRL: calling apply_attr_override"); + send_msg->response = call_apply_attr_override( + recv_msg->data, recv_msg->data_len); + send_msg->data_len = 0; +} + static void handle_prd_control(struct opal_prd_ctx *ctx, int fd) { struct control_msg msg, *recv_msg, *send_msg; @@ -1171,9 +1230,15 @@ static void handle_prd_control(struct opal_prd_ctx *ctx, int fd) case CONTROL_MSG_TEMP_OCC_ERROR: handle_prd_control_occ_error(send_msg); break; + 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; + case CONTROL_MSG_ATTR_OVERRIDE: + handle_prd_control_attr_override(send_msg, recv_msg); + break; default: pr_log(LOG_WARNING, "CTRL: Unknown control message action %d", recv_msg->type); @@ -1442,7 +1507,7 @@ static int send_prd_control(struct control_msg *send_msg, goto out_close; } else if (rc != (sizeof(*msg) + msg->data_len)) { - pr_log(LOG_WARNING, "CTRL: Short read from control socket"); + pr_log(LOG_WARNING, "CTRL: Short read from control socket: %m"); rc = -1; goto out_close; } @@ -1454,31 +1519,57 @@ out_close: return rc; } -static int send_occ_control(struct opal_prd_ctx *ctx, const char *str) +static int send_occ_control(struct opal_prd_ctx *ctx, int argc, char *argv[]) { - struct control_msg send_msg, *recv_msg = NULL; - int rc; - - memset(&send_msg, 0, sizeof(send_msg)); + struct control_msg msg, *send_msg, *recv_msg = NULL; + int rc, i; - if (!strcmp(str, "enable")) { - send_msg.type = CONTROL_MSG_ENABLE_OCCS; - } else if (!strcmp(str, "disable")) { - send_msg.type = CONTROL_MSG_DISABLE_OCCS; - } else if (!strcmp(str, "reset")) { - send_msg.type = CONTROL_MSG_TEMP_OCC_RESET; - } else if (!strcmp(str, "process-error")) { - send_msg.type = CONTROL_MSG_TEMP_OCC_ERROR; + memset(&msg, 0, sizeof(msg)); + + if (!strcmp(argv[0], "enable")) + msg.type = CONTROL_MSG_ENABLE_OCCS; + else if (!strcmp(argv[0], "disable")) + msg.type = CONTROL_MSG_DISABLE_OCCS; + else if (!strcmp(argv[0], "reset")) + msg.type = CONTROL_MSG_TEMP_OCC_RESET; + else if (!strcmp(argv[0], "process-error")) + msg.type = CONTROL_MSG_TEMP_OCC_ERROR; + else if (!strcmp(argv[0], "passthru")) { + msg.type = CONTROL_MSG_HTMGT_PASSTHRU; + msg.data_len = argc - 1; } else { - pr_log(LOG_ERR, "CTRL: Invalid OCC action '%s'", str); + pr_log(LOG_ERR, "OCC: Invalid OCC action '%s'", argv[0]); return -1; } - rc = send_prd_control(&send_msg, &recv_msg); + send_msg = malloc(sizeof(*send_msg) + msg.data_len); + if (!send_msg) { + pr_log(LOG_ERR, "CTRL: msg buffer malloc failed: %m"); + return -1; + } + + send_msg->type = msg.type; + send_msg->data_len = msg.data_len; + if (send_msg->type == CONTROL_MSG_HTMGT_PASSTHRU) { + for (i = 0; i < (argc - 1); i++) { + if (ctx->debug) { + pr_debug("CTRL: run command arguments:"); + pr_debug("argv[%d] = %s", i, argv[i]); + } + sscanf(argv[i + 1], "%hhx", &send_msg->data[i]); + } + } + + rc = send_prd_control(send_msg, &recv_msg); + free(send_msg); if (recv_msg) { if (recv_msg->response || ctx->debug) - pr_debug("CTRL: OCC action %s returned status %d", str, - recv_msg->response); + pr_debug("CTRL: OCC action %s returned status %d", + argv[0], recv_msg->response); + if (recv_msg->type == CONTROL_MSG_HTMGT_PASSTHRU && + !recv_msg->response && recv_msg->data_len) + pr_log_stream(recv_msg->data, recv_msg->data_len); + free(recv_msg); } @@ -1532,13 +1623,69 @@ static int send_run_command(struct opal_prd_ctx *ctx, int argc, char *argv[]) return rc; } +static int send_attr_override(struct opal_prd_ctx *ctx, uint32_t argc, + char *argv[]) +{ + struct control_msg *send_msg, *recv_msg = NULL; + struct stat statbuf; + size_t sz; + FILE *fd; + int rc; + + rc = stat(argv[0], &statbuf); + if (rc) { + pr_log(LOG_ERR, "CTRL: stat() failed on the file: %m"); + return -1; + } + + send_msg = malloc(sizeof(*send_msg) + statbuf.st_size); + if (!send_msg) { + pr_log(LOG_ERR, "CTRL: msg buffer malloc failed: %m"); + return -1; + } + + send_msg->type = CONTROL_MSG_ATTR_OVERRIDE; + send_msg->data_len = statbuf.st_size; + + fd = fopen(argv[0], "r"); + if (!fd) { + pr_log(LOG_NOTICE, "CTRL: can't open %s: %m", argv[0]); + rc = -1; + goto out_free; + } + + sz = fread(send_msg->data, 1, send_msg->data_len, fd); + fclose(fd); + if (sz != statbuf.st_size) { + pr_log(LOG_ERR, "CTRL: short read from the file"); + rc = -1; + goto out_free; + } + + rc = send_prd_control(send_msg, &recv_msg); + if (recv_msg) { + if (recv_msg->response || ctx->debug) + pr_debug("CTRL: attribute override returned status %d", + recv_msg->response); + free(recv_msg); + } + +out_free: + free(send_msg); + return rc; +} + +/* TODO usage */ static void usage(const char *progname) { printf("Usage:\n"); printf("\t%s [--debug] [--file ] [--pnor ]\n", progname); printf("\t%s occ \n", progname); + printf("\t%s occ passthru [1st byte] [2nd byte]..[nth byte]\n", + progname); printf("\t%s run [arg 0] [arg 1]..[arg n]\n", progname); + printf("\t%s override \n", progname); printf("\n"); printf("Options:\n" "\t--debug verbose logging for debug information\n" @@ -1568,6 +1715,7 @@ enum action { ACTION_RUN_DAEMON, ACTION_OCC_CONTROL, ACTION_RUN_COMMAND, + ACTION_ATTR_OVERRIDE, }; static int parse_action(const char *str, enum action *action) @@ -1587,6 +1735,11 @@ static int parse_action(const char *str, enum action *action) return 0; } + if (!strcmp(str, "override")) { + *action = ACTION_ATTR_OVERRIDE; + return 0; + } + pr_log(LOG_ERR, "CTRL: unknown argument '%s'", str); return -1; } @@ -1644,18 +1797,20 @@ int main(int argc, char *argv[]) action = ACTION_RUN_DAEMON; } - if (action == ACTION_RUN_DAEMON) { + switch (action) { + case ACTION_RUN_DAEMON: rc = run_prd_daemon(ctx); - - } else if (action == ACTION_OCC_CONTROL) { + break; + case ACTION_OCC_CONTROL: if (optind + 1 >= argc) { pr_log(LOG_ERR, "CTRL: occ command requires " "an argument"); return EXIT_FAILURE; } - rc = send_occ_control(ctx, argv[optind + 1]); - } else if (action == ACTION_RUN_COMMAND) { + rc = send_occ_control(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)"); @@ -1663,6 +1818,18 @@ int main(int argc, char *argv[]) } rc = send_run_command(ctx, argc - optind - 1, &argv[optind + 1]); + break; + case ACTION_ATTR_OVERRIDE: + if (optind + 1 >= argc) { + pr_log(LOG_ERR, "CTRL: attribute override command " + "requires an argument"); + return EXIT_FAILURE; + } + + rc = send_attr_override(ctx, argc - optind - 1, &argv[optind + 1]); + break; + default: + break; } return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/external/opal-prd/thunk.S b/external/opal-prd/thunk.S index 3828534..f259ba2 100644 --- a/external/opal-prd/thunk.S +++ b/external/opal-prd/thunk.S @@ -90,6 +90,8 @@ call_##name: ;\ CALL_THUNK(handle_attns, 9) CALL_THUNK(process_occ_reset, 10) 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