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