xref: /openbmc/openpower-vpd-parser/vpd-manager/src/keyword_vpd_parser.cpp (revision fa5e4d325ef9cea3c841fe89d202c340f92bd8c6)
1*fa5e4d32SSunny Srivastava #include "keyword_vpd_parser.hpp"
2*fa5e4d32SSunny Srivastava 
3*fa5e4d32SSunny Srivastava #include "constants.hpp"
4*fa5e4d32SSunny Srivastava #include "exceptions.hpp"
5*fa5e4d32SSunny Srivastava #include "logger.hpp"
6*fa5e4d32SSunny Srivastava 
7*fa5e4d32SSunny Srivastava #include <iostream>
8*fa5e4d32SSunny Srivastava #include <numeric>
9*fa5e4d32SSunny Srivastava #include <string>
10*fa5e4d32SSunny Srivastava 
11*fa5e4d32SSunny Srivastava namespace vpd
12*fa5e4d32SSunny Srivastava {
13*fa5e4d32SSunny Srivastava 
parse()14*fa5e4d32SSunny Srivastava types::VPDMapVariant KeywordVpdParser::parse()
15*fa5e4d32SSunny Srivastava {
16*fa5e4d32SSunny Srivastava     if (m_keywordVpdVector.empty())
17*fa5e4d32SSunny Srivastava     {
18*fa5e4d32SSunny Srivastava         throw(DataException("Vector for Keyword format VPD is empty"));
19*fa5e4d32SSunny Srivastava     }
20*fa5e4d32SSunny Srivastava     m_vpdIterator = m_keywordVpdVector.begin();
21*fa5e4d32SSunny Srivastava 
22*fa5e4d32SSunny Srivastava     if (*m_vpdIterator != constants::KW_VPD_START_TAG)
23*fa5e4d32SSunny Srivastava     {
24*fa5e4d32SSunny Srivastava         throw(DataException("Invalid Large resource type Identifier String"));
25*fa5e4d32SSunny Srivastava     }
26*fa5e4d32SSunny Srivastava 
27*fa5e4d32SSunny Srivastava     checkNextBytesValidity(sizeof(constants::KW_VPD_START_TAG));
28*fa5e4d32SSunny Srivastava     std::advance(m_vpdIterator, sizeof(constants::KW_VPD_START_TAG));
29*fa5e4d32SSunny Srivastava 
30*fa5e4d32SSunny Srivastava     uint16_t l_dataSize = getKwDataSize();
31*fa5e4d32SSunny Srivastava 
32*fa5e4d32SSunny Srivastava     checkNextBytesValidity(constants::TWO_BYTES + l_dataSize);
33*fa5e4d32SSunny Srivastava     std::advance(m_vpdIterator, constants::TWO_BYTES + l_dataSize);
34*fa5e4d32SSunny Srivastava 
35*fa5e4d32SSunny Srivastava     // Check for invalid vendor defined large resource type
36*fa5e4d32SSunny Srivastava     if (*m_vpdIterator != constants::KW_VPD_PAIR_START_TAG)
37*fa5e4d32SSunny Srivastava     {
38*fa5e4d32SSunny Srivastava         if (*m_vpdIterator != constants::ALT_KW_VPD_PAIR_START_TAG)
39*fa5e4d32SSunny Srivastava         {
40*fa5e4d32SSunny Srivastava             throw(DataException("Invalid Keyword Vpd Start Tag"));
41*fa5e4d32SSunny Srivastava         }
42*fa5e4d32SSunny Srivastava     }
43*fa5e4d32SSunny Srivastava     types::BinaryVector::const_iterator l_checkSumStart = m_vpdIterator;
44*fa5e4d32SSunny Srivastava     auto l_kwValMap = populateVpdMap();
45*fa5e4d32SSunny Srivastava 
46*fa5e4d32SSunny Srivastava     // Do these validations before returning parsed data.
47*fa5e4d32SSunny Srivastava     // Check for small resource type end tag
48*fa5e4d32SSunny Srivastava     if (*m_vpdIterator != constants::KW_VAL_PAIR_END_TAG)
49*fa5e4d32SSunny Srivastava     {
50*fa5e4d32SSunny Srivastava         throw(DataException("Invalid Small resource type End"));
51*fa5e4d32SSunny Srivastava     }
52*fa5e4d32SSunny Srivastava 
53*fa5e4d32SSunny Srivastava     types::BinaryVector::const_iterator l_checkSumEnd = m_vpdIterator;
54*fa5e4d32SSunny Srivastava     validateChecksum(l_checkSumStart, l_checkSumEnd);
55*fa5e4d32SSunny Srivastava 
56*fa5e4d32SSunny Srivastava     checkNextBytesValidity(constants::TWO_BYTES);
57*fa5e4d32SSunny Srivastava     std::advance(m_vpdIterator, constants::TWO_BYTES);
58*fa5e4d32SSunny Srivastava 
59*fa5e4d32SSunny Srivastava     // Check VPD end Tag.
60*fa5e4d32SSunny Srivastava     if (*m_vpdIterator != constants::KW_VPD_END_TAG)
61*fa5e4d32SSunny Srivastava     {
62*fa5e4d32SSunny Srivastava         throw(DataException("Invalid Small resource type."));
63*fa5e4d32SSunny Srivastava     }
64*fa5e4d32SSunny Srivastava 
65*fa5e4d32SSunny Srivastava     return l_kwValMap;
66*fa5e4d32SSunny Srivastava }
67*fa5e4d32SSunny Srivastava 
populateVpdMap()68*fa5e4d32SSunny Srivastava types::KeywordVpdMap KeywordVpdParser::populateVpdMap()
69*fa5e4d32SSunny Srivastava {
70*fa5e4d32SSunny Srivastava     checkNextBytesValidity(constants::ONE_BYTE);
71*fa5e4d32SSunny Srivastava     std::advance(m_vpdIterator, constants::ONE_BYTE);
72*fa5e4d32SSunny Srivastava 
73*fa5e4d32SSunny Srivastava     auto l_totalSize = getKwDataSize();
74*fa5e4d32SSunny Srivastava     if (l_totalSize == 0)
75*fa5e4d32SSunny Srivastava     {
76*fa5e4d32SSunny Srivastava         throw(DataException("Data size is 0, badly formed keyword VPD"));
77*fa5e4d32SSunny Srivastava     }
78*fa5e4d32SSunny Srivastava 
79*fa5e4d32SSunny Srivastava     checkNextBytesValidity(constants::TWO_BYTES);
80*fa5e4d32SSunny Srivastava     std::advance(m_vpdIterator, constants::TWO_BYTES);
81*fa5e4d32SSunny Srivastava 
82*fa5e4d32SSunny Srivastava     types::KeywordVpdMap l_kwValMap;
83*fa5e4d32SSunny Srivastava 
84*fa5e4d32SSunny Srivastava     // Parse the keyword-value and store the pairs in map
85*fa5e4d32SSunny Srivastava     while (l_totalSize > 0)
86*fa5e4d32SSunny Srivastava     {
87*fa5e4d32SSunny Srivastava         checkNextBytesValidity(constants::TWO_BYTES);
88*fa5e4d32SSunny Srivastava         std::string l_keywordName(m_vpdIterator,
89*fa5e4d32SSunny Srivastava                                   m_vpdIterator + constants::TWO_BYTES);
90*fa5e4d32SSunny Srivastava         std::advance(m_vpdIterator, constants::TWO_BYTES);
91*fa5e4d32SSunny Srivastava 
92*fa5e4d32SSunny Srivastava         size_t l_kwSize = *m_vpdIterator;
93*fa5e4d32SSunny Srivastava         checkNextBytesValidity(constants::ONE_BYTE + l_kwSize);
94*fa5e4d32SSunny Srivastava         m_vpdIterator++;
95*fa5e4d32SSunny Srivastava         std::vector<uint8_t> l_valueBytes(m_vpdIterator,
96*fa5e4d32SSunny Srivastava                                           m_vpdIterator + l_kwSize);
97*fa5e4d32SSunny Srivastava         std::advance(m_vpdIterator, l_kwSize);
98*fa5e4d32SSunny Srivastava 
99*fa5e4d32SSunny Srivastava         l_kwValMap.emplace(
100*fa5e4d32SSunny Srivastava             std::make_pair(std::move(l_keywordName), std::move(l_valueBytes)));
101*fa5e4d32SSunny Srivastava 
102*fa5e4d32SSunny Srivastava         l_totalSize -= constants::TWO_BYTES + constants::ONE_BYTE + l_kwSize;
103*fa5e4d32SSunny Srivastava     }
104*fa5e4d32SSunny Srivastava 
105*fa5e4d32SSunny Srivastava     return l_kwValMap;
106*fa5e4d32SSunny Srivastava }
107*fa5e4d32SSunny Srivastava 
validateChecksum(types::BinaryVector::const_iterator i_checkSumStart,types::BinaryVector::const_iterator i_checkSumEnd)108*fa5e4d32SSunny Srivastava void KeywordVpdParser::validateChecksum(
109*fa5e4d32SSunny Srivastava     types::BinaryVector::const_iterator i_checkSumStart,
110*fa5e4d32SSunny Srivastava     types::BinaryVector::const_iterator i_checkSumEnd)
111*fa5e4d32SSunny Srivastava {
112*fa5e4d32SSunny Srivastava     uint8_t l_checkSumCalculated = 0;
113*fa5e4d32SSunny Srivastava 
114*fa5e4d32SSunny Srivastava     // Checksum calculation
115*fa5e4d32SSunny Srivastava     l_checkSumCalculated =
116*fa5e4d32SSunny Srivastava         std::accumulate(i_checkSumStart, i_checkSumEnd, l_checkSumCalculated);
117*fa5e4d32SSunny Srivastava     l_checkSumCalculated = ~l_checkSumCalculated + 1;
118*fa5e4d32SSunny Srivastava     uint8_t l_checksumVpdValue = *(m_vpdIterator + constants::ONE_BYTE);
119*fa5e4d32SSunny Srivastava 
120*fa5e4d32SSunny Srivastava     if (l_checkSumCalculated != l_checksumVpdValue)
121*fa5e4d32SSunny Srivastava     {
122*fa5e4d32SSunny Srivastava         throw(DataException("Invalid Checksum"));
123*fa5e4d32SSunny Srivastava     }
124*fa5e4d32SSunny Srivastava }
125*fa5e4d32SSunny Srivastava 
checkNextBytesValidity(uint8_t i_numberOfBytes)126*fa5e4d32SSunny Srivastava void KeywordVpdParser::checkNextBytesValidity(uint8_t i_numberOfBytes)
127*fa5e4d32SSunny Srivastava {
128*fa5e4d32SSunny Srivastava     if ((std::distance(m_keywordVpdVector.begin(),
129*fa5e4d32SSunny Srivastava                        m_vpdIterator + i_numberOfBytes)) >
130*fa5e4d32SSunny Srivastava         std::distance(m_keywordVpdVector.begin(), m_keywordVpdVector.end()))
131*fa5e4d32SSunny Srivastava     {
132*fa5e4d32SSunny Srivastava         throw(DataException("Truncated VPD data"));
133*fa5e4d32SSunny Srivastava     }
134*fa5e4d32SSunny Srivastava }
135*fa5e4d32SSunny Srivastava 
136*fa5e4d32SSunny Srivastava } // namespace vpd
137