blob: 305045e90b7d53e2082b525567b8dbd9508fc461 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#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
13namespace 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 */
27class 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.
Sunny Srivastava765cf7b2025-02-04 05:24:11 -060045 * @param[in] i_maxThreadCount - Maximum thread while collecting FRUs VPD.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050046 *
47 * Note: Throws std::exception in case of construction failure. Caller needs
48 * to handle to detect successful object creation.
49 */
Sunny Srivastava765cf7b2025-02-04 05:24:11 -060050 Worker(std::string pathToConfigJson = std::string(),
51 uint8_t i_maxThreadCount = constants::MAX_THREADS);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050052
53 /**
54 * @brief Destructor
55 */
56 ~Worker() = default;
57
58#ifdef IBM_SYSTEM
59 /**
60 * @brief API to perform initial setup before manager claims Bus name.
61 *
62 * Before BUS name for VPD-Manager is claimed, fitconfig whould be set for
63 * corret device tree, inventory JSON w.r.t system should be linked and
64 * system VPD should be on DBus.
65 */
66 void performInitialSetup();
67#endif
68
69 /**
70 * @brief An API to check if system VPD is already published.
71 *
72 * @return Status, true if system is already collected else false.
73 */
74 bool isSystemVPDOnDBus() const;
75
76 /**
77 * @brief API to process all FRUs presnt in config JSON file.
78 *
79 * This API based on config JSON passed/selected for the system, will
80 * trigger parser for all the FRUs and publish it on DBus.
81 *
82 * Note: Config JSON file path should be passed to worker class constructor
83 * to make use of this API.
84 *
85 */
86 void collectFrusFromJson();
87
88 /**
89 * @brief API to parse VPD data
90 *
91 * @param[in] i_vpdFilePath - Path to the VPD file.
92 */
93 types::VPDMapVariant parseVpdFile(const std::string& i_vpdFilePath);
94
95 /**
96 * @brief An API to populate DBus interfaces for a FRU.
97 *
98 * Note: Call this API to populate D-Bus. Also caller should handle empty
99 * objectInterfaceMap.
100 *
101 * @param[in] parsedVpdMap - Parsed VPD as a map.
102 * @param[out] objectInterfaceMap - Object and its interfaces map.
103 * @param[in] vpdFilePath - EEPROM path of FRU.
104 */
105 void populateDbus(const types::VPDMapVariant& parsedVpdMap,
106 types::ObjectMap& objectInterfaceMap,
107 const std::string& vpdFilePath);
108
109 /**
110 * @brief An API to delete FRU VPD over DBus.
111 *
112 * @param[in] i_dbusObjPath - Dbus object path of the FRU.
113 *
114 * @throw std::runtime_error if given input path is empty.
115 */
116 void deleteFruVpd(const std::string& i_dbusObjPath);
117
118 /**
119 * @brief API to get status of VPD collection process.
120 *
121 * @return - True when done, false otherwise.
122 */
123 inline bool isAllFruCollectionDone() const
124 {
125 return m_isAllFruCollected;
126 }
127
128 /**
129 * @brief API to get system config JSON object
130 *
131 * @return System config JSON object.
132 */
133 inline nlohmann::json getSysCfgJsonObj() const
134 {
135 return m_parsedJson;
136 }
137
138 /**
139 * @brief API to get active thread count.
140 *
141 * Each FRU is collected in a separate thread. This API gives the active
142 * thread collecting FRU's VPD at any given time.
143 *
144 * @return Count of active threads.
145 */
146 size_t getActiveThreadCount() const
147 {
148 return m_activeCollectionThreadCount;
149 }
150
Souvik Roy1f4c8f82025-01-23 00:37:43 -0600151 /**
152 * @brief API to get list of EEPROMs for which thread creation failed.
153 *
154 * This API returns reference to list of EEPROM paths for which VPD
155 * collection thread creation has failed. Manager needs to process this list
156 * of EEPROMs and take appropriate action.
157 *
158 * @return reference to list of EEPROM paths for which VPD collection thread
159 * creation has failed
160 */
161 inline std::forward_list<std::string>& getFailedEepromPaths() noexcept
162 {
163 return m_failedEepromPaths;
164 }
165
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530166 /**
167 * @brief Collect single FRU VPD
168 * API can be used to perform VPD collection for the given FRU, only if the
169 * current state of the system matches with the state at which the FRU is
170 * allowed for VPD recollection.
171 *
172 * @param[in] i_dbusObjPath - D-bus object path
173 */
174 void collectSingleFruVpd(
175 const sdbusplus::message::object_path& i_dbusObjPath);
176
177 /**
178 * @brief Perform VPD recollection
179 * This api will trigger parser to perform VPD recollection for FRUs that
180 * can be replaced at standby.
181 */
182 void performVpdRecollection();
183
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500184 private:
185 /**
186 * @brief An API to parse and publish a FRU VPD over D-Bus.
187 *
188 * Note: This API will handle all the exceptions internally and will only
189 * return status of parsing and publishing of VPD over D-Bus.
190 *
191 * @param[in] i_vpdFilePath - Path of file containing VPD.
192 * @return Tuple of status and file path. Status, true if successfull else
193 * false.
194 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500195 std::tuple<bool, std::string> parseAndPublishVPD(
196 const std::string& i_vpdFilePath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500197
198 /**
199 * @brief An API to set appropriate device tree and JSON.
200 *
201 * This API based on system chooses corresponding device tree and JSON.
202 * If device tree change is required, it updates the "fitconfig" and reboots
203 * the system. Else it is NOOP.
204 *
Sunny Srivastava043955d2025-01-21 18:04:49 +0530205 * @throw std::exception
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500206 */
207 void setDeviceTreeAndJson();
208
209 /**
210 * @brief API to select system specific JSON.
211 *
212 * The API based on the IM value of VPD, will select appropriate JSON for
213 * the system. In case no system is found corresponding to the extracted IM
214 * value, error will be logged.
215 *
216 * @param[out] systemJson - System JSON name.
217 * @param[in] parsedVpdMap - Parsed VPD map.
218 */
219 void getSystemJson(std::string& systemJson,
220 const types::VPDMapVariant& parsedVpdMap);
221
222 /**
223 * @brief An API to read IM value from VPD.
224 *
225 * Note: Throws exception in case of error. Caller need to handle.
226 *
227 * @param[in] parsedVpd - Parsed VPD.
228 */
229 std::string getIMValue(const types::IPZVpdMap& parsedVpd) const;
230
231 /**
232 * @brief An API to read HW version from VPD.
233 *
234 * Note: Throws exception in case of error. Caller need to handle.
235 *
236 * @param[in] parsedVpd - Parsed VPD.
237 */
238 std::string getHWVersion(const types::IPZVpdMap& parsedVpd) const;
239
240 /**
241 * @brief An API to parse given VPD file path.
242 *
Sunny Srivastava043955d2025-01-21 18:04:49 +0530243 * @throw std::exception
244 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500245 * @param[in] vpdFilePath - EEPROM file path.
246 * @param[out] parsedVpd - Parsed VPD as a map.
247 */
248 void fillVPDMap(const std::string& vpdFilePath,
249 types::VPDMapVariant& parsedVpd);
250
251 /**
252 * @brief An API to parse and publish system VPD on D-Bus.
253 *
254 * Note: Throws exception in case of invalid VPD format.
255 *
256 * @param[in] parsedVpdMap - Parsed VPD as a map.
257 */
258 void publishSystemVPD(const types::VPDMapVariant& parsedVpdMap);
259
260 /**
261 * @brief An API to process extrainterfaces w.r.t a FRU.
262 *
263 * @param[in] singleFru - JSON block for a single FRU.
264 * @param[out] interfaces - Map to hold interface along with its properties.
265 * @param[in] parsedVpdMap - Parsed VPD as a map.
266 */
267 void processExtraInterfaces(const nlohmann::json& singleFru,
268 types::InterfaceMap& interfaces,
269 const types::VPDMapVariant& parsedVpdMap);
270
271 /**
272 * @brief An API to process embedded and synthesized FRUs.
273 *
274 * @param[in] singleFru - FRU to be processed.
275 * @param[out] interfaces - Map to hold interface along with its properties.
276 */
277 void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
278 types::InterfaceMap& interfaces);
279
280 /**
281 * @brief An API to read process FRU based in CCIN.
282 *
283 * For some FRUs VPD can be processed only if the FRU has some specific
284 * value for CCIN. In case the value is not from that set, VPD for those
285 * FRUs can't be processed.
286 *
287 * @param[in] singleFru - Fru whose CCIN value needs to be matched.
288 * @param[in] parsedVpdMap - Parsed VPD map.
289 */
290 bool processFruWithCCIN(const nlohmann::json& singleFru,
291 const types::VPDMapVariant& parsedVpdMap);
292
293 /**
294 * @brief API to process json's inherit flag.
295 *
296 * Inherit flag denotes that some property in the child FRU needs to be
297 * inherited from parent FRU.
298 *
299 * @param[in] parsedVpdMap - Parsed VPD as a map.
300 * @param[out] interfaces - Map to hold interface along with its properties.
301 */
302 void processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
303 types::InterfaceMap& interfaces);
304
305 /**
306 * @brief API to process json's "copyRecord" flag.
307 *
308 * copyRecord flag denotes if some record data needs to be copies in the
309 * given FRU.
310 *
311 * @param[in] singleFru - FRU being processed.
312 * @param[in] parsedVpdMap - Parsed VPD as a map.
313 * @param[out] interfaces - Map to hold interface along with its properties.
314 */
315 void processCopyRecordFlag(const nlohmann::json& singleFru,
316 const types::VPDMapVariant& parsedVpdMap,
317 types::InterfaceMap& interfaces);
318
319 /**
320 * @brief An API to populate IPZ VPD property map.
321 *
322 * @param[out] interfacePropMap - Map of interface and properties under it.
323 * @param[in] keyordValueMap - Keyword value map of IPZ VPD.
324 * @param[in] interfaceName - Name of the interface.
325 */
326 void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap,
327 const types::IPZKwdValueMap& keyordValueMap,
328 const std::string& interfaceName);
329
330 /**
331 * @brief An API to populate Kwd VPD property map.
332 *
333 * @param[in] keyordValueMap - Keyword value map of Kwd VPD.
334 * @param[out] interfaceMap - interface and property,value under it.
335 */
336 void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
337 types::InterfaceMap& interfaceMap);
338
339 /**
340 * @brief API to populate all required interface for a FRU.
341 *
342 * @param[in] interfaceJson - JSON containing interfaces to be populated.
343 * @param[out] interfaceMap - Map to hold populated interfaces.
344 * @param[in] parsedVpdMap - Parsed VPD as a map.
345 */
346 void populateInterfaces(const nlohmann::json& interfaceJson,
347 types::InterfaceMap& interfaceMap,
348 const types::VPDMapVariant& parsedVpdMap);
349
350 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500351 * @brief Check if the given CPU is an IO only chip.
352 *
353 * The CPU is termed as IO, whose all of the cores are bad and can never be
354 * used. Those CPU chips can be used for IO purpose like connecting PCIe
355 * devices etc., The CPU whose every cores are bad, can be identified from
356 * the CP00 record's PG keyword, only if all of the 8 EQs' value equals
357 * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.)
358 *
359 * @param [in] pgKeyword - PG Keyword of CPU.
360 * @return true if the given cpu is an IO, false otherwise.
361 */
362 bool isCPUIOGoodOnly(const std::string& pgKeyword);
363
364 /**
365 * @brief API to prime inventory Objects.
366 *
367 * @param[in] i_vpdFilePath - EEPROM file path.
368 * @return true if the prime inventory is success, false otherwise.
369 */
370 bool primeInventory(const std::string& i_vpdFilePath);
371
372 /**
373 * @brief API to process preAction(base_action) defined in config JSON.
374 *
375 * @note sequence of tags under any given flag of preAction is EXTREMELY
376 * important to ensure proper processing. The API will process all the
377 * nested items under the base action sequentially. Also if any of the tag
378 * processing fails, the code will not process remaining tags under the
379 * flag.
380 * ******** sample format **************
381 * fru EEPROM path: {
382 * base_action: {
383 * flag1: {
384 * tag1: {
385 * },
386 * tag2: {
387 * }
388 * }
389 * flag2: {
390 * tags: {
391 * }
392 * }
393 * }
394 * }
395 * *************************************
396 *
397 * @param[in] i_vpdFilePath - Path to the EEPROM file.
398 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
399 * processed under PreAction tag of config JSON.
400 * @return Execution status.
401 */
402 bool processPreAction(const std::string& i_vpdFilePath,
403 const std::string& i_flagToProcess);
404
405 /**
406 * @brief API to process postAction(base_action) defined in config JSON.
407 *
408 * @note Sequence of tags under any given flag of postAction is EXTREMELY
409 * important to ensure proper processing. The API will process all the
410 * nested items under the base action sequentially. Also if any of the tag
411 * processing fails, the code will not process remaining tags under the
412 * flag.
413 * ******** sample format **************
414 * fru EEPROM path: {
415 * base_action: {
416 * flag1: {
417 * tag1: {
418 * },
419 * tag2: {
420 * }
421 * }
422 * flag2: {
423 * tags: {
424 * }
425 * }
426 * }
427 * }
428 * *************************************
429 * Also, if post action is required to be processed only for FRUs with
430 * certain CCIN then CCIN list can be provided under flag.
431 *
432 * @param[in] i_vpdFruPath - Path to the EEPROM file.
433 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
434 * processed under postAction tag of config JSON.
435 * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is
436 * required.
437 * @return Execution status.
438 */
439 bool processPostAction(
440 const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
441 const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt);
442
443 /**
444 * @brief Function to enable and bring MUX out of idle state.
445 *
446 * This finds all the MUX defined in the system json and enables them by
447 * setting the holdidle parameter to 0.
448 *
449 * @throw std::runtime_error
450 */
451 void enableMuxChips();
452
453 /**
454 * @brief An API to perform backup or restore of VPD.
455 *
456 * @param[in,out] io_srcVpdMap - Source VPD map.
457 */
458 void performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap);
459
460 /**
461 * @brief API to update "Functional" property.
462 *
463 * The API sets the default value for "Functional" property once if the
464 * property is not yet populated over DBus. As the property value is not
465 * controlled by the VPD-Collection process, if it is found already
466 * populated, the functions skips re-populating the property so that already
467 * existing value can be retained.
468 *
469 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
470 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
471 */
472 void processFunctionalProperty(const std::string& i_inventoryObjPath,
473 types::InterfaceMap& io_interfaces);
474
475 /**
476 * @brief API to update "enabled" property.
477 *
478 * The API sets the default value for "enabled" property once if the
479 * property is not yet populated over DBus. As the property value is not
480 * controlled by the VPD-Collection process, if it is found already
481 * populated, the functions skips re-populating the property so that already
482 * existing value can be retained.
483 *
484 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
485 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
486 */
487 void processEnabledProperty(const std::string& i_inventoryObjPath,
488 types::InterfaceMap& io_interfaces);
489
490 /**
491 * @brief API to form asset tag string for the system.
492 *
493 * @param[in] i_parsedVpdMap - Parsed VPD map.
494 *
495 * @throw std::runtime_error
496 *
497 * @return - Formed asset tag string.
498 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500499 std::string createAssetTagString(
500 const types::VPDMapVariant& i_parsedVpdMap);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500501
502 /**
503 * @brief API to prime system blueprint.
504 *
505 * The API will traverse the system config JSON and will prime all the FRU
506 * paths which qualifies for priming.
507 */
508 void primeSystemBlueprint();
509
510 /**
511 * @brief API to set symbolic link for system config JSON.
512 *
513 * Once correct device tree is set, symbolic link to the correct sytsem
514 * config JSON is set to be used in subsequent BMC boot.
515 *
516 * @param[in] i_systemJson - system config JSON.
517 */
518 void setJsonSymbolicLink(const std::string& i_systemJson);
519
Sunny Srivastavad159bb42025-01-09 11:13:50 +0530520 /**
521 * @brief API to set present property.
522 *
Souvik Roy6a9553c2025-02-07 01:16:32 -0600523 * This API updates the present property of the given FRU with the given
524 * value. Note: It is the responsibility of the caller to determine whether
525 * the present property for the FRU should be updated or not.
526 *
Sunny Srivastavad159bb42025-01-09 11:13:50 +0530527 * @param[in] i_vpdPath - EEPROM or inventory path.
528 * @param[in] i_value - value to be set.
529 */
530 void setPresentProperty(const std::string& i_fruPath, const bool& i_value);
531
Sunny Srivastava61611752025-02-04 00:29:33 -0600532 /**
533 * @brief API to check if the path needs to be skipped for collection.
534 *
535 * Some FRUs, under some given scenarios should not be collected and
536 * skipped.
537 *
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600538 * @param[in] i_vpdFilePath - EEPROM path.
539 *
Sunny Srivastava61611752025-02-04 00:29:33 -0600540 * @return True - if path is empty or should be skipped, false otherwise.
541 */
542 bool skipPathForCollection(const std::string& i_vpdFilePath);
543
Souvik Roy6a9553c2025-02-07 01:16:32 -0600544 /**
545 * @brief API to check if present property should be handled for given FRU.
546 *
547 * vpd-manager should update present property for a FRU if and only if it's
548 * not synthesized and vpd-manager handles present property for the FRU.
549 * This API assumes "handlePresence" tag is a subset of "synthesized" tag.
550 *
551 * @param[in] i_fru - JSON block for a single FRU.
552 *
553 * @return true if present property should be handled, false otherwise.
554 */
555 inline bool isPresentPropertyHandlingRequired(
556 const nlohmann::json& i_fru) const noexcept
557 {
558 // TODO: revisit this to see if this logic can be optimized.
559 return !i_fru.value("synthesized", false) &&
560 i_fru.value("handlePresence", true);
561 }
562
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500563 // Parsed JSON file.
564 nlohmann::json m_parsedJson{};
565
566 // Hold if symlink is present or not.
567 bool m_isSymlinkPresent = false;
568
569 // Path to config JSON if applicable.
570 std::string& m_configJsonPath;
571
572 // Keeps track of active thread(s) doing VPD collection.
573 size_t m_activeCollectionThreadCount = 0;
574
575 // Holds status, if VPD collection has been done or not.
576 // Note: This variable does not give information about successfull or failed
577 // collection. It just states, if the VPD collection process is over or not.
578 bool m_isAllFruCollected = false;
579
580 // To distinguish the factory reset path.
581 bool m_isFactoryResetDone = false;
582
583 // Mutex to guard critical resource m_activeCollectionThreadCount.
584 std::mutex m_mutex;
585
586 // Counting semaphore to limit the number of threads.
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600587 std::counting_semaphore<constants::MAX_THREADS> m_semaphore;
Souvik Roy1f4c8f82025-01-23 00:37:43 -0600588
589 // List of EEPROM paths for which VPD collection thread creation has failed.
590 std::forward_list<std::string> m_failedEepromPaths;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500591};
592} // namespace vpd