| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 1 | #include "inband_code_update.hpp" | 
 | 2 |  | 
| Sagar Srinivas | 78a225a | 2020-08-27 00:52:20 -0500 | [diff] [blame] | 3 | #include "libpldmresponder/pdr.hpp" | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 4 | #include "oem_ibm_handler.hpp" | 
 | 5 | #include "xyz/openbmc_project/Common/error.hpp" | 
 | 6 |  | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 7 | #include <arpa/inet.h> | 
| George Liu | c453e16 | 2022-12-21 17:16:23 +0800 | [diff] [blame] | 8 | #include <libpldm/entity.h> | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 9 |  | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 10 | #include <phosphor-logging/lg2.hpp> | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 11 | #include <sdbusplus/server.hpp> | 
 | 12 | #include <xyz/openbmc_project/Dump/NewDump/server.hpp> | 
 | 13 |  | 
 | 14 | #include <exception> | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 15 | #include <fstream> | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 16 |  | 
 | 17 | PHOSPHOR_LOG2_USING; | 
 | 18 |  | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 19 | namespace pldm | 
 | 20 | { | 
| Brad Bishop | 5079ac4 | 2021-08-19 18:35:06 -0400 | [diff] [blame] | 21 | using namespace utils; | 
 | 22 |  | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 23 | namespace responder | 
 | 24 | { | 
 | 25 | using namespace oem_ibm_platform; | 
 | 26 |  | 
| Adriana Kobylak | fa810d7 | 2020-10-16 16:27:28 -0500 | [diff] [blame] | 27 | /** @brief Directory where the lid files without a header are stored */ | 
 | 28 | auto lidDirPath = fs::path(LID_STAGING_DIR) / "lid"; | 
 | 29 |  | 
| Adriana Kobylak | a1f158c | 2020-11-09 12:47:29 -0600 | [diff] [blame] | 30 | /** @brief Directory where the image files are stored as they are built */ | 
 | 31 | auto imageDirPath = fs::path(LID_STAGING_DIR) / "image"; | 
 | 32 |  | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 33 | /** @brief Directory where the code update tarball files are stored */ | 
 | 34 | auto updateDirPath = fs::path(LID_STAGING_DIR) / "update"; | 
 | 35 |  | 
| Adriana Kobylak | a1f158c | 2020-11-09 12:47:29 -0600 | [diff] [blame] | 36 | /** @brief The file name of the code update tarball */ | 
 | 37 | constexpr auto tarImageName = "image.tar"; | 
 | 38 |  | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 39 | /** @brief The file name of the hostfw image */ | 
| Adriana Kobylak | 131327e | 2021-03-10 18:45:24 +0000 | [diff] [blame] | 40 | constexpr auto hostfwImageName = "image-hostfw"; | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 41 |  | 
| Adriana Kobylak | a1f158c | 2020-11-09 12:47:29 -0600 | [diff] [blame] | 42 | /** @brief The path to the code update tarball file */ | 
 | 43 | auto tarImagePath = fs::path(imageDirPath) / tarImageName; | 
 | 44 |  | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 45 | /** @brief The path to the hostfw image */ | 
 | 46 | auto hostfwImagePath = fs::path(imageDirPath) / hostfwImageName; | 
 | 47 |  | 
 | 48 | /** @brief The path to the tarball file expected by the phosphor software | 
 | 49 |  *         manager */ | 
 | 50 | auto updateImagePath = fs::path("/tmp/images") / tarImageName; | 
 | 51 |  | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 52 | std::string CodeUpdate::fetchCurrentBootSide() | 
 | 53 | { | 
 | 54 |     return currBootSide; | 
 | 55 | } | 
 | 56 |  | 
 | 57 | std::string CodeUpdate::fetchNextBootSide() | 
 | 58 | { | 
 | 59 |     return nextBootSide; | 
 | 60 | } | 
 | 61 |  | 
 | 62 | int CodeUpdate::setCurrentBootSide(const std::string& currSide) | 
 | 63 | { | 
 | 64 |     currBootSide = currSide; | 
 | 65 |     return PLDM_SUCCESS; | 
 | 66 | } | 
 | 67 |  | 
 | 68 | int 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 Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 82 |         error("no nonRunningVersion present"); | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 83 |         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 Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 96 |         error("Failed to set the next boot side to {PATH} , error - {ERROR}", | 
 | 97 |               "PATH", objPath, "ERROR", e); | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 98 |         return PLDM_ERROR; | 
 | 99 |     } | 
 | 100 |     return PLDM_SUCCESS; | 
 | 101 | } | 
 | 102 |  | 
