blob: f17b209f3d0421e7358dfe2375a8c5c9ba542e61 [file] [log] [blame]
Sampa Misraaea5dde2020-08-31 08:33:47 -05001#include "inband_code_update.hpp"
2
3#include "oem_ibm_handler.hpp"
4#include "xyz/openbmc_project/Common/error.hpp"
5
6#include <sdbusplus/server.hpp>
7#include <xyz/openbmc_project/Dump/NewDump/server.hpp>
8
9#include <exception>
10
11namespace pldm
12{
13
14namespace responder
15{
16using namespace oem_ibm_platform;
17
18std::string CodeUpdate::fetchCurrentBootSide()
19{
20 return currBootSide;
21}
22
23std::string CodeUpdate::fetchNextBootSide()
24{
25 return nextBootSide;
26}
27
28int CodeUpdate::setCurrentBootSide(const std::string& currSide)
29{
30 currBootSide = currSide;
31 return PLDM_SUCCESS;
32}
33
34int CodeUpdate::setNextBootSide(const std::string& nextSide)
35{
36 nextBootSide = nextSide;
37 std::string objPath{};
38 if (nextBootSide == currBootSide)
39 {
40 objPath = runningVersion;
41 }
42 else
43 {
44 objPath = nonRunningVersion;
45 }
46 if (objPath.empty())
47 {
48 std::cerr << "no nonRunningVersion present \n";
49 return PLDM_PLATFORM_INVALID_STATE_VALUE;
50 }
51
52 pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority",
53 "uint8_t"};
54 uint8_t val = 0;
55 pldm::utils::PropertyValue value = static_cast<uint8_t>(val);
56 try
57 {
58 dBusIntf->setDbusProperty(dbusMapping, value);
59 }
60 catch (const std::exception& e)
61 {
62 std::cerr << "failed to set the next boot side to " << objPath.c_str()
63 << " ERROR=" << e.what() << "\n";
64 return PLDM_ERROR;
65 }
66 return PLDM_SUCCESS;
67}
68
69void CodeUpdate::setVersions()
70{
71 static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
72 static constexpr auto functionalObjPath =
73 "/xyz/openbmc_project/software/functional";
74 static constexpr auto activeObjPath =
75 "/xyz/openbmc_project/software/active";
76 static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
77
78 auto& bus = dBusIntf->getBus();
79
80 try
81 {
82 auto method = bus.new_method_call(mapperService, functionalObjPath,
83 propIntf, "Get");
84 method.append("xyz.openbmc_project.Association", "endpoints");
85 std::variant<std::vector<std::string>> paths;
86
87 auto reply = bus.call(method);
88 reply.read(paths);
89
90 runningVersion = std::get<std::vector<std::string>>(paths)[0];
91
92 auto method1 =
93 bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
94 method1.append("xyz.openbmc_project.Association", "endpoints");
95
96 auto reply1 = bus.call(method1);
97 reply1.read(paths);
98 for (const auto& path : std::get<std::vector<std::string>>(paths))
99 {
100 if (path != runningVersion)
101 {
102 nonRunningVersion = path;
103 break;
104 }
105 }
106 }
107 catch (const std::exception& e)
108 {
109 std::cerr << "failed to make a d-bus call to Object Mapper "
110 "Association, ERROR="
111 << e.what() << "\n";
112 return;
113 }
114
115 using namespace sdbusplus::bus::match::rules;
116 captureNextBootSideChange.push_back(
117 std::make_unique<sdbusplus::bus::match::match>(
118 pldm::utils::DBusHandler::getBus(),
119 propertiesChanged(runningVersion, redundancyIntf),
120 [this](sdbusplus::message::message& msg) {
121 DbusChangedProps props;
122 std::string iface;
123 msg.read(iface, props);
124 processPriorityChangeNotification(props);
125 }));
126 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
127 pldm::utils::DBusHandler::getBus(),
128 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
129 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
130 [this](sdbusplus::message::message& msg) {
131 DBusInterfaceAdded interfaces;
132 sdbusplus::message::object_path path;
133 msg.read(path, interfaces);
134 for (auto& interface : interfaces)
135 {
136 if (interface.first ==
137 "xyz.openbmc_project.Software.Activation")
138 {
139 newImageId = path.str;
140 break;
141 }
142 }
143 });
144}
145
146void CodeUpdate::processPriorityChangeNotification(
147 const DbusChangedProps& chProperties)
148{
149 static constexpr auto propName = "Priority";
150 const auto it = chProperties.find(propName);
151 if (it == chProperties.end())
152 {
153 return;
154 }
155 uint8_t newVal = std::get<uint8_t>(it->second);
156 nextBootSide = (newVal == 0) ? currBootSide
157 : ((currBootSide == Tside) ? Pside : Tside);
158}
159
160void CodeUpdate::setOemPlatformHandler(
161 pldm::responder::oem_platform::Handler* handler)
162{
163 oemPlatformHandler = handler;
164}
165
166uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
167{
168 uint8_t sensorOpState = tSideNum;
169
170 if (entityInstance == 0)
171 {
172 auto currSide = codeUpdate->fetchCurrentBootSide();
173 if (currSide == Pside)
174 {
175 sensorOpState = pSideNum;
176 }
177 }
178 else if (entityInstance == 1)
179 {
180 auto nextSide = codeUpdate->fetchNextBootSide();
181 if (nextSide == Pside)
182 {
183 sensorOpState = pSideNum;
184 }
185 }
186 else
187 {
188 sensorOpState = PLDM_SENSOR_UNKNOWN;
189 }
190
191 return sensorOpState;
192}
193
194int setBootSide(uint16_t entityInstance, uint8_t currState,
195 const std::vector<set_effecter_state_field>& stateField,
196 CodeUpdate* codeUpdate)
197{
198 int rc = PLDM_SUCCESS;
199 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
200
201 if (entityInstance == 0)
202 {
203 rc = codeUpdate->setCurrentBootSide(side);
204 }
205 else if (entityInstance == 1)
206 {
207 rc = codeUpdate->setNextBootSide(side);
208 }
209 else
210 {
211 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
212 }
213 return rc;
214}
215
216} // namespace responder
217} // namespace pldm