[Skiboot] [PATCH RFC 08/12] opal-prd: Add support for variable-sized messages
Vasant Hegde
hegdevasant at linux.vnet.ibm.com
Thu May 25 21:46:03 AEST 2017
On 05/25/2017 12:35 PM, Jeremy Kerr wrote:
> With the introductuion of the opaque firmware channel, we want to
> support variable-sized messages. Rather than expecting to read an
> entire 'struct opal_prd_msg' in one read() call, we can split this
> over mutiple reads, potentially expanding our message buffer.
>
> Signed-off-by: Jeremy Kerr <jk at ozlabs.org>
> ---
> external/opal-prd/opal-prd.c | 67 ++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 55 insertions(+), 12 deletions(-)
>
> diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
> index c7cdc61..ebd6c0f 100644
> --- a/external/opal-prd/opal-prd.c
> +++ b/external/opal-prd/opal-prd.c
> @@ -80,6 +80,8 @@ struct opal_prd_ctx {
> char *hbrt_file_name;
> bool use_syslog;
> bool expert_mode;
> + struct opal_prd_msg *msg;
> + size_t msg_alloc_len;
> void (*vlog)(int, const char *, va_list);
> };
>
> @@ -1225,41 +1227,76 @@ static int handle_msg_occ_reset(struct opal_prd_ctx *ctx,
>
> static int handle_prd_msg(struct opal_prd_ctx *ctx)
> {
> - struct opal_prd_msg msg;
> + struct opal_prd_msg *msg;
> int size;
> int rc;
>
> - rc = read(ctx->fd, &msg, sizeof(msg));
> + msg = ctx->msg;
> +
> + rc = read(ctx->fd, msg, ctx->msg_alloc_len);
> if (rc < 0 && errno == EAGAIN)
> return -1;
>
> - if (rc != sizeof(msg)) {
> - pr_log(LOG_WARNING, "FW: Error reading events from OPAL: %m");
> + /* we need at least enough for the message header... */
> + if (rc < 0) {
> + pr_log(LOG_WARNING, "FW: error reading from firmware: %m");
> + return -1;
> + }
> +
> + if (rc < sizeof(msg->hdr)) {
> + pr_log(LOG_WARNING, "FW: short message read from firmware");
> return -1;
> }
>
> - size = htobe16(msg.hdr.size);
> - if (size < sizeof(msg)) {
> + /* ... and for the reported message size to be sane */
> + size = htobe16(msg->hdr.size);
> + if (size < sizeof(msg->hdr)) {
> pr_log(LOG_ERR, "FW: Mismatched message size "
> "between opal-prd and firmware "
> "(%d from FW, %zd expected)",
> - size, sizeof(msg));
> + size, sizeof(msg->hdr));
> return -1;
> }
>
> - switch (msg.hdr.type) {
> + /* expand our message buffer if necessary... */
> + if (size > ctx->msg_alloc_len) {
> + ctx->msg = msg = realloc(ctx->msg, size);
Validate memory allocation ?
> + ctx->msg_alloc_len = size;
> + }
> +
> + /* ... and complete the read */
> + if (size > rc) {
> + size_t pos;
> +
> + for (pos = rc; pos < size;) {
> + rc = read(ctx->fd, msg + pos, size - pos);
> +
> + if (rc < 0 && errno == EAGAIN)
> + continue;
> +
> + if (rc <= 0) {
> + pr_log(LOG_WARNING,
> + "FW: error reading from firmware: %m");
> + return -1;
> + }
> +
> + pos += rc;
> + }
> + }
> +
> + switch (msg->hdr.type) {
> case OPAL_PRD_MSG_TYPE_ATTN:
> - rc = handle_msg_attn(ctx, &msg);
> + rc = handle_msg_attn(ctx, msg);
> break;
> case OPAL_PRD_MSG_TYPE_OCC_RESET:
> - rc = handle_msg_occ_reset(ctx, &msg);
> + rc = handle_msg_occ_reset(ctx, msg);
> break;
> case OPAL_PRD_MSG_TYPE_OCC_ERROR:
> - rc = handle_msg_occ_error(ctx, &msg);
> + rc = handle_msg_occ_error(ctx, msg);
> break;
> default:
> pr_log(LOG_WARNING, "Invalid incoming message type 0x%x",
> - msg.hdr.type);
> + msg->hdr.type);
> return -1;
> }
>
> @@ -1621,6 +1658,10 @@ static int run_prd_daemon(struct opal_prd_ctx *ctx)
> ctx->fd = -1;
> ctx->socket = -1;
>
> + /* set up our message buffer */
> + ctx->msg_alloc_len = sizeof(*ctx->msg);
> + ctx->msg = malloc(ctx->msg_alloc_len);
Validate malloc return value ?
-Vasant
More information about the Skiboot
mailing list