| Sagar Srinivas | cfdbca7 | 2020-09-22 10:03:35 -0500 | [diff] [blame] | 103 | int 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 Srinivas | 9040347 | 2023-08-21 06:08:55 -0500 | [diff] [blame] | 119 |         error( | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 120 |             "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 Srinivas | cfdbca7 | 2020-09-22 10:03:35 -0500 | [diff] [blame] | 123 |         rc = PLDM_ERROR; | 
 | 124 |     } | 
 | 125 |     return rc; | 
 | 126 | } | 
 | 127 |  | 
 | 128 | int 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 Srinivas | 9040347 | 2023-08-21 06:08:55 -0500 | [diff] [blame] | 144 |         error( | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 145 |             "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 Srinivas | cfdbca7 | 2020-09-22 10:03:35 -0500 | [diff] [blame] | 148 |         rc = PLDM_ERROR; | 
 | 149 |     } | 
| Sagar Srinivas | cfdbca7 | 2020-09-22 10:03:35 -0500 | [diff] [blame] | 150 |     return rc; | 
 | 151 | } | 
 | 152 |  | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 153 | void 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 Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 163 |     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.com | 91a092f | 2023-09-18 23:39:44 -0500 | [diff] [blame] | 170 |         auto reply = bus.call(method, dbusTimeout); | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 171 |         reply.read(paths); | 
 | 172 |  | 
 | 173 |         runningVersion = std::get<std::vector<std::string>>(paths)[0]; | 
 | 174 |  | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 175 |         auto method1 = | 
 | 176 |             bus.new_method_call(mapperService, activeObjPath, propIntf, "Get"); | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 177 |         method1.append("xyz.openbmc_project.Association", "endpoints"); | 
 | 178 |  | 
| vkaverap@in.ibm.com | 91a092f | 2023-09-18 23:39:44 -0500 | [diff] [blame] | 179 |         auto reply1 = bus.call(method1, dbusTimeout); | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 180 |         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 Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 192 |         error( | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 193 |             "Failed to make a d-bus call to Object Mapper Association, error - {ERROR}", | 
 | 194 |             "ERROR", e); | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 195 |         return; | 
 | 196 |     } | 
 | 197 |  | 
 | 198 |     using namespace sdbusplus::bus::match::rules; | 
 | 199 |     captureNextBootSideChange.push_back( | 
| Patrick Williams | 84b790c | 2022-07-22 19:26:56 -0500 | [diff] [blame] | 200 |         std::make_unique<sdbusplus::bus::match_t>( | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 201 |             pldm::utils::DBusHandler::getBus(), | 
 | 202 |             propertiesChanged(runningVersion, redundancyIntf), | 
| Patrick Williams | 84b790c | 2022-07-22 19:26:56 -0500 | [diff] [blame] | 203 |             [this](sdbusplus::message_t& msg) { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 204 |                 DbusChangedProps props; | 
 | 205 |                 std::string iface; | 
 | 206 |                 msg.read(iface, props); | 
 | 207 |                 processPriorityChangeNotification(props); | 
 | 208 |             })); | 
