xref: /openbmc/openpower-vpd-parser/vpd-manager/src/parser_factory.cpp (revision 4c509c2b0035ae0bed0458b599018c9d47ae87cb)
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(std::string(__FUNCTION__) +
104                                  "Empty VPD vector passed to parser factory");
105     }
106 
107     vpdType l_type = vpdTypeCheck(i_vpdVector);
108 
109     switch (l_type)
110     {
111         case vpdType::IPZ_VPD:
112         {
113             return std::make_shared<IpzVpdParser>(i_vpdVector, i_vpdFilePath,
114                                                   i_vpdStartOffset);
115         }
116 
117         case vpdType::KEYWORD_VPD:
118         {
119             return std::make_shared<KeywordVpdParser>(i_vpdVector);
120         }
121 
122         case vpdType::DDR5_DDIMM_MEMORY_VPD:
123         case vpdType::DDR4_DDIMM_MEMORY_VPD:
124         {
125             return std::make_shared<DdimmVpdParser>(i_vpdVector);
126         }
127 
128         case vpdType::DDR4_ISDIMM_MEMORY_VPD:
129         case vpdType::DDR5_ISDIMM_MEMORY_VPD:
130         {
131             // return shared pointer to class object.
132             logging::logMessage(
133                 "ISDIMM parser selected for VPD path: " + i_vpdFilePath);
134             return std::make_shared<JedecSpdParser>(i_vpdVector);
135         }
136 
137         default:
138             throw DataException(
139                 std::string(__FUNCTION__) + "Unable to determine VPD format");
140     }
141 }
142 } // namespace vpd
143