1*7d9157edSMarri Devender Rao #include <algorithm> 2*7d9157edSMarri Devender Rao #include <map> 3*7d9157edSMarri Devender Rao #include <numeric> 4*7d9157edSMarri Devender Rao #include "ipmi_fru_info_area.hpp" 5*7d9157edSMarri Devender Rao #include <phosphor-logging/elog.hpp> 6*7d9157edSMarri Devender Rao namespace ipmi 7*7d9157edSMarri Devender Rao { 8*7d9157edSMarri Devender Rao namespace fru 9*7d9157edSMarri Devender Rao { 10*7d9157edSMarri Devender Rao using namespace phosphor::logging; 11*7d9157edSMarri Devender Rao 12*7d9157edSMarri Devender Rao //Property variables 13*7d9157edSMarri Devender Rao static constexpr auto partNumber = "PartNumber"; 14*7d9157edSMarri Devender Rao static constexpr auto serialNumber = "SerialNumber"; 15*7d9157edSMarri Devender Rao static constexpr auto manufacturer = "Manufacturer"; 16*7d9157edSMarri Devender Rao static constexpr auto buildDate = "BuildDate"; 17*7d9157edSMarri Devender Rao static constexpr auto model = "Model"; 18*7d9157edSMarri Devender Rao static constexpr auto prettyName = "PrettyName"; 19*7d9157edSMarri Devender Rao static constexpr auto version = "Version"; 20*7d9157edSMarri Devender Rao 21*7d9157edSMarri Devender Rao //Board info areas 22*7d9157edSMarri Devender Rao static constexpr auto board = "Board"; 23*7d9157edSMarri Devender Rao static constexpr auto chassis = "Chassis"; 24*7d9157edSMarri Devender Rao static constexpr auto product = "Product"; 25*7d9157edSMarri Devender Rao 26*7d9157edSMarri Devender Rao static constexpr auto specVersion = 0x1; 27*7d9157edSMarri Devender Rao static constexpr auto recordUnitOfMeasurment = 0x8; //size in bytes 28*7d9157edSMarri Devender Rao static constexpr auto checksumSize = 0x1; //size in bytes 29*7d9157edSMarri Devender Rao static constexpr auto recordNotPresent = 0x0; 30*7d9157edSMarri Devender Rao static constexpr auto englishLanguageCode = 0x0; 31*7d9157edSMarri Devender Rao static constexpr auto typeLengthByteNull = 0x0; 32*7d9157edSMarri Devender Rao static constexpr auto endOfCustomFields = 0xC1; 33*7d9157edSMarri Devender Rao static constexpr auto commonHeaderFormatSize = 0x8; //size in bytes 34*7d9157edSMarri Devender Rao static constexpr auto manufacturingDateSize = 0x3; 35*7d9157edSMarri Devender Rao static constexpr auto areaSizeOffset = 0x1; 36*7d9157edSMarri Devender Rao 37*7d9157edSMarri Devender Rao /** 38*7d9157edSMarri Devender Rao * @brief Format Beginning of Individual IPMI FRU Data Section 39*7d9157edSMarri Devender Rao * 40*7d9157edSMarri Devender Rao * @param[in] langCode Language code 41*7d9157edSMarri Devender Rao * @param[in/out] data FRU area data 42*7d9157edSMarri Devender Rao */ 43*7d9157edSMarri Devender Rao void preFormatProcessing(bool langCode, FruAreaData& data) 44*7d9157edSMarri Devender Rao { 45*7d9157edSMarri Devender Rao //Add id for version of FRU Info Storage Spec used 46*7d9157edSMarri Devender Rao data.emplace_back(specVersion); 47*7d9157edSMarri Devender Rao 48*7d9157edSMarri Devender Rao //Add Data Size - 0 as a placeholder, can edit after the data is finalized 49*7d9157edSMarri Devender Rao data.emplace_back(typeLengthByteNull); 50*7d9157edSMarri Devender Rao 51*7d9157edSMarri Devender Rao if (langCode) 52*7d9157edSMarri Devender Rao { 53*7d9157edSMarri Devender Rao data.emplace_back(englishLanguageCode); 54*7d9157edSMarri Devender Rao } 55*7d9157edSMarri Devender Rao } 56*7d9157edSMarri Devender Rao 57*7d9157edSMarri Devender Rao /** 58*7d9157edSMarri Devender Rao * @brief Append checksum of the FRU area data 59*7d9157edSMarri Devender Rao * 60*7d9157edSMarri Devender Rao * @param[in/out] data FRU area data 61*7d9157edSMarri Devender Rao */ 62*7d9157edSMarri Devender Rao void appendDataChecksum(FruAreaData& data) 63*7d9157edSMarri Devender Rao { 64*7d9157edSMarri Devender Rao uint8_t checksumVal = std::accumulate(data.begin(), data.end(), 0); 65*7d9157edSMarri Devender Rao // Push the Zero checksum as the last byte of this data 66*7d9157edSMarri Devender Rao // This appears to be a simple summation of all the bytes 67*7d9157edSMarri Devender Rao data.emplace_back(-checksumVal); 68*7d9157edSMarri Devender Rao } 69*7d9157edSMarri Devender Rao 70*7d9157edSMarri Devender Rao /** 71*7d9157edSMarri Devender Rao * @brief Append padding bytes for the FRU area data 72*7d9157edSMarri Devender Rao * 73*7d9157edSMarri Devender Rao * @param[in/out] data FRU area data 74*7d9157edSMarri Devender Rao */ 75*7d9157edSMarri Devender Rao void padData(FruAreaData& data) 76*7d9157edSMarri Devender Rao { 77*7d9157edSMarri Devender Rao uint8_t pad = (data.size() + checksumSize) % recordUnitOfMeasurment; 78*7d9157edSMarri Devender Rao if (pad) 79*7d9157edSMarri Devender Rao { 80*7d9157edSMarri Devender Rao data.resize((data.size() + recordUnitOfMeasurment - pad)); 81*7d9157edSMarri Devender Rao } 82*7d9157edSMarri Devender Rao } 83*7d9157edSMarri Devender Rao 84*7d9157edSMarri Devender Rao /** 85*7d9157edSMarri Devender Rao * @brief Format End of Individual IPMI FRU Data Section 86*7d9157edSMarri Devender Rao * 87*7d9157edSMarri Devender Rao * @param[in/out] fruAreaData FRU area info data 88*7d9157edSMarri Devender Rao */ 89*7d9157edSMarri Devender Rao void postFormatProcessing(FruAreaData& data) 90*7d9157edSMarri Devender Rao { 91*7d9157edSMarri Devender Rao //This area needs to be padded to a multiple of 8 bytes (after checksum) 92*7d9157edSMarri Devender Rao padData(data); 93*7d9157edSMarri Devender Rao 94*7d9157edSMarri Devender Rao //Set size of data info area 95*7d9157edSMarri Devender Rao data.at(areaSizeOffset) = (data.size() + checksumSize) / 96*7d9157edSMarri Devender Rao (recordUnitOfMeasurment); 97*7d9157edSMarri Devender Rao 98*7d9157edSMarri Devender Rao //Finally add board info checksum 99*7d9157edSMarri Devender Rao appendDataChecksum(data); 100*7d9157edSMarri Devender Rao } 101*7d9157edSMarri Devender Rao 102*7d9157edSMarri Devender Rao /** 103*7d9157edSMarri Devender Rao * @brief Read property value from inventory and append to the FRU area data 104*7d9157edSMarri Devender Rao * 105*7d9157edSMarri Devender Rao * @param[in] key key to search for in the property inventory data 106*7d9157edSMarri Devender Rao * @param[in] propMap map of property values 107*7d9157edSMarri Devender Rao * @param[in,out] data FRU area data to be appended 108*7d9157edSMarri Devender Rao */ 109*7d9157edSMarri Devender Rao void appendData(const Property& key, const PropertyMap& propMap, 110*7d9157edSMarri Devender Rao FruAreaData& data) 111*7d9157edSMarri Devender Rao { 112*7d9157edSMarri Devender Rao auto iter = propMap.find(key); 113*7d9157edSMarri Devender Rao if (iter != propMap.end()) 114*7d9157edSMarri Devender Rao { 115*7d9157edSMarri Devender Rao auto value = iter->second; 116*7d9157edSMarri Devender Rao //If starts with 0x or 0X remove them 117*7d9157edSMarri Devender Rao //ex: 0x123a just take 123a 118*7d9157edSMarri Devender Rao if ((value.compare(0, 2, "0x")) == 0 || 119*7d9157edSMarri Devender Rao (value.compare(0, 2, "0X") == 0)) 120*7d9157edSMarri Devender Rao { 121*7d9157edSMarri Devender Rao value.erase(0, 2); 122*7d9157edSMarri Devender Rao } 123*7d9157edSMarri Devender Rao data.emplace_back(value.length()); 124*7d9157edSMarri Devender Rao std::copy(value.begin(), value.end(), std::back_inserter(data)); 125*7d9157edSMarri Devender Rao } 126*7d9157edSMarri Devender Rao else 127*7d9157edSMarri Devender Rao { 128*7d9157edSMarri Devender Rao //set 0 size 129*7d9157edSMarri Devender Rao data.emplace_back(typeLengthByteNull); 130*7d9157edSMarri Devender Rao } 131*7d9157edSMarri Devender Rao } 132*7d9157edSMarri Devender Rao 133*7d9157edSMarri Devender Rao 134*7d9157edSMarri Devender Rao /** 135*7d9157edSMarri Devender Rao * @brief Appends Build Date 136*7d9157edSMarri Devender Rao * 137*7d9157edSMarri Devender Rao * @param[in] propMap map of property values 138*7d9157edSMarri Devender Rao * @param[in/out] data FRU area to add the manfufacture date 139*7d9157edSMarri Devender Rao */ 140*7d9157edSMarri Devender Rao void appendMfgDate(const PropertyMap& propMap, FruAreaData& data) 141*7d9157edSMarri Devender Rao { 142*7d9157edSMarri Devender Rao //MFG Date/Time 143*7d9157edSMarri Devender Rao auto iter = propMap.find(buildDate); 144*7d9157edSMarri Devender Rao if (iter != propMap.end()) 145*7d9157edSMarri Devender Rao { 146*7d9157edSMarri Devender Rao auto& value = iter->second; 147*7d9157edSMarri Devender Rao if (value.length() == manufacturingDateSize) 148*7d9157edSMarri Devender Rao { 149*7d9157edSMarri Devender Rao std::copy( 150*7d9157edSMarri Devender Rao value.begin(), value.end(), std::back_inserter(data)); 151*7d9157edSMarri Devender Rao return; 152*7d9157edSMarri Devender Rao } 153*7d9157edSMarri Devender Rao } 154*7d9157edSMarri Devender Rao //Blank date 155*7d9157edSMarri Devender Rao data.emplace_back(0); 156*7d9157edSMarri Devender Rao data.emplace_back(0); 157*7d9157edSMarri Devender Rao data.emplace_back(0); 158*7d9157edSMarri Devender Rao } 159*7d9157edSMarri Devender Rao 160*7d9157edSMarri Devender Rao /** 161*7d9157edSMarri Devender Rao * @brief Builds a section of the common header 162*7d9157edSMarri Devender Rao * 163*7d9157edSMarri Devender Rao * @param[in] infoAreaSize size of the FRU area to write 164*7d9157edSMarri Devender Rao * @param[in] offset Current offset for data in overall record 165*7d9157edSMarri Devender Rao * @param[in/out] data Common Header section data container 166*7d9157edSMarri Devender Rao */ 167*7d9157edSMarri Devender Rao void buildCommonHeaderSection( 168*7d9157edSMarri Devender Rao const uint32_t& infoAreaSize, uint32_t& offset, FruAreaData& data) 169*7d9157edSMarri Devender Rao { 170*7d9157edSMarri Devender Rao //Check if data for internal use section populated 171*7d9157edSMarri Devender Rao if (infoAreaSize == 0) 172*7d9157edSMarri Devender Rao { 173*7d9157edSMarri Devender Rao //Indicate record not present 174*7d9157edSMarri Devender Rao data.emplace_back(recordNotPresent); 175*7d9157edSMarri Devender Rao } 176*7d9157edSMarri Devender Rao else 177*7d9157edSMarri Devender Rao { 178*7d9157edSMarri Devender Rao //Place data to define offset to area data section 179*7d9157edSMarri Devender Rao data.emplace_back((offset + commonHeaderFormatSize) 180*7d9157edSMarri Devender Rao / recordUnitOfMeasurment); 181*7d9157edSMarri Devender Rao offset += infoAreaSize; 182*7d9157edSMarri Devender Rao } 183*7d9157edSMarri Devender Rao } 184*7d9157edSMarri Devender Rao 185*7d9157edSMarri Devender Rao /** 186*7d9157edSMarri Devender Rao * @brief Builds the Chassis info area data section 187*7d9157edSMarri Devender Rao * 188*7d9157edSMarri Devender Rao * @param[in] propMap map of properties for chassis info area 189*7d9157edSMarri Devender Rao * @return FruAreaData container with chassis info area 190*7d9157edSMarri Devender Rao */ 191*7d9157edSMarri Devender Rao FruAreaData buildChassisInfoArea(const PropertyMap& propMap) 192*7d9157edSMarri Devender Rao { 193*7d9157edSMarri Devender Rao FruAreaData fruAreaData; 194*7d9157edSMarri Devender Rao if (!propMap.empty()) 195*7d9157edSMarri Devender Rao { 196*7d9157edSMarri Devender Rao //Set formatting data that goes at the beginning of the record 197*7d9157edSMarri Devender Rao preFormatProcessing(false, fruAreaData); 198*7d9157edSMarri Devender Rao 199*7d9157edSMarri Devender Rao //chassis type 200*7d9157edSMarri Devender Rao fruAreaData.emplace_back(0); 201*7d9157edSMarri Devender Rao 202*7d9157edSMarri Devender Rao //Chasiss part number, in config.yaml it is configured as model 203*7d9157edSMarri Devender Rao appendData(model, propMap, fruAreaData); 204*7d9157edSMarri Devender Rao 205*7d9157edSMarri Devender Rao //Board serial number 206*7d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 207*7d9157edSMarri Devender Rao 208*7d9157edSMarri Devender Rao //Indicate End of Custom Fields 209*7d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 210*7d9157edSMarri Devender Rao 211*7d9157edSMarri Devender Rao //Complete record data formatting 212*7d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 213*7d9157edSMarri Devender Rao } 214*7d9157edSMarri Devender Rao return fruAreaData; 215*7d9157edSMarri Devender Rao } 216*7d9157edSMarri Devender Rao 217*7d9157edSMarri Devender Rao /** 218*7d9157edSMarri Devender Rao * @brief Builds the Board info area data section 219*7d9157edSMarri Devender Rao * 220*7d9157edSMarri Devender Rao * @param[in] propMap map of properties for board info area 221*7d9157edSMarri Devender Rao * @return FruAreaData container with board info area 222*7d9157edSMarri Devender Rao */ 223*7d9157edSMarri Devender Rao FruAreaData buildBoardInfoArea(const PropertyMap& propMap) 224*7d9157edSMarri Devender Rao { 225*7d9157edSMarri Devender Rao FruAreaData fruAreaData; 226*7d9157edSMarri Devender Rao if (!propMap.empty()) 227*7d9157edSMarri Devender Rao { 228*7d9157edSMarri Devender Rao preFormatProcessing(true, fruAreaData); 229*7d9157edSMarri Devender Rao 230*7d9157edSMarri Devender Rao //Manufacturing date 231*7d9157edSMarri Devender Rao appendMfgDate(propMap, fruAreaData); 232*7d9157edSMarri Devender Rao 233*7d9157edSMarri Devender Rao //manufacturer 234*7d9157edSMarri Devender Rao appendData(manufacturer, propMap, fruAreaData); 235*7d9157edSMarri Devender Rao 236*7d9157edSMarri Devender Rao //Product name/Pretty name 237*7d9157edSMarri Devender Rao appendData(prettyName, propMap, fruAreaData); 238*7d9157edSMarri Devender Rao 239*7d9157edSMarri Devender Rao //Board serial number 240*7d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 241*7d9157edSMarri Devender Rao 242*7d9157edSMarri Devender Rao //Board part number 243*7d9157edSMarri Devender Rao appendData(partNumber, propMap, fruAreaData); 244*7d9157edSMarri Devender Rao 245*7d9157edSMarri Devender Rao //FRU File ID - Empty 246*7d9157edSMarri Devender Rao fruAreaData.emplace_back(typeLengthByteNull); 247*7d9157edSMarri Devender Rao 248*7d9157edSMarri Devender Rao // Empty FRU File ID bytes 249*7d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 250*7d9157edSMarri Devender Rao 251*7d9157edSMarri Devender Rao //End of custom fields 252*7d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 253*7d9157edSMarri Devender Rao 254*7d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 255*7d9157edSMarri Devender Rao } 256*7d9157edSMarri Devender Rao return fruAreaData; 257*7d9157edSMarri Devender Rao } 258*7d9157edSMarri Devender Rao 259*7d9157edSMarri Devender Rao /** 260*7d9157edSMarri Devender Rao * @brief Builds the Product info area data section 261*7d9157edSMarri Devender Rao * 262*7d9157edSMarri Devender Rao * @param[in] propMap map of FRU properties for Board info area 263*7d9157edSMarri Devender Rao * @return FruAreaData container with product info area data 264*7d9157edSMarri Devender Rao */ 265*7d9157edSMarri Devender Rao FruAreaData buildProductInfoArea(const PropertyMap& propMap) 266*7d9157edSMarri Devender Rao { 267*7d9157edSMarri Devender Rao FruAreaData fruAreaData; 268*7d9157edSMarri Devender Rao if (!propMap.empty()) 269*7d9157edSMarri Devender Rao { 270*7d9157edSMarri Devender Rao //Set formatting data that goes at the beginning of the record 271*7d9157edSMarri Devender Rao preFormatProcessing(true, fruAreaData); 272*7d9157edSMarri Devender Rao 273*7d9157edSMarri Devender Rao //manufacturer 274*7d9157edSMarri Devender Rao appendData(manufacturer, propMap, fruAreaData); 275*7d9157edSMarri Devender Rao 276*7d9157edSMarri Devender Rao //Product name/Pretty name 277*7d9157edSMarri Devender Rao appendData(prettyName, propMap, fruAreaData); 278*7d9157edSMarri Devender Rao 279*7d9157edSMarri Devender Rao //Product part/model number 280*7d9157edSMarri Devender Rao appendData(model, propMap, fruAreaData); 281*7d9157edSMarri Devender Rao 282*7d9157edSMarri Devender Rao //Product version 283*7d9157edSMarri Devender Rao appendData(version, propMap, fruAreaData); 284*7d9157edSMarri Devender Rao 285*7d9157edSMarri Devender Rao //Serial Number 286*7d9157edSMarri Devender Rao appendData(serialNumber, propMap, fruAreaData); 287*7d9157edSMarri Devender Rao 288*7d9157edSMarri Devender Rao //Add Asset Tag 289*7d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 290*7d9157edSMarri Devender Rao 291*7d9157edSMarri Devender Rao //FRU File ID - Empty 292*7d9157edSMarri Devender Rao fruAreaData.emplace_back(typeLengthByteNull); 293*7d9157edSMarri Devender Rao 294*7d9157edSMarri Devender Rao // Empty FRU File ID bytes 295*7d9157edSMarri Devender Rao fruAreaData.emplace_back(recordNotPresent); 296*7d9157edSMarri Devender Rao 297*7d9157edSMarri Devender Rao //End of custom fields 298*7d9157edSMarri Devender Rao fruAreaData.emplace_back(endOfCustomFields); 299*7d9157edSMarri Devender Rao 300*7d9157edSMarri Devender Rao postFormatProcessing(fruAreaData); 301*7d9157edSMarri Devender Rao } 302*7d9157edSMarri Devender Rao return fruAreaData; 303*7d9157edSMarri Devender Rao } 304*7d9157edSMarri Devender Rao 305*7d9157edSMarri Devender Rao FruAreaData buildFruAreaData(const FruInventoryData& inventory) 306*7d9157edSMarri Devender Rao { 307*7d9157edSMarri Devender Rao FruAreaData combFruArea; 308*7d9157edSMarri Devender Rao //Now build common header with data for this FRU Inv Record 309*7d9157edSMarri Devender Rao //Use this variable to increment size of header as we go along to determine 310*7d9157edSMarri Devender Rao //offset for the subsequent area offsets 311*7d9157edSMarri Devender Rao uint32_t curDataOffset = 0; 312*7d9157edSMarri Devender Rao 313*7d9157edSMarri Devender Rao //First byte is id for version of FRU Info Storage Spec used 314*7d9157edSMarri Devender Rao combFruArea.emplace_back(specVersion); 315*7d9157edSMarri Devender Rao 316*7d9157edSMarri Devender Rao //2nd byte is offset to internal use data 317*7d9157edSMarri Devender Rao combFruArea.emplace_back(recordNotPresent); 318*7d9157edSMarri Devender Rao 319*7d9157edSMarri Devender Rao //3rd byte is offset to chassis data 320*7d9157edSMarri Devender Rao FruAreaData chassisArea; 321*7d9157edSMarri Devender Rao auto chassisIt = inventory.find(chassis); 322*7d9157edSMarri Devender Rao if (chassisIt != inventory.end()) 323*7d9157edSMarri Devender Rao { 324*7d9157edSMarri Devender Rao chassisArea = std::move(buildChassisInfoArea(chassisIt->second)); 325*7d9157edSMarri Devender Rao } 326*7d9157edSMarri Devender Rao buildCommonHeaderSection(chassisArea.size(), curDataOffset, combFruArea); 327*7d9157edSMarri Devender Rao 328*7d9157edSMarri Devender Rao //4th byte is offset to board data 329*7d9157edSMarri Devender Rao FruAreaData boardArea; 330*7d9157edSMarri Devender Rao auto boardIt = inventory.find(board); 331*7d9157edSMarri Devender Rao if (boardIt != inventory.end()) 332*7d9157edSMarri Devender Rao { 333*7d9157edSMarri Devender Rao boardArea = std::move(buildBoardInfoArea(boardIt->second)); 334*7d9157edSMarri Devender Rao } 335*7d9157edSMarri Devender Rao 336*7d9157edSMarri Devender Rao //5th byte is offset to product data 337*7d9157edSMarri Devender Rao FruAreaData prodArea; 338*7d9157edSMarri Devender Rao auto prodIt = inventory.find(product); 339*7d9157edSMarri Devender Rao if (prodIt != inventory.end()) 340*7d9157edSMarri Devender Rao { 341*7d9157edSMarri Devender Rao prodArea = std::move(buildProductInfoArea(prodIt->second)); 342*7d9157edSMarri Devender Rao } 343*7d9157edSMarri Devender Rao buildCommonHeaderSection(prodArea.size(), curDataOffset, combFruArea); 344*7d9157edSMarri Devender Rao 345*7d9157edSMarri Devender Rao //6th byte is offset to multirecord data 346*7d9157edSMarri Devender Rao combFruArea.emplace_back(recordNotPresent); 347*7d9157edSMarri Devender Rao 348*7d9157edSMarri Devender Rao //7th byte is PAD 349*7d9157edSMarri Devender Rao padData(combFruArea); 350*7d9157edSMarri Devender Rao 351*7d9157edSMarri Devender Rao //8th (Final byte of Header Format) is the checksum 352*7d9157edSMarri Devender Rao appendDataChecksum(combFruArea); 353*7d9157edSMarri Devender Rao 354*7d9157edSMarri Devender Rao //Combine everything into one full IPMI FRU specification Record 355*7d9157edSMarri Devender Rao //add chassis use area data 356*7d9157edSMarri Devender Rao combFruArea.insert( 357*7d9157edSMarri Devender Rao combFruArea.end(), chassisArea.begin(), chassisArea.end()); 358*7d9157edSMarri Devender Rao 359*7d9157edSMarri Devender Rao //add board area data 360*7d9157edSMarri Devender Rao combFruArea.insert(combFruArea.end(), boardArea.begin(), boardArea.end()); 361*7d9157edSMarri Devender Rao 362*7d9157edSMarri Devender Rao //add product use area data 363*7d9157edSMarri Devender Rao combFruArea.insert(combFruArea.end(), prodArea.begin(), prodArea.end()); 364*7d9157edSMarri Devender Rao 365*7d9157edSMarri Devender Rao return combFruArea; 366*7d9157edSMarri Devender Rao } 367*7d9157edSMarri Devender Rao 368*7d9157edSMarri Devender Rao } //fru 369*7d9157edSMarri Devender Rao } //ipmi 370