1 #include "settings.hpp" 2 3 #include <ipmid/utils.hpp> 4 #include <phosphor-logging/elog-errors.hpp> 5 #include <phosphor-logging/log.hpp> 6 #include <sdbusplus/message/types.hpp> 7 #include <xyz/openbmc_project/Common/error.hpp> 8 9 namespace settings 10 { 11 12 using namespace phosphor::logging; 13 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 14 15 constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper"; 16 constexpr auto mapperPath = "/xyz/openbmc_project/object_mapper"; 17 constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper"; 18 19 Objects::Objects(sdbusplus::bus_t& bus, const std::vector<Interface>& filter) : 20 bus(bus) 21 { 22 auto depth = 0; 23 24 auto mapperCall = bus.new_method_call(mapperService, mapperPath, mapperIntf, 25 "GetSubTree"); 26 mapperCall.append(root); 27 mapperCall.append(depth); 28 mapperCall.append(filter); 29 30 using Interfaces = std::vector<Interface>; 31 using MapperResponse = std::map<Path, std::map<Service, Interfaces>>; 32 MapperResponse result; 33 try 34 { 35 auto response = bus.call(mapperCall); 36 response.read(result); 37 } 38 catch (const std::exception& e) 39 { 40 log<level::ERR>("Error in mapper GetSubTree", 41 entry("ERROR=%s", e.what())); 42 elog<InternalFailure>(); 43 } 44 45 for (auto& iter : result) 46 { 47 const auto& path = iter.first; 48 for (auto& interface : iter.second.begin()->second) 49 { 50 auto found = map.find(interface); 51 if (map.end() != found) 52 { 53 auto& paths = found->second; 54 paths.push_back(path); 55 } 56 else 57 { 58 map.emplace(std::move(interface), std::vector<Path>({path})); 59 } 60 } 61 } 62 } 63 64 Service Objects::service(const Path& path, const Interface& interface) const 65 { 66 using Interfaces = std::vector<Interface>; 67 auto mapperCall = bus.new_method_call(mapperService, mapperPath, mapperIntf, 68 "GetObject"); 69 mapperCall.append(path); 70 mapperCall.append(Interfaces({interface})); 71 72 std::map<Service, Interfaces> result; 73 try 74 { 75 auto response = bus.call(mapperCall); 76 response.read(result); 77 return result.begin()->first; 78 } 79 catch (const std::exception& e) 80 { 81 log<level::ERR>("Invalid response from mapper", 82 entry("ERROR=%s", e.what())); 83 elog<InternalFailure>(); 84 } 85 } 86 87 namespace boot 88 { 89 90 std::tuple<Path, OneTimeEnabled> setting(const Objects& objects, 91 const Interface& iface) 92 { 93 constexpr auto bootObjCount = 2; 94 constexpr auto oneTime = "one_time"; 95 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable"; 96 97 const std::vector<Path>& paths = objects.map.at(iface); 98 auto count = paths.size(); 99 if (count != bootObjCount) 100 { 101 log<level::ERR>("Exactly two objects expected", 102 entry("INTERFACE=%s", iface.c_str()), 103 entry("COUNT=%d", count)); 104 elog<InternalFailure>(); 105 } 106 size_t index = 0; 107 if (std::string::npos == paths[0].rfind(oneTime)) 108 { 109 index = 1; 110 } 111 const Path& oneTimeSetting = paths[index]; 112 const Path& regularSetting = paths[!index]; 113 114 auto method = objects.bus.new_method_call( 115 objects.service(oneTimeSetting, iface).c_str(), oneTimeSetting.c_str(), 116 ipmi::PROP_INTF, "Get"); 117 method.append(enabledIntf, "Enabled"); 118 119 std::variant<bool> enabled; 120 try 121 { 122 auto reply = objects.bus.call(method); 123 reply.read(enabled); 124 } 125 catch (const std::exception& e) 126 { 127 log<level::ERR>("Error in getting Enabled property", 128 entry("OBJECT=%s", oneTimeSetting.c_str()), 129 entry("INTERFACE=%s", iface.c_str()), 130 entry("ERROR=%s", e.what())); 131 elog<InternalFailure>(); 132 } 133 134 auto oneTimeEnabled = std::get<bool>(enabled); 135 const Path& setting = oneTimeEnabled ? oneTimeSetting : regularSetting; 136 return std::make_tuple(setting, oneTimeEnabled); 137 } 138 139 } // namespace boot 140 141 } // namespace settings 142