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