blob: e139c077698ce03eb3bcf48526a7a9430e394074 [file] [log] [blame]
Matt Spinlerc8705e22019-09-11 12:36:07 -05001#pragma once
2
Matt Spinler4dcd3f42020-01-22 14:55:07 -06003#include <filesystem>
Matt Spinlera7d9d962019-11-06 15:01:25 -06004#include <phosphor-logging/log.hpp>
Matt Spinlerc8705e22019-09-11 12:36:07 -05005#include <sdbusplus/bus.hpp>
6#include <sdbusplus/bus/match.hpp>
7
8namespace openpower
9{
10namespace pels
11{
12
13using DBusValue = sdbusplus::message::variant<std::string>;
14using DBusProperty = std::string;
15using DBusInterface = std::string;
16using DBusService = std::string;
17using DBusPath = std::string;
18using DBusInterfaceList = std::vector<DBusInterface>;
19using DBusPropertyMap = std::map<DBusProperty, DBusValue>;
20
21/**
22 * @class DataInterface
23 *
Matt Spinler19e89ce2019-11-06 13:02:23 -060024 * A base class for gathering data about the system for use
25 * in PELs. Implemented this way to facilitate mocking.
Matt Spinlerc8705e22019-09-11 12:36:07 -050026 */
27class DataInterfaceBase
28{
29 public:
30 DataInterfaceBase() = default;
31 virtual ~DataInterfaceBase() = default;
32 DataInterfaceBase(const DataInterfaceBase&) = default;
33 DataInterfaceBase& operator=(const DataInterfaceBase&) = default;
34 DataInterfaceBase(DataInterfaceBase&&) = default;
35 DataInterfaceBase& operator=(DataInterfaceBase&&) = default;
36
37 /**
Matt Spinler19e89ce2019-11-06 13:02:23 -060038 * @brief Returns the machine Type/Model
Matt Spinlerc8705e22019-09-11 12:36:07 -050039 *
40 * @return string - The machine Type/Model string
41 */
Matt Spinler19e89ce2019-11-06 13:02:23 -060042 virtual std::string getMachineTypeModel() const
43 {
44 return _machineTypeModel;
45 }
Matt Spinlerc8705e22019-09-11 12:36:07 -050046
47 /**
Matt Spinler19e89ce2019-11-06 13:02:23 -060048 * @brief Returns the machine serial number
Matt Spinlerc8705e22019-09-11 12:36:07 -050049 *
50 * @return string - The machine serial number
51 */
Matt Spinler19e89ce2019-11-06 13:02:23 -060052 virtual std::string getMachineSerialNumber() const
53 {
54 return _machineSerialNumber;
55 }
56
Matt Spinlera7d9d962019-11-06 15:01:25 -060057 /**
Matt Spinlercce14112019-12-11 14:20:36 -060058 * @brief Says if the system is managed by a hardware
59 * management console.
60 * @return bool - If the system is HMC managed
61 */
62 virtual bool isHMCManaged() const
63 {
64 return _hmcManaged;
65 }
66
67 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -060068 * @brief Says if the host is up and running
69 *
70 * @return bool - If the host is running
71 */
72 virtual bool isHostUp() const
73 {
74 return _hostUp;
75 }
76
Matt Spinlerb3f51862019-12-09 13:55:10 -060077 /**
78 * @brief Returns the PLDM instance ID to use for PLDM commands
79 *
80 * The base class implementation just returns zero.
81 *
82 * @param[in] eid - The PLDM EID
83 *
84 * @return uint8_t - The instance ID
85 */
86 virtual uint8_t getPLDMInstanceID(uint8_t eid) const
87 {
88 return 0;
89 }
90
Matt Spinlera7d9d962019-11-06 15:01:25 -060091 using HostStateChangeFunc = std::function<void(bool)>;
92
93 /**
94 * @brief Register a callback function that will get
95 * called on all host on/off transitions.
96 *
97 * The void(bool) function will get passed the new
98 * value of the host state.
99 *
100 * @param[in] name - The subscription name
101 * @param[in] func - The function to run
102 */
103 void subscribeToHostStateChange(const std::string& name,
104 HostStateChangeFunc func)
105 {
106 _hostChangeCallbacks[name] = func;
107 }
108
109 /**
110 * @brief Unsubscribe from host state changes.
111 *
112 * @param[in] name - The subscription name
113 */
114 void unsubscribeFromHostStateChange(const std::string& name)
115 {
116 _hostChangeCallbacks.erase(name);
117 }
118
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600119 /**
120 * @brief Returns the BMC firmware version
121 *
122 * @return std::string - The BMC version
123 */
124 virtual std::string getBMCFWVersion() const
125 {
126 return _bmcFWVersion;
127 }
128
129 /**
130 * @brief Returns the server firmware version
131 *
132 * @return std::string - The server firmware version
133 */
134 virtual std::string getServerFWVersion() const
135 {
136 return _serverFWVersion;
137 }
138
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600139 /**
Matt Spinler677381b2020-01-23 10:04:29 -0600140 * @brief Returns the BMC FW version ID
141 *
142 * @return std::string - The BMC FW version ID
143 */
144 virtual std::string getBMCFWVersionID() const
145 {
146 return _bmcFWVersionID;
147 }
148
149 /**
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600150 * @brief Returns the process name given its PID.
151 *
152 * @param[in] pid - The PID value as a string
153 *
154 * @return std::optional<std::string> - The name, or std::nullopt
155 */
156 std::optional<std::string> getProcessName(const std::string& pid) const
157 {
158 namespace fs = std::filesystem;
159
160 fs::path path{"/proc"};
161 path /= fs::path{pid} / "exe";
162
163 if (fs::exists(path))
164 {
165 return fs::read_symlink(path);
166 }
167
168 return std::nullopt;
169 }
170
Matt Spinler19e89ce2019-11-06 13:02:23 -0600171 protected:
172 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600173 * @brief Sets the host on/off state and runs any
174 * callback functions (if there was a change).
175 */
176 void setHostState(bool newState)
177 {
178 if (_hostUp != newState)
179 {
180 _hostUp = newState;
181
182 for (auto& [name, func] : _hostChangeCallbacks)
183 {
184 try
185 {
186 func(_hostUp);
187 }
188 catch (std::exception& e)
189 {
190 using namespace phosphor::logging;
191 log<level::ERR>("A host state change callback threw "
192 "an exception");
193 }
194 }
195 }
196 }
197
198 /**
Matt Spinler19e89ce2019-11-06 13:02:23 -0600199 * @brief The machine type-model. Always kept up to date
200 */
201 std::string _machineTypeModel;
202
203 /**
204 * @brief The machine serial number. Always kept up to date
205 */
206 std::string _machineSerialNumber;
Matt Spinlera7d9d962019-11-06 15:01:25 -0600207
208 /**
Matt Spinlercce14112019-12-11 14:20:36 -0600209 * @brief The hardware management console status. Always kept
210 * up to date.
211 */
212 bool _hmcManaged = false;
213
214 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600215 * @brief The host up status. Always kept up to date.
216 */
217 bool _hostUp = false;
218
219 /**
220 * @brief The map of host state change subscriber
221 * names to callback functions.
222 */
223 std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks;
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600224
225 /**
226 * @brief The BMC firmware version string
227 */
228 std::string _bmcFWVersion;
229
230 /**
231 * @brief The server firmware version string
232 */
233 std::string _serverFWVersion;
Matt Spinler677381b2020-01-23 10:04:29 -0600234
235 /**
236 * @brief The BMC firmware version ID string
237 */
238 std::string _bmcFWVersionID;
Matt Spinlerc8705e22019-09-11 12:36:07 -0500239};
240
241/**
242 * @class DataInterface
243 *
244 * Concrete implementation of DataInterfaceBase.
245 */
246class DataInterface : public DataInterfaceBase
247{
248 public:
249 DataInterface() = delete;
250 ~DataInterface() = default;
251 DataInterface(const DataInterface&) = default;
252 DataInterface& operator=(const DataInterface&) = default;
253 DataInterface(DataInterface&&) = default;
254 DataInterface& operator=(DataInterface&&) = default;
255
256 /**
257 * @brief Constructor
258 *
259 * @param[in] bus - The sdbusplus bus object
260 */
261 explicit DataInterface(sdbusplus::bus::bus& bus);
262
Matt Spinlerb3f51862019-12-09 13:55:10 -0600263 /**
264 * @brief Returns the PLDM instance ID to use for PLDM commands
265 *
266 * @param[in] eid - The PLDM EID
267 *
268 * @return uint8_t - The instance ID
269 */
270 uint8_t getPLDMInstanceID(uint8_t eid) const override;
271
Matt Spinlerc8705e22019-09-11 12:36:07 -0500272 private:
273 /**
274 * @brief Reads the machine type/model and SN from D-Bus.
275 *
276 * Looks for them on the 'system' inventory object, and also
277 * places a properties changed watch on them to obtain any changes
278 * (or read them for the first time if the inventory isn't ready
279 * when this function runs.)
280 */
281 void readMTMS();
282
283 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600284 * @brief Reads the host state from D-Bus.
285 *
286 * For host on, looks for the values of 'BootComplete' or 'Standby'
287 * in the OperatingSystemState property on the
288 * 'xyz.openbmc_project.State.OperatingSystem.Status' interface
289 * on the '/xyz/openbmc_project/state/host0' path.
290 *
291 * Also adds a properties changed watch on it so the code can be
292 * kept up to date on changes.
293 */
294 void readHostState();
295
296 /**
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600297 * @brief Reads the BMC firmware version string and puts it into
298 * _bmcFWVersion.
299 */
300 void readBMCFWVersion();
301
302 /**
303 * @brief Reads the server firmware version string and puts it into
304 * _serverFWVersion.
305 */
306 void readServerFWVersion();
307
308 /**
Matt Spinler677381b2020-01-23 10:04:29 -0600309 * @brief Reads the BMC firmware version ID and puts it into
310 * _bmcFWVersionID.
311 */
312 void readBMCFWVersionID();
313
314 /**
Matt Spinlerc8705e22019-09-11 12:36:07 -0500315 * @brief Finds the D-Bus service name that hosts the
316 * passed in path and interface.
317 *
318 * @param[in] objectPath - The D-Bus object path
319 * @param[in] interface - The D-Bus interface
320 */
321 DBusService getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600322 const std::string& interface) const;
Matt Spinlerc8705e22019-09-11 12:36:07 -0500323 /**
324 * @brief Wrapper for the 'GetAll' properties method call
325 *
326 * @param[in] service - The D-Bus service to call it on
327 * @param[in] objectPath - The D-Bus object path
328 * @param[in] interface - The interface to get the props on
329 *
330 * @return DBusPropertyMap - The property results
331 */
332 DBusPropertyMap getAllProperties(const std::string& service,
333 const std::string& objectPath,
334 const std::string& interface);
335
336 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600337 * @brief Wrapper for the 'Get' properties method call
338 *
339 * @param[in] service - The D-Bus service to call it on
340 * @param[in] objectPath - The D-Bus object path
341 * @param[in] interface - The interface to get the property on
342 * @param[in] property - The property name
343 * @param[out] value - Filled in with the property value.
344 */
345 void getProperty(const std::string& service, const std::string& objectPath,
346 const std::string& interface, const std::string& property,
347 DBusValue& value);
348
349 /**
Matt Spinlerc8705e22019-09-11 12:36:07 -0500350 * @brief The properties changed callback for the Asset iface
351 * on the system inventory object.
352 *
353 * @param[in] msg - The sdbusplus message of the signal
354 */
355 void sysAssetPropChanged(sdbusplus::message::message& msg);
356
357 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600358 * @brief The properties changed callback for the OperatingSystemStatus
359 * interface on the host state object.
360 *
361 * @param[in] msg - The sdbusplus message of the signal
362 */
363 void osStatePropChanged(sdbusplus::message::message& msg);
364
365 /**
Matt Spinlerc8705e22019-09-11 12:36:07 -0500366 * @brief The match object for the system path's properties
367 */
368 std::unique_ptr<sdbusplus::bus::match_t> _sysInventoryPropMatch;
369
370 /**
Matt Spinlera7d9d962019-11-06 15:01:25 -0600371 * @brief The match object for the operating system status.
372 */
373 std::unique_ptr<sdbusplus::bus::match_t> _osStateMatch;
374
375 /**
Matt Spinlerc8705e22019-09-11 12:36:07 -0500376 * @brief The sdbusplus bus object for making D-Bus calls.
377 */
378 sdbusplus::bus::bus& _bus;
379};
380
381} // namespace pels
382} // namespace openpower