1 #include "software.hpp" 2 3 #include "device.hpp" 4 #include "software_update.hpp" 5 6 #include <phosphor-logging/lg2.hpp> 7 #include <sdbusplus/async/context.hpp> 8 #include <xyz/openbmc_project/Association/Definitions/server.hpp> 9 #include <xyz/openbmc_project/Software/Activation/aserver.hpp> 10 #include <xyz/openbmc_project/Software/Update/aserver.hpp> 11 #include <xyz/openbmc_project/State/Host/client.hpp> 12 13 PHOSPHOR_LOG2_USING; 14 15 using namespace phosphor::software; 16 using namespace phosphor::software::device; 17 using namespace phosphor::software::config; 18 using namespace phosphor::software::update; 19 20 const static std::string baseObjPathSoftware = "/xyz/openbmc_project/software/"; 21 22 Software::Software(sdbusplus::async::context& ctx, Device& parent) : 23 Software(ctx, parent, getRandomSoftwareId(parent)) 24 {} 25 26 Software::Software(sdbusplus::async::context& ctx, Device& parent, 27 const std::string& swid) : 28 SoftwareActivation(ctx, (baseObjPathSoftware + swid).c_str(), 29 Activation::properties_t{Activations::NotReady, 30 RequestedActivations::None}), 31 objectPath(baseObjPathSoftware + swid), parentDevice(parent), swid(swid), 32 ctx(ctx) 33 { 34 std::string objPath = baseObjPathSoftware + swid; 35 36 debug("{SWID}: created dbus interfaces on path {OBJPATH}", "SWID", swid, 37 "OBJPATH", objPath); 38 }; 39 40 long int Software::getRandomId() 41 { 42 struct timespec ts; 43 clock_gettime(CLOCK_REALTIME, &ts); 44 unsigned int seed = ts.tv_nsec ^ getpid(); 45 srandom(seed); 46 return random() % 10000; 47 } 48 49 std::string Software::getRandomSoftwareId(Device& parent) 50 { 51 return std::format("{}_{}", parent.config.configName, getRandomId()); 52 } 53 54 sdbusplus::async::task<> Software::createInventoryAssociations(bool isRunning) 55 { 56 debug("{SWID}: setting association definitions", "SWID", swid); 57 58 std::string endpoint = ""; 59 60 try 61 { 62 endpoint = co_await parentDevice.config.getInventoryItemObjectPath(ctx); 63 } 64 catch (std::exception& e) 65 { 66 error(e.what()); 67 } 68 69 if (!associationDefinitions) 70 { 71 std::string path = objectPath; 72 associationDefinitions = 73 std::make_unique<SoftwareAssociationDefinitions>( 74 ctx, path.c_str(), 75 SoftwareAssociationDefinitions::properties_t{{}}); 76 } 77 78 if (endpoint.empty()) 79 { 80 co_return; 81 } 82 83 std::vector<std::tuple<std::string, std::string, std::string>> assocs; 84 85 if (isRunning) 86 { 87 debug("{SWID}: creating 'running' association to {OBJPATH}", "SWID", 88 swid, "OBJPATH", endpoint); 89 std::tuple<std::string, std::string, std::string> assocRunning = { 90 "running", "ran_on", endpoint}; 91 assocs.push_back(assocRunning); 92 } 93 else 94 { 95 debug("{SWID}: creating 'activating' association to {OBJPATH}", "SWID", 96 swid, "OBJPATH", endpoint); 97 std::tuple<std::string, std::string, std::string> assocActivating = { 98 "activating", "activated_on", endpoint}; 99 assocs.push_back(assocActivating); 100 } 101 102 associationDefinitions->associations(assocs); 103 104 co_return; 105 } 106 107 void Software::setVersion(const std::string& versionStr, 108 SoftwareVersion::VersionPurpose versionPurpose) 109 { 110 debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr); 111 112 if (!version) 113 { 114 version = std::make_unique<SoftwareVersion>( 115 ctx, objectPath.str.c_str(), 116 SoftwareVersion::properties_t{versionStr, versionPurpose}); 117 version->emit_added(); 118 return; 119 } 120 121 version->version(versionStr); 122 version->purpose(versionPurpose); 123 } 124 125 SoftwareVersion::VersionPurpose Software::getPurpose() 126 { 127 return version->purpose(); 128 } 129 130 void Software::setActivationBlocksTransition(bool enabled) 131 { 132 if (!enabled) 133 { 134 activationBlocksTransition = nullptr; 135 return; 136 } 137 138 std::string path = objectPath; 139 activationBlocksTransition = 140 std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str()); 141 } 142 143 void Software::setActivation(SoftwareActivation::Activations act) 144 { 145 activation(act); 146 } 147 148 void Software::enableUpdate( 149 const std::set<RequestedApplyTimes>& allowedApplyTimes) 150 { 151 if (updateIntf != nullptr) 152 { 153 error("[Software] update of {OBJPATH} has already been enabled", 154 "OBJPATH", objectPath); 155 return; 156 } 157 158 debug( 159 "[Software] enabling update of {OBJPATH} (adding the update interface)", 160 "OBJPATH", objectPath); 161 162 updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(), 163 *this, allowedApplyTimes); 164 } 165