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 | |
Alexander Hansen | f2c95a0 | 2024-11-26 11:16:44 +0100 | [diff] [blame] | 58 | long int Software::getRandomId() |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 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 | |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 126 | void Software::setVersion(const std::string& versionStr, |
| 127 | SoftwareVersion::VersionPurpose versionPurpose) |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 128 | { |
| 129 | debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr); |
| 130 | |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 131 | const bool emitSignal = !version; |
| 132 | |
Alexander Hansen | ccec7c6 | 2025-02-21 17:17:45 +0100 | [diff] [blame] | 133 | if (!version) |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 134 | { |
Alexander Hansen | ccec7c6 | 2025-02-21 17:17:45 +0100 | [diff] [blame] | 135 | version = |
| 136 | std::make_unique<SoftwareVersion>(ctx, objectPath.str.c_str()); |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 137 | } |
| 138 | |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 139 | version->version(versionStr); |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 140 | version->purpose(versionPurpose); |
| 141 | |
| 142 | if (emitSignal) |
| 143 | { |
| 144 | version->emit_added(); |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | SoftwareVersion::VersionPurpose Software::getPurpose() |
| 149 | { |
| 150 | return version->purpose(); |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | void Software::setActivationBlocksTransition(bool enabled) |
| 154 | { |
| 155 | if (!enabled) |
| 156 | { |
| 157 | activationBlocksTransition = nullptr; |
| 158 | return; |
| 159 | } |
| 160 | |
| 161 | std::string path = objectPath; |
| 162 | activationBlocksTransition = |
| 163 | std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str()); |
| 164 | } |
| 165 | |
| 166 | void Software::setActivation(SoftwareActivation::Activations act) |
| 167 | { |
| 168 | activation(act); |
| 169 | } |
| 170 | |
| 171 | void Software::enableUpdate( |
| 172 | const std::set<RequestedApplyTimes>& allowedApplyTimes) |
| 173 | { |
| 174 | if (updateIntf != nullptr) |
| 175 | { |
| 176 | error("[Software] update of {OBJPATH} has already been enabled", |
| 177 | "OBJPATH", objectPath); |
| 178 | return; |
| 179 | } |
| 180 | |
| 181 | debug( |
| 182 | "[Software] enabling update of {OBJPATH} (adding the update interface)", |
| 183 | "OBJPATH", objectPath); |
| 184 | |
| 185 | updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(), |
| 186 | *this, allowedApplyTimes); |
| 187 | } |