1 #include "config.h"
2 
3 #ifdef UBIFS_LAYOUT
4 #include "ubi/item_updater_ubi.hpp"
5 #include "ubi/watch.hpp"
6 #elif defined MMC_LAYOUT
7 #include "mmc/item_updater_mmc.hpp"
8 #else
9 #include "static/item_updater_static.hpp"
10 #endif
11 #include "functions.hpp"
12 
13 #include <CLI/CLI.hpp>
14 #include <phosphor-logging/log.hpp>
15 #include <sdbusplus/bus.hpp>
16 #include <sdbusplus/server/manager.hpp>
17 #include <sdeventplus/event.hpp>
18 
19 #include <map>
20 #include <memory>
21 #include <string>
22 #include <system_error>
23 #include <vector>
24 
25 namespace openpower
26 {
27 namespace software
28 {
29 namespace updater
30 {
31 void initializeService(sdbusplus::bus::bus& bus)
32 {
33     static sdbusplus::server::manager::manager objManager(bus,
34                                                           SOFTWARE_OBJPATH);
35 #ifdef UBIFS_LAYOUT
36     static ItemUpdaterUbi updater(bus, SOFTWARE_OBJPATH);
37     static Watch watch(
38         bus.get_event(),
39         std::bind(std::mem_fn(&ItemUpdater::updateFunctionalAssociation),
40                   &updater, std::placeholders::_1));
41 #elif defined MMC_LAYOUT
42     static ItemUpdaterMMC updater(bus, SOFTWARE_OBJPATH);
43 #else
44     static ItemUpdaterStatic updater(bus, SOFTWARE_OBJPATH);
45 #endif
46     bus.request_name(BUSNAME_UPDATER);
47 }
48 } // namespace updater
49 } // namespace software
50 } // namespace openpower
51 
52 int main(int argc, char* argv[])
53 {
54     using namespace openpower::software::updater;
55     using namespace phosphor::logging;
56     auto bus = sdbusplus::bus::new_default();
57     auto loop = sdeventplus::Event::get_default();
58 
59     bus.attach_event(loop.get(), SD_EVENT_PRIORITY_NORMAL);
60 
61     CLI::App app{"OpenPOWER host firmware manager"};
62 
63     // subcommandContext allows program subcommand callbacks to add loop event
64     // callbacks (e.g. reception of a dbus signal) and then return to main,
65     // without the loop event callback being destroyed until the loop event
66     // callback has a chance to run and instruct the loop to exit.
67     std::shared_ptr<void> subcommandContext;
68     static_cast<void>(
69         app.add_subcommand("process-host-firmware",
70                            "Point the host firmware at its data.")
71             ->callback([&bus, &loop, &subcommandContext]() {
72                 using namespace std::string_literals;
73                 std::map<std::string, std::vector<std::string>> extensionMap{{
74                     {"ibm,everest"s, {".EVEREST_XML"s, ".P10"s}},
75                     {"ibm,rainier-2u"s, {".RAINIER_2U_XML"s, ".P10"s}},
76                     {"ibm,rainier-4u"s, {".RAINIER_4U_XML"s, ".P10"s}},
77                 }};
78                 auto hostFirmwareDirectory = "/media/hostfw/running"s;
79                 auto logCallback = [](const auto& path, auto& ec) {
80                     std::cerr << path << ": " << ec.message() << "\n";
81                 };
82                 subcommandContext =
83                     functions::process_hostfirmware::processHostFirmware(
84                         bus, std::move(extensionMap),
85                         std::move(hostFirmwareDirectory),
86                         std::move(logCallback), loop);
87             }));
88     CLI11_PARSE(app, argc, argv);
89 
90     if (app.get_subcommands().size() == 0)
91     {
92         initializeService(bus);
93     }
94 
95     try
96     {
97         auto rc = loop.loop();
98         if (rc < 0)
99         {
100             log<level::ERR>("Error occurred during the sd_event_loop",
101                             entry("RC=%d", rc));
102             return -1;
103         }
104     }
105     catch (const std::system_error& e)
106     {
107         log<level::ERR>(e.what());
108         return -1;
109     }
110 
111     return 0;
112 }
113