blob: 888d5c8a4bc456b9e23cf893be7e1070a6ef525c [file] [log] [blame]
Alexander Hansen1ba6e1c2024-11-26 11:16:44 +01001#include "spi_device_code_updater.hpp"
2
3#include "common/include/software_manager.hpp"
4#include "spi_device.hpp"
5
6#include <gpiod.hpp>
7#include <phosphor-logging/lg2.hpp>
8#include <sdbusplus/async.hpp>
9#include <sdbusplus/bus.hpp>
10#include <xyz/openbmc_project/ObjectMapper/client.hpp>
11
12SPIDeviceCodeUpdater::SPIDeviceCodeUpdater(sdbusplus::async::context& ctx,
13 bool isDryRun, bool debug) :
14 SoftwareManager(ctx, configTypeSPIDevice, isDryRun), debug(debug)
15{}
16
17// NOLINTBEGIN
18sdbusplus::async::task<>
19 SPIDeviceCodeUpdater::getInitialConfigurationSingleDevice(
20 const std::string& service, const std::string& path,
21 DeviceConfig& config)
22// NOLINTEND
23{
24 std::optional<std::string> optSpiPath =
25 co_await SoftwareManager::dbusGetRequiredConfigurationProperty<
26 std::string>(service, path, "Path", config);
27
28 std::optional<bool> optHasME =
29 co_await SoftwareManager::dbusGetRequiredConfigurationProperty<bool>(
30 service, path, "HasME", config);
31
32 std::optional<std::string> optLayout =
33 co_await SoftwareManager::dbusGetRequiredConfigurationProperty<
34 std::string>(service, path, "Layout", config);
35
36 std::optional<std::string> optTool =
37 co_await SoftwareManager::dbusGetRequiredConfigurationProperty<
38 std::string>(service, path, "Tool", config);
39
40 if (!optSpiPath.has_value() || !optHasME.has_value())
41 {
42 co_return;
43 }
44
45 std::string spiPath = optSpiPath.value();
46 bool hasME = optHasME.value();
47
48 lg2::debug("[config] spi device: {SPIDEV}", "SPIDEV", spiPath);
49
50 std::vector<std::string> gpioLines;
51 std::vector<uint8_t> gpioValues;
52
53 std::string configIntfMuxGpios;
54
55 std::vector<std::string> configIntfs = {
56 "xyz.openbmc_project.Configuration." + configTypeSPIDevice};
57
58 for (auto& iface : configIntfs)
59 {
60 configIntfMuxGpios = iface + ".MuxGpios";
61 }
62
63 for (size_t i = 0; true; i++)
64 {
65 std::string intf = configIntfMuxGpios + std::to_string(i);
66 std::optional<std::string> optGpioName =
67 co_await SoftwareManager::dbusGetRequiredProperty<std::string>(
68 service, path, intf, "Name");
69 std::optional<std::string> optGpioPolarity =
70 co_await SoftwareManager::dbusGetRequiredProperty<std::string>(
71 service, path, intf, "Polarity");
72
73 if (!optGpioName.has_value() || !optGpioPolarity.has_value())
74 {
75 break;
76 }
77
78 gpioLines.push_back(optGpioName.value());
79 gpioValues.push_back((optGpioPolarity.value() == "High") ? 1 : 0);
80
81 lg2::debug("[config] gpio {NAME} = {VALUE}", "NAME",
82 optGpioName.value(), "VALUE", optGpioPolarity.value());
83 }
84
85 lg2::debug("[config] extracted {N} gpios from EM config", "N",
86 gpioLines.size());
87
88 bool layoutFlat;
89
90 if (!optLayout.has_value())
91 {
92 lg2::info("[config] error: no flash layout chosen (property 'Layout')");
93 co_return;
94 }
95
96 const std::string& layout = optLayout.value();
97 if (layout == "Flat")
98 {
99 layoutFlat = true;
100 }
101 else if (layout == "IFD")
102 {
103 layoutFlat = false;
104 }
105 else
106 {
107 lg2::error("[config] unsupported flash layout config: {OPTION}",
108 "OPTION", layout);
109 lg2::info("supported options: 'Flat', 'IFD'");
110 co_return;
111 }
112
113 bool toolFlashrom;
114 if (!optTool.has_value())
115 {
116 lg2::error("[config] error: no tool chose (property 'Tool')");
117 co_return;
118 }
119
120 const std::string& tool = optTool.value();
121
122 if (tool == "flashrom")
123 {
124 toolFlashrom = true;
125 }
126 else if (tool == "None")
127 {
128 toolFlashrom = false;
129 }
130 else
131 {
132 lg2::error("[config] unsupported Tool: {OPTION}", "OPTION", tool);
133 co_return;
134 }
135
136 auto spiDevice = std::make_unique<SPIDevice>(
137 ctx, spiPath, dryRun, hasME, gpioLines, gpioValues, config, this,
138 layoutFlat, toolFlashrom, this->debug);
139
140 // we do not know the version on startup, it becomes known on update
141 std::string version = "unknown";
142
143 std::unique_ptr<Software> bsws =
144 std::make_unique<Software>(ctx, "spi_swid_unknown", *spiDevice);
145
146 bsws->setVersion("unknown");
147
148 // enable this software to be updated
149 std::set<RequestedApplyTimes> allowedApplyTimes = {
150 RequestedApplyTimes::Immediate, RequestedApplyTimes::OnReset};
151
152 bsws->enableUpdate(allowedApplyTimes);
153
154 spiDevice->softwareCurrent = std::move(bsws);
155
156 devices.insert(std::move(spiDevice));
157}