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