1f36466f4SZane Shelley #include <attn/attn_common.hpp> 2f36466f4SZane Shelley #include <attn/attn_dbus.hpp> 3f36466f4SZane Shelley #include <attn/attn_logging.hpp> 4bfa831a8Saustinfcui #include <util/trace.hpp> 5188f1096SBen Tyner 6188f1096SBen Tyner #include <string> 7188f1096SBen Tyner #include <vector> 8188f1096SBen Tyner 9188f1096SBen Tyner namespace attn 10188f1096SBen Tyner { 11188f1096SBen Tyner 125c5db65aSBen Tyner /** @brief Create a dbus method */ 13188f1096SBen Tyner int dbusMethod(const std::string& i_path, const std::string& i_interface, 14188f1096SBen Tyner const std::string& i_function, 15*a098210fSBen Tyner sdbusplus::message::message& o_method) 16188f1096SBen Tyner { 174bbcb38fSBen Tyner int rc = RC_DBUS_ERROR; // assume error 18188f1096SBen Tyner 19188f1096SBen Tyner try 20188f1096SBen Tyner { 21188f1096SBen Tyner constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper"; 22188f1096SBen Tyner constexpr auto pathFind = "/xyz/openbmc_project/object_mapper"; 23188f1096SBen Tyner constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper"; 24188f1096SBen Tyner constexpr auto functionFind = "GetObject"; 25188f1096SBen Tyner 26188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); // using system dbus 27188f1096SBen Tyner 28188f1096SBen Tyner // method to find service from object path and object interface 29188f1096SBen Tyner auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind, 30188f1096SBen Tyner functionFind); 31188f1096SBen Tyner 32188f1096SBen Tyner // find the service for specified object path and interface 33188f1096SBen Tyner method.append(i_path.c_str()); 34188f1096SBen Tyner method.append(std::vector<std::string>({i_interface})); 35188f1096SBen Tyner auto reply = bus.call(method); 36188f1096SBen Tyner 37188f1096SBen Tyner // dbus call results 38188f1096SBen Tyner std::map<std::string, std::vector<std::string>> responseFindService; 39188f1096SBen Tyner reply.read(responseFindService); 40188f1096SBen Tyner 41188f1096SBen Tyner // If we successfully found the service associated with the dbus object 42188f1096SBen Tyner // path and interface then create a method for the specified interface 43188f1096SBen Tyner // and function. 44188f1096SBen Tyner if (!responseFindService.empty()) 45188f1096SBen Tyner { 46188f1096SBen Tyner auto service = responseFindService.begin()->first; 47188f1096SBen Tyner 48188f1096SBen Tyner // return the method 49188f1096SBen Tyner o_method = 50188f1096SBen Tyner bus.new_method_call(service.c_str(), i_path.c_str(), 51*a098210fSBen Tyner i_interface.c_str(), i_function.c_str()); 524bbcb38fSBen Tyner rc = RC_SUCCESS; 53188f1096SBen Tyner } 54188f1096SBen Tyner else 55188f1096SBen Tyner { 566764d70eSBen Tyner // This trace will be picked up in event log 57bfa831a8Saustinfcui trace::inf("dbusMethod service not found"); 58bfa831a8Saustinfcui trace::inf(i_path.c_str()); 59bfa831a8Saustinfcui trace::inf(i_interface.c_str()); 60188f1096SBen Tyner } 61188f1096SBen Tyner } 62188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 63188f1096SBen Tyner { 64bfa831a8Saustinfcui trace::err("dbusMethod exception"); 65bfa831a8Saustinfcui trace::err(e.what()); 66188f1096SBen Tyner } 67188f1096SBen Tyner 68188f1096SBen Tyner return rc; 69188f1096SBen Tyner } 70188f1096SBen Tyner 71188f1096SBen Tyner /** @brief Create a PEL for the specified event type */ 72188f1096SBen Tyner uint32_t createPel(const std::string& i_event, 73188f1096SBen Tyner std::map<std::string, std::string>& i_additional, 74188f1096SBen Tyner const std::vector<util::FFDCTuple>& i_ffdc) 75188f1096SBen Tyner { 76188f1096SBen Tyner // CreatePELWithFFDCFiles returns plid 77188f1096SBen Tyner int plid = 0; 78188f1096SBen Tyner 79188f1096SBen Tyner // Need to provide pid when using create or create-with-ffdc methods 80188f1096SBen Tyner i_additional.emplace("_PID", std::to_string(getpid())); 81188f1096SBen Tyner 82188f1096SBen Tyner // Sdbus call specifics 83188f1096SBen Tyner constexpr auto interface = "org.open_power.Logging.PEL"; 84188f1096SBen Tyner constexpr auto function = "CreatePELWithFFDCFiles"; 85188f1096SBen Tyner 86188f1096SBen Tyner sdbusplus::message::message method; 87188f1096SBen Tyner 88188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 89188f1096SBen Tyner { 90188f1096SBen Tyner try 91188f1096SBen Tyner { 92188f1096SBen Tyner // append additional dbus call paramaters 93188f1096SBen Tyner method.append(i_event, levelPelError, i_additional, i_ffdc); 94188f1096SBen Tyner 95188f1096SBen Tyner // using system dbus 96188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 97188f1096SBen Tyner auto response = bus.call(method); 98188f1096SBen Tyner 99188f1096SBen Tyner // reply will be tuple containing bmc log id, platform log id 100188f1096SBen Tyner std::tuple<uint32_t, uint32_t> reply = {0, 0}; 101188f1096SBen Tyner 1024bbcb38fSBen Tyner // parse dbus response into reply 103188f1096SBen Tyner response.read(reply); 104188f1096SBen Tyner plid = std::get<1>(reply); // platform log id is tuple "second" 105188f1096SBen Tyner } 106188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 107188f1096SBen Tyner { 108bfa831a8Saustinfcui trace::err("createPel exception"); 109bfa831a8Saustinfcui trace::err(e.what()); 110188f1096SBen Tyner } 111188f1096SBen Tyner } 112188f1096SBen Tyner 113188f1096SBen Tyner return plid; // platform log id or 0 114188f1096SBen Tyner } 115188f1096SBen Tyner 116188f1096SBen Tyner /** @brief Create a PEL from raw PEL data */ 117188f1096SBen Tyner void createPelRaw(const std::vector<uint8_t>& i_buffer) 118188f1096SBen Tyner { 119188f1096SBen Tyner // Create FFDC file from buffer data 120188f1096SBen Tyner util::FFDCFile pelFile{util::FFDCFormat::Text}; 121188f1096SBen Tyner auto fd = pelFile.getFileDescriptor(); 122188f1096SBen Tyner 123188f1096SBen Tyner auto filePath = pelFile.getPath(); // path to ffdc file 124188f1096SBen Tyner 125d700609cSBen Tyner size_t numBytes = write(fd, i_buffer.data(), i_buffer.size()); 126d700609cSBen Tyner if (i_buffer.size() != numBytes) 127d700609cSBen Tyner { 128bfa831a8Saustinfcui trace::err("%s only %u of %u bytes written", filePath.c_str(), numBytes, 129bfa831a8Saustinfcui i_buffer.size()); 130d700609cSBen Tyner } 131d700609cSBen Tyner 132d700609cSBen Tyner lseek(fd, 0, SEEK_SET); 133d700609cSBen Tyner 134188f1096SBen Tyner // Additional data for log 135188f1096SBen Tyner std::map<std::string, std::string> additional; 136188f1096SBen Tyner additional.emplace("RAWPEL", filePath.string()); 137188f1096SBen Tyner additional.emplace("_PID", std::to_string(getpid())); 138188f1096SBen Tyner 139188f1096SBen Tyner // dbus specifics 140188f1096SBen Tyner constexpr auto interface = "xyz.openbmc_project.Logging.Create"; 141188f1096SBen Tyner constexpr auto function = "Create"; 142188f1096SBen Tyner 143188f1096SBen Tyner sdbusplus::message::message method; 144188f1096SBen Tyner 145188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 146188f1096SBen Tyner { 147188f1096SBen Tyner try 148188f1096SBen Tyner { 149188f1096SBen Tyner // append additional dbus call parameters 150188f1096SBen Tyner method.append(eventPelTerminate, levelPelError, additional); 151188f1096SBen Tyner 152188f1096SBen Tyner // using system dbus, no reply 153188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 154188f1096SBen Tyner bus.call_noreply(method); 155188f1096SBen Tyner } 156188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 157188f1096SBen Tyner { 158bfa831a8Saustinfcui trace::err("createPelRaw exception"); 159bfa831a8Saustinfcui trace::err(e.what()); 160188f1096SBen Tyner } 161188f1096SBen Tyner } 162188f1096SBen Tyner } 163188f1096SBen Tyner 164188f1096SBen Tyner /** @brief Get file descriptor of exisitng PEL */ 165188f1096SBen Tyner int getPel(const uint32_t i_pelId) 166188f1096SBen Tyner { 167188f1096SBen Tyner // GetPEL returns file descriptor (int) 168188f1096SBen Tyner int fd = -1; 169188f1096SBen Tyner 170188f1096SBen Tyner // dbus specifics 171188f1096SBen Tyner constexpr auto interface = "org.open_power.Logging.PEL"; 172188f1096SBen Tyner constexpr auto function = "GetPEL"; 173188f1096SBen Tyner 174188f1096SBen Tyner sdbusplus::message::message method; 175188f1096SBen Tyner 176188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 177188f1096SBen Tyner { 178188f1096SBen Tyner try 179188f1096SBen Tyner { 180188f1096SBen Tyner // additional dbus call parameters 181188f1096SBen Tyner method.append(i_pelId); 182188f1096SBen Tyner 183188f1096SBen Tyner // using system dbus 184188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 185188f1096SBen Tyner auto response = bus.call(method); 186188f1096SBen Tyner 187188f1096SBen Tyner // reply will be a unix file descriptor 188188f1096SBen Tyner sdbusplus::message::unix_fd reply; 189188f1096SBen Tyner 1904bbcb38fSBen Tyner // parse dbus response into reply 191188f1096SBen Tyner response.read(reply); 192188f1096SBen Tyner 193188f1096SBen Tyner fd = dup(reply); // need to copy (dup) the file descriptor 194188f1096SBen Tyner } 195188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 196188f1096SBen Tyner { 197bfa831a8Saustinfcui trace::err("getPel exception"); 198bfa831a8Saustinfcui trace::err(e.what()); 199188f1096SBen Tyner } 200188f1096SBen Tyner } 201188f1096SBen Tyner 202188f1096SBen Tyner return fd; // file descriptor or -1 203188f1096SBen Tyner } 204188f1096SBen Tyner 205188f1096SBen Tyner } // namespace attn 206