14bbcb38fSBen Tyner #include <attn_dbus.hpp> 24bbcb38fSBen Tyner #include <attn_handler.hpp> 3188f1096SBen Tyner #include <attn_logging.hpp> 44bbcb38fSBen 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 12*5c5db65aSBen 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, 154bbcb38fSBen Tyner sdbusplus::message::message& o_method, 16*5c5db65aSBen Tyner const std::string& i_extended) 17188f1096SBen Tyner { 184bbcb38fSBen Tyner int rc = RC_DBUS_ERROR; // assume error 19188f1096SBen Tyner 20188f1096SBen Tyner try 21188f1096SBen Tyner { 22188f1096SBen Tyner constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper"; 23188f1096SBen Tyner constexpr auto pathFind = "/xyz/openbmc_project/object_mapper"; 24188f1096SBen Tyner constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper"; 25188f1096SBen Tyner constexpr auto functionFind = "GetObject"; 26188f1096SBen Tyner 27188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); // using system dbus 28188f1096SBen Tyner 29188f1096SBen Tyner // method to find service from object path and object interface 30188f1096SBen Tyner auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind, 31188f1096SBen Tyner functionFind); 32188f1096SBen Tyner 33188f1096SBen Tyner // find the service for specified object path and interface 34188f1096SBen Tyner method.append(i_path.c_str()); 35188f1096SBen Tyner method.append(std::vector<std::string>({i_interface})); 36188f1096SBen Tyner auto reply = bus.call(method); 37188f1096SBen Tyner 38188f1096SBen Tyner // dbus call results 39188f1096SBen Tyner std::map<std::string, std::vector<std::string>> responseFindService; 40188f1096SBen Tyner reply.read(responseFindService); 41188f1096SBen Tyner 42188f1096SBen Tyner // If we successfully found the service associated with the dbus object 43188f1096SBen Tyner // path and interface then create a method for the specified interface 44188f1096SBen Tyner // and function. 45188f1096SBen Tyner if (!responseFindService.empty()) 46188f1096SBen Tyner { 47188f1096SBen Tyner auto service = responseFindService.begin()->first; 48188f1096SBen Tyner 494bbcb38fSBen Tyner // Some methods (e.g. get attribute) take an extended parameter 504bbcb38fSBen Tyner if (i_extended == "") 514bbcb38fSBen Tyner { 52188f1096SBen Tyner // return the method 534bbcb38fSBen Tyner o_method = bus.new_method_call(service.c_str(), i_path.c_str(), 544bbcb38fSBen Tyner i_interface.c_str(), 554bbcb38fSBen Tyner i_function.c_str()); 564bbcb38fSBen Tyner } 574bbcb38fSBen Tyner else 584bbcb38fSBen Tyner { 594bbcb38fSBen Tyner // return extended method 60188f1096SBen Tyner o_method = 61188f1096SBen Tyner bus.new_method_call(service.c_str(), i_path.c_str(), 624bbcb38fSBen Tyner i_extended.c_str(), i_function.c_str()); 634bbcb38fSBen Tyner } 64188f1096SBen Tyner 654bbcb38fSBen Tyner rc = RC_SUCCESS; 66188f1096SBen Tyner } 67188f1096SBen Tyner else 68188f1096SBen Tyner { 696764d70eSBen Tyner // This trace will be picked up in event log 706764d70eSBen Tyner trace<level::INFO>("dbusMethod service not found"); 716764d70eSBen Tyner std::string traceMsgPath = std::string(i_path, maxTraceLen); 726764d70eSBen Tyner trace<level::INFO>(traceMsgPath.c_str()); 736764d70eSBen Tyner std::string traceMsgIface = std::string(i_interface, maxTraceLen); 746764d70eSBen Tyner trace<level::INFO>(traceMsgIface.c_str()); 75188f1096SBen Tyner } 76188f1096SBen Tyner } 77188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 78188f1096SBen Tyner { 79*5c5db65aSBen Tyner trace<level::ERROR>("dbusMethod exception"); 806764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 816764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 82188f1096SBen Tyner } 83188f1096SBen Tyner 84188f1096SBen Tyner return rc; 85188f1096SBen Tyner } 86188f1096SBen Tyner 87188f1096SBen Tyner /** @brief Create a PEL for the specified event type */ 88188f1096SBen Tyner uint32_t createPel(const std::string& i_event, 89188f1096SBen Tyner std::map<std::string, std::string>& i_additional, 90188f1096SBen Tyner const std::vector<util::FFDCTuple>& i_ffdc) 91188f1096SBen Tyner { 92188f1096SBen Tyner // CreatePELWithFFDCFiles returns plid 93188f1096SBen Tyner int plid = 0; 94188f1096SBen Tyner 95188f1096SBen Tyner // Need to provide pid when using create or create-with-ffdc methods 96188f1096SBen Tyner i_additional.emplace("_PID", std::to_string(getpid())); 97188f1096SBen Tyner 98188f1096SBen Tyner // Sdbus call specifics 99188f1096SBen Tyner constexpr auto interface = "org.open_power.Logging.PEL"; 100188f1096SBen Tyner constexpr auto function = "CreatePELWithFFDCFiles"; 101188f1096SBen Tyner 102188f1096SBen Tyner sdbusplus::message::message method; 103188f1096SBen Tyner 104188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 105188f1096SBen Tyner { 106188f1096SBen Tyner try 107188f1096SBen Tyner { 108188f1096SBen Tyner // append additional dbus call paramaters 109188f1096SBen Tyner method.append(i_event, levelPelError, i_additional, i_ffdc); 110188f1096SBen Tyner 111188f1096SBen Tyner // using system dbus 112188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 113188f1096SBen Tyner auto response = bus.call(method); 114188f1096SBen Tyner 115188f1096SBen Tyner // reply will be tuple containing bmc log id, platform log id 116188f1096SBen Tyner std::tuple<uint32_t, uint32_t> reply = {0, 0}; 117188f1096SBen Tyner 1184bbcb38fSBen Tyner // parse dbus response into reply 119188f1096SBen Tyner response.read(reply); 120188f1096SBen Tyner plid = std::get<1>(reply); // platform log id is tuple "second" 121188f1096SBen Tyner } 122188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 123188f1096SBen Tyner { 124*5c5db65aSBen Tyner trace<level::ERROR>("createPel exception"); 1256764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 1266764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 127188f1096SBen Tyner } 128188f1096SBen Tyner } 129188f1096SBen Tyner 130188f1096SBen Tyner return plid; // platform log id or 0 131188f1096SBen Tyner } 132188f1096SBen Tyner 133188f1096SBen Tyner /** @brief Create a PEL from raw PEL data */ 134188f1096SBen Tyner void createPelRaw(const std::vector<uint8_t>& i_buffer) 135188f1096SBen Tyner { 136188f1096SBen Tyner // Create FFDC file from buffer data 137188f1096SBen Tyner util::FFDCFile pelFile{util::FFDCFormat::Text}; 138188f1096SBen Tyner auto fd = pelFile.getFileDescriptor(); 139188f1096SBen Tyner 140188f1096SBen Tyner auto filePath = pelFile.getPath(); // path to ffdc file 141188f1096SBen Tyner 142d700609cSBen Tyner size_t numBytes = write(fd, i_buffer.data(), i_buffer.size()); 143d700609cSBen Tyner if (i_buffer.size() != numBytes) 144d700609cSBen Tyner { 145d700609cSBen Tyner std::stringstream traceMsg; 146d700609cSBen Tyner traceMsg << filePath.c_str() << " only " << (int)numBytes << " of " 147d700609cSBen Tyner << (int)i_buffer.size() << " bytes written"; 148d700609cSBen Tyner auto strobj = traceMsg.str(); 149d700609cSBen Tyner trace<level::ERROR>(strobj.c_str()); 150d700609cSBen Tyner } 151d700609cSBen Tyner 152d700609cSBen Tyner lseek(fd, 0, SEEK_SET); 153d700609cSBen Tyner 154188f1096SBen Tyner // Additional data for log 155188f1096SBen Tyner std::map<std::string, std::string> additional; 156188f1096SBen Tyner additional.emplace("RAWPEL", filePath.string()); 157188f1096SBen Tyner additional.emplace("_PID", std::to_string(getpid())); 158188f1096SBen Tyner 159188f1096SBen Tyner // dbus specifics 160188f1096SBen Tyner constexpr auto interface = "xyz.openbmc_project.Logging.Create"; 161188f1096SBen Tyner constexpr auto function = "Create"; 162188f1096SBen Tyner 163188f1096SBen Tyner sdbusplus::message::message method; 164188f1096SBen Tyner 165188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 166188f1096SBen Tyner { 167188f1096SBen Tyner try 168188f1096SBen Tyner { 169188f1096SBen Tyner // append additional dbus call parameters 170188f1096SBen Tyner method.append(eventPelTerminate, levelPelError, additional); 171188f1096SBen Tyner 172188f1096SBen Tyner // using system dbus, no reply 173188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 174188f1096SBen Tyner bus.call_noreply(method); 175188f1096SBen Tyner } 176188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 177188f1096SBen Tyner { 178*5c5db65aSBen Tyner trace<level::ERROR>("createPelRaw exception"); 1796764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 1806764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 181188f1096SBen Tyner } 182188f1096SBen Tyner } 183188f1096SBen Tyner } 184188f1096SBen Tyner 185188f1096SBen Tyner /** @brief Get file descriptor of exisitng PEL */ 186188f1096SBen Tyner int getPel(const uint32_t i_pelId) 187188f1096SBen Tyner { 188188f1096SBen Tyner // GetPEL returns file descriptor (int) 189188f1096SBen Tyner int fd = -1; 190188f1096SBen Tyner 191188f1096SBen Tyner // dbus specifics 192188f1096SBen Tyner constexpr auto interface = "org.open_power.Logging.PEL"; 193188f1096SBen Tyner constexpr auto function = "GetPEL"; 194188f1096SBen Tyner 195188f1096SBen Tyner sdbusplus::message::message method; 196188f1096SBen Tyner 197188f1096SBen Tyner if (0 == dbusMethod(pathLogging, interface, function, method)) 198188f1096SBen Tyner { 199188f1096SBen Tyner try 200188f1096SBen Tyner { 201188f1096SBen Tyner // additional dbus call parameters 202188f1096SBen Tyner method.append(i_pelId); 203188f1096SBen Tyner 204188f1096SBen Tyner // using system dbus 205188f1096SBen Tyner auto bus = sdbusplus::bus::new_system(); 206188f1096SBen Tyner auto response = bus.call(method); 207188f1096SBen Tyner 208188f1096SBen Tyner // reply will be a unix file descriptor 209188f1096SBen Tyner sdbusplus::message::unix_fd reply; 210188f1096SBen Tyner 2114bbcb38fSBen Tyner // parse dbus response into reply 212188f1096SBen Tyner response.read(reply); 213188f1096SBen Tyner 214188f1096SBen Tyner fd = dup(reply); // need to copy (dup) the file descriptor 215188f1096SBen Tyner } 216188f1096SBen Tyner catch (const sdbusplus::exception::SdBusError& e) 217188f1096SBen Tyner { 218*5c5db65aSBen Tyner trace<level::ERROR>("getPel exception"); 2196764d70eSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 2206764d70eSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 221188f1096SBen Tyner } 222188f1096SBen Tyner } 223188f1096SBen Tyner 224188f1096SBen Tyner return fd; // file descriptor or -1 225188f1096SBen Tyner } 226188f1096SBen Tyner 2274bbcb38fSBen Tyner /** @brief Get the running state of the host */ 2284bbcb38fSBen Tyner HostRunningState hostRunningState() 2294bbcb38fSBen Tyner { 2304bbcb38fSBen Tyner HostRunningState host = HostRunningState::Unknown; 2314bbcb38fSBen Tyner 2324bbcb38fSBen Tyner // dbus specifics 2334bbcb38fSBen Tyner constexpr auto path = "/xyz/openbmc_project/state/host0"; 2344bbcb38fSBen Tyner constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress"; 2354bbcb38fSBen Tyner constexpr auto extended = "org.freedesktop.DBus.Properties"; 2364bbcb38fSBen Tyner constexpr auto function = "Get"; 2374bbcb38fSBen Tyner 2384bbcb38fSBen Tyner sdbusplus::message::message method; 2394bbcb38fSBen Tyner 2404bbcb38fSBen Tyner if (0 == dbusMethod(path, interface, function, method, extended)) 2414bbcb38fSBen Tyner { 2424bbcb38fSBen Tyner try 2434bbcb38fSBen Tyner { 2444bbcb38fSBen Tyner // additional dbus call parameters 2454bbcb38fSBen Tyner method.append(interface, "BootProgress"); 2464bbcb38fSBen Tyner 2474bbcb38fSBen Tyner // using system dbus 2484bbcb38fSBen Tyner auto bus = sdbusplus::bus::new_system(); 2494bbcb38fSBen Tyner auto response = bus.call(method); 2504bbcb38fSBen Tyner 2514bbcb38fSBen Tyner // reply will be a variant 2524bbcb38fSBen Tyner std::variant<std::string, bool, std::vector<uint8_t>, 2534bbcb38fSBen Tyner std::vector<std::string>> 2544bbcb38fSBen Tyner reply; 2554bbcb38fSBen Tyner 2564bbcb38fSBen Tyner // parse dbus response into reply 2574bbcb38fSBen Tyner response.read(reply); 2584bbcb38fSBen Tyner 2594bbcb38fSBen Tyner // get boot progress (string) and convert to boot stage 2604bbcb38fSBen Tyner std::string bootProgress(std::get<std::string>(reply)); 2614bbcb38fSBen Tyner 2624bbcb38fSBen Tyner using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot:: 2634bbcb38fSBen Tyner server::Progress::ProgressStages; 2644bbcb38fSBen Tyner 2654bbcb38fSBen Tyner BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot:: 2664bbcb38fSBen Tyner server::Progress::convertProgressStagesFromString(bootProgress); 2674bbcb38fSBen Tyner 2684bbcb38fSBen Tyner if ((stage == BootProgress::SystemInitComplete) || 2694bbcb38fSBen Tyner (stage == BootProgress::OSStart) || 2704bbcb38fSBen Tyner (stage == BootProgress::OSRunning)) 2714bbcb38fSBen Tyner { 2724bbcb38fSBen Tyner host = HostRunningState::Started; 2734bbcb38fSBen Tyner } 2744bbcb38fSBen Tyner else 2754bbcb38fSBen Tyner { 2764bbcb38fSBen Tyner host = HostRunningState::NotStarted; 2774bbcb38fSBen Tyner } 2784bbcb38fSBen Tyner } 2794bbcb38fSBen Tyner catch (const sdbusplus::exception::SdBusError& e) 2804bbcb38fSBen Tyner { 281*5c5db65aSBen Tyner trace<level::ERROR>("hostRunningState exception"); 2824bbcb38fSBen Tyner std::string traceMsg = std::string(e.what(), maxTraceLen); 2834bbcb38fSBen Tyner trace<level::ERROR>(traceMsg.c_str()); 2844bbcb38fSBen Tyner } 2854bbcb38fSBen Tyner } 2864bbcb38fSBen Tyner 2874bbcb38fSBen Tyner return host; 2884bbcb38fSBen Tyner } 289188f1096SBen Tyner } // namespace attn 290