blob: c69c1bcfa04019f4bf412aa728653ed72b4f9793 [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
167 auto reply = bus.call(method);
168 reply.read(paths);
169
170 runningVersion = std::get<std::vector<std::string>>(paths)[0];
171
Patrick Williams6da4f912023-05-10 07:50:53 -0500172 auto method1 = bus.new_method_call(mapperService, activeObjPath,
173 propIntf, "Get");
Sampa Misraaea5dde2020-08-31 08:33:47 -0500174 method1.append("xyz.openbmc_project.Association", "endpoints");
175
176 auto reply1 = bus.call(method1);
177 reply1.read(paths);
178 for (const auto& path : std::get<std::vector<std::string>>(paths))
179 {
180 if (path != runningVersion)
181 {
182 nonRunningVersion = path;
183 break;
184 }
185 }
186 }
187 catch (const std::exception& e)
188 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600189 error(
190 "failed to make a d-bus call to Object Mapper Association, ERROR={ERR_EXCEP}",
191 "ERR_EXCEP", e.what());
Sampa Misraaea5dde2020-08-31 08:33:47 -0500192 return;
193 }
194
195 using namespace sdbusplus::bus::match::rules;
196 captureNextBootSideChange.push_back(
Patrick Williams84b790c2022-07-22 19:26:56 -0500197 std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500198 pldm::utils::DBusHandler::getBus(),
199 propertiesChanged(runningVersion, redundancyIntf),
Patrick Williams84b790c2022-07-22 19:26:56 -0500200 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500201 DbusChangedProps props;
202 std::string iface;
203 msg.read(iface, props);
204 processPriorityChangeNotification(props);
Sampa Misraaea5dde2020-08-31 08:33:47 -0500205 }));
Patrick Williams84b790c2022-07-22 19:26:56 -0500206 fwUpdateMatcher.push_back(std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500207 pldm::utils::DBusHandler::getBus(),
208 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
209 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
Patrick Williams84b790c2022-07-22 19:26:56 -0500210 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500211 DBusInterfaceAdded interfaces;
212 sdbusplus::message::object_path path;
213 msg.read(path, interfaces);
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600214
Patrick Williams6da4f912023-05-10 07:50:53 -0500215 for (auto& interface : interfaces)
216 {
217 if (interface.first == "xyz.openbmc_project.Software.Activation")
Sampa Misraaea5dde2020-08-31 08:33:47 -0500218 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500219 auto imageInterface = "xyz.openbmc_project.Software.Activation";
220 auto imageObjPath = path.str.c_str();
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600221
Patrick Williams6da4f912023-05-10 07:50:53 -0500222 try
223 {
224 auto propVal = dBusIntf->getDbusPropertyVariant(
225 imageObjPath, "Activation", imageInterface);
226 const auto& imageProp = std::get<std::string>(propVal);
227 if (imageProp == "xyz.openbmc_project.Software."
228 "Activation.Activations.Ready" &&
229 isCodeUpdateInProgress())
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500230 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500231 newImageId = path.str;
232 if (!imageActivationMatch)
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500233 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500234 imageActivationMatch =
235 std::make_unique<sdbusplus::bus::match_t>(
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600236 pldm::utils::DBusHandler::getBus(),
237 propertiesChanged(newImageId,
238 "xyz.openbmc_project."
239 "Software.Activation"),
Patrick Williams84b790c2022-07-22 19:26:56 -0500240 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500241 DbusChangedProps props;
242 std::string iface;
243 msg.read(iface, props);
244 const auto itr = props.find("Activation");
245 if (itr != props.end())
246 {
247 PropertyValue value = itr->second;
248 auto propVal = std::get<std::string>(value);
249 if (propVal ==
250 "xyz.openbmc_project.Software."
251 "Activation.Activations.Active")
252 {
253 CodeUpdateState state =
254 CodeUpdateState::END;
255 setCodeUpdateProgress(false);
256 auto sensorId =
257 getFirmwareUpdateSensor();
258 sendStateSensorEvent(
259 sensorId, PLDM_STATE_SENSOR_STATE,
260 0, uint8_t(state),
261 uint8_t(CodeUpdateState::START));
262 newImageId.clear();
263 }
264 else if (propVal == "xyz.openbmc_project."
265 "Software.Activation."
266 "Activations.Failed" ||
267 propVal == "xyz.openbmc_"
268 "project.Software."
269 "Activation."
270 "Activations."
271 "Invalid")
272 {
273 CodeUpdateState state =
274 CodeUpdateState::FAIL;
275 setCodeUpdateProgress(false);
276 auto sensorId =
277 getFirmwareUpdateSensor();
278 sendStateSensorEvent(
279 sensorId, PLDM_STATE_SENSOR_STATE,
280 0, uint8_t(state),
281 uint8_t(CodeUpdateState::START));
282 newImageId.clear();
283 }
284 }
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600285 });
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500286 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500287 auto rc = setRequestedActivation();
288 if (rc != PLDM_SUCCESS)
289 {
290 CodeUpdateState state = CodeUpdateState::FAIL;
291 setCodeUpdateProgress(false);
292 auto sensorId = getFirmwareUpdateSensor();
293 sendStateSensorEvent(
294 sensorId, PLDM_STATE_SENSOR_STATE, 0,
295 uint8_t(state),
296 uint8_t(CodeUpdateState::START));
297 error("could not set RequestedActivation");
298 }
299 break;
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500300 }
Sampa Misraaea5dde2020-08-31 08:33:47 -0500301 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500302 catch (const sdbusplus::exception_t& e)
303 {
304 error(
305 "Error in getting Activation status,ERROR= {ERR_EXCEP}, INTERFACE={IMG_INTERFACE}, OBJECT PATH={OBJ_PATH}",
306 "ERR_EXCEP", e.what(), "IMG_INTERFACE", imageInterface,
307 "OBJ_PATH", imageObjPath);
308 }
Sampa Misraaea5dde2020-08-31 08:33:47 -0500309 }
Patrick Williams6da4f912023-05-10 07:50:53 -0500310 }
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600311 }));
Sampa Misraaea5dde2020-08-31 08:33:47 -0500312}
313
314void CodeUpdate::processPriorityChangeNotification(
315 const DbusChangedProps& chProperties)
316{
317 static constexpr auto propName = "Priority";
318 const auto it = chProperties.find(propName);
319 if (it == chProperties.end())
320 {
321 return;
322 }
323 uint8_t newVal = std::get<uint8_t>(it->second);
324 nextBootSide = (newVal == 0) ? currBootSide
325 : ((currBootSide == Tside) ? Pside : Tside);
326}
327
328void CodeUpdate::setOemPlatformHandler(
329 pldm::responder::oem_platform::Handler* handler)
330{
331 oemPlatformHandler = handler;
332}
333
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500334void CodeUpdate::clearDirPath(const std::string& dirPath)
335{
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530336 if (!fs::is_directory(dirPath))
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500337 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600338 error("The directory does not exist, dirPath = {DIR_PATH}", "DIR_PATH",
339 dirPath.c_str());
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530340 return;
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500341 }
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530342 for (const auto& iter : fs::directory_iterator(dirPath))
343 {
344 fs::remove_all(iter);
345 }
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500346}
347
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500348void CodeUpdate::sendStateSensorEvent(
349 uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
350 uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
351{
352 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
353 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
354 oemPlatformHandler);
355 oemIbmPlatformHandler->sendStateSensorEvent(
356 sensorId, sensorEventClass, sensorOffset, eventState, prevEventState);
357}
358
359void CodeUpdate::deleteImage()
360{
361 static constexpr auto UPDATER_SERVICE =
362 "xyz.openbmc_project.Software.BMC.Updater";
363 static constexpr auto SW_OBJ_PATH = "/xyz/openbmc_project/software";
364 static constexpr auto DELETE_INTF =
365 "xyz.openbmc_project.Collection.DeleteAll";
366
367 auto& bus = dBusIntf->getBus();
368 try
369 {
370 auto method = bus.new_method_call(UPDATER_SERVICE, SW_OBJ_PATH,
371 DELETE_INTF, "DeleteAll");
372 bus.call_noreply(method);
373 }
374 catch (const std::exception& e)
375 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600376 error("Failed to delete image, ERROR={ERR_EXCEP}", "ERR_EXCEP",
377 e.what());
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500378 return;
379 }
380}
381
Sampa Misraaea5dde2020-08-31 08:33:47 -0500382uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
383{
384 uint8_t sensorOpState = tSideNum;
Sampa Misraaea5dde2020-08-31 08:33:47 -0500385 if (entityInstance == 0)
386 {
387 auto currSide = codeUpdate->fetchCurrentBootSide();
388 if (currSide == Pside)
389 {
390 sensorOpState = pSideNum;
391 }
392 }
393 else if (entityInstance == 1)
394 {
395 auto nextSide = codeUpdate->fetchNextBootSide();
396 if (nextSide == Pside)
397 {
398 sensorOpState = pSideNum;
399 }
400 }
401 else
402 {
403 sensorOpState = PLDM_SENSOR_UNKNOWN;
404 }
405
406 return sensorOpState;
407}
408
409int setBootSide(uint16_t entityInstance, uint8_t currState,
410 const std::vector<set_effecter_state_field>& stateField,
411 CodeUpdate* codeUpdate)
412{
413 int rc = PLDM_SUCCESS;
414 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
415
416 if (entityInstance == 0)
417 {
418 rc = codeUpdate->setCurrentBootSide(side);
419 }
420 else if (entityInstance == 1)
421 {
422 rc = codeUpdate->setNextBootSide(side);
423 }
424 else
425 {
426 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
427 }
428 return rc;
429}
430
Adriana Kobylak837fb472020-10-16 16:53:42 -0500431template <typename... T>
Patrick Williams6da4f912023-05-10 07:50:53 -0500432int executeCmd(const T&... t)
Adriana Kobylak837fb472020-10-16 16:53:42 -0500433{
434 std::stringstream cmd;
435 ((cmd << t << " "), ...) << std::endl;
436 FILE* pipe = popen(cmd.str().c_str(), "r");
437 if (!pipe)
438 {
439 throw std::runtime_error("popen() failed!");
440 }
441 int rc = pclose(pipe);
442 if (WEXITSTATUS(rc))
443 {
444 std::cerr << "Error executing: ";
445 ((std::cerr << " " << t), ...);
446 std::cerr << "\n";
447 return -1;
448 }
449
450 return 0;
451}
452
Adriana Kobylak727f7382020-09-01 14:38:25 -0500453int processCodeUpdateLid(const std::string& filePath)
454{
455 struct LidHeader
456 {
457 uint16_t magicNumber;
Adriana Kobylak86d14182020-10-16 16:11:08 -0500458 uint16_t headerVersion;
459 uint32_t lidNumber;
460 uint32_t lidDate;
461 uint16_t lidTime;
462 uint16_t lidClass;
463 uint32_t lidCrc;
464 uint32_t lidSize;
465 uint32_t headerSize;
Adriana Kobylak727f7382020-09-01 14:38:25 -0500466 };
467 LidHeader header;
468
469 std::ifstream ifs(filePath, std::ios::in | std::ios::binary);
470 if (!ifs)
471 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600472 error("ifstream open error: {DIR_PATH}", "DIR_PATH", filePath.c_str());
Adriana Kobylak727f7382020-09-01 14:38:25 -0500473 return PLDM_ERROR;
474 }
475 ifs.seekg(0);
476 ifs.read(reinterpret_cast<char*>(&header), sizeof(header));
Adriana Kobylak727f7382020-09-01 14:38:25 -0500477
Adriana Kobylak86d14182020-10-16 16:11:08 -0500478 // File size should be the value of lid size minus the header size
479 auto fileSize = fs::file_size(filePath);
480 fileSize -= htonl(header.headerSize);
481 if (fileSize < htonl(header.lidSize))
482 {
483 // File is not completely written yet
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500484 ifs.close();
Adriana Kobylak86d14182020-10-16 16:11:08 -0500485 return PLDM_SUCCESS;
486 }
487
Adriana Kobylak727f7382020-09-01 14:38:25 -0500488 constexpr auto magicNumber = 0x0222;
489 if (htons(header.magicNumber) != magicNumber)
490 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600491 error("Invalid magic number: {DIR_PATH}", "DIR_PATH", filePath.c_str());
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500492 ifs.close();
Adriana Kobylak727f7382020-09-01 14:38:25 -0500493 return PLDM_ERROR;
494 }
495
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600496 fs::create_directories(imageDirPath);
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500497 fs::create_directories(lidDirPath);
498
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600499 constexpr auto bmcClass = 0x2000;
500 if (htons(header.lidClass) == bmcClass)
501 {
502 // Skip the header and concatenate the BMC LIDs into a tar file
503 std::ofstream ofs(tarImagePath,
504 std::ios::out | std::ios::binary | std::ios::app);
505 ifs.seekg(htonl(header.headerSize));
506 ofs << ifs.rdbuf();
507 ofs.flush();
508 ofs.close();
509 }
510 else
511 {
512 std::stringstream lidFileName;
513 lidFileName << std::hex << htonl(header.lidNumber) << ".lid";
514 auto lidNoHeaderPath = fs::path(lidDirPath) / lidFileName.str();
515 std::ofstream ofs(lidNoHeaderPath,
516 std::ios::out | std::ios::binary | std::ios::trunc);
517 ifs.seekg(htonl(header.headerSize));
518 ofs << ifs.rdbuf();
519 ofs.flush();
520 ofs.close();
521 }
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500522
523 ifs.close();
524 fs::remove(filePath);
Adriana Kobylak727f7382020-09-01 14:38:25 -0500525 return PLDM_SUCCESS;
526}
527
Adriana Kobylak9296f242021-09-22 15:52:00 +0000528int CodeUpdate::assembleCodeUpdateImage()
Adriana Kobylak837fb472020-10-16 16:53:42 -0500529{
Adriana Kobylak9296f242021-09-22 15:52:00 +0000530 pid_t pid = fork();
531
532 if (pid == 0)
Adriana Kobylak837fb472020-10-16 16:53:42 -0500533 {
Adriana Kobylak9296f242021-09-22 15:52:00 +0000534 pid_t nextPid = fork();
535 if (nextPid == 0)
536 {
537 // Create the hostfw squashfs image from the LID files without
538 // header
539 auto rc = executeCmd("/usr/sbin/mksquashfs", lidDirPath.c_str(),
540 hostfwImagePath.c_str(), "-all-root",
541 "-no-recovery");
542 if (rc < 0)
543 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600544 error("Error occurred during the mksqusquashfs call");
Adriana Kobylak9296f242021-09-22 15:52:00 +0000545 setCodeUpdateProgress(false);
546 auto sensorId = getFirmwareUpdateSensor();
547 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
548 uint8_t(CodeUpdateState::FAIL),
549 uint8_t(CodeUpdateState::START));
550 exit(EXIT_FAILURE);
551 }
552
553 fs::create_directories(updateDirPath);
554
555 // Extract the BMC tarball content
556 rc = executeCmd("/bin/tar", "-xf", tarImagePath.c_str(), "-C",
557 updateDirPath);
558 if (rc < 0)
559 {
560 setCodeUpdateProgress(false);
561 auto sensorId = getFirmwareUpdateSensor();
562 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
563 uint8_t(CodeUpdateState::FAIL),
564 uint8_t(CodeUpdateState::START));
565 exit(EXIT_FAILURE);
566 }
567
568 // Add the hostfw image to the directory where the contents were
569 // extracted
570 fs::copy_file(hostfwImagePath,
571 fs::path(updateDirPath) / hostfwImageName,
572 fs::copy_options::overwrite_existing);
573
574 // Remove the tarball file, then re-generate it with so that the
575 // hostfw image becomes part of the tarball
576 fs::remove(tarImagePath);
577 rc = executeCmd("/bin/tar", "-cf", tarImagePath, ".", "-C",
578 updateDirPath);
579 if (rc < 0)
580 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600581 error("Error occurred during the generation of the tarball");
Adriana Kobylak9296f242021-09-22 15:52:00 +0000582 setCodeUpdateProgress(false);
583 auto sensorId = getFirmwareUpdateSensor();
584 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
585 uint8_t(CodeUpdateState::FAIL),
586 uint8_t(CodeUpdateState::START));
587 exit(EXIT_FAILURE);
588 }
589
590 // Copy the tarball to the update directory to trigger the phosphor
591 // software manager to create a version interface
592 fs::copy_file(tarImagePath, updateImagePath,
593 fs::copy_options::overwrite_existing);
594
595 // Cleanup
596 fs::remove_all(updateDirPath);
597 fs::remove_all(lidDirPath);
598 fs::remove_all(imageDirPath);
599
600 exit(EXIT_SUCCESS);
601 }
602 else if (nextPid < 0)
603 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600604 error("Error occurred during fork. ERROR={ERR}", "ERR", errno);
Adriana Kobylak9296f242021-09-22 15:52:00 +0000605 exit(EXIT_FAILURE);
606 }
607
608 // Do nothing as parent. When parent exits, child will be reparented
609 // under init and be reaped properly.
610 exit(0);
611 }
612 else if (pid > 0)
613 {
614 int status;
615 if (waitpid(pid, &status, 0) < 0)
616 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600617 error("Error occurred during waitpid. ERROR={ERR}", "ERR", errno);
618
Adriana Kobylak9296f242021-09-22 15:52:00 +0000619 return PLDM_ERROR;
620 }
621 else if (WEXITSTATUS(status) != 0)
622 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600623 error(
624 "Failed to execute the assembling of the image. STATUS={IMG_STATUS}",
625 "IMG_STATUS", status);
Adriana Kobylak9296f242021-09-22 15:52:00 +0000626 return PLDM_ERROR;
627 }
628 }
629 else
630 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600631 error("Error occurred during fork. ERROR={ERR}", "ERR", errno);
Adriana Kobylak837fb472020-10-16 16:53:42 -0500632 return PLDM_ERROR;
633 }
634
Adriana Kobylak837fb472020-10-16 16:53:42 -0500635 return PLDM_SUCCESS;
636}
637
Sampa Misraaea5dde2020-08-31 08:33:47 -0500638} // namespace responder
639} // namespace pldm