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