| Patrick Williams | 84b790c | 2022-07-22 19:26:56 -0500 | [diff] [blame] | 209 |     fwUpdateMatcher.push_back(std::make_unique<sdbusplus::bus::match_t>( | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 210 |         pldm::utils::DBusHandler::getBus(), | 
 | 211 |         "interface='org.freedesktop.DBus.ObjectManager',type='signal'," | 
 | 212 |         "member='InterfacesAdded',path='/xyz/openbmc_project/software'", | 
| Patrick Williams | 84b790c | 2022-07-22 19:26:56 -0500 | [diff] [blame] | 213 |         [this](sdbusplus::message_t& msg) { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 214 |             DBusInterfaceAdded interfaces; | 
 | 215 |             sdbusplus::message::object_path path; | 
 | 216 |             msg.read(path, interfaces); | 
| Sagar Srinivas | 9a64b4a | 2021-02-09 07:55:38 -0600 | [diff] [blame] | 217 |  | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 218 |             for (auto& interface : interfaces) | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 219 |             { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 220 |                 if (interface.first == | 
 | 221 |                     "xyz.openbmc_project.Software.Activation") | 
| Patrick Williams | 6da4f91 | 2023-05-10 07:50:53 -0500 | [diff] [blame] | 222 |                 { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 223 |                     auto imageInterface = | 
 | 224 |                         "xyz.openbmc_project.Software.Activation"; | 
 | 225 |                     auto imageObjPath = path.str.c_str(); | 
 | 226 |  | 
 | 227 |                     try | 
| Sampa Misra | 3a0e3b9 | 2020-10-21 05:58:00 -0500 | [diff] [blame] | 228 |                     { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 229 |                         auto propVal = dBusIntf->getDbusPropertyVariant( | 
 | 230 |                             imageObjPath, "Activation", imageInterface); | 
 | 231 |                         const auto& imageProp = std::get<std::string>(propVal); | 
 | 232 |                         if (imageProp == "xyz.openbmc_project.Software." | 
 | 233 |                                          "Activation.Activations.Ready" && | 
 | 234 |                             isCodeUpdateInProgress()) | 
| Sampa Misra | 3a0e3b9 | 2020-10-21 05:58:00 -0500 | [diff] [blame] | 235 |                         { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 236 |                             newImageId = path.str; | 
 | 237 |                             if (!imageActivationMatch) | 
 | 238 |                             { | 
 | 239 |                                 imageActivationMatch = std::make_unique< | 
 | 240 |                                     sdbusplus::bus::match_t>( | 
| Sagar Srinivas | 9a64b4a | 2021-02-09 07:55:38 -0600 | [diff] [blame] | 241 |                                     pldm::utils::DBusHandler::getBus(), | 
 | 242 |                                     propertiesChanged(newImageId, | 
 | 243 |                                                       "xyz.openbmc_project." | 
 | 244 |                                                       "Software.Activation"), | 
| Patrick Williams | 84b790c | 2022-07-22 19:26:56 -0500 | [diff] [blame] | 245 |                                     [this](sdbusplus::message_t& msg) { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 246 |                                         DbusChangedProps props; | 
 | 247 |                                         std::string iface; | 
 | 248 |                                         msg.read(iface, props); | 
 | 249 |                                         const auto itr = | 
 | 250 |                                             props.find("Activation"); | 
 | 251 |                                         if (itr != props.end()) | 
 | 252 |                                         { | 
 | 253 |                                             PropertyValue value = itr->second; | 
 | 254 |                                             auto propVal = | 
 | 255 |                                                 std::get<std::string>(value); | 
 | 256 |                                             if (propVal == | 
 | 257 |                                                 "xyz.openbmc_project.Software." | 
 | 258 |                                                 "Activation.Activations.Active") | 
 | 259 |                                             { | 
 | 260 |                                                 CodeUpdateState state = | 
 | 261 |                                                     CodeUpdateState::END; | 
 | 262 |                                                 setCodeUpdateProgress(false); | 
 | 263 |                                                 auto sensorId = | 
 | 264 |                                                     getFirmwareUpdateSensor(); | 
 | 265 |                                                 sendStateSensorEvent( | 
 | 266 |                                                     sensorId, | 
 | 267 |                                                     PLDM_STATE_SENSOR_STATE, 0, | 
 | 268 |                                                     uint8_t(state), | 
 | 269 |                                                     uint8_t(CodeUpdateState:: | 
 | 270 |                                                                 START)); | 
 | 271 |                                                 newImageId.clear(); | 
 | 272 |                                             } | 
 | 273 |                                             else if (propVal == | 
 | 274 |                                                          "xyz.openbmc_project." | 
 | 275 |                                                          "Software.Activation." | 
 | 276 |                                                          "Activations.Failed" || | 
 | 277 |                                                      propVal == | 
 | 278 |                                                          "xyz.openbmc_" | 
 | 279 |                                                          "project.Software." | 
 | 280 |                                                          "Activation." | 
 | 281 |                                                          "Activations." | 
 | 282 |                                                          "Invalid") | 
 | 283 |                                             { | 
 | 284 |                                                 CodeUpdateState state = | 
 | 285 |                                                     CodeUpdateState::FAIL; | 
 | 286 |                                                 setCodeUpdateProgress(false); | 
 | 287 |                                                 auto sensorId = | 
 | 288 |                                                     getFirmwareUpdateSensor(); | 
 | 289 |                                                 sendStateSensorEvent( | 
 | 290 |                                                     sensorId, | 
 | 291 |                                                     PLDM_STATE_SENSOR_STATE, 0, | 
 | 292 |                                                     uint8_t(state), | 
 | 293 |                                                     uint8_t(CodeUpdateState:: | 
 | 294 |                                                                 START)); | 
 | 295 |                                                 newImageId.clear(); | 
 | 296 |                                             } | 
 | 297 |                                         } | 
 | 298 |                                     }); | 
 | 299 |                             } | 
 | 300 |                             auto rc = setRequestedActivation(); | 
 | 301 |                             if (rc != PLDM_SUCCESS) | 
 | 302 |                             { | 
 | 303 |                                 error("Could not set Requested Activation"); | 
 | 304 |                                 CodeUpdateState state = CodeUpdateState::FAIL; | 
 | 305 |                                 setCodeUpdateProgress(false); | 
 | 306 |                                 auto sensorId = getFirmwareUpdateSensor(); | 
 | 307 |                                 sendStateSensorEvent( | 
 | 308 |                                     sensorId, PLDM_STATE_SENSOR_STATE, 0, | 
 | 309 |                                     uint8_t(state), | 
 | 310 |                                     uint8_t(CodeUpdateState::START)); | 
 | 311 |                             } | 
 | 312 |                             break; | 
| Sampa Misra | 3a0e3b9 | 2020-10-21 05:58:00 -0500 | [diff] [blame] | 313 |                         } | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 314 |                     } | 
 | 315 |                     catch (const sdbusplus::exception_t& e) | 
 | 316 |                     { | 
 | 317 |                         error( | 
 | 318 |                             "Failed to get activation status for interface '{INTERFACE}' and object path '{PATH}', error - {ERROR}", | 
 | 319 |                             "ERROR", e, "INTERFACE", imageInterface, "PATH", | 
 | 320 |                             imageObjPath); | 
| Sampa Misra | 3a0e3b9 | 2020-10-21 05:58:00 -0500 | [diff] [blame] | 321 |                     } | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 322 |                 } | 
 | 323 |             } | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 324 |         })); | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 325 | } | 
 | 326 |  | 
 | 327 | void CodeUpdate::processPriorityChangeNotification( | 
 | 328 |     const DbusChangedProps& chProperties) | 
 | 329 | { | 
 | 330 |     static constexpr auto propName = "Priority"; | 
 | 331 |     const auto it = chProperties.find(propName); | 
 | 332 |     if (it == chProperties.end()) | 
 | 333 |     { | 
 | 334 |         return; | 
 | 335 |     } | 
 | 336 |     uint8_t newVal = std::get<uint8_t>(it->second); | 
 | 337 |     nextBootSide = (newVal == 0) ? currBootSide | 
 | 338 |                                  : ((currBootSide == Tside) ? Pside : Tside); | 
 | 339 | } | 
 | 340 |  | 
 | 341 | void CodeUpdate::setOemPlatformHandler( | 
 | 342 |     pldm::responder::oem_platform::Handler* handler) | 
 | 343 | { | 
 | 344 |     oemPlatformHandler = handler; | 
 | 345 | } | 
 | 346 |  | 
