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