| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1 | #include "ipmi_fru_info_area.hpp" | 
 | 2 |  | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 3 | #include <algorithm> | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 4 | #include <ctime> | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 5 | #include <map> | 
 | 6 | #include <numeric> | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 7 | #include <phosphor-logging/elog.hpp> | 
| Patrick Venture | b51bf9c | 2018-09-10 15:53:14 -0700 | [diff] [blame] | 8 |  | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 9 | namespace ipmi | 
 | 10 | { | 
 | 11 | namespace fru | 
 | 12 | { | 
 | 13 | using namespace phosphor::logging; | 
 | 14 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 15 | // Property variables | 
 | 16 | static constexpr auto partNumber = "PartNumber"; | 
 | 17 | static constexpr auto serialNumber = "SerialNumber"; | 
 | 18 | static constexpr auto manufacturer = "Manufacturer"; | 
 | 19 | static constexpr auto buildDate = "BuildDate"; | 
 | 20 | static constexpr auto model = "Model"; | 
 | 21 | static constexpr auto prettyName = "PrettyName"; | 
 | 22 | static constexpr auto version = "Version"; | 
| Oskar Senft | 40f59e2 | 2018-12-04 22:43:19 -0500 | [diff] [blame^] | 23 | static constexpr auto type = "Type"; | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 24 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 25 | // Board info areas | 
 | 26 | static constexpr auto board = "Board"; | 
 | 27 | static constexpr auto chassis = "Chassis"; | 
 | 28 | static constexpr auto product = "Product"; | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 29 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 30 | static constexpr auto specVersion = 0x1; | 
 | 31 | static constexpr auto recordUnitOfMeasurement = 0x8; // size in bytes | 
 | 32 | static constexpr auto checksumSize = 0x1;            // size in bytes | 
 | 33 | static constexpr auto recordNotPresent = 0x0; | 
 | 34 | static constexpr auto englishLanguageCode = 0x0; | 
 | 35 | static constexpr auto typeLengthByteNull = 0x0; | 
 | 36 | static constexpr auto endOfCustomFields = 0xC1; | 
 | 37 | static constexpr auto commonHeaderFormatSize = 0x8; // size in bytes | 
 | 38 | static constexpr auto manufacturingDateSize = 0x3; | 
 | 39 | static constexpr auto areaSizeOffset = 0x1; | 
 | 40 | static constexpr uint8_t typeASCII = 0xC0; | 
 | 41 | static constexpr auto maxRecordAttributeValue = 0x1F; | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 42 |  | 
| Andres Oportus | 7ebd246 | 2018-04-09 10:35:21 -0700 | [diff] [blame] | 43 | static constexpr auto secs_from_1970_1996 = 820454400; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 44 | static constexpr auto maxMfgDateValue = 0xFFFFFF; // 3 Byte length | 
| Andres Oportus | 7ebd246 | 2018-04-09 10:35:21 -0700 | [diff] [blame] | 45 | static constexpr auto secs_per_min = 60; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 46 | static constexpr auto secsToMaxMfgdate = | 
 | 47 |     secs_from_1970_1996 + secs_per_min * maxMfgDateValue; | 
| Andres Oportus | 7ebd246 | 2018-04-09 10:35:21 -0700 | [diff] [blame] | 48 |  | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 49 | /** | 
 | 50 |  * @brief Format Beginning of Individual IPMI FRU Data Section | 
 | 51 |  * | 
 | 52 |  * @param[in] langCode Language code | 
 | 53 |  * @param[in/out] data FRU area data | 
 | 54 |  */ | 
 | 55 | void preFormatProcessing(bool langCode, FruAreaData& data) | 
 | 56 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 57 |     // Add id for version of FRU Info Storage Spec used | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 58 |     data.emplace_back(specVersion); | 
 | 59 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 60 |     // Add Data Size - 0 as a placeholder, can edit after the data is finalized | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 61 |     data.emplace_back(typeLengthByteNull); | 
 | 62 |  | 
 | 63 |     if (langCode) | 
 | 64 |     { | 
 | 65 |         data.emplace_back(englishLanguageCode); | 
 | 66 |     } | 
 | 67 | } | 
 | 68 |  | 
 | 69 | /** | 
 | 70 |  * @brief Append checksum of the FRU area data | 
 | 71 |  * | 
 | 72 |  * @param[in/out] data FRU area data | 
 | 73 |  */ | 
 | 74 | void appendDataChecksum(FruAreaData& data) | 
 | 75 | { | 
 | 76 |     uint8_t checksumVal = std::accumulate(data.begin(), data.end(), 0); | 
 | 77 |     // Push the Zero checksum as the last byte of this data | 
 | 78 |     // This appears to be a simple summation of all the bytes | 
 | 79 |     data.emplace_back(-checksumVal); | 
 | 80 | } | 
 | 81 |  | 
 | 82 | /** | 
 | 83 |  * @brief Append padding bytes for the FRU area data | 
 | 84 |  * | 
 | 85 |  * @param[in/out] data FRU area data | 
 | 86 |  */ | 
 | 87 | void padData(FruAreaData& data) | 
 | 88 | { | 
| Ratan Gupta | 3e6a769 | 2018-02-07 16:10:16 +0530 | [diff] [blame] | 89 |     uint8_t pad = (data.size() + checksumSize) % recordUnitOfMeasurement; | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 90 |     if (pad) | 
 | 91 |     { | 
| Ratan Gupta | 3e6a769 | 2018-02-07 16:10:16 +0530 | [diff] [blame] | 92 |         data.resize((data.size() + recordUnitOfMeasurement - pad)); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 93 |     } | 
 | 94 | } | 
 | 95 |  | 
 | 96 | /** | 
 | 97 |  * @brief Format End of Individual IPMI FRU Data Section | 
 | 98 |  * | 
 | 99 |  * @param[in/out] fruAreaData FRU area info data | 
 | 100 |  */ | 
 | 101 | void postFormatProcessing(FruAreaData& data) | 
 | 102 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 103 |     // This area needs to be padded to a multiple of 8 bytes (after checksum) | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 104 |     padData(data); | 
 | 105 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 106 |     // Set size of data info area | 
 | 107 |     data.at(areaSizeOffset) = | 
 | 108 |         (data.size() + checksumSize) / (recordUnitOfMeasurement); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 109 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 110 |     // Finally add area checksum | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 111 |     appendDataChecksum(data); | 
 | 112 | } | 
 | 113 |  | 
 | 114 | /** | 
| Oskar Senft | 40f59e2 | 2018-12-04 22:43:19 -0500 | [diff] [blame^] | 115 |  * @brief Read chassis type property value from inventory and append to the FRU | 
 | 116 |  * area data. | 
 | 117 |  * | 
 | 118 |  * @param[in] propMap map of property values | 
 | 119 |  * @param[in,out] data FRU area data to be appended | 
 | 120 |  */ | 
 | 121 | void appendChassisType(const PropertyMap& propMap, FruAreaData& data) | 
 | 122 | { | 
 | 123 |     uint8_t chassisType = 0; // Not specified | 
 | 124 |     auto iter = propMap.find(type); | 
 | 125 |     if (iter != propMap.end()) | 
 | 126 |     { | 
 | 127 |         auto value = iter->second; | 
 | 128 |         chassisType = std::stoi(value); | 
 | 129 |     } | 
 | 130 |     data.emplace_back(chassisType); | 
 | 131 | } | 
 | 132 |  | 
 | 133 | /** | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 134 |  * @brief Read property value from inventory and append to the FRU area data | 
 | 135 |  * | 
 | 136 |  * @param[in] key key to search for in the property inventory data | 
 | 137 |  * @param[in] propMap map of property values | 
 | 138 |  * @param[in,out] data FRU area data to be appended | 
 | 139 |  */ | 
 | 140 | void appendData(const Property& key, const PropertyMap& propMap, | 
 | 141 |                 FruAreaData& data) | 
 | 142 | { | 
 | 143 |     auto iter = propMap.find(key); | 
 | 144 |     if (iter != propMap.end()) | 
 | 145 |     { | 
 | 146 |         auto value = iter->second; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 147 |         // If starts with 0x or 0X remove them | 
 | 148 |         // ex: 0x123a just take 123a | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 149 |         if ((value.compare(0, 2, "0x")) == 0 || | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 150 |             (value.compare(0, 2, "0X") == 0)) | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 151 |         { | 
 | 152 |             value.erase(0, 2); | 
 | 153 |         } | 
| Ratan Gupta | 6edfc5c | 2018-01-31 21:41:45 +0530 | [diff] [blame] | 154 |  | 
 | 155 |         // 5 bits for length | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 156 |         // if length is greater then 31(2^5) bytes then trim the data to 31 | 
 | 157 |         // bytess. | 
 | 158 |         auto valueLength = (value.length() > maxRecordAttributeValue) | 
 | 159 |                                ? maxRecordAttributeValue | 
 | 160 |                                : value.length(); | 
| Ratan Gupta | 6edfc5c | 2018-01-31 21:41:45 +0530 | [diff] [blame] | 161 |         // 2 bits for type | 
 | 162 |         // Set the type to ascii | 
 | 163 |         uint8_t typeLength = valueLength | ipmi::fru::typeASCII; | 
 | 164 |  | 
 | 165 |         data.emplace_back(typeLength); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 166 |         std::copy(value.begin(), value.begin() + valueLength, | 
| Ratan Gupta | 6edfc5c | 2018-01-31 21:41:45 +0530 | [diff] [blame] | 167 |                   std::back_inserter(data)); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 168 |     } | 
 | 169 |     else | 
 | 170 |     { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 171 |         // set 0 size | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 172 |         data.emplace_back(typeLengthByteNull); | 
 | 173 |     } | 
 | 174 | } | 
 | 175 |  | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 176 | /** | 
 | 177 |  * @brief Appends Build Date | 
 | 178 |  * | 
 | 179 |  * @param[in] propMap map of property values | 
 | 180 |  * @param[in/out] data FRU area to add the manfufacture date | 
 | 181 |  */ | 
 | 182 | void appendMfgDate(const PropertyMap& propMap, FruAreaData& data) | 
 | 183 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 184 |     // MFG Date/Time | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 185 |     auto iter = propMap.find(buildDate); | 
