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