1*4bbcb38fSBen Tyner #include <attn_dbus.hpp> 2*4bbcb38fSBen Tyner #include <attn_handler.hpp> 3188f1096SBen Tyner #include <attn_logging.hpp> 4*4bbcb38fSBen Tyner #include <xyz/openbmc_project/State/Boot/Progress/server.hpp> 5188f1096SBen Tyner 6188f1096SBen Tyner #include <string> 7188f1096SBen Tyner #include <vector> 8188f1096SBen Tyner 9188f1096SBen Tyner namespace attn 10188f1096SBen Tyner { 11188f1096SBen Tyner 12188f1096SBen Tyner /** 13188f1096SBen Tyner * Create a dbus method 14188f1096SBen Tyner * 15188f1096SBen Tyner * Find the dbus service associated with the dbus object path and create 16188f1096SBen Tyner * a dbus method for calling the specified dbus interface and function. 17188f1096SBen Tyner * 18188f1096SBen Tyner * @param i_path - dbus object path 19188f1096SBen Tyner * @param i_interface - dbus method interface 20188f1096SBen Tyner * @param i_function - dbus interface function 21188f1096SBen Tyner * @param o_method - method that is created 22*4bbcb38fSBen Tyner * @param i_extended - optional for extended methods 23188f1096SBen Tyner * @return non-zero if error 24188f1096SBen Tyner * 25188f1096SBen Tyner **/ 26188f1096SBen Tyner int dbusMethod(const std::string& i_path, const std::string& i_interface, 27188f1096SBen Tyner const std::string& i_function, 28*4bbcb38fSBen Tyner sdbusplus::message::message& o_method, 29*4bbcb38fSBen Tyner const std::string& i_extended = "") 30188f1096SBen Tyner { 31*4bbcb38fSBen Tyner int rc = RC_DBUS_ERROR; // assume error 32188f1096SBen Tyner 33188f1096SBen Tyner try 34188f1096SBen Tyner { 35188f1096SBen Tyner constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper"; 36188f1096SBen Tyner constexpr auto pathFind = "/xyz/openbmc_project/object_mapper"; 37188f1096SBen Tyner constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper"; 38188f1096SBen Tyner constexpr auto functionFind = "GetObject"; 39188f1096SBen Tyner 40188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); // using system dbus 41188f1096SBen Tyner 42188f1096SBen Tyner // method to find service from object path and object interface 43188f1096SBen Tyner auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind, 44188f1096SBen Tyner functionFind); 45188f1096SBen Tyner 46188f1096SBen Tyner // find the service for specified object path and interface 47188f1096SBen Tyner method.append(i_path.c_str()); 48188f1096SBen Tyner method.append(std::vector<std::string>({i_interface})); 49188f1096SBen Tyner auto reply = bus.call(method); 50188f1096SBen Tyner 51188f1096SBen Tyner // dbus call results 52188f1096SBen Tyner std::map<std::string, std::vector<std::string>> responseFindService; 53188f1096SBen Tyner reply.read(responseFindService); 54188f1096SBen Tyner 55188f1096SBen Tyner // If we successfully found the service associated with the dbus object 56188f1096SBen Tyner // path and interface then create a method for the specified interface 57188f1096SBen Tyner // and function. 58188f1096SBen Tyner if (!responseFindService.empty()) 59188f1096SBen Tyner { 60188f1096SBen Tyner auto service = responseFindService.begin()->first; 61188f1096SBen Tyner 62*4bbcb38fSBen Tyner // Some methods (e.g. get attribute) take an extended parameter 63*4bbcb38fSBen Tyner if (i_extended == "") 64*4bbcb38fSBen Tyner { 65188f1096SBen Tyner // return the method 66*4bbcb38fSBen Tyner o_method = bus.new_method_call(service.c_str(), i_path.c_str(), 67*4bbcb38fSBen Tyner i_interface.c_str(), 68*4bbcb38fSBen Tyner i_function.c_str()); 69*4bbcb38fSBen Tyner } 70*4bbcb38fSBen Tyner else 71*4bbcb38fSBen Tyner { 72*4bbcb38fSBen Tyner // return extended method 73188f1096SBen Tyner o_method = 74188f1096SBen Tyner bus.new_method_call(service.c_str(), i_path.c_str(), 75*4bbcb38fSBen Tyner i_extended.c_str(), i_function.c_str()); 76*4bbcb38fSBen Tyner } 77188f1096SBen Tyner 78*4bbcb38fSBen Tyner rc = RC_SUCCESS; 79188f1096SBen Tyner } 80188f1096SBen Tyner else 81188f1096SBen Tyner { 826764d70eSBen Tyner // This trace will be picked up in event log 836764d70eSBen Tyner trace<level::INFO>("dbusMethod service not found"); 846764d70eSBen Tyner std::string traceMsgPath = std::string(i_path, maxTraceLen); 856764d70eSBen Tyner trace<level::INFO>(traceMsgPath.c_str()); 866764d70eSBen Tyner std::string traceMsgIface = std::string(i_interface, maxTraceLen); 876764d70eSBen Tyner trace<level::INFO>(traceMsgIface.c_str()); 88188f1096SBen Tyner } 89188f1096SBen Tyner } 90188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 91188f1096SBen Tyner { 926764d70eSBen Tyner trace<level::INFO>("dbusMethod exception"); 936764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 946764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 95188f1096SBen Tyner } 96188f1096SBen Tyner 97188f1096SBen Tyner return rc; 98188f1096SBen Tyner } 99188f1096SBen Tyner 100188f1096SBen Tyner /** @brief Create a PEL for the specified event type */ 101188f1096SBen Tyner uint32_t createPel(const std::string& i_event, 102188f1096SBen Tyner std::map<std::string, std::string>& i_additional, 103188f1096SBen Tyner const std::vector<util::FFDCTuple>& i_ffdc) 104188f1096SBen Tyner { 105188f1096SBen Tyner // CreatePELWithFFDCFiles returns plid 106188f1096SBen Tyner int plid = 0; 107188f1096SBen Tyner 108188f1096SBen Tyner // Need to provide pid when using create or create-with-ffdc methods 109188f1096SBen Tyner i_additional.emplace("_PID", std::to_string(getpid())); 110188f1096SBen Tyner 111188f1096SBen Tyner // Sdbus call specifics 112188f1096SBen Tyner constexpr auto interface = "org.open_power.Logging.PEL"; 113188f1096SBen Tyner constexpr auto function = "CreatePELWithFFDCFiles"; 114188f1096SBen Tyner 115188f1096SBen Tyner sdbusplus::message::message method; 116188f1096SBen Tyner 117188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 118188f1096SBen Tyner { 119188f1096SBen Tyner try 120188f1096SBen Tyner { 121188f1096SBen Tyner // append additional dbus call paramaters 122188f1096SBen Tyner method.append(i_event, levelPelError, i_additional, i_ffdc); 123188f1096SBen Tyner 124188f1096SBen Tyner // using system dbus 125188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 126188f1096SBen Tyner auto response = bus.call(method); 127188f1096SBen Tyner 128188f1096SBen Tyner // reply will be tuple containing bmc log id, platform log id 129188f1096SBen Tyner std::tuple<uint32_t, uint32_t> reply = {0, 0}; 130188f1096SBen Tyner 131*4bbcb38fSBen Tyner // parse dbus response into reply 132188f1096SBen Tyner response.read(reply); 133188f1096SBen Tyner plid = std::get<1>(reply); // platform log id is tuple "second" 134188f1096SBen Tyner } 135188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 136188f1096SBen Tyner { 1376764d70eSBen Tyner trace<level::INFO>("createPel exception"); 1386764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 1396764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 140188f1096SBen Tyner } 141188f1096SBen Tyner } 142188f1096SBen Tyner 143188f1096SBen Tyner return plid; // platform log id or 0 144188f1096SBen Tyner } 145188f1096SBen Tyner 146188f1096SBen Tyner /** @brief Create a PEL from raw PEL data */ 147188f1096SBen Tyner void createPelRaw(const std::vector<uint8_t>& i_buffer) 148188f1096SBen Tyner { 149188f1096SBen Tyner // Create FFDC file from buffer data 150188f1096SBen Tyner util::FFDCFile pelFile{util::FFDCFormat::Text}; 151188f1096SBen Tyner auto fd = pelFile.getFileDescriptor(); 152188f1096SBen Tyner 153188f1096SBen Tyner auto filePath = pelFile.getPath(); // path to ffdc file 154188f1096SBen Tyner 155d700609cSBen Tyner size_t numBytes = write(fd, i_buffer.data(), i_buffer.size()); 156d700609cSBen Tyner if (i_buffer.size() != numBytes) 157d700609cSBen Tyner { 158d700609cSBen Tyner std::stringstream traceMsg; 159d700609cSBen Tyner traceMsg << filePath.c_str() << " only " << (int)numBytes << " of " 160d700609cSBen Tyner << (int)i_buffer.size() << " bytes written"; 161d700609cSBen Tyner auto strobj = traceMsg.str(); 162d700609cSBen Tyner trace<level::ERROR>(strobj.c_str()); 163d700609cSBen Tyner } 164d700609cSBen Tyner 165d700609cSBen Tyner lseek(fd, 0, SEEK_SET); 166d700609cSBen Tyner 167188f1096SBen Tyner // Additional data for log 168188f1096SBen Tyner std::map<std::string, std::string> additional; 169188f1096SBen Tyner additional.emplace("RAWPEL", filePath.string()); 170188f1096SBen Tyner additional.emplace("_PID", std::to_string(getpid())); 171188f1096SBen Tyner 172188f1096SBen Tyner // dbus specifics 173188f1096SBen Tyner constexpr auto interface = "xyz.openbmc_project.Logging.Create"; 174188f1096SBen Tyner constexpr auto function = "Create"; 175188f1096SBen Tyner 176188f1096SBen Tyner sdbusplus::message::message method; 177188f1096SBen Tyner 178188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 179188f1096SBen Tyner { 180188f1096SBen Tyner try 181188f1096SBen Tyner { 182188f1096SBen Tyner // append additional dbus call parameters 183188f1096SBen Tyner method.append(eventPelTerminate, levelPelError, additional); 184188f1096SBen Tyner 185188f1096SBen Tyner // using system dbus, no reply 186188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 187188f1096SBen Tyner bus.call_noreply(method); 188188f1096SBen Tyner } 189188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 190188f1096SBen Tyner { 1916764d70eSBen Tyner trace<level::INFO>("createPelRaw exception"); 1926764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 1936764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 194188f1096SBen Tyner } 195188f1096SBen Tyner } 196188f1096SBen Tyner } 197188f1096SBen Tyner 198188f1096SBen Tyner /** @brief Get file descriptor of exisitng PEL */ 199188f1096SBen Tyner int getPel(const uint32_t i_pelId) 200188f1096SBen Tyner { 201188f1096SBen Tyner // GetPEL returns file descriptor (int) 202188f1096SBen Tyner int fd = -1; 203188f1096SBen Tyner 204188f1096SBen Tyner // dbus specifics 205188f1096SBen Tyner constexpr auto interface = "org.open_power.Logging.PEL"; 206188f1096SBen Tyner constexpr auto function = "GetPEL"; 207188f1096SBen Tyner 208188f1096SBen Tyner sdbusplus::message::message method; 209188f1096SBen Tyner 210188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 211188f1096SBen Tyner { 212188f1096SBen Tyner try 213188f1096SBen Tyner { 214188f1096SBen Tyner // additional dbus call parameters 215188f1096SBen Tyner method.append(i_pelId); 216188f1096SBen Tyner 217188f1096SBen Tyner // using system dbus 218188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 219188f1096SBen Tyner auto response = bus.call(method); 220188f1096SBen Tyner 221188f1096SBen Tyner // reply will be a unix file descriptor 222188f1096SBen Tyner sdbusplus::message::unix_fd reply; 223188f1096SBen Tyner 224*4bbcb38fSBen Tyner // parse dbus response into reply 225188f1096SBen Tyner response.read(reply); 226188f1096SBen Tyner 227188f1096SBen Tyner fd = dup(reply); // need to copy (dup) the file descriptor 228188f1096SBen Tyner } 229188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 230188f1096SBen Tyner { 2316764d70eSBen Tyner trace<level::INFO>("getPel exception"); 2326764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 2336764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 234188f1096SBen Tyner } 235188f1096SBen Tyner } 236188f1096SBen Tyner 237188f1096SBen Tyner return fd; // file descriptor or -1 238188f1096SBen Tyner } 239188f1096SBen Tyner 240*4bbcb38fSBen Tyner /** @brief Get the running state of the host */ 241*4bbcb38fSBen Tyner HostRunningState hostRunningState() 242*4bbcb38fSBen Tyner { 243*4bbcb38fSBen Tyner HostRunningState host = HostRunningState::Unknown; 244*4bbcb38fSBen Tyner 245*4bbcb38fSBen Tyner // dbus specifics 246*4bbcb38fSBen Tyner constexpr auto path = "/xyz/openbmc_project/state/host0"; 247*4bbcb38fSBen Tyner constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress"; 248*4bbcb38fSBen Tyner constexpr auto extended = "org.freedesktop.DBus.Properties"; 249*4bbcb38fSBen Tyner constexpr auto function = "Get"; 250*4bbcb38fSBen Tyner 251*4bbcb38fSBen Tyner sdbusplus::message::message method; 252*4bbcb38fSBen Tyner 253*4bbcb38fSBen Tyner if (0 == dbusMethod(path, interface, function, method, extended)) 254*4bbcb38fSBen Tyner { 255*4bbcb38fSBen Tyner try 256*4bbcb38fSBen Tyner { 257*4bbcb38fSBen Tyner // additional dbus call parameters 258*4bbcb38fSBen Tyner method.append(interface, "BootProgress"); 259*4bbcb38fSBen Tyner 260*4bbcb38fSBen Tyner // using system dbus 261*4bbcb38fSBen Tyner auto bus = sdbusplus::bus::new_system(); 262*4bbcb38fSBen Tyner auto response = bus.call(method); 263*4bbcb38fSBen Tyner 264*4bbcb38fSBen Tyner // reply will be a variant 265*4bbcb38fSBen Tyner std::variant<std::string, bool, std::vector<uint8_t>, 266*4bbcb38fSBen Tyner std::vector<std::string>> 267*4bbcb38fSBen Tyner reply; 268*4bbcb38fSBen Tyner 269*4bbcb38fSBen Tyner // parse dbus response into reply 270*4bbcb38fSBen Tyner response.read(reply); 271*4bbcb38fSBen Tyner 272*4bbcb38fSBen Tyner // get boot progress (string) and convert to boot stage 273*4bbcb38fSBen Tyner std::string bootProgress(std::get<std::string>(reply)); 274*4bbcb38fSBen Tyner 275*4bbcb38fSBen Tyner using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot:: 276*4bbcb38fSBen Tyner server::Progress::ProgressStages; 277*4bbcb38fSBen Tyner 278*4bbcb38fSBen Tyner BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot:: 279*4bbcb38fSBen Tyner server::Progress::convertProgressStagesFromString(bootProgress); 280*4bbcb38fSBen Tyner 281*4bbcb38fSBen Tyner if ((stage == BootProgress::SystemInitComplete) || 282*4bbcb38fSBen Tyner (stage == BootProgress::OSStart) || 283*4bbcb38fSBen Tyner (stage == BootProgress::OSRunning)) 284*4bbcb38fSBen Tyner { 285*4bbcb38fSBen Tyner host = HostRunningState::Started; 286*4bbcb38fSBen Tyner } 287*4bbcb38fSBen Tyner else 288*4bbcb38fSBen Tyner { 289*4bbcb38fSBen Tyner host = HostRunningState::NotStarted; 290*4bbcb38fSBen Tyner } 291*4bbcb38fSBen Tyner } 292*4bbcb38fSBen Tyner catch (const sdbusplus::exception::SdBusError& e) 293*4bbcb38fSBen Tyner { 294*4bbcb38fSBen Tyner trace<level::INFO>("hostRunningState exception"); 295*4bbcb38fSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 296*4bbcb38fSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 297*4bbcb38fSBen Tyner } 298*4bbcb38fSBen Tyner } 299*4bbcb38fSBen Tyner 300*4bbcb38fSBen Tyner return host; 301*4bbcb38fSBen Tyner } 302188f1096SBen Tyner } // namespace attn 303