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