1 #pragma once
2 
3 #include "dbus_types.hpp"
4 #include "dbus_watcher.hpp"
5 
6 #include <phosphor-logging/lg2.hpp>
7 #include <sdbusplus/bus.hpp>
8 #include <sdbusplus/bus/match.hpp>
9 
10 #include <expected>
11 #include <filesystem>
12 #include <fstream>
13 #include <unordered_map>
14 
15 namespace openpower
16 {
17 namespace pels
18 {
19 
20 /**
21  * @class DataInterface
22  *
23  * A base class for gathering data about the system for use
24  * in PELs. Implemented this way to facilitate mocking.
25  */
26 class DataInterfaceBase
27 {
28   public:
29     DataInterfaceBase() = default;
30     virtual ~DataInterfaceBase() = default;
31     DataInterfaceBase(const DataInterfaceBase&) = default;
32     DataInterfaceBase& operator=(const DataInterfaceBase&) = default;
33     DataInterfaceBase(DataInterfaceBase&&) = default;
34     DataInterfaceBase& operator=(DataInterfaceBase&&) = default;
35 
36     /**
37      * @brief Returns the machine Type/Model
38      *
39      * @return string - The machine Type/Model string
40      */
41     virtual std::string getMachineTypeModel() const = 0;
42 
43     /**
44      * @brief Returns the machine serial number
45      *
46      * @return string - The machine serial number
47      */
48     virtual std::string getMachineSerialNumber() const = 0;
49 
50     /**
51      * @brief Says if the system is managed by a hardware
52      *        management console.
53      * @return bool - If the system is HMC managed
54      */
55     virtual bool isHMCManaged() const
56     {
57         return _hmcManaged;
58     }
59 
60     /**
61      * @brief Says if the host is up and running
62      *
63      * @return bool - If the host is running
64      */
65     virtual bool isHostUp() const
66     {
67         return _hostUp;
68     }
69 
70     using HostStateChangeFunc = std::function<void(bool)>;
71 
72     /**
73      * @brief Register a callback function that will get
74      *        called on all host on/off transitions.
75      *
76      * The void(bool) function will get passed the new
77      * value of the host state.
78      *
79      * @param[in] name - The subscription name
80      * @param[in] func - The function to run
81      */
82     void subscribeToHostStateChange(const std::string& name,
83                                     HostStateChangeFunc func)
84     {
85         _hostChangeCallbacks[name] = func;
86     }
87 
88     /**
89      * @brief Unsubscribe from host state changes.
90      *
91      * @param[in] name - The subscription name
92      */
93     void unsubscribeFromHostStateChange(const std::string& name)
94     {
95         _hostChangeCallbacks.erase(name);
96     }
97 
98     using FRUPresentFunc =
99         std::function<void(const std::string& /* locationCode */)>;
100 
101     /**
102      * @brief Register a callback function that will get
103      *        called when certain FRUs become present.
104      *
105      * The void(std::string) function will get passed the
106      * location code of the FRU.
107      *
108      * @param[in] name - The subscription name
109      * @param[in] func - The function to run
110      */
111     void subscribeToFruPresent(const std::string& name, FRUPresentFunc func)
112     {
113         _fruPresentCallbacks[name] = std::move(func);
114     }
115 
116     /**
117      * @brief Returns the BMC firmware version
118      *
119      * @return std::string - The BMC version
120      */
121     virtual std::string getBMCFWVersion() const
122     {
123         return _bmcFWVersion;
124     }
125 
126     /**
127      * @brief Returns the server firmware version
128      *
129      * @return std::string - The server firmware version
130      */
131     virtual std::string getServerFWVersion() const
132     {
133         return _serverFWVersion;
134     }
135 
136     /**
137      * @brief Returns the BMC FW version ID
138      *
139      * @return std::string - The BMC FW version ID
140      */
141     virtual std::string getBMCFWVersionID() const
142     {
143         return _bmcFWVersionID;
144     }
145 
146     /**
147      * @brief Returns the process name given its PID.
148      *
149      * @param[in] pid - The PID value as a string
150      *
151      * @return std::optional<std::string> - The name, or std::nullopt
152      */
153     std::optional<std::string> getProcessName(const std::string& pid) const
154     {
155         namespace fs = std::filesystem;
156 
157         fs::path path{"/proc"};
158         path /= fs::path{pid} / "exe";
159 
160         if (fs::exists(path))
161         {
162             return fs::read_symlink(path);
163         }
164 
165         return std::nullopt;
166     }
167 
168     /**
169      * @brief Returns the time the system was running.
170      *
171      * @return std::optional<uint64_t> - The System uptime or std::nullopt
172      */
173     std::optional<uint64_t> getUptimeInSeconds() const
174     {
175         std::ifstream versionFile{"/proc/uptime"};
176         std::string line{};
177 
178         std::getline(versionFile, line);
179         auto pos = line.find(" ");
180         if (pos == std::string::npos)
181         {
182             return std::nullopt;
183         }
184 
185         uint64_t seconds = atol(line.substr(0, pos).c_str());
186         if (seconds == 0)
187         {
188             return std::nullopt;
189         }
190 
191         return seconds;
192     }
193 
194     /**
195      * @brief Returns the time the system was running.
196      *
197      * @param[in] seconds - The number of seconds the system has been running
198      *
199      * @return std::string - days/hours/minutes/seconds
200      */
201     std::string getBMCUptime(uint64_t seconds) const
202     {
203         time_t t(seconds);
204         tm* p = gmtime(&t);
205 
206         std::string uptime =
207             std::to_string(p->tm_year - 70) + "y " +
208             std::to_string(p->tm_yday) + "d " + std::to_string(p->tm_hour) +
209             "h " + std::to_string(p->tm_min) + "m " +
210             std::to_string(p->tm_sec) + "s";
211 
212         return uptime;
213     }
214 
215     /**
216      * @brief Returns the system load average over the past 1 minute, 5 minutes
217      *        and 15 minutes.
218      *
219      * @return std::string - The system load average
220      */
221     std::string getBMCLoadAvg() const
222     {
223         std::string loadavg{};
224 
225         std::ifstream loadavgFile{"/proc/loadavg"};
226         std::string line;
227         std::getline(loadavgFile, line);
228 
229         size_t count = 3;
230         for (size_t i = 0; i < count; i++)
231         {
232             auto pos = line.find(" ");
233             if (pos == std::string::npos)
234             {
235                 return {};
236             }
237 
238             if (i != count - 1)
239             {
240                 loadavg.append(line.substr(0, pos + 1));
241             }
242             else
243             {
244                 loadavg.append(line.substr(0, pos));
245             }
246 
247             line = line.substr(pos + 1);
248         }
249 
250         return loadavg;
251     }
252 
253     /**
254      * @brief Returns the 'send event logs to host' setting.
255      *
256      * @return bool - If sending PELs to the host is enabled.
257      */
258     virtual bool getHostPELEnablement() const
259     {
260         return _sendPELsToHost;
261     }
262 
263     /**
264      * @brief Returns the BMC state
265      *
266      * @return std::string - The BMC state property value
267      */
268     virtual std::string getBMCState() const
269     {
270         return _bmcState;
271     }
272 
273     /**
274      * @brief Returns the Chassis state
275      *
276      * @return std::string - The chassis state property value
277      */
278     virtual std::string getChassisState() const
279     {
280         return _chassisState;
281     }
282 
283     /**
284      * @brief Returns the chassis requested power
285      *        transition value.
286      *
287      * @return std::string - The chassis transition property
288      */
289     virtual std::string getChassisTransition() const
290     {
291         return _chassisTransition;
292     }
293 
294     /**
295      * @brief Returns the Host state
296      *
297      * @return std::string - The Host state property value
298      */
299     virtual std::string getHostState() const
300     {
301         return _hostState;
302     }
303 
304     /**
305      * @brief Returns the Boot state
306      *
307      * @return std::string - The Boot state property value
308      */
309     virtual std::string getBootState() const
310     {
311         return _bootState;
312     }
313 
314     /**
315      * @brief Returns the motherboard CCIN
316      *
317      * @return std::string The motherboard CCIN
318      */
319     virtual std::string getMotherboardCCIN() const = 0;
320 
321     /**
322      * @brief Returns the system IM
323      *
324      * @return std::string The system IM
325      */
326     virtual std::vector<uint8_t> getSystemIMKeyword() const = 0;
327 
328     /**
329      * @brief Get the fields from the inventory necessary for doing
330      *        a callout on an inventory path.
331      *
332      * @param[in] inventoryPath - The item to get the data for
333      * @param[out] fruPartNumber - Filled in with the VINI/FN keyword
334      * @param[out] ccin - Filled in with the VINI/CC keyword
335      * @param[out] serialNumber - Filled in with the VINI/SN keyword
336      */
337     virtual void getHWCalloutFields(
338         const std::string& inventoryPath, std::string& fruPartNumber,
339         std::string& ccin, std::string& serialNumber) const = 0;
340 
341     /**
342      * @brief Get the location code for an inventory item.
343      *
344      * @param[in] inventoryPath - The item to get the data for
345      *
346      * @return std::string - The location code
347      */
348     virtual std::string
349         getLocationCode(const std::string& inventoryPath) const = 0;
350 
351     /**
352      * @brief Get the list of system type names the system is called.
353      *
354      * @return std::vector<std::string> - The list of names
355      */
356     virtual std::vector<std::string> getSystemNames() const = 0;
357 
358     /**
359      * @brief Fills in the placeholder 'Ufcs' in the passed in location
360      *        code with the machine feature code and serial number, which
361      *        is needed to create a valid location code.
362      *
363      * @param[in] locationCode - Location code value starting with Ufcs-, and
364      *                           if that isn't present it will be added first.
365      *
366      * @param[in] node - The node number the location is on.
367      *
368      * @return std::string - The expanded location code
369      */
370     virtual std::string expandLocationCode(const std::string& locationCode,
371                                            uint16_t node) const = 0;
372 
373     /**
374      * @brief Returns the inventory paths for the FRU that the location
375      *        code represents.
376      *
377      * @param[in] locationCode - If an expanded location code, then the
378      *                           full location code.
379      *                           If not expanded, a location code value
380      *                           starting with Ufcs-, and if that isn't
381      *                           present it will be added first.
382      *
383      * @param[in] node - The node number the location is on.  Ignored if the
384      *                   expanded location code is passed in.
385      *
386      * @param[in] expanded - If the location code already has the relevent
387      *                       VPD fields embedded in it.
388      *
389      * @return std::vector<std::string> - The inventory D-Bus objects
390      */
391     virtual std::vector<std::string>
392         getInventoryFromLocCode(const std::string& LocationCode, uint16_t node,
393                                 bool expanded) const = 0;
394 
395     /**
396      * @brief Sets the Asserted property on the LED group passed in.
397      *
398      * @param[in] ledGroup - The LED group D-Bus path
399      * @param[in] value - The value to set it to
400      */
401     virtual void assertLEDGroup(const std::string& ledGroup,
402                                 bool value) const = 0;
403 
404     /**
405      * @brief Sets the Functional property on the OperationalStatus
406      *        interface on a D-Bus object.
407      *
408      * @param[in] objectPath - The D-Bus object path
409      * @param[in] functional - The value
410      */
411     virtual void setFunctional(const std::string& objectPath,
412                                bool functional) const = 0;
413 
414     /**
415      * @brief Sets the critical association on the D-Bus object.
416      *
417      * @param[in] objectPath - The D-Bus object path
418      */
419     virtual void
420         setCriticalAssociation(const std::string& objectPath) const = 0;
421 
422     /**
423      * @brief Returns the manufacturing QuiesceOnError property
424      *
425      * @return bool - Manufacturing QuiesceOnError property
426      */
427     virtual bool getQuiesceOnError() const = 0;
428 
429     /**
430      * @brief Split location code into base and connector segments
431      *
432      * A location code that ends in '-Tx', where 'x' is a number,
433      * represents a connector, such as a USB cable connector.
434      *
435      * This function splits the passed in location code into a
436      * base and connector segment.  e.g.:
437      *   P0-T1 -> ['P0', '-T1']
438      *   P0 -> ['P0', '']
439      *
440      * @param[in] locationCode - location code to split
441      * @return pair<string, string> - The base and connector segments
442      */
443     static std::pair<std::string, std::string>
444         extractConnectorFromLocCode(const std::string& locationCode);
445 
446     /**
447      * @brief Create guard record
448      *
449      *  @param[in] binPath: phal devtree binary path used as key
450      *  @param[in] type: Guard type
451      *  @param[in] logPath: error log entry object path
452      */
453     virtual void createGuardRecord(const std::vector<uint8_t>& binPath,
454                                    const std::string& type,
455                                    const std::string& logPath) const = 0;
456 
457     /**
458      * @brief Create Progress SRC property on the boot progress
459      *        interface on a D-Bus object.
460      *
461      * @param[in] priSRC - Primary SRC value (e.g. BD8D1001)
462      * @param[in] srcStruct - Full SRC base structure
463      */
464     virtual void
465         createProgressSRC(const uint64_t& priSRC,
466                           const std::vector<uint8_t>& srcStruct) const = 0;
467 
468     /**
469      * @brief Get the list of unresolved OpenBMC event log ids that have an
470      * associated hardware isolation entry.
471      *
472      * @return std::vector<uint32_t> - The list of log ids
473      */
474     virtual std::vector<uint32_t> getLogIDWithHwIsolation() const = 0;
475 
476     /**
477      * @brief Returns the latest raw progress SRC from the State.Boot.Raw
478      *        D-Bus interface.
479      *
480      * @return std::vector<uint8_t> - The progress SRC bytes
481      */
482     virtual std::vector<uint8_t> getRawProgressSRC() const = 0;
483 
484     /**
485      * @brief Returns the FRUs DI property value hosted on the VINI iterface for
486      * the given location code.
487      *
488      * @param[in] locationCode - The location code of the FRU
489      *
490      * @return std::optional<std::vector<uint8_t>> -  The FRUs DI or
491      * std::nullopt
492      */
493     virtual std::optional<std::vector<uint8_t>>
494         getDIProperty(const std::string& locationCode) const = 0;
495 
496     /**
497      * @brief Wrpper API to call pHAL API 'getFRUType()' and check whether the
498      * given location code is DIMM or not
499      *
500      * @param[in] locCode - The location code of the FRU
501      *
502      * @return - true, if the given location code is DIMM
503      *         - false, if the given location code is not DIMM or if it fails to
504      *         determine the FRU type.
505      */
506     bool isDIMM(const std::string& locCode);
507 
508     /**
509      * @brief Check whether the given location code present in the cache
510      * memory
511      *
512      * @param[in] locCode - The location code of the FRU
513      *
514      * @return true, if the given location code present in cache and is a DIMM
515      *         false, if the given location code present in cache, but a non
516      *         DIMM FRU
517      *         std::nullopt, if the given location code is not present in the
518      *         cache.
519      */
520     std::optional<bool> isDIMMLocCode(const std::string& locCode) const;
521 
522     /**
523      * @brief add the given location code to the cache memory
524      *
525      * @param[in] locCode - The location code of the FRU
526      * @param[in] isFRUDIMM - true indicates the FRU is a DIMM
527      *                        false indicates the FRU is a non DIMM
528      *
529      */
530     void addDIMMLocCode(const std::string& locCode, bool isFRUDIMM);
531 
532     /**
533      * @brief Finds all D-Bus Associated paths that contain any of the
534      *        interfaces passed in, by using GetAssociatedSubTreePaths.
535      *
536      * @param[in] associatedPath - The D-Bus object path
537      * @param[in] subtree - The subtree path for which the result should be
538      *                      fetched
539      * @param[in] depth - The maximum subtree depth for which results should be
540      *                    fetched
541      * @param[in] interfaces - The desired interfaces
542      *
543      * @return The D-Bus paths.
544      */
545     virtual DBusPathList getAssociatedPaths(
546         const DBusPath& associatedPath, const DBusPath& subtree, int32_t depth,
547         const DBusInterfaceList& interfaces) const = 0;
548 
549   protected:
550     /**
551      * @brief Sets the host on/off state and runs any
552      *        callback functions (if there was a change).
553      */
554     void setHostUp(bool hostUp)
555     {
556         if (_hostUp != hostUp)
557         {
558             _hostUp = hostUp;
559 
560             for (auto& [name, func] : _hostChangeCallbacks)
561             {
562                 try
563                 {
564                     func(_hostUp);
565                 }
566                 catch (const std::exception& e)
567                 {
568                     lg2::error(
569                         "A host state change callback threw an exception");
570                 }
571             }
572         }
573     }
574 
575     /**
576      * @brief Runs the callback functions registered when
577      *        FRUs become present.
578      */
579     void setFruPresent(const std::string& locationCode)
580     {
581         for (const auto& [_, func] : _fruPresentCallbacks)
582         {
583             try
584             {
585                 func(locationCode);
586             }
587             catch (const std::exception& e)
588             {
589                 lg2::error("A FRU present callback threw an exception");
590             }
591         }
592     }
593 
594     /**
595      * @brief The hardware management console status.  Always kept
596      *        up to date.
597      */
598     bool _hmcManaged = false;
599 
600     /**
601      * @brief The host up status.  Always kept up to date.
602      */
603     bool _hostUp = false;
604 
605     /**
606      * @brief The map of host state change subscriber
607      *        names to callback functions.
608      */
609     std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks;
610 
611     /**
612      * @brief The map of FRU present subscriber
613      *        names to callback functions.
614      */
615     std::map<std::string, FRUPresentFunc> _fruPresentCallbacks;
616 
617     /**
618      * @brief The BMC firmware version string
619      */
620     std::string _bmcFWVersion;
621 
622     /**
623      * @brief The server firmware version string
624      */
625     std::string _serverFWVersion;
626 
627     /**
628      * @brief The BMC firmware version ID string
629      */
630     std::string _bmcFWVersionID;
631 
632     /**
633      * @brief If sending PELs is enabled.
634      *
635      * This is usually set to false in manufacturing test.
636      */
637     bool _sendPELsToHost = true;
638 
639     /**
640      * @brief The BMC state property
641      */
642     std::string _bmcState;
643 
644     /**
645      * @brief The Chassis current power state property
646      */
647     std::string _chassisState;
648 
649     /**
650      * @brief The Chassis requested power transition property
651      */
652     std::string _chassisTransition;
653 
654     /**
655      * @brief The host state property
656      */
657     std::string _hostState;
658 
659     /**
660      * @brief The boot state property
661      */
662     std::string _bootState;
663 
664     /**
665      * @brief A cache storage for location code and its FRU Type
666      *  - The key 'std::string' represents the locationCode of the FRU
667      *  - The bool value - true indicates the FRU is a DIMM
668      *                     false indicates the FRU is a non DIMM.
669      */
670     std::unordered_map<std::string, bool> _locationCache;
671 };
672 
673 /**
674  * @class DataInterface
675  *
676  * Concrete implementation of DataInterfaceBase.
677  */
678 class DataInterface : public DataInterfaceBase
679 {
680   public:
681     DataInterface() = delete;
682     ~DataInterface() = default;
683     DataInterface(const DataInterface&) = default;
684     DataInterface& operator=(const DataInterface&) = default;
685     DataInterface(DataInterface&&) = default;
686     DataInterface& operator=(DataInterface&&) = default;
687 
688     /**
689      * @brief Constructor
690      *
691      * @param[in] bus - The sdbusplus bus object
692      */
693     explicit DataInterface(sdbusplus::bus_t& bus);
694 
695     /**
696      * @brief Finds the D-Bus service name that hosts the
697      *        passed in path and interface.
698      *
699      * @param[in] objectPath - The D-Bus object path
700      * @param[in] interface - The D-Bus interface
701      */
702     DBusService getService(const std::string& objectPath,
703                            const std::string& interface) const;
704 
705     /**
706      * @brief Wrapper for the 'GetAll' properties method call
707      *
708      * @param[in] service - The D-Bus service to call it on
709      * @param[in] objectPath - The D-Bus object path
710      * @param[in] interface - The interface to get the props on
711      *
712      * @return DBusPropertyMap - The property results
713      */
714     DBusPropertyMap getAllProperties(const std::string& service,
715                                      const std::string& objectPath,
716                                      const std::string& interface) const;
717     /**
718      * @brief Wrapper for the 'Get' properties method call
719      *
720      * @param[in] service - The D-Bus service to call it on
721      * @param[in] objectPath - The D-Bus object path
722      * @param[in] interface - The interface to get the property on
723      * @param[in] property - The property name
724      * @param[out] value - Filled in with the property value.
725      */
726     void getProperty(const std::string& service, const std::string& objectPath,
727                      const std::string& interface, const std::string& property,
728                      DBusValue& value) const;
729     /**
730      * @brief Returns the machine Type/Model
731      *
732      * @return string - The machine Type/Model string
733      */
734     std::string getMachineTypeModel() const override;
735 
736     /**
737      * @brief Returns the machine serial number
738      *
739      * @return string - The machine serial number
740      */
741     std::string getMachineSerialNumber() const override;
742 
743     /**
744      * @brief Returns the motherboard CCIN
745      *
746      * @return std::string The motherboard CCIN
747      */
748     std::string getMotherboardCCIN() const override;
749 
750     /**
751      * @brief Returns the system IM
752      *
753      * @return std::vector The system IM keyword in 4 byte vector
754      */
755     std::vector<uint8_t> getSystemIMKeyword() const override;
756 
757     /**
758      * @brief Get the fields from the inventory necessary for doing
759      *        a callout on an inventory path.
760      *
761      * @param[in] inventoryPath - The item to get the data for
762      * @param[out] fruPartNumber - Filled in with the VINI/FN keyword
763      * @param[out] ccin - Filled in with the VINI/CC keyword
764      * @param[out] serialNumber - Filled in with the VINI/SN keyword
765      */
766     void getHWCalloutFields(const std::string& inventoryPath,
767                             std::string& fruPartNumber, std::string& ccin,
768                             std::string& serialNumber) const override;
769 
770     /**
771      * @brief Get the location code for an inventory item.
772      *
773      * Throws an exception if the inventory item doesn't have the
774      * location code interface.
775      *
776      * @param[in] inventoryPath - The item to get the data for
777      *
778      * @return std::string - The location code
779      */
780     std::string
781         getLocationCode(const std::string& inventoryPath) const override;
782 
783     /**
784      * @brief Get the list of system type names the system is called.
785      *
786      * @return std::vector<std::string> - The list of names
787      */
788     std::vector<std::string> getSystemNames() const override;
789 
790     /**
791      * @brief Fills in the placeholder 'Ufcs' in the passed in location
792      *        code with the machine feature code and serial number, which
793      *        is needed to create a valid location code.
794      *
795      * @param[in] locationCode - Location code value starting with Ufcs-, and
796      *                           if that isn't present it will be added first.
797      *
798      * @param[in] node - The node number the location is one.
799      *
800      * @return std::string - The expanded location code
801      */
802     std::string expandLocationCode(const std::string& locationCode,
803                                    uint16_t node) const override;
804 
805     /**
806      * @brief Returns the inventory paths for the FRU that the location
807      *        code represents.
808      *
809      * @param[in] locationCode - If an expanded location code, then the
810      *                           full location code.
811      *                           If not expanded, a location code value
812      *                           starting with Ufcs-, and if that isn't
813      *                           present it will be added first.
814      *
815      * @param[in] node - The node number the location is on.  Ignored if the
816      *                   expanded location code is passed in.
817      *
818      * @param[in] expanded - If the location code already has the relevent
819      *                       VPD fields embedded in it.
820      *
821      * @return std::vector<std::string> - The inventory D-Bus objects
822      */
823     std::vector<std::string>
824         getInventoryFromLocCode(const std::string& locationCode, uint16_t node,
825                                 bool expanded) const override;
826 
827     /**
828      * @brief Sets the Asserted property on the LED group passed in.
829      *
830      * @param[in] ledGroup - The LED group D-Bus path
831      * @param[in] value - The value to set it to
832      */
833     void assertLEDGroup(const std::string& ledGroup, bool value) const override;
834 
835     /**
836      * @brief Sets the Functional property on the OperationalStatus
837      *        interface on a D-Bus object.
838      *
839      * @param[in] objectPath - The D-Bus object path
840      * @param[in] functional - The value
841      */
842     void setFunctional(const std::string& objectPath,
843                        bool functional) const override;
844 
845     /**
846      * @brief Sets the critical association on the D-Bus object.
847      *
848      * @param[in] objectPath - The D-Bus object path
849      */
850     void setCriticalAssociation(const std::string& objectPath) const override;
851 
852     /**
853      * @brief Returns the manufacturing QuiesceOnError property
854      *
855      * @return bool - Manufacturing QuiesceOnError property
856      */
857     bool getQuiesceOnError() const override;
858 
859     /**
860      * @brief Create guard record
861      *
862      *  @param[in] binPath: phal devtree binary path used as key
863      *  @param[in] type: Guard type
864      *  @param[in] logPath: error log entry object path
865      */
866     void createGuardRecord(const std::vector<uint8_t>& binPath,
867                            const std::string& type,
868                            const std::string& logPath) const override;
869 
870     /**
871      * @brief Create Progress SRC property on the boot progress
872      *        interface on a D-Bus object.
873      *
874      * @param[in] priSRC - Primary SRC value
875      * @param[in] srcStruct - Full SRC base structure
876      */
877     void
878         createProgressSRC(const uint64_t& priSRC,
879                           const std::vector<uint8_t>& srcStruct) const override;
880 
881     /**
882      * @brief Get the list of unresolved OpenBMC event log ids that have an
883      * associated hardware isolation entry.
884      *
885      * @return std::vector<uint32_t> - The list of log ids
886      */
887     std::vector<uint32_t> getLogIDWithHwIsolation() const override;
888 
889     /**
890      * @brief Returns the latest raw progress SRC from the State.Boot.Raw
891      *        D-Bus interface.
892      *
893      * @return std::vector<uint8_t>: The progress SRC bytes
894      */
895     std::vector<uint8_t> getRawProgressSRC() const override;
896 
897     /**
898      * @brief Returns the FRUs DI property value hosted on the VINI iterface for
899      * the given location code.
900      *
901      * @param[in] locationCode - The location code of the FRU
902      *
903      * @return std::optional<std::vector<uint8_t>> -  The FRUs DI or
904      * std::nullopt
905      */
906     std::optional<std::vector<uint8_t>>
907         getDIProperty(const std::string& locationCode) const override;
908 
909     /**
910      * @brief Finds all D-Bus Associated paths that contain any of the
911      *        interfaces passed in, by using GetAssociatedSubTreePaths.
912      *
913      * @param[in] associatedPath - The D-Bus object path
914      * @param[in] subtree - The subtree path for which the result should be
915      *                      fetched
916      * @param[in] depth - The maximum subtree depth for which results should be
917      *                    fetched
918      * @param[in] interfaces - The desired interfaces
919      *
920      * @return The D-Bus paths.
921      */
922     DBusPathList getAssociatedPaths(
923         const DBusPath& associatedPath, const DBusPath& subtree, int32_t depth,
924         const DBusInterfaceList& interfaces) const override;
925 
926   private:
927     /**
928      * @brief Reads the BMC firmware version string and puts it into
929      *        _bmcFWVersion.
930      */
931     void readBMCFWVersion();
932 
933     /**
934      * @brief Reads the server firmware version string and puts it into
935      *        _serverFWVersion.
936      */
937     void readServerFWVersion();
938 
939     /**
940      * @brief Reads the BMC firmware version ID and puts it into
941      *        _bmcFWVersionID.
942      */
943     void readBMCFWVersionID();
944 
945     /**
946      * @brief Finds all D-Bus paths that contain any of the interfaces
947      *        passed in, by using GetSubTreePaths.
948      *
949      * @param[in] interfaces - The desired interfaces
950      *
951      * @return The D-Bus paths.
952      */
953     DBusPathList getPaths(const DBusInterfaceList& interfaces) const;
954 
955     /**
956      * @brief The interfacesAdded callback used on the inventory to
957      *        find the D-Bus object that has the motherboard interface.
958      *        When the motherboard is found, it then adds a PropertyWatcher
959      *        for the motherboard CCIN.
960      */
961     void motherboardIfaceAdded(sdbusplus::message_t& msg);
962 
963     /**
964      * @brief Start watching for the hotpluggable FRUs to become
965      *        present.
966      */
967     void startFruPlugWatch();
968 
969     /**
970      * @brief Create a D-Bus match object for the Present property
971      *        to change on the path passed in.
972      * @param[in] path - The path to watch.
973      */
974     void addHotplugWatch(const std::string& path);
975 
976     /**
977      * @brief Callback when an inventory interface was added.
978      *
979      * Only does something if it's one of the hotpluggable FRUs,
980      * in which case it will treat it as a hotplug if the
981      * Present property is true.
982      *
983      * @param[in] msg - The InterfacesAdded signal contents.
984      */
985     void inventoryIfaceAdded(sdbusplus::message_t& msg);
986 
987     /**
988      * @brief Callback when the Present property changes.
989      *
990      * If present, will run the registered callbacks.
991      *
992      * @param[in] msg - The PropertiesChanged signal contents.
993      */
994     void presenceChanged(sdbusplus::message_t& msg);
995 
996     /**
997      * @brief If the Present property is in the properties map
998      *        passed in and it is true, notify the subscribers.
999      *
1000      * @param[in] path - The object path of the inventory item.
1001      * @param[in] properties - The properties map
1002      */
1003     void notifyPresenceSubsribers(const std::string& path,
1004                                   const DBusPropertyMap& properties);
1005 
1006     /**
1007      * @brief Adds the Ufcs- prefix to the location code passed in
1008      *        if necessary.
1009      *
1010      * Needed because the location codes that come back from the
1011      * message registry and device callout JSON don't have it.
1012      *
1013      * @param[in] - The location code without a prefix, like P1-C1
1014      *
1015      * @return std::string - The location code with the prefix
1016      */
1017     static std::string addLocationCodePrefix(const std::string& locationCode);
1018 
1019     /**
1020      * @brief A helper API to check whether the PHAL device tree is exists,
1021      *        ensuring the PHAL init API can be invoked.
1022      *
1023      * @return true if the PHAL device tree is exists, otherwise false
1024      */
1025     bool isPHALDevTreeExist() const;
1026 
1027 #ifdef PEL_ENABLE_PHAL
1028     /**
1029      * @brief A helper API to init PHAL libraries
1030      *
1031      * @return None
1032      */
1033     void initPHAL();
1034 #endif // PEL_ENABLE_PHAL
1035 
1036     /**
1037      * @brief A helper API to subscribe to systemd signals
1038      *
1039      * @return None
1040      */
1041     void subscribeToSystemdSignals();
1042 
1043     /**
1044      * @brief A helper API to unsubscribe to systemd signals
1045      *
1046      * @return None
1047      */
1048     void unsubscribeFromSystemdSignals();
1049 
1050     /**
1051      * @brief The D-Bus property or interface watchers that have callbacks
1052      *        registered that will set members in this class when
1053      *        they change.
1054      */
1055     std::vector<std::unique_ptr<DBusWatcher>> _properties;
1056 
1057     std::unique_ptr<sdbusplus::bus::match_t> _invIaMatch;
1058 
1059     /**
1060      * @brief The matches for watching for hotplugs.
1061      *
1062      * A map so we can check that we never get duplicates.
1063      */
1064     std::map<std::string, std::unique_ptr<sdbusplus::bus::match_t>>
1065         _invPresentMatches;
1066 
1067     /**
1068      * @brief The sdbusplus bus object for making D-Bus calls.
1069      */
1070     sdbusplus::bus_t& _bus;
1071 
1072     /**
1073      * @brief Watcher to check "openpower-update-bios-attr-table" service
1074      *        is "done" to init PHAL libraires
1075      */
1076     std::unique_ptr<sdbusplus::bus::match_t> _systemdMatch;
1077 
1078     /**
1079      * @brief A slot object for async dbus call
1080      */
1081     sdbusplus::slot_t _systemdSlot;
1082 };
1083 
1084 } // namespace pels
1085 } // namespace openpower
1086