blob: 4e4f12f2be7b7afc9e045ef89b65cbaeb2b9e595 [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 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050063 * @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 */
109 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 */
119 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 */
132 size_t getActiveThreadCount() const
133 {
134 return m_activeCollectionThreadCount;
135 }
136
Souvik Roy1f4c8f82025-01-23 00:37:43 -0600137 /**
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 */
147 inline std::forward_list<std::string>& getFailedEepromPaths() noexcept
148 {
149 return m_failedEepromPaths;
150 }
151
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530152 /**
Souvik Roy31548842025-10-22 07:03:12 +0000153 * @brief API to get VPD collection mode
154 *
155 * @return VPD collection mode enum value
156 */
157 inline types::VpdCollectionMode getVpdCollectionMode() const
158 {
159 return m_vpdCollectionMode;
160 }
161
162 /**
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530163 * @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
Sunny Srivastava78a50422025-04-25 11:17:56 +0530180 /**
Anupama B R4c65fcd2025-09-01 08:09:00 -0500181 * @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
Sunny Srivastavac607fe52025-11-18 20:52:23 +0530192 /**
193 * @brief API to set symbolic link for system config JSON.
194 *
195 * Once correct device tree is set, symbolic link to the correct sytsem
196 * config JSON is set to be used in subsequent BMC boot.
197 *
198 * @param[in] i_systemJson - system config JSON.
199 */
200 void setJsonSymbolicLink(const std::string& i_systemJson);
201
202 /**
203 * @brief An API to parse and publish system VPD on D-Bus.
204 *
205 * Note: Throws exception in case of invalid VPD format.
206 * Moved temporarily to public space. Will be eventually moved to
207 * ibm-handler.
208 * @param[in] parsedVpdMap - Parsed VPD as a map.
209 */
210 void publishSystemVPD(const types::VPDMapVariant& parsedVpdMap);
211
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500212 private:
213 /**
214 * @brief An API to parse and publish a FRU VPD over D-Bus.
215 *
216 * Note: This API will handle all the exceptions internally and will only
217 * return status of parsing and publishing of VPD over D-Bus.
218 *
219 * @param[in] i_vpdFilePath - Path of file containing VPD.
220 * @return Tuple of status and file path. Status, true if successfull else
221 * false.
222 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500223 std::tuple<bool, std::string> parseAndPublishVPD(
224 const std::string& i_vpdFilePath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500225
226 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500227 * @brief An API to process extrainterfaces w.r.t a FRU.
228 *
229 * @param[in] singleFru - JSON block for a single FRU.
230 * @param[out] interfaces - Map to hold interface along with its properties.
231 * @param[in] parsedVpdMap - Parsed VPD as a map.
232 */
233 void processExtraInterfaces(const nlohmann::json& singleFru,
234 types::InterfaceMap& interfaces,
235 const types::VPDMapVariant& parsedVpdMap);
236
237 /**
238 * @brief An API to process embedded and synthesized FRUs.
239 *
240 * @param[in] singleFru - FRU to be processed.
241 * @param[out] interfaces - Map to hold interface along with its properties.
242 */
243 void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
244 types::InterfaceMap& interfaces);
245
246 /**
247 * @brief An API to read process FRU based in CCIN.
248 *
249 * For some FRUs VPD can be processed only if the FRU has some specific
250 * value for CCIN. In case the value is not from that set, VPD for those
251 * FRUs can't be processed.
252 *
253 * @param[in] singleFru - Fru whose CCIN value needs to be matched.
254 * @param[in] parsedVpdMap - Parsed VPD map.
255 */
256 bool processFruWithCCIN(const nlohmann::json& singleFru,
257 const types::VPDMapVariant& parsedVpdMap);
258
259 /**
260 * @brief API to process json's inherit flag.
261 *
262 * Inherit flag denotes that some property in the child FRU needs to be
263 * inherited from parent FRU.
264 *
265 * @param[in] parsedVpdMap - Parsed VPD as a map.
266 * @param[out] interfaces - Map to hold interface along with its properties.
267 */
268 void processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
269 types::InterfaceMap& interfaces);
270
271 /**
272 * @brief API to process json's "copyRecord" flag.
273 *
274 * copyRecord flag denotes if some record data needs to be copies in the
275 * given FRU.
276 *
277 * @param[in] singleFru - FRU being processed.
278 * @param[in] parsedVpdMap - Parsed VPD as a map.
279 * @param[out] interfaces - Map to hold interface along with its properties.
280 */
281 void processCopyRecordFlag(const nlohmann::json& singleFru,
282 const types::VPDMapVariant& parsedVpdMap,
283 types::InterfaceMap& interfaces);
284
285 /**
286 * @brief An API to populate IPZ VPD property map.
287 *
288 * @param[out] interfacePropMap - Map of interface and properties under it.
289 * @param[in] keyordValueMap - Keyword value map of IPZ VPD.
290 * @param[in] interfaceName - Name of the interface.
291 */
292 void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap,
293 const types::IPZKwdValueMap& keyordValueMap,
294 const std::string& interfaceName);
295
296 /**
297 * @brief An API to populate Kwd VPD property map.
298 *
299 * @param[in] keyordValueMap - Keyword value map of Kwd VPD.
300 * @param[out] interfaceMap - interface and property,value under it.
301 */
302 void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
303 types::InterfaceMap& interfaceMap);
304
305 /**
306 * @brief API to populate all required interface for a FRU.
307 *
308 * @param[in] interfaceJson - JSON containing interfaces to be populated.
309 * @param[out] interfaceMap - Map to hold populated interfaces.
310 * @param[in] parsedVpdMap - Parsed VPD as a map.
311 */
312 void populateInterfaces(const nlohmann::json& interfaceJson,
313 types::InterfaceMap& interfaceMap,
314 const types::VPDMapVariant& parsedVpdMap);
315
316 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500317 * @brief Check if the given CPU is an IO only chip.
318 *
319 * The CPU is termed as IO, whose all of the cores are bad and can never be
320 * used. Those CPU chips can be used for IO purpose like connecting PCIe
321 * devices etc., The CPU whose every cores are bad, can be identified from
322 * the CP00 record's PG keyword, only if all of the 8 EQs' value equals
323 * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.)
324 *
325 * @param [in] pgKeyword - PG Keyword of CPU.
326 * @return true if the given cpu is an IO, false otherwise.
327 */
328 bool isCPUIOGoodOnly(const std::string& pgKeyword);
329
330 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500331 * @brief API to process preAction(base_action) defined in config JSON.
332 *
333 * @note sequence of tags under any given flag of preAction is EXTREMELY
334 * important to ensure proper processing. The API will process all the
335 * nested items under the base action sequentially. Also if any of the tag
336 * processing fails, the code will not process remaining tags under the
337 * flag.
338 * ******** sample format **************
339 * fru EEPROM path: {
340 * base_action: {
341 * flag1: {
342 * tag1: {
343 * },
344 * tag2: {
345 * }
346 * }
347 * flag2: {
348 * tags: {
349 * }
350 * }
351 * }
352 * }
353 * *************************************
354 *
355 * @param[in] i_vpdFilePath - Path to the EEPROM file.
356 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
357 * processed under PreAction tag of config JSON.
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500358 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500359 * @return Execution status.
360 */
361 bool processPreAction(const std::string& i_vpdFilePath,
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500362 const std::string& i_flagToProcess,
363 uint16_t& o_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500364
365 /**
366 * @brief API to process postAction(base_action) defined in config JSON.
367 *
368 * @note Sequence of tags under any given flag of postAction is EXTREMELY
369 * important to ensure proper processing. The API will process all the
370 * nested items under the base action sequentially. Also if any of the tag
371 * processing fails, the code will not process remaining tags under the
372 * flag.
373 * ******** sample format **************
374 * fru EEPROM path: {
375 * base_action: {
376 * flag1: {
377 * tag1: {
378 * },
379 * tag2: {
380 * }
381 * }
382 * flag2: {
383 * tags: {
384 * }
385 * }
386 * }
387 * }
388 * *************************************
389 * Also, if post action is required to be processed only for FRUs with
390 * certain CCIN then CCIN list can be provided under flag.
391 *
392 * @param[in] i_vpdFruPath - Path to the EEPROM file.
393 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
394 * processed under postAction tag of config JSON.
395 * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is
396 * required.
397 * @return Execution status.
398 */
399 bool processPostAction(
400 const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
401 const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt);
402
403 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500404 * @brief API to update "Functional" property.
405 *
406 * The API sets the default value for "Functional" property once if the
407 * property is not yet populated over DBus. As the property value is not
408 * controlled by the VPD-Collection process, if it is found already
409 * populated, the functions skips re-populating the property so that already
410 * existing value can be retained.
411 *
412 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
413 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
414 */
415 void processFunctionalProperty(const std::string& i_inventoryObjPath,
416 types::InterfaceMap& io_interfaces);
417
418 /**
419 * @brief API to update "enabled" property.
420 *
421 * The API sets the default value for "enabled" property once if the
422 * property is not yet populated over DBus. As the property value is not
423 * controlled by the VPD-Collection process, if it is found already
424 * populated, the functions skips re-populating the property so that already
425 * existing value can be retained.
426 *
427 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
428 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
429 */
430 void processEnabledProperty(const std::string& i_inventoryObjPath,
431 types::InterfaceMap& io_interfaces);
432
433 /**
434 * @brief API to form asset tag string for the system.
435 *
436 * @param[in] i_parsedVpdMap - Parsed VPD map.
437 *
438 * @throw std::runtime_error
439 *
440 * @return - Formed asset tag string.
441 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500442 std::string createAssetTagString(
443 const types::VPDMapVariant& i_parsedVpdMap);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500444
445 /**
Sunny Srivastavad159bb42025-01-09 11:13:50 +0530446 * @brief API to set present property.
447 *
Souvik Roy6a9553c2025-02-07 01:16:32 -0600448 * This API updates the present property of the given FRU with the given
449 * value. Note: It is the responsibility of the caller to determine whether
450 * the present property for the FRU should be updated or not.
451 *
Sunny Srivastavad159bb42025-01-09 11:13:50 +0530452 * @param[in] i_vpdPath - EEPROM or inventory path.
453 * @param[in] i_value - value to be set.
454 */
455 void setPresentProperty(const std::string& i_fruPath, const bool& i_value);
456
Sunny Srivastava61611752025-02-04 00:29:33 -0600457 /**
458 * @brief API to check if the path needs to be skipped for collection.
459 *
460 * Some FRUs, under some given scenarios should not be collected and
461 * skipped.
462 *
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600463 * @param[in] i_vpdFilePath - EEPROM path.
464 *
Sunny Srivastava61611752025-02-04 00:29:33 -0600465 * @return True - if path is empty or should be skipped, false otherwise.
466 */
467 bool skipPathForCollection(const std::string& i_vpdFilePath);
468
Souvik Roy6a9553c2025-02-07 01:16:32 -0600469 /**
470 * @brief API to check if present property should be handled for given FRU.
471 *
472 * vpd-manager should update present property for a FRU if and only if it's
473 * not synthesized and vpd-manager handles present property for the FRU.
474 * This API assumes "handlePresence" tag is a subset of "synthesized" tag.
475 *
476 * @param[in] i_fru - JSON block for a single FRU.
477 *
478 * @return true if present property should be handled, false otherwise.
479 */
480 inline bool isPresentPropertyHandlingRequired(
481 const nlohmann::json& i_fru) const noexcept
482 {
483 // TODO: revisit this to see if this logic can be optimized.
484 return !i_fru.value("synthesized", false) &&
485 i_fru.value("handlePresence", true);
486 }
487
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500488 // Parsed JSON file.
489 nlohmann::json m_parsedJson{};
490
491 // Hold if symlink is present or not.
492 bool m_isSymlinkPresent = false;
493
494 // Path to config JSON if applicable.
495 std::string& m_configJsonPath;
496
497 // Keeps track of active thread(s) doing VPD collection.
498 size_t m_activeCollectionThreadCount = 0;
499
500 // Holds status, if VPD collection has been done or not.
501 // Note: This variable does not give information about successfull or failed
502 // collection. It just states, if the VPD collection process is over or not.
503 bool m_isAllFruCollected = false;
504
505 // To distinguish the factory reset path.
506 bool m_isFactoryResetDone = false;
507
508 // Mutex to guard critical resource m_activeCollectionThreadCount.
509 std::mutex m_mutex;
510
511 // Counting semaphore to limit the number of threads.
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600512 std::counting_semaphore<constants::MAX_THREADS> m_semaphore;
Souvik Roy1f4c8f82025-01-23 00:37:43 -0600513
514 // List of EEPROM paths for which VPD collection thread creation has failed.
515 std::forward_list<std::string> m_failedEepromPaths;
Souvik Roy31548842025-10-22 07:03:12 +0000516
517 // VPD collection mode
518 types::VpdCollectionMode m_vpdCollectionMode{
519 types::VpdCollectionMode::DEFAULT_MODE};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500520};
521} // namespace vpd