blob: 6ad8b6e8265312108d19125c6697a00ea07add2b [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 Spinlera7d9d962019-11-06 15:01:25 -060037constexpr auto hostState = "/xyz/openbmc_project/state/host0";
Matt Spinlerb3f51862019-12-09 13:55:10 -060038constexpr auto pldm = "/xyz/openbmc_project/pldm";
Matt Spinlerc8705e22019-09-11 12:36:07 -050039} // namespace object_path
40
41namespace interface
42{
43constexpr auto dbusProperty = "org.freedesktop.DBus.Properties";
44constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
45constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset";
Matt Spinlera7d9d962019-11-06 15:01:25 -060046constexpr auto osStatus = "xyz.openbmc_project.State.OperatingSystem.Status";
Matt Spinlerb3f51862019-12-09 13:55:10 -060047constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
Matt Spinlerc8705e22019-09-11 12:36:07 -050048} // namespace interface
49
Matt Spinlera7d9d962019-11-06 15:01:25 -060050using namespace sdbusplus::xyz::openbmc_project::State::OperatingSystem::server;
51
Matt Spinlerc8705e22019-09-11 12:36:07 -050052DataInterface::DataInterface(sdbusplus::bus::bus& bus) : _bus(bus)
53{
54 readMTMS();
Matt Spinlera7d9d962019-11-06 15:01:25 -060055 readHostState();
Matt Spinlercad9c2b2019-12-02 15:42:01 -060056 readBMCFWVersion();
57 readServerFWVersion();
Matt Spinlerc8705e22019-09-11 12:36:07 -050058}
59
60void DataInterface::readMTMS()
61{
62 // If this runs when the inventory service isn't running, it will get the
63 // value whenever it starts via the propertiesChanged callback.
64 try
65 {
66 auto inventoryService =
67 getService(object_path::systemInv, interface::invAsset);
68
69 if (!inventoryService.empty())
70 {
71 auto properties = getAllProperties(
72 inventoryService, object_path::systemInv, interface::invAsset);
73
74 _machineTypeModel = std::get<std::string>(properties["Model"]);
75
76 _machineSerialNumber =
77 std::get<std::string>(properties["SerialNumber"]);
78 }
79 }
80 catch (std::exception& e)
81 {
82 // Inventory must not be running at this moment.
83 }
84
85 // Keep up to date by watching for the propertiesChanged signal.
86 _sysInventoryPropMatch = std::make_unique<sdbusplus::bus::match_t>(
87 _bus,
88 sdbusplus::bus::match::rules::propertiesChanged(object_path::systemInv,
89 interface::invAsset),
90 std::bind(std::mem_fn(&DataInterface::sysAssetPropChanged), this,
91 std::placeholders::_1));
92}
93
94void DataInterface::sysAssetPropChanged(sdbusplus::message::message& msg)
95{
96 DBusInterface interface;
97 DBusPropertyMap properties;
98
99 msg.read(interface, properties);
100
101 auto model = properties.find("Model");
102 if (model != properties.end())
103 {
104 _machineTypeModel = std::get<std::string>(model->second);
105 }
106
107 auto sn = properties.find("SerialNumber");
108 if (sn != properties.end())
109 {
110 _machineSerialNumber = std::get<std::string>(sn->second);
111 }
112}
113
114DBusPropertyMap DataInterface::getAllProperties(const std::string& service,
115 const std::string& objectPath,
116 const std::string& interface)
117{
118 DBusPropertyMap properties;
119
120 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
121 interface::dbusProperty, "GetAll");
122 method.append(interface);
123 auto reply = _bus.call(method);
124
125 reply.read(properties);
126
127 return properties;
128}
129
Matt Spinlera7d9d962019-11-06 15:01:25 -0600130void DataInterface::getProperty(const std::string& service,
131 const std::string& objectPath,
132 const std::string& interface,
133 const std::string& property, DBusValue& value)
134{
135
136 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
137 interface::dbusProperty, "Get");
138 method.append(interface, property);
139 auto reply = _bus.call(method);
140
141 reply.read(value);
142}
143
Matt Spinlerc8705e22019-09-11 12:36:07 -0500144DBusService DataInterface::getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600145 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500146{
147 auto method = _bus.new_method_call(service_name::objectMapper,
148 object_path::objectMapper,
149 interface::objectMapper, "GetObject");
150
151 method.append(objectPath, std::vector<std::string>({interface}));
152
153 auto reply = _bus.call(method);
154
155 std::map<DBusService, DBusInterfaceList> response;
156 reply.read(response);
157
158 if (!response.empty())
159 {
160 return response.begin()->first;
161 }
162
163 return std::string{};
164}
Matt Spinlera7d9d962019-11-06 15:01:25 -0600165
166void DataInterface::readHostState()
167{
168 _hostUp = false;
169
170 try
171 {
172 auto service = getService(object_path::hostState, interface::osStatus);
173 if (!service.empty())
174 {
175 DBusValue value;
176 getProperty(service, object_path::hostState, interface::osStatus,
177 "OperatingSystemState", value);
178
179 auto status =
180 Status::convertOSStatusFromString(std::get<std::string>(value));
181
182 if ((status == Status::OSStatus::BootComplete) ||
183 (status == Status::OSStatus::Standby))
184 {
185 _hostUp = true;
186 }
187 }
188 }
189 catch (std::exception& e)
190 {
191 // Not available yet.
192 }
193
194 // Keep up to date by watching for the propertiesChanged signal.
195 _osStateMatch = std::make_unique<sdbusplus::bus::match_t>(
196 _bus,
197 sdbusplus::bus::match::rules::propertiesChanged(object_path::hostState,
198 interface::osStatus),
199 std::bind(std::mem_fn(&DataInterface::osStatePropChanged), this,
200 std::placeholders::_1));
201}
202
203void DataInterface::osStatePropChanged(sdbusplus::message::message& msg)
204{
205 DBusInterface interface;
206 DBusPropertyMap properties;
207
208 msg.read(interface, properties);
209
210 auto state = properties.find("OperatingSystemState");
211 if (state != properties.end())
212 {
213 auto status = Status::convertOSStatusFromString(
214 std::get<std::string>(state->second));
215
216 bool newHostState = false;
217 if ((status == Status::OSStatus::BootComplete) ||
218 (status == Status::OSStatus::Standby))
219 {
220 newHostState = true;
221 }
222
223 setHostState(newHostState);
224 }
225}
226
Matt Spinlerb3f51862019-12-09 13:55:10 -0600227uint8_t DataInterface::getPLDMInstanceID(uint8_t eid) const
228{
229 return 0;
230// Don't use until PLDM switches to async D-Bus.
231#if 0
232 auto service = getService(object_path::pldm, interface::pldmRequester);
233
234 auto method =
235 _bus.new_method_call(service.c_str(), object_path::pldm,
236 interface::pldmRequester, "GetInstanceId");
237 method.append(eid);
238 auto reply = _bus.call(method);
239
240 uint8_t instanceID = 0;
241 reply.read(instanceID);
242
243 return instanceID;
244#endif
245}
246
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600247void DataInterface::readBMCFWVersion()
248{
249 std::ifstream versionFile{BMC_VERSION_FILE};
250 std::string line;
251 static const auto versionID = "VERSION=";
252
253 while (std::getline(versionFile, line))
254 {
255 if (line.find(versionID) != std::string::npos)
256 {
257 auto pos = line.find_first_of('"') + 1;
258 _bmcFWVersion = line.substr(pos, line.find_last_of('"') - pos);
259 break;
260 }
261 }
262}
263
264void DataInterface::readServerFWVersion()
265{
266 // Not available yet
267}
268
Matt Spinlerc8705e22019-09-11 12:36:07 -0500269} // namespace pels
270} // namespace openpower