1 #include "parser_factory.hpp"
2
3 #include "constants.hpp"
4 #include "ddimm_parser.hpp"
5 #include "exceptions.hpp"
6 #include "ipz_parser.hpp"
7 #include "isdimm_parser.hpp"
8 #include "keyword_vpd_parser.hpp"
9
10 namespace vpd
11 {
12
13 /**
14 * @brief Type of VPD formats.
15 */
16 enum vpdType
17 {
18 IPZ_VPD, /**< IPZ VPD type */
19 KEYWORD_VPD, /**< Keyword VPD type */
20 DDR4_DDIMM_MEMORY_VPD, /**< DDR4 DDIMM Memory VPD type */
21 DDR5_DDIMM_MEMORY_VPD, /**< DDR5 DDIMM Memory VPD type */
22 DDR4_ISDIMM_MEMORY_VPD, /**< DDR4 ISDIMM Memory VPD type */
23 DDR5_ISDIMM_MEMORY_VPD, /**< DDR5 ISDIMM Memory VPD type */
24 INVALID_VPD_FORMAT /**< Invalid VPD type */
25 };
26
27 /**
28 * @brief API to get the type of VPD.
29 *
30 * @param[in] i_vpdVector - VPD file content
31 *
32 * @return Type of VPD data, "INVALID_VPD_FORMAT" in case of unknown type.
33 */
vpdTypeCheck(const types::BinaryVector & i_vpdVector)34 static vpdType vpdTypeCheck(const types::BinaryVector& i_vpdVector)
35 {
36 if (i_vpdVector[constants::IPZ_DATA_START] == constants::IPZ_DATA_START_TAG)
37 {
38 return vpdType::IPZ_VPD;
39 }
40 else if (i_vpdVector[constants::KW_VPD_DATA_START] ==
41 constants::KW_VPD_START_TAG)
42 {
43 return vpdType::KEYWORD_VPD;
44 }
45 else if (((i_vpdVector[constants::SPD_BYTE_3] &
46 constants::SPD_BYTE_BIT_0_3_MASK) ==
47 constants::SPD_MODULE_TYPE_DDIMM))
48 {
49 std::string l_is11SFormat;
50 if (i_vpdVector.size() > (constants::DDIMM_11S_BARCODE_START +
51 constants::DDIMM_11S_BARCODE_LEN))
52 {
53 // Read first 3 Bytes to check the 11S bar code format
54 for (uint8_t l_index = 0; l_index < constants::DDIMM_11S_FORMAT_LEN;
55 l_index++)
56 {
57 l_is11SFormat +=
58 i_vpdVector[constants::DDIMM_11S_BARCODE_START + l_index];
59 }
60 }
61
62 if (l_is11SFormat.compare(constants::DDIMM_11S_BARCODE_START_TAG) == 0)
63 {
64 // DDIMM memory VPD format
65 if ((i_vpdVector[constants::SPD_BYTE_2] &
66 constants::SPD_BYTE_MASK) == constants::SPD_DRAM_TYPE_DDR5)
67 {
68 return vpdType::DDR5_DDIMM_MEMORY_VPD;
69 }
70
71 if ((i_vpdVector[constants::SPD_BYTE_2] &
72 constants::SPD_BYTE_MASK) == constants::SPD_DRAM_TYPE_DDR4)
73 {
74 return vpdType::DDR4_DDIMM_MEMORY_VPD;
75 }
76 }
77
78 logging::logMessage("11S format is not found in the DDIMM VPD.");
79 return vpdType::INVALID_VPD_FORMAT;
80 }
81 else if ((i_vpdVector[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
82 constants::SPD_DRAM_TYPE_DDR5)
83 {
84 // ISDIMM memory VPD format
85 return vpdType::DDR5_ISDIMM_MEMORY_VPD;
86 }
87 else if ((i_vpdVector[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
88 constants::SPD_DRAM_TYPE_DDR4)
89 {
90 // ISDIMM memory VPD format
91 return vpdType::DDR4_ISDIMM_MEMORY_VPD;
92 }
93
94 return vpdType::INVALID_VPD_FORMAT;
95 }
96
getParser(const types::BinaryVector & i_vpdVector,const std::string & i_vpdFilePath,size_t i_vpdStartOffset)97 std::shared_ptr<ParserInterface> ParserFactory::getParser(
98 const types::BinaryVector& i_vpdVector, const std::string& i_vpdFilePath,
99 size_t i_vpdStartOffset)
100 {
101 if (i_vpdVector.empty())
102 {
103 throw std::runtime_error("Empty VPD vector passed to parser factory");
104 }
105
106 vpdType l_type = vpdTypeCheck(i_vpdVector);
107
108 switch (l_type)
109 {
110 case vpdType::IPZ_VPD:
111 {
112 return std::make_shared<IpzVpdParser>(i_vpdVector, i_vpdFilePath,
113 i_vpdStartOffset);
114 }
115
116 case vpdType::KEYWORD_VPD:
117 {
118 return std::make_shared<KeywordVpdParser>(i_vpdVector);
119 }
120
121 case vpdType::DDR5_DDIMM_MEMORY_VPD:
122 case vpdType::DDR4_DDIMM_MEMORY_VPD:
123 {
124 return std::make_shared<DdimmVpdParser>(i_vpdVector);
125 }
126
127 case vpdType::DDR4_ISDIMM_MEMORY_VPD:
128 case vpdType::DDR5_ISDIMM_MEMORY_VPD:
129 {
130 // return shared pointer to class object.
131 logging::logMessage(
132 "ISDIMM parser selected for VPD path: " + i_vpdFilePath);
133 return std::make_shared<JedecSpdParser>(i_vpdVector);
134 }
135
136 default:
137 throw DataException("Unable to determine VPD format");
138 }
139 }
140 } // namespace vpd
141