1 #include "utils.hpp" 2 3 #include <gpiod.h> 4 5 #include <phosphor-logging/lg2.hpp> 6 7 namespace phosphor 8 { 9 namespace state 10 { 11 namespace manager 12 { 13 namespace utils 14 { 15 16 PHOSPHOR_LOG2_USING; 17 18 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; 19 constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; 20 constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; 21 constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"; 22 23 std::string getService(sdbusplus::bus_t& bus, std::string path, 24 std::string interface) 25 { 26 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, 27 MAPPER_INTERFACE, "GetObject"); 28 29 mapper.append(path, std::vector<std::string>({interface})); 30 31 std::vector<std::pair<std::string, std::vector<std::string>>> 32 mapperResponse; 33 34 try 35 { 36 auto mapperResponseMsg = bus.call(mapper); 37 38 mapperResponseMsg.read(mapperResponse); 39 if (mapperResponse.empty()) 40 { 41 error( 42 "Error no matching service with path {PATH} and interface {INTERFACE}", 43 "PATH", path, "INTERFACE", interface); 44 throw std::runtime_error("Error no matching service"); 45 } 46 } 47 catch (const sdbusplus::exception_t& e) 48 { 49 error("Error in mapper call with path {PATH}, interface " 50 "{INTERFACE}, and exception {ERROR}", 51 "PATH", path, "INTERFACE", interface, "ERROR", e); 52 throw; 53 } 54 55 return mapperResponse.begin()->first; 56 } 57 58 std::string getProperty(sdbusplus::bus_t& bus, const std::string& path, 59 const std::string& interface, 60 const std::string& propertyName) 61 { 62 std::variant<std::string> property; 63 std::string service = getService(bus, path, interface); 64 65 auto method = bus.new_method_call(service.c_str(), path.c_str(), 66 PROPERTY_INTERFACE, "Get"); 67 68 method.append(interface, propertyName); 69 70 try 71 { 72 auto reply = bus.call(method); 73 reply.read(property); 74 } 75 catch (const sdbusplus::exception_t& e) 76 { 77 error("Error in property Get, error {ERROR}, property {PROPERTY}", 78 "ERROR", e, "PROPERTY", propertyName); 79 throw; 80 } 81 82 if (std::get<std::string>(property).empty()) 83 { 84 error("Error reading property response for {PROPERTY}", "PROPERTY", 85 propertyName); 86 throw std::runtime_error("Error reading property response"); 87 } 88 89 return std::get<std::string>(property); 90 } 91 92 void setProperty(sdbusplus::bus_t& bus, const std::string& path, 93 const std::string& interface, const std::string& property, 94 const std::string& value) 95 { 96 std::variant<std::string> variantValue = value; 97 std::string service = getService(bus, path, interface); 98 99 auto method = bus.new_method_call(service.c_str(), path.c_str(), 100 PROPERTY_INTERFACE, "Set"); 101 102 method.append(interface, property, variantValue); 103 bus.call_noreply(method); 104 105 return; 106 } 107 108 int getGpioValue(const std::string& gpioName) 109 { 110 int gpioval = -1; 111 gpiod_line* line = gpiod_line_find(gpioName.c_str()); 112 113 if (nullptr != line) 114 { 115 // take ownership of gpio 116 if (0 != gpiod_line_request_input(line, "state-manager")) 117 { 118 error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName); 119 } 120 else 121 { 122 // get gpio value 123 gpioval = gpiod_line_get_value(line); 124 125 // release ownership of gpio 126 gpiod_line_close_chip(line); 127 } 128 } 129 return gpioval; 130 } 131 132 void createError( 133 sdbusplus::bus_t& bus, const std::string& errorMsg, 134 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level errLevel, 135 std::map<std::string, std::string> additionalData) 136 { 137 try 138 { 139 // Always add the _PID on for some extra logging debug 140 additionalData.emplace("_PID", std::to_string(getpid())); 141 142 auto method = bus.new_method_call( 143 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", 144 "xyz.openbmc_project.Logging.Create", "Create"); 145 146 method.append(errorMsg, errLevel, additionalData); 147 auto resp = bus.call(method); 148 } 149 catch (const sdbusplus::exception_t& e) 150 { 151 error("sdbusplus D-Bus call exception, error {ERROR} trying to create " 152 "an error with {ERROR_MSG}", 153 "ERROR", e, "ERROR_MSG", errorMsg); 154 155 throw std::runtime_error( 156 "Error in invoking D-Bus logging create interface"); 157 } 158 catch (const std::exception& e) 159 { 160 error("D-bus call exception: {ERROR}", "ERROR", e); 161 throw e; 162 } 163 } 164 165 void createBmcDump(sdbusplus::bus_t& bus) 166 { 167 auto method = bus.new_method_call( 168 "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc", 169 "xyz.openbmc_project.Dump.Create", "CreateDump"); 170 method.append( 171 std::vector< 172 std::pair<std::string, std::variant<std::string, uint64_t>>>()); 173 try 174 { 175 bus.call_noreply(method); 176 } 177 catch (const sdbusplus::exception_t& e) 178 { 179 error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e); 180 // just continue, this is error path anyway so we're just collecting 181 // what we can 182 } 183 } 184 185 } // namespace utils 186 } // namespace manager 187 } // namespace state 188 } // namespace phosphor 189