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