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