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 | |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 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) : |
Alexander Hansen | df62819 | 2025-06-18 16:28:59 +0200 | [diff] [blame] | 28 | SoftwareActivation(ctx, (baseObjPathSoftware + swid).c_str(), |
| 29 | Activation::properties_t{Activations::NotReady, |
| 30 | RequestedActivations::None}), |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 31 | objectPath(baseObjPathSoftware + swid), parentDevice(parent), swid(swid), |
| 32 | ctx(ctx) |
| 33 | { |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 34 | std::string objPath = baseObjPathSoftware + swid; |
| 35 | |
Alexander Hansen | 0fdb612 | 2025-07-09 14:33:13 +0200 | [diff] [blame] | 36 | emit_added(); |
| 37 | |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 38 | debug("{SWID}: created dbus interfaces on path {OBJPATH}", "SWID", swid, |
| 39 | "OBJPATH", objPath); |
| 40 | }; |
| 41 | |
Alexander Hansen | f2c95a0 | 2024-11-26 11:16:44 +0100 | [diff] [blame] | 42 | long int Software::getRandomId() |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 43 | { |
| 44 | struct timespec ts; |
| 45 | clock_gettime(CLOCK_REALTIME, &ts); |
| 46 | unsigned int seed = ts.tv_nsec ^ getpid(); |
| 47 | srandom(seed); |
| 48 | return random() % 10000; |
| 49 | } |
| 50 | |
| 51 | std::string Software::getRandomSoftwareId(Device& parent) |
| 52 | { |
| 53 | return std::format("{}_{}", parent.config.configName, getRandomId()); |
| 54 | } |
| 55 | |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 56 | sdbusplus::async::task<> Software::createInventoryAssociations(bool isRunning) |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 57 | { |
| 58 | debug("{SWID}: setting association definitions", "SWID", swid); |
| 59 | |
| 60 | std::string endpoint = ""; |
| 61 | |
| 62 | try |
| 63 | { |
| 64 | endpoint = co_await parentDevice.config.getInventoryItemObjectPath(ctx); |
| 65 | } |
| 66 | catch (std::exception& e) |
| 67 | { |
Alexander Hansen | d73d564 | 2025-07-23 14:05:06 +0200 | [diff] [blame] | 68 | error("Failed to create association with {ERROR}", "ERROR", e.what()); |
| 69 | co_return; |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 70 | } |
| 71 | |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 72 | if (endpoint.empty()) |
| 73 | { |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 74 | co_return; |
| 75 | } |
| 76 | |
Alexander Hansen | df62819 | 2025-06-18 16:28:59 +0200 | [diff] [blame] | 77 | std::vector<std::tuple<std::string, std::string, std::string>> assocs; |
| 78 | |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 79 | if (isRunning) |
| 80 | { |
| 81 | debug("{SWID}: creating 'running' association to {OBJPATH}", "SWID", |
| 82 | swid, "OBJPATH", endpoint); |
| 83 | std::tuple<std::string, std::string, std::string> assocRunning = { |
| 84 | "running", "ran_on", endpoint}; |
| 85 | assocs.push_back(assocRunning); |
| 86 | } |
| 87 | else |
| 88 | { |
| 89 | debug("{SWID}: creating 'activating' association to {OBJPATH}", "SWID", |
| 90 | swid, "OBJPATH", endpoint); |
| 91 | std::tuple<std::string, std::string, std::string> assocActivating = { |
| 92 | "activating", "activated_on", endpoint}; |
| 93 | assocs.push_back(assocActivating); |
| 94 | } |
| 95 | |
Alexander Hansen | d73d564 | 2025-07-23 14:05:06 +0200 | [diff] [blame] | 96 | if (associationDefinitions) |
| 97 | { |
| 98 | associationDefinitions->associations(assocs); |
| 99 | } |
| 100 | else |
| 101 | { |
| 102 | std::string path = objectPath; |
| 103 | associationDefinitions = |
| 104 | std::make_unique<SoftwareAssociationDefinitions>( |
| 105 | ctx, path.c_str(), |
| 106 | SoftwareAssociationDefinitions::properties_t{assocs}); |
| 107 | associationDefinitions->emit_added(); |
| 108 | } |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 109 | |
| 110 | co_return; |
| 111 | } |
| 112 | |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 113 | void Software::setVersion(const std::string& versionStr, |
| 114 | SoftwareVersion::VersionPurpose versionPurpose) |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 115 | { |
| 116 | debug("{SWID}: set version {VERSION}", "SWID", swid, "VERSION", versionStr); |
| 117 | |
Alexander Hansen | ccec7c6 | 2025-02-21 17:17:45 +0100 | [diff] [blame] | 118 | if (!version) |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 119 | { |
Alexander Hansen | df62819 | 2025-06-18 16:28:59 +0200 | [diff] [blame] | 120 | version = std::make_unique<SoftwareVersion>( |
| 121 | ctx, objectPath.str.c_str(), |
| 122 | SoftwareVersion::properties_t{versionStr, versionPurpose}); |
| 123 | version->emit_added(); |
| 124 | return; |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 125 | } |
| 126 | |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 127 | version->version(versionStr); |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 128 | version->purpose(versionPurpose); |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 129 | } |
| 130 | |
Alexander Hansen | b0cfda6 | 2025-07-18 16:30:32 +0200 | [diff] [blame] | 131 | std::optional<SoftwareVersion::VersionPurpose> Software::getPurpose() |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 132 | { |
Alexander Hansen | b0cfda6 | 2025-07-18 16:30:32 +0200 | [diff] [blame] | 133 | if (!version) |
| 134 | { |
| 135 | return std::nullopt; |
| 136 | } |
Alexander Hansen | de5e76f | 2025-02-20 16:30:11 +0100 | [diff] [blame] | 137 | return version->purpose(); |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | void Software::setActivationBlocksTransition(bool enabled) |
| 141 | { |
| 142 | if (!enabled) |
| 143 | { |
| 144 | activationBlocksTransition = nullptr; |
| 145 | return; |
| 146 | } |
| 147 | |
| 148 | std::string path = objectPath; |
| 149 | activationBlocksTransition = |
| 150 | std::make_unique<SoftwareActivationBlocksTransition>(ctx, path.c_str()); |
Alexander Hansen | 0fdb612 | 2025-07-09 14:33:13 +0200 | [diff] [blame] | 151 | |
| 152 | activationBlocksTransition->emit_added(); |
Alexander Hansen | cc37235 | 2025-01-14 14:15:39 +0100 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | void Software::setActivation(SoftwareActivation::Activations act) |
| 156 | { |
| 157 | activation(act); |
| 158 | } |
| 159 | |
| 160 | void Software::enableUpdate( |
| 161 | const std::set<RequestedApplyTimes>& allowedApplyTimes) |
| 162 | { |
| 163 | if (updateIntf != nullptr) |
| 164 | { |
| 165 | error("[Software] update of {OBJPATH} has already been enabled", |
| 166 | "OBJPATH", objectPath); |
| 167 | return; |
| 168 | } |
| 169 | |
| 170 | debug( |
| 171 | "[Software] enabling update of {OBJPATH} (adding the update interface)", |
| 172 | "OBJPATH", objectPath); |
| 173 | |
| 174 | updateIntf = std::make_unique<SoftwareUpdate>(ctx, objectPath.str.c_str(), |
| 175 | *this, allowedApplyTimes); |
| 176 | } |