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