blob: 9e147b5edce7ddaf8ae47bbb4ca8aa531a9c879c [file] [log] [blame]
#include "keyword_vpd_parser.hpp"
#include "const.hpp"
#include <iostream>
#include <numeric>
#include <string>
namespace vpd
{
namespace keyword
{
namespace parser
{
using namespace openpower::vpd::constants;
using namespace openpower::vpd::inventory;
KeywordVpdMap KeywordVpdParser::parseKwVpd()
{
int kwVpdType;
if (keywordVpdVector.empty())
{
throw std::runtime_error("Blank Vpd Data");
}
validateLargeResourceIdentifierString();
kwVpdType = validateTheTypeOfKwVpd();
auto kwValMap = kwValParser();
// Donot process these two functions for bono type VPD
if (!kwVpdType)
{
validateSmallResourceTypeEnd();
validateChecksum();
}
validateSmallResourceTypeLastEnd();
#ifdef DEBUG_KW_VPD
cerr << '\n' << " KW " << '\t' << " VALUE " << '\n';
for (const auto& it : kwValMap)
{
cerr << '\n' << " " << it->first << '\t';
copy((it->second).begin(), (it->second).end(),
ostream_iterator<int>(cout << hex, " "));
}
#endif
return kwValMap;
}
void KeywordVpdParser::validateLargeResourceIdentifierString()
{
kwVpdIterator = keywordVpdVector.begin();
// Check for large resource type identfier string
if (*kwVpdIterator != KW_VPD_START_TAG)
{
throw std::runtime_error(
"Invalid Large resource type Identifier String");
}
itrOutOfBoundCheck(1);
advance(kwVpdIterator, sizeof(KW_VPD_START_TAG));
}
int KeywordVpdParser::validateTheTypeOfKwVpd()
{
size_t dataSize = getKwDataSize();
itrOutOfBoundCheck(TWO_BYTES + dataSize);
#ifdef DEBUG_KW_VPD
auto dsDeb = dataSize;
auto itDeb = kwVpdIterator + TWO_BYTES;
std::cout << '\n' << '\t';
while (dsDeb != 0)
{
std::cout << *itDeb;
itDeb++;
dsDeb--;
}
std::cout << '\n';
#endif
// +TWO_BYTES is the description's size byte
std::advance(kwVpdIterator, TWO_BYTES + dataSize);
int kwVpdType = 0;
// Check for invalid vendor defined large resource type
if (*kwVpdIterator != KW_VAL_PAIR_START_TAG)
{
if (*kwVpdIterator != ALT_KW_VAL_PAIR_START_TAG)
{
throw std::runtime_error("Invalid Keyword Value Pair Start Tag");
}
// Bono vpd referred as 1
kwVpdType = 1;
}
return kwVpdType;
}
KeywordVpdMap KeywordVpdParser::kwValParser()
{
int totalSize = 0;
KeywordVpdMap kwValMap;
checkSumStart = kwVpdIterator;
itrOutOfBoundCheck(1);
kwVpdIterator++;
// Get the total length of all keyword value pairs
totalSize = getKwDataSize();
if (totalSize == 0)
{
throw std::runtime_error("Badly formed keyword VPD data");
}
itrOutOfBoundCheck(TWO_BYTES);
std::advance(kwVpdIterator, TWO_BYTES);
// Parse the keyword-value and store the pairs in map
while (totalSize > 0)
{
std::string kwStr(kwVpdIterator, kwVpdIterator + TWO_BYTES);
totalSize -= TWO_BYTES;
itrOutOfBoundCheck(TWO_BYTES);
std::advance(kwVpdIterator, TWO_BYTES);
size_t kwSize = *kwVpdIterator;
itrOutOfBoundCheck(1);
kwVpdIterator++;
std::vector<uint8_t> valVec(kwVpdIterator, kwVpdIterator + kwSize);
itrOutOfBoundCheck(kwSize);
std::advance(kwVpdIterator, kwSize);
totalSize -= kwSize + 1;
kwValMap.emplace(std::make_pair(std::move(kwStr), std::move(valVec)));
}
checkSumEnd = kwVpdIterator - 1;
return kwValMap;
}
void KeywordVpdParser::validateSmallResourceTypeEnd()
{
// Check for small resource type end tag
if (*kwVpdIterator != KW_VAL_PAIR_END_TAG)
{
throw std::runtime_error("Invalid Small resource type End");
}
}
void KeywordVpdParser::validateChecksum()
{
uint8_t checkSum = 0;
// Checksum calculation
checkSum = std::accumulate(checkSumStart, checkSumEnd + 1, checkSum);
checkSum = ~checkSum + 1;
if (checkSum != *(kwVpdIterator + 1))
{
throw std::runtime_error("Invalid Check sum");
}
#ifdef DEBUG_KW_VPD
std::cout << "\nCHECKSUM : " << std::hex << static_cast<int>(checkSum)
<< std::endl;
#endif
itrOutOfBoundCheck(TWO_BYTES);
std::advance(kwVpdIterator, TWO_BYTES);
}
void KeywordVpdParser::validateSmallResourceTypeLastEnd()
{
// Check for small resource type last end of data
if (*kwVpdIterator != KW_VPD_END_TAG)
{
throw std::runtime_error(
"Invalid Small resource type Last End Of Data");
}
}
size_t KeywordVpdParser::getKwDataSize()
{
return (*(kwVpdIterator + 1) << 8 | *kwVpdIterator);
}
void KeywordVpdParser::itrOutOfBoundCheck(uint8_t incVar)
{
if ((std::distance(keywordVpdVector.begin(), kwVpdIterator + incVar)) >
std::distance(keywordVpdVector.begin(), keywordVpdVector.end()))
{
throw std::runtime_error("Badly formed VPD data");
}
}
} // namespace parser
} // namespace keyword
} // namespace vpd