summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-03-04 14:53:05 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-03-13 10:24:52 +0100
commit3b21c8a8b4bf9592fbb99a298c2df0e98b8ff3e9 (patch)
treed2dbe339f2c0cf74dacb3000d85d1e2d70d89078 /lib
parent0560c251266468b8ac042be24fcb2b4a6a7e39fc (diff)
downloadbarebox-3b21c8a8b4bf9592fbb99a298c2df0e98b8ff3e9.tar.gz
barebox-3b21c8a8b4bf9592fbb99a298c2df0e98b8ff3e9.tar.xz
Add Freescale QUICC Engine firmware support
The Freescale QUICC Engine found on Layerscape SoCs needs firmware loaded. This adds support for loading such a firmware. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig4
-rw-r--r--lib/Makefile1
-rw-r--r--lib/fsl-qe-firmware.c64
3 files changed, 69 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index b0839e6c6e..150d63b1ba 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -93,6 +93,10 @@ config IMAGE_SPARSE
config STMP_DEVICE
bool
+config FSL_QE_FIRMWARE
+ select CRC32
+ bool
+
config RATP
select CRC_ITU_T
bool "RATP protocol support"
diff --git a/lib/Makefile b/lib/Makefile
index 763516d41a..8dabf4ae77 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -68,6 +68,7 @@ obj-y += clz_ctz.o
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
obj-$(CONFIG_CRC8) += crc8.o
obj-$(CONFIG_NLS) += nls_base.o
+obj-$(CONFIG_FSL_QE_FIRMWARE) += fsl-qe-firmware.o
# GCC library routines
obj-$(CONFIG_GENERIC_LIB_ASHLDI3) += ashldi3.o
diff --git a/lib/fsl-qe-firmware.c b/lib/fsl-qe-firmware.c
new file mode 100644
index 0000000000..960703f561
--- /dev/null
+++ b/lib/fsl-qe-firmware.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <crc.h>
+#include <soc/fsl/qe.h>
+
+/*
+ * qe_validate_firmware - Validate a QE firmware
+ *
+ * This function checks a QE firmware for validity. It checks the crc
+ * and consistency of various fields. Returns 0 for success or a negative
+ * error code otherwise.
+ */
+int qe_validate_firmware(const struct qe_firmware *firmware, int size)
+{
+ u32 crc;
+ size_t calc_size;
+ int i;
+ const struct qe_header *hdr = &firmware->header;
+
+ if (size < sizeof(*firmware)) {
+ pr_err("firmware is too small\n");
+ return -EINVAL;
+ }
+
+ if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
+ (hdr->magic[2] != 'F')) {
+ pr_err("Data at %p is not a QE firmware\n", firmware);
+ return -EPERM;
+ }
+
+ if (size != be32_to_cpu(hdr->length)) {
+ pr_err("Firmware size doesn't match size in header\n");
+ return -EINVAL;
+ }
+
+ if (hdr->version != 1) {
+ pr_err("Unsupported firmware version %u\n", hdr->version);
+ return -EPERM;
+ }
+
+ calc_size = sizeof(*firmware) +
+ (firmware->count - 1) * sizeof(struct qe_microcode);
+
+ if (size < calc_size)
+ return -EINVAL;
+
+ for (i = 0; i < firmware->count; i++)
+ calc_size += sizeof(u32) *
+ be32_to_cpu(firmware->microcode[i].count);
+
+ if (size != calc_size + sizeof(u32)) {
+ pr_err("Invalid length in firmware header\n");
+ return -EPERM;
+ }
+
+ crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
+ if (crc != (crc32_no_comp(0, (const void *)firmware, calc_size))) {
+ pr_err("Firmware CRC is invalid\n");
+ return -EIO;
+ }
+
+ return 0;
+}