[Pdbg] [PATCH 13/17] libsbefifo: Refactor output parsing and ffdc extraction

Amitay Isaacs amitay at ozlabs.org
Thu Oct 31 17:34:24 AEDT 2019


When ffdc is generated, use special error code ESBEFIFO.

Signed-off-by: Amitay Isaacs <amitay at ozlabs.org>
---
 libsbefifo/libsbefifo.h |   9 ++++
 libsbefifo/operation.c  | 101 +++++++++++++++++++++-------------------
 2 files changed, 62 insertions(+), 48 deletions(-)

diff --git a/libsbefifo/libsbefifo.h b/libsbefifo/libsbefifo.h
index be0defd..ce2963e 100644
--- a/libsbefifo/libsbefifo.h
+++ b/libsbefifo/libsbefifo.h
@@ -19,6 +19,8 @@
 
 #include <stdint.h>
 
+#define ESBEFIFO	201
+
 #define SBEFIFO_PRI_SUCCESS           0x00000000
 #define SBEFIFO_PRI_INVALID_COMMAND   0x00010000
 #define SBEFIFO_PRI_INVALID_DATA      0x00020000
@@ -54,6 +56,13 @@ void sbefifo_free(struct sbefifo_context *sctx);
 int sbefifo_connect(const char *fifo_path, struct sbefifo_context **out);
 void sbefifo_disconnect(struct sbefifo_context *sctx);
 
+int sbefifo_parse_output(struct sbefifo_context *sctx, uint32_t cmd,
+			 uint8_t *buf, uint32_t buflen,
+			 uint8_t **out, uint32_t *out_len);
+int sbefifo_operation(struct sbefifo_context *sctx,
+		      uint8_t *msg, uint32_t msg_len,
+		      uint8_t **out, uint32_t *out_len);
+
 uint32_t sbefifo_ffdc_get(struct sbefifo_context *sctx, const uint8_t **ffdc, uint32_t *ffdc_len);
 void sbefifo_ffdc_dump(struct sbefifo_context *sctx);
 
diff --git a/libsbefifo/operation.c b/libsbefifo/operation.c
index 744dd6c..aaf2668 100644
--- a/libsbefifo/operation.c
+++ b/libsbefifo/operation.c
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <endian.h>
 
+#include "libsbefifo.h"
 #include "sbefifo_private.h"
 
 static int sbefifo_read(struct sbefifo_context *sctx, void *buf, size_t *buflen)
@@ -54,57 +55,24 @@ static int sbefifo_write(struct sbefifo_context *sctx, void *buf, size_t buflen)
 	return 0;
 }
 
-int sbefifo_operation(struct sbefifo_context *sctx,
-		      uint8_t *msg, uint32_t msg_len,
-		      uint8_t **out, uint32_t *out_len)
+int sbefifo_parse_output(struct sbefifo_context *sctx, uint32_t cmd,
+			 uint8_t *buf, uint32_t buflen,
+			 uint8_t **out, uint32_t *out_len)
 {
-	uint8_t *buf;
-	size_t buflen;
 	uint32_t offset_word, header_word, status_word;
 	uint32_t offset;
-	uint32_t cmd;
-	int rc;
-
-	assert(msg);
-	assert(msg_len > 0);
 
 	sbefifo_ffdc_clear(sctx);
 
-	/*
-	 * Allocate extra memory for FFDC (SBEFIFO_MAX_FFDC_SIZE = 0x2000)
-	 * Use *out_len as a hint to expected reply length
-	 */
-	buflen = (*out_len + 0x2000 + 3) & ~(uint32_t)3;
-	buf = malloc(buflen);
-	if (!buf)
-		return ENOMEM;
-
-	cmd = be32toh(*(uint32_t *)(msg + 4));
-
-	LOG("request: cmd=%08x, len=%u\n", cmd, msg_len);
-
-	rc = sbefifo_write(sctx, msg, msg_len);
-	if (rc) {
-		LOG("write: cmd=%08x, rc=%d\n", cmd, rc);
-		return rc;
-	}
-
-	rc = sbefifo_read(sctx, buf, &buflen);
-	if (rc) {
-		LOG("read: cmd=%08x, buflen=%zu, rc=%d\n", cmd, buflen, rc);
-		return rc;
-	}
-
 	/*
 	 * At least 3 words are expected in response
 	 *   - header word
 	 *   - status word
 	 *   - header offset word
 	 */
-	if (buflen < 3 * 4) {
+	if (buflen < 3 * sizeof(uint32_t)) {
 		LOG("reply: cmd=%08x, len=%u\n", cmd, buflen);
-		rc = EPROTO;
-		goto fail;
+		return EPROTO;
 	}
 
 	/* Last word is header offset (in words) */
@@ -121,33 +89,70 @@ int sbefifo_operation(struct sbefifo_context *sctx,
 
 	if (header_word != (0xc0de0000 | cmd)) {
 		LOG("reply: cmd=%08x, len=%u, header=%08x\n", cmd, buflen, header_word);
-		rc = EPROTO;
-		goto fail;
+		return EPROTO;
 	}
 
 	LOG("reply: cmd=%08x, len=%u, status=%08x\n", cmd, buflen, status_word);
 
 	if (status_word) {
 		sbefifo_ffdc_set(sctx, status_word, buf + offset, buflen - offset-4);
-		rc = 201;
-		goto fail;
+		return ESBEFIFO;
 	}
 
 	if (*out_len > 0) {
 		*out = malloc(*out_len);
-		if (! *out) {
-			rc = ENOMEM;
-			goto fail;
-		}
+		if (! *out)
+			return ENOMEM;
+
 		memcpy(*out, buf, *out_len);
 	} else {
 		*out = NULL;
 	}
 
-	free(buf);
 	return 0;
+}
+
+int sbefifo_operation(struct sbefifo_context *sctx,
+		      uint8_t *msg, uint32_t msg_len,
+		      uint8_t **out, uint32_t *out_len)
+{
+	uint8_t *buf;
+	size_t buflen;
+	uint32_t cmd;
+	int rc;
+
+	assert(msg);
+	assert(msg_len > 0);
+
+	if (sctx->fd == -1)
+		return ENOTCONN;
+
+	/*
+	 * Allocate extra memory for FFDC (SBEFIFO_MAX_FFDC_SIZE = 0x2000)
+	 * Use *out_len as a hint to expected reply length
+	 */
+	buflen = (*out_len + 0x2000 + 3) & ~(uint32_t)3;
+	buf = malloc(buflen);
+	if (!buf)
+		return ENOMEM;
+
+	cmd = be32toh(*(uint32_t *)(msg + 4));
+
+	LOG("request: cmd=%08x, len=%u\n", cmd, msg_len);
+
+	rc = sbefifo_write(sctx, msg, msg_len);
+	if (rc) {
+		LOG("write: cmd=%08x, rc=%d\n", cmd, rc);
+		return rc;
+	}
+
+	rc = sbefifo_read(sctx, buf, &buflen);
+	if (rc) {
+		LOG("read: cmd=%08x, buflen=%zu, rc=%d\n", cmd, buflen, rc);
+		return rc;
+	}
 
-fail:
+	rc = sbefifo_parse_output(sctx, cmd, buf, buflen, out, out_len);
 	free(buf);
 	return rc;
 }
-- 
2.21.0



More information about the Pdbg mailing list