xref: /openbmc/phosphor-bmc-code-mgmt/bios/bios_software_manager.cpp (revision 7e446a407a579ec72f48009008ad2f83c01c2262)
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 
17 BIOSSoftwareManager::BIOSSoftwareManager(sdbusplus::async::context& ctx,
18                                          bool isDryRun) :
19     SoftwareManager(ctx, configTypeBIOS), dryRun(isDryRun)
20 {}
21 
22 // NOLINTBEGIN(readability-static-accessed-through-instance)
23 sdbusplus::async::task<bool> BIOSSoftwareManager::initDevice(
24     const std::string& service, const std::string& path, SoftwareConfig& config)
25 // NOLINTEND(readability-static-accessed-through-instance)
26 {
27     std::string configIface =
28         "xyz.openbmc_project.Configuration." + config.configType;
29 
30     std::optional<int64_t> spiControllerIndex =
31         co_await dbusGetRequiredProperty<uint64_t>(
32             ctx, service, path, configIface, "SPIControllerIndex");
33 
34     std::optional<int64_t> spiDeviceIndex =
35         co_await dbusGetRequiredProperty<uint64_t>(
36             ctx, service, path, configIface, "SPIDeviceIndex");
37 
38     const std::string configIfaceMux = configIface + ".MuxOutputs";
39 
40     std::vector<std::string> names;
41     std::vector<uint64_t> values;
42 
43     for (size_t i = 0; true; i++)
44     {
45         const std::string iface = configIfaceMux + std::to_string(i);
46 
47         std::optional<std::string> name =
48             co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
49                                                           iface, "Name");
50 
51         std::optional<std::string> polarity =
52             co_await dbusGetRequiredProperty<std::string>(ctx, service, path,
53                                                           iface, "Polarity");
54 
55         if (!name.has_value() || !polarity.has_value())
56         {
57             break;
58         }
59 
60         names.push_back(name.value());
61         values.push_back((polarity == "High") ? 1 : 0);
62     }
63 
64     if (!spiControllerIndex.has_value() || !spiDeviceIndex.has_value())
65     {
66         error("Error: Missing property");
67         co_return false;
68     }
69 
70     enum FlashLayout layout = flashLayoutFlat;
71     enum FlashTool tool = flashToolNone;
72 
73     debug("SPI device: {INDEX1}:{INDEX2}", "INDEX1", spiControllerIndex.value(),
74           "INDEX2", spiDeviceIndex.value());
75 
76     std::unique_ptr<SPIDevice> spiDevice;
77     try
78     {
79         spiDevice = std::make_unique<SPIDevice>(
80             ctx, spiControllerIndex.value(), spiDeviceIndex.value(), dryRun,
81             names, values, config, this, layout, tool);
82     }
83     catch (std::exception& e)
84     {
85         co_return false;
86     }
87 
88     std::unique_ptr<Software> software =
89         std::make_unique<Software>(ctx, *spiDevice);
90 
91     // enable this software to be updated
92     std::set<RequestedApplyTimes> allowedApplyTimes = {
93         RequestedApplyTimes::Immediate, RequestedApplyTimes::OnReset};
94 
95     software->enableUpdate(allowedApplyTimes);
96 
97     spiDevice->softwareCurrent = std::move(software);
98 
99     spiDevice->softwareCurrent->setVersion(SPIDevice::getVersion());
100 
101     devices.insert({config.objectPath, std::move(spiDevice)});
102 
103     co_return true;
104 }
105