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