diff options
Diffstat (limited to 'mpm/tools/tlv_eeprom/tlv_eeprom.c')
-rw-r--r-- | mpm/tools/tlv_eeprom/tlv_eeprom.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/mpm/tools/tlv_eeprom/tlv_eeprom.c b/mpm/tools/tlv_eeprom/tlv_eeprom.c new file mode 100644 index 000000000..8b2e2d9c0 --- /dev/null +++ b/mpm/tools/tlv_eeprom/tlv_eeprom.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2019 Ettus Research, a National Instruments Brand + */ + +#include <string.h> +#include "tlv_eeprom.h" + +struct tlv_eeprom *tlv_eeprom_init(void *data) +{ + struct tlv_eeprom *e = data; + + return e; +} + +void tlv_eeprom_seal(struct tlv_eeprom *e, uint32_t magic, size_t len) +{ + e->magic = magic; + e->size = len; + e->crc = tlv_eeprom_crc(e); +} + +int tlv_eeprom_validate(const struct tlv_eeprom *e, uint32_t magic) +{ + uint32_t crc; + + if (e->magic != magic) + return -1; + + if (e->size > TLV_EEPROM_SIZE) + return -2; + + crc = tlv_eeprom_crc(e); + if (e->crc != crc) + return -3; + + return 0; +} + +struct tlv { + uint8_t tag; + uint8_t len; + uint8_t val[0]; +}; + + +static inline const struct tlv *tlv_next(const struct tlv *tlv, const void *end) +{ + const void *p = &tlv->val; + + p += tlv->len; + if (p >= end) + return NULL; + return p; +} + +static inline const struct tlv *tlv_find(const struct tlv *tlv, + const void *end, uint8_t tag) +{ + do { + if (tlv->tag == tag) + break; + } while ((tlv = tlv_next(tlv, end))); + + return tlv; +} + +void tlv_for_each(const void *buf, size_t bufsz, + void (*fn)(uint8_t tag, uint8_t len, const void *val)) +{ + const struct tlv *tlv = buf; + + do { + fn(tlv->tag, tlv->len, tlv->val); + } while ((tlv = tlv_next(tlv, buf + bufsz))); +} + +const void *tlv_lookup(const void *buf, size_t bufsz, uint8_t tag) +{ + const struct tlv *tlv; + + tlv = tlv_find(buf, buf + bufsz, tag); + if (!tlv) + return tlv; + + return tlv->val; +} + +size_t tlv_write(void *buf, uint8_t tag, uint8_t len, const void *val) +{ + struct tlv *tlv = buf; + + tlv->tag = tag; + tlv->len = len; + memcpy(tlv->val, val, len); + + return sizeof(*tlv) + len; +} |