xref: /openbmc/openpower-vpd-parser/vpd-manager/src/parser_factory.cpp (revision fa5e4d325ef9cea3c841fe89d202c340f92bd8c6)
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