blob: ac1b3d8ff81e3be67bda586a68824d4f5d1cfcd1 [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
151 private:
152 /**
153 * @brief An API to parse and publish a FRU VPD over D-Bus.
154 *
155 * Note: This API will handle all the exceptions internally and will only
156 * return status of parsing and publishing of VPD over D-Bus.
157 *
158 * @param[in] i_vpdFilePath - Path of file containing VPD.
159 * @return Tuple of status and file path. Status, true if successfull else
160 * false.
161 */
162 std::tuple<bool, std::string>
163 parseAndPublishVPD(const std::string& i_vpdFilePath);
164
165 /**
166 * @brief An API to set appropriate device tree and JSON.
167 *
168 * This API based on system chooses corresponding device tree and JSON.
169 * If device tree change is required, it updates the "fitconfig" and reboots
170 * the system. Else it is NOOP.
171 *
172 * @throw std::runtime_error
173 */
174 void setDeviceTreeAndJson();
175
176 /**
177 * @brief API to select system specific JSON.
178 *
179 * The API based on the IM value of VPD, will select appropriate JSON for
180 * the system. In case no system is found corresponding to the extracted IM
181 * value, error will be logged.
182 *
183 * @param[out] systemJson - System JSON name.
184 * @param[in] parsedVpdMap - Parsed VPD map.
185 */
186 void getSystemJson(std::string& systemJson,
187 const types::VPDMapVariant& parsedVpdMap);
188
189 /**
190 * @brief An API to read IM value from VPD.
191 *
192 * Note: Throws exception in case of error. Caller need to handle.
193 *
194 * @param[in] parsedVpd - Parsed VPD.
195 */
196 std::string getIMValue(const types::IPZVpdMap& parsedVpd) const;
197
198 /**
199 * @brief An API to read HW version from VPD.
200 *
201 * Note: Throws exception in case of error. Caller need to handle.
202 *
203 * @param[in] parsedVpd - Parsed VPD.
204 */
205 std::string getHWVersion(const types::IPZVpdMap& parsedVpd) const;
206
207 /**
208 * @brief An API to parse given VPD file path.
209 *
210 * @param[in] vpdFilePath - EEPROM file path.
211 * @param[out] parsedVpd - Parsed VPD as a map.
212 */
213 void fillVPDMap(const std::string& vpdFilePath,
214 types::VPDMapVariant& parsedVpd);
215
216 /**
217 * @brief An API to parse and publish system VPD on D-Bus.
218 *
219 * Note: Throws exception in case of invalid VPD format.
220 *
221 * @param[in] parsedVpdMap - Parsed VPD as a map.
222 */
223 void publishSystemVPD(const types::VPDMapVariant& parsedVpdMap);
224
225 /**
226 * @brief An API to process extrainterfaces w.r.t a FRU.
227 *
228 * @param[in] singleFru - JSON block for a single FRU.
229 * @param[out] interfaces - Map to hold interface along with its properties.
230 * @param[in] parsedVpdMap - Parsed VPD as a map.
231 */
232 void processExtraInterfaces(const nlohmann::json& singleFru,
233 types::InterfaceMap& interfaces,
234 const types::VPDMapVariant& parsedVpdMap);
235
236 /**
237 * @brief An API to process embedded and synthesized FRUs.
238 *
239 * @param[in] singleFru - FRU to be processed.
240 * @param[out] interfaces - Map to hold interface along with its properties.
241 */
242 void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
243 types::InterfaceMap& interfaces);
244
245 /**
246 * @brief An API to read process FRU based in CCIN.
247 *
248 * For some FRUs VPD can be processed only if the FRU has some specific
249 * value for CCIN. In case the value is not from that set, VPD for those
250 * FRUs can't be processed.
251 *
252 * @param[in] singleFru - Fru whose CCIN value needs to be matched.
253 * @param[in] parsedVpdMap - Parsed VPD map.
254 */
255 bool processFruWithCCIN(const nlohmann::json& singleFru,
256 const types::VPDMapVariant& parsedVpdMap);
257
258 /**
259 * @brief API to process json's inherit flag.
260 *
261 * Inherit flag denotes that some property in the child FRU needs to be
262 * inherited from parent FRU.
263 *
264 * @param[in] parsedVpdMap - Parsed VPD as a map.
265 * @param[out] interfaces - Map to hold interface along with its properties.
266 */
267 void processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
268 types::InterfaceMap& interfaces);
269
270 /**
271 * @brief API to process json's "copyRecord" flag.
272 *
273 * copyRecord flag denotes if some record data needs to be copies in the
274 * given FRU.
275 *
276 * @param[in] singleFru - FRU being processed.
277 * @param[in] parsedVpdMap - Parsed VPD as a map.
278 * @param[out] interfaces - Map to hold interface along with its properties.
279 */
280 void processCopyRecordFlag(const nlohmann::json& singleFru,
281 const types::VPDMapVariant& parsedVpdMap,
282 types::InterfaceMap& interfaces);
283
284 /**
285 * @brief An API to populate IPZ VPD property map.
286 *
287 * @param[out] interfacePropMap - Map of interface and properties under it.
288 * @param[in] keyordValueMap - Keyword value map of IPZ VPD.
289 * @param[in] interfaceName - Name of the interface.
290 */
291 void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap,
292 const types::IPZKwdValueMap& keyordValueMap,
293 const std::string& interfaceName);
294
295 /**
296 * @brief An API to populate Kwd VPD property map.
297 *
298 * @param[in] keyordValueMap - Keyword value map of Kwd VPD.
299 * @param[out] interfaceMap - interface and property,value under it.
300 */
301 void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
302 types::InterfaceMap& interfaceMap);
303
304 /**
305 * @brief API to populate all required interface for a FRU.
306 *
307 * @param[in] interfaceJson - JSON containing interfaces to be populated.
308 * @param[out] interfaceMap - Map to hold populated interfaces.
309 * @param[in] parsedVpdMap - Parsed VPD as a map.
310 */
311 void populateInterfaces(const nlohmann::json& interfaceJson,
312 types::InterfaceMap& interfaceMap,
313 const types::VPDMapVariant& parsedVpdMap);
314
315 /**
316 * @brief Helper function to insert or merge in map.
317 *
318 * This method checks in the given inventory::InterfaceMap if the given
319 * interface key is existing or not. If the interface key already exists,
320 * given property map is inserted into it. If the key does'nt exist then
321 * given interface and property map pair is newly created. If the property
322 * present in propertymap already exist in the InterfaceMap, then the new
323 * property value is ignored.
324 *
325 * @param[in,out] interfaceMap - map object of type inventory::InterfaceMap
326 * only.
327 * @param[in] interface - Interface name.
328 * @param[in] property - new property map that needs to be emplaced.
329 */
330 void insertOrMerge(types::InterfaceMap& interfaceMap,
331 const std::string& interface,
332 types::PropertyMap&& property);
333
334 /**
335 * @brief Check if the given CPU is an IO only chip.
336 *
337 * The CPU is termed as IO, whose all of the cores are bad and can never be
338 * used. Those CPU chips can be used for IO purpose like connecting PCIe
339 * devices etc., The CPU whose every cores are bad, can be identified from
340 * the CP00 record's PG keyword, only if all of the 8 EQs' value equals
341 * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.)
342 *
343 * @param [in] pgKeyword - PG Keyword of CPU.
344 * @return true if the given cpu is an IO, false otherwise.
345 */
346 bool isCPUIOGoodOnly(const std::string& pgKeyword);
347
348 /**
349 * @brief API to prime inventory Objects.
350 *
351 * @param[in] i_vpdFilePath - EEPROM file path.
352 * @return true if the prime inventory is success, false otherwise.
353 */
354 bool primeInventory(const std::string& i_vpdFilePath);
355
356 /**
357 * @brief API to process preAction(base_action) defined in config JSON.
358 *
359 * @note sequence of tags under any given flag of preAction is EXTREMELY
360 * important to ensure proper processing. The API will process all the
361 * nested items under the base action sequentially. Also if any of the tag
362 * processing fails, the code will not process remaining tags under the
363 * flag.
364 * ******** sample format **************
365 * fru EEPROM path: {
366 * base_action: {
367 * flag1: {
368 * tag1: {
369 * },
370 * tag2: {
371 * }
372 * }
373 * flag2: {
374 * tags: {
375 * }
376 * }
377 * }
378 * }
379 * *************************************
380 *
381 * @param[in] i_vpdFilePath - Path to the EEPROM file.
382 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
383 * processed under PreAction tag of config JSON.
384 * @return Execution status.
385 */
386 bool processPreAction(const std::string& i_vpdFilePath,
387 const std::string& i_flagToProcess);
388
389 /**
390 * @brief API to process postAction(base_action) defined in config JSON.
391 *
392 * @note Sequence of tags under any given flag of postAction is EXTREMELY
393 * important to ensure proper processing. The API will process all the
394 * nested items under the base action sequentially. Also if any of the tag
395 * processing fails, the code will not process remaining tags under the
396 * flag.
397 * ******** sample format **************
398 * fru EEPROM path: {
399 * base_action: {
400 * flag1: {
401 * tag1: {
402 * },
403 * tag2: {
404 * }
405 * }
406 * flag2: {
407 * tags: {
408 * }
409 * }
410 * }
411 * }
412 * *************************************
413 * Also, if post action is required to be processed only for FRUs with
414 * certain CCIN then CCIN list can be provided under flag.
415 *
416 * @param[in] i_vpdFruPath - Path to the EEPROM file.
417 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
418 * processed under postAction tag of config JSON.
419 * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is
420 * required.
421 * @return Execution status.
422 */
423 bool processPostAction(
424 const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
425 const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt);
426
427 /**
428 * @brief Function to enable and bring MUX out of idle state.
429 *
430 * This finds all the MUX defined in the system json and enables them by
431 * setting the holdidle parameter to 0.
432 *
433 * @throw std::runtime_error
434 */
435 void enableMuxChips();
436
437 /**
438 * @brief An API to perform backup or restore of VPD.
439 *
440 * @param[in,out] io_srcVpdMap - Source VPD map.
441 */
442 void performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap);
443
444 /**
445 * @brief API to update "Functional" property.
446 *
447 * The API sets the default value for "Functional" property once if the
448 * property is not yet populated over DBus. As the property value is not
449 * controlled by the VPD-Collection process, if it is found already
450 * populated, the functions skips re-populating the property so that already
451 * existing value can be retained.
452 *
453 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
454 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
455 */
456 void processFunctionalProperty(const std::string& i_inventoryObjPath,
457 types::InterfaceMap& io_interfaces);
458
459 /**
460 * @brief API to update "enabled" property.
461 *
462 * The API sets the default value for "enabled" 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 processEnabledProperty(const std::string& i_inventoryObjPath,
472 types::InterfaceMap& io_interfaces);
473
474 /**
475 * @brief API to form asset tag string for the system.
476 *
477 * @param[in] i_parsedVpdMap - Parsed VPD map.
478 *
479 * @throw std::runtime_error
480 *
481 * @return - Formed asset tag string.
482 */
483 std::string
484 createAssetTagString(const types::VPDMapVariant& i_parsedVpdMap);
485
486 /**
487 * @brief API to prime system blueprint.
488 *
489 * The API will traverse the system config JSON and will prime all the FRU
490 * paths which qualifies for priming.
491 */
492 void primeSystemBlueprint();
493
494 /**
495 * @brief API to set symbolic link for system config JSON.
496 *
497 * Once correct device tree is set, symbolic link to the correct sytsem
498 * config JSON is set to be used in subsequent BMC boot.
499 *
500 * @param[in] i_systemJson - system config JSON.
501 */
502 void setJsonSymbolicLink(const std::string& i_systemJson);
503
Sunny Srivastavad159bb42025-01-09 11:13:50 +0530504 /**
505 * @brief API to set present property.
506 *
507 * @param[in] i_vpdPath - EEPROM or inventory path.
508 * @param[in] i_value - value to be set.
509 */
510 void setPresentProperty(const std::string& i_fruPath, const bool& i_value);
511
Sunny Srivastava61611752025-02-04 00:29:33 -0600512 /**
513 * @brief API to check if the path needs to be skipped for collection.
514 *
515 * Some FRUs, under some given scenarios should not be collected and
516 * skipped.
517 *
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600518 * @param[in] i_vpdFilePath - EEPROM path.
519 *
Sunny Srivastava61611752025-02-04 00:29:33 -0600520 * @return True - if path is empty or should be skipped, false otherwise.
521 */
522 bool skipPathForCollection(const std::string& i_vpdFilePath);
523
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500524 // Parsed JSON file.
525 nlohmann::json m_parsedJson{};
526
527 // Hold if symlink is present or not.
528 bool m_isSymlinkPresent = false;
529
530 // Path to config JSON if applicable.
531 std::string& m_configJsonPath;
532
533 // Keeps track of active thread(s) doing VPD collection.
534 size_t m_activeCollectionThreadCount = 0;
535
536 // Holds status, if VPD collection has been done or not.
537 // Note: This variable does not give information about successfull or failed
538 // collection. It just states, if the VPD collection process is over or not.
539 bool m_isAllFruCollected = false;
540
541 // To distinguish the factory reset path.
542 bool m_isFactoryResetDone = false;
543
544 // Mutex to guard critical resource m_activeCollectionThreadCount.
545 std::mutex m_mutex;
546
547 // Counting semaphore to limit the number of threads.
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600548 std::counting_semaphore<constants::MAX_THREADS> m_semaphore;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500549};
550} // namespace vpd