1 #include <attn_dbus.hpp> 2 #include <attn_handler.hpp> 3 #include <attn_logging.hpp> 4 #include <xyz/openbmc_project/State/Boot/Progress/server.hpp> 5 6 #include <string> 7 #include <vector> 8 9 namespace attn 10 { 11 12 /** @brief Create a dbus method */ 13 int dbusMethod(const std::string& i_path, const std::string& i_interface, 14 const std::string& i_function, 15 sdbusplus::message::message& o_method, 16 const std::string& i_extended) 17 { 18 int rc = RC_DBUS_ERROR; // assume error 19 20 try 21 { 22 constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper"; 23 constexpr auto pathFind = "/xyz/openbmc_project/object_mapper"; 24 constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper"; 25 constexpr auto functionFind = "GetObject"; 26 27 auto bus = sdbusplus::bus::new_system(); // using system dbus 28 29 // method to find service from object path and object interface 30 auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind, 31 functionFind); 32 33 // find the service for specified object path and interface 34 method.append(i_path.c_str()); 35 method.append(std::vector<std::string>({i_interface})); 36 auto reply = bus.call(method); 37 38 // dbus call results 39 std::map<std::string, std::vector<std::string>> responseFindService; 40 reply.read(responseFindService); 41 42 // If we successfully found the service associated with the dbus object 43 // path and interface then create a method for the specified interface 44 // and function. 45 if (!responseFindService.empty()) 46 { 47 auto service = responseFindService.begin()->first; 48 49 // Some methods (e.g. get attribute) take an extended parameter 50 if (i_extended == "") 51 { 52 // return the method 53 o_method = bus.new_method_call(service.c_str(), i_path.c_str(), 54 i_interface.c_str(), 55 i_function.c_str()); 56 } 57 else 58 { 59 // return extended method 60 o_method = 61 bus.new_method_call(service.c_str(), i_path.c_str(), 62 i_extended.c_str(), i_function.c_str()); 63 } 64 65 rc = RC_SUCCESS; 66 } 67 else 68 { 69 // This trace will be picked up in event log 70 trace<level::INFO>("dbusMethod service not found"); 71 std::string traceMsgPath = std::string(i_path, maxTraceLen); 72 trace<level::INFO>(traceMsgPath.c_str()); 73 std::string traceMsgIface = std::string(i_interface, maxTraceLen); 74 trace<level::INFO>(traceMsgIface.c_str()); 75 } 76 } 77 catch (const sdbusplus::exception::SdBusError& e) 78 { 79 trace<level::ERROR>("dbusMethod exception"); 80 std::string traceMsg = std::string(e.what(), maxTraceLen); 81 trace<level::ERROR>(traceMsg.c_str()); 82 } 83 84 return rc; 85 } 86 87 /** @brief Create a PEL for the specified event type */ 88 uint32_t createPel(const std::string& i_event, 89 std::map<std::string, std::string>& i_additional, 90 const std::vector<util::FFDCTuple>& i_ffdc) 91 { 92 // CreatePELWithFFDCFiles returns plid 93 int plid = 0; 94 95 // Need to provide pid when using create or create-with-ffdc methods 96 i_additional.emplace("_PID", std::to_string(getpid())); 97 98 // Sdbus call specifics 99 constexpr auto interface = "org.open_power.Logging.PEL"; 100 constexpr auto function = "CreatePELWithFFDCFiles"; 101 102 sdbusplus::message::message method; 103 104 if (0 == dbusMethod(pathLogging, interface, function, method)) 105 { 106 try 107 { 108 // append additional dbus call paramaters 109 method.append(i_event, levelPelError, i_additional, i_ffdc); 110 111 // using system dbus 112 auto bus = sdbusplus::bus::new_system(); 113 auto response = bus.call(method); 114 115 // reply will be tuple containing bmc log id, platform log id 116 std::tuple<uint32_t, uint32_t> reply = {0, 0}; 117 118 // parse dbus response into reply 119 response.read(reply); 120 plid = std::get<1>(reply); // platform log id is tuple "second" 121 } 122 catch (const sdbusplus::exception::SdBusError& e) 123 { 124 trace<level::ERROR>("createPel exception"); 125 std::string traceMsg = std::string(e.what(), maxTraceLen); 126 trace<level::ERROR>(traceMsg.c_str()); 127 } 128 } 129 130 return plid; // platform log id or 0 131 } 132 133 /** @brief Create a PEL from raw PEL data */ 134 void createPelRaw(const std::vector<uint8_t>& i_buffer) 135 { 136 // Create FFDC file from buffer data 137 util::FFDCFile pelFile{util::FFDCFormat::Text}; 138 auto fd = pelFile.getFileDescriptor(); 139 140 auto filePath = pelFile.getPath(); // path to ffdc file 141 142 size_t numBytes = write(fd, i_buffer.data(), i_buffer.size()); 143 if (i_buffer.size() != numBytes) 144 { 145 std::stringstream traceMsg; 146 traceMsg << filePath.c_str() << " only " << (int)numBytes << " of " 147 << (int)i_buffer.size() << " bytes written"; 148 auto strobj = traceMsg.str(); 149 trace<level::ERROR>(strobj.c_str()); 150 } 151 152 lseek(fd, 0, SEEK_SET); 153 154 // Additional data for log 155 std::map<std::string, std::string> additional; 156 additional.emplace("RAWPEL", filePath.string()); 157 additional.emplace("_PID", std::to_string(getpid())); 158 159 // dbus specifics 160 constexpr auto interface = "xyz.openbmc_project.Logging.Create"; 161 constexpr auto function = "Create"; 162 163 sdbusplus::message::message method; 164 165 if (0 == dbusMethod(pathLogging, interface, function, method)) 166 { 167 try 168 { 169 // append additional dbus call parameters 170 method.append(eventPelTerminate, levelPelError, additional); 171 172 // using system dbus, no reply 173 auto bus = sdbusplus::bus::new_system(); 174 bus.call_noreply(method); 175 } 176 catch (const sdbusplus::exception::SdBusError& e) 177 { 178 trace<level::ERROR>("createPelRaw exception"); 179 std::string traceMsg = std::string(e.what(), maxTraceLen); 180 trace<level::ERROR>(traceMsg.c_str()); 181 } 182 } 183 } 184 185 /** @brief Get file descriptor of exisitng PEL */ 186 int getPel(const uint32_t i_pelId) 187 { 188 // GetPEL returns file descriptor (int) 189 int fd = -1; 190 191 // dbus specifics 192 constexpr auto interface = "org.open_power.Logging.PEL"; 193 constexpr auto function = "GetPEL"; 194 195 sdbusplus::message::message method; 196 197 if (0 == dbusMethod(pathLogging, interface, function, method)) 198 { 199 try 200 { 201 // additional dbus call parameters 202 method.append(i_pelId); 203 204 // using system dbus 205 auto bus = sdbusplus::bus::new_system(); 206 auto response = bus.call(method); 207 208 // reply will be a unix file descriptor 209 sdbusplus::message::unix_fd reply; 210 211 // parse dbus response into reply 212 response.read(reply); 213 214 fd = dup(reply); // need to copy (dup) the file descriptor 215 } 216 catch (const sdbusplus::exception::SdBusError& e) 217 { 218 trace<level::ERROR>("getPel exception"); 219 std::string traceMsg = std::string(e.what(), maxTraceLen); 220 trace<level::ERROR>(traceMsg.c_str()); 221 } 222 } 223 224 return fd; // file descriptor or -1 225 } 226 227 /** @brief Get the running state of the host */ 228 HostRunningState hostRunningState() 229 { 230 HostRunningState host = HostRunningState::Unknown; 231 232 // dbus specifics 233 constexpr auto path = "/xyz/openbmc_project/state/host0"; 234 constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress"; 235 constexpr auto extended = "org.freedesktop.DBus.Properties"; 236 constexpr auto function = "Get"; 237 238 sdbusplus::message::message method; 239 240 if (0 == dbusMethod(path, interface, function, method, extended)) 241 { 242 try 243 { 244 // additional dbus call parameters 245 method.append(interface, "BootProgress"); 246 247 // using system dbus 248 auto bus = sdbusplus::bus::new_system(); 249 auto response = bus.call(method); 250 251 // reply will be a variant 252 std::variant<std::string, bool, std::vector<uint8_t>, 253 std::vector<std::string>> 254 reply; 255 256 // parse dbus response into reply 257 response.read(reply); 258 259 // get boot progress (string) and convert to boot stage 260 std::string bootProgress(std::get<std::string>(reply)); 261 262 using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot:: 263 server::Progress::ProgressStages; 264 265 BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot:: 266 server::Progress::convertProgressStagesFromString(bootProgress); 267 268 if ((stage == BootProgress::SystemInitComplete) || 269 (stage == BootProgress::OSStart) || 270 (stage == BootProgress::OSRunning)) 271 { 272 host = HostRunningState::Started; 273 } 274 else 275 { 276 host = HostRunningState::NotStarted; 277 } 278 } 279 catch (const sdbusplus::exception::SdBusError& e) 280 { 281 trace<level::ERROR>("hostRunningState exception"); 282 std::string traceMsg = std::string(e.what(), maxTraceLen); 283 trace<level::ERROR>(traceMsg.c_str()); 284 } 285 } 286 287 return host; 288 } 289 } // namespace attn 290