0001
0002
0003
0004
0005
0006
0007
0008 #ifndef __LINUX_IHEX_H__
0009 #define __LINUX_IHEX_H__
0010
0011 #include <linux/types.h>
0012 #include <linux/firmware.h>
0013 #include <linux/device.h>
0014
0015
0016
0017
0018 struct ihex_binrec {
0019 __be32 addr;
0020 __be16 len;
0021 uint8_t data[];
0022 } __attribute__((packed));
0023
0024 static inline uint16_t ihex_binrec_size(const struct ihex_binrec *p)
0025 {
0026 return be16_to_cpu(p->len) + sizeof(*p);
0027 }
0028
0029
0030 static inline const struct ihex_binrec *
0031 __ihex_next_binrec(const struct ihex_binrec *rec)
0032 {
0033 const void *p = rec;
0034
0035 return p + ALIGN(ihex_binrec_size(rec), 4);
0036 }
0037
0038 static inline const struct ihex_binrec *
0039 ihex_next_binrec(const struct ihex_binrec *rec)
0040 {
0041 rec = __ihex_next_binrec(rec);
0042
0043 return be16_to_cpu(rec->len) ? rec : NULL;
0044 }
0045
0046
0047 static inline int ihex_validate_fw(const struct firmware *fw)
0048 {
0049 const struct ihex_binrec *end, *rec;
0050
0051 rec = (const void *)fw->data;
0052 end = (const void *)&fw->data[fw->size - sizeof(*end)];
0053
0054 for (; rec <= end; rec = __ihex_next_binrec(rec)) {
0055
0056 if (rec == end && !be16_to_cpu(rec->len))
0057 return 0;
0058 }
0059 return -EINVAL;
0060 }
0061
0062
0063
0064 static inline int request_ihex_firmware(const struct firmware **fw,
0065 const char *fw_name,
0066 struct device *dev)
0067 {
0068 const struct firmware *lfw;
0069 int ret;
0070
0071 ret = request_firmware(&lfw, fw_name, dev);
0072 if (ret)
0073 return ret;
0074 ret = ihex_validate_fw(lfw);
0075 if (ret) {
0076 dev_err(dev, "Firmware \"%s\" not valid IHEX records\n",
0077 fw_name);
0078 release_firmware(lfw);
0079 return ret;
0080 }
0081 *fw = lfw;
0082 return 0;
0083 }
0084 #endif