blob: 2023a9922ab45449965ddce25b5a407ad0f04484 [file] [log] [blame]
Sampa Misraaea5dde2020-08-31 08:33:47 -05001#include "inband_code_update.hpp"
2
Sagar Srinivas78a225a2020-08-27 00:52:20 -05003#include "libpldm/entity.h"
4
5#include "libpldmresponder/pdr.hpp"
Sampa Misraaea5dde2020-08-31 08:33:47 -05006#include "oem_ibm_handler.hpp"
7#include "xyz/openbmc_project/Common/error.hpp"
8
Adriana Kobylak727f7382020-09-01 14:38:25 -05009#include <arpa/inet.h>
10
Sampa Misraaea5dde2020-08-31 08:33:47 -050011#include <sdbusplus/server.hpp>
12#include <xyz/openbmc_project/Dump/NewDump/server.hpp>
13
14#include <exception>
Adriana Kobylak727f7382020-09-01 14:38:25 -050015#include <fstream>
Sampa Misraaea5dde2020-08-31 08:33:47 -050016
17namespace pldm
18{
Sampa Misraaea5dde2020-08-31 08:33:47 -050019namespace responder
20{
21using namespace oem_ibm_platform;
22
23std::string CodeUpdate::fetchCurrentBootSide()
24{
25 return currBootSide;
26}
27
28std::string CodeUpdate::fetchNextBootSide()
29{
30 return nextBootSide;
31}
32
33int CodeUpdate::setCurrentBootSide(const std::string& currSide)
34{
35 currBootSide = currSide;
36 return PLDM_SUCCESS;
37}
38
39int CodeUpdate::setNextBootSide(const std::string& nextSide)
40{
41 nextBootSide = nextSide;
42 std::string objPath{};
43 if (nextBootSide == currBootSide)
44 {
45 objPath = runningVersion;
46 }
47 else
48 {
49 objPath = nonRunningVersion;
50 }
51 if (objPath.empty())
52 {
53 std::cerr << "no nonRunningVersion present \n";
54 return PLDM_PLATFORM_INVALID_STATE_VALUE;
55 }
56
57 pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority",
58 "uint8_t"};
59 uint8_t val = 0;
60 pldm::utils::PropertyValue value = static_cast<uint8_t>(val);
61 try
62 {
63 dBusIntf->setDbusProperty(dbusMapping, value);
64 }
65 catch (const std::exception& e)
66 {
67 std::cerr << "failed to set the next boot side to " << objPath.c_str()
68 << " ERROR=" << e.what() << "\n";
69 return PLDM_ERROR;
70 }
71 return PLDM_SUCCESS;
72}
73
74void CodeUpdate::setVersions()
75{
76 static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
77 static constexpr auto functionalObjPath =
78 "/xyz/openbmc_project/software/functional";
79 static constexpr auto activeObjPath =
80 "/xyz/openbmc_project/software/active";
81 static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
82
83 auto& bus = dBusIntf->getBus();
Sampa Misraaea5dde2020-08-31 08:33:47 -050084 try
85 {
86 auto method = bus.new_method_call(mapperService, functionalObjPath,
87 propIntf, "Get");
88 method.append("xyz.openbmc_project.Association", "endpoints");
89 std::variant<std::vector<std::string>> paths;
90
91 auto reply = bus.call(method);
92 reply.read(paths);
93
94 runningVersion = std::get<std::vector<std::string>>(paths)[0];
95
96 auto method1 =
97 bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
98 method1.append("xyz.openbmc_project.Association", "endpoints");
99
100 auto reply1 = bus.call(method1);
101 reply1.read(paths);
102 for (const auto& path : std::get<std::vector<std::string>>(paths))
103 {
104 if (path != runningVersion)
105 {
106 nonRunningVersion = path;
107 break;
108 }
109 }
110 }
111 catch (const std::exception& e)
112 {
113 std::cerr << "failed to make a d-bus call to Object Mapper "
114 "Association, ERROR="
115 << e.what() << "\n";
116 return;
117 }
118
119 using namespace sdbusplus::bus::match::rules;
120 captureNextBootSideChange.push_back(
121 std::make_unique<sdbusplus::bus::match::match>(
122 pldm::utils::DBusHandler::getBus(),
123 propertiesChanged(runningVersion, redundancyIntf),
124 [this](sdbusplus::message::message& msg) {
125 DbusChangedProps props;
126 std::string iface;
127 msg.read(iface, props);
128 processPriorityChangeNotification(props);
129 }));
130 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
131 pldm::utils::DBusHandler::getBus(),
132 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
133 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
134 [this](sdbusplus::message::message& msg) {
135 DBusInterfaceAdded interfaces;
136 sdbusplus::message::object_path path;
137 msg.read(path, interfaces);
138 for (auto& interface : interfaces)
139 {
140 if (interface.first ==
141 "xyz.openbmc_project.Software.Activation")
142 {
143 newImageId = path.str;
144 break;
145 }
146 }
147 });
148}
149
150void CodeUpdate::processPriorityChangeNotification(
151 const DbusChangedProps& chProperties)
152{
153 static constexpr auto propName = "Priority";
154 const auto it = chProperties.find(propName);
155 if (it == chProperties.end())
156 {
157 return;
158 }
159 uint8_t newVal = std::get<uint8_t>(it->second);
160 nextBootSide = (newVal == 0) ? currBootSide
161 : ((currBootSide == Tside) ? Pside : Tside);
162}
163
164void CodeUpdate::setOemPlatformHandler(
165 pldm::responder::oem_platform::Handler* handler)
166{
167 oemPlatformHandler = handler;
168}
169
170uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
171{
172 uint8_t sensorOpState = tSideNum;
Sampa Misraaea5dde2020-08-31 08:33:47 -0500173 if (entityInstance == 0)
174 {
175 auto currSide = codeUpdate->fetchCurrentBootSide();
176 if (currSide == Pside)
177 {
178 sensorOpState = pSideNum;
179 }
180 }
181 else if (entityInstance == 1)
182 {
183 auto nextSide = codeUpdate->fetchNextBootSide();
184 if (nextSide == Pside)
185 {
186 sensorOpState = pSideNum;
187 }
188 }
189 else
190 {
191 sensorOpState = PLDM_SENSOR_UNKNOWN;
192 }
193
194 return sensorOpState;
195}
196
197int setBootSide(uint16_t entityInstance, uint8_t currState,
198 const std::vector<set_effecter_state_field>& stateField,
199 CodeUpdate* codeUpdate)
200{
201 int rc = PLDM_SUCCESS;
202 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
203
204 if (entityInstance == 0)
205 {
206 rc = codeUpdate->setCurrentBootSide(side);
207 }
208 else if (entityInstance == 1)
209 {
210 rc = codeUpdate->setNextBootSide(side);
211 }
212 else
213 {
214 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
215 }
216 return rc;
217}
218
Adriana Kobylak727f7382020-09-01 14:38:25 -0500219int processCodeUpdateLid(const std::string& filePath)
220{
221 struct LidHeader
222 {
223 uint16_t magicNumber;
Adriana Kobylak86d14182020-10-16 16:11:08 -0500224 uint16_t headerVersion;
225 uint32_t lidNumber;
226 uint32_t lidDate;
227 uint16_t lidTime;
228 uint16_t lidClass;
229 uint32_t lidCrc;
230 uint32_t lidSize;
231 uint32_t headerSize;
Adriana Kobylak727f7382020-09-01 14:38:25 -0500232 };
233 LidHeader header;
234
235 std::ifstream ifs(filePath, std::ios::in | std::ios::binary);
236 if (!ifs)
237 {
238 std::cerr << "ifstream open error: " << filePath << "\n";
239 return PLDM_ERROR;
240 }
241 ifs.seekg(0);
242 ifs.read(reinterpret_cast<char*>(&header), sizeof(header));
243 ifs.close();
244
Adriana Kobylak86d14182020-10-16 16:11:08 -0500245 // File size should be the value of lid size minus the header size
246 auto fileSize = fs::file_size(filePath);
247 fileSize -= htonl(header.headerSize);
248 if (fileSize < htonl(header.lidSize))
249 {
250 // File is not completely written yet
251 return PLDM_SUCCESS;
252 }
253
Adriana Kobylak727f7382020-09-01 14:38:25 -0500254 constexpr auto magicNumber = 0x0222;
255 if (htons(header.magicNumber) != magicNumber)
256 {
257 std::cerr << "Invalid magic number: " << filePath << "\n";
258 return PLDM_ERROR;
259 }
260
261 return PLDM_SUCCESS;
262}
263
Sampa Misraaea5dde2020-08-31 08:33:47 -0500264} // namespace responder
265} // namespace pldm