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