1 #pragma once 2 3 #include "const.hpp" 4 #include "store.hpp" 5 #include "types.hpp" 6 7 #include <iostream> 8 #include <nlohmann/json.hpp> 9 #include <optional> 10 11 namespace openpower 12 { 13 namespace vpd 14 { 15 16 // Map to hold record, kwd pair which can be re-stored at standby. 17 // The list of keywords for VSYS record is as per the S0 system. Should 18 // be updated for another type of systems 19 static const std::unordered_map<std::string, std::vector<std::string>> 20 svpdKwdMap{{"VSYS", {"BR", "TM", "SE", "SU", "RB", "WN", "RG", "FV"}}, 21 {"VCEN", {"FC", "SE"}}, 22 {"LXR0", {"LX"}}, 23 {"UTIL", {"D0"}}}; 24 25 /** @brief Return the hex representation of the incoming byte 26 * 27 * @param [in] c - The input byte 28 * @returns The hex representation of the byte as a character. 29 */ 30 constexpr auto toHex(size_t c) 31 { 32 constexpr auto map = "0123456789abcdef"; 33 return map[c]; 34 } 35 36 namespace inventory 37 { 38 /** @brief API to obtain a dictionary of path -> services 39 * where path is in subtree and services is of the type 40 * returned by the GetObject method. 41 * 42 * @param [in] root - Root path for object subtree 43 * @param [in] depth - Maximum subtree depth required 44 * @param [in] interfaces - Array to interfaces for which 45 * result is required. 46 * @return A dictionary of Path -> services 47 */ 48 MapperResponse 49 getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth, 50 const std::vector<std::string>& interfaces); 51 52 } // namespace inventory 53 54 /**@brief This API reads 2 Bytes of data and swap the read data 55 * @param[in] iterator- Pointer pointing to the data to be read 56 * @return returns 2 Byte data read at the given pointer 57 */ 58 openpower::vpd::constants::LE2ByteData 59 readUInt16LE(Binary::const_iterator iterator); 60 61 /** @brief Encodes a keyword for D-Bus. 62 * @param[in] kw - kwd data in string format 63 * @param[in] encoding - required for kwd data 64 */ 65 std::string encodeKeyword(const std::string& kw, const std::string& encoding); 66 67 /** @brief Reads a property from the inventory manager given object path, 68 * intreface and property. 69 * @param[in] obj - object path 70 * @param[in] inf - interface 71 * @param[in] prop - property whose value is fetched 72 * @return [out] - value of the property 73 */ 74 std::string readBusProperty(const std::string& obj, const std::string& inf, 75 const std::string& prop); 76 77 /** @brief A templated function to read D-Bus properties. 78 * 79 * @param[in] service - Service path 80 * @param[in] object - object path 81 * @param[in] inf - interface 82 * @param[in] prop - property whose value is fetched 83 * @return The property value of its own type. 84 */ 85 template <typename T> 86 T readDBusProperty(const std::string& service, const std::string& object, 87 const std::string& inf, const std::string& prop) 88 { 89 T retVal{}; 90 try 91 { 92 auto bus = sdbusplus::bus::new_default(); 93 auto properties = 94 bus.new_method_call(service.c_str(), object.c_str(), 95 "org.freedesktop.DBus.Properties", "Get"); 96 properties.append(inf); 97 properties.append(prop); 98 auto result = bus.call(properties); 99 result.read(retVal); 100 } 101 catch (const sdbusplus::exception::SdBusError& e) 102 { 103 std::cerr << e.what(); 104 } 105 return retVal; 106 } 107 108 /** @brief A templated method to get all D-Bus properties 109 * 110 * @param[in] service - Service path 111 * @param[in] object - Object path 112 * @param[in] inf - Interface 113 * 114 * @return All properties under the given interface. 115 */ 116 template <typename T> 117 T getAllDBusProperty(const std::string& service, const std::string& object, 118 const std::string& inf) 119 { 120 T retVal{}; 121 try 122 { 123 auto bus = sdbusplus::bus::new_default(); 124 auto allProperties = 125 bus.new_method_call(service.c_str(), object.c_str(), 126 "org.freedesktop.DBus.Properties", "GetAll"); 127 allProperties.append(inf); 128 129 auto result = bus.call(allProperties); 130 result.read(retVal); 131 } 132 catch (const sdbusplus::exception::SdBusError& e) 133 { 134 std::cerr << e.what(); 135 } 136 return retVal; 137 } 138 139 /** 140 * @brief API to create PEL entry 141 * @param[in] additionalData - Map holding the additional data 142 * @param[in] sev - Severity 143 * @param[in] errIntf - error interface 144 */ 145 void createPEL(const std::map<std::string, std::string>& additionalData, 146 const constants::PelSeverity& sev, const std::string& errIntf); 147 148 /** 149 * @brief getVpdFilePath 150 * Get vpd file path corresponding to the given object path. 151 * @param[in] - json file path 152 * @param[in] - Object path 153 * @return - Vpd file path 154 */ 155 inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile, 156 const std::string& ObjPath); 157 158 /** 159 * @brief isPathInJson 160 * API which checks for the presence of the given eeprom path in the given json. 161 * @param[in] - eepromPath 162 * @return - true if the eeprom is present in the json; false otherwise 163 */ 164 bool isPathInJson(const std::string& eepromPath); 165 166 /** 167 * @brief isRecKwInDbusJson 168 * API which checks whether the given keyword under the given record is to be 169 * published on dbus or not. Checks against the keywords present in 170 * dbus_property.json. 171 * @param[in] - record name 172 * @param[in] - keyword name 173 * @return - true if the record-keyword pair is present in dbus_property.json; 174 * false otherwise. 175 */ 176 bool isRecKwInDbusJson(const std::string& record, const std::string& keyword); 177 178 /** 179 * @brief Check the type of VPD. 180 * 181 * Checks the type of vpd based on the start tag. 182 * @param[in] vector - Vpd data in vector format 183 * 184 * @return enum of type vpdType 185 */ 186 constants::vpdType vpdTypeCheck(const Binary& vector); 187 188 /* 189 * @brief This method does nothing. Just an empty function to return null 190 * at the end of variadic template args 191 */ 192 inline std::string getCommand() 193 { 194 return ""; 195 } 196 197 /** 198 * @brief This function to arrange all arguments to make commandy 199 * @param[in] arguments to create the command 200 * @return cmd - command string 201 */ 202 template <typename T, typename... Types> 203 inline std::string getCommand(T arg1, Types... args) 204 { 205 std::string cmd = " " + arg1 + getCommand(args...); 206 207 return cmd; 208 } 209 210 /** 211 * @brief This API takes arguments, creates a shell command line and executes 212 * them. 213 * @param[in] arguments for command 214 * @returns output of that command 215 */ 216 template <typename T, typename... Types> 217 inline std::vector<std::string> executeCmd(T&& path, Types... args) 218 { 219 std::vector<std::string> stdOutput; 220 std::array<char, 128> buffer; 221 222 std::string cmd = path + getCommand(args...); 223 224 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), 225 pclose); 226 if (!pipe) 227 { 228 throw std::runtime_error("popen() failed!"); 229 } 230 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) 231 { 232 stdOutput.emplace_back(buffer.data()); 233 } 234 235 return stdOutput; 236 } 237 238 /** @brief This API checks for IM and HW keywords, and based 239 * on these values decides which system json to be used. 240 * @param[in] vpdMap - parsed vpd 241 * @returns System json path 242 */ 243 std::string getSystemsJson(const Parsed& vpdMap); 244 245 /** @brief Reads HW Keyword from the vpd 246 * @param[in] vpdMap - parsed vpd 247 * @returns value of HW Keyword 248 */ 249 const std::string getHW(const Parsed& vpdMap); 250 251 /** @brief Reads IM Keyword from the vpd 252 * @param[in] vpdMap - parsed vpd 253 * @returns value of IM Keyword 254 */ 255 const std::string getIM(const Parsed& vpdMap); 256 257 /** @brief Translate udev event generated path to a generic /sys/bus eeprom path 258 * @param[io] file - path generated from udev event. 259 */ 260 void udevToGenericPath(std::string& file); 261 262 /** 263 * @brief API to generate a vpd name in some pattern. 264 * This vpd-name denotes name of the bad vpd file. 265 * For i2c eeproms - the pattern of the vpd-name will be 266 * i2c-<bus-number>-<eeprom-address>. For spi eeproms - the pattern of the 267 * vpd-name will be spi-<spi-number>. 268 * 269 * @param[in] file - file path of the vpd 270 * @return the vpd-name. 271 */ 272 std::string getBadVpdName(const std::string& file); 273 274 /** 275 * @brief API which dumps the broken/bad vpd in a directory 276 * When the vpd is bad, this api places the bad vpd file inside 277 * "/tmp/bad-vpd" in BMC, in order to collect bad VPD data as a part of user 278 * initiated BMC dump. 279 * 280 * @param[in] file - bad vpd file path 281 * @param[in] vpdVector - bad vpd vector 282 */ 283 void dumpBadVpd(const std::string& file, const Binary& vpdVector); 284 285 /* 286 * @brief This function fetches the value for given keyword in the given record 287 * from vpd data and returns this value. 288 * 289 * @param[in] vpdMap - vpd to find out the data 290 * @param[in] rec - Record under which desired keyword exists 291 * @param[in] kwd - keyword to read the data from 292 * 293 * @returns keyword value if record/keyword combination found 294 * empty string if record or keyword is not found. 295 */ 296 const std::string getKwVal(const Parsed& vpdMap, const std::string& rec, 297 const std::string& kwd); 298 299 /** @brief This creates a complete command using all it's input parameters, 300 * to bind or unbind the driver. 301 * @param[in] devNameAddr - device address on that bus 302 * @param[in] busType - i2c, spi 303 * @param[in] driverType - type of driver like at24 304 * @param[in] bindOrUnbind - either bind or unbind 305 * @returns Command to bind or unbind the driver. 306 */ 307 inline std::string createBindUnbindDriverCmnd(const std::string& devNameAddr, 308 const std::string& busType, 309 const std::string& driverType, 310 const std::string& bindOrUnbind) 311 { 312 return ("echo " + devNameAddr + " > /sys/bus/" + busType + "/drivers/" + 313 driverType + "/" + bindOrUnbind); 314 } 315 316 /** 317 * @brief Get Printable Value 318 * 319 * Checks if the vector value has non printable characters. 320 * Returns hex value if non printable char is found else 321 * returns ascii value. 322 * 323 * @param[in] vector - Reference of the Binary vector 324 * @return printable value - either in hex or in ascii. 325 */ 326 std::string getPrintableValue(const Binary& vec); 327 328 /** 329 * @brief Convert byte array to hex string. 330 * @param[in] vec - byte array 331 * @return hexadecimal string of bytes. 332 */ 333 std::string byteArrayToHexString(const Binary& vec); 334 335 /** 336 * @brief Return presence of the FRU. 337 * 338 * This API returns the presence information of the FRU corresponding to the 339 * given EEPROM. If the JSON contains no information about presence detect, this 340 * will return an empty optional. Else it will get the presence GPIO information 341 * from the JSON and return the appropriate present status. 342 * In case of GPIO find/read errors, it will return false. 343 * 344 * @param[in] json - The VPD JSON 345 * @param[in] file - EEPROM file path 346 * @return Empty optional if there is no presence info. Else returns presence 347 * based on the GPIO read. 348 */ 349 std::optional<bool> isPresent(const nlohmann::json& json, 350 const std::string& file); 351 352 /** 353 * @brief Performs any pre-action needed to get the FRU setup for 354 * collection. 355 * 356 * @param[in] json - json object 357 * @param[in] file - eeprom file path 358 * @return - success or failure 359 */ 360 bool executePreAction(const nlohmann::json& json, const std::string& file); 361 362 /** 363 * @brief This API will be called at the end of VPD collection to perform any 364 * post actions. 365 * 366 * @param[in] json - json object 367 * @param[in] file - eeprom file path 368 */ 369 void executePostFailAction(const nlohmann::json& json, const std::string& file); 370 371 /** 372 * @brief Helper function to insert or merge in map. 373 * 374 * This method checks in the given inventory::InterfaceMap if the given 375 * interface key is existing or not. If the interface key already exists, given 376 * property map is inserted into it. If the key does'nt exist then given 377 * interface and property map pair is newly created. If the property present in 378 * propertymap already exist in the InterfaceMap, then the new property value is 379 * ignored. 380 * 381 * @param[in,out] map - map object of type inventory::InterfaceMap only. 382 * @param[in] interface - Interface name. 383 * @param[in] property - new property map that needs to be emplaced. 384 */ 385 void insertOrMerge(inventory::InterfaceMap& map, 386 const inventory::Interface& interface, 387 inventory::PropertyMap&& property); 388 389 /** 390 * @brief Utility API to set a D-Bus property 391 * 392 * This calls org.freedesktop.DBus.Properties;Set method with the supplied 393 * arguments 394 * 395 * @tparam T Template type of the D-Bus property 396 * @param service[in] - The D-Bus service name. 397 * @param object[in] - The D-Bus object on which the property is to be set. 398 * @param interface[in] - The D-Bus interface to which the property belongs. 399 * @param propertyName[in] - The name of the property to set. 400 * @param propertyValue[in] - The value of the property. 401 */ 402 template <typename T> 403 void setBusProperty(const std::string& service, const std::string& object, 404 const std::string& interface, 405 const std::string& propertyName, 406 const std::variant<T>& propertyValue) 407 { 408 try 409 { 410 auto bus = sdbusplus::bus::new_default(); 411 auto method = 412 bus.new_method_call(service.c_str(), object.c_str(), 413 "org.freedesktop.DBus.Properties", "Set"); 414 method.append(interface); 415 method.append(propertyName); 416 method.append(propertyValue); 417 418 bus.call(method); 419 } 420 catch (const sdbusplus::exception::SdBusError& e) 421 { 422 std::cerr << e.what() << std::endl; 423 } 424 } 425 426 /** 427 * @brief Reads BIOS Attribute by name. 428 * 429 * @param attrName[in] - The BIOS attribute name. 430 * @return std::variant<int64_t, std::string> - The BIOS attribute value. 431 */ 432 std::variant<int64_t, std::string> 433 readBIOSAttribute(const std::string& attrName); 434 435 /** 436 * @brief Returns the power state for chassis0 437 * @return The chassis power state. 438 */ 439 std::string getPowerState(); 440 441 /** 442 * @brief Reads VPD from the supplied EEPROM 443 * 444 * This function reads the given VPD EEPROM file and returns its contents as a 445 * byte array. It handles any offsets into the file that need to be taken care 446 * of by looking up the VPD JSON for a possible offset key. 447 * 448 * @param js[in] - The VPD JSON Object 449 * @param file[in] - The path to the EEPROM to read 450 * @return A byte array containing the raw VPD. 451 */ 452 Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file); 453 } // namespace vpd 454 } // namespace openpower