| Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 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 | SoftwareActivationProgress::SoftwareActivationProgress( | 
|  | 23 | sdbusplus::async::context& ctx, const char* objPath) : | 
|  | 24 | ActivationProgress(ctx, objPath) | 
|  | 25 | { | 
|  | 26 | // This prevents "Conditional jump or move depends on uninitialised | 
|  | 27 | // value(s)" | 
|  | 28 | // when properties are updated for the first time | 
|  | 29 | progress_ = 0; | 
|  | 30 | } | 
|  | 31 |  | 
|  | 32 | void SoftwareActivationProgress::setProgress(int progressArg) | 
|  | 33 | { | 
|  | 34 | progress(progressArg); | 
|  | 35 | } | 
|  | 36 |  | 
|  | 37 | Software::Software(sdbusplus::async::context& ctx, Device& parent) : | 
|  | 38 | Software(ctx, parent, getRandomSoftwareId(parent)) | 
|  | 39 | {} | 
|  | 40 |  | 
|  | 41 | Software::Software(sdbusplus::async::context& ctx, Device& parent, | 
|  | 42 | const std::string& swid) : | 
|  | 43 | SoftwareActivation(ctx, (baseObjPathSoftware + swid).c_str()), | 
|  | 44 | objectPath(baseObjPathSoftware + swid), parentDevice(parent), swid(swid), | 
|  | 45 | ctx(ctx) | 
|  | 46 | { | 
|  | 47 | // initialize the members of our base class to prevent | 
|  | 48 | // "Conditional jump or move depends on uninitialised value(s)" | 
|  | 49 | activation_ = Activations::NotReady; | 
|  | 50 | requested_activation_ = RequestedActivations::None; | 
|  | 51 |  | 
|  | 52 | std::string objPath = baseObjPathSoftware + swid; | 
|  | 53 |  | 
|  | 54 | debug("{SWID}: created dbus interfaces on path {OBJPATH}", "SWID", swid, | 
|  | 55 | "OBJPATH", objPath); | 
|  | 56 | }; | 
|  | 57 |  | 
|  | 58 | static long int getRandomId() | 
|  | 59 | { | 
|  | 60 | struct timespec ts; | 
|  | 61 | clock_gettime(CLOCK_REALTIME, &ts); | 
|  | 62 | unsigned int seed = ts.tv_nsec ^ getpid(); | 
|  | 63 | srandom(seed); | 
|  | 64 | return random() % 10000; | 
|  | 65 | } | 
|  | 66 |  | 
|  | 67 | std::string Software::getRandomSoftwareId(Device& parent) | 
|  | 68 | { | 
|  | 69 | return std::format("{}_{}", parent.config.configName, getRandomId()); | 
|  | 70 | } | 
|  | 71 |  | 
|  | 72 | // NOLINTBEGIN(readability-static-accessed-through-instance) | 
|  | 73 | sdbusplus::async::task<> Software::createInventoryAssociations(bool isRunning) | 
|  | 74 | // NOLINTEND(readability-static-accessed-through-instance) | 
|  | 75 | { | 
|  | 76 | debug("{SWID}: setting association definitions", "SWID", swid); | 
|  | 77 |  | 
|  | 78 | std::string endpoint = ""; | 
|  | 79 |  | 
|  | 80 | try | 
|  | 81 | { | 
|  | 82 | endpoint = co_await parentDevice.config.getInventoryItemObjectPath(ctx); | 
|  | 83 | } | 
|  | 84 | catch (std::exception& e) | 
|  | 85 | { | 
|  | 86 | error(e.what()); | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | if (!associationDefinitions) | 
|  | 90 | { | 
|  | 91 | std::string path = objectPath; | 
|  | 92 | associationDefinitions = | 
|  | 93 | std::make_unique<SoftwareAssociationDefinitions>(ctx, path.c_str()); | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | std::vector<std::tuple<std::string, std::string, std::string>> assocs; | 
|  | 97 |  | 
|  | 98 | if (endpoint.empty()) | 
|  | 99 | { | 
|  | 100 | associationDefinitions->associations(assocs); | 
|  | 101 | co_return; | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | if (isRunning) | 
|  | 105 | { | 
|  | 106 | debug("{SWID}: creating 'running' association to {OBJPATH}", "SWID", | 
|  | 107 | swid, "OBJPATH", endpoint); | 
|  | 108 | std::tuple<std::string, std::string, std::string> assocRunning = { | 
|  | 109 | "running", "ran_on", endpoint}; | 
|  | 110 | assocs.push_back(assocRunning); | 
|  | 111 | } | 
|  | 112 | else | 
|  | 113 | { | 
|  | 114 | debug("{SWID}: creating 'activating' association to {OBJPATH}", "SWID", | 
|  | 115 | swid, "OBJPATH", endpoint); | 
|  | 116 | std::tuple<std::string, std::string, std::string> assocActivating = { | 
|  | 117 | "activating", "activated_on", endpoint}; | 
|  | 118 | assocs.push_back(assocActivating); | 
|  | 119 | } | 
|  | 120 |  | 
|  | 121 | associationDefinitions->associations(assocs); | 
|  | 122 |  | 
|  | 123 | co_return; | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | void Software::setVersion(const std::string& versionStr) | 
|  | 127 | { | 
|  | 128 | debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr); | 
|  | 129 |  | 
| Alexander Hansen | ccec7c6 | 2025-02-21 17:17:45 +0100 | [diff] [blame] | 130 | if (!version) | 
| Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 131 | { | 
| Alexander Hansen | ccec7c6 | 2025-02-21 17:17:45 +0100 | [diff] [blame] | 132 | version = | 
|  | 133 | std::make_unique<SoftwareVersion>(ctx, objectPath.str.c_str()); | 
| Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 134 | } | 
|  | 135 |  | 
| Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 136 | version->version(versionStr); | 
|  | 137 | } | 
|  | 138 |  | 
|  | 139 | void Software::setActivationBlocksTransition(bool enabled) | 
|  | 140 | { | 
|  | 141 | if (!enabled) | 
|  | 142 | { | 
|  | 143 | activationBlocksTransition = nullptr; | 
|  | 144 | return; | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | std::string path = objectPath; | 
|  | 148 | activationBlocksTransition = | 
|  | 149 | std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str()); | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | void Software::setActivation(SoftwareActivation::Activations act) | 
|  | 153 | { | 
|  | 154 | activation(act); | 
|  | 155 | } | 
|  | 156 |  | 
|  | 157 | void Software::enableUpdate( | 
|  | 158 | const std::set<RequestedApplyTimes>& allowedApplyTimes) | 
|  | 159 | { | 
|  | 160 | if (updateIntf != nullptr) | 
|  | 161 | { | 
|  | 162 | error("[Software] update of {OBJPATH} has already been enabled", | 
|  | 163 | "OBJPATH", objectPath); | 
|  | 164 | return; | 
|  | 165 | } | 
|  | 166 |  | 
|  | 167 | debug( | 
|  | 168 | "[Software] enabling update of {OBJPATH} (adding the update interface)", | 
|  | 169 | "OBJPATH", objectPath); | 
|  | 170 |  | 
|  | 171 | updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(), | 
|  | 172 | *this, allowedApplyTimes); | 
|  | 173 | } |