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