aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/libflash/ecc.h
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/libflash/ecc.h')
-rw-r--r--roms/skiboot/libflash/ecc.h64
1 files changed, 64 insertions, 0 deletions
diff --git a/roms/skiboot/libflash/ecc.h b/roms/skiboot/libflash/ecc.h
new file mode 100644
index 000000000..bdf04201f
--- /dev/null
+++ b/roms/skiboot/libflash/ecc.h
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * This is based on the hostboot ecc code
+ *
+ * Copyright 2013-2018 IBM Corp.
+ */
+
+#ifndef __ECC_H
+#define __ECC_H
+
+#include <stdint.h>
+#include <ccan/endian/endian.h>
+
+struct ecc64 {
+ beint64_t data;
+ uint8_t ecc;
+} __attribute__((__packed__));
+
+extern int memcpy_from_ecc(beint64_t *dst, struct ecc64 *src, uint64_t len);
+extern int memcpy_from_ecc_unaligned(beint64_t *dst, struct ecc64 *src, uint64_t len,
+ uint8_t alignment);
+
+extern int memcpy_to_ecc(struct ecc64 *dst, const beint64_t *src, uint64_t len);
+extern int memcpy_to_ecc_unaligned(struct ecc64 *dst, const beint64_t *src, uint64_t len,
+ uint8_t alignment);
+
+/*
+ * Calculate the size of a buffer if ECC is added
+ *
+ * We add 1 byte of ecc for every 8 bytes of data. So we need to round up to 8
+ * bytes length and then add 1/8
+ */
+#ifndef ALIGN_UP
+#define ALIGN_UP(_v, _a) (((_v) + (_a) - 1) & ~((_a) - 1))
+#endif
+
+#define BYTES_PER_ECC 8
+
+static inline uint64_t ecc_size(uint64_t len)
+{
+ return ALIGN_UP(len, BYTES_PER_ECC) >> 3;
+}
+
+static inline uint64_t ecc_buffer_size(uint64_t len)
+{
+ return ALIGN_UP(len, BYTES_PER_ECC) + ecc_size(len);
+}
+
+static inline int ecc_buffer_size_check(uint64_t len)
+{
+ return len % (BYTES_PER_ECC + 1);
+}
+
+static inline uint64_t ecc_buffer_size_minus_ecc(uint64_t len)
+{
+ return len * BYTES_PER_ECC / (BYTES_PER_ECC + 1);
+}
+
+static inline uint64_t ecc_buffer_align(uint64_t start, uint64_t pos)
+{
+ return pos - ((pos - start) % (BYTES_PER_ECC + 1));
+}
+
+#endif