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