1 #pragma once 2 3 #include "constants.hpp" 4 #include "types.hpp" 5 6 #include <nlohmann/json.hpp> 7 8 #include <mutex> 9 #include <optional> 10 #include <semaphore> 11 #include <tuple> 12 13 namespace vpd 14 { 15 /** 16 * @brief A class to process and publish VPD data. 17 * 18 * The class works on VPD and is mainly responsible for following tasks: 19 * 1) Select appropriate device tree and JSON. Reboot if required. 20 * 2) Get desired parser using parser factory. 21 * 3) Calling respective parser class to get parsed VPD. 22 * 4) Arranging VPD data under required interfaces. 23 * 5) Calling PIM to publish VPD. 24 * 25 * The class may also implement helper functions required for VPD handling. 26 */ 27 class Worker 28 { 29 public: 30 /** 31 * List of deleted functions. 32 */ 33 Worker(const Worker&) = delete; 34 Worker& operator=(const Worker&) = delete; 35 Worker(Worker&&) = delete; 36 Worker& operator=(const Worker&&) = delete; 37 38 /** 39 * @brief Constructor. 40 * 41 * In case the processing is not JSON based, no argument needs to be passed. 42 * Constructor will also, based on symlink pick the correct JSON and 43 * initialize the parsed JSON variable. 44 * 45 * @param[in] pathToConfigJSON - Path to the config JSON, if applicable. 46 * @param[in] i_maxThreadCount - Maximum thread while collecting FRUs VPD. 47 * @param[in] i_vpdCollectionMode - Mode in which VPD collection should take 48 * place. 49 * 50 * Note: Throws std::exception in case of construction failure. Caller needs 51 * to handle to detect successful object creation. 52 */ 53 Worker(std::string pathToConfigJson = std::string(), 54 uint8_t i_maxThreadCount = constants::MAX_THREADS, 55 types::VpdCollectionMode i_vpdCollectionMode = 56 types::VpdCollectionMode::DEFAULT_MODE); 57 58 /** 59 * @brief Destructor 60 */ 61 ~Worker() = default; 62 63 /** 64 * @brief API to process all FRUs presnt in config JSON file. 65 * 66 * This API based on config JSON passed/selected for the system, will 67 * trigger parser for all the FRUs and publish it on DBus. 68 * 69 * Note: Config JSON file path should be passed to worker class constructor 70 * to make use of this API. 71 * 72 */ 73 void collectFrusFromJson(); 74 75 /** 76 * @brief API to parse VPD data 77 * 78 * @param[in] i_vpdFilePath - Path to the VPD file. 79 */ 80 types::VPDMapVariant parseVpdFile(const std::string& i_vpdFilePath); 81 82 /** 83 * @brief An API to populate DBus interfaces for a FRU. 84 * 85 * Note: Call this API to populate D-Bus. Also caller should handle empty 86 * objectInterfaceMap. 87 * 88 * @param[in] parsedVpdMap - Parsed VPD as a map. 89 * @param[out] objectInterfaceMap - Object and its interfaces map. 90 * @param[in] vpdFilePath - EEPROM path of FRU. 91 */ 92 void populateDbus(const types::VPDMapVariant& parsedVpdMap, 93 types::ObjectMap& objectInterfaceMap, 94 const std::string& vpdFilePath); 95 96 /** 97 * @brief An API to delete FRU VPD over DBus. 98 * 99 * @param[in] i_dbusObjPath - Dbus object path of the FRU. 100 * 101 * @throw std::runtime_error if given input path is empty. 102 */ 103 void deleteFruVpd(const std::string& i_dbusObjPath); 104 105 /** 106 * @brief API to get status of VPD collection process. 107 * 108 * @return - True when done, false otherwise. 109 */ isAllFruCollectionDone() const110 inline bool isAllFruCollectionDone() const 111 { 112 return m_isAllFruCollected; 113 } 114 115 /** 116 * @brief API to get system config JSON object 117 * 118 * @return System config JSON object. 119 */ getSysCfgJsonObj() const120 inline nlohmann::json getSysCfgJsonObj() const 121 { 122 return m_parsedJson; 123 } 124 125 /** 126 * @brief API to get active thread count. 127 * 128 * Each FRU is collected in a separate thread. This API gives the active 129 * thread collecting FRU's VPD at any given time. 130 * 131 * @return Count of active threads. 132 */ getActiveThreadCount() const133 size_t getActiveThreadCount() const 134 { 135 return m_activeCollectionThreadCount; 136 } 137 138 /** 139 * @brief API to get list of EEPROMs for which thread creation failed. 140 * 141 * This API returns reference to list of EEPROM paths for which VPD 142 * collection thread creation has failed. Manager needs to process this list 143 * of EEPROMs and take appropriate action. 144 * 145 * @return reference to list of EEPROM paths for which VPD collection thread 146 * creation has failed 147 */ getFailedEepromPaths()148 inline std::forward_list<std::string>& getFailedEepromPaths() noexcept 149 { 150 return m_failedEepromPaths; 151 } 152 153 /** 154 * @brief API to get VPD collection mode 155 * 156 * @return VPD collection mode enum value 157 */ getVpdCollectionMode() const158 inline types::VpdCollectionMode getVpdCollectionMode() const 159 { 160 return m_vpdCollectionMode; 161 } 162 163 /** 164 * @brief Collect single FRU VPD 165 * API can be used to perform VPD collection for the given FRU, only if the 166 * current state of the system matches with the state at which the FRU is 167 * allowed for VPD recollection. 168 * 169 * @param[in] i_dbusObjPath - D-bus object path 170 */ 171 void collectSingleFruVpd( 172 const sdbusplus::message::object_path& i_dbusObjPath); 173 174 /** 175 * @brief Perform VPD recollection 176 * This api will trigger parser to perform VPD recollection for FRUs that 177 * can be replaced at standby. 178 */ 179 void performVpdRecollection(); 180 181 /** 182 * @brief API to set CollectionStatus property. 183 * 184 * This API updates the CollectionStatus property of the given FRU with the 185 * given value. 186 * 187 * @param[in] i_vpdPath - EEPROM or inventory path. 188 * @param[in] i_value - Value to be set. 189 */ 190 void setCollectionStatusProperty(const std::string& i_fruPath, 191 const std::string& i_value) const noexcept; 192 193 private: 194 /** 195 * @brief An API to parse and publish a FRU VPD over D-Bus. 196 * 197 * Note: This API will handle all the exceptions internally and will only 198 * return status of parsing and publishing of VPD over D-Bus. 199 * 200 * @param[in] i_vpdFilePath - Path of file containing VPD. 201 * @return Tuple of status and file path. Status, true if successfull else 202 * false. 203 */ 204 std::tuple<bool, std::string> parseAndPublishVPD( 205 const std::string& i_vpdFilePath); 206 207 /** 208 * @brief An API to process extrainterfaces w.r.t a FRU. 209 * 210 * @param[in] singleFru - JSON block for a single FRU. 211 * @param[out] interfaces - Map to hold interface along with its properties. 212 * @param[in] parsedVpdMap - Parsed VPD as a map. 213 */ 214 void processExtraInterfaces(const nlohmann::json& singleFru, 215 types::InterfaceMap& interfaces, 216 const types::VPDMapVariant& parsedVpdMap); 217 218 /** 219 * @brief An API to process embedded and synthesized FRUs. 220 * 221 * @param[in] singleFru - FRU to be processed. 222 * @param[out] interfaces - Map to hold interface along with its properties. 223 */ 224 void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru, 225 types::InterfaceMap& interfaces); 226 227 /** 228 * @brief An API to read process FRU based in CCIN. 229 * 230 * For some FRUs VPD can be processed only if the FRU has some specific 231 * value for CCIN. In case the value is not from that set, VPD for those 232 * FRUs can't be processed. 233 * 234 * @param[in] singleFru - Fru whose CCIN value needs to be matched. 235 * @param[in] parsedVpdMap - Parsed VPD map. 236 */ 237 bool processFruWithCCIN(const nlohmann::json& singleFru, 238 const types::VPDMapVariant& parsedVpdMap); 239 240 /** 241 * @brief API to process json's inherit flag. 242 * 243 * Inherit flag denotes that some property in the child FRU needs to be 244 * inherited from parent FRU. 245 * 246 * @param[in] parsedVpdMap - Parsed VPD as a map. 247 * @param[out] interfaces - Map to hold interface along with its properties. 248 */ 249 void processInheritFlag(const types::VPDMapVariant& parsedVpdMap, 250 types::InterfaceMap& interfaces); 251 252 /** 253 * @brief API to process json's "copyRecord" flag. 254 * 255 * copyRecord flag denotes if some record data needs to be copies in the 256 * given FRU. 257 * 258 * @param[in] singleFru - FRU being processed. 259 * @param[in] parsedVpdMap - Parsed VPD as a map. 260 * @param[out] interfaces - Map to hold interface along with its properties. 261 */ 262 void processCopyRecordFlag(const nlohmann::json& singleFru, 263 const types::VPDMapVariant& parsedVpdMap, 264 types::InterfaceMap& interfaces); 265 266 /** 267 * @brief An API to populate IPZ VPD property map. 268 * 269 * @param[out] interfacePropMap - Map of interface and properties under it. 270 * @param[in] keyordValueMap - Keyword value map of IPZ VPD. 271 * @param[in] interfaceName - Name of the interface. 272 */ 273 void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap, 274 const types::IPZKwdValueMap& keyordValueMap, 275 const std::string& interfaceName); 276 277 /** 278 * @brief An API to populate Kwd VPD property map. 279 * 280 * @param[in] keyordValueMap - Keyword value map of Kwd VPD. 281 * @param[out] interfaceMap - interface and property,value under it. 282 */ 283 void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap, 284 types::InterfaceMap& interfaceMap); 285 286 /** 287 * @brief API to populate all required interface for a FRU. 288 * 289 * @param[in] interfaceJson - JSON containing interfaces to be populated. 290 * @param[out] interfaceMap - Map to hold populated interfaces. 291 * @param[in] parsedVpdMap - Parsed VPD as a map. 292 */ 293 void populateInterfaces(const nlohmann::json& interfaceJson, 294 types::InterfaceMap& interfaceMap, 295 const types::VPDMapVariant& parsedVpdMap); 296 297 /** 298 * @brief Check if the given CPU is an IO only chip. 299 * 300 * The CPU is termed as IO, whose all of the cores are bad and can never be 301 * used. Those CPU chips can be used for IO purpose like connecting PCIe 302 * devices etc., The CPU whose every cores are bad, can be identified from 303 * the CP00 record's PG keyword, only if all of the 8 EQs' value equals 304 * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.) 305 * 306 * @param [in] pgKeyword - PG Keyword of CPU. 307 * @return true if the given cpu is an IO, false otherwise. 308 */ 309 bool isCPUIOGoodOnly(const std::string& pgKeyword); 310 311 /** 312 * @brief API to process preAction(base_action) defined in config JSON. 313 * 314 * @note sequence of tags under any given flag of preAction is EXTREMELY 315 * important to ensure proper processing. The API will process all the 316 * nested items under the base action sequentially. Also if any of the tag 317 * processing fails, the code will not process remaining tags under the 318 * flag. 319 * ******** sample format ************** 320 * fru EEPROM path: { 321 * base_action: { 322 * flag1: { 323 * tag1: { 324 * }, 325 * tag2: { 326 * } 327 * } 328 * flag2: { 329 * tags: { 330 * } 331 * } 332 * } 333 * } 334 * ************************************* 335 * 336 * @param[in] i_vpdFilePath - Path to the EEPROM file. 337 * @param[in] i_flagToProcess - To identify which flag(s) needs to be 338 * processed under PreAction tag of config JSON. 339 * @param[out] o_errCode - To set error code in case of error. 340 * @return Execution status. 341 */ 342 bool processPreAction(const std::string& i_vpdFilePath, 343 const std::string& i_flagToProcess, 344 uint16_t& o_errCode); 345 346 /** 347 * @brief API to process postAction(base_action) defined in config JSON. 348 * 349 * @note Sequence of tags under any given flag of postAction is EXTREMELY 350 * important to ensure proper processing. The API will process all the 351 * nested items under the base action sequentially. Also if any of the tag 352 * processing fails, the code will not process remaining tags under the 353 * flag. 354 * ******** sample format ************** 355 * fru EEPROM path: { 356 * base_action: { 357 * flag1: { 358 * tag1: { 359 * }, 360 * tag2: { 361 * } 362 * } 363 * flag2: { 364 * tags: { 365 * } 366 * } 367 * } 368 * } 369 * ************************************* 370 * Also, if post action is required to be processed only for FRUs with 371 * certain CCIN then CCIN list can be provided under flag. 372 * 373 * @param[in] i_vpdFruPath - Path to the EEPROM file. 374 * @param[in] i_flagToProcess - To identify which flag(s) needs to be 375 * processed under postAction tag of config JSON. 376 * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is 377 * required. 378 * @return Execution status. 379 */ 380 bool processPostAction( 381 const std::string& i_vpdFruPath, const std::string& i_flagToProcess, 382 const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt); 383 384 /** 385 * @brief API to update "Functional" property. 386 * 387 * The API sets the default value for "Functional" property once if the 388 * property is not yet populated over DBus. As the property value is not 389 * controlled by the VPD-Collection process, if it is found already 390 * populated, the functions skips re-populating the property so that already 391 * existing value can be retained. 392 * 393 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON. 394 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU. 395 */ 396 void processFunctionalProperty(const std::string& i_inventoryObjPath, 397 types::InterfaceMap& io_interfaces); 398 399 /** 400 * @brief API to update "enabled" property. 401 * 402 * The API sets the default value for "enabled" property once if the 403 * property is not yet populated over DBus. As the property value is not 404 * controlled by the VPD-Collection process, if it is found already 405 * populated, the functions skips re-populating the property so that already 406 * existing value can be retained. 407 * 408 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON. 409 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU. 410 */ 411 void processEnabledProperty(const std::string& i_inventoryObjPath, 412 types::InterfaceMap& io_interfaces); 413 414 /** 415 * @brief API to set present property. 416 * 417 * This API updates the present property of the given FRU with the given 418 * value. Note: It is the responsibility of the caller to determine whether 419 * the present property for the FRU should be updated or not. 420 * 421 * @param[in] i_vpdPath - EEPROM or inventory path. 422 * @param[in] i_value - value to be set. 423 */ 424 void setPresentProperty(const std::string& i_fruPath, const bool& i_value); 425 426 /** 427 * @brief API to check if the path needs to be skipped for collection. 428 * 429 * Some FRUs, under some given scenarios should not be collected and 430 * skipped. 431 * 432 * @param[in] i_vpdFilePath - EEPROM path. 433 * 434 * @return True - if path is empty or should be skipped, false otherwise. 435 */ 436 bool skipPathForCollection(const std::string& i_vpdFilePath); 437 438 /** 439 * @brief API to check if present property should be handled for given FRU. 440 * 441 * vpd-manager should update present property for a FRU if and only if it's 442 * not synthesized and vpd-manager handles present property for the FRU. 443 * This API assumes "handlePresence" tag is a subset of "synthesized" tag. 444 * 445 * @param[in] i_fru - JSON block for a single FRU. 446 * 447 * @return true if present property should be handled, false otherwise. 448 */ isPresentPropertyHandlingRequired(const nlohmann::json & i_fru) const449 inline bool isPresentPropertyHandlingRequired( 450 const nlohmann::json& i_fru) const noexcept 451 { 452 // TODO: revisit this to see if this logic can be optimized. 453 return !i_fru.value("synthesized", false) && 454 i_fru.value("handlePresence", true); 455 } 456 457 // Parsed JSON file. 458 nlohmann::json m_parsedJson{}; 459 460 // Path to config JSON if applicable. 461 std::string& m_configJsonPath; 462 463 // Keeps track of active thread(s) doing VPD collection. 464 size_t m_activeCollectionThreadCount = 0; 465 466 // Holds status, if VPD collection has been done or not. 467 // Note: This variable does not give information about successfull or failed 468 // collection. It just states, if the VPD collection process is over or not. 469 bool m_isAllFruCollected = false; 470 471 // Mutex to guard critical resource m_activeCollectionThreadCount. 472 std::mutex m_mutex; 473 474 // Counting semaphore to limit the number of threads. 475 std::counting_semaphore<constants::MAX_THREADS> m_semaphore; 476 477 // List of EEPROM paths for which VPD collection thread creation has failed. 478 std::forward_list<std::string> m_failedEepromPaths; 479 480 // VPD collection mode 481 types::VpdCollectionMode m_vpdCollectionMode{ 482 types::VpdCollectionMode::DEFAULT_MODE}; 483 }; 484 } // namespace vpd 485