diff options
Diffstat (limited to 'board/solidrun/common')
-rw-r--r-- | board/solidrun/common/Makefile | 5 | ||||
-rw-r--r-- | board/solidrun/common/tlv_data.c | 102 | ||||
-rw-r--r-- | board/solidrun/common/tlv_data.h | 18 |
3 files changed, 125 insertions, 0 deletions
diff --git a/board/solidrun/common/Makefile b/board/solidrun/common/Makefile new file mode 100644 index 0000000000..a72ac1b7b9 --- /dev/null +++ b/board/solidrun/common/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) SolidRun + +obj-$(CONFIG_TARGET_CLEARFOG) += tlv_data.o diff --git a/board/solidrun/common/tlv_data.c b/board/solidrun/common/tlv_data.c new file mode 100644 index 0000000000..f08ac8975a --- /dev/null +++ b/board/solidrun/common/tlv_data.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 SolidRun + */ + +#include <common.h> +#include <tlv_eeprom.h> +#include "tlv_data.h" + +#define SR_TLV_CODE_RAM_SIZE 0x81 + +static void store_product_name(struct tlvinfo_tlv *tlv_entry, + struct tlv_data *td) +{ + int len; + char *dest; + + if (strlen(td->tlv_product_name[0]) == 0) + dest = td->tlv_product_name[0]; + else if (strlen(td->tlv_product_name[1]) == 0) + dest = td->tlv_product_name[1]; + else + return; + + len = min_t(unsigned int, tlv_entry->length, + sizeof(td->tlv_product_name[0]) - 1); + memcpy(dest, tlv_entry->value, len); +} + +static void parse_tlv_vendor_ext(struct tlvinfo_tlv *tlv_entry, + struct tlv_data *td) +{ + u8 *val = tlv_entry->value; + u32 pen; /* IANA Private Enterprise Numbers */ + + if (tlv_entry->length < 5) /* 4 bytes PEN + at least 1 byte type */ + return; + + /* PEN is big endian */ + pen = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3]; + /* Not a real PEN */ + if (pen != 0xffffffff) + return; + + if (val[4] != SR_TLV_CODE_RAM_SIZE) + return; + if (tlv_entry->length != 6) + return; + td->ram_size = val[5]; +} + +static void parse_tlv_data(u8 *eeprom, struct tlvinfo_header *hdr, + struct tlvinfo_tlv *entry, struct tlv_data *td) +{ + unsigned int tlv_offset, tlv_len; + + tlv_offset = sizeof(struct tlvinfo_header); + tlv_len = sizeof(struct tlvinfo_header) + be16_to_cpu(hdr->totallen); + while (tlv_offset < tlv_len) { + entry = (struct tlvinfo_tlv *)&eeprom[tlv_offset]; + + switch (entry->type) { + case TLV_CODE_PRODUCT_NAME: + store_product_name(entry, td); + break; + case TLV_CODE_VENDOR_EXT: + parse_tlv_vendor_ext(entry, td); + break; + default: + break; + } + + tlv_offset += sizeof(struct tlvinfo_tlv) + entry->length; + } +} + +void read_tlv_data(struct tlv_data *td) +{ + u8 eeprom_data[TLV_TOTAL_LEN_MAX]; + struct tlvinfo_header *tlv_hdr; + struct tlvinfo_tlv *tlv_entry; + int ret, i; + + for (i = 0; i < 2; i++) { + ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr, + &tlv_entry, i); + if (ret < 0) + continue; + parse_tlv_data(eeprom_data, tlv_hdr, tlv_entry, td); + } +} + +bool sr_product_is(const struct tlv_data *td, const char *product) +{ + /* Allow prefix sub-string match */ + if (strncmp(td->tlv_product_name[0], product, strlen(product)) == 0) + return true; + if (strncmp(td->tlv_product_name[1], product, strlen(product)) == 0) + return true; + + return false; +} diff --git a/board/solidrun/common/tlv_data.h b/board/solidrun/common/tlv_data.h new file mode 100644 index 0000000000..a1432e4b8e --- /dev/null +++ b/board/solidrun/common/tlv_data.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2020 SolidRun + */ + +#ifndef __BOARD_SR_COMMON_H_ +#define __BOARD_SR_COMMON_H_ + +struct tlv_data { + /* Store product name of both SOM and carrier */ + char tlv_product_name[2][32]; + unsigned int ram_size; +}; + +void read_tlv_data(struct tlv_data *td); +bool sr_product_is(const struct tlv_data *td, const char *product); + +#endif /* __BOARD_SR_COMMON_H_ */ |