blob: 8acfe56accae7a40a72fd5f5f2836db7e85347a3 [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 Dixitfc84f632024-04-06 14:00:02 -050096 error("Failed to set the next boot side to {PATH} , error - {ERROR}",
97 "PATH", objPath, "ERROR", e);
Sampa Misraaea5dde2020-08-31 08:33:47 -050098 return PLDM_ERROR;
99 }
100 return PLDM_SUCCESS;
101}
102
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500103int CodeUpdate::setRequestedApplyTime()
104{
105 int rc = PLDM_SUCCESS;
106 pldm::utils::PropertyValue value =
107 "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.OnReset";
108 DBusMapping dbusMapping;
109 dbusMapping.objectPath = "/xyz/openbmc_project/software/apply_time";
110 dbusMapping.interface = "xyz.openbmc_project.Software.ApplyTime";
111 dbusMapping.propertyName = "RequestedApplyTime";
112 dbusMapping.propertyType = "string";
113 try
114 {
115 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
116 }
117 catch (const std::exception& e)
118 {
Sagar Srinivas90403472023-08-21 06:08:55 -0500119 error(
Riya Dixitfc84f632024-04-06 14:00:02 -0500120 "Failed to set property '{PROPERTY}' at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}",
121 "PATH", dbusMapping.objectPath, "INTERFACE", dbusMapping.interface,
122 "PROPERTY", dbusMapping.propertyName, "ERROR", e);
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500123 rc = PLDM_ERROR;
124 }
125 return rc;
126}
127
128int CodeUpdate::setRequestedActivation()
129{
130 int rc = PLDM_SUCCESS;
131 pldm::utils::PropertyValue value =
132 "xyz.openbmc_project.Software.Activation.RequestedActivations.Active";
133 DBusMapping dbusMapping;
134 dbusMapping.objectPath = newImageId;
135 dbusMapping.interface = "xyz.openbmc_project.Software.Activation";
136 dbusMapping.propertyName = "RequestedActivation";
137 dbusMapping.propertyType = "string";
138 try
139 {
140 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
141 }
142 catch (const std::exception& e)
143 {
Sagar Srinivas90403472023-08-21 06:08:55 -0500144 error(
Riya Dixitfc84f632024-04-06 14:00:02 -0500145 "Failed to set property {PROPERTY} at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}",
146 "PATH", dbusMapping.objectPath, "INTERFACE", dbusMapping.interface,
147 "PROPERTY", dbusMapping.propertyName, "ERROR", e);
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500148 rc = PLDM_ERROR;
149 }
Sagar Srinivascfdbca72020-09-22 10:03:35 -0500150 return rc;
151}
152
Sampa Misraaea5dde2020-08-31 08:33:47 -0500153void CodeUpdate::setVersions()
154{
155 static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
156 static constexpr auto functionalObjPath =
157 "/xyz/openbmc_project/software/functional";
158 static constexpr auto activeObjPath =
159 "/xyz/openbmc_project/software/active";
160 static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
161
162 auto& bus = dBusIntf->getBus();
Sampa Misraaea5dde2020-08-31 08:33:47 -0500163 try
164 {
165 auto method = bus.new_method_call(mapperService, functionalObjPath,
166 propIntf, "Get");
167 method.append("xyz.openbmc_project.Association", "endpoints");
168 std::variant<std::vector<std::string>> paths;
169
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500170 auto reply = bus.call(method, dbusTimeout);
Sampa Misraaea5dde2020-08-31 08:33:47 -0500171 reply.read(paths);
172
173 runningVersion = std::get<std::vector<std::string>>(paths)[0];
174
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400175 auto method1 =
176 bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
Sampa Misraaea5dde2020-08-31 08:33:47 -0500177 method1.append("xyz.openbmc_project.Association", "endpoints");
178
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500179 auto reply1 = bus.call(method1, dbusTimeout);
Sampa Misraaea5dde2020-08-31 08:33:47 -0500180 reply1.read(paths);
181 for (const auto& path : std::get<std::vector<std::string>>(paths))
182 {
183 if (path != runningVersion)
184 {
185 nonRunningVersion = path;
186 break;
187 }
188 }
189 }
190 catch (const std::exception& e)
191 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600192 error(
Riya Dixitfc84f632024-04-06 14:00:02 -0500193 "Failed to make a d-bus call to Object Mapper Association, error - {ERROR}",
194 "ERROR", e);
Sampa Misraaea5dde2020-08-31 08:33:47 -0500195 return;
196 }
197
198 using namespace sdbusplus::bus::match::rules;
199 captureNextBootSideChange.push_back(
Patrick Williams84b790c2022-07-22 19:26:56 -0500200 std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500201 pldm::utils::DBusHandler::getBus(),
202 propertiesChanged(runningVersion, redundancyIntf),
Patrick Williams84b790c2022-07-22 19:26:56 -0500203 [this](sdbusplus::message_t& msg) {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400204 DbusChangedProps props;
205 std::string iface;
206 msg.read(iface, props);
207 processPriorityChangeNotification(props);
208 }));
Patrick Williams84b790c2022-07-22 19:26:56 -0500209 fwUpdateMatcher.push_back(std::make_unique<sdbusplus::bus::match_t>(
Sampa Misraaea5dde2020-08-31 08:33:47 -0500210 pldm::utils::DBusHandler::getBus(),
211 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
212 "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
Patrick Williams84b790c2022-07-22 19:26:56 -0500213 [this](sdbusplus::message_t& msg) {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400214 DBusInterfaceAdded interfaces;
215 sdbusplus::message::object_path path;
216 msg.read(path, interfaces);
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600217
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400218 for (auto& interface : interfaces)
Sampa Misraaea5dde2020-08-31 08:33:47 -0500219 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400220 if (interface.first ==
221 "xyz.openbmc_project.Software.Activation")
Patrick Williams6da4f912023-05-10 07:50:53 -0500222 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400223 auto imageInterface =
224 "xyz.openbmc_project.Software.Activation";
225 auto imageObjPath = path.str.c_str();
226
227 try
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500228 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400229 auto propVal = dBusIntf->getDbusPropertyVariant(
230 imageObjPath, "Activation", imageInterface);
Archana Kakanic23b6142025-02-19 04:04:20 -0600231 if (isCodeUpdateInProgress())
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500232 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400233 newImageId = path.str;
234 if (!imageActivationMatch)
235 {
236 imageActivationMatch = std::make_unique<
237 sdbusplus::bus::match_t>(
Sagar Srinivas9a64b4a2021-02-09 07:55:38 -0600238 pldm::utils::DBusHandler::getBus(),
239 propertiesChanged(newImageId,
240 "xyz.openbmc_project."
241 "Software.Activation"),
Patrick Williams84b790c2022-07-22 19:26:56 -0500242 [this](sdbusplus::message_t& msg) {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400243 DbusChangedProps props;
244 std::string iface;
245 msg.read(iface, props);
246 const auto itr =
247 props.find("Activation");
248 if (itr != props.end())
249 {
250 PropertyValue value = itr->second;
251 auto propVal =
252 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,
264 PLDM_STATE_SENSOR_STATE, 0,
265 uint8_t(state),
266 uint8_t(CodeUpdateState::
267 START));
268 newImageId.clear();
269 }
270 else if (propVal ==
271 "xyz.openbmc_project."
272 "Software.Activation."
273 "Activations.Failed" ||
274 propVal ==
275 "xyz.openbmc_"
276 "project.Software."
277 "Activation."
278 "Activations."
279 "Invalid")
280 {
281 CodeUpdateState state =
282 CodeUpdateState::FAIL;
283 setCodeUpdateProgress(false);
284 auto sensorId =
285 getFirmwareUpdateSensor();
286 sendStateSensorEvent(
287 sensorId,
288 PLDM_STATE_SENSOR_STATE, 0,
289 uint8_t(state),
290 uint8_t(CodeUpdateState::
291 START));
292 newImageId.clear();
293 }
294 }
295 });
296 }
297 auto rc = setRequestedActivation();
298 if (rc != PLDM_SUCCESS)
299 {
300 error("Could not set Requested Activation");
301 CodeUpdateState state = CodeUpdateState::FAIL;
302 setCodeUpdateProgress(false);
303 auto sensorId = getFirmwareUpdateSensor();
304 sendStateSensorEvent(
305 sensorId, PLDM_STATE_SENSOR_STATE, 0,
306 uint8_t(state),
307 uint8_t(CodeUpdateState::START));
308 }
309 break;
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500310 }
Archana Kakanic23b6142025-02-19 04:04:20 -0600311 else
312 {
313 // Out of band update
314 processRenameEvent();
315 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400316 }
317 catch (const sdbusplus::exception_t& e)
318 {
319 error(
320 "Failed to get activation status for interface '{INTERFACE}' and object path '{PATH}', error - {ERROR}",
321 "ERROR", e, "INTERFACE", imageInterface, "PATH",
322 imageObjPath);
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500323 }
Sampa Misraaea5dde2020-08-31 08:33:47 -0500324 }
325 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400326 }));
Sampa Misraaea5dde2020-08-31 08:33:47 -0500327}
328
Archana Kakanic23b6142025-02-19 04:04:20 -0600329void CodeUpdate::processRenameEvent()
330{
331 currBootSide = Pside;
332 auto sensorId = getBootSideRenameStateSensor();
333 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
334 PLDM_OEM_IBM_BOOT_SIDE_RENAME_STATE_RENAMED,
335 PLDM_OEM_IBM_BOOT_SIDE_RENAME_STATE_NOT_RENAMED);
336}
337
Sampa Misraaea5dde2020-08-31 08:33:47 -0500338void CodeUpdate::processPriorityChangeNotification(
339 const DbusChangedProps& chProperties)
340{
341 static constexpr auto propName = "Priority";
342 const auto it = chProperties.find(propName);
343 if (it == chProperties.end())
344 {
345 return;
346 }
347 uint8_t newVal = std::get<uint8_t>(it->second);
348 nextBootSide = (newVal == 0) ? currBootSide
349 : ((currBootSide == Tside) ? Pside : Tside);
350}
351
352void CodeUpdate::setOemPlatformHandler(
353 pldm::responder::oem_platform::Handler* handler)
354{
355 oemPlatformHandler = handler;
356}
357
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500358void CodeUpdate::clearDirPath(const std::string& dirPath)
359{
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530360 if (!fs::is_directory(dirPath))
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500361 {
Riya Dixitfc84f632024-04-06 14:00:02 -0500362 error("The directory '{PATH}' does not exist", "PATH", dirPath);
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530363 return;
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500364 }
Manojkiran Eda78124cf2022-08-29 11:22:43 +0530365 for (const auto& iter : fs::directory_iterator(dirPath))
366 {
367 fs::remove_all(iter);
368 }
Varsha Kaverappa3ca29df2020-09-27 12:39:22 -0500369}
370
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500371void CodeUpdate::sendStateSensorEvent(
372 uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
373 uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
374{
375 pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
376 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
377 oemPlatformHandler);
378 oemIbmPlatformHandler->sendStateSensorEvent(
379 sensorId, sensorEventClass, sensorOffset, eventState, prevEventState);
380}
381
382void CodeUpdate::deleteImage()
383{
384 static constexpr auto UPDATER_SERVICE =
385 "xyz.openbmc_project.Software.BMC.Updater";
386 static constexpr auto SW_OBJ_PATH = "/xyz/openbmc_project/software";
387 static constexpr auto DELETE_INTF =
388 "xyz.openbmc_project.Collection.DeleteAll";
389
390 auto& bus = dBusIntf->getBus();
391 try
392 {
393 auto method = bus.new_method_call(UPDATER_SERVICE, SW_OBJ_PATH,
394 DELETE_INTF, "DeleteAll");
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000395 bus.call_noreply(method, dbusTimeout);
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500396 }
397 catch (const std::exception& e)
398 {
Sagar Srinivas90403472023-08-21 06:08:55 -0500399 error(
Riya Dixitfc84f632024-04-06 14:00:02 -0500400 "Failed to delete image at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}",
401 "PATH", SW_OBJ_PATH, "INTERFACE", DELETE_INTF, "ERROR", e);
Sampa Misra3a0e3b92020-10-21 05:58:00 -0500402 return;
403 }
404}
405
Sampa Misraaea5dde2020-08-31 08:33:47 -0500406uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
407{
408 uint8_t sensorOpState = tSideNum;
Sampa Misraaea5dde2020-08-31 08:33:47 -0500409 if (entityInstance == 0)
410 {
411 auto currSide = codeUpdate->fetchCurrentBootSide();
412 if (currSide == Pside)
413 {
414 sensorOpState = pSideNum;
415 }
416 }
417 else if (entityInstance == 1)
418 {
419 auto nextSide = codeUpdate->fetchNextBootSide();
420 if (nextSide == Pside)
421 {
422 sensorOpState = pSideNum;
423 }
424 }
425 else
426 {
427 sensorOpState = PLDM_SENSOR_UNKNOWN;
428 }
429
430 return sensorOpState;
431}
432
433int setBootSide(uint16_t entityInstance, uint8_t currState,
434 const std::vector<set_effecter_state_field>& stateField,
435 CodeUpdate* codeUpdate)
436{
437 int rc = PLDM_SUCCESS;
438 auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
439
440 if (entityInstance == 0)
441 {
442 rc = codeUpdate->setCurrentBootSide(side);
443 }
444 else if (entityInstance == 1)
445 {
446 rc = codeUpdate->setNextBootSide(side);
447 }
448 else
449 {
450 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
451 }
452 return rc;
453}
454
Adriana Kobylak837fb472020-10-16 16:53:42 -0500455template <typename... T>
Patrick Williams6da4f912023-05-10 07:50:53 -0500456int executeCmd(const T&... t)
Adriana Kobylak837fb472020-10-16 16:53:42 -0500457{
458 std::stringstream cmd;
459 ((cmd << t << " "), ...) << std::endl;
460 FILE* pipe = popen(cmd.str().c_str(), "r");
461 if (!pipe)
462 {
463 throw std::runtime_error("popen() failed!");
464 }
465 int rc = pclose(pipe);
466 if (WEXITSTATUS(rc))
467 {
468 std::cerr << "Error executing: ";
469 ((std::cerr << " " << t), ...);
470 std::cerr << "\n";
471 return -1;
472 }
473
474 return 0;
475}
476
Adriana Kobylak727f7382020-09-01 14:38:25 -0500477int processCodeUpdateLid(const std::string& filePath)
478{
479 struct LidHeader
480 {
481 uint16_t magicNumber;
Adriana Kobylak86d14182020-10-16 16:11:08 -0500482 uint16_t headerVersion;
483 uint32_t lidNumber;
484 uint32_t lidDate;
485 uint16_t lidTime;
486 uint16_t lidClass;
487 uint32_t lidCrc;
488 uint32_t lidSize;
489 uint32_t headerSize;
Adriana Kobylak727f7382020-09-01 14:38:25 -0500490 };
491 LidHeader header;
492
493 std::ifstream ifs(filePath, std::ios::in | std::ios::binary);
494 if (!ifs)
495 {
Riya Dixitfc84f632024-04-06 14:00:02 -0500496 error("Failed to opening file '{FILE}' ifstream", "PATH", filePath);
Adriana Kobylak727f7382020-09-01 14:38:25 -0500497 return PLDM_ERROR;
498 }
499 ifs.seekg(0);
500 ifs.read(reinterpret_cast<char*>(&header), sizeof(header));
Adriana Kobylak727f7382020-09-01 14:38:25 -0500501
Adriana Kobylak86d14182020-10-16 16:11:08 -0500502 // File size should be the value of lid size minus the header size
503 auto fileSize = fs::file_size(filePath);
504 fileSize -= htonl(header.headerSize);
505 if (fileSize < htonl(header.lidSize))
506 {
507 // File is not completely written yet
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500508 ifs.close();
Adriana Kobylak86d14182020-10-16 16:11:08 -0500509 return PLDM_SUCCESS;
510 }
511
Adriana Kobylak727f7382020-09-01 14:38:25 -0500512 constexpr auto magicNumber = 0x0222;
513 if (htons(header.magicNumber) != magicNumber)
514 {
Riya Dixitfc84f632024-04-06 14:00:02 -0500515 error("Invalid magic number for file '{PATH}'", "PATH", filePath);
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500516 ifs.close();
Adriana Kobylak727f7382020-09-01 14:38:25 -0500517 return PLDM_ERROR;
518 }
519
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600520 fs::create_directories(imageDirPath);
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500521 fs::create_directories(lidDirPath);
522
Adriana Kobylaka1f158c2020-11-09 12:47:29 -0600523 constexpr auto bmcClass = 0x2000;
524 if (htons(header.lidClass) == bmcClass)
525 {
526 // Skip the header and concatenate the BMC LIDs into a tar file
527 std::ofstream ofs(tarImagePath,
528 std::ios::out | std::ios::binary | std::ios::app);
529 ifs.seekg(htonl(header.headerSize));
530 ofs << ifs.rdbuf();
531 ofs.flush();
532 ofs.close();
533 }
534 else
535 {
536 std::stringstream lidFileName;
537 lidFileName << std::hex << htonl(header.lidNumber) << ".lid";
538 auto lidNoHeaderPath = fs::path(lidDirPath) / lidFileName.str();
539 std::ofstream ofs(lidNoHeaderPath,
540 std::ios::out | std::ios::binary | std::ios::trunc);
541 ifs.seekg(htonl(header.headerSize));
542 ofs << ifs.rdbuf();
543 ofs.flush();
544 ofs.close();
545 }
Adriana Kobylakfa810d72020-10-16 16:27:28 -0500546
547 ifs.close();
548 fs::remove(filePath);
Adriana Kobylak727f7382020-09-01 14:38:25 -0500549 return PLDM_SUCCESS;
550}
551
Adriana Kobylak9296f242021-09-22 15:52:00 +0000552int CodeUpdate::assembleCodeUpdateImage()
Adriana Kobylak837fb472020-10-16 16:53:42 -0500553{
Adriana Kobylak9296f242021-09-22 15:52:00 +0000554 pid_t pid = fork();
555
556 if (pid == 0)
Adriana Kobylak837fb472020-10-16 16:53:42 -0500557 {
Adriana Kobylak9296f242021-09-22 15:52:00 +0000558 pid_t nextPid = fork();
559 if (nextPid == 0)
560 {
561 // Create the hostfw squashfs image from the LID files without
562 // header
563 auto rc = executeCmd("/usr/sbin/mksquashfs", lidDirPath.c_str(),
564 hostfwImagePath.c_str(), "-all-root",
565 "-no-recovery");
566 if (rc < 0)
567 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600568 error("Error occurred during the mksqusquashfs call");
Adriana Kobylak9296f242021-09-22 15:52:00 +0000569 setCodeUpdateProgress(false);
570 auto sensorId = getFirmwareUpdateSensor();
571 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
572 uint8_t(CodeUpdateState::FAIL),
573 uint8_t(CodeUpdateState::START));
574 exit(EXIT_FAILURE);
575 }
576
577 fs::create_directories(updateDirPath);
578
579 // Extract the BMC tarball content
580 rc = executeCmd("/bin/tar", "-xf", tarImagePath.c_str(), "-C",
581 updateDirPath);
582 if (rc < 0)
583 {
584 setCodeUpdateProgress(false);
585 auto sensorId = getFirmwareUpdateSensor();
586 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
587 uint8_t(CodeUpdateState::FAIL),
588 uint8_t(CodeUpdateState::START));
589 exit(EXIT_FAILURE);
590 }
591
592 // Add the hostfw image to the directory where the contents were
593 // extracted
594 fs::copy_file(hostfwImagePath,
595 fs::path(updateDirPath) / hostfwImageName,
596 fs::copy_options::overwrite_existing);
597
598 // Remove the tarball file, then re-generate it with so that the
599 // hostfw image becomes part of the tarball
600 fs::remove(tarImagePath);
601 rc = executeCmd("/bin/tar", "-cf", tarImagePath, ".", "-C",
602 updateDirPath);
603 if (rc < 0)
604 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600605 error("Error occurred during the generation of the tarball");
Adriana Kobylak9296f242021-09-22 15:52:00 +0000606 setCodeUpdateProgress(false);
607 auto sensorId = getFirmwareUpdateSensor();
608 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
609 uint8_t(CodeUpdateState::FAIL),
610 uint8_t(CodeUpdateState::START));
611 exit(EXIT_FAILURE);
612 }
613
614 // Copy the tarball to the update directory to trigger the phosphor
615 // software manager to create a version interface
616 fs::copy_file(tarImagePath, updateImagePath,
617 fs::copy_options::overwrite_existing);
618
619 // Cleanup
620 fs::remove_all(updateDirPath);
621 fs::remove_all(lidDirPath);
622 fs::remove_all(imageDirPath);
623
624 exit(EXIT_SUCCESS);
625 }
626 else if (nextPid < 0)
627 {
Riya Dixitfc84f632024-04-06 14:00:02 -0500628 error("Failure occurred during fork, error number - {ERROR_NUM}",
629 "ERROR_NUM", errno);
Adriana Kobylak9296f242021-09-22 15:52:00 +0000630 exit(EXIT_FAILURE);
631 }
632
633 // Do nothing as parent. When parent exits, child will be reparented
634 // under init and be reaped properly.
635 exit(0);
636 }
637 else if (pid > 0)
638 {
639 int status;
640 if (waitpid(pid, &status, 0) < 0)
641 {
Riya Dixitfc84f632024-04-06 14:00:02 -0500642 error("Error occurred during waitpid, error number - {ERROR_NUM}",
643 "ERROR_NUM", errno);
Riya Dixit49cfb132023-03-02 04:26:53 -0600644
Adriana Kobylak9296f242021-09-22 15:52:00 +0000645 return PLDM_ERROR;
646 }
647 else if (WEXITSTATUS(status) != 0)
648 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600649 error(
Riya Dixitfc84f632024-04-06 14:00:02 -0500650 "Failed to execute the assembling of the image, status is {IMG_STATUS}",
Riya Dixit49cfb132023-03-02 04:26:53 -0600651 "IMG_STATUS", status);
Adriana Kobylak9296f242021-09-22 15:52:00 +0000652 return PLDM_ERROR;
653 }
654 }
655 else
656 {
Riya Dixitfc84f632024-04-06 14:00:02 -0500657 error("Error occurred during fork, error number - {ERROR_NUM}}",
658 "ERROR_NUM", errno);
Adriana Kobylak837fb472020-10-16 16:53:42 -0500659 return PLDM_ERROR;
660 }
661
Adriana Kobylak837fb472020-10-16 16:53:42 -0500662 return PLDM_SUCCESS;
663}
664
Sampa Misraaea5dde2020-08-31 08:33:47 -0500665} // namespace responder
666} // namespace pldm