17d9157edSMarri Devender Rao #include <algorithm>
27d9157edSMarri Devender Rao #include <map>
37d9157edSMarri Devender Rao #include <numeric>
47d9157edSMarri Devender Rao #include "ipmi_fru_info_area.hpp"
57d9157edSMarri Devender Rao #include <phosphor-logging/elog.hpp>
67d9157edSMarri Devender Rao namespace ipmi
77d9157edSMarri Devender Rao {
87d9157edSMarri Devender Rao namespace fru
97d9157edSMarri Devender Rao {
107d9157edSMarri Devender Rao using namespace phosphor::logging;
117d9157edSMarri Devender Rao 
127d9157edSMarri Devender Rao //Property variables
137d9157edSMarri Devender Rao static constexpr auto partNumber       = "PartNumber";
147d9157edSMarri Devender Rao static constexpr auto serialNumber     = "SerialNumber";
157d9157edSMarri Devender Rao static constexpr auto manufacturer     = "Manufacturer";
167d9157edSMarri Devender Rao static constexpr auto buildDate        = "BuildDate";
177d9157edSMarri Devender Rao static constexpr auto model            = "Model";
187d9157edSMarri Devender Rao static constexpr auto prettyName       = "PrettyName";
197d9157edSMarri Devender Rao static constexpr auto version          = "Version";
207d9157edSMarri Devender Rao 
217d9157edSMarri Devender Rao //Board info areas
227d9157edSMarri Devender Rao static constexpr auto board            = "Board";
237d9157edSMarri Devender Rao static constexpr auto chassis          = "Chassis";
247d9157edSMarri Devender Rao static constexpr auto product          = "Product";
257d9157edSMarri Devender Rao 
267d9157edSMarri Devender Rao static constexpr auto specVersion              = 0x1;
277d9157edSMarri Devender Rao static constexpr auto recordUnitOfMeasurment   = 0x8; //size in bytes
287d9157edSMarri Devender Rao static constexpr auto checksumSize             = 0x1; //size in bytes
297d9157edSMarri Devender Rao static constexpr auto recordNotPresent         = 0x0;
307d9157edSMarri Devender Rao static constexpr auto englishLanguageCode      = 0x0;
317d9157edSMarri Devender Rao static constexpr auto typeLengthByteNull       = 0x0;
327d9157edSMarri Devender Rao static constexpr auto endOfCustomFields        = 0xC1;
337d9157edSMarri Devender Rao static constexpr auto commonHeaderFormatSize   = 0x8; //size in bytes
347d9157edSMarri Devender Rao static constexpr auto manufacturingDateSize     = 0x3;
357d9157edSMarri Devender Rao static constexpr auto areaSizeOffset           = 0x1;
36*6edfc5c1SRatan Gupta static constexpr uint8_t typeASCII             = 0xC0;
37*6edfc5c1SRatan Gupta static constexpr auto maxRecordAttributeValue  = 0x1F;
387d9157edSMarri Devender Rao 
397d9157edSMarri Devender Rao /**
407d9157edSMarri Devender Rao  * @brief Format Beginning of Individual IPMI FRU Data Section
417d9157edSMarri Devender Rao  *
427d9157edSMarri Devender Rao  * @param[in] langCode Language code
437d9157edSMarri Devender Rao  * @param[in/out] data FRU area data
447d9157edSMarri Devender Rao  */
457d9157edSMarri Devender Rao void preFormatProcessing(bool langCode, FruAreaData& data)
467d9157edSMarri Devender Rao {
477d9157edSMarri Devender Rao     //Add id for version of FRU Info Storage Spec used
487d9157edSMarri Devender Rao     data.emplace_back(specVersion);
497d9157edSMarri Devender Rao 
507d9157edSMarri Devender Rao     //Add Data Size - 0 as a placeholder, can edit after the data is finalized
517d9157edSMarri Devender Rao     data.emplace_back(typeLengthByteNull);
527d9157edSMarri Devender Rao 
537d9157edSMarri Devender Rao     if (langCode)
547d9157edSMarri Devender Rao     {
557d9157edSMarri Devender Rao         data.emplace_back(englishLanguageCode);
567d9157edSMarri Devender Rao     }
577d9157edSMarri Devender Rao }
587d9157edSMarri Devender Rao 
597d9157edSMarri Devender Rao /**
607d9157edSMarri Devender Rao  * @brief Append checksum of the FRU area data
617d9157edSMarri Devender Rao  *
627d9157edSMarri Devender Rao  * @param[in/out] data FRU area data
637d9157edSMarri Devender Rao  */
647d9157edSMarri Devender Rao void appendDataChecksum(FruAreaData& data)
657d9157edSMarri Devender Rao {
667d9157edSMarri Devender Rao     uint8_t checksumVal = std::accumulate(data.begin(), data.end(), 0);
677d9157edSMarri Devender Rao     // Push the Zero checksum as the last byte of this data
687d9157edSMarri Devender Rao     // This appears to be a simple summation of all the bytes
697d9157edSMarri Devender Rao     data.emplace_back(-checksumVal);
707d9157edSMarri Devender Rao }
717d9157edSMarri Devender Rao 
727d9157edSMarri Devender Rao /**
737d9157edSMarri Devender Rao  * @brief Append padding bytes for the FRU area data
747d9157edSMarri Devender Rao  *
757d9157edSMarri Devender Rao  * @param[in/out] data FRU area data
767d9157edSMarri Devender Rao  */
777d9157edSMarri Devender Rao void padData(FruAreaData& data)
787d9157edSMarri Devender Rao {
797d9157edSMarri Devender Rao     uint8_t pad = (data.size() + checksumSize) % recordUnitOfMeasurment;
807d9157edSMarri Devender Rao     if (pad)
817d9157edSMarri Devender Rao     {
827d9157edSMarri Devender Rao         data.resize((data.size() + recordUnitOfMeasurment - pad));
837d9157edSMarri Devender Rao     }
847d9157edSMarri Devender Rao }
857d9157edSMarri Devender Rao 
867d9157edSMarri Devender Rao /**
877d9157edSMarri Devender Rao  * @brief Format End of Individual IPMI FRU Data Section
887d9157edSMarri Devender Rao  *
897d9157edSMarri Devender Rao  * @param[in/out] fruAreaData FRU area info data
907d9157edSMarri Devender Rao  */
917d9157edSMarri Devender Rao void postFormatProcessing(FruAreaData& data)
927d9157edSMarri Devender Rao {
937d9157edSMarri Devender Rao     //This area needs to be padded to a multiple of 8 bytes (after checksum)
947d9157edSMarri Devender Rao     padData(data);
957d9157edSMarri Devender Rao 
967d9157edSMarri Devender Rao     //Set size of data info area
977d9157edSMarri Devender Rao     data.at(areaSizeOffset) = (data.size() + checksumSize) /
987d9157edSMarri Devender Rao         (recordUnitOfMeasurment);
997d9157edSMarri Devender Rao 
1002f66f00eSRatan Gupta     //Finally add area checksum
1017d9157edSMarri Devender Rao     appendDataChecksum(data);
1027d9157edSMarri Devender Rao }
1037d9157edSMarri Devender Rao 
1047d9157edSMarri Devender Rao /**
1057d9157edSMarri Devender Rao  * @brief Read property value from inventory and append to the FRU area data
1067d9157edSMarri Devender Rao  *
1077d9157edSMarri Devender Rao  * @param[in] key key to search for in the property inventory data
1087d9157edSMarri Devender Rao  * @param[in] propMap map of property values
1097d9157edSMarri Devender Rao  * @param[in,out] data FRU area data to be appended
1107d9157edSMarri Devender Rao  */
1117d9157edSMarri Devender Rao void appendData(const Property& key, const PropertyMap& propMap,
1127d9157edSMarri Devender Rao                 FruAreaData& data)
1137d9157edSMarri Devender Rao {
1147d9157edSMarri Devender Rao     auto iter = propMap.find(key);
1157d9157edSMarri Devender Rao     if (iter != propMap.end())
1167d9157edSMarri Devender Rao     {
1177d9157edSMarri Devender Rao         auto value = iter->second;
1187d9157edSMarri Devender Rao         //If starts with 0x or 0X remove them
1197d9157edSMarri Devender Rao         //ex: 0x123a just take 123a
1207d9157edSMarri Devender Rao         if ((value.compare(0, 2, "0x")) == 0 ||
1217d9157edSMarri Devender Rao            (value.compare(0, 2, "0X") == 0))
1227d9157edSMarri Devender Rao         {
1237d9157edSMarri Devender Rao             value.erase(0, 2);
1247d9157edSMarri Devender Rao         }
125*6edfc5c1SRatan Gupta 
126*6edfc5c1SRatan Gupta         // 5 bits for length
127*6edfc5c1SRatan Gupta         // if length is greater then 31(2^5) bytes then trim the data to 31 bytess.
128*6edfc5c1SRatan Gupta         auto valueLength =  (value.length() > maxRecordAttributeValue) ?
129*6edfc5c1SRatan Gupta             maxRecordAttributeValue : value.length();
130*6edfc5c1SRatan Gupta         // 2 bits for type
131*6edfc5c1SRatan Gupta         // Set the type to ascii
132*6edfc5c1SRatan Gupta         uint8_t typeLength = valueLength | ipmi::fru::typeASCII;
133*6edfc5c1SRatan Gupta 
134*6edfc5c1SRatan Gupta         data.emplace_back(typeLength);
135*6edfc5c1SRatan Gupta         std::copy(value.begin(),
136*6edfc5c1SRatan Gupta                   value.begin() + valueLength,
137*6edfc5c1SRatan Gupta                   std::back_inserter(data));
1387d9157edSMarri Devender Rao     }
1397d9157edSMarri Devender Rao     else
1407d9157edSMarri Devender Rao     {
1417d9157edSMarri Devender Rao         //set 0 size
1427d9157edSMarri Devender Rao         data.emplace_back(typeLengthByteNull);
1437d9157edSMarri Devender Rao     }
1447d9157edSMarri Devender Rao }
1457d9157edSMarri Devender Rao 
1467d9157edSMarri Devender Rao 
1477d9157edSMarri Devender Rao /**
1487d9157edSMarri Devender Rao  * @brief Appends Build Date
1497d9157edSMarri Devender Rao  *
1507d9157edSMarri Devender Rao  * @param[in] propMap map of property values
1517d9157edSMarri Devender Rao  * @param[in/out] data FRU area to add the manfufacture date
1527d9157edSMarri Devender Rao  */
1537d9157edSMarri Devender Rao void appendMfgDate(const PropertyMap& propMap, FruAreaData& data)
1547d9157edSMarri Devender Rao {
1557d9157edSMarri Devender Rao     //MFG Date/Time
1567d9157edSMarri Devender Rao     auto iter = propMap.find(buildDate);
1577d9157edSMarri Devender Rao     if (iter != propMap.end())
1587d9157edSMarri Devender Rao     {
1597d9157edSMarri Devender Rao         auto& value = iter->second;
1607d9157edSMarri Devender Rao         if (value.length() == manufacturingDateSize)
1617d9157edSMarri Devender Rao         {
1627d9157edSMarri Devender Rao             std::copy(
1637d9157edSMarri Devender Rao                 value.begin(), value.end(), std::back_inserter(data));
1647d9157edSMarri Devender Rao             return;
1657d9157edSMarri Devender Rao         }
1667d9157edSMarri Devender Rao     }
1677d9157edSMarri Devender Rao     //Blank date
1687d9157edSMarri Devender Rao     data.emplace_back(0);
1697d9157edSMarri Devender Rao     data.emplace_back(0);
1707d9157edSMarri Devender Rao     data.emplace_back(0);
1717d9157edSMarri Devender Rao }
1727d9157edSMarri Devender Rao 
1737d9157edSMarri Devender Rao /**
1747d9157edSMarri Devender Rao  * @brief Builds a section of the common header
1757d9157edSMarri Devender Rao  *
1767d9157edSMarri Devender Rao  * @param[in] infoAreaSize size of the FRU area to write
1777d9157edSMarri Devender Rao  * @param[in] offset Current offset for data in overall record
1787d9157edSMarri Devender Rao  * @param[in/out] data Common Header section data container
1797d9157edSMarri Devender Rao  */
1807d9157edSMarri Devender Rao void buildCommonHeaderSection(
1812f66f00eSRatan Gupta     const uint32_t& infoAreaSize, uint16_t& offset, FruAreaData& data)
1827d9157edSMarri Devender Rao {
1837d9157edSMarri Devender Rao     //Check if data for internal use section populated
1847d9157edSMarri Devender Rao     if (infoAreaSize == 0)
1857d9157edSMarri Devender Rao     {
1867d9157edSMarri Devender Rao         //Indicate record not present
1877d9157edSMarri Devender Rao         data.emplace_back(recordNotPresent);
1887d9157edSMarri Devender Rao     }
1897d9157edSMarri Devender Rao     else
1907d9157edSMarri Devender Rao     {
1912f66f00eSRatan Gupta         // offset should be multiple of 8.
1922f66f00eSRatan Gupta         auto remainder = offset % recordUnitOfMeasurment;
1932f66f00eSRatan Gupta         // add the padding bytes in the offset so that offset
1942f66f00eSRatan Gupta         // will be multiple of 8 byte.
1952f66f00eSRatan Gupta         offset += (remainder > 0) ? recordUnitOfMeasurment - remainder : 0;
1967d9157edSMarri Devender Rao         //Place data to define offset to area data section
1972f66f00eSRatan Gupta         data.emplace_back(offset / recordUnitOfMeasurment);
1982f66f00eSRatan Gupta 
1997d9157edSMarri Devender Rao         offset += infoAreaSize;
2007d9157edSMarri Devender Rao     }
2017d9157edSMarri Devender Rao }
2027d9157edSMarri Devender Rao 
2037d9157edSMarri Devender Rao /**
2047d9157edSMarri Devender Rao  * @brief Builds the Chassis info area data section
2057d9157edSMarri Devender Rao  *
2067d9157edSMarri Devender Rao  * @param[in] propMap map of properties for chassis info area
2077d9157edSMarri Devender Rao  * @return FruAreaData container with chassis info area
2087d9157edSMarri Devender Rao  */
2097d9157edSMarri Devender Rao FruAreaData buildChassisInfoArea(const PropertyMap& propMap)
2107d9157edSMarri Devender Rao {
2117d9157edSMarri Devender Rao     FruAreaData fruAreaData;
2127d9157edSMarri Devender Rao     if (!propMap.empty())
2137d9157edSMarri Devender Rao     {
2147d9157edSMarri Devender Rao         //Set formatting data that goes at the beginning of the record
2157d9157edSMarri Devender Rao         preFormatProcessing(false, fruAreaData);
2167d9157edSMarri Devender Rao 
2177d9157edSMarri Devender Rao         //chassis type
2187d9157edSMarri Devender Rao         fruAreaData.emplace_back(0);
2197d9157edSMarri Devender Rao 
2207d9157edSMarri Devender Rao         //Chasiss part number, in config.yaml it is configured as model
2217d9157edSMarri Devender Rao         appendData(model, propMap, fruAreaData);
2227d9157edSMarri Devender Rao 
2237d9157edSMarri Devender Rao         //Board serial number
2247d9157edSMarri Devender Rao         appendData(serialNumber, propMap, fruAreaData);
2257d9157edSMarri Devender Rao 
2267d9157edSMarri Devender Rao         //Indicate End of Custom Fields
2277d9157edSMarri Devender Rao         fruAreaData.emplace_back(endOfCustomFields);
2287d9157edSMarri Devender Rao 
2297d9157edSMarri Devender Rao         //Complete record data formatting
2307d9157edSMarri Devender Rao         postFormatProcessing(fruAreaData);
2317d9157edSMarri Devender Rao     }
2327d9157edSMarri Devender Rao     return fruAreaData;
2337d9157edSMarri Devender Rao }
2347d9157edSMarri Devender Rao 
2357d9157edSMarri Devender Rao /**
2367d9157edSMarri Devender Rao  * @brief Builds the Board info area data section
2377d9157edSMarri Devender Rao  *
2387d9157edSMarri Devender Rao  * @param[in] propMap map of properties for board info area
2397d9157edSMarri Devender Rao  * @return FruAreaData container with board info area
2407d9157edSMarri Devender Rao  */
2417d9157edSMarri Devender Rao FruAreaData buildBoardInfoArea(const PropertyMap& propMap)
2427d9157edSMarri Devender Rao {
2437d9157edSMarri Devender Rao     FruAreaData fruAreaData;
2447d9157edSMarri Devender Rao     if (!propMap.empty())
2457d9157edSMarri Devender Rao     {
2467d9157edSMarri Devender Rao         preFormatProcessing(true, fruAreaData);
2477d9157edSMarri Devender Rao 
2487d9157edSMarri Devender Rao         //Manufacturing date
2497d9157edSMarri Devender Rao         appendMfgDate(propMap, fruAreaData);
2507d9157edSMarri Devender Rao 
2517d9157edSMarri Devender Rao         //manufacturer
2527d9157edSMarri Devender Rao         appendData(manufacturer, propMap, fruAreaData);
2537d9157edSMarri Devender Rao 
2547d9157edSMarri Devender Rao         //Product name/Pretty name
2557d9157edSMarri Devender Rao         appendData(prettyName, propMap, fruAreaData);
2567d9157edSMarri Devender Rao 
2577d9157edSMarri Devender Rao         //Board serial number
2587d9157edSMarri Devender Rao         appendData(serialNumber, propMap, fruAreaData);
2597d9157edSMarri Devender Rao 
2607d9157edSMarri Devender Rao         //Board part number
2617d9157edSMarri Devender Rao         appendData(partNumber, propMap, fruAreaData);
2627d9157edSMarri Devender Rao 
2637d9157edSMarri Devender Rao         //FRU File ID - Empty
2647d9157edSMarri Devender Rao         fruAreaData.emplace_back(typeLengthByteNull);
2657d9157edSMarri Devender Rao 
2667d9157edSMarri Devender Rao         // Empty FRU File ID bytes
2677d9157edSMarri Devender Rao         fruAreaData.emplace_back(recordNotPresent);
2687d9157edSMarri Devender Rao 
2697d9157edSMarri Devender Rao         //End of custom fields
2707d9157edSMarri Devender Rao         fruAreaData.emplace_back(endOfCustomFields);
2717d9157edSMarri Devender Rao 
2727d9157edSMarri Devender Rao         postFormatProcessing(fruAreaData);
2737d9157edSMarri Devender Rao     }
2747d9157edSMarri Devender Rao     return fruAreaData;
2757d9157edSMarri Devender Rao }
2767d9157edSMarri Devender Rao 
2777d9157edSMarri Devender Rao /**
2787d9157edSMarri Devender Rao  * @brief Builds the Product info area data section
2797d9157edSMarri Devender Rao  *
2807d9157edSMarri Devender Rao  * @param[in] propMap map of FRU properties for Board info area
2817d9157edSMarri Devender Rao  * @return FruAreaData container with product info area data
2827d9157edSMarri Devender Rao  */
2837d9157edSMarri Devender Rao FruAreaData buildProductInfoArea(const PropertyMap& propMap)
2847d9157edSMarri Devender Rao {
2857d9157edSMarri Devender Rao     FruAreaData fruAreaData;
2867d9157edSMarri Devender Rao     if (!propMap.empty())
2877d9157edSMarri Devender Rao     {
2887d9157edSMarri Devender Rao         //Set formatting data that goes at the beginning of the record
2897d9157edSMarri Devender Rao         preFormatProcessing(true, fruAreaData);
2907d9157edSMarri Devender Rao 
2917d9157edSMarri Devender Rao         //manufacturer
2927d9157edSMarri Devender Rao         appendData(manufacturer, propMap, fruAreaData);
2937d9157edSMarri Devender Rao 
2947d9157edSMarri Devender Rao         //Product name/Pretty name
2957d9157edSMarri Devender Rao         appendData(prettyName, propMap, fruAreaData);
2967d9157edSMarri Devender Rao 
2977d9157edSMarri Devender Rao         //Product part/model number
2987d9157edSMarri Devender Rao         appendData(model, propMap, fruAreaData);
2997d9157edSMarri Devender Rao 
3007d9157edSMarri Devender Rao         //Product version
3017d9157edSMarri Devender Rao         appendData(version, propMap, fruAreaData);
3027d9157edSMarri Devender Rao 
3037d9157edSMarri Devender Rao         //Serial Number
3047d9157edSMarri Devender Rao         appendData(serialNumber, propMap, fruAreaData);
3057d9157edSMarri Devender Rao 
3067d9157edSMarri Devender Rao         //Add Asset Tag
3077d9157edSMarri Devender Rao         fruAreaData.emplace_back(recordNotPresent);
3087d9157edSMarri Devender Rao 
3097d9157edSMarri Devender Rao         //FRU File ID - Empty
3107d9157edSMarri Devender Rao         fruAreaData.emplace_back(typeLengthByteNull);
3117d9157edSMarri Devender Rao 
3127d9157edSMarri Devender Rao         // Empty FRU File ID bytes
3137d9157edSMarri Devender Rao         fruAreaData.emplace_back(recordNotPresent);
3147d9157edSMarri Devender Rao 
3157d9157edSMarri Devender Rao         //End of custom fields
3167d9157edSMarri Devender Rao         fruAreaData.emplace_back(endOfCustomFields);
3177d9157edSMarri Devender Rao 
3187d9157edSMarri Devender Rao         postFormatProcessing(fruAreaData);
3197d9157edSMarri Devender Rao     }
3207d9157edSMarri Devender Rao     return fruAreaData;
3217d9157edSMarri Devender Rao }
3227d9157edSMarri Devender Rao 
3237d9157edSMarri Devender Rao FruAreaData buildFruAreaData(const FruInventoryData& inventory)
3247d9157edSMarri Devender Rao {
3252f66f00eSRatan Gupta     FruAreaData combFruArea{};
3267d9157edSMarri Devender Rao     //Now build common header with data for this FRU Inv Record
3277d9157edSMarri Devender Rao     //Use this variable to increment size of header as we go along to determine
3287d9157edSMarri Devender Rao     //offset for the subsequent area offsets
3292f66f00eSRatan Gupta     uint16_t curDataOffset = commonHeaderFormatSize;
3307d9157edSMarri Devender Rao     //First byte is id for version of FRU Info Storage Spec used
3317d9157edSMarri Devender Rao     combFruArea.emplace_back(specVersion);
3327d9157edSMarri Devender Rao 
3337d9157edSMarri Devender Rao     //2nd byte is offset to internal use data
3347d9157edSMarri Devender Rao     combFruArea.emplace_back(recordNotPresent);
3357d9157edSMarri Devender Rao 
3367d9157edSMarri Devender Rao     //3rd byte is offset to chassis data
3377d9157edSMarri Devender Rao     FruAreaData chassisArea;
3387d9157edSMarri Devender Rao     auto chassisIt = inventory.find(chassis);
3397d9157edSMarri Devender Rao     if (chassisIt != inventory.end())
3407d9157edSMarri Devender Rao     {
3417d9157edSMarri Devender Rao         chassisArea = std::move(buildChassisInfoArea(chassisIt->second));
3427d9157edSMarri Devender Rao     }
3432f66f00eSRatan Gupta     // update the offset to chassis data.
3447d9157edSMarri Devender Rao     buildCommonHeaderSection(chassisArea.size(), curDataOffset, combFruArea);
3457d9157edSMarri Devender Rao 
3467d9157edSMarri Devender Rao     //4th byte is offset to board data
3477d9157edSMarri Devender Rao     FruAreaData boardArea;
3487d9157edSMarri Devender Rao     auto boardIt = inventory.find(board);
3497d9157edSMarri Devender Rao     if (boardIt != inventory.end())
3507d9157edSMarri Devender Rao     {
3517d9157edSMarri Devender Rao         boardArea = std::move(buildBoardInfoArea(boardIt->second));
3527d9157edSMarri Devender Rao     }
3532f66f00eSRatan Gupta     // update the offset to the board data.
3542f66f00eSRatan Gupta     buildCommonHeaderSection(boardArea.size(), curDataOffset, combFruArea);
3557d9157edSMarri Devender Rao 
3567d9157edSMarri Devender Rao     //5th byte is offset to product data
3577d9157edSMarri Devender Rao     FruAreaData prodArea;
3587d9157edSMarri Devender Rao     auto prodIt = inventory.find(product);
3597d9157edSMarri Devender Rao     if (prodIt != inventory.end())
3607d9157edSMarri Devender Rao     {
3617d9157edSMarri Devender Rao         prodArea = std::move(buildProductInfoArea(prodIt->second));
3627d9157edSMarri Devender Rao     }
3632f66f00eSRatan Gupta     // update the offset to the product data.
3647d9157edSMarri Devender Rao     buildCommonHeaderSection(prodArea.size(), curDataOffset, combFruArea);
3657d9157edSMarri Devender Rao 
3667d9157edSMarri Devender Rao     //6th byte is offset to multirecord data
3677d9157edSMarri Devender Rao     combFruArea.emplace_back(recordNotPresent);
3687d9157edSMarri Devender Rao 
3697d9157edSMarri Devender Rao     //7th byte is PAD
3702f66f00eSRatan Gupta     combFruArea.emplace_back(recordNotPresent);
3717d9157edSMarri Devender Rao 
3727d9157edSMarri Devender Rao     //8th (Final byte of Header Format) is the checksum
3737d9157edSMarri Devender Rao     appendDataChecksum(combFruArea);
3747d9157edSMarri Devender Rao 
3757d9157edSMarri Devender Rao     //Combine everything into one full IPMI FRU specification Record
3767d9157edSMarri Devender Rao     //add chassis use area data
3777d9157edSMarri Devender Rao     combFruArea.insert(
3787d9157edSMarri Devender Rao             combFruArea.end(), chassisArea.begin(), chassisArea.end());
3797d9157edSMarri Devender Rao 
3807d9157edSMarri Devender Rao     //add board area data
3817d9157edSMarri Devender Rao     combFruArea.insert(combFruArea.end(), boardArea.begin(), boardArea.end());
3827d9157edSMarri Devender Rao 
3837d9157edSMarri Devender Rao     //add product use area data
3847d9157edSMarri Devender Rao     combFruArea.insert(combFruArea.end(), prodArea.begin(), prodArea.end());
3857d9157edSMarri Devender Rao 
3867d9157edSMarri Devender Rao     return combFruArea;
3877d9157edSMarri Devender Rao }
3887d9157edSMarri Devender Rao 
3897d9157edSMarri Devender Rao } //fru
3907d9157edSMarri Devender Rao } //ipmi
391