blob: deb4ba421cf8312fced0a49e946da0f1a8ff6c03 [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{
Matt Spinlercad9c2b2019-12-02 15:42:01 -060054 readBMCFWVersion();
55 readServerFWVersion();
Matt Spinler677381b2020-01-23 10:04:29 -060056 readBMCFWVersionID();
Matt Spinler2a28c932020-02-03 14:23:40 -060057
58 // Watch both the Model and SN properties on the system's Asset iface
59 _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
60 bus, object_path::systemInv, interface::invAsset, *this,
61 [this](const auto& properties) {
62 auto model = properties.find("Model");
63 if (model != properties.end())
64 {
65 this->_machineTypeModel = std::get<std::string>(model->second);
66 }
67
68 auto sn = properties.find("SerialNumber");
69 if (sn != properties.end())
70 {
71 this->_machineSerialNumber = std::get<std::string>(sn->second);
72 }
73 }));
74
75 // Watch the OperatingSystemState property
76 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
77 bus, object_path::hostState, interface::osStatus,
78 "OperatingSystemState", *this, [this](const auto& value) {
79 auto status =
80 Status::convertOSStatusFromString(std::get<std::string>(value));
81
82 if ((status == Status::OSStatus::BootComplete) ||
83 (status == Status::OSStatus::Standby))
84 {
85 setHostState(true);
86 }
87 else
88 {
89 setHostState(false);
90 }
91 }));
Matt Spinlerc8705e22019-09-11 12:36:07 -050092}
93
Matt Spinler2a28c932020-02-03 14:23:40 -060094DBusPropertyMap
95 DataInterface::getAllProperties(const std::string& service,
96 const std::string& objectPath,
97 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -050098{
99 DBusPropertyMap properties;
100
101 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
102 interface::dbusProperty, "GetAll");
103 method.append(interface);
104 auto reply = _bus.call(method);
105
106 reply.read(properties);
107
108 return properties;
109}
110
Matt Spinlera7d9d962019-11-06 15:01:25 -0600111void DataInterface::getProperty(const std::string& service,
112 const std::string& objectPath,
113 const std::string& interface,
Matt Spinler2a28c932020-02-03 14:23:40 -0600114 const std::string& property,
115 DBusValue& value) const
Matt Spinlera7d9d962019-11-06 15:01:25 -0600116{
117
118 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
119 interface::dbusProperty, "Get");
120 method.append(interface, property);
121 auto reply = _bus.call(method);
122
123 reply.read(value);
124}
125
Matt Spinlerc8705e22019-09-11 12:36:07 -0500126DBusService DataInterface::getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600127 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500128{
129 auto method = _bus.new_method_call(service_name::objectMapper,
130 object_path::objectMapper,
131 interface::objectMapper, "GetObject");
132
133 method.append(objectPath, std::vector<std::string>({interface}));
134
135 auto reply = _bus.call(method);
136
137 std::map<DBusService, DBusInterfaceList> response;
138 reply.read(response);
139
140 if (!response.empty())
141 {
142 return response.begin()->first;
143 }
144
145 return std::string{};
146}
Matt Spinlera7d9d962019-11-06 15:01:25 -0600147
Matt Spinlerb3f51862019-12-09 13:55:10 -0600148uint8_t DataInterface::getPLDMInstanceID(uint8_t eid) const
149{
150 return 0;
151// Don't use until PLDM switches to async D-Bus.
152#if 0
153 auto service = getService(object_path::pldm, interface::pldmRequester);
154
155 auto method =
156 _bus.new_method_call(service.c_str(), object_path::pldm,
157 interface::pldmRequester, "GetInstanceId");
158 method.append(eid);
159 auto reply = _bus.call(method);
160
161 uint8_t instanceID = 0;
162 reply.read(instanceID);
163
164 return instanceID;
165#endif
166}
167
Matt Spinler677381b2020-01-23 10:04:29 -0600168/**
169 * @brief Return a value found in the /etc/os-release file
170 *
171 * @param[in] key - The key name, like "VERSION"
172 *
173 * @return std::optional<std::string> - The value
174 */
175std::optional<std::string> getOSReleaseValue(const std::string& key)
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600176{
177 std::ifstream versionFile{BMC_VERSION_FILE};
178 std::string line;
Matt Spinler677381b2020-01-23 10:04:29 -0600179 std::string keyPattern{key + '='};
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600180
181 while (std::getline(versionFile, line))
182 {
Matt Spinler677381b2020-01-23 10:04:29 -0600183 if (line.find(keyPattern) != std::string::npos)
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600184 {
185 auto pos = line.find_first_of('"') + 1;
Matt Spinler677381b2020-01-23 10:04:29 -0600186 auto value = line.substr(pos, line.find_last_of('"') - pos);
187 return value;
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600188 }
189 }
Matt Spinler677381b2020-01-23 10:04:29 -0600190
191 return std::nullopt;
192}
193
194void DataInterface::readBMCFWVersion()
195{
196 _bmcFWVersion = getOSReleaseValue("VERSION").value_or("");
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600197}
198
199void DataInterface::readServerFWVersion()
200{
201 // Not available yet
202}
203
Matt Spinler677381b2020-01-23 10:04:29 -0600204void DataInterface::readBMCFWVersionID()
205{
206 _bmcFWVersionID = getOSReleaseValue("VERSION_ID").value_or("");
207}
208
Matt Spinlerc8705e22019-09-11 12:36:07 -0500209} // namespace pels
210} // namespace openpower