10b02be92SPatrick Venture #include "settings.hpp"
20b02be92SPatrick Venture 
3*6a98fe7fSVernon 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;
1318aa044eSDeepak Kodihalli using namespace sdbusplus::xyz::openbmc_project::Common::Error;
144c008028SWilliam A. Kennington III namespace variant_ns = sdbusplus::message::variant_ns;
1518aa044eSDeepak Kodihalli 
1618aa044eSDeepak Kodihalli constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
1718aa044eSDeepak Kodihalli constexpr auto mapperPath = "/xyz/openbmc_project/object_mapper";
1818aa044eSDeepak Kodihalli constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
1918aa044eSDeepak Kodihalli 
2018aa044eSDeepak Kodihalli Objects::Objects(sdbusplus::bus::bus& bus,
2118aa044eSDeepak Kodihalli                  const std::vector<Interface>& filter) :
2218aa044eSDeepak Kodihalli     bus(bus)
2318aa044eSDeepak Kodihalli {
2418aa044eSDeepak Kodihalli     auto depth = 0;
2518aa044eSDeepak Kodihalli 
260b02be92SPatrick Venture     auto mapperCall = bus.new_method_call(mapperService, mapperPath, mapperIntf,
2718aa044eSDeepak Kodihalli                                           "GetSubTree");
2818aa044eSDeepak Kodihalli     mapperCall.append(root);
2918aa044eSDeepak Kodihalli     mapperCall.append(depth);
3018aa044eSDeepak Kodihalli     mapperCall.append(filter);
3118aa044eSDeepak Kodihalli     auto response = bus.call(mapperCall);
3218aa044eSDeepak Kodihalli     if (response.is_method_error())
3318aa044eSDeepak Kodihalli     {
3418aa044eSDeepak Kodihalli         log<level::ERR>("Error in mapper GetSubTree");
3518aa044eSDeepak Kodihalli         elog<InternalFailure>();
3618aa044eSDeepak Kodihalli     }
3718aa044eSDeepak Kodihalli 
3818aa044eSDeepak Kodihalli     using Interfaces = std::vector<Interface>;
3918aa044eSDeepak Kodihalli     using MapperResponse = std::map<Path, std::map<Service, Interfaces>>;
4018aa044eSDeepak Kodihalli     MapperResponse result;
4118aa044eSDeepak Kodihalli     response.read(result);
4218aa044eSDeepak Kodihalli     if (result.empty())
4318aa044eSDeepak Kodihalli     {
4418aa044eSDeepak Kodihalli         log<level::ERR>("Invalid response from mapper");
4518aa044eSDeepak Kodihalli         elog<InternalFailure>();
4618aa044eSDeepak Kodihalli     }
4718aa044eSDeepak Kodihalli 
4818aa044eSDeepak Kodihalli     for (auto& iter : result)
4918aa044eSDeepak Kodihalli     {
5018aa044eSDeepak Kodihalli         const auto& path = iter.first;
51e602709dSDeepak Kodihalli         for (auto& interface : iter.second.begin()->second)
52e602709dSDeepak Kodihalli         {
53e602709dSDeepak Kodihalli             auto found = map.find(interface);
54e602709dSDeepak Kodihalli             if (map.end() != found)
55e602709dSDeepak Kodihalli             {
56e602709dSDeepak Kodihalli                 auto& paths = found->second;
57e602709dSDeepak Kodihalli                 paths.push_back(path);
58e602709dSDeepak Kodihalli             }
59e602709dSDeepak Kodihalli             else
60e602709dSDeepak Kodihalli             {
61e602709dSDeepak Kodihalli                 map.emplace(std::move(interface), std::vector<Path>({path}));
62e602709dSDeepak Kodihalli             }
63e602709dSDeepak Kodihalli         }
6418aa044eSDeepak Kodihalli     }
6518aa044eSDeepak Kodihalli }
6618aa044eSDeepak Kodihalli 
6718aa044eSDeepak Kodihalli Service Objects::service(const Path& path, const Interface& interface) const
6818aa044eSDeepak Kodihalli {
6918aa044eSDeepak Kodihalli     using Interfaces = std::vector<Interface>;
700b02be92SPatrick Venture     auto mapperCall =
710b02be92SPatrick Venture         bus.new_method_call(mapperService, mapperPath, mapperIntf, "GetObject");
7218aa044eSDeepak Kodihalli     mapperCall.append(path);
7318aa044eSDeepak Kodihalli     mapperCall.append(Interfaces({interface}));
7418aa044eSDeepak Kodihalli 
7518aa044eSDeepak Kodihalli     auto response = bus.call(mapperCall);
7618aa044eSDeepak Kodihalli     if (response.is_method_error())
7718aa044eSDeepak Kodihalli     {
7818aa044eSDeepak Kodihalli         log<level::ERR>("Error in mapper GetObject");
7918aa044eSDeepak Kodihalli         elog<InternalFailure>();
8018aa044eSDeepak Kodihalli     }
8118aa044eSDeepak Kodihalli 
8218aa044eSDeepak Kodihalli     std::map<Service, Interfaces> result;
8318aa044eSDeepak Kodihalli     response.read(result);
8418aa044eSDeepak Kodihalli     if (result.empty())
8518aa044eSDeepak Kodihalli     {
8618aa044eSDeepak Kodihalli         log<level::ERR>("Invalid response from mapper");
8718aa044eSDeepak Kodihalli         elog<InternalFailure>();
8818aa044eSDeepak Kodihalli     }
8918aa044eSDeepak Kodihalli 
9018aa044eSDeepak Kodihalli     return result.begin()->first;
9118aa044eSDeepak Kodihalli }
9218aa044eSDeepak Kodihalli 
9313791bd5SDeepak Kodihalli namespace boot
9413791bd5SDeepak Kodihalli {
9513791bd5SDeepak Kodihalli 
9613791bd5SDeepak Kodihalli std::tuple<Path, OneTimeEnabled> setting(const Objects& objects,
9713791bd5SDeepak Kodihalli                                          const Interface& iface)
9813791bd5SDeepak Kodihalli {
9913791bd5SDeepak Kodihalli     constexpr auto bootObjCount = 2;
10013791bd5SDeepak Kodihalli     constexpr auto oneTime = "one_time";
10113791bd5SDeepak Kodihalli     constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
10213791bd5SDeepak Kodihalli 
10313791bd5SDeepak Kodihalli     const std::vector<Path>& paths = objects.map.at(iface);
10413791bd5SDeepak Kodihalli     auto count = paths.size();
10513791bd5SDeepak Kodihalli     if (count != bootObjCount)
10613791bd5SDeepak Kodihalli     {
10713791bd5SDeepak Kodihalli         log<level::ERR>("Exactly two objects expected",
10813791bd5SDeepak Kodihalli                         entry("INTERFACE=%s", iface.c_str()),
10913791bd5SDeepak Kodihalli                         entry("COUNT=%d", count));
11013791bd5SDeepak Kodihalli         elog<InternalFailure>();
11113791bd5SDeepak Kodihalli     }
11213791bd5SDeepak Kodihalli     size_t index = 0;
11313791bd5SDeepak Kodihalli     if (std::string::npos == paths[0].rfind(oneTime))
11413791bd5SDeepak Kodihalli     {
11513791bd5SDeepak Kodihalli         index = 1;
11613791bd5SDeepak Kodihalli     }
11713791bd5SDeepak Kodihalli     const Path& oneTimeSetting = paths[index];
11813791bd5SDeepak Kodihalli     const Path& regularSetting = paths[!index];
11913791bd5SDeepak Kodihalli 
1200b02be92SPatrick Venture     auto method = objects.bus.new_method_call(
1210b02be92SPatrick Venture         objects.service(oneTimeSetting, iface).c_str(), oneTimeSetting.c_str(),
1220b02be92SPatrick Venture         ipmi::PROP_INTF, "Get");
12313791bd5SDeepak Kodihalli     method.append(enabledIntf, "Enabled");
12413791bd5SDeepak Kodihalli     auto reply = objects.bus.call(method);
12513791bd5SDeepak Kodihalli     if (reply.is_method_error())
12613791bd5SDeepak Kodihalli     {
12713791bd5SDeepak Kodihalli         log<level::ERR>("Error in getting Enabled property",
12813791bd5SDeepak Kodihalli                         entry("OBJECT=%s", oneTimeSetting.c_str()),
12913791bd5SDeepak Kodihalli                         entry("INTERFACE=%s", iface.c_str()));
13013791bd5SDeepak Kodihalli         elog<InternalFailure>();
13113791bd5SDeepak Kodihalli     }
13213791bd5SDeepak Kodihalli 
13313791bd5SDeepak Kodihalli     sdbusplus::message::variant<bool> enabled;
13413791bd5SDeepak Kodihalli     reply.read(enabled);
1354c008028SWilliam A. Kennington III     auto oneTimeEnabled = variant_ns::get<bool>(enabled);
13613791bd5SDeepak Kodihalli     const Path& setting = oneTimeEnabled ? oneTimeSetting : regularSetting;
13713791bd5SDeepak Kodihalli     return std::make_tuple(setting, oneTimeEnabled);
13813791bd5SDeepak Kodihalli }
13913791bd5SDeepak Kodihalli 
14013791bd5SDeepak Kodihalli } // namespace boot
14113791bd5SDeepak Kodihalli 
14218aa044eSDeepak Kodihalli } // namespace settings
143