aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/flash.c10
-rw-r--r--external/gard/gard.c2
-rw-r--r--libflash/ecc.c51
-rw-r--r--libflash/ecc.h44
-rw-r--r--libflash/libflash.c27
-rw-r--r--libflash/test/test-ecc.c16
6 files changed, 84 insertions, 66 deletions
diff --git a/core/flash.c b/core/flash.c
index bea5160..b9c739d 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -418,7 +418,7 @@ static int flash_find_subpartition(struct blocklevel_device *bl, uint32_t subid,
/* Get raw partition size without ECC */
partsize = *total_size;
if (ecc)
- partsize = BUFFER_SIZE_MINUS_ECC(*total_size);
+ partsize = ecc_buffer_size_minus_ecc(*total_size);
/* Get the TOC */
rc = flash_read_corrected(bl, *start, header,
@@ -483,8 +483,8 @@ static int flash_find_subpartition(struct blocklevel_device *bl, uint32_t subid,
*start += offset;
*total_size = size;
if (ecc) {
- *start += ECC_SIZE(offset);
- *total_size += ECC_SIZE(size);
+ *start += ecc_size(offset);
+ *total_size += ecc_size(size);
}
rc = 0;
goto end;
@@ -577,12 +577,12 @@ static int flash_load_resource(enum resource_id id, uint32_t subid,
/* Work out what the final size of buffer will be without ECC */
size = part_size;
if (ecc) {
- if ECC_BUFFER_SIZE_CHECK(part_size) {
+ if (ecc_buffer_size_check(part_size)) {
prerror("FLASH: %s image invalid size for ECC %d\n",
name, part_size);
goto out_free_ffs;
}
- size = BUFFER_SIZE_MINUS_ECC(part_size);
+ size = ecc_buffer_size_minus_ecc(part_size);
}
if (size > *len) {
diff --git a/external/gard/gard.c b/external/gard/gard.c
index 93a1c07..bfcd0dd 100644
--- a/external/gard/gard.c
+++ b/external/gard/gard.c
@@ -63,7 +63,7 @@ struct gard_ctx {
*/
static inline size_t sizeof_gard(struct gard_ctx *ctx)
{
- return ctx->ecc ? ECC_BUFFER_SIZE(sizeof(struct gard_record)) : sizeof(struct gard_record);
+ return ctx->ecc ? ecc_buffer_size(sizeof(struct gard_record)) : sizeof(struct gard_record);
}
static void show_flash_err(int rc)
diff --git a/libflash/ecc.c b/libflash/ecc.c
index 78c88d0..05c0e14 100644
--- a/libflash/ecc.c
+++ b/libflash/ecc.c
@@ -23,6 +23,22 @@
#include "libflash.h"
#include "ecc.h"
+/* Bit field identifiers for syndrome calculations. */
+enum eccbitfields
+{
+ GD = 0xff, //< Good, ECC matches.
+ UE = 0xfe, //< Uncorrectable.
+ E0 = 71, //< Error in ECC bit 0
+ E1 = 70, //< Error in ECC bit 1
+ E2 = 69, //< Error in ECC bit 2
+ E3 = 68, //< Error in ECC bit 3
+ E4 = 67, //< Error in ECC bit 4
+ E5 = 66, //< Error in ECC bit 5
+ E6 = 65, //< Error in ECC bit 6
+ E7 = 64 //< Error in ECC bit 7
+ /* 0-63 Correctable bit in byte */
+};
+
/*
* Matrix used for ECC calculation.
*
@@ -73,7 +89,7 @@ static uint64_t eccmatrix[] = {
*
* Bits are in MSB order.
*/
-static uint8_t syndromematrix[] = {
+static enum eccbitfields syndromematrix[] = {
GD, E7, E6, UE, E5, UE, UE, 47, E4, UE, UE, 37, UE, 35, 39, UE,
E3, UE, UE, 48, UE, 30, 29, UE, UE, 57, 27, UE, 31, UE, UE, UE,
E2, UE, UE, 17, UE, 18, 40, UE, UE, 58, 22, UE, 21, UE, UE, UE,
@@ -121,7 +137,7 @@ static uint8_t eccgenerate(uint64_t data)
* @retval UE - Indicates the data is uncorrectable.
* @retval all others - Indication of which bit is incorrect.
*/
-static uint8_t eccverify(uint64_t data, uint8_t ecc)
+static enum eccbitfields eccverify(uint64_t data, uint8_t ecc)
{
return syndromematrix[eccgenerate(data) ^ ecc];
}
@@ -142,15 +158,14 @@ static inline uint64_t eccflipbit(uint64_t data, uint8_t bit)
* @dst: destination buffer without ECC
* @src: source buffer with ECC
* @len: number of bytes of data to copy (without ecc).
- Must be 8 byte aligned.
+ * Must be 8 byte aligned.
*
- * @return: eccBitfield or 0-64.
+ * @return: Success or error
*
- * @retval GD - Data is good.
- * @retval UE - Data is uncorrectable.
- * @retval all others - which bit was corrected.
+ * @retval: 0 - success
+ * @retfal: other - fail
*/
-uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
+int memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
{
beint64_t data;
uint8_t ecc;
@@ -161,7 +176,7 @@ uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
/* TODO: we could probably handle this */
FL_ERR("ECC data length must be 8 byte aligned length:%i\n",
len);
- return UE;
+ return -1;
}
/* Handle in chunks of 8 bytes, so adjust the length */
@@ -184,7 +199,7 @@ uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
*dst = (uint64_t)be64_to_cpu(eccflipbit(be64_to_cpu(data), badbit));
dst++;
}
- return GD;
+ return 0;
}
/**
@@ -194,23 +209,23 @@ uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
* @src: source buffer without ECC
* @len: number of bytes of data to copy (without ecc, length of src).
* Note: dst must be big enough to hold ecc bytes as well.
- Must be 8 byte aligned.
+ * Must be 8 byte aligned.
*
- * @return: eccBitfield.
+ * @return: success or failure
*
- * @retval GD - Success.
- * @retval UE - Length is not 8 byte aligned.
+ * @retval: 0 - success
+ * @retfal: other - fail
*/
-uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len)
+int memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len)
{
struct ecc64 ecc_word;
uint32_t i;
if (len & 0x7) {
- /* TODO: we could problably handle this */
+ /* TODO: we could probably handle this */
FL_ERR("Data to add ECC bytes to must be 8 byte aligned length: %i\n",
len);
- return UE;
+ return -1;
}
/* Handle in chunks of 8 bytes, so adjust the length */
@@ -223,5 +238,5 @@ uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len)
*(dst + i) = ecc_word;
}
- return GD;
+ return 0;
}
diff --git a/libflash/ecc.h b/libflash/ecc.h
index d58ec3e..1e14724 100644
--- a/libflash/ecc.h
+++ b/libflash/ecc.h
@@ -22,29 +22,14 @@
#include <stdint.h>
#include <ccan/endian/endian.h>
-/* Bit field identifiers for syndrome calculations. */
-enum eccbitfields
-{
- GD = 0xff, //< Good, ECC matches.
- UE = 0xfe, //< Uncorrectable.
- E0 = 71, //< Error in ECC bit 0
- E1 = 70, //< Error in ECC bit 1
- E2 = 69, //< Error in ECC bit 2
- E3 = 68, //< Error in ECC bit 3
- E4 = 67, //< Error in ECC bit 4
- E5 = 66, //< Error in ECC bit 5
- E6 = 65, //< Error in ECC bit 6
- E7 = 64 //< Error in ECC bit 7
-};
-
struct ecc64 {
beint64_t data;
uint8_t ecc;
} __attribute__((__packed__));
-extern uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len);
+extern int memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len);
-extern uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len);
+extern int memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len);
/*
* Calculate the size of a buffer if ECC is added
@@ -56,9 +41,26 @@ extern uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t le
#define ALIGN_UP(_v, _a) (((_v) + (_a) - 1) & ~((_a) - 1))
#endif
-#define ECC_SIZE(len) (ALIGN_UP((len), 8) >> 3)
-#define ECC_BUFFER_SIZE(len) (ALIGN_UP((len), 8) + ECC_SIZE(len))
-#define ECC_BUFFER_SIZE_CHECK(len) ((len) % 9)
-#define BUFFER_SIZE_MINUS_ECC(len) ((len) * 8 / 9)
+#define BYTES_PER_ECC 8
+
+static inline uint32_t ecc_size(uint32_t len)
+{
+ return ALIGN_UP(len, BYTES_PER_ECC) >> 3;
+}
+
+static inline uint32_t ecc_buffer_size(uint32_t len)
+{
+ return ALIGN_UP(len, BYTES_PER_ECC) + ecc_size(len);
+}
+
+static inline int ecc_buffer_size_check(uint32_t len)
+{
+ return len % (BYTES_PER_ECC + 1);
+}
+
+static inline uint32_t ecc_buffer_size_minus_ecc(uint32_t len)
+{
+ return len * BYTES_PER_ECC / (BYTES_PER_ECC + 1);
+}
#endif
diff --git a/libflash/libflash.c b/libflash/libflash.c
index e7b3c8e..a142e17 100644
--- a/libflash/libflash.c
+++ b/libflash/libflash.c
@@ -153,7 +153,7 @@ int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
return flash_read(bl, pos, buf, len);
/* Copy the buffer in chunks */
- bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH));
+ bufecc = malloc(ecc_buffer_size(COPY_BUFFER_LENGTH));
if (!bufecc)
return FLASH_ERR_MALLOC_FAILED;
@@ -162,13 +162,13 @@ int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
copylen = MIN(len, COPY_BUFFER_LENGTH);
/* Read ECCed data from flash */
- rc = flash_read(bl, pos, bufecc, ECC_BUFFER_SIZE(copylen));
+ rc = flash_read(bl, pos, bufecc, ecc_buffer_size(copylen));
if (rc)
goto err;
/* Extract data from ECCed data */
ret = memcpy_from_ecc(buf, bufecc, copylen);
- if (ret == UE) {
+ if (ret) {
rc = FLASH_ERR_ECC_INVALID;
goto err;
}
@@ -176,7 +176,7 @@ int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
/* Update for next copy */
len -= copylen;
buf = (uint8_t *)buf + copylen;
- pos += ECC_BUFFER_SIZE(copylen);
+ pos += ecc_buffer_size(copylen);
}
rc = 0;
@@ -397,7 +397,7 @@ int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void
uint32_t len, bool verify, bool ecc)
{
struct ecc64 *bufecc;
- uint32_t copylen;
+ uint32_t copylen, copylen_minus_ecc;
int rc;
uint8_t ret;
@@ -405,17 +405,18 @@ int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void
return flash_write(bl, pos, buf, len, verify);
/* Copy the buffer in chunks */
- bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH));
+ 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);
+ copylen_minus_ecc = ecc_buffer_size_minus_ecc(copylen);
/* Add the ecc byte to the data */
- ret = memcpy_to_ecc(bufecc, buf, BUFFER_SIZE_MINUS_ECC(copylen));
- if (ret == UE) {
+ ret = memcpy_to_ecc(bufecc, buf, copylen_minus_ecc);
+ if (ret) {
rc = FLASH_ERR_ECC_INVALID;
goto err;
}
@@ -426,8 +427,8 @@ int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void
goto err;
/* Update for next copy */
- len -= BUFFER_SIZE_MINUS_ECC(copylen);
- buf = (uint8_t *)buf + BUFFER_SIZE_MINUS_ECC(copylen);
+ len -= copylen_minus_ecc;
+ buf = (uint8_t *)buf + copylen_minus_ecc;
pos += copylen;
}
@@ -554,17 +555,17 @@ int flash_smart_write_corrected(struct blocklevel_device *bl, uint32_t dst, cons
if (!ecc)
return flash_smart_write(bl, dst, src, size);
- buf = malloc(ECC_BUFFER_SIZE(size));
+ buf = malloc(ecc_buffer_size(size));
if (!buf)
return FLASH_ERR_MALLOC_FAILED;
rc = memcpy_to_ecc(buf, src, size);
- if (rc != GD) {
+ if (rc) {
rc = FLASH_ERR_ECC_INVALID;
goto out;
}
- rc = flash_smart_write(bl, dst, buf, ECC_BUFFER_SIZE(size));
+ rc = flash_smart_write(bl, dst, buf, ecc_buffer_size(size));
out:
free(buf);
diff --git a/libflash/test/test-ecc.c b/libflash/test/test-ecc.c
index 8bbce9d..9d5a43a 100644
--- a/libflash/test/test-ecc.c
+++ b/libflash/test/test-ecc.c
@@ -389,7 +389,7 @@ int main(void)
printf("Testing bitflip recovery\n");
for (i = 0; i < 64; i++) {
ret_memcpy = memcpy_from_ecc(&dst, &ecc_data[i], 8);
- if (dst != 0xffffffffffffffff || ret_memcpy != GD) {
+ if (dst != 0xffffffffffffffff || ret_memcpy) {
ERR("ECC code didn't correct bad bit %d in 0x%016lx\n", 63 - i, be64toh(ecc_data[i].data));
exit(1);
}
@@ -412,7 +412,7 @@ int main(void)
/* Test a large memcpy */
printf("Testing a large(ish) memcpy_from_ecc()\n");
ret_memcpy = memcpy_from_ecc(buf, ecc_data, NUM_ECC_ROWS * sizeof(*buf));
- if (ret_memcpy != GD) {
+ if (ret_memcpy) {
ERR("ECC Couldn't memcpy entire buffer\n");
exit(1);
}
@@ -436,14 +436,14 @@ int main(void)
/* Test a memcpy to add ecc data */
printf("Testing a large(ish) memcpy_to_ecc()\n");
- ret_buf = malloc(ECC_BUFFER_SIZE(NUM_ECC_ROWS * sizeof(*buf)));
+ ret_buf = malloc(ecc_buffer_size(NUM_ECC_ROWS * sizeof(*buf)));
if (!buf) {
ERR("malloc #2 failed during ecc test\n");
exit(1);
}
ret_memcpy = memcpy_to_ecc(ret_buf, buf, NUM_ECC_ROWS * sizeof(*buf));
- if (ret_memcpy != GD) {
+ if (ret_memcpy) {
ERR("ECC Couldn't memcpy entire buffer\n");
exit(1);
}
@@ -466,20 +466,20 @@ int main(void)
printf("ECC tests pass\n");
printf("ECC test error conditions\n");
- if (memcpy_to_ecc(ret_buf, buf, 7) != UE) {
+ if (memcpy_to_ecc(ret_buf, buf, 7) == 0) {
ERR("memcpy_to_ecc didn't detect bad size 7\n");
exit(1);
}
- if (memcpy_to_ecc(ret_buf, buf, 15) != UE) {
+ if (memcpy_to_ecc(ret_buf, buf, 15) == 0) {
ERR("memcpy_to_ecc didn't detect bad size 15\n");
exit(1);
}
- if (memcpy_from_ecc(buf, ret_buf, 7) != UE) {
+ if (memcpy_from_ecc(buf, ret_buf, 7) == 0) {
ERR("memcpy_from_ecc didn't detect bad size 7\n");
exit(1);
}
- if (memcpy_from_ecc(buf, ret_buf, 15) != UE) {
+ if (memcpy_from_ecc(buf, ret_buf, 15) == 0) {
ERR("memcpy_from_ecc didn't detect bad size 15\n");
exit(1);
}