1 #include "config.h" 2 3 #include "reader_impl.hpp" 4 5 #include "utils.hpp" 6 7 #include <algorithm> 8 #include <com/ibm/VPD/error.hpp> 9 #include <map> 10 #include <phosphor-logging/elog-errors.hpp> 11 #include <vector> 12 #include <xyz/openbmc_project/Common/error.hpp> 13 14 #ifdef ManagerTest 15 #include "reader_test.hpp" 16 #endif 17 18 namespace openpower 19 { 20 namespace vpd 21 { 22 namespace manager 23 { 24 namespace reader 25 { 26 27 using namespace phosphor::logging; 28 using namespace openpower::vpd::inventory; 29 using namespace openpower::vpd::constants; 30 using namespace openpower::vpd::utils::interface; 31 32 using InvalidArgument = 33 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 34 using Argument = xyz::openbmc_project::Common::InvalidArgument; 35 using LocationNotFound = sdbusplus::com::ibm::VPD::Error::LocationNotFound; 36 37 bool ReaderImpl::isValidLocationCode(const LocationCode& locationCode) const 38 { 39 if ((locationCode.length() < UNEXP_LOCATION_CODE_MIN_LENGTH) || 40 (locationCode[0] != 'U') || 41 ((locationCode.find("fcs", 1, 3) == std::string::npos) && 42 (locationCode.find("mts", 1, 3) == std::string::npos))) 43 { 44 return false; 45 } 46 47 return true; 48 } 49 50 LocationCode ReaderImpl::getExpandedLocationCode( 51 const LocationCode& locationCode, const NodeNumber& nodeNumber, 52 const LocationCodeMap& frusLocationCode) const 53 { 54 // unused at this moment. Hence to avoid warnings 55 (void)nodeNumber; 56 if (!isValidLocationCode(locationCode)) 57 { 58 // argument is not valid 59 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"), 60 Argument::ARGUMENT_VALUE(locationCode.c_str())); 61 } 62 auto iterator = frusLocationCode.find(locationCode); 63 if (iterator == frusLocationCode.end()) 64 { 65 // TODO: Implementation of error logic till then throwing invalid 66 // argument 67 // the location code was not found in the system 68 // elog<LocationNotFound>(); 69 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"), 70 Argument::ARGUMENT_VALUE(locationCode.c_str())); 71 } 72 73 std::string expandedLocationCode{}; 74 #ifndef ManagerTest 75 utility utilObj; 76 #endif 77 expandedLocationCode = utilObj.readBusProperty( 78 iterator->second, LOCATION_CODE_INF, "LocationCode"); 79 return expandedLocationCode; 80 } 81 82 ListOfPaths 83 ReaderImpl::getFrusAtLocation(const LocationCode& locationCode, 84 const NodeNumber& nodeNumber, 85 const LocationCodeMap& frusLocationCode) const 86 { 87 // unused at this moment, to avoid compilation warning 88 (void)nodeNumber; 89 90 // TODO:Implementation related to node number 91 if (!isValidLocationCode(locationCode)) 92 { 93 // argument is not valid 94 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"), 95 Argument::ARGUMENT_VALUE(locationCode.c_str())); 96 } 97 98 auto range = frusLocationCode.equal_range(locationCode); 99 100 if (range.first == frusLocationCode.end()) 101 { 102 // TODO: Implementation of error logic till then throwing invalid 103 // argument 104 // the location code was not found in the system 105 // elog<LocationNotFound>(); 106 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"), 107 Argument::ARGUMENT_VALUE(locationCode.c_str())); 108 } 109 110 ListOfPaths inventoryPaths; 111 112 for_each(range.first, range.second, 113 [&inventoryPaths]( 114 const inventory::LocationCodeMap::value_type& mappedItem) { 115 inventoryPaths.push_back(INVENTORY_PATH + mappedItem.second); 116 }); 117 return inventoryPaths; 118 } 119 120 std::tuple<LocationCode, NodeNumber> 121 ReaderImpl::getCollapsedLocationCode(const LocationCode& locationCode) const 122 { 123 // Location code should always start with U and fulfil minimum length 124 // criteria. 125 if (locationCode[0] != 'U' || 126 locationCode.length() < EXP_LOCATIN_CODE_MIN_LENGTH) 127 { 128 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"), 129 Argument::ARGUMENT_VALUE(locationCode.c_str())); 130 } 131 132 std::string fc{}; 133 #ifndef ManagerTest 134 utility utilObj; 135 #endif 136 137 fc = utilObj.readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC"); 138 139 // get the first part of expanded location code to check for FC or TM 140 std::string firstKeyword = locationCode.substr(1, 4); 141 142 LocationCode unexpandedLocationCode{}; 143 NodeNumber nodeNummber = INVALID_NODE_NUMBER; 144 145 // check if this value matches the value of FC kwd 146 if (fc.substr(0, 4) == 147 firstKeyword) // implies this is Ufcs format location code 148 { 149 // period(.) should be there in expanded location code to seggregate FC, 150 // Node number and SE values. 151 size_t nodeStartPos = locationCode.find('.'); 152 if (nodeStartPos == std::string::npos) 153 { 154 elog<InvalidArgument>( 155 Argument::ARGUMENT_NAME("LOCATIONCODE"), 156 Argument::ARGUMENT_VALUE(locationCode.c_str())); 157 } 158 159 // second period(.) should be there to end the node details in non 160 // system location code 161 size_t nodeEndPos = locationCode.find('.', nodeStartPos + 1); 162 if (nodeEndPos == std::string::npos) 163 { 164 elog<InvalidArgument>( 165 Argument::ARGUMENT_NAME("LOCATIONCODE"), 166 Argument::ARGUMENT_VALUE(locationCode.c_str())); 167 } 168 169 // skip 3 for '.ND' 170 nodeNummber = std::stoi(locationCode.substr( 171 nodeStartPos + 3, (nodeEndPos - nodeStartPos - 3))); 172 173 // confirm if there are other details apart FC, Node number and SE in 174 // location code 175 if (locationCode.length() > EXP_LOCATIN_CODE_MIN_LENGTH) 176 { 177 unexpandedLocationCode = 178 locationCode[0] + (std::string) "fcs" + 179 locationCode.substr(nodeEndPos + 1 + SE_KWD_LENGTH, 180 std::string::npos); 181 } 182 else 183 { 184 unexpandedLocationCode = "Ufcs"; 185 } 186 } 187 else 188 { 189 std::string tm{}; 190 // read TM kwd value 191 tm = 192 utilObj.readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM"); 193 ; 194 195 // check if the substr matches to TM kwd 196 if (tm.substr(0, 4) == 197 firstKeyword) // implies this is Umts format of location code 198 { 199 // system location code will not have any other details and node 200 // number 201 unexpandedLocationCode = "Umts"; 202 } 203 // it does not belong to either "fcs" or "mts" 204 else 205 { 206 elog<InvalidArgument>( 207 Argument::ARGUMENT_NAME("LOCATIONCODE"), 208 Argument::ARGUMENT_VALUE(locationCode.c_str())); 209 } 210 } 211 212 return std::make_tuple(unexpandedLocationCode, nodeNummber); 213 } 214 215 ListOfPaths ReaderImpl::getFRUsByExpandedLocationCode( 216 const inventory::LocationCode& locationCode, 217 const inventory::LocationCodeMap& frusLocationCode) const 218 { 219 std::tuple<LocationCode, NodeNumber> locationAndNodePair = 220 getCollapsedLocationCode(locationCode); 221 222 return getFrusAtLocation(std::get<0>(locationAndNodePair), 223 std::get<1>(locationAndNodePair), 224 frusLocationCode); 225 } 226 } // namespace reader 227 } // namespace manager 228 } // namespace vpd 229 } // namespace openpower 230