| Varsha Kaverappa | 3ca29df | 2020-09-27 12:39:22 -0500 | [diff] [blame] | 347 | void CodeUpdate::clearDirPath(const std::string& dirPath) | 
 | 348 | { | 
| Manojkiran Eda | 78124cf | 2022-08-29 11:22:43 +0530 | [diff] [blame] | 349 |     if (!fs::is_directory(dirPath)) | 
| Varsha Kaverappa | 3ca29df | 2020-09-27 12:39:22 -0500 | [diff] [blame] | 350 |     { | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 351 |         error("The directory '{PATH}' does not exist", "PATH", dirPath); | 
| Manojkiran Eda | 78124cf | 2022-08-29 11:22:43 +0530 | [diff] [blame] | 352 |         return; | 
| Varsha Kaverappa | 3ca29df | 2020-09-27 12:39:22 -0500 | [diff] [blame] | 353 |     } | 
| Manojkiran Eda | 78124cf | 2022-08-29 11:22:43 +0530 | [diff] [blame] | 354 |     for (const auto& iter : fs::directory_iterator(dirPath)) | 
 | 355 |     { | 
 | 356 |         fs::remove_all(iter); | 
 | 357 |     } | 
| Varsha Kaverappa | 3ca29df | 2020-09-27 12:39:22 -0500 | [diff] [blame] | 358 | } | 
 | 359 |  | 
