blob: 9092fe755b39cbf94c5b0618628b2de0f6311d5c [file] [log] [blame]
Andrew Geisslere426b582020-05-28 12:40:55 -05001#include "config.h"
2
Andrew Geissler0971dea2017-03-28 14:32:40 -05003#include <unistd.h>
Andrew Geisslere426b582020-05-28 12:40:55 -05004
5#include <phosphor-logging/log.hpp>
Andrew Geisslerb09463d2017-03-24 15:55:17 -05006#include <sdbusplus/bus.hpp>
Anthony Wilson32c532e2018-10-25 21:56:07 -05007#include <sdbusplus/exception.hpp>
Andrew Geissler2d7b69e2021-05-06 13:12:45 -05008#include <xyz/openbmc_project/Condition/HostFirmware/server.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -05009
10#include <cstdio>
11#include <cstdlib>
12#include <fstream>
13#include <iostream>
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050014#include <vector>
Andrew Geisslerb09463d2017-03-24 15:55:17 -050015
Andrew Geisslereeaccf82017-03-28 15:23:27 -050016using namespace std::literals;
Andrew Geisslerb09463d2017-03-24 15:55:17 -050017using namespace phosphor::logging;
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050018using namespace sdbusplus::xyz::openbmc_project::Condition::server;
Anthony Wilson32c532e2018-10-25 21:56:07 -050019using sdbusplus::exception::SdBusError;
Andrew Geissler0971dea2017-03-28 14:32:40 -050020
Andrew Geisslereeaccf82017-03-28 15:23:27 -050021// Required strings for sending the msg to check on host
22constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
23constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
24constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050025constexpr auto CONDITION_HOST_INTERFACE =
26 "xyz.openbmc_project.Condition.HostFirmware";
27constexpr auto CONDITION_HOST_PROPERTY = "CurrentFirmwareCondition";
28constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
Andrew Geissler0971dea2017-03-28 14:32:40 -050029
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050030// Find all implementations of Condition interface and check if host is
31// running over it
32bool checkFirmwareConditionRunning(sdbusplus::bus::bus& bus)
Andrew Geissler0971dea2017-03-28 14:32:40 -050033{
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050034 // Find all implementations of host firmware condition interface
Andrew Geissler58a18012018-01-19 19:36:05 -080035 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050036 MAPPER_INTERFACE, "GetSubTree");
Andrew Geisslereeaccf82017-03-28 15:23:27 -050037
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050038 mapper.append("/", 0, std::vector<std::string>({CONDITION_HOST_INTERFACE}));
Andrew Geisslereeaccf82017-03-28 15:23:27 -050039
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050040 std::map<std::string, std::map<std::string, std::vector<std::string>>>
41 mapperResponse;
Anthony Wilson32c532e2018-10-25 21:56:07 -050042
43 try
44 {
45 auto mapperResponseMsg = bus.call(mapper);
46 mapperResponseMsg.read(mapperResponse);
47 }
48 catch (const SdBusError& e)
49 {
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050050 log<level::ERR>(
51 "Error in mapper GetSubTree call for HostFirmware condition",
52 entry("ERROR=%s", e.what()));
Anthony Wilson32c532e2018-10-25 21:56:07 -050053 throw;
Andrew Geisslereeaccf82017-03-28 15:23:27 -050054 }
55
Andrew Geissler2d7b69e2021-05-06 13:12:45 -050056 if (mapperResponse.empty())
57 {
58 log<level::INFO>(
59 "Mapper response for HostFirmware conditions is empty!");
60 return false;
61 }
62
63 // Now read the CurrentFirmwareCondition from all interfaces we found
64 for (const auto& [path, services] : mapperResponse)
65 {
66 for (const auto& serviceIter : services)
67 {
68 const std::string& service = serviceIter.first;
69
70 try
71 {
72 auto method = bus.new_method_call(service.c_str(), path.c_str(),
73 PROPERTY_INTERFACE, "Get");
74 method.append(CONDITION_HOST_INTERFACE,
75 CONDITION_HOST_PROPERTY);
76
77 auto response = bus.call(method);
78
79 std::variant<std::string> currentFwCond;
80 response.read(currentFwCond);
81
82 if (std::get<std::string>(currentFwCond) ==
83 "xyz.openbmc_project.Condition.HostFirmware."
84 "FirmwareCondition."
85 "Running")
86 {
87 return true;
88 }
89 }
90 catch (const SdBusError& e)
91 {
92 log<level::ERR>("Error reading HostFirmware condition",
93 entry("ERROR=%s", e.what()),
94 entry("SERVICE=%s", service.c_str()),
95 entry("PATH=%s", path.c_str()));
96 throw;
97 }
98 }
99 }
100 return false;
Andrew Geisslereeaccf82017-03-28 15:23:27 -0500101}
102
Andrew Geissler769a62f2019-12-06 13:36:08 -0600103int main()
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500104{
105 log<level::INFO>("Check if host is running");
106
Andrew Geissler0971dea2017-03-28 14:32:40 -0500107 auto bus = sdbusplus::bus::new_default();
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500108
Andrew Geissler2d7b69e2021-05-06 13:12:45 -0500109 if (checkFirmwareConditionRunning(bus))
Andrew Geissler0971dea2017-03-28 14:32:40 -0500110 {
Andrew Geissler0971dea2017-03-28 14:32:40 -0500111 log<level::INFO>("Host is running!");
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500112 // Create file for host instance and create in filesystem to indicate
113 // to services that host is running
Andrew Geissler58a18012018-01-19 19:36:05 -0800114 auto size = std::snprintf(nullptr, 0, HOST_RUNNING_FILE, 0);
Andrew Geissler0135bd52017-05-09 13:54:10 -0500115 size++; // null
116 std::unique_ptr<char[]> buf(new char[size]);
Andrew Geissler58a18012018-01-19 19:36:05 -0800117 std::snprintf(buf.get(), size, HOST_RUNNING_FILE, 0);
Andrew Geissler07d0ed52017-03-28 15:44:18 -0500118 std::ofstream outfile(buf.get());
119 outfile.close();
120 }
121 else
122 {
123 log<level::INFO>("Host is not running!");
Andrew Geissler0971dea2017-03-28 14:32:40 -0500124 }
Andrew Geisslerb09463d2017-03-24 15:55:17 -0500125
126 return 0;
127}