[Skiboot] [PATCH 10/16] libffs: Add ffs_flash_read()

Michael Neuling mikey at neuling.org
Fri Feb 20 11:37:53 AEDT 2015


Add ffs_flash_read() which mimics flash_read() but handles ECC checking,
correction and uncorrectable errors.

Signed-off-by: Michael Neuling <mikey at neuling.org>
---
 libflash/libffs.c   | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 libflash/libffs.h   |  4 ++++
 libflash/libflash.h |  1 +
 3 files changed, 57 insertions(+)

diff --git a/libflash/libffs.c b/libflash/libffs.c
index cfd5456..c28fd66 100644
--- a/libflash/libffs.c
+++ b/libflash/libffs.c
@@ -18,6 +18,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <ecc.h>
 
 #include <ccan/endian/endian.h>
 
@@ -286,3 +287,54 @@ int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx,
 		return 0;
 	return flash_smart_write(ffs->chip, offset, ent, FFS_ENTRY_SIZE);
 }
+
+#define COPY_BUFFER_LENGTH 4096
+
+/*
+ * This provides a wrapper around flash_read on ECCed data
+ * len is length of data without ECC attached
+ */
+int ffs_flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len,
+		   bool ecc)
+{
+	uint64_t *bufecc;
+	uint32_t copylen;
+	int rc;
+	uint8_t ret;
+
+	if (!ecc)
+		return flash_read(c, pos, buf, len);
+
+	/* Copy the buffer in chunks */
+	bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH));
+	if (!bufecc)
+		return FLASH_ERR_MALLOC_FAILED;
+
+	while (len > 0) {
+		/* What's left to copy? */
+		copylen = MIN(len, COPY_BUFFER_LENGTH);
+
+		/* Read ECCed data from flash */
+		rc = flash_read(c, pos, bufecc, ECC_BUFFER_SIZE(copylen));
+		if (rc)
+			goto err;
+
+		/* Extract data from ECCed data */
+		ret = eccmemcpy(buf, bufecc, copylen);
+		if (ret == UE) {
+			rc = FLASH_ERR_ECC_INVALID;
+			goto err;
+		}
+
+		/* Update for next copy */
+		len -= copylen;
+		buf = (uint8_t *)buf + copylen;
+		pos += ECC_BUFFER_SIZE(copylen);
+	}
+
+	return 0;
+
+err:
+	free(bufecc);
+	return rc;
+}
diff --git a/libflash/libffs.h b/libflash/libffs.h
index 69e44bb..15ed3c5 100644
--- a/libflash/libffs.h
+++ b/libflash/libffs.h
@@ -32,6 +32,7 @@ struct ffs_handle;
 #define FFS_ERR_BAD_VERSION	101
 #define FFS_ERR_BAD_CKSUM	102
 #define FFS_ERR_PART_NOT_FOUND	103
+#define FFS_ERR_BAD_ECC		104
 
 int ffs_open_flash(struct flash_chip *chip, uint32_t offset,
 		   uint32_t max_size, struct ffs_handle **ffs);
@@ -52,5 +53,8 @@ int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx,
 int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx,
 			uint32_t act_size);
 
+int ffs_flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len,
+		   bool ecc);
+
 
 #endif /* __LIBFFS_H */
diff --git a/libflash/libflash.h b/libflash/libflash.h
index 31d3562..8e031dd 100644
--- a/libflash/libflash.h
+++ b/libflash/libflash.h
@@ -51,6 +51,7 @@ extern bool libflash_debug;
 #define FLASH_ERR_CHIP_ER_NOT_SUPPORTED	11
 #define FLASH_ERR_CTRL_CMD_UNSUPPORTED	12
 #define FLASH_ERR_CTRL_TIMEOUT		13
+#define FLASH_ERR_ECC_INVALID		14
 
 /* Flash chip, opaque */
 struct flash_chip;
-- 
2.1.0



More information about the Skiboot mailing list