| Sampa Misra | 3a0e3b9 | 2020-10-21 05:58:00 -0500 | [diff] [blame] | 360 | void CodeUpdate::sendStateSensorEvent( | 
 | 361 |     uint16_t sensorId, enum sensor_event_class_states sensorEventClass, | 
 | 362 |     uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState) | 
 | 363 | { | 
 | 364 |     pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler = | 
 | 365 |         dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>( | 
 | 366 |             oemPlatformHandler); | 
 | 367 |     oemIbmPlatformHandler->sendStateSensorEvent( | 
 | 368 |         sensorId, sensorEventClass, sensorOffset, eventState, prevEventState); | 
 | 369 | } | 
 | 370 |  | 
 | 371 | void CodeUpdate::deleteImage() | 
 | 372 | { | 
 | 373 |     static constexpr auto UPDATER_SERVICE = | 
 | 374 |         "xyz.openbmc_project.Software.BMC.Updater"; | 
 | 375 |     static constexpr auto SW_OBJ_PATH = "/xyz/openbmc_project/software"; | 
 | 376 |     static constexpr auto DELETE_INTF = | 
 | 377 |         "xyz.openbmc_project.Collection.DeleteAll"; | 
 | 378 |  | 
 | 379 |     auto& bus = dBusIntf->getBus(); | 
 | 380 |     try | 
 | 381 |     { | 
 | 382 |         auto method = bus.new_method_call(UPDATER_SERVICE, SW_OBJ_PATH, | 
 | 383 |                                           DELETE_INTF, "DeleteAll"); | 
| vkaverap@in.ibm.com | 5b71b86 | 2023-08-21 05:19:04 +0000 | [diff] [blame] | 384 |         bus.call_noreply(method, dbusTimeout); | 
| Sampa Misra | 3a0e3b9 | 2020-10-21 05:58:00 -0500 | [diff] [blame] | 385 |     } | 
 | 386 |     catch (const std::exception& e) | 
 | 387 |     { | 
| Sagar Srinivas | 9040347 | 2023-08-21 06:08:55 -0500 | [diff] [blame] | 388 |         error( | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 389 |             "Failed to delete image at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}", | 
 | 390 |             "PATH", SW_OBJ_PATH, "INTERFACE", DELETE_INTF, "ERROR", e); | 
| Sampa Misra | 3a0e3b9 | 2020-10-21 05:58:00 -0500 | [diff] [blame] | 391 |         return; | 
 | 392 |     } | 
 | 393 | } | 
 | 394 |  | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 395 | uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate) | 
 | 396 | { | 
 | 397 |     uint8_t sensorOpState = tSideNum; | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 398 |     if (entityInstance == 0) | 
 | 399 |     { | 
 | 400 |         auto currSide = codeUpdate->fetchCurrentBootSide(); | 
 | 401 |         if (currSide == Pside) | 
 | 402 |         { | 
 | 403 |             sensorOpState = pSideNum; | 
 | 404 |         } | 
 | 405 |     } | 
 | 406 |     else if (entityInstance == 1) | 
 | 407 |     { | 
 | 408 |         auto nextSide = codeUpdate->fetchNextBootSide(); | 
 | 409 |         if (nextSide == Pside) | 
 | 410 |         { | 
 | 411 |             sensorOpState = pSideNum; | 
 | 412 |         } | 
 | 413 |     } | 
 | 414 |     else | 
 | 415 |     { | 
 | 416 |         sensorOpState = PLDM_SENSOR_UNKNOWN; | 
 | 417 |     } | 
 | 418 |  | 
 | 419 |     return sensorOpState; | 
 | 420 | } | 
 | 421 |  | 
 | 422 | int setBootSide(uint16_t entityInstance, uint8_t currState, | 
 | 423 |                 const std::vector<set_effecter_state_field>& stateField, | 
 | 424 |                 CodeUpdate* codeUpdate) | 
 | 425 | { | 
 | 426 |     int rc = PLDM_SUCCESS; | 
 | 427 |     auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T"; | 
 | 428 |  | 
 | 429 |     if (entityInstance == 0) | 
 | 430 |     { | 
 | 431 |         rc = codeUpdate->setCurrentBootSide(side); | 
 | 432 |     } | 
 | 433 |     else if (entityInstance == 1) | 
 | 434 |     { | 
 | 435 |         rc = codeUpdate->setNextBootSide(side); | 
 | 436 |     } | 
 | 437 |     else | 
 | 438 |     { | 
 | 439 |         rc = PLDM_PLATFORM_INVALID_STATE_VALUE; | 
 | 440 |     } | 
 | 441 |     return rc; | 
 | 442 | } | 
 | 443 |  | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 444 | template <typename... T> | 
