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