tlv_data.c 2.4 KB

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