blob: 549dada2e96c659dcbfc52f7c241dec7d3b9ebf3 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#pragma once
2
3#include "constants.hpp"
Alpana Kumari1ca45202025-11-11 04:07:07 -06004#include "logger.hpp"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05005#include "types.hpp"
6
7#include <nlohmann/json.hpp>
8
9#include <mutex>
10#include <optional>
11#include <semaphore>
12#include <tuple>
13
14namespace vpd
15{
16/**
17 * @brief A class to process and publish VPD data.
18 *
19 * The class works on VPD and is mainly responsible for following tasks:
20 * 1) Select appropriate device tree and JSON. Reboot if required.
21 * 2) Get desired parser using parser factory.
22 * 3) Calling respective parser class to get parsed VPD.
23 * 4) Arranging VPD data under required interfaces.
24 * 5) Calling PIM to publish VPD.
25 *
26 * The class may also implement helper functions required for VPD handling.
27 */
28class Worker
29{
30 public:
31 /**
32 * List of deleted functions.
33 */
Souvik Roy63a822a2025-12-03 15:14:03 +000034 Worker(const Worker&) = delete;
35 Worker& operator=(const Worker&) = delete;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050036 Worker(Worker&&) = delete;
Souvik Roy63a822a2025-12-03 15:14:03 +000037 Worker& operator=(const Worker&&) = delete;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050038
39 /**
40 * @brief Constructor.
41 *
42 * In case the processing is not JSON based, no argument needs to be passed.
43 * Constructor will also, based on symlink pick the correct JSON and
44 * initialize the parsed JSON variable.
45 *
46 * @param[in] pathToConfigJSON - Path to the config JSON, if applicable.
Sunny Srivastava765cf7b2025-02-04 05:24:11 -060047 * @param[in] i_maxThreadCount - Maximum thread while collecting FRUs VPD.
Souvik Roy31548842025-10-22 07:03:12 +000048 * @param[in] i_vpdCollectionMode - Mode in which VPD collection should take
49 * place.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050050 *
51 * Note: Throws std::exception in case of construction failure. Caller needs
52 * to handle to detect successful object creation.
53 */
Sunny Srivastava765cf7b2025-02-04 05:24:11 -060054 Worker(std::string pathToConfigJson = std::string(),
Souvik Roy31548842025-10-22 07:03:12 +000055 uint8_t i_maxThreadCount = constants::MAX_THREADS,
56 types::VpdCollectionMode i_vpdCollectionMode =
57 types::VpdCollectionMode::DEFAULT_MODE);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050058
59 /**
60 * @brief Destructor
61 */
62 ~Worker() = default;
63
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050064 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050065 * @brief API to process all FRUs presnt in config JSON file.
66 *
67 * This API based on config JSON passed/selected for the system, will
68 * trigger parser for all the FRUs and publish it on DBus.
69 *
70 * Note: Config JSON file path should be passed to worker class constructor
71 * to make use of this API.
72 *
73 */
74 void collectFrusFromJson();
75
76 /**
77 * @brief API to parse VPD data
78 *
79 * @param[in] i_vpdFilePath - Path to the VPD file.
80 */
81 types::VPDMapVariant parseVpdFile(const std::string& i_vpdFilePath);
82
83 /**
84 * @brief An API to populate DBus interfaces for a FRU.
85 *
86 * Note: Call this API to populate D-Bus. Also caller should handle empty
87 * objectInterfaceMap.
88 *
89 * @param[in] parsedVpdMap - Parsed VPD as a map.
90 * @param[out] objectInterfaceMap - Object and its interfaces map.
91 * @param[in] vpdFilePath - EEPROM path of FRU.
92 */
93 void populateDbus(const types::VPDMapVariant& parsedVpdMap,
94 types::ObjectMap& objectInterfaceMap,
95 const std::string& vpdFilePath);
96
97 /**
98 * @brief An API to delete FRU VPD over DBus.
99 *
100 * @param[in] i_dbusObjPath - Dbus object path of the FRU.
101 *
102 * @throw std::runtime_error if given input path is empty.
103 */
104 void deleteFruVpd(const std::string& i_dbusObjPath);
105
106 /**
107 * @brief API to get status of VPD collection process.
108 *
109 * @return - True when done, false otherwise.
110 */
111 inline bool isAllFruCollectionDone() const
112 {
113 return m_isAllFruCollected;
114 }
115
116 /**
117 * @brief API to get system config JSON object
118 *
119 * @return System config JSON object.
120 */
121 inline nlohmann::json getSysCfgJsonObj() const
122 {
123 return m_parsedJson;
124 }
125
126 /**
127 * @brief API to get active thread count.
128 *
129 * Each FRU is collected in a separate thread. This API gives the active
130 * thread collecting FRU's VPD at any given time.
131 *
132 * @return Count of active threads.
133 */
134 size_t getActiveThreadCount() const
135 {
136 return m_activeCollectionThreadCount;
137 }
138
Souvik Roy1f4c8f82025-01-23 00:37:43 -0600139 /**
140 * @brief API to get list of EEPROMs for which thread creation failed.
141 *
142 * This API returns reference to list of EEPROM paths for which VPD
143 * collection thread creation has failed. Manager needs to process this list
144 * of EEPROMs and take appropriate action.
145 *
146 * @return reference to list of EEPROM paths for which VPD collection thread
147 * creation has failed
148 */
149 inline std::forward_list<std::string>& getFailedEepromPaths() noexcept
150 {
151 return m_failedEepromPaths;
152 }
153
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530154 /**
Souvik Roy31548842025-10-22 07:03:12 +0000155 * @brief API to get VPD collection mode
156 *
157 * @return VPD collection mode enum value
158 */
159 inline types::VpdCollectionMode getVpdCollectionMode() const
160 {
161 return m_vpdCollectionMode;
162 }
163
164 /**
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530165 * @brief Collect single FRU VPD
166 * API can be used to perform VPD collection for the given FRU, only if the
167 * current state of the system matches with the state at which the FRU is
168 * allowed for VPD recollection.
169 *
170 * @param[in] i_dbusObjPath - D-bus object path
171 */
172 void collectSingleFruVpd(
173 const sdbusplus::message::object_path& i_dbusObjPath);
174
175 /**
176 * @brief Perform VPD recollection
177 * This api will trigger parser to perform VPD recollection for FRUs that
178 * can be replaced at standby.
179 */
180 void performVpdRecollection();
181
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500182 private:
183 /**
184 * @brief An API to parse and publish a FRU VPD over D-Bus.
185 *
186 * Note: This API will handle all the exceptions internally and will only
187 * return status of parsing and publishing of VPD over D-Bus.
188 *
189 * @param[in] i_vpdFilePath - Path of file containing VPD.
190 * @return Tuple of status and file path. Status, true if successfull else
191 * false.
192 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500193 std::tuple<bool, std::string> parseAndPublishVPD(
194 const std::string& i_vpdFilePath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500195
196 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500197 * @brief An API to process extrainterfaces w.r.t a FRU.
198 *
199 * @param[in] singleFru - JSON block for a single FRU.
200 * @param[out] interfaces - Map to hold interface along with its properties.
201 * @param[in] parsedVpdMap - Parsed VPD as a map.
202 */
203 void processExtraInterfaces(const nlohmann::json& singleFru,
204 types::InterfaceMap& interfaces,
205 const types::VPDMapVariant& parsedVpdMap);
206
207 /**
208 * @brief An API to process embedded and synthesized FRUs.
209 *
210 * @param[in] singleFru - FRU to be processed.
211 * @param[out] interfaces - Map to hold interface along with its properties.
212 */
213 void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
214 types::InterfaceMap& interfaces);
215
216 /**
217 * @brief An API to read process FRU based in CCIN.
218 *
219 * For some FRUs VPD can be processed only if the FRU has some specific
220 * value for CCIN. In case the value is not from that set, VPD for those
221 * FRUs can't be processed.
222 *
223 * @param[in] singleFru - Fru whose CCIN value needs to be matched.
224 * @param[in] parsedVpdMap - Parsed VPD map.
225 */
226 bool processFruWithCCIN(const nlohmann::json& singleFru,
227 const types::VPDMapVariant& parsedVpdMap);
228
229 /**
230 * @brief API to process json's inherit flag.
231 *
232 * Inherit flag denotes that some property in the child FRU needs to be
233 * inherited from parent FRU.
234 *
235 * @param[in] parsedVpdMap - Parsed VPD as a map.
236 * @param[out] interfaces - Map to hold interface along with its properties.
237 */
238 void processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
239 types::InterfaceMap& interfaces);
240
241 /**
242 * @brief API to process json's "copyRecord" flag.
243 *
244 * copyRecord flag denotes if some record data needs to be copies in the
245 * given FRU.
246 *
247 * @param[in] singleFru - FRU being processed.
248 * @param[in] parsedVpdMap - Parsed VPD as a map.
249 * @param[out] interfaces - Map to hold interface along with its properties.
250 */
251 void processCopyRecordFlag(const nlohmann::json& singleFru,
252 const types::VPDMapVariant& parsedVpdMap,
253 types::InterfaceMap& interfaces);
254
255 /**
256 * @brief An API to populate IPZ VPD property map.
257 *
258 * @param[out] interfacePropMap - Map of interface and properties under it.
259 * @param[in] keyordValueMap - Keyword value map of IPZ VPD.
260 * @param[in] interfaceName - Name of the interface.
261 */
262 void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap,
263 const types::IPZKwdValueMap& keyordValueMap,
264 const std::string& interfaceName);
265
266 /**
267 * @brief An API to populate Kwd VPD property map.
268 *
269 * @param[in] keyordValueMap - Keyword value map of Kwd VPD.
270 * @param[out] interfaceMap - interface and property,value under it.
271 */
272 void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
273 types::InterfaceMap& interfaceMap);
274
275 /**
276 * @brief API to populate all required interface for a FRU.
277 *
278 * @param[in] interfaceJson - JSON containing interfaces to be populated.
279 * @param[out] interfaceMap - Map to hold populated interfaces.
280 * @param[in] parsedVpdMap - Parsed VPD as a map.
281 */
282 void populateInterfaces(const nlohmann::json& interfaceJson,
283 types::InterfaceMap& interfaceMap,
284 const types::VPDMapVariant& parsedVpdMap);
285
286 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500287 * @brief Check if the given CPU is an IO only chip.
288 *
289 * The CPU is termed as IO, whose all of the cores are bad and can never be
290 * used. Those CPU chips can be used for IO purpose like connecting PCIe
291 * devices etc., The CPU whose every cores are bad, can be identified from
292 * the CP00 record's PG keyword, only if all of the 8 EQs' value equals
293 * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.)
294 *
295 * @param [in] pgKeyword - PG Keyword of CPU.
296 * @return true if the given cpu is an IO, false otherwise.
297 */
298 bool isCPUIOGoodOnly(const std::string& pgKeyword);
299
300 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500301 * @brief API to process preAction(base_action) defined in config JSON.
302 *
303 * @note sequence of tags under any given flag of preAction is EXTREMELY
304 * important to ensure proper processing. The API will process all the
305 * nested items under the base action sequentially. Also if any of the tag
306 * processing fails, the code will not process remaining tags under the
307 * flag.
308 * ******** sample format **************
309 * fru EEPROM path: {
310 * base_action: {
311 * flag1: {
312 * tag1: {
313 * },
314 * tag2: {
315 * }
316 * }
317 * flag2: {
318 * tags: {
319 * }
320 * }
321 * }
322 * }
323 * *************************************
324 *
325 * @param[in] i_vpdFilePath - Path to the EEPROM file.
326 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
327 * processed under PreAction tag of config JSON.
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500328 * @param[out] o_errCode - To set error code in case of error.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500329 * @return Execution status.
330 */
331 bool processPreAction(const std::string& i_vpdFilePath,
Sunny Srivastava4f053df2025-09-03 02:27:37 -0500332 const std::string& i_flagToProcess,
333 uint16_t& o_errCode);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500334
335 /**
336 * @brief API to process postAction(base_action) defined in config JSON.
337 *
338 * @note Sequence of tags under any given flag of postAction is EXTREMELY
339 * important to ensure proper processing. The API will process all the
340 * nested items under the base action sequentially. Also if any of the tag
341 * processing fails, the code will not process remaining tags under the
342 * flag.
343 * ******** sample format **************
344 * fru EEPROM path: {
345 * base_action: {
346 * flag1: {
347 * tag1: {
348 * },
349 * tag2: {
350 * }
351 * }
352 * flag2: {
353 * tags: {
354 * }
355 * }
356 * }
357 * }
358 * *************************************
359 * Also, if post action is required to be processed only for FRUs with
360 * certain CCIN then CCIN list can be provided under flag.
361 *
362 * @param[in] i_vpdFruPath - Path to the EEPROM file.
363 * @param[in] i_flagToProcess - To identify which flag(s) needs to be
364 * processed under postAction tag of config JSON.
365 * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is
366 * required.
367 * @return Execution status.
368 */
369 bool processPostAction(
370 const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
371 const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt);
372
373 /**
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500374 * @brief API to update "Functional" property.
375 *
376 * The API sets the default value for "Functional" property once if the
377 * property is not yet populated over DBus. As the property value is not
378 * controlled by the VPD-Collection process, if it is found already
379 * populated, the functions skips re-populating the property so that already
380 * existing value can be retained.
381 *
382 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
383 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
384 */
385 void processFunctionalProperty(const std::string& i_inventoryObjPath,
386 types::InterfaceMap& io_interfaces);
387
388 /**
389 * @brief API to update "enabled" property.
390 *
391 * The API sets the default value for "enabled" property once if the
392 * property is not yet populated over DBus. As the property value is not
393 * controlled by the VPD-Collection process, if it is found already
394 * populated, the functions skips re-populating the property so that already
395 * existing value can be retained.
396 *
397 * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
398 * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
399 */
400 void processEnabledProperty(const std::string& i_inventoryObjPath,
401 types::InterfaceMap& io_interfaces);
402
403 /**
Sunny Srivastavad159bb42025-01-09 11:13:50 +0530404 * @brief API to set present property.
405 *
Souvik Roy6a9553c2025-02-07 01:16:32 -0600406 * This API updates the present property of the given FRU with the given
407 * value. Note: It is the responsibility of the caller to determine whether
408 * the present property for the FRU should be updated or not.
409 *
Sunny Srivastavad159bb42025-01-09 11:13:50 +0530410 * @param[in] i_vpdPath - EEPROM or inventory path.
411 * @param[in] i_value - value to be set.
412 */
413 void setPresentProperty(const std::string& i_fruPath, const bool& i_value);
414
Sunny Srivastava61611752025-02-04 00:29:33 -0600415 /**
416 * @brief API to check if the path needs to be skipped for collection.
417 *
418 * Some FRUs, under some given scenarios should not be collected and
419 * skipped.
420 *
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600421 * @param[in] i_vpdFilePath - EEPROM path.
422 *
Sunny Srivastava61611752025-02-04 00:29:33 -0600423 * @return True - if path is empty or should be skipped, false otherwise.
424 */
425 bool skipPathForCollection(const std::string& i_vpdFilePath);
426
Souvik Roy6a9553c2025-02-07 01:16:32 -0600427 /**
428 * @brief API to check if present property should be handled for given FRU.
429 *
430 * vpd-manager should update present property for a FRU if and only if it's
431 * not synthesized and vpd-manager handles present property for the FRU.
432 * This API assumes "handlePresence" tag is a subset of "synthesized" tag.
433 *
434 * @param[in] i_fru - JSON block for a single FRU.
435 *
436 * @return true if present property should be handled, false otherwise.
437 */
438 inline bool isPresentPropertyHandlingRequired(
439 const nlohmann::json& i_fru) const noexcept
440 {
441 // TODO: revisit this to see if this logic can be optimized.
442 return !i_fru.value("synthesized", false) &&
443 i_fru.value("handlePresence", true);
444 }
445
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500446 // Parsed JSON file.
447 nlohmann::json m_parsedJson{};
448
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500449 // Path to config JSON if applicable.
450 std::string& m_configJsonPath;
451
452 // Keeps track of active thread(s) doing VPD collection.
453 size_t m_activeCollectionThreadCount = 0;
454
455 // Holds status, if VPD collection has been done or not.
456 // Note: This variable does not give information about successfull or failed
457 // collection. It just states, if the VPD collection process is over or not.
458 bool m_isAllFruCollected = false;
459
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500460 // Mutex to guard critical resource m_activeCollectionThreadCount.
461 std::mutex m_mutex;
462
463 // Counting semaphore to limit the number of threads.
Sunny Srivastava765cf7b2025-02-04 05:24:11 -0600464 std::counting_semaphore<constants::MAX_THREADS> m_semaphore;
Souvik Roy1f4c8f82025-01-23 00:37:43 -0600465
466 // List of EEPROM paths for which VPD collection thread creation has failed.
467 std::forward_list<std::string> m_failedEepromPaths;
Souvik Roy31548842025-10-22 07:03:12 +0000468
469 // VPD collection mode
470 types::VpdCollectionMode m_vpdCollectionMode{
471 types::VpdCollectionMode::DEFAULT_MODE};
Alpana Kumari1ca45202025-11-11 04:07:07 -0600472
Sunny Srivastava0cdf9dd2025-12-02 21:49:45 -0600473 // Shared pointer to Logger object
Alpana Kumari1ca45202025-11-11 04:07:07 -0600474 std::shared_ptr<Logger> m_logger;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500475};
476} // namespace vpd