1 #include "bios_software_manager.hpp"
2
3 #include "common/include/dbus_helper.hpp"
4 #include "common/include/software_manager.hpp"
5 #include "spi_device.hpp"
6
7 #include <gpiod.hpp>
8 #include <phosphor-logging/lg2.hpp>
9 #include <sdbusplus/async.hpp>
10 #include <sdbusplus/bus.hpp>
11 #include <xyz/openbmc_project/ObjectMapper/client.hpp>
12
13 using namespace phosphor::software;
14
15 PHOSPHOR_LOG2_USING;
16
BIOSSoftwareManager(sdbusplus::async::context & ctx,bool isDryRun)17 BIOSSoftwareManager::BIOSSoftwareManager(sdbusplus::async::context& ctx,
18 bool isDryRun) :
19 SoftwareManager(ctx, configTypeBIOS), dryRun(isDryRun)
20 {}
21
initDevice(const std::string & service,const std::string & path,SoftwareConfig & config)22 sdbusplus::async::task<bool> BIOSSoftwareManager::initDevice(
23 const std::string& service, const std::string& path, SoftwareConfig& config)
24 {
25 std::string configIface =
26 "xyz.openbmc_project.Configuration." + config.configType;
27
28 std::optional<uint64_t> spiControllerIndex =
29 co_await dbusGetRequiredProperty<uint64_t>(
30 ctx, service, path, configIface, "SPIControllerIndex");
31
32 if (!spiControllerIndex.has_value())
33 {
34 error("Missing property: SPIControllerIndex");
35 co_return false;
36 }
37
38 std::optional<uint64_t> spiDeviceIndex =
39 co_await dbusGetRequiredProperty<uint64_t>(
40 ctx, service, path, configIface, "SPIDeviceIndex");
41
42 if (!spiDeviceIndex.has_value())
43 {
44 error("Missing property: SPIDeviceIndex");
45 co_return false;
46 }
47
48 enum FlashTool tool = flashToolNone;
49
50 if (config.configType == "IntelSPIFlash")
51 {
52 tool = flashToolFlashrom;
53 }
54 else if (config.configType == "SPIFlash")
55 {
56 tool = flashToolFlashcp;
57 }
58
59 const std::string configIfaceMux = configIface + ".MuxOutputs";
60
61 std::vector<std::string> names;
62 std::vector<uint64_t> values;
63
64 for (size_t i = 0; true; i++)
65 {
66 const std::string iface = configIfaceMux + std::to_string(i);
67
68 std::optional<std::string> name =
69 co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
70 iface, "Name");
71
72 std::optional<std::string> polarity =
73 co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
74 iface, "Polarity");
75
76 if (!name.has_value() || !polarity.has_value())
77 {
78 break;
79 }
80
81 names.push_back(name.value());
82 values.push_back((polarity == "High") ? 1 : 0);
83 }
84
85 enum FlashLayout layout = flashLayoutFlat;
86
87 debug("SPI device: {INDEX1}:{INDEX2}", "INDEX1", spiControllerIndex.value(),
88 "INDEX2", spiDeviceIndex.value());
89
90 std::unique_ptr<SPIDevice> spiDevice;
91 try
92 {
93 spiDevice = std::make_unique<SPIDevice>(
94 ctx, spiControllerIndex.value(), spiDeviceIndex.value(), dryRun,
95 names, values, config, this, layout, tool);
96 }
97 catch (std::exception& e)
98 {
99 co_return false;
100 }
101
102 std::unique_ptr<Software> software =
103 std::make_unique<Software>(ctx, *spiDevice);
104
105 // enable this software to be updated
106 std::set<RequestedApplyTimes> allowedApplyTimes = {
107 RequestedApplyTimes::Immediate, RequestedApplyTimes::OnReset};
108
109 software->enableUpdate(allowedApplyTimes);
110
111 spiDevice->softwareCurrent = std::move(software);
112
113 spiDevice->softwareCurrent->setVersion(
114 SPIDevice::getVersion(), SoftwareVersion::VersionPurpose::Host);
115
116 devices.insert({config.objectPath, std::move(spiDevice)});
117
118 co_return true;
119 }
120