xref: /openbmc/phosphor-bmc-code-mgmt/bios/bios_software_manager.cpp (revision 2e168dba1029d1c5baaf065ad7306150dd3cafc2)
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