blob: 351805cfee7305536bf6c0fa4b04406ec294d7ba [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matt Spinlercad9c2b2019-12-02 15:42:01 -060016#include "config.h"
17
Matt Spinlerc8705e22019-09-11 12:36:07 -050018#include "data_interface.hpp"
19
Matt Spinlercad9c2b2019-12-02 15:42:01 -060020#include <fstream>
Matt Spinlera7d9d962019-11-06 15:01:25 -060021#include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp>
22
Matt Spinlerc8705e22019-09-11 12:36:07 -050023namespace openpower
24{
25namespace pels
26{
27
28namespace service_name
29{
30constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
31} // namespace service_name
32
33namespace object_path
34{
35constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper";
36constexpr auto systemInv = "/xyz/openbmc_project/inventory/system";
Matt Spinler4aa23a12020-02-03 15:05:09 -060037constexpr auto bmcState = "/xyz/openbmc_project/state/bmc0";
38constexpr auto chassisState = "/xyz/openbmc_project/state/chassis0";
Matt Spinlera7d9d962019-11-06 15:01:25 -060039constexpr auto hostState = "/xyz/openbmc_project/state/host0";
Matt Spinlerb3f51862019-12-09 13:55:10 -060040constexpr auto pldm = "/xyz/openbmc_project/pldm";
Matt Spinler9cf3cfd2020-02-03 14:41:55 -060041constexpr auto enableHostPELs =
42 "/xyz/openbmc_project/logging/send_event_logs_to_host";
Matt Spinlerc8705e22019-09-11 12:36:07 -050043} // namespace object_path
44
45namespace interface
46{
47constexpr auto dbusProperty = "org.freedesktop.DBus.Properties";
48constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
49constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset";
Matt Spinlera7d9d962019-11-06 15:01:25 -060050constexpr auto osStatus = "xyz.openbmc_project.State.OperatingSystem.Status";
Matt Spinlerb3f51862019-12-09 13:55:10 -060051constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
Matt Spinler9cf3cfd2020-02-03 14:41:55 -060052constexpr auto enable = "xyz.openbmc_project.Object.Enable";
Matt Spinler4aa23a12020-02-03 15:05:09 -060053constexpr auto bmcState = "xyz.openbmc_project.State.BMC";
54constexpr auto chassisState = "xyz.openbmc_project.State.Chassis";
55constexpr auto hostState = "xyz.openbmc_project.State.Host";
Matt Spinlerc8705e22019-09-11 12:36:07 -050056} // namespace interface
57
Matt Spinlera7d9d962019-11-06 15:01:25 -060058using namespace sdbusplus::xyz::openbmc_project::State::OperatingSystem::server;
59
Matt Spinlerc8705e22019-09-11 12:36:07 -050060DataInterface::DataInterface(sdbusplus::bus::bus& bus) : _bus(bus)
61{
Matt Spinlercad9c2b2019-12-02 15:42:01 -060062 readBMCFWVersion();
63 readServerFWVersion();
Matt Spinler677381b2020-01-23 10:04:29 -060064 readBMCFWVersionID();
Matt Spinler2a28c932020-02-03 14:23:40 -060065
66 // Watch both the Model and SN properties on the system's Asset iface
67 _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
68 bus, object_path::systemInv, interface::invAsset, *this,
69 [this](const auto& properties) {
70 auto model = properties.find("Model");
71 if (model != properties.end())
72 {
73 this->_machineTypeModel = std::get<std::string>(model->second);
74 }
75
76 auto sn = properties.find("SerialNumber");
77 if (sn != properties.end())
78 {
79 this->_machineSerialNumber = std::get<std::string>(sn->second);
80 }
81 }));
82
83 // Watch the OperatingSystemState property
84 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
85 bus, object_path::hostState, interface::osStatus,
86 "OperatingSystemState", *this, [this](const auto& value) {
87 auto status =
88 Status::convertOSStatusFromString(std::get<std::string>(value));
89
90 if ((status == Status::OSStatus::BootComplete) ||
91 (status == Status::OSStatus::Standby))
92 {
Matt Spinler4aa23a12020-02-03 15:05:09 -060093 setHostUp(true);
Matt Spinler2a28c932020-02-03 14:23:40 -060094 }
95 else
96 {
Matt Spinler4aa23a12020-02-03 15:05:09 -060097 setHostUp(false);
Matt Spinler2a28c932020-02-03 14:23:40 -060098 }
99 }));
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600100
101 // Watch the host PEL enable property
102 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
103 bus, object_path::enableHostPELs, interface::enable, "Enabled", *this,
104 [this](const auto& value) {
105 this->_sendPELsToHost = std::get<bool>(value);
106 }));
Matt Spinler4aa23a12020-02-03 15:05:09 -0600107
108 // Watch the BMCState property
109 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
110 bus, object_path::bmcState, interface::bmcState, "CurrentBMCState",
111 *this, [this](const auto& value) {
112 this->_bmcState = std::get<std::string>(value);
113 }));
114
115 // Watch the chassis current and requested power state properties
116 _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
117 bus, object_path::chassisState, interface::chassisState, *this,
118 [this](const auto& properties) {
119 auto state = properties.find("CurrentPowerState");
120 if (state != properties.end())
121 {
122 this->_chassisState = std::get<std::string>(state->second);
123 }
124
125 auto trans = properties.find("RequestedPowerTransition");
126 if (trans != properties.end())
127 {
128 this->_chassisTransition = std::get<std::string>(trans->second);
129 }
130 }));
131
132 // Watch the CurrentHostState property
133 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
134 bus, object_path::hostState, interface::hostState, "CurrentHostState",
135 *this, [this](const auto& value) {
136 this->_hostState = std::get<std::string>(value);
137 }));
Matt Spinlerc8705e22019-09-11 12:36:07 -0500138}
139
Matt Spinler2a28c932020-02-03 14:23:40 -0600140DBusPropertyMap
141 DataInterface::getAllProperties(const std::string& service,
142 const std::string& objectPath,
143 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500144{
145 DBusPropertyMap properties;
146
147 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
148 interface::dbusProperty, "GetAll");
149 method.append(interface);
150 auto reply = _bus.call(method);
151
152 reply.read(properties);
153
154 return properties;
155}
156
Matt Spinlera7d9d962019-11-06 15:01:25 -0600157void DataInterface::getProperty(const std::string& service,
158 const std::string& objectPath,
159 const std::string& interface,
Matt Spinler2a28c932020-02-03 14:23:40 -0600160 const std::string& property,
161 DBusValue& value) const
Matt Spinlera7d9d962019-11-06 15:01:25 -0600162{
163
164 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
165 interface::dbusProperty, "Get");
166 method.append(interface, property);
167 auto reply = _bus.call(method);
168
169 reply.read(value);
170}
171
Matt Spinlerc8705e22019-09-11 12:36:07 -0500172DBusService DataInterface::getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600173 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500174{
175 auto method = _bus.new_method_call(service_name::objectMapper,
176 object_path::objectMapper,
177 interface::objectMapper, "GetObject");
178
179 method.append(objectPath, std::vector<std::string>({interface}));
180
181 auto reply = _bus.call(method);
182
183 std::map<DBusService, DBusInterfaceList> response;
184 reply.read(response);
185
186 if (!response.empty())
187 {
188 return response.begin()->first;
189 }
190
191 return std::string{};
192}
Matt Spinlera7d9d962019-11-06 15:01:25 -0600193
Matt Spinlerb3f51862019-12-09 13:55:10 -0600194uint8_t DataInterface::getPLDMInstanceID(uint8_t eid) const
195{
196 return 0;
197// Don't use until PLDM switches to async D-Bus.
198#if 0
199 auto service = getService(object_path::pldm, interface::pldmRequester);
200
201 auto method =
202 _bus.new_method_call(service.c_str(), object_path::pldm,
203 interface::pldmRequester, "GetInstanceId");
204 method.append(eid);
205 auto reply = _bus.call(method);
206
207 uint8_t instanceID = 0;
208 reply.read(instanceID);
209
210 return instanceID;
211#endif
212}
213
Matt Spinler677381b2020-01-23 10:04:29 -0600214/**
215 * @brief Return a value found in the /etc/os-release file
216 *
217 * @param[in] key - The key name, like "VERSION"
218 *
219 * @return std::optional<std::string> - The value
220 */
221std::optional<std::string> getOSReleaseValue(const std::string& key)
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600222{
223 std::ifstream versionFile{BMC_VERSION_FILE};
224 std::string line;
Matt Spinler677381b2020-01-23 10:04:29 -0600225 std::string keyPattern{key + '='};
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600226
227 while (std::getline(versionFile, line))
228 {
Matt Spinler677381b2020-01-23 10:04:29 -0600229 if (line.find(keyPattern) != std::string::npos)
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600230 {
231 auto pos = line.find_first_of('"') + 1;
Matt Spinler677381b2020-01-23 10:04:29 -0600232 auto value = line.substr(pos, line.find_last_of('"') - pos);
233 return value;
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600234 }
235 }
Matt Spinler677381b2020-01-23 10:04:29 -0600236
237 return std::nullopt;
238}
239
240void DataInterface::readBMCFWVersion()
241{
242 _bmcFWVersion = getOSReleaseValue("VERSION").value_or("");
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600243}
244
245void DataInterface::readServerFWVersion()
246{
247 // Not available yet
248}
249
Matt Spinler677381b2020-01-23 10:04:29 -0600250void DataInterface::readBMCFWVersionID()
251{
252 _bmcFWVersionID = getOSReleaseValue("VERSION_ID").value_or("");
253}
254
Matt Spinlerc8705e22019-09-11 12:36:07 -0500255} // namespace pels
256} // namespace openpower