1*0b02be92SPatrick Venture #include "ipmi_fru_info_area.hpp" 2*0b02be92SPatrick Venture 37d9157edSMarri Devender Rao #include <algorithm> 4*0b02be92SPatrick Venture #include <ctime> 57d9157edSMarri Devender Rao #include <map> 67d9157edSMarri Devender Rao #include <numeric> 77d9157edSMarri Devender Rao #include <phosphor-logging/elog.hpp> 87d9157edSMarri Devender Rao namespace ipmi 97d9157edSMarri Devender Rao { 107d9157edSMarri Devender Rao namespace fru 117d9157edSMarri Devender Rao { 127d9157edSMarri Devender Rao using namespace phosphor::logging; 137d9157edSMarri Devender Rao 147d9157edSMarri Devender Rao // Property variables 157d9157edSMarri Devender Rao static constexpr auto partNumber = "PartNumber"; 167d9157edSMarri Devender Rao static constexpr auto serialNumber = "SerialNumber"; 177d9157edSMarri Devender Rao static constexpr auto manufacturer = "Manufacturer"; 187d9157edSMarri Devender Rao static constexpr auto buildDate = "BuildDate"; 197d9157edSMarri Devender Rao static constexpr auto model = "Model"; 207d9157edSMarri Devender Rao static constexpr auto prettyName = "PrettyName"; 217d9157edSMarri Devender Rao static constexpr auto version = "Version"; 227d9157edSMarri Devender Rao 237d9157edSMarri Devender Rao // Board info areas 247d9157edSMarri Devender Rao static constexpr auto board = "Board"; 257d9157edSMarri Devender Rao static constexpr auto chassis = "Chassis"; 267d9157edSMarri Devender Rao static constexpr auto product = "Product"; 277d9157edSMarri Devender Rao 287d9157edSMarri Devender Rao static constexpr auto specVersion = 0x1; 293e6a769bSRatan Gupta static constexpr auto recordUnitOfMeasurement = 0x8; // size in bytes 307d9157edSMarri Devender Rao static constexpr auto checksumSize = 0x1; // size in bytes 317d9157edSMarri Devender Rao static constexpr auto recordNotPresent = 0x0; 327d9157edSMarri Devender Rao static constexpr auto englishLanguageCode = 0x0; 337d9157edSMarri Devender Rao static constexpr auto typeLengthByteNull = 0x0; 347d9157edSMarri Devender Rao static constexpr auto endOfCustomFields = 0xC1; 357d9157edSMarri Devender Rao static constexpr auto commonHeaderFormatSize = 0x8; // size in bytes 367d9157edSMarri Devender Rao static constexpr auto manufacturingDateSize = 0x3; 377d9157edSMarri Devender Rao static constexpr auto areaSizeOffset = 0x1; 386edfc5c1SRatan Gupta static constexpr uint8_t typeASCII = 0xC0; 396edfc5c1SRatan Gupta static constexpr auto maxRecordAttributeValue = 0x1F; 407d9157edSMarri Devender Rao 417ebd2464SAndres Oportus static constexpr auto secs_from_1970_1996 = 820454400; 42b898cde6SNagaraju Goruganti static constexpr auto maxMfgDateValue = 0xFFFFFF; // 3 Byte length 437ebd2464SAndres Oportus static constexpr auto secs_per_min = 60; 44*0b02be92SPatrick Venture static constexpr auto secsToMaxMfgdate = 45*0b02be92SPatrick Venture secs_from_1970_1996 + secs_per_min * maxMfgDateValue; 467ebd2464SAndres Oportus 477d9157edSMarri Devender Rao /** 487d9157edSMarri Devender Rao * @brief Format Beginning of Individual IPMI FRU Data Section 497d9157edSMarri Devender Rao * 507d9157edSMarri Devender Rao * @param[in] langCode Language code 517d9157edSMarri Devender Rao * @param[in/out] data FRU area data 527d9157edSMarri Devender Rao */ 537d9157edSMarri Devender Rao void preFormatProcessing(bool langCode, FruAreaData& data) 547d9157edSMarri Devender Rao { 557d9157edSMarri Devender Rao // Add id for version of FRU Info Storage Spec used 567d9157edSMarri Devender Rao data.emplace_back(specVersion); 577d9157edSMarri Devender Rao 587d9157edSMarri Devender Rao // Add Data Size - 0 as a placeholder, can edit after the data is finalized 597d9157edSMarri Devender Rao data.emplace_back(typeLengthByteNull); 607d9157edSMarri Devender Rao 617d9157edSMarri Devender Rao if (langCode) 627d9157edSMarri Devender Rao { 637d9157edSMarri Devender Rao data.emplace_back(englishLanguageCode); 647d9157edSMarri Devender Rao } 657d9157edSMarri Devender Rao } 667d9157edSMarri Devender Rao 677d9157edSMarri Devender Rao /** 687d9157edSMarri Devender Rao * @brief Append checksum of the FRU area data 697d9157edSMarri Devender Rao * 707d9157edSMarri Devender Rao * @param[in/out] data FRU area data 717d9157edSMarri Devender Rao */ 727d9157edSMarri Devender Rao void appendDataChecksum(FruAreaData& data) 737d9157edSMarri Devender Rao { 747d9157edSMarri Devender Rao uint8_t checksumVal = std::accumulate(data.begin(), data.end(), 0); 757d9157edSMarri Devender Rao // Push the Zero checksum as the last byte of this data 767d9157edSMarri Devender Rao // This appears to be a simple summation of all the bytes 777d9157edSMarri Devender Rao data.emplace_back(-checksumVal); 787d9157edSMarri Devender Rao } 797d9157edSMarri Devender Rao 807d9157edSMarri Devender Rao /** 817d9157edSMarri Devender Rao * @brief Append padding bytes for the FRU area data 827d9157edSMarri Devender Rao * 837d9157edSMarri Devender Rao * @param[in/out] data FRU area data 847d9157edSMarri Devender Rao */ 857d9157edSMarri Devender Rao void padData(FruAreaData& data) 867d9157edSMarri Devender Rao { 873e6a769bSRatan Gupta uint8_t pad = (data.size() + checksumSize) % recordUnitOfMeasurement; 887d9157edSMarri Devender Rao if (pad) 897d9157edSMarri Devender Rao { 903e6a769bSRatan Gupta data.resize((data.size() + recordUnitOfMeasurement - pad)); 917d9157edSMarri Devender Rao } 927d9157edSMarri Devender Rao } 937d9157edSMarri Devender Rao 947d9157edSMarri Devender Rao /** 957d9157edSMarri Devender Rao * @brief Format End of Individual IPMI FRU Data Section 967d9157edSMarri Devender Rao * 977d9157edSMarri Devender Rao * @param[in/out] fruAreaData FRU area info data 987d9157edSMarri Devender Rao */ 997d9157edSMarri Devender Rao void postFormatProcessing(FruAreaData& data) 1007d9157edSMarri Devender Rao { 1017d9157edSMarri Devender Rao // This area needs to be padded to a multiple of 8 bytes (after checksum) 1027d9157edSMarri Devender Rao padData(data); 1037d9157edSMarri Devender Rao 1047d9157edSMarri Devender Rao // Set size of data info area 105*0b02be92SPatrick Venture data.at(areaSizeOffset) = 106*0b02be92SPatrick Venture (data.size() + checksumSize) / (recordUnitOfMeasurement); 1077d9157edSMarri Devender Rao 1082f66f00eSRatan Gupta // Finally add area checksum 1097d9157edSMarri Devender Rao appendDataChecksum(data); 1107d9157edSMarri Devender Rao } 1117d9157edSMarri Devender Rao 1127d9157edSMarri Devender Rao /** 1137d9157edSMarri Devender Rao * @brief Read property value from inventory and append to the FRU area data 1147d9157edSMarri Devender Rao * 1157d9157edSMarri Devender Rao * @param[in] key key to search for in the property inventory data 1167d9157edSMarri Devender Rao * @param[in] propMap map of property values 1177d9157edSMarri Devender Rao * @param[in,out] data FRU area data to be appended 1187d9157edSMarri Devender Rao */ 1197d9157edSMarri Devender Rao void appendData(const Property& key, const PropertyMap& propMap, 1207d9157edSMarri Devender Rao FruAreaData& data) 1217d9157edSMarri Devender Rao { 1227d9157edSMarri Devender Rao auto iter = propMap.find(key); 1237d9157edSMarri Devender Rao if (iter != propMap.end()) 1247d9157edSMarri Devender Rao { 1257d9157edSMarri Devender Rao auto value = iter->second; 1267d9157edSMarri Devender Rao // If starts with 0x or 0X remove them 1277d9157edSMarri Devender Rao // ex: 0x123a just take 123a 1287d9157edSMarri Devender Rao if ((value.compare(0, 2, "0x")) == 0 || 1297d9157edSMarri Devender Rao (value.compare(0, 2, "0X") == 0)) 1307d9157edSMarri Devender Rao { 1317d9157edSMarri Devender Rao value.erase(0, 2); 1327d9157edSMarri Devender Rao } 1336edfc5c1SRatan Gupta 1346edfc5c1SRatan Gupta // 5 bits for length 135*0b02be92SPatrick Venture // if length is greater then 31(2^5) bytes then trim the data to 31 136*0b02be92SPatrick Venture // bytess. 137*0b02be92SPatrick Venture auto valueLength = (value.length() > maxRecordAttributeValue) 138*0b02be92SPatrick Venture ? maxRecordAttributeValue 139*0b02be92SPatrick Venture : value.length(); 1406edfc5c1SRatan Gupta // 2 bits for type 1416edfc5c1SRatan Gupta // Set the type to ascii 1426edfc5c1SRatan Gupta uint8_t typeLength = valueLength | ipmi::fru::typeASCII; 1436edfc5c1SRatan Gupta 1446edfc5c1SRatan Gupta data.emplace_back(typeLength); 145*0b02be92SPatrick Venture std::copy(value.begin(), value.begin() + valueLength, 1466edfc5c1SRatan Gupta std::back_inserter(data)); 1477d9157edSMarri Devender Rao } 1487d9157edSMarri Devender Rao else 1497d9157edSMarri Devender Rao { 1507d9157edSMarri Devender Rao // set 0 size 1517d9157edSMarri Devender Rao data.emplace_back(typeLengthByteNull); 1527d9157edSMarri Devender Rao } 1537d9157edSMarri Devender Rao } 1547d9157edSMarri Devender Rao 1557d9157edSMarri Devender Rao /** 1567d9157edSMarri Devender Rao * @brief Appends Build Date 1577d9157edSMarri Devender Rao * 1587d9157edSMarri Devender Rao * @param[in] propMap map of property values 1597d9157edSMarri Devender Rao * @param[in/out] data FRU area to add the manfufacture date 1607d9157edSMarri Devender Rao */ 1617d9157edSMarri Devender Rao void appendMfgDate(const PropertyMap& propMap, FruAreaData& data) 1627d9157edSMarri Devender Rao { 1637d9157edSMarri Devender Rao // MFG Date/Time 1647d9157edSMarri Devender Rao auto iter = propMap.find(buildDate); 165b898cde6SNagaraju Goruganti if ((iter != propMap.end()) && (iter->second.size() > 0)) 1667d9157edSMarri Devender Rao { 1677ebd2464SAndres Oportus tm time = {}; 1687ebd2464SAndres Oportus strptime(iter->second.c_str(), "%F - %H:%M:%S", &time); 1697ebd2464SAndres Oportus time_t raw = mktime(&time); 1707ebd2464SAndres Oportus 1717ebd2464SAndres Oportus // From FRU Spec: 1727ebd2464SAndres Oportus // "Mfg. Date / Time 1737ebd2464SAndres Oportus // Number of minutes from 0:00 hrs 1/1/96. 1747ebd2464SAndres Oportus // LSbyte first (little endian) 1757ebd2464SAndres Oportus // 00_00_00h = unspecified." 176b898cde6SNagaraju Goruganti if ((raw >= secs_from_1970_1996) && (raw <= secsToMaxMfgdate)) 1777d9157edSMarri Devender Rao { 1787ebd2464SAndres Oportus raw -= secs_from_1970_1996; 1797ebd2464SAndres Oportus raw /= secs_per_min; 1807ebd2464SAndres Oportus uint8_t fru_raw[3]; 1817ebd2464SAndres Oportus fru_raw[0] = raw & 0xFF; 1827ebd2464SAndres Oportus fru_raw[1] = (raw >> 8) & 0xFF; 1837ebd2464SAndres Oportus fru_raw[2] = (raw >> 16) & 0xFF; 1847ebd2464SAndres Oportus std::copy(fru_raw, fru_raw + 3, std::back_inserter(data)); 1857d9157edSMarri Devender Rao return; 1867d9157edSMarri Devender Rao } 1877ebd2464SAndres Oportus fprintf(stderr, "MgfDate invalid date: %u secs since UNIX epoch\n", 1887ebd2464SAndres Oportus static_cast<unsigned int>(raw)); 1897d9157edSMarri Devender Rao } 1907d9157edSMarri Devender Rao // Blank date 1917d9157edSMarri Devender Rao data.emplace_back(0); 1927d9157edSMarri Devender Rao data.emplace_back(0); 1937d9157edSMarri Devender Rao data.emplace_back(0); 1947d9157edSMarri Devender Rao } 1957d9157edSMarri Devender Rao 1967d9157edSMarri Devender Rao /** 1977d9157edSMarri Devender Rao * @brief Builds a section of the common header 1987d9157edSMarri Devender Rao * 1997d9157edSMarri Devender Rao * @param[in] infoAreaSize size of the FRU area to write 2007d9157edSMarri Devender Rao * @param[in] offset Current offset for data in overall record 2017d9157edSMarri Devender Rao * @param[in/out] data Common Header section data container 2027d9157edSMarri Devender Rao */ 203*0b02be92SPatrick Venture void buildCommonHeaderSection(const uint32_t& infoAreaSize, uint16_t& offset, 204*0b02be92SPatrick Venture FruAreaData& data) 2057d9157edSMarri Devender Rao { 2067d9157edSMarri Devender Rao // Check if data for internal use section populated 2077d9157edSMarri Devender Rao if (infoAreaSize == 0) 2087d9157edSMarri Devender Rao { 2097d9157edSMarri Devender Rao // Indicate record not present 2107d9157edSMarri Devender Rao data.emplace_back(recordNotPresent); 2117d9157edSMarri Devender Rao } 2127d9157edSMarri Devender Rao else 2137d9157edSMarri Devender Rao { 2142f66f00eSRatan Gupta // offset should be multiple of 8. 2153e6a769bSRatan Gupta auto remainder = offset % recordUnitOfMeasurement; 2162f66f00eSRatan Gupta // add the padding bytes in the offset so that offset 2172f66f00eSRatan Gupta // will be multiple of 8 byte. 2183e6a769bSRatan Gupta offset += (remainder > 0) ? recordUnitOfMeasurement - remainder : 0; 2197d9157edSMarri Devender Rao // Place data to define offset to area data section 2203e6a769bSRatan Gupta data.emplace_back(offset / recordUnitOfMeasurement); 2212f66f00eSRatan Gupta 2227d9157edSMarri Devender Rao offset += infoAreaSize; 2237d9157edSMarri Devender Rao } 2247d9157edSMarri Devender Rao } 2257d9157edSMarri Devender Rao 2267d9157edSMarri Devender Rao /** 2277d9157edSMarri Devender Rao * @brief Builds the Chassis info area data section 2287d9157edSMarri Devender Rao * 2297d9157edSMarri Devender Rao * @param[in] propMap map of properties for chassis info area 2307d9157edSMarri Devender Rao * @return FruAreaData container with chassis info area 2317d9157edSMarri Devender Rao */ 2327d9157edSMarri Devender Rao FruAreaData buildChassisInfoArea(const PropertyMap& propMap) 2337d9157edSMarri Devender Rao { 2347d9157edSMarri Devender Rao FruAreaData fruAreaData; 2357d9157edSMarri Devender Rao if (!propMap.empty()) 2367d9157edSMarri Devender Rao { 2377d9157edSMarri Devender Rao // Set formatting data that goes at the beginning of the record 2387d9157edSMarri Devender Rao preFormatProcessing(false, fruAreaData); 2397d9157edSMarri Devender Rao 2407d9157edSMarri Devender Rao // chassis type 2417d9157edSMarri Devender Rao fruAreaData.emplace_back(0); 2427d9157edSMarri Devender Rao 2437d9157edSMarri Devender Rao // Chasiss part number, in config.yaml it is configured as model 2447d9157edSMarri Devender Rao appendData(model, propMap, fruAreaData); 2457d9157edSMarri Devender Rao 2467d9157edSMarri Devender Rao // Board serial number 2477d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 2487d9157edSMarri Devender Rao 2497d9157edSMarri Devender Rao // Indicate End of Custom Fields 2507d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 2517d9157edSMarri Devender Rao 2527d9157edSMarri Devender Rao // Complete record data formatting 2537d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 2547d9157edSMarri Devender Rao } 2557d9157edSMarri Devender Rao return fruAreaData; 2567d9157edSMarri Devender Rao } 2577d9157edSMarri Devender Rao 2587d9157edSMarri Devender Rao /** 2597d9157edSMarri Devender Rao * @brief Builds the Board info area data section 2607d9157edSMarri Devender Rao * 2617d9157edSMarri Devender Rao * @param[in] propMap map of properties for board info area 2627d9157edSMarri Devender Rao * @return FruAreaData container with board info area 2637d9157edSMarri Devender Rao */ 2647d9157edSMarri Devender Rao FruAreaData buildBoardInfoArea(const PropertyMap& propMap) 2657d9157edSMarri Devender Rao { 2667d9157edSMarri Devender Rao FruAreaData fruAreaData; 2677d9157edSMarri Devender Rao if (!propMap.empty()) 2687d9157edSMarri Devender Rao { 2697d9157edSMarri Devender Rao preFormatProcessing(true, fruAreaData); 2707d9157edSMarri Devender Rao 2717d9157edSMarri Devender Rao // Manufacturing date 2727d9157edSMarri Devender Rao appendMfgDate(propMap, fruAreaData); 2737d9157edSMarri Devender Rao 2747d9157edSMarri Devender Rao // manufacturer 2757d9157edSMarri Devender Rao appendData(manufacturer, propMap, fruAreaData); 2767d9157edSMarri Devender Rao 2777d9157edSMarri Devender Rao // Product name/Pretty name 2787d9157edSMarri Devender Rao appendData(prettyName, propMap, fruAreaData); 2797d9157edSMarri Devender Rao 2807d9157edSMarri Devender Rao // Board serial number 2817d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 2827d9157edSMarri Devender Rao 2837d9157edSMarri Devender Rao // Board part number 2847d9157edSMarri Devender Rao appendData(partNumber, propMap, fruAreaData); 2857d9157edSMarri Devender Rao 2867d9157edSMarri Devender Rao // FRU File ID - Empty 2877d9157edSMarri Devender Rao fruAreaData.emplace_back(typeLengthByteNull); 2887d9157edSMarri Devender Rao 2897d9157edSMarri Devender Rao // Empty FRU File ID bytes 2907d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 2917d9157edSMarri Devender Rao 2927d9157edSMarri Devender Rao // End of custom fields 2937d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 2947d9157edSMarri Devender Rao 2957d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 2967d9157edSMarri Devender Rao } 2977d9157edSMarri Devender Rao return fruAreaData; 2987d9157edSMarri Devender Rao } 2997d9157edSMarri Devender Rao 3007d9157edSMarri Devender Rao /** 3017d9157edSMarri Devender Rao * @brief Builds the Product info area data section 3027d9157edSMarri Devender Rao * 3037d9157edSMarri Devender Rao * @param[in] propMap map of FRU properties for Board info area 3047d9157edSMarri Devender Rao * @return FruAreaData container with product info area data 3057d9157edSMarri Devender Rao */ 3067d9157edSMarri Devender Rao FruAreaData buildProductInfoArea(const PropertyMap& propMap) 3077d9157edSMarri Devender Rao { 3087d9157edSMarri Devender Rao FruAreaData fruAreaData; 3097d9157edSMarri Devender Rao if (!propMap.empty()) 3107d9157edSMarri Devender Rao { 3117d9157edSMarri Devender Rao // Set formatting data that goes at the beginning of the record 3127d9157edSMarri Devender Rao preFormatProcessing(true, fruAreaData); 3137d9157edSMarri Devender Rao 3147d9157edSMarri Devender Rao // manufacturer 3157d9157edSMarri Devender Rao appendData(manufacturer, propMap, fruAreaData); 3167d9157edSMarri Devender Rao 3177d9157edSMarri Devender Rao // Product name/Pretty name 3187d9157edSMarri Devender Rao appendData(prettyName, propMap, fruAreaData); 3197d9157edSMarri Devender Rao 3207d9157edSMarri Devender Rao // Product part/model number 3217d9157edSMarri Devender Rao appendData(model, propMap, fruAreaData); 3227d9157edSMarri Devender Rao 3237d9157edSMarri Devender Rao // Product version 3247d9157edSMarri Devender Rao appendData(version, propMap, fruAreaData); 3257d9157edSMarri Devender Rao 3267d9157edSMarri Devender Rao // Serial Number 3277d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 3287d9157edSMarri Devender Rao 3297d9157edSMarri Devender Rao // Add Asset Tag 3307d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 3317d9157edSMarri Devender Rao 3327d9157edSMarri Devender Rao // FRU File ID - Empty 3337d9157edSMarri Devender Rao fruAreaData.emplace_back(typeLengthByteNull); 3347d9157edSMarri Devender Rao 3357d9157edSMarri Devender Rao // Empty FRU File ID bytes 3367d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 3377d9157edSMarri Devender Rao 3387d9157edSMarri Devender Rao // End of custom fields 3397d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 3407d9157edSMarri Devender Rao 3417d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 3427d9157edSMarri Devender Rao } 3437d9157edSMarri Devender Rao return fruAreaData; 3447d9157edSMarri Devender Rao } 3457d9157edSMarri Devender Rao 3467d9157edSMarri Devender Rao FruAreaData buildFruAreaData(const FruInventoryData& inventory) 3477d9157edSMarri Devender Rao { 3482f66f00eSRatan Gupta FruAreaData combFruArea{}; 3497d9157edSMarri Devender Rao // Now build common header with data for this FRU Inv Record 3507d9157edSMarri Devender Rao // Use this variable to increment size of header as we go along to determine 3517d9157edSMarri Devender Rao // offset for the subsequent area offsets 3522f66f00eSRatan Gupta uint16_t curDataOffset = commonHeaderFormatSize; 3537d9157edSMarri Devender Rao // First byte is id for version of FRU Info Storage Spec used 3547d9157edSMarri Devender Rao combFruArea.emplace_back(specVersion); 3557d9157edSMarri Devender Rao 3567d9157edSMarri Devender Rao // 2nd byte is offset to internal use data 3577d9157edSMarri Devender Rao combFruArea.emplace_back(recordNotPresent); 3587d9157edSMarri Devender Rao 3597d9157edSMarri Devender Rao // 3rd byte is offset to chassis data 3607d9157edSMarri Devender Rao FruAreaData chassisArea; 3617d9157edSMarri Devender Rao auto chassisIt = inventory.find(chassis); 3627d9157edSMarri Devender Rao if (chassisIt != inventory.end()) 3637d9157edSMarri Devender Rao { 3647d9157edSMarri Devender Rao chassisArea = std::move(buildChassisInfoArea(chassisIt->second)); 3657d9157edSMarri Devender Rao } 3662f66f00eSRatan Gupta // update the offset to chassis data. 3677d9157edSMarri Devender Rao buildCommonHeaderSection(chassisArea.size(), curDataOffset, combFruArea); 3687d9157edSMarri Devender Rao 3697d9157edSMarri Devender Rao // 4th byte is offset to board data 3707d9157edSMarri Devender Rao FruAreaData boardArea; 3717d9157edSMarri Devender Rao auto boardIt = inventory.find(board); 3727d9157edSMarri Devender Rao if (boardIt != inventory.end()) 3737d9157edSMarri Devender Rao { 3747d9157edSMarri Devender Rao boardArea = std::move(buildBoardInfoArea(boardIt->second)); 3757d9157edSMarri Devender Rao } 3762f66f00eSRatan Gupta // update the offset to the board data. 3772f66f00eSRatan Gupta buildCommonHeaderSection(boardArea.size(), curDataOffset, combFruArea); 3787d9157edSMarri Devender Rao 3797d9157edSMarri Devender Rao // 5th byte is offset to product data 3807d9157edSMarri Devender Rao FruAreaData prodArea; 3817d9157edSMarri Devender Rao auto prodIt = inventory.find(product); 3827d9157edSMarri Devender Rao if (prodIt != inventory.end()) 3837d9157edSMarri Devender Rao { 3847d9157edSMarri Devender Rao prodArea = std::move(buildProductInfoArea(prodIt->second)); 3857d9157edSMarri Devender Rao } 3862f66f00eSRatan Gupta // update the offset to the product data. 3877d9157edSMarri Devender Rao buildCommonHeaderSection(prodArea.size(), curDataOffset, combFruArea); 3887d9157edSMarri Devender Rao 3897d9157edSMarri Devender Rao // 6th byte is offset to multirecord data 3907d9157edSMarri Devender Rao combFruArea.emplace_back(recordNotPresent); 3917d9157edSMarri Devender Rao 3927d9157edSMarri Devender Rao // 7th byte is PAD 3932f66f00eSRatan Gupta combFruArea.emplace_back(recordNotPresent); 3947d9157edSMarri Devender Rao 3957d9157edSMarri Devender Rao // 8th (Final byte of Header Format) is the checksum 3967d9157edSMarri Devender Rao appendDataChecksum(combFruArea); 3977d9157edSMarri Devender Rao 3987d9157edSMarri Devender Rao // Combine everything into one full IPMI FRU specification Record 3997d9157edSMarri Devender Rao // add chassis use area data 400*0b02be92SPatrick Venture combFruArea.insert(combFruArea.end(), chassisArea.begin(), 401*0b02be92SPatrick Venture chassisArea.end()); 4027d9157edSMarri Devender Rao 4037d9157edSMarri Devender Rao // add board area data 4047d9157edSMarri Devender Rao combFruArea.insert(combFruArea.end(), boardArea.begin(), boardArea.end()); 4057d9157edSMarri Devender Rao 4067d9157edSMarri Devender Rao // add product use area data 4077d9157edSMarri Devender Rao combFruArea.insert(combFruArea.end(), prodArea.begin(), prodArea.end()); 4087d9157edSMarri Devender Rao 4097d9157edSMarri Devender Rao return combFruArea; 4107d9157edSMarri Devender Rao } 4117d9157edSMarri Devender Rao 412*0b02be92SPatrick Venture } // namespace fru 413*0b02be92SPatrick Venture } // namespace ipmi 414