blob: 3066b40326a556d91c5bf48c1ca1caa896cb7dc1 [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
Sampa Misraaea5dde2020-08-31 08:33:47 -050010#include <sdbusplus/server.hpp>
11#include <xyz/openbmc_project/Dump/NewDump/server.hpp>
12
13#include <exception>
Adriana Kobylak727f7382020-09-01 14:38:25 -050014#include <fstream>
Sampa Misraaea5dde2020-08-31 08:33:47 -050015namespace pldm
16{
Brad Bishop5079ac42021-08-19 18:35:06 -040017using namespace utils;
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
Adriana Kobylaka1f158c2020-11-09 12:47:29 -060026/** @brief Directory where the image files are stored as they are built */
27auto imageDirPath = fs::path(LID_STAGING_DIR) / "image";
28
Adriana Kobylak837fb472020-10-16 16:53:42 -050029/** @brief Directory where the code update tarball files are stored */
30auto updateDirPath = fs::path(LID_STAGING_DIR) / "update";
31
Adriana Kobylaka1f158c2020-11-09 12:47:29 -060032/** @brief The file name of the code update tarball */
33constexpr auto tarImageName = "image.tar";
34
Adriana Kobylak837fb472020-10-16 16:53:42 -050035/** @brief The file name of the hostfw image */
Adriana Kobylak131327e2021-03-10 18:45:24 +000036constexpr auto hostfwImageName = "image-hostfw";
Adriana Kobylak837fb472020-10-16 16:53:42 -050037
Adriana Kobylaka1f158c2020-11-09 12:47:29 -060038/** @brief The path to the code update tarball file */
39auto tarImagePath = fs::path(imageDirPath) / tarImageName;
40
Adriana Kobylak837fb472020-10-16 16:53:42 -050041/** @brief The path to the hostfw image */
42auto hostfwImagePath = fs::path(imageDirPath) / hostfwImageName;
43
44/** @brief The path to the tarball file expected by the phosphor software
45 * manager */
46auto updateImagePath = fs::path("/tmp/images") / tarImageName;
47
Sampa Misraaea5dde2020-08-31 08:33:47 -050048std::string CodeUpdate::fetchCurrentBootSide()
49{
50 return currBootSide;
51}
52
53std::string CodeUpdate::fetchNextBootSide()
54{
55 return nextBootSide;
56}
57
58int CodeUpdate::setCurrentBootSide(const std::string& currSide)
59{
60 currBootSide = currSide;
61 return PLDM_SUCCESS;
62}
63
64int CodeUpdate::setNextBootSide(const std::string& nextSide)
65{
66 nextBootSide = nextSide;
67 std::string objPath{};
68 if (nextBootSide == currBootSide)
69 {
70 objPath = runningVersion;
71 }
72 else
73 {
74 objPath = nonRunningVersion;
75 }
76 if (objPath.empty())
77 {
78 std::cerr << "no nonRunningVersion present \n";
79 return PLDM_PLATFORM_INVALID_STATE_VALUE;
80 }
81
82 pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority",
83 "uint8_t"};
84 uint8_t val = 0;
85 pldm::utils::PropertyValue value = static_cast<uint8_t>(val);
86 try
87 {
88 dBusIntf->setDbusProperty(dbusMapping, value);
89 }
90 catch (const std::exception& e)
91 {
92 std::cerr << "failed to set the next boot side to " << objPath.c_str()
93 << " ERROR=" << e.what() << "\n";
94 return PLDM_ERROR;
95 }
96 return PLDM_SUCCESS;
97}
98
Sagar Srinivascfdbca72020-09-22 10:03:35 -050099int CodeUpdate::setRequestedApplyTime()
100{
101 int rc = PLDM_SUCCESS;
102 pldm::utils::PropertyValue value =
103 "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.OnReset";
104 DBusMapping dbusMapping;
105 dbusMapping.objectPath = "/xyz/openbmc_project/software/apply_time";
106 dbusMapping.interface = "xyz.openbmc_project.Software.ApplyTime";
107 dbusMapping.propertyName = "RequestedApplyTime";
108 dbusMapping.propertyType = "string";
109 try
110 {
111 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
112 }
113 catch (const std::exception& e)
114 {
115 std::cerr << "Failed To set RequestedApplyTime property "
116 << "ERROR=" << e.what() << std::endl;
117 rc = PLDM_ERROR;
118 }
119 return rc;
120}
121
122int CodeUpdate::setRequestedActivation()
123{
124 int rc = PLDM_SUCCESS;
125 pldm::utils::PropertyValue value =
126 "xyz.openbmc_project.Software.Activation.RequestedActivations.Active";
127 DBusMapping dbusMapping;
128 dbusMapping.objectPath = newImageId;
129 dbusMapping.interface = "xyz.openbmc_project.Software.Activation";
130 dbusMapping.propertyName = "RequestedActivation";
131 dbusMapping.propertyType = "string";
132 try
133 {
134 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
135 }
136 catch (const std::exception& e)
137 {
138 std::cerr << "Failed To set RequestedActivation property"
139 << "ERROR=" << e.what() << std::endl;
140 rc = PLDM_ERROR;
141 }
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500142 return rc;
143}
144
Sampa Misraaea5dde2020-08-31 08:33:47 -0500145void CodeUpdate::setVersions()
146{
147 static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
148 static constexpr auto functionalObjPath =
149 "/xyz/openbmc_project/software/functional";
150 static constexpr auto activeObjPath =
151 "/xyz/openbmc_project/software/active";
152 static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
153
154 auto& bus = dBusIntf->getBus();
Sampa Misraaea5dde2020-08-31 08:33:47 -0500155 try
156 {
157 auto method = bus.new_method_call(mapperService, functionalObjPath,
158 propIntf, "Get");
159 method.append("xyz.openbmc_project.Association", "endpoints");
160 std::variant<std::vector<std::string>> paths;
161
162 auto reply = bus.call(method);
163 reply.read(paths);
164
165 runningVersion = std::get<std::vector<std::string>>(paths)[0];
166
167 auto method1 =
168 bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
169 method1.append("xyz.openbmc_project.Association", "endpoints");
170
171 auto reply1 = bus.call(method1);
172 reply1.read(paths);
173 for (const auto& path : std::get<std::vector<std::string>>(paths))
174 {
175 if (path != runningVersion)
176 {
177 nonRunningVersion = path;
178 break;
179 }
180 }
181 }
182 catch (const std::exception& e)
183 {
184 std::cerr << "failed to make a d-bus call to Object Mapper "
185 "Association, ERROR="
186 << e.what() << "\n";
187 return;
188 }
189
190 using namespace sdbusplus::bus::match::rules;
191 captureNextBootSideChange.push_back(
Patrick Williams84b790c2022-07-22 19:26:56 -0500192 std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500193 pldm::utils::DBusHandler::getBus(),
194 propertiesChanged(runningVersion, redundancyIntf),
Patrick Williams84b790c2022-07-22 19:26:56 -0500195 [this](sdbusplus::message_t& msg) {
Sampa Misraaea5dde2020-08-31 08:33:47 -0500196 DbusChangedProps props;
197 std::string iface;
198 msg.read(iface, props);
199 processPriorityChangeNotification(props);
200 }));
Patrick Williams84b790c2022-07-22 19:26:56 -0500201 fwUpdateMatcher.push_back(std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500202 pldm::utils::DBusHandler::getBus(),
203 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
204 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
Patrick Williams84b790c2022-07-22 19:26:56 -0500205 [this](sdbusplus::message_t& msg) {
Sampa Misraaea5dde2020-08-31 08:33:47 -0500206 DBusInterfaceAdded interfaces;
207 sdbusplus::message::object_path path;
208 msg.read(path, interfaces);
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600209
Sampa Misraaea5dde2020-08-31 08:33:47 -0500210 for (auto& interface : interfaces)
211 {
212 if (interface.first ==
213 "xyz.openbmc_project.Software.Activation")
214 {
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500215 auto imageInterface =
216 "xyz.openbmc_project.Software.Activation";
217 auto imageObjPath = path.str.c_str();
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600218
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500219 try
220 {
221 auto propVal = dBusIntf->getDbusPropertyVariant(
222 imageObjPath, "Activation", imageInterface);
223 const auto& imageProp = std::get<std::string>(propVal);
224 if (imageProp == "xyz.openbmc_project.Software."
225 "Activation.Activations.Ready" &&
226 isCodeUpdateInProgress())
227 {
228 newImageId = path.str;
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600229 if (!imageActivationMatch)
230 {
231 imageActivationMatch = std::make_unique<
Patrick Williams84b790c2022-07-22 19:26:56 -0500232 sdbusplus::bus::match_t>(
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600233 pldm::utils::DBusHandler::getBus(),
234 propertiesChanged(newImageId,
235 "xyz.openbmc_project."
236 "Software.Activation"),
Patrick Williams84b790c2022-07-22 19:26:56 -0500237 [this](sdbusplus::message_t& msg) {
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600238 DbusChangedProps props;
239 std::string iface;
240 msg.read(iface, props);
241 const auto itr =
242 props.find("Activation");
243 if (itr != props.end())
244 {
245 PropertyValue value = itr->second;
246 auto propVal =
247 std::get<std::string>(value);
248 if (propVal ==
249 "xyz.openbmc_project.Software."
250 "Activation.Activations.Active")
251 {
252 CodeUpdateState state =
253 CodeUpdateState::END;
254 setCodeUpdateProgress(false);
255 auto sensorId =
256 getFirmwareUpdateSensor();
257 sendStateSensorEvent(
258 sensorId,
259 PLDM_STATE_SENSOR_STATE, 0,
260 uint8_t(state),
261 uint8_t(CodeUpdateState::
262 START));
263 newImageId.clear();
264 }
265 else if (propVal ==
266 "xyz.openbmc_project."
267 "Software.Activation."
268 "Activations.Failed" ||
269 propVal ==
270 "xyz.openbmc_"
271 "project.Software."
272 "Activation."
273 "Activations."
274 "Invalid")
275 {
276 CodeUpdateState state =
277 CodeUpdateState::FAIL;
278 setCodeUpdateProgress(false);
279 auto sensorId =
280 getFirmwareUpdateSensor();
281 sendStateSensorEvent(
282 sensorId,
283 PLDM_STATE_SENSOR_STATE, 0,
284 uint8_t(state),
285 uint8_t(CodeUpdateState::
286 START));
287 newImageId.clear();
288 }
289 }
290 });
291 }
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500292 auto rc = setRequestedActivation();
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500293 if (rc != PLDM_SUCCESS)
294 {
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600295 CodeUpdateState state = CodeUpdateState::FAIL;
296 setCodeUpdateProgress(false);
297 auto sensorId = getFirmwareUpdateSensor();
298 sendStateSensorEvent(
299 sensorId, PLDM_STATE_SENSOR_STATE, 0,
300 uint8_t(state),
301 uint8_t(CodeUpdateState::START));
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500302 std::cerr
303 << "could not set RequestedActivation \n";
304 }
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500305 break;
306 }
307 }
Patrick Williams84b790c2022-07-22 19:26:56 -0500308 catch (const sdbusplus::exception_t& e)
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500309 {
310 std::cerr << "Error in getting Activation status \n";
311 }
Sampa Misraaea5dde2020-08-31 08:33:47 -0500312 }
313 }
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600314 }));
Sampa Misraaea5dde2020-08-31 08:33:47 -0500315}
316
317void CodeUpdate::processPriorityChangeNotification(
318 const DbusChangedProps& chProperties)
319{
320 static constexpr auto propName = "Priority";
321 const auto it = chProperties.find(propName);
322 if (it == chProperties.end())
323 {
324 return;
325 }
326 uint8_t newVal = std::get<uint8_t>(it->second);
327 nextBootSide = (newVal == 0) ? currBootSide
328 : ((currBootSide == Tside) ? Pside : Tside);
329}
330
331void CodeUpdate::setOemPlatformHandler(
332 pldm::responder::oem_platform::Handler* handler)
333{
334 oemPlatformHandler = handler;
335}
336
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500337void CodeUpdate::clearDirPath(const std::string& dirPath)
338{
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530339 if (!fs::is_directory(dirPath))
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500340 {
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530341 std::cerr << "The directory does not exist, dirPath = " << dirPath
342 << std::endl;
343 return;
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500344 }
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530345 for (const auto& iter : fs::directory_iterator(dirPath))
346 {
347 fs::remove_all(iter);
348 }
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500349}
350
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500351void CodeUpdate::sendStateSensorEvent(
352 uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
353 uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
354{
355 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
356 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
357 oemPlatformHandler);
358 oemIbmPlatformHandler->sendStateSensorEvent(
359 sensorId, sensorEventClass, sensorOffset, eventState, prevEventState);
360}
361
362void CodeUpdate::deleteImage()
363{
364 static constexpr auto UPDATER_SERVICE =
365 "xyz.openbmc_project.Software.BMC.Updater";
366 static constexpr auto SW_OBJ_PATH = "/xyz/openbmc_project/software";
367 static constexpr auto DELETE_INTF =
368 "xyz.openbmc_project.Collection.DeleteAll";
369
370 auto& bus = dBusIntf->getBus();
371 try
372 {
373 auto method = bus.new_method_call(UPDATER_SERVICE, SW_OBJ_PATH,
374 DELETE_INTF, "DeleteAll");
375 bus.call_noreply(method);
376 }
377 catch (const std::exception& e)
378 {
379 std::cerr << "Failed to delete image, ERROR=" << e.what() << "\n";
380 return;
381 }
382}
383
Sampa Misraaea5dde2020-08-31 08:33:47 -0500384uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
385{
386 uint8_t sensorOpState = tSideNum;
Sampa Misraaea5dde2020-08-31 08:33:47 -0500387 if (entityInstance == 0)
388 {
389 auto currSide = codeUpdate->fetchCurrentBootSide();
390 if (currSide == Pside)
391 {
392 sensorOpState = pSideNum;
393 }
394 }
395 else if (entityInstance == 1)
396 {
397 auto nextSide = codeUpdate->fetchNextBootSide();
398 if (nextSide == Pside)
399 {
400 sensorOpState = pSideNum;
401 }
402 }
403 else
404 {
405 sensorOpState = PLDM_SENSOR_UNKNOWN;
406 }
407
408 return sensorOpState;
409}
410
411int setBootSide(uint16_t entityInstance, uint8_t currState,
412 const std::vector<set_effecter_state_field>& stateField,
413 CodeUpdate* codeUpdate)
414{
415 int rc = PLDM_SUCCESS;
416 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
417
418 if (entityInstance == 0)
419 {
420 rc = codeUpdate->setCurrentBootSide(side);
421 }
422 else if (entityInstance == 1)
423 {
424 rc = codeUpdate->setNextBootSide(side);
425 }
426 else
427 {
428 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
429 }
430 return rc;
431}
432
Adriana Kobylak837fb472020-10-16 16:53:42 -0500433template <typename... T>
434int executeCmd(T const&... t)
435{
436 std::stringstream cmd;
437 ((cmd << t << " "), ...) << std::endl;
438 FILE* pipe = popen(cmd.str().c_str(), "r");
439 if (!pipe)
440 {
441 throw std::runtime_error("popen() failed!");
442 }
443 int rc = pclose(pipe);
444 if (WEXITSTATUS(rc))
445 {
446 std::cerr << "Error executing: ";
447 ((std::cerr << " " << t), ...);
448 std::cerr << "\n";
449 return -1;
450 }
451
452 return 0;
453}
454
Adriana Kobylak727f7382020-09-01 14:38:25 -0500455int processCodeUpdateLid(const std::string& filePath)
456{
457 struct LidHeader
458 {
459 uint16_t magicNumber;
Adriana Kobylak86d14182020-10-16 16:11:08 -0500460 uint16_t headerVersion;
461 uint32_t lidNumber;
462 uint32_t lidDate;
463 uint16_t lidTime;
464 uint16_t lidClass;
465 uint32_t lidCrc;
466 uint32_t lidSize;
467 uint32_t headerSize;
Adriana Kobylak727f7382020-09-01 14:38:25 -0500468 };
469 LidHeader header;
470
471 std::ifstream ifs(filePath, std::ios::in | std::ios::binary);
472 if (!ifs)
473 {
474 std::cerr << "ifstream open error: " << filePath << "\n";
475 return PLDM_ERROR;
476 }
477 ifs.seekg(0);
478 ifs.read(reinterpret_cast<char*>(&header), sizeof(header));
Adriana Kobylak727f7382020-09-01 14:38:25 -0500479
Adriana Kobylak86d14182020-10-16 16:11:08 -0500480 // File size should be the value of lid size minus the header size
481 auto fileSize = fs::file_size(filePath);
482 fileSize -= htonl(header.headerSize);
483 if (fileSize < htonl(header.lidSize))
484 {
485 // File is not completely written yet
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500486 ifs.close();
Adriana Kobylak86d14182020-10-16 16:11:08 -0500487 return PLDM_SUCCESS;
488 }
489
Adriana Kobylak727f7382020-09-01 14:38:25 -0500490 constexpr auto magicNumber = 0x0222;
491 if (htons(header.magicNumber) != magicNumber)
492 {
493 std::cerr << "Invalid magic number: " << filePath << "\n";
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500494 ifs.close();
Adriana Kobylak727f7382020-09-01 14:38:25 -0500495 return PLDM_ERROR;
496 }
497
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600498 fs::create_directories(imageDirPath);
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500499 fs::create_directories(lidDirPath);
500
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600501 constexpr auto bmcClass = 0x2000;
502 if (htons(header.lidClass) == bmcClass)
503 {
504 // Skip the header and concatenate the BMC LIDs into a tar file
505 std::ofstream ofs(tarImagePath,
506 std::ios::out | std::ios::binary | std::ios::app);
507 ifs.seekg(htonl(header.headerSize));
508 ofs << ifs.rdbuf();
509 ofs.flush();
510 ofs.close();
511 }
512 else
513 {
514 std::stringstream lidFileName;
515 lidFileName << std::hex << htonl(header.lidNumber) << ".lid";
516 auto lidNoHeaderPath = fs::path(lidDirPath) / lidFileName.str();
517 std::ofstream ofs(lidNoHeaderPath,
518 std::ios::out | std::ios::binary | std::ios::trunc);
519 ifs.seekg(htonl(header.headerSize));
520 ofs << ifs.rdbuf();
521 ofs.flush();
522 ofs.close();
523 }
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500524
525 ifs.close();
526 fs::remove(filePath);
Adriana Kobylak727f7382020-09-01 14:38:25 -0500527 return PLDM_SUCCESS;
528}
529
Adriana Kobylak9296f242021-09-22 15:52:00 +0000530int CodeUpdate::assembleCodeUpdateImage()
Adriana Kobylak837fb472020-10-16 16:53:42 -0500531{
Adriana Kobylak9296f242021-09-22 15:52:00 +0000532 pid_t pid = fork();
533
534 if (pid == 0)
Adriana Kobylak837fb472020-10-16 16:53:42 -0500535 {
Adriana Kobylak9296f242021-09-22 15:52:00 +0000536 pid_t nextPid = fork();
537 if (nextPid == 0)
538 {
539 // Create the hostfw squashfs image from the LID files without
540 // header
541 auto rc = executeCmd("/usr/sbin/mksquashfs", lidDirPath.c_str(),
542 hostfwImagePath.c_str(), "-all-root",
543 "-no-recovery");
544 if (rc < 0)
545 {
546 std::cerr << "Error occurred during the mksqusquashfs call"
547 << std::endl;
548 setCodeUpdateProgress(false);
549 auto sensorId = getFirmwareUpdateSensor();
550 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
551 uint8_t(CodeUpdateState::FAIL),
552 uint8_t(CodeUpdateState::START));
553 exit(EXIT_FAILURE);
554 }
555
556 fs::create_directories(updateDirPath);
557
558 // Extract the BMC tarball content
559 rc = executeCmd("/bin/tar", "-xf", tarImagePath.c_str(), "-C",
560 updateDirPath);
561 if (rc < 0)
562 {
563 setCodeUpdateProgress(false);
564 auto sensorId = getFirmwareUpdateSensor();
565 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
566 uint8_t(CodeUpdateState::FAIL),
567 uint8_t(CodeUpdateState::START));
568 exit(EXIT_FAILURE);
569 }
570
571 // Add the hostfw image to the directory where the contents were
572 // extracted
573 fs::copy_file(hostfwImagePath,
574 fs::path(updateDirPath) / hostfwImageName,
575 fs::copy_options::overwrite_existing);
576
577 // Remove the tarball file, then re-generate it with so that the
578 // hostfw image becomes part of the tarball
579 fs::remove(tarImagePath);
580 rc = executeCmd("/bin/tar", "-cf", tarImagePath, ".", "-C",
581 updateDirPath);
582 if (rc < 0)
583 {
584 std::cerr
585 << "Error occurred during the generation of the tarball"
586 << std::endl;
587 setCodeUpdateProgress(false);
588 auto sensorId = getFirmwareUpdateSensor();
589 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
590 uint8_t(CodeUpdateState::FAIL),
591 uint8_t(CodeUpdateState::START));
592 exit(EXIT_FAILURE);
593 }
594
595 // Copy the tarball to the update directory to trigger the phosphor
596 // software manager to create a version interface
597 fs::copy_file(tarImagePath, updateImagePath,
598 fs::copy_options::overwrite_existing);
599
600 // Cleanup
601 fs::remove_all(updateDirPath);
602 fs::remove_all(lidDirPath);
603 fs::remove_all(imageDirPath);
604
605 exit(EXIT_SUCCESS);
606 }
607 else if (nextPid < 0)
608 {
609 std::cerr << "Error occurred during fork. ERROR=" << errno
610 << std::endl;
611 exit(EXIT_FAILURE);
612 }
613
614 // Do nothing as parent. When parent exits, child will be reparented
615 // under init and be reaped properly.
616 exit(0);
617 }
618 else if (pid > 0)
619 {
620 int status;
621 if (waitpid(pid, &status, 0) < 0)
622 {
623 std::cerr << "Error occurred during waitpid. ERROR=" << errno
624 << std::endl;
625 return PLDM_ERROR;
626 }
627 else if (WEXITSTATUS(status) != 0)
628 {
629 std::cerr
630 << "Failed to execute the assembling of the image. STATUS="
631 << status << std::endl;
632 return PLDM_ERROR;
633 }
634 }
635 else
636 {
637 std::cerr << "Error occurred during fork. ERROR=" << errno << std::endl;
Adriana Kobylak837fb472020-10-16 16:53:42 -0500638 return PLDM_ERROR;
639 }
640
Adriana Kobylak837fb472020-10-16 16:53:42 -0500641 return PLDM_SUCCESS;
642}
643
Sampa Misraaea5dde2020-08-31 08:33:47 -0500644} // namespace responder
645} // namespace pldm