blob: 101025ef1e0823fc537683b7015d0eac9756fcc9 [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
Adriana Kobylakfa810d72020-10-16 16:27:28 -050023/** @brief Directory where the lid files without a header are stored */
24auto lidDirPath = fs::path(LID_STAGING_DIR) / "lid";
25
Sampa Misraaea5dde2020-08-31 08:33:47 -050026std::string CodeUpdate::fetchCurrentBootSide()
27{
28 return currBootSide;
29}
30
31std::string CodeUpdate::fetchNextBootSide()
32{
33 return nextBootSide;
34}
35
36int CodeUpdate::setCurrentBootSide(const std::string& currSide)
37{
38 currBootSide = currSide;
39 return PLDM_SUCCESS;
40}
41
42int CodeUpdate::setNextBootSide(const std::string& nextSide)
43{
44 nextBootSide = nextSide;
45 std::string objPath{};
46 if (nextBootSide == currBootSide)
47 {
48 objPath = runningVersion;
49 }
50 else
51 {
52 objPath = nonRunningVersion;
53 }
54 if (objPath.empty())
55 {
56 std::cerr << "no nonRunningVersion present \n";
57 return PLDM_PLATFORM_INVALID_STATE_VALUE;
58 }
59
60 pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority",
61 "uint8_t"};
62 uint8_t val = 0;
63 pldm::utils::PropertyValue value = static_cast<uint8_t>(val);
64 try
65 {
66 dBusIntf->setDbusProperty(dbusMapping, value);
67 }
68 catch (const std::exception& e)
69 {
70 std::cerr << "failed to set the next boot side to " << objPath.c_str()
71 << " ERROR=" << e.what() << "\n";
72 return PLDM_ERROR;
73 }
74 return PLDM_SUCCESS;
75}
76
77void CodeUpdate::setVersions()
78{
79 static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
80 static constexpr auto functionalObjPath =
81 "/xyz/openbmc_project/software/functional";
82 static constexpr auto activeObjPath =
83 "/xyz/openbmc_project/software/active";
84 static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
85
86 auto& bus = dBusIntf->getBus();
Sampa Misraaea5dde2020-08-31 08:33:47 -050087 try
88 {
89 auto method = bus.new_method_call(mapperService, functionalObjPath,
90 propIntf, "Get");
91 method.append("xyz.openbmc_project.Association", "endpoints");
92 std::variant<std::vector<std::string>> paths;
93
94 auto reply = bus.call(method);
95 reply.read(paths);
96
97 runningVersion = std::get<std::vector<std::string>>(paths)[0];
98
99 auto method1 =
100 bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
101 method1.append("xyz.openbmc_project.Association", "endpoints");
102
103 auto reply1 = bus.call(method1);
104 reply1.read(paths);
105 for (const auto& path : std::get<std::vector<std::string>>(paths))
106 {
107 if (path != runningVersion)
108 {
109 nonRunningVersion = path;
110 break;
111 }
112 }
113 }
114 catch (const std::exception& e)
115 {
116 std::cerr << "failed to make a d-bus call to Object Mapper "
117 "Association, ERROR="
118 << e.what() << "\n";
119 return;
120 }
121
122 using namespace sdbusplus::bus::match::rules;
123 captureNextBootSideChange.push_back(
124 std::make_unique<sdbusplus::bus::match::match>(
125 pldm::utils::DBusHandler::getBus(),
126 propertiesChanged(runningVersion, redundancyIntf),
127 [this](sdbusplus::message::message& msg) {
128 DbusChangedProps props;
129 std::string iface;
130 msg.read(iface, props);
131 processPriorityChangeNotification(props);
132 }));
133 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
134 pldm::utils::DBusHandler::getBus(),
135 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
136 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
137 [this](sdbusplus::message::message& msg) {
138 DBusInterfaceAdded interfaces;
139 sdbusplus::message::object_path path;
140 msg.read(path, interfaces);
141 for (auto& interface : interfaces)
142 {
143 if (interface.first ==
144 "xyz.openbmc_project.Software.Activation")
145 {
146 newImageId = path.str;
147 break;
148 }
149 }
150 });
151}
152
153void CodeUpdate::processPriorityChangeNotification(
154 const DbusChangedProps& chProperties)
155{
156 static constexpr auto propName = "Priority";
157 const auto it = chProperties.find(propName);
158 if (it == chProperties.end())
159 {
160 return;
161 }
162 uint8_t newVal = std::get<uint8_t>(it->second);
163 nextBootSide = (newVal == 0) ? currBootSide
164 : ((currBootSide == Tside) ? Pside : Tside);
165}
166
167void CodeUpdate::setOemPlatformHandler(
168 pldm::responder::oem_platform::Handler* handler)
169{
170 oemPlatformHandler = handler;
171}
172
173uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
174{
175 uint8_t sensorOpState = tSideNum;
Sampa Misraaea5dde2020-08-31 08:33:47 -0500176 if (entityInstance == 0)
177 {
178 auto currSide = codeUpdate->fetchCurrentBootSide();
179 if (currSide == Pside)
180 {
181 sensorOpState = pSideNum;
182 }
183 }
184 else if (entityInstance == 1)
185 {
186 auto nextSide = codeUpdate->fetchNextBootSide();
187 if (nextSide == Pside)
188 {
189 sensorOpState = pSideNum;
190 }
191 }
192 else
193 {
194 sensorOpState = PLDM_SENSOR_UNKNOWN;
195 }
196
197 return sensorOpState;
198}
199
200int setBootSide(uint16_t entityInstance, uint8_t currState,
201 const std::vector<set_effecter_state_field>& stateField,
202 CodeUpdate* codeUpdate)
203{
204 int rc = PLDM_SUCCESS;
205 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
206
207 if (entityInstance == 0)
208 {
209 rc = codeUpdate->setCurrentBootSide(side);
210 }
211 else if (entityInstance == 1)
212 {
213 rc = codeUpdate->setNextBootSide(side);
214 }
215 else
216 {
217 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
218 }
219 return rc;
220}
221
Adriana Kobylak727f7382020-09-01 14:38:25 -0500222int processCodeUpdateLid(const std::string& filePath)
223{
224 struct LidHeader
225 {
226 uint16_t magicNumber;
Adriana Kobylak86d14182020-10-16 16:11:08 -0500227 uint16_t headerVersion;
228 uint32_t lidNumber;
229 uint32_t lidDate;
230 uint16_t lidTime;
231 uint16_t lidClass;
232 uint32_t lidCrc;
233 uint32_t lidSize;
234 uint32_t headerSize;
Adriana Kobylak727f7382020-09-01 14:38:25 -0500235 };
236 LidHeader header;
237
238 std::ifstream ifs(filePath, std::ios::in | std::ios::binary);
239 if (!ifs)
240 {
241 std::cerr << "ifstream open error: " << filePath << "\n";
242 return PLDM_ERROR;
243 }
244 ifs.seekg(0);
245 ifs.read(reinterpret_cast<char*>(&header), sizeof(header));
Adriana Kobylak727f7382020-09-01 14:38:25 -0500246
Adriana Kobylak86d14182020-10-16 16:11:08 -0500247 // File size should be the value of lid size minus the header size
248 auto fileSize = fs::file_size(filePath);
249 fileSize -= htonl(header.headerSize);
250 if (fileSize < htonl(header.lidSize))
251 {
252 // File is not completely written yet
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500253 ifs.close();
Adriana Kobylak86d14182020-10-16 16:11:08 -0500254 return PLDM_SUCCESS;
255 }
256
Adriana Kobylak727f7382020-09-01 14:38:25 -0500257 constexpr auto magicNumber = 0x0222;
258 if (htons(header.magicNumber) != magicNumber)
259 {
260 std::cerr << "Invalid magic number: " << filePath << "\n";
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500261 ifs.close();
Adriana Kobylak727f7382020-09-01 14:38:25 -0500262 return PLDM_ERROR;
263 }
264
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500265 fs::create_directories(lidDirPath);
266
267 std::stringstream lidFileName;
268 lidFileName << std::hex << htonl(header.lidNumber) << ".lid";
269 auto lidNoHeaderPath = fs::path(lidDirPath) / lidFileName.str();
270 std::ofstream ofs(lidNoHeaderPath,
271 std::ios::out | std::ios::binary | std::ios::trunc);
272 ifs.seekg(htonl(header.headerSize));
273 ofs << ifs.rdbuf();
274 ofs.flush();
275 ofs.close();
276
277 ifs.close();
278 fs::remove(filePath);
Adriana Kobylak727f7382020-09-01 14:38:25 -0500279 return PLDM_SUCCESS;
280}
281
Sampa Misraaea5dde2020-08-31 08:33:47 -0500282} // namespace responder
283} // namespace pldm