| Patrick Williams | 6da4f91 | 2023-05-10 07:50:53 -0500 | [diff] [blame] | 445 | int executeCmd(const T&... t) | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 446 | { | 
 | 447 |     std::stringstream cmd; | 
 | 448 |     ((cmd << t << " "), ...) << std::endl; | 
 | 449 |     FILE* pipe = popen(cmd.str().c_str(), "r"); | 
 | 450 |     if (!pipe) | 
 | 451 |     { | 
 | 452 |         throw std::runtime_error("popen() failed!"); | 
 | 453 |     } | 
 | 454 |     int rc = pclose(pipe); | 
 | 455 |     if (WEXITSTATUS(rc)) | 
 | 456 |     { | 
 | 457 |         std::cerr << "Error executing: "; | 
 | 458 |         ((std::cerr << " " << t), ...); | 
 | 459 |         std::cerr << "\n"; | 
 | 460 |         return -1; | 
 | 461 |     } | 
 | 462 |  | 
 | 463 |     return 0; | 
 | 464 | } | 
 | 465 |  | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 466 | int processCodeUpdateLid(const std::string& filePath) | 
 | 467 | { | 
 | 468 |     struct LidHeader | 
 | 469 |     { | 
 | 470 |         uint16_t magicNumber; | 
| Adriana Kobylak | 86d1418 | 2020-10-16 16:11:08 -0500 | [diff] [blame] | 471 |         uint16_t headerVersion; | 
 | 472 |         uint32_t lidNumber; | 
 | 473 |         uint32_t lidDate; | 
 | 474 |         uint16_t lidTime; | 
 | 475 |         uint16_t lidClass; | 
 | 476 |         uint32_t lidCrc; | 
 | 477 |         uint32_t lidSize; | 
 | 478 |         uint32_t headerSize; | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 479 |     }; | 
 | 480 |     LidHeader header; | 
 | 481 |  | 
 | 482 |     std::ifstream ifs(filePath, std::ios::in | std::ios::binary); | 
 | 483 |     if (!ifs) | 
 | 484 |     { | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 485 |         error("Failed to opening file '{FILE}' ifstream", "PATH", filePath); | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 486 |         return PLDM_ERROR; | 
 | 487 |     } | 
 | 488 |     ifs.seekg(0); | 
 | 489 |     ifs.read(reinterpret_cast<char*>(&header), sizeof(header)); | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 490 |  | 
| Adriana Kobylak | 86d1418 | 2020-10-16 16:11:08 -0500 | [diff] [blame] | 491 |     // File size should be the value of lid size minus the header size | 
 | 492 |     auto fileSize = fs::file_size(filePath); | 
 | 493 |     fileSize -= htonl(header.headerSize); | 
 | 494 |     if (fileSize < htonl(header.lidSize)) | 
 | 495 |     { | 
 | 496 |         // File is not completely written yet | 
| Adriana Kobylak | fa810d7 | 2020-10-16 16:27:28 -0500 | [diff] [blame] | 497 |         ifs.close(); | 
| Adriana Kobylak | 86d1418 | 2020-10-16 16:11:08 -0500 | [diff] [blame] | 498 |         return PLDM_SUCCESS; | 
 | 499 |     } | 
 | 500 |  | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 501 |     constexpr auto magicNumber = 0x0222; | 
 | 502 |     if (htons(header.magicNumber) != magicNumber) | 
 | 503 |     { | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 504 |         error("Invalid magic number for file '{PATH}'", "PATH", filePath); | 
| Adriana Kobylak | fa810d7 | 2020-10-16 16:27:28 -0500 | [diff] [blame] | 505 |         ifs.close(); | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 506 |         return PLDM_ERROR; | 
 | 507 |     } | 
 | 508 |  | 
| Adriana Kobylak | a1f158c | 2020-11-09 12:47:29 -0600 | [diff] [blame] | 509 |     fs::create_directories(imageDirPath); | 
| Adriana Kobylak | fa810d7 | 2020-10-16 16:27:28 -0500 | [diff] [blame] | 510 |     fs::create_directories(lidDirPath); | 
 | 511 |  | 
| Adriana Kobylak | a1f158c | 2020-11-09 12:47:29 -0600 | [diff] [blame] | 512 |     constexpr auto bmcClass = 0x2000; | 
 | 513 |     if (htons(header.lidClass) == bmcClass) | 
 | 514 |     { | 
 | 515 |         // Skip the header and concatenate the BMC LIDs into a tar file | 
 | 516 |         std::ofstream ofs(tarImagePath, | 
 | 517 |                           std::ios::out | std::ios::binary | std::ios::app); | 
 | 518 |         ifs.seekg(htonl(header.headerSize)); | 
 | 519 |         ofs << ifs.rdbuf(); | 
 | 520 |         ofs.flush(); | 
 | 521 |         ofs.close(); | 
 | 522 |     } | 
 | 523 |     else | 
 | 524 |     { | 
 | 525 |         std::stringstream lidFileName; | 
 | 526 |         lidFileName << std::hex << htonl(header.lidNumber) << ".lid"; | 
 | 527 |         auto lidNoHeaderPath = fs::path(lidDirPath) / lidFileName.str(); | 
 | 528 |         std::ofstream ofs(lidNoHeaderPath, | 
 | 529 |                           std::ios::out | std::ios::binary | std::ios::trunc); | 
 | 530 |         ifs.seekg(htonl(header.headerSize)); | 
 | 531 |         ofs << ifs.rdbuf(); | 
 | 532 |         ofs.flush(); | 
 | 533 |         ofs.close(); | 
 | 534 |     } | 
| Adriana Kobylak | fa810d7 | 2020-10-16 16:27:28 -0500 | [diff] [blame] | 535 |  | 
 | 536 |     ifs.close(); | 
 | 537 |     fs::remove(filePath); | 
| Adriana Kobylak | 727f738 | 2020-09-01 14:38:25 -0500 | [diff] [blame] | 538 |     return PLDM_SUCCESS; | 
 | 539 | } | 
 | 540 |  | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 541 | int CodeUpdate::assembleCodeUpdateImage() | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 542 | { | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 543 |     pid_t pid = fork(); | 
 | 544 |  | 
 | 545 |     if (pid == 0) | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 546 |     { | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 547 |         pid_t nextPid = fork(); | 
 | 548 |         if (nextPid == 0) | 
 | 549 |         { | 
 | 550 |             // Create the hostfw squashfs image from the LID files without | 
 | 551 |             // header | 
 | 552 |             auto rc = executeCmd("/usr/sbin/mksquashfs", lidDirPath.c_str(), | 
 | 553 |                                  hostfwImagePath.c_str(), "-all-root", | 
 | 554 |                                  "-no-recovery"); | 
 | 555 |             if (rc < 0) | 
 | 556 |             { | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 557 |                 error("Error occurred during the mksqusquashfs call"); | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 558 |                 setCodeUpdateProgress(false); | 
 | 559 |                 auto sensorId = getFirmwareUpdateSensor(); | 
 | 560 |                 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, | 
 | 561 |                                      uint8_t(CodeUpdateState::FAIL), | 
 | 562 |                                      uint8_t(CodeUpdateState::START)); | 
 | 563 |                 exit(EXIT_FAILURE); | 
 | 564 |             } | 
 | 565 |  | 
 | 566 |             fs::create_directories(updateDirPath); | 
 | 567 |  | 
 | 568 |             // Extract the BMC tarball content | 
 | 569 |             rc = executeCmd("/bin/tar", "-xf", tarImagePath.c_str(), "-C", | 
 | 570 |                             updateDirPath); | 
 | 571 |             if (rc < 0) | 
 | 572 |             { | 
 | 573 |                 setCodeUpdateProgress(false); | 
 | 574 |                 auto sensorId = getFirmwareUpdateSensor(); | 
 | 575 |                 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, | 
 | 576 |                                      uint8_t(CodeUpdateState::FAIL), | 
 | 577 |                                      uint8_t(CodeUpdateState::START)); | 
 | 578 |                 exit(EXIT_FAILURE); | 
 | 579 |             } | 
 | 580 |  | 
 | 581 |             // Add the hostfw image to the directory where the contents were | 
 | 582 |             // extracted | 
 | 583 |             fs::copy_file(hostfwImagePath, | 
 | 584 |                           fs::path(updateDirPath) / hostfwImageName, | 
 | 585 |                           fs::copy_options::overwrite_existing); | 
 | 586 |  | 
 | 587 |             // Remove the tarball file, then re-generate it with so that the | 
 | 588 |             // hostfw image becomes part of the tarball | 
 | 589 |             fs::remove(tarImagePath); | 
 | 590 |             rc = executeCmd("/bin/tar", "-cf", tarImagePath, ".", "-C", | 
 | 591 |                             updateDirPath); | 
 | 592 |             if (rc < 0) | 
 | 593 |             { | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 594 |                 error("Error occurred during the generation of the tarball"); | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 595 |                 setCodeUpdateProgress(false); | 
 | 596 |                 auto sensorId = getFirmwareUpdateSensor(); | 
 | 597 |                 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, | 
 | 598 |                                      uint8_t(CodeUpdateState::FAIL), | 
 | 599 |                                      uint8_t(CodeUpdateState::START)); | 
 | 600 |                 exit(EXIT_FAILURE); | 
 | 601 |             } | 
 | 602 |  | 
 | 603 |             // Copy the tarball to the update directory to trigger the phosphor | 
 | 604 |             // software manager to create a version interface | 
 | 605 |             fs::copy_file(tarImagePath, updateImagePath, | 
 | 606 |                           fs::copy_options::overwrite_existing); | 
 | 607 |  | 
 | 608 |             // Cleanup | 
 | 609 |             fs::remove_all(updateDirPath); | 
 | 610 |             fs::remove_all(lidDirPath); | 
 | 611 |             fs::remove_all(imageDirPath); | 
 | 612 |  | 
 | 613 |             exit(EXIT_SUCCESS); | 
 | 614 |         } | 
 | 615 |         else if (nextPid < 0) | 
 | 616 |         { | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 617 |             error("Failure occurred during fork, error number - {ERROR_NUM}", | 
 | 618 |                   "ERROR_NUM", errno); | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 619 |             exit(EXIT_FAILURE); | 
 | 620 |         } | 
 | 621 |  | 
 | 622 |         // Do nothing as parent. When parent exits, child will be reparented | 
 | 623 |         // under init and be reaped properly. | 
 | 624 |         exit(0); | 
 | 625 |     } | 
 | 626 |     else if (pid > 0) | 
 | 627 |     { | 
 | 628 |         int status; | 
 | 629 |         if (waitpid(pid, &status, 0) < 0) | 
 | 630 |         { | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 631 |             error("Error occurred during waitpid, error number - {ERROR_NUM}", | 
 | 632 |                   "ERROR_NUM", errno); | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 633 |  | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 634 |             return PLDM_ERROR; | 
 | 635 |         } | 
 | 636 |         else if (WEXITSTATUS(status) != 0) | 
 | 637 |         { | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 638 |             error( | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 639 |                 "Failed to execute the assembling of the image, status is {IMG_STATUS}", | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 640 |                 "IMG_STATUS", status); | 
| Adriana Kobylak | 9296f24 | 2021-09-22 15:52:00 +0000 | [diff] [blame] | 641 |             return PLDM_ERROR; | 
 | 642 |         } | 
 | 643 |     } | 
 | 644 |     else | 
 | 645 |     { | 
| Riya Dixit | fc84f63 | 2024-04-06 14:00:02 -0500 | [diff] [blame] | 646 |         error("Error occurred during fork, error number - {ERROR_NUM}}", | 
 | 647 |               "ERROR_NUM", errno); | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 648 |         return PLDM_ERROR; | 
 | 649 |     } | 
 | 650 |  | 
| Adriana Kobylak | 837fb47 | 2020-10-16 16:53:42 -0500 | [diff] [blame] | 651 |     return PLDM_SUCCESS; | 
 | 652 | } | 
 | 653 |  | 
| Sampa Misra | aea5dde | 2020-08-31 08:33:47 -0500 | [diff] [blame] | 654 | } // namespace responder | 
 | 655 | } // namespace pldm |