blob: 1e87824fad4e081289a63ef1a44a45852c5bfa67 [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 "libpldmresponder/pdr.hpp"
Sampa Misraaea5dde2020-08-31 08:33:47 -05004#include "oem_ibm_handler.hpp"
5#include "xyz/openbmc_project/Common/error.hpp"
6
Adriana Kobylak727f7382020-09-01 14:38:25 -05007#include <arpa/inet.h>
George Liuc453e162022-12-21 17:16:23 +08008#include <libpldm/entity.h>
Adriana Kobylak727f7382020-09-01 14:38:25 -05009
Riya Dixit49cfb132023-03-02 04:26:53 -060010#include <phosphor-logging/lg2.hpp>
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>
Riya Dixit49cfb132023-03-02 04:26:53 -060016
17PHOSPHOR_LOG2_USING;
18
Sampa Misraaea5dde2020-08-31 08:33:47 -050019namespace pldm
20{
Brad Bishop5079ac42021-08-19 18:35:06 -040021using namespace utils;
22
Sampa Misraaea5dde2020-08-31 08:33:47 -050023namespace responder
24{
25using namespace oem_ibm_platform;
26
Adriana Kobylakfa810d72020-10-16 16:27:28 -050027/** @brief Directory where the lid files without a header are stored */
28auto lidDirPath = fs::path(LID_STAGING_DIR) / "lid";
29
Adriana Kobylaka1f158c2020-11-09 12:47:29 -060030/** @brief Directory where the image files are stored as they are built */
31auto imageDirPath = fs::path(LID_STAGING_DIR) / "image";
32
Adriana Kobylak837fb472020-10-16 16:53:42 -050033/** @brief Directory where the code update tarball files are stored */
34auto updateDirPath = fs::path(LID_STAGING_DIR) / "update";
35
Adriana Kobylaka1f158c2020-11-09 12:47:29 -060036/** @brief The file name of the code update tarball */
37constexpr auto tarImageName = "image.tar";
38
Adriana Kobylak837fb472020-10-16 16:53:42 -050039/** @brief The file name of the hostfw image */
Adriana Kobylak131327e2021-03-10 18:45:24 +000040constexpr auto hostfwImageName = "image-hostfw";
Adriana Kobylak837fb472020-10-16 16:53:42 -050041
Adriana Kobylaka1f158c2020-11-09 12:47:29 -060042/** @brief The path to the code update tarball file */
43auto tarImagePath = fs::path(imageDirPath) / tarImageName;
44
Adriana Kobylak837fb472020-10-16 16:53:42 -050045/** @brief The path to the hostfw image */
46auto hostfwImagePath = fs::path(imageDirPath) / hostfwImageName;
47
48/** @brief The path to the tarball file expected by the phosphor software
49 * manager */
50auto updateImagePath = fs::path("/tmp/images") / tarImageName;
51
Sampa Misraaea5dde2020-08-31 08:33:47 -050052std::string CodeUpdate::fetchCurrentBootSide()
53{
54 return currBootSide;
55}
56
57std::string CodeUpdate::fetchNextBootSide()
58{
59 return nextBootSide;
60}
61
62int CodeUpdate::setCurrentBootSide(const std::string& currSide)
63{
64 currBootSide = currSide;
65 return PLDM_SUCCESS;
66}
67
68int CodeUpdate::setNextBootSide(const std::string& nextSide)
69{
70 nextBootSide = nextSide;
71 std::string objPath{};
72 if (nextBootSide == currBootSide)
73 {
74 objPath = runningVersion;
75 }
76 else
77 {
78 objPath = nonRunningVersion;
79 }
80 if (objPath.empty())
81 {
Riya Dixit49cfb132023-03-02 04:26:53 -060082 error("no nonRunningVersion present");
Sampa Misraaea5dde2020-08-31 08:33:47 -050083 return PLDM_PLATFORM_INVALID_STATE_VALUE;
84 }
85
86 pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority",
87 "uint8_t"};
88 uint8_t val = 0;
89 pldm::utils::PropertyValue value = static_cast<uint8_t>(val);
90 try
91 {
92 dBusIntf->setDbusProperty(dbusMapping, value);
93 }
94 catch (const std::exception& e)
95 {
Riya Dixit49cfb132023-03-02 04:26:53 -060096 error(
97 "failed to set the next boot side to {OBJ_PATH} ERROR={ERR_EXCEP}",
98 "OBJ_PATH", objPath.c_str(), "ERR_EXCEP", e.what());
Sampa Misraaea5dde2020-08-31 08:33:47 -050099 return PLDM_ERROR;
100 }
101 return PLDM_SUCCESS;
102}
103
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500104int CodeUpdate::setRequestedApplyTime()
105{
106 int rc = PLDM_SUCCESS;
107 pldm::utils::PropertyValue value =
108 "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.OnReset";
109 DBusMapping dbusMapping;
110 dbusMapping.objectPath = "/xyz/openbmc_project/software/apply_time";
111 dbusMapping.interface = "xyz.openbmc_project.Software.ApplyTime";
112 dbusMapping.propertyName = "RequestedApplyTime";
113 dbusMapping.propertyType = "string";
114 try
115 {
116 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
117 }
118 catch (const std::exception& e)
119 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600120 error("Failed To set RequestedApplyTime property ERROR={ERR_EXCEP}",
121 "ERR_EXCEP", e.what());
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500122 rc = PLDM_ERROR;
123 }
124 return rc;
125}
126
127int CodeUpdate::setRequestedActivation()
128{
129 int rc = PLDM_SUCCESS;
130 pldm::utils::PropertyValue value =
131 "xyz.openbmc_project.Software.Activation.RequestedActivations.Active";
132 DBusMapping dbusMapping;
133 dbusMapping.objectPath = newImageId;
134 dbusMapping.interface = "xyz.openbmc_project.Software.Activation";
135 dbusMapping.propertyName = "RequestedActivation";
136 dbusMapping.propertyType = "string";
137 try
138 {
139 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
140 }
141 catch (const std::exception& e)
142 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600143 error("Failed To set RequestedActivation property ERROR={ERR_EXCEP}",
144 "ERR_EXCEP", e.what());
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500145 rc = PLDM_ERROR;
146 }
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500147 return rc;
148}
149
Sampa Misraaea5dde2020-08-31 08:33:47 -0500150void CodeUpdate::setVersions()
151{
152 static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
153 static constexpr auto functionalObjPath =
154 "/xyz/openbmc_project/software/functional";
155 static constexpr auto activeObjPath =
156 "/xyz/openbmc_project/software/active";
157 static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
158
159 auto& bus = dBusIntf->getBus();
Sampa Misraaea5dde2020-08-31 08:33:47 -0500160 try
161 {
162 auto method = bus.new_method_call(mapperService, functionalObjPath,
163 propIntf, "Get");
164 method.append("xyz.openbmc_project.Association", "endpoints");
165 std::variant<std::vector<std::string>> paths;
166
vkaverap@in.ibm.com9138c202023-05-19 07:50:47 -0500167 auto reply = bus.call(
168 method,
169 std::chrono::duration_cast<microsec>(sec(DBUS_TIMEOUT)).count());
Sampa Misraaea5dde2020-08-31 08:33:47 -0500170 reply.read(paths);
171
172 runningVersion = std::get<std::vector<std::string>>(paths)[0];
173
Patrick Williams6da4f912023-05-10 07:50:53 -0500174 auto method1 = bus.new_method_call(mapperService, activeObjPath,
175 propIntf, "Get");
Sampa Misraaea5dde2020-08-31 08:33:47 -0500176 method1.append("xyz.openbmc_project.Association", "endpoints");
177
vkaverap@in.ibm.com9138c202023-05-19 07:50:47 -0500178 auto reply1 = bus.call(
179 method1,
180 std::chrono::duration_cast<microsec>(sec(DBUS_TIMEOUT)).count());
Sampa Misraaea5dde2020-08-31 08:33:47 -0500181 reply1.read(paths);
182 for (const auto& path : std::get<std::vector<std::string>>(paths))
183 {
184 if (path != runningVersion)
185 {
186 nonRunningVersion = path;
187 break;
188 }
189 }
190 }
191 catch (const std::exception& e)
192 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600193 error(
194 "failed to make a d-bus call to Object Mapper Association, ERROR={ERR_EXCEP}",
195 "ERR_EXCEP", e.what());
Sampa Misraaea5dde2020-08-31 08:33:47 -0500196 return;
197 }
198
199 using namespace sdbusplus::bus::match::rules;
200 captureNextBootSideChange.push_back(
Patrick Williams84b790c2022-07-22 19:26:56 -0500201 std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500202 pldm::utils::DBusHandler::getBus(),
203 propertiesChanged(runningVersion, redundancyIntf),
Patrick Williams84b790c2022-07-22 19:26:56 -0500204 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500205 DbusChangedProps props;
206 std::string iface;
207 msg.read(iface, props);
208 processPriorityChangeNotification(props);
Sampa Misraaea5dde2020-08-31 08:33:47 -0500209 }));
Patrick Williams84b790c2022-07-22 19:26:56 -0500210 fwUpdateMatcher.push_back(std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500211 pldm::utils::DBusHandler::getBus(),
212 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
213 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
Patrick Williams84b790c2022-07-22 19:26:56 -0500214 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500215 DBusInterfaceAdded interfaces;
216 sdbusplus::message::object_path path;
217 msg.read(path, interfaces);
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600218
Patrick Williams6da4f912023-05-10 07:50:53 -0500219 for (auto& interface : interfaces)
220 {
221 if (interface.first == "xyz.openbmc_project.Software.Activation")
Sampa Misraaea5dde2020-08-31 08:33:47 -0500222 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500223 auto imageInterface = "xyz.openbmc_project.Software.Activation";
224 auto imageObjPath = path.str.c_str();
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600225
Patrick Williams6da4f912023-05-10 07:50:53 -0500226 try
227 {
228 auto propVal = dBusIntf->getDbusPropertyVariant(
229 imageObjPath, "Activation", imageInterface);
230 const auto& imageProp = std::get<std::string>(propVal);
231 if (imageProp == "xyz.openbmc_project.Software."
232 "Activation.Activations.Ready" &&
233 isCodeUpdateInProgress())
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500234 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500235 newImageId = path.str;
236 if (!imageActivationMatch)
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500237 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500238 imageActivationMatch =
239 std::make_unique<sdbusplus::bus::match_t>(
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600240 pldm::utils::DBusHandler::getBus(),
241 propertiesChanged(newImageId,
242 "xyz.openbmc_project."
243 "Software.Activation"),
Patrick Williams84b790c2022-07-22 19:26:56 -0500244 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500245 DbusChangedProps props;
246 std::string iface;
247 msg.read(iface, props);
248 const auto itr = props.find("Activation");
249 if (itr != props.end())
250 {
251 PropertyValue value = itr->second;
252 auto propVal = std::get<std::string>(value);
253 if (propVal ==
254 "xyz.openbmc_project.Software."
255 "Activation.Activations.Active")
256 {
257 CodeUpdateState state =
258 CodeUpdateState::END;
259 setCodeUpdateProgress(false);
260 auto sensorId =
261 getFirmwareUpdateSensor();
262 sendStateSensorEvent(
263 sensorId, PLDM_STATE_SENSOR_STATE,
264 0, uint8_t(state),
265 uint8_t(CodeUpdateState::START));
266 newImageId.clear();
267 }
268 else if (propVal == "xyz.openbmc_project."
269 "Software.Activation."
270 "Activations.Failed" ||
271 propVal == "xyz.openbmc_"
272 "project.Software."
273 "Activation."
274 "Activations."
275 "Invalid")
276 {
277 CodeUpdateState state =
278 CodeUpdateState::FAIL;
279 setCodeUpdateProgress(false);
280 auto sensorId =
281 getFirmwareUpdateSensor();
282 sendStateSensorEvent(
283 sensorId, PLDM_STATE_SENSOR_STATE,
284 0, uint8_t(state),
285 uint8_t(CodeUpdateState::START));
286 newImageId.clear();
287 }
288 }
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600289 });
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500290 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500291 auto rc = setRequestedActivation();
292 if (rc != PLDM_SUCCESS)
293 {
294 CodeUpdateState state = CodeUpdateState::FAIL;
295 setCodeUpdateProgress(false);
296 auto sensorId = getFirmwareUpdateSensor();
297 sendStateSensorEvent(
298 sensorId, PLDM_STATE_SENSOR_STATE, 0,
299 uint8_t(state),
300 uint8_t(CodeUpdateState::START));
301 error("could not set RequestedActivation");
302 }
303 break;
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500304 }
Sampa Misraaea5dde2020-08-31 08:33:47 -0500305 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500306 catch (const sdbusplus::exception_t& e)
307 {
308 error(
309 "Error in getting Activation status,ERROR= {ERR_EXCEP}, INTERFACE={IMG_INTERFACE}, OBJECT PATH={OBJ_PATH}",
310 "ERR_EXCEP", e.what(), "IMG_INTERFACE", imageInterface,
311 "OBJ_PATH", imageObjPath);
312 }
Sampa Misraaea5dde2020-08-31 08:33:47 -0500313 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500314 }
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600315 }));
Sampa Misraaea5dde2020-08-31 08:33:47 -0500316}
317
318void CodeUpdate::processPriorityChangeNotification(
319 const DbusChangedProps& chProperties)
320{
321 static constexpr auto propName = "Priority";
322 const auto it = chProperties.find(propName);
323 if (it == chProperties.end())
324 {
325 return;
326 }
327 uint8_t newVal = std::get<uint8_t>(it->second);
328 nextBootSide = (newVal == 0) ? currBootSide
329 : ((currBootSide == Tside) ? Pside : Tside);
330}
331
332void CodeUpdate::setOemPlatformHandler(
333 pldm::responder::oem_platform::Handler* handler)
334{
335 oemPlatformHandler = handler;
336}
337
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500338void CodeUpdate::clearDirPath(const std::string& dirPath)
339{
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530340 if (!fs::is_directory(dirPath))
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500341 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600342 error("The directory does not exist, dirPath = {DIR_PATH}", "DIR_PATH",
343 dirPath.c_str());
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530344 return;
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500345 }
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530346 for (const auto& iter : fs::directory_iterator(dirPath))
347 {
348 fs::remove_all(iter);
349 }
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500350}
351
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500352void CodeUpdate::sendStateSensorEvent(
353 uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
354 uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
355{
356 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
357 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
358 oemPlatformHandler);
359 oemIbmPlatformHandler->sendStateSensorEvent(
360 sensorId, sensorEventClass, sensorOffset, eventState, prevEventState);
361}
362
363void CodeUpdate::deleteImage()
364{
365 static constexpr auto UPDATER_SERVICE =
366 "xyz.openbmc_project.Software.BMC.Updater";
367 static constexpr auto SW_OBJ_PATH = "/xyz/openbmc_project/software";
368 static constexpr auto DELETE_INTF =
369 "xyz.openbmc_project.Collection.DeleteAll";
370
371 auto& bus = dBusIntf->getBus();
372 try
373 {
374 auto method = bus.new_method_call(UPDATER_SERVICE, SW_OBJ_PATH,
375 DELETE_INTF, "DeleteAll");
376 bus.call_noreply(method);
377 }
378 catch (const std::exception& e)
379 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600380 error("Failed to delete image, ERROR={ERR_EXCEP}", "ERR_EXCEP",
381 e.what());
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500382 return;
383 }
384}
385
Sampa Misraaea5dde2020-08-31 08:33:47 -0500386uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
387{
388 uint8_t sensorOpState = tSideNum;
Sampa Misraaea5dde2020-08-31 08:33:47 -0500389 if (entityInstance == 0)
390 {
391 auto currSide = codeUpdate->fetchCurrentBootSide();
392 if (currSide == Pside)
393 {
394 sensorOpState = pSideNum;
395 }
396 }
397 else if (entityInstance == 1)
398 {
399 auto nextSide = codeUpdate->fetchNextBootSide();
400 if (nextSide == Pside)
401 {
402 sensorOpState = pSideNum;
403 }
404 }
405 else
406 {
407 sensorOpState = PLDM_SENSOR_UNKNOWN;
408 }
409
410 return sensorOpState;
411}
412
413int setBootSide(uint16_t entityInstance, uint8_t currState,
414 const std::vector<set_effecter_state_field>& stateField,
415 CodeUpdate* codeUpdate)
416{
417 int rc = PLDM_SUCCESS;
418 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
419
420 if (entityInstance == 0)
421 {
422 rc = codeUpdate->setCurrentBootSide(side);
423 }
424 else if (entityInstance == 1)
425 {
426 rc = codeUpdate->setNextBootSide(side);
427 }
428 else
429 {
430 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
431 }
432 return rc;
433}
434
Adriana Kobylak837fb472020-10-16 16:53:42 -0500435template <typename... T>
Patrick Williams6da4f912023-05-10 07:50:53 -0500436int executeCmd(const T&... t)
Adriana Kobylak837fb472020-10-16 16:53:42 -0500437{
438 std::stringstream cmd;
439 ((cmd << t << " "), ...) << std::endl;
440 FILE* pipe = popen(cmd.str().c_str(), "r");
441 if (!pipe)
442 {
443 throw std::runtime_error("popen() failed!");
444 }
445 int rc = pclose(pipe);
446 if (WEXITSTATUS(rc))
447 {
448 std::cerr << "Error executing: ";
449 ((std::cerr << " " << t), ...);
450 std::cerr << "\n";
451 return -1;
452 }
453
454 return 0;
455}
456
Adriana Kobylak727f7382020-09-01 14:38:25 -0500457int processCodeUpdateLid(const std::string& filePath)
458{
459 struct LidHeader
460 {
461 uint16_t magicNumber;
Adriana Kobylak86d14182020-10-16 16:11:08 -0500462 uint16_t headerVersion;
463 uint32_t lidNumber;
464 uint32_t lidDate;
465 uint16_t lidTime;
466 uint16_t lidClass;
467 uint32_t lidCrc;
468 uint32_t lidSize;
469 uint32_t headerSize;
Adriana Kobylak727f7382020-09-01 14:38:25 -0500470 };
471 LidHeader header;
472
473 std::ifstream ifs(filePath, std::ios::in | std::ios::binary);
474 if (!ifs)
475 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600476 error("ifstream open error: {DIR_PATH}", "DIR_PATH", filePath.c_str());
Adriana Kobylak727f7382020-09-01 14:38:25 -0500477 return PLDM_ERROR;
478 }
479 ifs.seekg(0);
480 ifs.read(reinterpret_cast<char*>(&header), sizeof(header));
Adriana Kobylak727f7382020-09-01 14:38:25 -0500481
Adriana Kobylak86d14182020-10-16 16:11:08 -0500482 // File size should be the value of lid size minus the header size
483 auto fileSize = fs::file_size(filePath);
484 fileSize -= htonl(header.headerSize);
485 if (fileSize < htonl(header.lidSize))
486 {
487 // File is not completely written yet
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500488 ifs.close();
Adriana Kobylak86d14182020-10-16 16:11:08 -0500489 return PLDM_SUCCESS;
490 }
491
Adriana Kobylak727f7382020-09-01 14:38:25 -0500492 constexpr auto magicNumber = 0x0222;
493 if (htons(header.magicNumber) != magicNumber)
494 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600495 error("Invalid magic number: {DIR_PATH}", "DIR_PATH", filePath.c_str());
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500496 ifs.close();
Adriana Kobylak727f7382020-09-01 14:38:25 -0500497 return PLDM_ERROR;
498 }
499
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600500 fs::create_directories(imageDirPath);
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500501 fs::create_directories(lidDirPath);
502
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600503 constexpr auto bmcClass = 0x2000;
504 if (htons(header.lidClass) == bmcClass)
505 {
506 // Skip the header and concatenate the BMC LIDs into a tar file
507 std::ofstream ofs(tarImagePath,
508 std::ios::out | std::ios::binary | std::ios::app);
509 ifs.seekg(htonl(header.headerSize));
510 ofs << ifs.rdbuf();
511 ofs.flush();
512 ofs.close();
513 }
514 else
515 {
516 std::stringstream lidFileName;
517 lidFileName << std::hex << htonl(header.lidNumber) << ".lid";
518 auto lidNoHeaderPath = fs::path(lidDirPath) / lidFileName.str();
519 std::ofstream ofs(lidNoHeaderPath,
520 std::ios::out | std::ios::binary | std::ios::trunc);
521 ifs.seekg(htonl(header.headerSize));
522 ofs << ifs.rdbuf();
523 ofs.flush();
524 ofs.close();
525 }
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500526
527 ifs.close();
528 fs::remove(filePath);
Adriana Kobylak727f7382020-09-01 14:38:25 -0500529 return PLDM_SUCCESS;
530}
531
Adriana Kobylak9296f242021-09-22 15:52:00 +0000532int CodeUpdate::assembleCodeUpdateImage()
Adriana Kobylak837fb472020-10-16 16:53:42 -0500533{
Adriana Kobylak9296f242021-09-22 15:52:00 +0000534 pid_t pid = fork();
535
536 if (pid == 0)
Adriana Kobylak837fb472020-10-16 16:53:42 -0500537 {
Adriana Kobylak9296f242021-09-22 15:52:00 +0000538 pid_t nextPid = fork();
539 if (nextPid == 0)
540 {
541 // Create the hostfw squashfs image from the LID files without
542 // header
543 auto rc = executeCmd("/usr/sbin/mksquashfs", lidDirPath.c_str(),
544 hostfwImagePath.c_str(), "-all-root",
545 "-no-recovery");
546 if (rc < 0)
547 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600548 error("Error occurred during the mksqusquashfs call");
Adriana Kobylak9296f242021-09-22 15:52:00 +0000549 setCodeUpdateProgress(false);
550 auto sensorId = getFirmwareUpdateSensor();
551 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
552 uint8_t(CodeUpdateState::FAIL),
553 uint8_t(CodeUpdateState::START));
554 exit(EXIT_FAILURE);
555 }
556
557 fs::create_directories(updateDirPath);
558
559 // Extract the BMC tarball content
560 rc = executeCmd("/bin/tar", "-xf", tarImagePath.c_str(), "-C",
561 updateDirPath);
562 if (rc < 0)
563 {
564 setCodeUpdateProgress(false);
565 auto sensorId = getFirmwareUpdateSensor();
566 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
567 uint8_t(CodeUpdateState::FAIL),
568 uint8_t(CodeUpdateState::START));
569 exit(EXIT_FAILURE);
570 }
571
572 // Add the hostfw image to the directory where the contents were
573 // extracted
574 fs::copy_file(hostfwImagePath,
575 fs::path(updateDirPath) / hostfwImageName,
576 fs::copy_options::overwrite_existing);
577
578 // Remove the tarball file, then re-generate it with so that the
579 // hostfw image becomes part of the tarball
580 fs::remove(tarImagePath);
581 rc = executeCmd("/bin/tar", "-cf", tarImagePath, ".", "-C",
582 updateDirPath);
583 if (rc < 0)
584 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600585 error("Error occurred during the generation of the tarball");
Adriana Kobylak9296f242021-09-22 15:52:00 +0000586 setCodeUpdateProgress(false);
587 auto sensorId = getFirmwareUpdateSensor();
588 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
589 uint8_t(CodeUpdateState::FAIL),
590 uint8_t(CodeUpdateState::START));
591 exit(EXIT_FAILURE);
592 }
593
594 // Copy the tarball to the update directory to trigger the phosphor
595 // software manager to create a version interface
596 fs::copy_file(tarImagePath, updateImagePath,
597 fs::copy_options::overwrite_existing);
598
599 // Cleanup
600 fs::remove_all(updateDirPath);
601 fs::remove_all(lidDirPath);
602 fs::remove_all(imageDirPath);
603
604 exit(EXIT_SUCCESS);
605 }
606 else if (nextPid < 0)
607 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600608 error("Error occurred during fork. ERROR={ERR}", "ERR", errno);
Adriana Kobylak9296f242021-09-22 15:52:00 +0000609 exit(EXIT_FAILURE);
610 }
611
612 // Do nothing as parent. When parent exits, child will be reparented
613 // under init and be reaped properly.
614 exit(0);
615 }
616 else if (pid > 0)
617 {
618 int status;
619 if (waitpid(pid, &status, 0) < 0)
620 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600621 error("Error occurred during waitpid. ERROR={ERR}", "ERR", errno);
622
Adriana Kobylak9296f242021-09-22 15:52:00 +0000623 return PLDM_ERROR;
624 }
625 else if (WEXITSTATUS(status) != 0)
626 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600627 error(
628 "Failed to execute the assembling of the image. STATUS={IMG_STATUS}",
629 "IMG_STATUS", status);
Adriana Kobylak9296f242021-09-22 15:52:00 +0000630 return PLDM_ERROR;
631 }
632 }
633 else
634 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600635 error("Error occurred during fork. ERROR={ERR}", "ERR", errno);
Adriana Kobylak837fb472020-10-16 16:53:42 -0500636 return PLDM_ERROR;
637 }
638
Adriana Kobylak837fb472020-10-16 16:53:42 -0500639 return PLDM_SUCCESS;
640}
641
Sampa Misraaea5dde2020-08-31 08:33:47 -0500642} // namespace responder
643} // namespace pldm