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