1 #include <attn_common.hpp> 2 #include <attn_dbus.hpp> 3 #include <attn_logging.hpp> 4 5 #include <string> 6 #include <vector> 7 8 namespace attn 9 { 10 11 /** @brief Create a dbus method */ 12 int dbusMethod(const std::string& i_path, const std::string& i_interface, 13 const std::string& i_function, 14 sdbusplus::message::message& o_method, 15 const std::string& i_extended) 16 { 17 int rc = RC_DBUS_ERROR; // assume error 18 19 try 20 { 21 constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper"; 22 constexpr auto pathFind = "/xyz/openbmc_project/object_mapper"; 23 constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper"; 24 constexpr auto functionFind = "GetObject"; 25 26 auto bus = sdbusplus::bus::new_system(); // using system dbus 27 28 // method to find service from object path and object interface 29 auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind, 30 functionFind); 31 32 // find the service for specified object path and interface 33 method.append(i_path.c_str()); 34 method.append(std::vector<std::string>({i_interface})); 35 auto reply = bus.call(method); 36 37 // dbus call results 38 std::map<std::string, std::vector<std::string>> responseFindService; 39 reply.read(responseFindService); 40 41 // If we successfully found the service associated with the dbus object 42 // path and interface then create a method for the specified interface 43 // and function. 44 if (!responseFindService.empty()) 45 { 46 auto service = responseFindService.begin()->first; 47 48 // Some methods (e.g. get attribute) take an extended parameter 49 if (i_extended == "") 50 { 51 // return the method 52 o_method = bus.new_method_call(service.c_str(), i_path.c_str(), 53 i_interface.c_str(), 54 i_function.c_str()); 55 } 56 else 57 { 58 // return extended method 59 o_method = 60 bus.new_method_call(service.c_str(), i_path.c_str(), 61 i_extended.c_str(), i_function.c_str()); 62 } 63 64 rc = RC_SUCCESS; 65 } 66 else 67 { 68 // This trace will be picked up in event log 69 trace<level::INFO>("dbusMethod service not found"); 70 std::string traceMsgPath = std::string(i_path, maxTraceLen); 71 trace<level::INFO>(traceMsgPath.c_str()); 72 std::string traceMsgIface = std::string(i_interface, maxTraceLen); 73 trace<level::INFO>(traceMsgIface.c_str()); 74 } 75 } 76 catch (const sdbusplus::exception::SdBusError& e) 77 { 78 trace<level::ERROR>("dbusMethod exception"); 79 std::string traceMsg = std::string(e.what(), maxTraceLen); 80 trace<level::ERROR>(traceMsg.c_str()); 81 } 82 83 return rc; 84 } 85 86 /** @brief Create a PEL for the specified event type */ 87 uint32_t createPel(const std::string& i_event, 88 std::map<std::string, std::string>& i_additional, 89 const std::vector<util::FFDCTuple>& i_ffdc) 90 { 91 // CreatePELWithFFDCFiles returns plid 92 int plid = 0; 93 94 // Need to provide pid when using create or create-with-ffdc methods 95 i_additional.emplace("_PID", std::to_string(getpid())); 96 97 // Sdbus call specifics 98 constexpr auto interface = "org.open_power.Logging.PEL"; 99 constexpr auto function = "CreatePELWithFFDCFiles"; 100 101 sdbusplus::message::message method; 102 103 if (0 == dbusMethod(pathLogging, interface, function, method)) 104 { 105 try 106 { 107 // append additional dbus call paramaters 108 method.append(i_event, levelPelError, i_additional, i_ffdc); 109 110 // using system dbus 111 auto bus = sdbusplus::bus::new_system(); 112 auto response = bus.call(method); 113 114 // reply will be tuple containing bmc log id, platform log id 115 std::tuple<uint32_t, uint32_t> reply = {0, 0}; 116 117 // parse dbus response into reply 118 response.read(reply); 119 plid = std::get<1>(reply); // platform log id is tuple "second" 120 } 121 catch (const sdbusplus::exception::SdBusError& e) 122 { 123 trace<level::ERROR>("createPel exception"); 124 std::string traceMsg = std::string(e.what(), maxTraceLen); 125 trace<level::ERROR>(traceMsg.c_str()); 126 } 127 } 128 129 return plid; // platform log id or 0 130 } 131 132 /** @brief Create a PEL from raw PEL data */ 133 void createPelRaw(const std::vector<uint8_t>& i_buffer) 134 { 135 // Create FFDC file from buffer data 136 util::FFDCFile pelFile{util::FFDCFormat::Text}; 137 auto fd = pelFile.getFileDescriptor(); 138 139 auto filePath = pelFile.getPath(); // path to ffdc file 140 141 size_t numBytes = write(fd, i_buffer.data(), i_buffer.size()); 142 if (i_buffer.size() != numBytes) 143 { 144 std::stringstream traceMsg; 145 traceMsg << filePath.c_str() << " only " << (int)numBytes << " of " 146 << (int)i_buffer.size() << " bytes written"; 147 auto strobj = traceMsg.str(); 148 trace<level::ERROR>(strobj.c_str()); 149 } 150 151 lseek(fd, 0, SEEK_SET); 152 153 // Additional data for log 154 std::map<std::string, std::string> additional; 155 additional.emplace("RAWPEL", filePath.string()); 156 additional.emplace("_PID", std::to_string(getpid())); 157 158 // dbus specifics 159 constexpr auto interface = "xyz.openbmc_project.Logging.Create"; 160 constexpr auto function = "Create"; 161 162 sdbusplus::message::message method; 163 164 if (0 == dbusMethod(pathLogging, interface, function, method)) 165 { 166 try 167 { 168 // append additional dbus call parameters 169 method.append(eventPelTerminate, levelPelError, additional); 170 171 // using system dbus, no reply 172 auto bus = sdbusplus::bus::new_system(); 173 bus.call_noreply(method); 174 } 175 catch (const sdbusplus::exception::SdBusError& e) 176 { 177 trace<level::ERROR>("createPelRaw exception"); 178 std::string traceMsg = std::string(e.what(), maxTraceLen); 179 trace<level::ERROR>(traceMsg.c_str()); 180 } 181 } 182 } 183 184 /** @brief Get file descriptor of exisitng PEL */ 185 int getPel(const uint32_t i_pelId) 186 { 187 // GetPEL returns file descriptor (int) 188 int fd = -1; 189 190 // dbus specifics 191 constexpr auto interface = "org.open_power.Logging.PEL"; 192 constexpr auto function = "GetPEL"; 193 194 sdbusplus::message::message method; 195 196 if (0 == dbusMethod(pathLogging, interface, function, method)) 197 { 198 try 199 { 200 // additional dbus call parameters 201 method.append(i_pelId); 202 203 // using system dbus 204 auto bus = sdbusplus::bus::new_system(); 205 auto response = bus.call(method); 206 207 // reply will be a unix file descriptor 208 sdbusplus::message::unix_fd reply; 209 210 // parse dbus response into reply 211 response.read(reply); 212 213 fd = dup(reply); // need to copy (dup) the file descriptor 214 } 215 catch (const sdbusplus::exception::SdBusError& e) 216 { 217 trace<level::ERROR>("getPel exception"); 218 std::string traceMsg = std::string(e.what(), maxTraceLen); 219 trace<level::ERROR>(traceMsg.c_str()); 220 } 221 } 222 223 return fd; // file descriptor or -1 224 } 225 226 } // namespace attn 227