10b02be92SPatrick Venture #include "settings.hpp"
20b02be92SPatrick Venture 
36a98fe7fSVernon Mauery #include <ipmid/utils.hpp>
418aa044eSDeepak Kodihalli #include <phosphor-logging/elog-errors.hpp>
518aa044eSDeepak Kodihalli #include <phosphor-logging/log.hpp>
64c008028SWilliam A. Kennington III #include <sdbusplus/message/types.hpp>
70b02be92SPatrick Venture #include <xyz/openbmc_project/Common/error.hpp>
818aa044eSDeepak Kodihalli 
918aa044eSDeepak Kodihalli namespace settings
1018aa044eSDeepak Kodihalli {
1118aa044eSDeepak Kodihalli 
1218aa044eSDeepak Kodihalli using namespace phosphor::logging;
13*523e2d1bSWilly Tu using namespace sdbusplus::error::xyz::openbmc_project::common;
1418aa044eSDeepak Kodihalli 
1518aa044eSDeepak Kodihalli constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
1618aa044eSDeepak Kodihalli constexpr auto mapperPath = "/xyz/openbmc_project/object_mapper";
1718aa044eSDeepak Kodihalli constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
1818aa044eSDeepak Kodihalli 
195d82f474SPatrick Williams Objects::Objects(sdbusplus::bus_t& bus, const std::vector<Interface>& filter) :
2018aa044eSDeepak Kodihalli     bus(bus)
2118aa044eSDeepak Kodihalli {
2218aa044eSDeepak Kodihalli     auto depth = 0;
2318aa044eSDeepak Kodihalli 
240b02be92SPatrick Venture     auto mapperCall = bus.new_method_call(mapperService, mapperPath, mapperIntf,
2518aa044eSDeepak Kodihalli                                           "GetSubTree");
2618aa044eSDeepak Kodihalli     mapperCall.append(root);
2718aa044eSDeepak Kodihalli     mapperCall.append(depth);
2818aa044eSDeepak Kodihalli     mapperCall.append(filter);
2918aa044eSDeepak Kodihalli 
3018aa044eSDeepak Kodihalli     using Interfaces = std::vector<Interface>;
3118aa044eSDeepak Kodihalli     using MapperResponse = std::map<Path, std::map<Service, Interfaces>>;
3218aa044eSDeepak Kodihalli     MapperResponse result;
333e3cc35bSGeorge Liu     try
3418aa044eSDeepak Kodihalli     {
353e3cc35bSGeorge Liu         auto response = bus.call(mapperCall);
363e3cc35bSGeorge Liu         response.read(result);
373e3cc35bSGeorge Liu     }
383e3cc35bSGeorge Liu     catch (const std::exception& e)
393e3cc35bSGeorge Liu     {
403e3cc35bSGeorge Liu         log<level::ERR>("Error in mapper GetSubTree",
413e3cc35bSGeorge Liu                         entry("ERROR=%s", e.what()));
4218aa044eSDeepak Kodihalli         elog<InternalFailure>();
4318aa044eSDeepak Kodihalli     }
4418aa044eSDeepak Kodihalli 
4518aa044eSDeepak Kodihalli     for (auto& iter : result)
4618aa044eSDeepak Kodihalli     {
4718aa044eSDeepak Kodihalli         const auto& path = iter.first;
48e602709dSDeepak Kodihalli         for (auto& interface : iter.second.begin()->second)
49e602709dSDeepak Kodihalli         {
50e602709dSDeepak Kodihalli             auto found = map.find(interface);
51e602709dSDeepak Kodihalli             if (map.end() != found)
52e602709dSDeepak Kodihalli             {
53e602709dSDeepak Kodihalli                 auto& paths = found->second;
54e602709dSDeepak Kodihalli                 paths.push_back(path);
55e602709dSDeepak Kodihalli             }
56e602709dSDeepak Kodihalli             else
57e602709dSDeepak Kodihalli             {
58e602709dSDeepak Kodihalli                 map.emplace(std::move(interface), std::vector<Path>({path}));
59e602709dSDeepak Kodihalli             }
60e602709dSDeepak Kodihalli         }
6118aa044eSDeepak Kodihalli     }
6218aa044eSDeepak Kodihalli }
6318aa044eSDeepak Kodihalli 
6418aa044eSDeepak Kodihalli Service Objects::service(const Path& path, const Interface& interface) const
6518aa044eSDeepak Kodihalli {
6618aa044eSDeepak Kodihalli     using Interfaces = std::vector<Interface>;
67fbc6c9d7SPatrick Williams     auto mapperCall = bus.new_method_call(mapperService, mapperPath, mapperIntf,
68fbc6c9d7SPatrick Williams                                           "GetObject");
6918aa044eSDeepak Kodihalli     mapperCall.append(path);
7018aa044eSDeepak Kodihalli     mapperCall.append(Interfaces({interface}));
7118aa044eSDeepak Kodihalli 
7218aa044eSDeepak Kodihalli     std::map<Service, Interfaces> result;
733e3cc35bSGeorge Liu     try
7418aa044eSDeepak Kodihalli     {
753e3cc35bSGeorge Liu         auto response = bus.call(mapperCall);
763e3cc35bSGeorge Liu         response.read(result);
773e3cc35bSGeorge Liu         return result.begin()->first;
783e3cc35bSGeorge Liu     }
793e3cc35bSGeorge Liu     catch (const std::exception& e)
803e3cc35bSGeorge Liu     {
813e3cc35bSGeorge Liu         log<level::ERR>("Invalid response from mapper",
823e3cc35bSGeorge Liu                         entry("ERROR=%s", e.what()));
8318aa044eSDeepak Kodihalli         elog<InternalFailure>();
8418aa044eSDeepak Kodihalli     }
8518aa044eSDeepak Kodihalli }
8618aa044eSDeepak Kodihalli 
8713791bd5SDeepak Kodihalli namespace boot
8813791bd5SDeepak Kodihalli {
8913791bd5SDeepak Kodihalli 
9013791bd5SDeepak Kodihalli std::tuple<Path, OneTimeEnabled> setting(const Objects& objects,
9113791bd5SDeepak Kodihalli                                          const Interface& iface)
9213791bd5SDeepak Kodihalli {
9313791bd5SDeepak Kodihalli     constexpr auto bootObjCount = 2;
9413791bd5SDeepak Kodihalli     constexpr auto oneTime = "one_time";
9513791bd5SDeepak Kodihalli     constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
9613791bd5SDeepak Kodihalli 
9713791bd5SDeepak Kodihalli     const std::vector<Path>& paths = objects.map.at(iface);
9813791bd5SDeepak Kodihalli     auto count = paths.size();
9913791bd5SDeepak Kodihalli     if (count != bootObjCount)
10013791bd5SDeepak Kodihalli     {
10113791bd5SDeepak Kodihalli         log<level::ERR>("Exactly two objects expected",
10213791bd5SDeepak Kodihalli                         entry("INTERFACE=%s", iface.c_str()),
10313791bd5SDeepak Kodihalli                         entry("COUNT=%d", count));
10413791bd5SDeepak Kodihalli         elog<InternalFailure>();
10513791bd5SDeepak Kodihalli     }
10613791bd5SDeepak Kodihalli     size_t index = 0;
10713791bd5SDeepak Kodihalli     if (std::string::npos == paths[0].rfind(oneTime))
10813791bd5SDeepak Kodihalli     {
10913791bd5SDeepak Kodihalli         index = 1;
11013791bd5SDeepak Kodihalli     }
11113791bd5SDeepak Kodihalli     const Path& oneTimeSetting = paths[index];
11213791bd5SDeepak Kodihalli     const Path& regularSetting = paths[!index];
11313791bd5SDeepak Kodihalli 
1140b02be92SPatrick Venture     auto method = objects.bus.new_method_call(
1150b02be92SPatrick Venture         objects.service(oneTimeSetting, iface).c_str(), oneTimeSetting.c_str(),
1160b02be92SPatrick Venture         ipmi::PROP_INTF, "Get");
11713791bd5SDeepak Kodihalli     method.append(enabledIntf, "Enabled");
1183e3cc35bSGeorge Liu 
1193e3cc35bSGeorge Liu     std::variant<bool> enabled;
1203e3cc35bSGeorge Liu     try
1213e3cc35bSGeorge Liu     {
12213791bd5SDeepak Kodihalli         auto reply = objects.bus.call(method);
1233e3cc35bSGeorge Liu         reply.read(enabled);
1243e3cc35bSGeorge Liu     }
1253e3cc35bSGeorge Liu     catch (const std::exception& e)
12613791bd5SDeepak Kodihalli     {
12713791bd5SDeepak Kodihalli         log<level::ERR>("Error in getting Enabled property",
12813791bd5SDeepak Kodihalli                         entry("OBJECT=%s", oneTimeSetting.c_str()),
1293e3cc35bSGeorge Liu                         entry("INTERFACE=%s", iface.c_str()),
1303e3cc35bSGeorge Liu                         entry("ERROR=%s", e.what()));
13113791bd5SDeepak Kodihalli         elog<InternalFailure>();
13213791bd5SDeepak Kodihalli     }
13313791bd5SDeepak Kodihalli 
134f442e119SVernon Mauery     auto oneTimeEnabled = std::get<bool>(enabled);
13513791bd5SDeepak Kodihalli     const Path& setting = oneTimeEnabled ? oneTimeSetting : regularSetting;
13613791bd5SDeepak Kodihalli     return std::make_tuple(setting, oneTimeEnabled);
13713791bd5SDeepak Kodihalli }
13813791bd5SDeepak Kodihalli 
13913791bd5SDeepak Kodihalli } // namespace boot
14013791bd5SDeepak Kodihalli 
14118aa044eSDeepak Kodihalli } // namespace settings
142