blob: 6caf2b8fdc3a4933a72379a244f3074915f3c328 [file] [log] [blame]
Matt Spinlerc8705e22019-09-11 12:36:07 -05001#pragma once
2
Matt Spinler2a28c932020-02-03 14:23:40 -06003#include "dbus_types.hpp"
4#include "dbus_watcher.hpp"
5
Matt Spinler4dcd3f42020-01-22 14:55:07 -06006#include <filesystem>
Matt Spinlera7d9d962019-11-06 15:01:25 -06007#include <phosphor-logging/log.hpp>
Matt Spinlerc8705e22019-09-11 12:36:07 -05008#include <sdbusplus/bus.hpp>
9#include <sdbusplus/bus/match.hpp>
10
11namespace openpower
12{
13namespace pels
14{
15
Matt Spinlerc8705e22019-09-11 12:36:07 -050016/**
17 * @class DataInterface
18 *
Matt Spinler19e89ce2019-11-06 13:02:23 -060019 * A base class for gathering data about the system for use
20 * in PELs. Implemented this way to facilitate mocking.
Matt Spinlerc8705e22019-09-11 12:36:07 -050021 */
22class DataInterfaceBase
23{
24 public:
25 DataInterfaceBase() = default;
26 virtual ~DataInterfaceBase() = default;
27 DataInterfaceBase(const DataInterfaceBase&) = default;
28 DataInterfaceBase& operator=(const DataInterfaceBase&) = default;
29 DataInterfaceBase(DataInterfaceBase&&) = default;
30 DataInterfaceBase& operator=(DataInterfaceBase&&) = default;
31
32 /**
Matt Spinler19e89ce2019-11-06 13:02:23 -060033 * @brief Returns the machine Type/Model
Matt Spinlerc8705e22019-09-11 12:36:07 -050034 *
35 * @return string - The machine Type/Model string
36 */
Matt Spinler19e89ce2019-11-06 13:02:23 -060037 virtual std::string getMachineTypeModel() const
38 {
39 return _machineTypeModel;
40 }
Matt Spinlerc8705e22019-09-11 12:36:07 -050041
42 /**
Matt Spinler19e89ce2019-11-06 13:02:23 -060043 * @brief Returns the machine serial number
Matt Spinlerc8705e22019-09-11 12:36:07 -050044 *
45 * @return string - The machine serial number
46 */
Matt Spinler19e89ce2019-11-06 13:02:23 -060047 virtual std::string getMachineSerialNumber() const
48 {
49 return _machineSerialNumber;
50 }
51
Matt Spinlera7d9d962019-11-06 15:01:25 -060052 /**
Matt Spinlercce14112019-12-11 14:20:36 -060053 * @brief Says if the system is managed by a hardware
54 * management console.
55 * @return bool - If the system is HMC managed
56 */
57 virtual bool isHMCManaged() const
58 {
59 return _hmcManaged;
60 }
61
62 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -060063 * @brief Says if the host is up and running
64 *
65 * @return bool - If the host is running
66 */
67 virtual bool isHostUp() const
68 {
69 return _hostUp;
70 }
71
Matt Spinlerb3f51862019-12-09 13:55:10 -060072 /**
73 * @brief Returns the PLDM instance ID to use for PLDM commands
74 *
75 * The base class implementation just returns zero.
76 *
77 * @param[in] eid - The PLDM EID
78 *
79 * @return uint8_t - The instance ID
80 */
81 virtual uint8_t getPLDMInstanceID(uint8_t eid) const
82 {
83 return 0;
84 }
85
Matt Spinlera7d9d962019-11-06 15:01:25 -060086 using HostStateChangeFunc = std::function<void(bool)>;
87
88 /**
89 * @brief Register a callback function that will get
90 * called on all host on/off transitions.
91 *
92 * The void(bool) function will get passed the new
93 * value of the host state.
94 *
95 * @param[in] name - The subscription name
96 * @param[in] func - The function to run
97 */
98 void subscribeToHostStateChange(const std::string& name,
99 HostStateChangeFunc func)
100 {
101 _hostChangeCallbacks[name] = func;
102 }
103
104 /**
105 * @brief Unsubscribe from host state changes.
106 *
107 * @param[in] name - The subscription name
108 */
109 void unsubscribeFromHostStateChange(const std::string& name)
110 {
111 _hostChangeCallbacks.erase(name);
112 }
113
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600114 /**
115 * @brief Returns the BMC firmware version
116 *
117 * @return std::string - The BMC version
118 */
119 virtual std::string getBMCFWVersion() const
120 {
121 return _bmcFWVersion;
122 }
123
124 /**
125 * @brief Returns the server firmware version
126 *
127 * @return std::string - The server firmware version
128 */
129 virtual std::string getServerFWVersion() const
130 {
131 return _serverFWVersion;
132 }
133
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600134 /**
Matt Spinler677381b2020-01-23 10:04:29 -0600135 * @brief Returns the BMC FW version ID
136 *
137 * @return std::string - The BMC FW version ID
138 */
139 virtual std::string getBMCFWVersionID() const
140 {
141 return _bmcFWVersionID;
142 }
143
144 /**
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600145 * @brief Returns the process name given its PID.
146 *
147 * @param[in] pid - The PID value as a string
148 *
149 * @return std::optional<std::string> - The name, or std::nullopt
150 */
151 std::optional<std::string> getProcessName(const std::string& pid) const
152 {
153 namespace fs = std::filesystem;
154
155 fs::path path{"/proc"};
156 path /= fs::path{pid} / "exe";
157
158 if (fs::exists(path))
159 {
160 return fs::read_symlink(path);
161 }
162
163 return std::nullopt;
164 }
165
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600166 /**
167 * @brief Returns the 'send event logs to host' setting.
168 *
169 * @return bool - If sending PELs to the host is enabled.
170 */
171 virtual bool getHostPELEnablement() const
172 {
173 return _sendPELsToHost;
174 }
175
Matt Spinler4aa23a12020-02-03 15:05:09 -0600176 /**
177 * @brief Returns the BMC state
178 *
179 * @return std::string - The BMC state property value
180 */
181 virtual std::string getBMCState() const
182 {
183 return _bmcState;
184 }
185
186 /**
187 * @brief Returns the Chassis state
188 *
189 * @return std::string - The chassis state property value
190 */
191 virtual std::string getChassisState() const
192 {
193 return _chassisState;
194 }
195
196 /**
197 * @brief Returns the chassis requested power
198 * transition value.
199 *
200 * @return std::string - The chassis transition property
201 */
202 virtual std::string getChassisTransition() const
203 {
204 return _chassisTransition;
205 }
206
207 /**
208 * @brief Returns the Host state
209 *
210 * @return std::string - The Host state property value
211 */
212 virtual std::string getHostState() const
213 {
214 return _hostState;
215 }
216
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600217 /**
218 * @brief Returns the motherboard CCIN
219 *
220 * @return std::string The motherboard CCIN
221 */
222 virtual std::string getMotherboardCCIN() const
223 {
224 return _motherboardCCIN;
225 }
226
Matt Spinler19e89ce2019-11-06 13:02:23 -0600227 protected:
228 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600229 * @brief Sets the host on/off state and runs any
230 * callback functions (if there was a change).
231 */
Matt Spinler4aa23a12020-02-03 15:05:09 -0600232 void setHostUp(bool hostUp)
Matt Spinlera7d9d962019-11-06 15:01:25 -0600233 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600234 if (_hostUp != hostUp)
Matt Spinlera7d9d962019-11-06 15:01:25 -0600235 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600236 _hostUp = hostUp;
Matt Spinlera7d9d962019-11-06 15:01:25 -0600237
238 for (auto& [name, func] : _hostChangeCallbacks)
239 {
240 try
241 {
242 func(_hostUp);
243 }
244 catch (std::exception& e)
245 {
246 using namespace phosphor::logging;
247 log<level::ERR>("A host state change callback threw "
248 "an exception");
249 }
250 }
251 }
252 }
253
254 /**
Matt Spinler19e89ce2019-11-06 13:02:23 -0600255 * @brief The machine type-model. Always kept up to date
256 */
257 std::string _machineTypeModel;
258
259 /**
260 * @brief The machine serial number. Always kept up to date
261 */
262 std::string _machineSerialNumber;
Matt Spinlera7d9d962019-11-06 15:01:25 -0600263
264 /**
Matt Spinlercce14112019-12-11 14:20:36 -0600265 * @brief The hardware management console status. Always kept
266 * up to date.
267 */
268 bool _hmcManaged = false;
269
270 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600271 * @brief The host up status. Always kept up to date.
272 */
273 bool _hostUp = false;
274
275 /**
276 * @brief The map of host state change subscriber
277 * names to callback functions.
278 */
279 std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks;
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600280
281 /**
282 * @brief The BMC firmware version string
283 */
284 std::string _bmcFWVersion;
285
286 /**
287 * @brief The server firmware version string
288 */
289 std::string _serverFWVersion;
Matt Spinler677381b2020-01-23 10:04:29 -0600290
291 /**
292 * @brief The BMC firmware version ID string
293 */
294 std::string _bmcFWVersionID;
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600295
296 /**
297 * @brief If sending PELs is enabled.
298 *
299 * This is usually set to false in manufacturing test.
300 */
301 bool _sendPELsToHost = true;
Matt Spinler4aa23a12020-02-03 15:05:09 -0600302
303 /**
304 * @brief The BMC state property
305 */
306 std::string _bmcState;
307
308 /**
309 * @brief The Chassis current power state property
310 */
311 std::string _chassisState;
312
313 /**
314 * @brief The Chassis requested power transition property
315 */
316 std::string _chassisTransition;
317
318 /**
319 * @brief The host state property
320 */
321 std::string _hostState;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600322
323 /**
324 * @brief The motherboard CCIN
325 */
326 std::string _motherboardCCIN;
Matt Spinlerc8705e22019-09-11 12:36:07 -0500327};
328
329/**
330 * @class DataInterface
331 *
332 * Concrete implementation of DataInterfaceBase.
333 */
334class DataInterface : public DataInterfaceBase
335{
336 public:
337 DataInterface() = delete;
338 ~DataInterface() = default;
339 DataInterface(const DataInterface&) = default;
340 DataInterface& operator=(const DataInterface&) = default;
341 DataInterface(DataInterface&&) = default;
342 DataInterface& operator=(DataInterface&&) = default;
343
344 /**
345 * @brief Constructor
346 *
347 * @param[in] bus - The sdbusplus bus object
348 */
349 explicit DataInterface(sdbusplus::bus::bus& bus);
350
Matt Spinlerb3f51862019-12-09 13:55:10 -0600351 /**
352 * @brief Returns the PLDM instance ID to use for PLDM commands
353 *
354 * @param[in] eid - The PLDM EID
355 *
356 * @return uint8_t - The instance ID
357 */
358 uint8_t getPLDMInstanceID(uint8_t eid) const override;
359
Matt Spinler677381b2020-01-23 10:04:29 -0600360 /**
Matt Spinlerc8705e22019-09-11 12:36:07 -0500361 * @brief Finds the D-Bus service name that hosts the
362 * passed in path and interface.
363 *
364 * @param[in] objectPath - The D-Bus object path
365 * @param[in] interface - The D-Bus interface
366 */
367 DBusService getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600368 const std::string& interface) const;
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600369
Matt Spinlerc8705e22019-09-11 12:36:07 -0500370 /**
371 * @brief Wrapper for the 'GetAll' properties method call
372 *
373 * @param[in] service - The D-Bus service to call it on
374 * @param[in] objectPath - The D-Bus object path
375 * @param[in] interface - The interface to get the props on
376 *
377 * @return DBusPropertyMap - The property results
378 */
379 DBusPropertyMap getAllProperties(const std::string& service,
380 const std::string& objectPath,
Matt Spinler2a28c932020-02-03 14:23:40 -0600381 const std::string& interface) const;
Matt Spinlerc8705e22019-09-11 12:36:07 -0500382 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600383 * @brief Wrapper for the 'Get' properties method call
384 *
385 * @param[in] service - The D-Bus service to call it on
386 * @param[in] objectPath - The D-Bus object path
387 * @param[in] interface - The interface to get the property on
388 * @param[in] property - The property name
389 * @param[out] value - Filled in with the property value.
390 */
391 void getProperty(const std::string& service, const std::string& objectPath,
392 const std::string& interface, const std::string& property,
Matt Spinler2a28c932020-02-03 14:23:40 -0600393 DBusValue& value) const;
394
395 private:
396 /**
397 * @brief Reads the BMC firmware version string and puts it into
398 * _bmcFWVersion.
399 */
400 void readBMCFWVersion();
Matt Spinlera7d9d962019-11-06 15:01:25 -0600401
402 /**
Matt Spinler2a28c932020-02-03 14:23:40 -0600403 * @brief Reads the server firmware version string and puts it into
404 * _serverFWVersion.
Matt Spinlerc8705e22019-09-11 12:36:07 -0500405 */
Matt Spinler2a28c932020-02-03 14:23:40 -0600406 void readServerFWVersion();
Matt Spinlerc8705e22019-09-11 12:36:07 -0500407
408 /**
Matt Spinler2a28c932020-02-03 14:23:40 -0600409 * @brief Reads the BMC firmware version ID and puts it into
410 * _bmcFWVersionID.
Matt Spinlera7d9d962019-11-06 15:01:25 -0600411 */
Matt Spinler2a28c932020-02-03 14:23:40 -0600412 void readBMCFWVersionID();
Matt Spinlera7d9d962019-11-06 15:01:25 -0600413
414 /**
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600415 * @brief Reads the motherboard CCIN and puts it into _motherboardCCIN.
416 *
417 * It finds the motherboard first, possibly having to wait for it to
418 * show up.
419 */
420 void readMotherboardCCIN();
421
422 /**
423 * @brief Finds all D-Bus paths that contain any of the interfaces
424 * passed in, by using GetSubTreePaths.
425 *
426 * @param[in] interfaces - The desired interfaces
427 *
428 * @return The D-Bus paths.
429 */
430 DBusPathList getPaths(const DBusInterfaceList& interfaces) const;
431
432 /**
433 * @brief The interfacesAdded callback used on the inventory to
434 * find the D-Bus object that has the motherboard interface.
435 * When the motherboard is found, it then adds a PropertyWatcher
436 * for the motherboard CCIN.
437 */
438 void motherboardIfaceAdded(sdbusplus::message::message& msg);
439
440 /**
441 * @brief Set the motherboard CCIN from the DBus variant that
442 * contains it.
443 *
444 * @param[in] ccin - The CCIN variant, a vector<uint8_t>.
445 */
446 void setMotherboardCCIN(const DBusValue& ccin)
447 {
448 const auto& c = std::get<std::vector<uint8_t>>(ccin);
449 _motherboardCCIN = std::string{c.begin(), c.end()};
450 }
451
452 /**
Matt Spinler2a28c932020-02-03 14:23:40 -0600453 * @brief The D-Bus property or interface watchers that have callbacks
454 * registered that will set members in this class when
455 * they change.
Matt Spinlerc8705e22019-09-11 12:36:07 -0500456 */
Matt Spinler2a28c932020-02-03 14:23:40 -0600457 std::vector<std::unique_ptr<DBusWatcher>> _properties;
Matt Spinlera7d9d962019-11-06 15:01:25 -0600458
459 /**
Matt Spinlerc8705e22019-09-11 12:36:07 -0500460 * @brief The sdbusplus bus object for making D-Bus calls.
461 */
462 sdbusplus::bus::bus& _bus;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600463
464 /**
465 * @brief The interfacesAdded match object used to wait for inventory
466 * interfaces to show up, so that the object with the motherboard
467 * interface can be found. After it is found, this object is
468 * deleted.
469 */
470 std::unique_ptr<sdbusplus::bus::match_t> _inventoryIfacesAddedMatch;
Matt Spinlerc8705e22019-09-11 12:36:07 -0500471};
472
473} // namespace pels
474} // namespace openpower