| Nagaraju Goruganti | b898cde | 2018-07-10 00:47:43 -0500 | [diff] [blame] | 186 |     if ((iter != propMap.end()) && (iter->second.size() > 0)) | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 187 |     { | 
| Andres Oportus | 7ebd246 | 2018-04-09 10:35:21 -0700 | [diff] [blame] | 188 |         tm time = {}; | 
 | 189 |         strptime(iter->second.c_str(), "%F - %H:%M:%S", &time); | 
 | 190 |         time_t raw = mktime(&time); | 
 | 191 |  | 
 | 192 |         // From FRU Spec: | 
 | 193 |         // "Mfg. Date / Time | 
 | 194 |         // Number of minutes from 0:00 hrs 1/1/96. | 
 | 195 |         // LSbyte first (little endian) | 
 | 196 |         // 00_00_00h = unspecified." | 
| Nagaraju Goruganti | b898cde | 2018-07-10 00:47:43 -0500 | [diff] [blame] | 197 |         if ((raw >= secs_from_1970_1996) && (raw <= secsToMaxMfgdate)) | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 198 |         { | 
| Andres Oportus | 7ebd246 | 2018-04-09 10:35:21 -0700 | [diff] [blame] | 199 |             raw -= secs_from_1970_1996; | 
 | 200 |             raw /= secs_per_min; | 
 | 201 |             uint8_t fru_raw[3]; | 
 | 202 |             fru_raw[0] = raw & 0xFF; | 
 | 203 |             fru_raw[1] = (raw >> 8) & 0xFF; | 
 | 204 |             fru_raw[2] = (raw >> 16) & 0xFF; | 
 | 205 |             std::copy(fru_raw, fru_raw + 3, std::back_inserter(data)); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 206 |             return; | 
 | 207 |         } | 
| Patrick Venture | b51bf9c | 2018-09-10 15:53:14 -0700 | [diff] [blame] | 208 |         std::fprintf(stderr, "MgfDate invalid date: %u secs since UNIX epoch\n", | 
 | 209 |                      static_cast<unsigned int>(raw)); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 210 |     } | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 211 |     // Blank date | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 212 |     data.emplace_back(0); | 
 | 213 |     data.emplace_back(0); | 
 | 214 |     data.emplace_back(0); | 
 | 215 | } | 
 | 216 |  | 
 | 217 | /** | 
 | 218 |  * @brief Builds a section of the common header | 
 | 219 |  * | 
 | 220 |  * @param[in] infoAreaSize size of the FRU area to write | 
 | 221 |  * @param[in] offset Current offset for data in overall record | 
 | 222 |  * @param[in/out] data Common Header section data container | 
 | 223 |  */ | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 224 | void buildCommonHeaderSection(const uint32_t& infoAreaSize, uint16_t& offset, | 
 | 225 |                               FruAreaData& data) | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 226 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 227 |     // Check if data for internal use section populated | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 228 |     if (infoAreaSize == 0) | 
 | 229 |     { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 230 |         // Indicate record not present | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 231 |         data.emplace_back(recordNotPresent); | 
 | 232 |     } | 
 | 233 |     else | 
 | 234 |     { | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 235 |         // offset should be multiple of 8. | 
| Ratan Gupta | 3e6a769 | 2018-02-07 16:10:16 +0530 | [diff] [blame] | 236 |         auto remainder = offset % recordUnitOfMeasurement; | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 237 |         // add the padding bytes in the offset so that offset | 
 | 238 |         // will be multiple of 8 byte. | 
| Ratan Gupta | 3e6a769 | 2018-02-07 16:10:16 +0530 | [diff] [blame] | 239 |         offset += (remainder > 0) ? recordUnitOfMeasurement - remainder : 0; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 240 |         // Place data to define offset to area data section | 
| Ratan Gupta | 3e6a769 | 2018-02-07 16:10:16 +0530 | [diff] [blame] | 241 |         data.emplace_back(offset / recordUnitOfMeasurement); | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 242 |  | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 243 |         offset += infoAreaSize; | 
 | 244 |     } | 
 | 245 | } | 
 | 246 |  | 
 | 247 | /** | 
 | 248 |  * @brief Builds the Chassis info area data section | 
 | 249 |  * | 
 | 250 |  * @param[in] propMap map of properties for chassis info area | 
 | 251 |  * @return FruAreaData container with chassis info area | 
 | 252 |  */ | 
 | 253 | FruAreaData buildChassisInfoArea(const PropertyMap& propMap) | 
 | 254 | { | 
 | 255 |     FruAreaData fruAreaData; | 
 | 256 |     if (!propMap.empty()) | 
 | 257 |     { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 258 |         // Set formatting data that goes at the beginning of the record | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 259 |         preFormatProcessing(false, fruAreaData); | 
 | 260 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 261 |         // chassis type | 
| Oskar Senft | 40f59e2 | 2018-12-04 22:43:19 -0500 | [diff] [blame^] | 262 |         appendChassisType(propMap, fruAreaData); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 263 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 264 |         // Chasiss part number, in config.yaml it is configured as model | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 265 |         appendData(model, propMap, fruAreaData); | 
 | 266 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 267 |         // Board serial number | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 268 |         appendData(serialNumber, propMap, fruAreaData); | 
 | 269 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 270 |         // Indicate End of Custom Fields | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 271 |         fruAreaData.emplace_back(endOfCustomFields); | 
 | 272 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 273 |         // Complete record data formatting | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 274 |         postFormatProcessing(fruAreaData); | 
 | 275 |     } | 
 | 276 |     return fruAreaData; | 
 | 277 | } | 
 | 278 |  | 
 | 279 | /** | 
 | 280 |  * @brief Builds the Board info area data section | 
 | 281 |  * | 
 | 282 |  * @param[in] propMap map of properties for board info area | 
 | 283 |  * @return FruAreaData container with board info area | 
 | 284 |  */ | 
 | 285 | FruAreaData buildBoardInfoArea(const PropertyMap& propMap) | 
 | 286 | { | 
 | 287 |     FruAreaData fruAreaData; | 
 | 288 |     if (!propMap.empty()) | 
 | 289 |     { | 
 | 290 |         preFormatProcessing(true, fruAreaData); | 
 | 291 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 292 |         // Manufacturing date | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 293 |         appendMfgDate(propMap, fruAreaData); | 
 | 294 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 295 |         // manufacturer | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 296 |         appendData(manufacturer, propMap, fruAreaData); | 
 | 297 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 298 |         // Product name/Pretty name | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 299 |         appendData(prettyName, propMap, fruAreaData); | 
 | 300 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 301 |         // Board serial number | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 302 |         appendData(serialNumber, propMap, fruAreaData); | 
 | 303 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 304 |         // Board part number | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 305 |         appendData(partNumber, propMap, fruAreaData); | 
 | 306 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 307 |         // FRU File ID - Empty | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 308 |         fruAreaData.emplace_back(typeLengthByteNull); | 
 | 309 |  | 
 | 310 |         // Empty FRU File ID bytes | 
 | 311 |         fruAreaData.emplace_back(recordNotPresent); | 
 | 312 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 313 |         // End of custom fields | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 314 |         fruAreaData.emplace_back(endOfCustomFields); | 
 | 315 |  | 
 | 316 |         postFormatProcessing(fruAreaData); | 
 | 317 |     } | 
 | 318 |     return fruAreaData; | 
 | 319 | } | 
 | 320 |  | 
 | 321 | /** | 
 | 322 |  * @brief Builds the Product info area data section | 
 | 323 |  * | 
 | 324 |  * @param[in] propMap map of FRU properties for Board info area | 
 | 325 |  * @return FruAreaData container with product info area data | 
 | 326 |  */ | 
 | 327 | FruAreaData buildProductInfoArea(const PropertyMap& propMap) | 
 | 328 | { | 
 | 329 |     FruAreaData fruAreaData; | 
 | 330 |     if (!propMap.empty()) | 
 | 331 |     { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 332 |         // Set formatting data that goes at the beginning of the record | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 333 |         preFormatProcessing(true, fruAreaData); | 
 | 334 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 335 |         // manufacturer | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 336 |         appendData(manufacturer, propMap, fruAreaData); | 
 | 337 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 338 |         // Product name/Pretty name | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 339 |         appendData(prettyName, propMap, fruAreaData); | 
 | 340 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 341 |         // Product part/model number | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 342 |         appendData(model, propMap, fruAreaData); | 
 | 343 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 344 |         // Product version | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 345 |         appendData(version, propMap, fruAreaData); | 
 | 346 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 347 |         // Serial Number | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 348 |         appendData(serialNumber, propMap, fruAreaData); | 
 | 349 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 350 |         // Add Asset Tag | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 351 |         fruAreaData.emplace_back(recordNotPresent); | 
 | 352 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 353 |         // FRU File ID - Empty | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 354 |         fruAreaData.emplace_back(typeLengthByteNull); | 
 | 355 |  | 
 | 356 |         // Empty FRU File ID bytes | 
 | 357 |         fruAreaData.emplace_back(recordNotPresent); | 
 | 358 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 359 |         // End of custom fields | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 360 |         fruAreaData.emplace_back(endOfCustomFields); | 
 | 361 |  | 
 | 362 |         postFormatProcessing(fruAreaData); | 
 | 363 |     } | 
 | 364 |     return fruAreaData; | 
 | 365 | } | 
 | 366 |  | 
 | 367 | FruAreaData buildFruAreaData(const FruInventoryData& inventory) | 
 | 368 | { | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 369 |     FruAreaData combFruArea{}; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 370 |     // Now build common header with data for this FRU Inv Record | 
 | 371 |     // Use this variable to increment size of header as we go along to determine | 
 | 372 |     // offset for the subsequent area offsets | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 373 |     uint16_t curDataOffset = commonHeaderFormatSize; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 374 |     // First byte is id for version of FRU Info Storage Spec used | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 375 |     combFruArea.emplace_back(specVersion); | 
 | 376 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 377 |     // 2nd byte is offset to internal use data | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 378 |     combFruArea.emplace_back(recordNotPresent); | 
 | 379 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 380 |     // 3rd byte is offset to chassis data | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 381 |     FruAreaData chassisArea; | 
 | 382 |     auto chassisIt = inventory.find(chassis); | 
 | 383 |     if (chassisIt != inventory.end()) | 
 | 384 |     { | 
 | 385 |         chassisArea = std::move(buildChassisInfoArea(chassisIt->second)); | 
 | 386 |     } | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 387 |     // update the offset to chassis data. | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 388 |     buildCommonHeaderSection(chassisArea.size(), curDataOffset, combFruArea); | 
 | 389 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 390 |     // 4th byte is offset to board data | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 391 |     FruAreaData boardArea; | 
 | 392 |     auto boardIt = inventory.find(board); | 
 | 393 |     if (boardIt != inventory.end()) | 
 | 394 |     { | 
 | 395 |         boardArea = std::move(buildBoardInfoArea(boardIt->second)); | 
 | 396 |     } | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 397 |     // update the offset to the board data. | 
 | 398 |     buildCommonHeaderSection(boardArea.size(), curDataOffset, combFruArea); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 399 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 400 |     // 5th byte is offset to product data | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 401 |     FruAreaData prodArea; | 
 | 402 |     auto prodIt = inventory.find(product); | 
 | 403 |     if (prodIt != inventory.end()) | 
 | 404 |     { | 
 | 405 |         prodArea = std::move(buildProductInfoArea(prodIt->second)); | 
 | 406 |     } | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 407 |     // update the offset to the product data. | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 408 |     buildCommonHeaderSection(prodArea.size(), curDataOffset, combFruArea); | 
 | 409 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 410 |     // 6th byte is offset to multirecord data | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 411 |     combFruArea.emplace_back(recordNotPresent); | 
 | 412 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 413 |     // 7th byte is PAD | 
| Ratan Gupta | 2f66f00 | 2018-01-31 21:26:25 +0530 | [diff] [blame] | 414 |     combFruArea.emplace_back(recordNotPresent); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 415 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 416 |     // 8th (Final byte of Header Format) is the checksum | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 417 |     appendDataChecksum(combFruArea); | 
 | 418 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 419 |     // Combine everything into one full IPMI FRU specification Record | 
 | 420 |     // add chassis use area data | 
 | 421 |     combFruArea.insert(combFruArea.end(), chassisArea.begin(), | 
 | 422 |                        chassisArea.end()); | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 423 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 424 |     // add board area data | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 425 |     combFruArea.insert(combFruArea.end(), boardArea.begin(), boardArea.end()); | 
 | 426 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 427 |     // add product use area data | 
| Marri Devender Rao | 7d9157e | 2017-07-01 16:11:40 -0500 | [diff] [blame] | 428 |     combFruArea.insert(combFruArea.end(), prodArea.begin(), prodArea.end()); | 
 | 429 |  | 
 | 430 |     return combFruArea; | 
 | 431 | } | 
 | 432 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 433 | } // namespace fru | 
 | 434 | } // namespace ipmi |