blob: 489ad696a84ec1ce284feb135e5c6e828a5000fd [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();
Sampa Misraaea5dde2020-08-31 08:33:47 -050079 try
80 {
81 auto method = bus.new_method_call(mapperService, functionalObjPath,
82 propIntf, "Get");
83 method.append("xyz.openbmc_project.Association", "endpoints");
84 std::variant<std::vector<std::string>> paths;
85
86 auto reply = bus.call(method);
87 reply.read(paths);
88
89 runningVersion = std::get<std::vector<std::string>>(paths)[0];
90
91 auto method1 =
92 bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
93 method1.append("xyz.openbmc_project.Association", "endpoints");
94
95 auto reply1 = bus.call(method1);
96 reply1.read(paths);
97 for (const auto& path : std::get<std::vector<std::string>>(paths))
98 {
99 if (path != runningVersion)
100 {
101 nonRunningVersion = path;
102 break;
103 }
104 }
105 }
106 catch (const std::exception& e)
107 {
108 std::cerr << "failed to make a d-bus call to Object Mapper "
109 "Association, ERROR="
110 << e.what() << "\n";
111 return;
112 }
113
114 using namespace sdbusplus::bus::match::rules;
115 captureNextBootSideChange.push_back(
116 std::make_unique<sdbusplus::bus::match::match>(
117 pldm::utils::DBusHandler::getBus(),
118 propertiesChanged(runningVersion, redundancyIntf),
119 [this](sdbusplus::message::message& msg) {
120 DbusChangedProps props;
121 std::string iface;
122 msg.read(iface, props);
123 processPriorityChangeNotification(props);
124 }));
125 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
126 pldm::utils::DBusHandler::getBus(),
127 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
128 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
129 [this](sdbusplus::message::message& msg) {
130 DBusInterfaceAdded interfaces;
131 sdbusplus::message::object_path path;
132 msg.read(path, interfaces);
133 for (auto& interface : interfaces)
134 {
135 if (interface.first ==
136 "xyz.openbmc_project.Software.Activation")
137 {
138 newImageId = path.str;
139 break;
140 }
141 }
142 });
143}
144
145void CodeUpdate::processPriorityChangeNotification(
146 const DbusChangedProps& chProperties)
147{
148 static constexpr auto propName = "Priority";
149 const auto it = chProperties.find(propName);
150 if (it == chProperties.end())
151 {
152 return;
153 }
154 uint8_t newVal = std::get<uint8_t>(it->second);
155 nextBootSide = (newVal == 0) ? currBootSide
156 : ((currBootSide == Tside) ? Pside : Tside);
157}
158
159void CodeUpdate::setOemPlatformHandler(
160 pldm::responder::oem_platform::Handler* handler)
161{
162 oemPlatformHandler = handler;
163}
164
165uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
166{
167 uint8_t sensorOpState = tSideNum;
Sampa Misraaea5dde2020-08-31 08:33:47 -0500168 if (entityInstance == 0)
169 {
170 auto currSide = codeUpdate->fetchCurrentBootSide();
171 if (currSide == Pside)
172 {
173 sensorOpState = pSideNum;
174 }
175 }
176 else if (entityInstance == 1)
177 {
178 auto nextSide = codeUpdate->fetchNextBootSide();
179 if (nextSide == Pside)
180 {
181 sensorOpState = pSideNum;
182 }
183 }
184 else
185 {
186 sensorOpState = PLDM_SENSOR_UNKNOWN;
187 }
188
189 return sensorOpState;
190}
191
192int setBootSide(uint16_t entityInstance, uint8_t currState,
193 const std::vector<set_effecter_state_field>& stateField,
194 CodeUpdate* codeUpdate)
195{
196 int rc = PLDM_SUCCESS;
197 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
198
199 if (entityInstance == 0)
200 {
201 rc = codeUpdate->setCurrentBootSide(side);
202 }
203 else if (entityInstance == 1)
204 {
205 rc = codeUpdate->setNextBootSide(side);
206 }
207 else
208 {
209 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
210 }
211 return rc;
212}
213
214} // namespace responder
215} // namespace pldm