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::bus& 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::exception& 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::bus& 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::exception& 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::bus& 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 111 int gpioval = -1; 112 gpiod_line* line = gpiod_line_find(gpioName.c_str()); 113 114 if (nullptr != line) 115 { 116 // take ownership of gpio 117 if (0 != gpiod_line_request_input(line, "state-manager")) 118 { 119 error("Failed request for {GPIO_NAME} GPIO", "GPIO_NAME", gpioName); 120 } 121 else 122 { 123 // get gpio value 124 gpioval = gpiod_line_get_value(line); 125 126 // release ownership of gpio 127 gpiod_line_close_chip(line); 128 } 129 } 130 return gpioval; 131 } 132 133 void createError( 134 sdbusplus::bus::bus& bus, const std::string& errorMsg, 135 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level errLevel, 136 std::map<std::string, std::string> additionalData) 137 { 138 139 try 140 { 141 // Always add the _PID on for some extra logging debug 142 additionalData.emplace("_PID", std::to_string(getpid())); 143 144 auto method = bus.new_method_call( 145 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", 146 "xyz.openbmc_project.Logging.Create", "Create"); 147 148 method.append(errorMsg, errLevel, additionalData); 149 auto resp = bus.call(method); 150 } 151 catch (const sdbusplus::exception::exception& e) 152 { 153 error("sdbusplus D-Bus call exception, error {ERROR} trying to create " 154 "an error with {ERROR_MSG}", 155 "ERROR", e, "ERROR_MSG", errorMsg); 156 157 throw std::runtime_error( 158 "Error in invoking D-Bus logging create interface"); 159 } 160 catch (const std::exception& e) 161 { 162 error("D-bus call exception: {ERROR}", "ERROR", e); 163 throw e; 164 } 165 } 166 167 void createBmcDump(sdbusplus::bus::bus& bus) 168 { 169 auto method = bus.new_method_call( 170 "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc", 171 "xyz.openbmc_project.Dump.Create", "CreateDump"); 172 method.append( 173 std::vector< 174 std::pair<std::string, std::variant<std::string, uint64_t>>>()); 175 try 176 { 177 bus.call_noreply(method); 178 } 179 catch (const sdbusplus::exception::exception& e) 180 { 181 error("Failed to create BMC dump, exception:{ERROR}", "ERROR", e); 182 // just continue, this is error path anyway so we're just collecting 183 // what we can 184 } 185 } 186 187 } // namespace utils 188 } // namespace manager 189 } // namespace state 190 } // namespace phosphor 191