[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