xref: /openbmc/openpower-vpd-parser/vpd-manager/include/worker.hpp (revision d159bb4975c92f11e1100a534adaa70f31a3566b)
1 #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 
13 namespace 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  */
27 class 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 
502     /**
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 
510     // Parsed JSON file.
511     nlohmann::json m_parsedJson{};
512 
513     // Hold if symlink is present or not.
514     bool m_isSymlinkPresent = false;
515 
516     // Path to config JSON if applicable.
517     std::string& m_configJsonPath;
518 
519     // Keeps track of active thread(s) doing VPD collection.
520     size_t m_activeCollectionThreadCount = 0;
521 
522     // Holds status, if VPD collection has been done or not.
523     // Note: This variable does not give information about successfull or failed
524     // collection. It just states, if the VPD collection process is over or not.
525     bool m_isAllFruCollected = false;
526 
527     // To distinguish the factory reset path.
528     bool m_isFactoryResetDone = false;
529 
530     // Mutex to guard critical resource m_activeCollectionThreadCount.
531     std::mutex m_mutex;
532 
533     // Counting semaphore to limit the number of threads.
534     std::counting_semaphore<constants::MAX_THREADS> m_semaphore{
535         constants::MAX_THREADS};
536 };
537 } // namespace vpd
538