1 #include "activation_ubi.hpp" 2 3 #include "item_updater.hpp" 4 #include "serialize.hpp" 5 6 #include <phosphor-logging/log.hpp> 7 8 #include <filesystem> 9 10 namespace openpower 11 { 12 namespace software 13 { 14 namespace updater 15 { 16 namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server; 17 using namespace phosphor::logging; 18 19 uint8_t RedundancyPriorityUbi::priority(uint8_t value) 20 { 21 storeToFile(parent.versionId, value); 22 return RedundancyPriority::priority(value); 23 } 24 25 auto ActivationUbi::activation(Activations value) -> Activations 26 { 27 if (value != softwareServer::Activation::Activations::Active) 28 { 29 redundancyPriority.reset(nullptr); 30 } 31 32 if (value == softwareServer::Activation::Activations::Activating) 33 { 34 parent.freeSpace(); 35 softwareServer::Activation::activation(value); 36 37 if (ubiVolumesCreated == false) 38 { 39 // Enable systemd signals 40 subscribeToSystemdSignals(); 41 42 #ifdef WANT_SIGNATURE_VERIFY 43 // Validate the signed image. 44 if (!validateSignature(squashFSImage)) 45 { 46 // Cleanup 47 activationBlocksTransition.reset(nullptr); 48 activationProgress.reset(nullptr); 49 50 return softwareServer::Activation::activation( 51 softwareServer::Activation::Activations::Failed); 52 } 53 #endif 54 startActivation(); 55 return softwareServer::Activation::activation(value); 56 } 57 else if (ubiVolumesCreated == true) 58 { 59 // Only when the squashfs image is finished loading AND the RW 60 // volumes have been created do we proceed with activation. To 61 // verify that this happened, we check for the mount dirs PNOR_PRSV 62 // and PNOR_RW_PREFIX_<versionid>, as well as the image dir R0. 63 64 if ((std::filesystem::is_directory(PNOR_PRSV)) && 65 (std::filesystem::is_directory(PNOR_RW_PREFIX + versionId)) && 66 (std::filesystem::is_directory(PNOR_RO_PREFIX + versionId))) 67 { 68 finishActivation(); 69 if (Activation::checkApplyTimeImmediate()) 70 { 71 log<level::INFO>("Image Active. ApplyTime is immediate, " 72 "rebooting Host."); 73 Activation::rebootHost(); 74 } 75 return softwareServer::Activation::activation( 76 softwareServer::Activation::Activations::Active); 77 } 78 else 79 { 80 activationBlocksTransition.reset(nullptr); 81 activationProgress.reset(nullptr); 82 return softwareServer::Activation::activation( 83 softwareServer::Activation::Activations::Failed); 84 } 85 } 86 } 87 else 88 { 89 activationBlocksTransition.reset(nullptr); 90 activationProgress.reset(nullptr); 91 } 92 93 return softwareServer::Activation::activation(value); 94 } 95 96 auto ActivationUbi::requestedActivation(RequestedActivations value) 97 -> RequestedActivations 98 { 99 ubiVolumesCreated = false; 100 return Activation::requestedActivation(value); 101 } 102 103 void ActivationUbi::startActivation() 104 { 105 // Since the squashfs image has not yet been loaded to pnor and the 106 // RW volumes have not yet been created, we need to start the 107 // service files for each of those actions. 108 109 if (!activationProgress) 110 { 111 activationProgress = std::make_unique<ActivationProgress>(bus, path); 112 } 113 114 if (!activationBlocksTransition) 115 { 116 activationBlocksTransition = 117 std::make_unique<ActivationBlocksTransition>(bus, path); 118 } 119 120 constexpr auto ubimountService = "obmc-flash-bios-ubimount@"; 121 auto ubimountServiceFile = std::string(ubimountService) + versionId + 122 ".service"; 123 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, 124 SYSTEMD_INTERFACE, "StartUnit"); 125 method.append(ubimountServiceFile, "replace"); 126 bus.call_noreply(method); 127 128 activationProgress->progress(10); 129 } 130 131 void ActivationUbi::unitStateChange(sdbusplus::message_t& msg) 132 { 133 uint32_t newStateID{}; 134 sdbusplus::message::object_path newStateObjPath; 135 std::string newStateUnit{}; 136 std::string newStateResult{}; 137 138 // Read the msg and populate each variable 139 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult); 140 141 auto ubimountServiceFile = "obmc-flash-bios-ubimount@" + versionId + 142 ".service"; 143 144 if (newStateUnit == ubimountServiceFile && newStateResult == "done") 145 { 146 ubiVolumesCreated = true; 147 activationProgress->progress(activationProgress->progress() + 50); 148 } 149 150 if (ubiVolumesCreated) 151 { 152 activation(softwareServer::Activation::Activations::Activating); 153 } 154 155 if ((newStateUnit == ubimountServiceFile) && 156 (newStateResult == "failed" || newStateResult == "dependency")) 157 { 158 activation(softwareServer::Activation::Activations::Failed); 159 } 160 161 return; 162 } 163 164 void ActivationUbi::finishActivation() 165 { 166 activationProgress->progress(90); 167 168 // Set Redundancy Priority before setting to Active 169 if (!redundancyPriority) 170 { 171 redundancyPriority = std::make_unique<RedundancyPriorityUbi>(bus, path, 172 *this, 0); 173 } 174 175 activationProgress->progress(100); 176 177 activationBlocksTransition.reset(nullptr); 178 activationProgress.reset(nullptr); 179 180 ubiVolumesCreated = false; 181 unsubscribeFromSystemdSignals(); 182 // Remove version object from image manager 183 deleteImageManagerObject(); 184 // Create active association 185 parent.createActiveAssociation(path); 186 // Create updateable association as this 187 // can be re-programmed. 188 parent.createUpdateableAssociation(path); 189 } 190 191 } // namespace updater 192 } // namespace software 193 } // namespace openpower 194