10b02be92SPatrick Venture #include "ipmi_fru_info_area.hpp" 20b02be92SPatrick Venture 37d9157edSMarri Devender Rao #include <algorithm> 40b02be92SPatrick Venture #include <ctime> 57d9157edSMarri Devender Rao #include <map> 67d9157edSMarri Devender Rao #include <numeric> 77d9157edSMarri Devender Rao #include <phosphor-logging/elog.hpp> 8b51bf9c8SPatrick Venture 97d9157edSMarri Devender Rao namespace ipmi 107d9157edSMarri Devender Rao { 117d9157edSMarri Devender Rao namespace fru 127d9157edSMarri Devender Rao { 137d9157edSMarri Devender Rao using namespace phosphor::logging; 147d9157edSMarri Devender Rao 157d9157edSMarri Devender Rao // Property variables 167d9157edSMarri Devender Rao static constexpr auto partNumber = "PartNumber"; 177d9157edSMarri Devender Rao static constexpr auto serialNumber = "SerialNumber"; 187d9157edSMarri Devender Rao static constexpr auto manufacturer = "Manufacturer"; 197d9157edSMarri Devender Rao static constexpr auto buildDate = "BuildDate"; 207d9157edSMarri Devender Rao static constexpr auto model = "Model"; 217d9157edSMarri Devender Rao static constexpr auto prettyName = "PrettyName"; 227d9157edSMarri Devender Rao static constexpr auto version = "Version"; 2340f59e2cSOskar Senft static constexpr auto type = "Type"; 247d9157edSMarri Devender Rao 257d9157edSMarri Devender Rao // Board info areas 267d9157edSMarri Devender Rao static constexpr auto board = "Board"; 277d9157edSMarri Devender Rao static constexpr auto chassis = "Chassis"; 287d9157edSMarri Devender Rao static constexpr auto product = "Product"; 297d9157edSMarri Devender Rao 307d9157edSMarri Devender Rao static constexpr auto specVersion = 0x1; 313e6a769bSRatan Gupta static constexpr auto recordUnitOfMeasurement = 0x8; // size in bytes 327d9157edSMarri Devender Rao static constexpr auto checksumSize = 0x1; // size in bytes 337d9157edSMarri Devender Rao static constexpr auto recordNotPresent = 0x0; 347d9157edSMarri Devender Rao static constexpr auto englishLanguageCode = 0x0; 357d9157edSMarri Devender Rao static constexpr auto typeLengthByteNull = 0x0; 367d9157edSMarri Devender Rao static constexpr auto endOfCustomFields = 0xC1; 377d9157edSMarri Devender Rao static constexpr auto commonHeaderFormatSize = 0x8; // size in bytes 387d9157edSMarri Devender Rao static constexpr auto manufacturingDateSize = 0x3; 397d9157edSMarri Devender Rao static constexpr auto areaSizeOffset = 0x1; 406edfc5c1SRatan Gupta static constexpr uint8_t typeASCII = 0xC0; 416edfc5c1SRatan Gupta static constexpr auto maxRecordAttributeValue = 0x1F; 427d9157edSMarri Devender Rao 437ebd2464SAndres Oportus static constexpr auto secs_from_1970_1996 = 820454400; 44b898cde6SNagaraju Goruganti static constexpr auto maxMfgDateValue = 0xFFFFFF; // 3 Byte length 457ebd2464SAndres Oportus static constexpr auto secs_per_min = 60; 460b02be92SPatrick Venture static constexpr auto secsToMaxMfgdate = 470b02be92SPatrick Venture secs_from_1970_1996 + secs_per_min * maxMfgDateValue; 487ebd2464SAndres Oportus 49*8b18941dSOskar Senft // Minimum size of resulting FRU blob. 50*8b18941dSOskar Senft // This is also the theoretical maximum size according to the spec: 51*8b18941dSOskar Senft // 8 bytes header + 5 areas at 0xff*8 bytes max each 52*8b18941dSOskar Senft // 8 + 5*0xff*8 = 0x27e0 53*8b18941dSOskar Senft static constexpr auto fruMinSize = 0x27E0; 54*8b18941dSOskar Senft 55*8b18941dSOskar Senft // Value to use for padding. 56*8b18941dSOskar Senft // Using 0xff to match the default (blank) value in a physical EEPROM. 57*8b18941dSOskar Senft static constexpr auto fruPadValue = 0xff; 58*8b18941dSOskar Senft 597d9157edSMarri Devender Rao /** 607d9157edSMarri Devender Rao * @brief Format Beginning of Individual IPMI FRU Data Section 617d9157edSMarri Devender Rao * 627d9157edSMarri Devender Rao * @param[in] langCode Language code 637d9157edSMarri Devender Rao * @param[in/out] data FRU area data 647d9157edSMarri Devender Rao */ 657d9157edSMarri Devender Rao void preFormatProcessing(bool langCode, FruAreaData& data) 667d9157edSMarri Devender Rao { 677d9157edSMarri Devender Rao // Add id for version of FRU Info Storage Spec used 687d9157edSMarri Devender Rao data.emplace_back(specVersion); 697d9157edSMarri Devender Rao 707d9157edSMarri Devender Rao // Add Data Size - 0 as a placeholder, can edit after the data is finalized 717d9157edSMarri Devender Rao data.emplace_back(typeLengthByteNull); 727d9157edSMarri Devender Rao 737d9157edSMarri Devender Rao if (langCode) 747d9157edSMarri Devender Rao { 757d9157edSMarri Devender Rao data.emplace_back(englishLanguageCode); 767d9157edSMarri Devender Rao } 777d9157edSMarri Devender Rao } 787d9157edSMarri Devender Rao 797d9157edSMarri Devender Rao /** 807d9157edSMarri Devender Rao * @brief Append checksum of the FRU area data 817d9157edSMarri Devender Rao * 827d9157edSMarri Devender Rao * @param[in/out] data FRU area data 837d9157edSMarri Devender Rao */ 847d9157edSMarri Devender Rao void appendDataChecksum(FruAreaData& data) 857d9157edSMarri Devender Rao { 867d9157edSMarri Devender Rao uint8_t checksumVal = std::accumulate(data.begin(), data.end(), 0); 877d9157edSMarri Devender Rao // Push the Zero checksum as the last byte of this data 887d9157edSMarri Devender Rao // This appears to be a simple summation of all the bytes 897d9157edSMarri Devender Rao data.emplace_back(-checksumVal); 907d9157edSMarri Devender Rao } 917d9157edSMarri Devender Rao 927d9157edSMarri Devender Rao /** 937d9157edSMarri Devender Rao * @brief Append padding bytes for the FRU area data 947d9157edSMarri Devender Rao * 957d9157edSMarri Devender Rao * @param[in/out] data FRU area data 967d9157edSMarri Devender Rao */ 977d9157edSMarri Devender Rao void padData(FruAreaData& data) 987d9157edSMarri Devender Rao { 993e6a769bSRatan Gupta uint8_t pad = (data.size() + checksumSize) % recordUnitOfMeasurement; 1007d9157edSMarri Devender Rao if (pad) 1017d9157edSMarri Devender Rao { 1023e6a769bSRatan Gupta data.resize((data.size() + recordUnitOfMeasurement - pad)); 1037d9157edSMarri Devender Rao } 1047d9157edSMarri Devender Rao } 1057d9157edSMarri Devender Rao 1067d9157edSMarri Devender Rao /** 1077d9157edSMarri Devender Rao * @brief Format End of Individual IPMI FRU Data Section 1087d9157edSMarri Devender Rao * 1097d9157edSMarri Devender Rao * @param[in/out] fruAreaData FRU area info data 1107d9157edSMarri Devender Rao */ 1117d9157edSMarri Devender Rao void postFormatProcessing(FruAreaData& data) 1127d9157edSMarri Devender Rao { 1137d9157edSMarri Devender Rao // This area needs to be padded to a multiple of 8 bytes (after checksum) 1147d9157edSMarri Devender Rao padData(data); 1157d9157edSMarri Devender Rao 1167d9157edSMarri Devender Rao // Set size of data info area 1170b02be92SPatrick Venture data.at(areaSizeOffset) = 1180b02be92SPatrick Venture (data.size() + checksumSize) / (recordUnitOfMeasurement); 1197d9157edSMarri Devender Rao 1202f66f00eSRatan Gupta // Finally add area checksum 1217d9157edSMarri Devender Rao appendDataChecksum(data); 1227d9157edSMarri Devender Rao } 1237d9157edSMarri Devender Rao 1247d9157edSMarri Devender Rao /** 12540f59e2cSOskar Senft * @brief Read chassis type property value from inventory and append to the FRU 12640f59e2cSOskar Senft * area data. 12740f59e2cSOskar Senft * 12840f59e2cSOskar Senft * @param[in] propMap map of property values 12940f59e2cSOskar Senft * @param[in,out] data FRU area data to be appended 13040f59e2cSOskar Senft */ 13140f59e2cSOskar Senft void appendChassisType(const PropertyMap& propMap, FruAreaData& data) 13240f59e2cSOskar Senft { 13340f59e2cSOskar Senft uint8_t chassisType = 0; // Not specified 13440f59e2cSOskar Senft auto iter = propMap.find(type); 13540f59e2cSOskar Senft if (iter != propMap.end()) 13640f59e2cSOskar Senft { 13740f59e2cSOskar Senft auto value = iter->second; 13840f59e2cSOskar Senft chassisType = std::stoi(value); 13940f59e2cSOskar Senft } 14040f59e2cSOskar Senft data.emplace_back(chassisType); 14140f59e2cSOskar Senft } 14240f59e2cSOskar Senft 14340f59e2cSOskar Senft /** 1447d9157edSMarri Devender Rao * @brief Read property value from inventory and append to the FRU area data 1457d9157edSMarri Devender Rao * 1467d9157edSMarri Devender Rao * @param[in] key key to search for in the property inventory data 1477d9157edSMarri Devender Rao * @param[in] propMap map of property values 1487d9157edSMarri Devender Rao * @param[in,out] data FRU area data to be appended 1497d9157edSMarri Devender Rao */ 1507d9157edSMarri Devender Rao void appendData(const Property& key, const PropertyMap& propMap, 1517d9157edSMarri Devender Rao FruAreaData& data) 1527d9157edSMarri Devender Rao { 1537d9157edSMarri Devender Rao auto iter = propMap.find(key); 1547d9157edSMarri Devender Rao if (iter != propMap.end()) 1557d9157edSMarri Devender Rao { 1567d9157edSMarri Devender Rao auto value = iter->second; 1577d9157edSMarri Devender Rao // If starts with 0x or 0X remove them 1587d9157edSMarri Devender Rao // ex: 0x123a just take 123a 1597d9157edSMarri Devender Rao if ((value.compare(0, 2, "0x")) == 0 || 1607d9157edSMarri Devender Rao (value.compare(0, 2, "0X") == 0)) 1617d9157edSMarri Devender Rao { 1627d9157edSMarri Devender Rao value.erase(0, 2); 1637d9157edSMarri Devender Rao } 1646edfc5c1SRatan Gupta 1656edfc5c1SRatan Gupta // 5 bits for length 1660b02be92SPatrick Venture // if length is greater then 31(2^5) bytes then trim the data to 31 1670b02be92SPatrick Venture // bytess. 1680b02be92SPatrick Venture auto valueLength = (value.length() > maxRecordAttributeValue) 1690b02be92SPatrick Venture ? maxRecordAttributeValue 1700b02be92SPatrick Venture : value.length(); 1716edfc5c1SRatan Gupta // 2 bits for type 1726edfc5c1SRatan Gupta // Set the type to ascii 1736edfc5c1SRatan Gupta uint8_t typeLength = valueLength | ipmi::fru::typeASCII; 1746edfc5c1SRatan Gupta 1756edfc5c1SRatan Gupta data.emplace_back(typeLength); 1760b02be92SPatrick Venture std::copy(value.begin(), value.begin() + valueLength, 1776edfc5c1SRatan Gupta std::back_inserter(data)); 1787d9157edSMarri Devender Rao } 1797d9157edSMarri Devender Rao else 1807d9157edSMarri Devender Rao { 1817d9157edSMarri Devender Rao // set 0 size 1827d9157edSMarri Devender Rao data.emplace_back(typeLengthByteNull); 1837d9157edSMarri Devender Rao } 1847d9157edSMarri Devender Rao } 1857d9157edSMarri Devender Rao 1867d9157edSMarri Devender Rao /** 1877d9157edSMarri Devender Rao * @brief Appends Build Date 1887d9157edSMarri Devender Rao * 1897d9157edSMarri Devender Rao * @param[in] propMap map of property values 1907d9157edSMarri Devender Rao * @param[in/out] data FRU area to add the manfufacture date 1917d9157edSMarri Devender Rao */ 1927d9157edSMarri Devender Rao void appendMfgDate(const PropertyMap& propMap, FruAreaData& data) 1937d9157edSMarri Devender Rao { 1947d9157edSMarri Devender Rao // MFG Date/Time 1957d9157edSMarri Devender Rao auto iter = propMap.find(buildDate); 196b898cde6SNagaraju Goruganti if ((iter != propMap.end()) && (iter->second.size() > 0)) 1977d9157edSMarri Devender Rao { 1987ebd2464SAndres Oportus tm time = {}; 1997ebd2464SAndres Oportus strptime(iter->second.c_str(), "%F - %H:%M:%S", &time); 2007ebd2464SAndres Oportus time_t raw = mktime(&time); 2017ebd2464SAndres Oportus 2027ebd2464SAndres Oportus // From FRU Spec: 2037ebd2464SAndres Oportus // "Mfg. Date / Time 2047ebd2464SAndres Oportus // Number of minutes from 0:00 hrs 1/1/96. 2057ebd2464SAndres Oportus // LSbyte first (little endian) 2067ebd2464SAndres Oportus // 00_00_00h = unspecified." 207b898cde6SNagaraju Goruganti if ((raw >= secs_from_1970_1996) && (raw <= secsToMaxMfgdate)) 2087d9157edSMarri Devender Rao { 2097ebd2464SAndres Oportus raw -= secs_from_1970_1996; 2107ebd2464SAndres Oportus raw /= secs_per_min; 2117ebd2464SAndres Oportus uint8_t fru_raw[3]; 2127ebd2464SAndres Oportus fru_raw[0] = raw & 0xFF; 2137ebd2464SAndres Oportus fru_raw[1] = (raw >> 8) & 0xFF; 2147ebd2464SAndres Oportus fru_raw[2] = (raw >> 16) & 0xFF; 2157ebd2464SAndres Oportus std::copy(fru_raw, fru_raw + 3, std::back_inserter(data)); 2167d9157edSMarri Devender Rao return; 2177d9157edSMarri Devender Rao } 218b51bf9c8SPatrick Venture std::fprintf(stderr, "MgfDate invalid date: %u secs since UNIX epoch\n", 2197ebd2464SAndres Oportus static_cast<unsigned int>(raw)); 2207d9157edSMarri Devender Rao } 2217d9157edSMarri Devender Rao // Blank date 2227d9157edSMarri Devender Rao data.emplace_back(0); 2237d9157edSMarri Devender Rao data.emplace_back(0); 2247d9157edSMarri Devender Rao data.emplace_back(0); 2257d9157edSMarri Devender Rao } 2267d9157edSMarri Devender Rao 2277d9157edSMarri Devender Rao /** 2287d9157edSMarri Devender Rao * @brief Builds a section of the common header 2297d9157edSMarri Devender Rao * 2307d9157edSMarri Devender Rao * @param[in] infoAreaSize size of the FRU area to write 2317d9157edSMarri Devender Rao * @param[in] offset Current offset for data in overall record 2327d9157edSMarri Devender Rao * @param[in/out] data Common Header section data container 2337d9157edSMarri Devender Rao */ 2340b02be92SPatrick Venture void buildCommonHeaderSection(const uint32_t& infoAreaSize, uint16_t& offset, 2350b02be92SPatrick Venture FruAreaData& data) 2367d9157edSMarri Devender Rao { 2377d9157edSMarri Devender Rao // Check if data for internal use section populated 2387d9157edSMarri Devender Rao if (infoAreaSize == 0) 2397d9157edSMarri Devender Rao { 2407d9157edSMarri Devender Rao // Indicate record not present 2417d9157edSMarri Devender Rao data.emplace_back(recordNotPresent); 2427d9157edSMarri Devender Rao } 2437d9157edSMarri Devender Rao else 2447d9157edSMarri Devender Rao { 2452f66f00eSRatan Gupta // offset should be multiple of 8. 2463e6a769bSRatan Gupta auto remainder = offset % recordUnitOfMeasurement; 2472f66f00eSRatan Gupta // add the padding bytes in the offset so that offset 2482f66f00eSRatan Gupta // will be multiple of 8 byte. 2493e6a769bSRatan Gupta offset += (remainder > 0) ? recordUnitOfMeasurement - remainder : 0; 2507d9157edSMarri Devender Rao // Place data to define offset to area data section 2513e6a769bSRatan Gupta data.emplace_back(offset / recordUnitOfMeasurement); 2522f66f00eSRatan Gupta 2537d9157edSMarri Devender Rao offset += infoAreaSize; 2547d9157edSMarri Devender Rao } 2557d9157edSMarri Devender Rao } 2567d9157edSMarri Devender Rao 2577d9157edSMarri Devender Rao /** 2587d9157edSMarri Devender Rao * @brief Builds the Chassis info area data section 2597d9157edSMarri Devender Rao * 2607d9157edSMarri Devender Rao * @param[in] propMap map of properties for chassis info area 2617d9157edSMarri Devender Rao * @return FruAreaData container with chassis info area 2627d9157edSMarri Devender Rao */ 2637d9157edSMarri Devender Rao FruAreaData buildChassisInfoArea(const PropertyMap& propMap) 2647d9157edSMarri Devender Rao { 2657d9157edSMarri Devender Rao FruAreaData fruAreaData; 2667d9157edSMarri Devender Rao if (!propMap.empty()) 2677d9157edSMarri Devender Rao { 2687d9157edSMarri Devender Rao // Set formatting data that goes at the beginning of the record 2697d9157edSMarri Devender Rao preFormatProcessing(false, fruAreaData); 2707d9157edSMarri Devender Rao 2717d9157edSMarri Devender Rao // chassis type 27240f59e2cSOskar Senft appendChassisType(propMap, fruAreaData); 2737d9157edSMarri Devender Rao 2747d9157edSMarri Devender Rao // Chasiss part number, in config.yaml it is configured as model 2757d9157edSMarri Devender Rao appendData(model, propMap, fruAreaData); 2767d9157edSMarri Devender Rao 2777d9157edSMarri Devender Rao // Board serial number 2787d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 2797d9157edSMarri Devender Rao 2807d9157edSMarri Devender Rao // Indicate End of Custom Fields 2817d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 2827d9157edSMarri Devender Rao 2837d9157edSMarri Devender Rao // Complete record data formatting 2847d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 2857d9157edSMarri Devender Rao } 2867d9157edSMarri Devender Rao return fruAreaData; 2877d9157edSMarri Devender Rao } 2887d9157edSMarri Devender Rao 2897d9157edSMarri Devender Rao /** 2907d9157edSMarri Devender Rao * @brief Builds the Board info area data section 2917d9157edSMarri Devender Rao * 2927d9157edSMarri Devender Rao * @param[in] propMap map of properties for board info area 2937d9157edSMarri Devender Rao * @return FruAreaData container with board info area 2947d9157edSMarri Devender Rao */ 2957d9157edSMarri Devender Rao FruAreaData buildBoardInfoArea(const PropertyMap& propMap) 2967d9157edSMarri Devender Rao { 2977d9157edSMarri Devender Rao FruAreaData fruAreaData; 2987d9157edSMarri Devender Rao if (!propMap.empty()) 2997d9157edSMarri Devender Rao { 3007d9157edSMarri Devender Rao preFormatProcessing(true, fruAreaData); 3017d9157edSMarri Devender Rao 3027d9157edSMarri Devender Rao // Manufacturing date 3037d9157edSMarri Devender Rao appendMfgDate(propMap, fruAreaData); 3047d9157edSMarri Devender Rao 3057d9157edSMarri Devender Rao // manufacturer 3067d9157edSMarri Devender Rao appendData(manufacturer, propMap, fruAreaData); 3077d9157edSMarri Devender Rao 3087d9157edSMarri Devender Rao // Product name/Pretty name 3097d9157edSMarri Devender Rao appendData(prettyName, propMap, fruAreaData); 3107d9157edSMarri Devender Rao 3117d9157edSMarri Devender Rao // Board serial number 3127d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 3137d9157edSMarri Devender Rao 3147d9157edSMarri Devender Rao // Board part number 3157d9157edSMarri Devender Rao appendData(partNumber, propMap, fruAreaData); 3167d9157edSMarri Devender Rao 3177d9157edSMarri Devender Rao // FRU File ID - Empty 3187d9157edSMarri Devender Rao fruAreaData.emplace_back(typeLengthByteNull); 3197d9157edSMarri Devender Rao 3207d9157edSMarri Devender Rao // Empty FRU File ID bytes 3217d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 3227d9157edSMarri Devender Rao 3237d9157edSMarri Devender Rao // End of custom fields 3247d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 3257d9157edSMarri Devender Rao 3267d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 3277d9157edSMarri Devender Rao } 3287d9157edSMarri Devender Rao return fruAreaData; 3297d9157edSMarri Devender Rao } 3307d9157edSMarri Devender Rao 3317d9157edSMarri Devender Rao /** 3327d9157edSMarri Devender Rao * @brief Builds the Product info area data section 3337d9157edSMarri Devender Rao * 3347d9157edSMarri Devender Rao * @param[in] propMap map of FRU properties for Board info area 3357d9157edSMarri Devender Rao * @return FruAreaData container with product info area data 3367d9157edSMarri Devender Rao */ 3377d9157edSMarri Devender Rao FruAreaData buildProductInfoArea(const PropertyMap& propMap) 3387d9157edSMarri Devender Rao { 3397d9157edSMarri Devender Rao FruAreaData fruAreaData; 3407d9157edSMarri Devender Rao if (!propMap.empty()) 3417d9157edSMarri Devender Rao { 3427d9157edSMarri Devender Rao // Set formatting data that goes at the beginning of the record 3437d9157edSMarri Devender Rao preFormatProcessing(true, fruAreaData); 3447d9157edSMarri Devender Rao 3457d9157edSMarri Devender Rao // manufacturer 3467d9157edSMarri Devender Rao appendData(manufacturer, propMap, fruAreaData); 3477d9157edSMarri Devender Rao 3487d9157edSMarri Devender Rao // Product name/Pretty name 3497d9157edSMarri Devender Rao appendData(prettyName, propMap, fruAreaData); 3507d9157edSMarri Devender Rao 3517d9157edSMarri Devender Rao // Product part/model number 3527d9157edSMarri Devender Rao appendData(model, propMap, fruAreaData); 3537d9157edSMarri Devender Rao 3547d9157edSMarri Devender Rao // Product version 3557d9157edSMarri Devender Rao appendData(version, propMap, fruAreaData); 3567d9157edSMarri Devender Rao 3577d9157edSMarri Devender Rao // Serial Number 3587d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 3597d9157edSMarri Devender Rao 3607d9157edSMarri Devender Rao // Add Asset Tag 3617d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 3627d9157edSMarri Devender Rao 3637d9157edSMarri Devender Rao // FRU File ID - Empty 3647d9157edSMarri Devender Rao fruAreaData.emplace_back(typeLengthByteNull); 3657d9157edSMarri Devender Rao 3667d9157edSMarri Devender Rao // Empty FRU File ID bytes 3677d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 3687d9157edSMarri Devender Rao 3697d9157edSMarri Devender Rao // End of custom fields 3707d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 3717d9157edSMarri Devender Rao 3727d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 3737d9157edSMarri Devender Rao } 3747d9157edSMarri Devender Rao return fruAreaData; 3757d9157edSMarri Devender Rao } 3767d9157edSMarri Devender Rao 3777d9157edSMarri Devender Rao FruAreaData buildFruAreaData(const FruInventoryData& inventory) 3787d9157edSMarri Devender Rao { 3792f66f00eSRatan Gupta FruAreaData combFruArea{}; 3807d9157edSMarri Devender Rao // Now build common header with data for this FRU Inv Record 3817d9157edSMarri Devender Rao // Use this variable to increment size of header as we go along to determine 3827d9157edSMarri Devender Rao // offset for the subsequent area offsets 3832f66f00eSRatan Gupta uint16_t curDataOffset = commonHeaderFormatSize; 3847d9157edSMarri Devender Rao // First byte is id for version of FRU Info Storage Spec used 3857d9157edSMarri Devender Rao combFruArea.emplace_back(specVersion); 3867d9157edSMarri Devender Rao 3877d9157edSMarri Devender Rao // 2nd byte is offset to internal use data 3887d9157edSMarri Devender Rao combFruArea.emplace_back(recordNotPresent); 3897d9157edSMarri Devender Rao 3907d9157edSMarri Devender Rao // 3rd byte is offset to chassis data 3917d9157edSMarri Devender Rao FruAreaData chassisArea; 3927d9157edSMarri Devender Rao auto chassisIt = inventory.find(chassis); 3937d9157edSMarri Devender Rao if (chassisIt != inventory.end()) 3947d9157edSMarri Devender Rao { 3957d9157edSMarri Devender Rao chassisArea = std::move(buildChassisInfoArea(chassisIt->second)); 3967d9157edSMarri Devender Rao } 3972f66f00eSRatan Gupta // update the offset to chassis data. 3987d9157edSMarri Devender Rao buildCommonHeaderSection(chassisArea.size(), curDataOffset, combFruArea); 3997d9157edSMarri Devender Rao 4007d9157edSMarri Devender Rao // 4th byte is offset to board data 4017d9157edSMarri Devender Rao FruAreaData boardArea; 4027d9157edSMarri Devender Rao auto boardIt = inventory.find(board); 4037d9157edSMarri Devender Rao if (boardIt != inventory.end()) 4047d9157edSMarri Devender Rao { 4057d9157edSMarri Devender Rao boardArea = std::move(buildBoardInfoArea(boardIt->second)); 4067d9157edSMarri Devender Rao } 4072f66f00eSRatan Gupta // update the offset to the board data. 4082f66f00eSRatan Gupta buildCommonHeaderSection(boardArea.size(), curDataOffset, combFruArea); 4097d9157edSMarri Devender Rao 4107d9157edSMarri Devender Rao // 5th byte is offset to product data 4117d9157edSMarri Devender Rao FruAreaData prodArea; 4127d9157edSMarri Devender Rao auto prodIt = inventory.find(product); 4137d9157edSMarri Devender Rao if (prodIt != inventory.end()) 4147d9157edSMarri Devender Rao { 4157d9157edSMarri Devender Rao prodArea = std::move(buildProductInfoArea(prodIt->second)); 4167d9157edSMarri Devender Rao } 4172f66f00eSRatan Gupta // update the offset to the product data. 4187d9157edSMarri Devender Rao buildCommonHeaderSection(prodArea.size(), curDataOffset, combFruArea); 4197d9157edSMarri Devender Rao 4207d9157edSMarri Devender Rao // 6th byte is offset to multirecord data 4217d9157edSMarri Devender Rao combFruArea.emplace_back(recordNotPresent); 4227d9157edSMarri Devender Rao 4237d9157edSMarri Devender Rao // 7th byte is PAD 4242f66f00eSRatan Gupta combFruArea.emplace_back(recordNotPresent); 4257d9157edSMarri Devender Rao 4267d9157edSMarri Devender Rao // 8th (Final byte of Header Format) is the checksum 4277d9157edSMarri Devender Rao appendDataChecksum(combFruArea); 4287d9157edSMarri Devender Rao 4297d9157edSMarri Devender Rao // Combine everything into one full IPMI FRU specification Record 4307d9157edSMarri Devender Rao // add chassis use area data 4310b02be92SPatrick Venture combFruArea.insert(combFruArea.end(), chassisArea.begin(), 4320b02be92SPatrick Venture chassisArea.end()); 4337d9157edSMarri Devender Rao 4347d9157edSMarri Devender Rao // add board area data 4357d9157edSMarri Devender Rao combFruArea.insert(combFruArea.end(), boardArea.begin(), boardArea.end()); 4367d9157edSMarri Devender Rao 4377d9157edSMarri Devender Rao // add product use area data 4387d9157edSMarri Devender Rao combFruArea.insert(combFruArea.end(), prodArea.begin(), prodArea.end()); 4397d9157edSMarri Devender Rao 440*8b18941dSOskar Senft // If area is smaller than the minimum size, pad it. This enables ipmitool 441*8b18941dSOskar Senft // to update the FRU blob with values longer than the original payload. 442*8b18941dSOskar Senft if (combFruArea.size() < fruMinSize) 443*8b18941dSOskar Senft { 444*8b18941dSOskar Senft combFruArea.resize(fruMinSize, fruPadValue); 445*8b18941dSOskar Senft } 446*8b18941dSOskar Senft 4477d9157edSMarri Devender Rao return combFruArea; 4487d9157edSMarri Devender Rao } 4497d9157edSMarri Devender Rao 4500b02be92SPatrick Venture } // namespace fru 4510b02be92SPatrick Venture } // namespace ipmi 452