blob: f08ac8975a6a15ec56afa2df3963fa1a5bfa7384 [file] [log] [blame]
Baruch Siacha2e41ad2020-01-20 14:20:11 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2020 SolidRun
4 */
5
6#include <common.h>
7#include <tlv_eeprom.h>
8#include "tlv_data.h"
9
10#define SR_TLV_CODE_RAM_SIZE 0x81
11
12static void store_product_name(struct tlvinfo_tlv *tlv_entry,
13 struct tlv_data *td)
14{
15 int len;
16 char *dest;
17
18 if (strlen(td->tlv_product_name[0]) == 0)
19 dest = td->tlv_product_name[0];
20 else if (strlen(td->tlv_product_name[1]) == 0)
21 dest = td->tlv_product_name[1];
22 else
23 return;
24
25 len = min_t(unsigned int, tlv_entry->length,
26 sizeof(td->tlv_product_name[0]) - 1);
27 memcpy(dest, tlv_entry->value, len);
28}
29
30static void parse_tlv_vendor_ext(struct tlvinfo_tlv *tlv_entry,
31 struct tlv_data *td)
32{
33 u8 *val = tlv_entry->value;
34 u32 pen; /* IANA Private Enterprise Numbers */
35
36 if (tlv_entry->length < 5) /* 4 bytes PEN + at least 1 byte type */
37 return;
38
39 /* PEN is big endian */
40 pen = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
41 /* Not a real PEN */
42 if (pen != 0xffffffff)
43 return;
44
45 if (val[4] != SR_TLV_CODE_RAM_SIZE)
46 return;
47 if (tlv_entry->length != 6)
48 return;
49 td->ram_size = val[5];
50}
51
52static void parse_tlv_data(u8 *eeprom, struct tlvinfo_header *hdr,
53 struct tlvinfo_tlv *entry, struct tlv_data *td)
54{
55 unsigned int tlv_offset, tlv_len;
56
57 tlv_offset = sizeof(struct tlvinfo_header);
58 tlv_len = sizeof(struct tlvinfo_header) + be16_to_cpu(hdr->totallen);
59 while (tlv_offset < tlv_len) {
60 entry = (struct tlvinfo_tlv *)&eeprom[tlv_offset];
61
62 switch (entry->type) {
63 case TLV_CODE_PRODUCT_NAME:
64 store_product_name(entry, td);
65 break;
66 case TLV_CODE_VENDOR_EXT:
67 parse_tlv_vendor_ext(entry, td);
68 break;
69 default:
70 break;
71 }
72
73 tlv_offset += sizeof(struct tlvinfo_tlv) + entry->length;
74 }
75}
76
77void read_tlv_data(struct tlv_data *td)
78{
79 u8 eeprom_data[TLV_TOTAL_LEN_MAX];
80 struct tlvinfo_header *tlv_hdr;
81 struct tlvinfo_tlv *tlv_entry;
82 int ret, i;
83
84 for (i = 0; i < 2; i++) {
85 ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr,
86 &tlv_entry, i);
87 if (ret < 0)
88 continue;
89 parse_tlv_data(eeprom_data, tlv_hdr, tlv_entry, td);
90 }
91}
92
93bool sr_product_is(const struct tlv_data *td, const char *product)
94{
95 /* Allow prefix sub-string match */
96 if (strncmp(td->tlv_product_name[0], product, strlen(product)) == 0)
97 return true;
98 if (strncmp(td->tlv_product_name[1], product, strlen(product)) == 0)
99 return true;
100
101 return false;
102}