1 #include "config.h"
2 
3 #include "ramoops_manager.hpp"
4 
5 #include "dump_manager.hpp"
6 
7 #include <phosphor-logging/elog-errors.hpp>
8 #include <phosphor-logging/lg2.hpp>
9 #include <sdbusplus/bus.hpp>
10 #include <sdbusplus/exception.hpp>
11 #include <xyz/openbmc_project/Dump/Create/common.hpp>
12 #include <xyz/openbmc_project/Dump/Create/server.hpp>
13 
14 #include <filesystem>
15 #include <set>
16 
17 namespace phosphor
18 {
19 namespace dump
20 {
21 namespace ramoops
22 {
23 
24 Manager::Manager(const std::string& filePath)
25 {
26     namespace fs = std::filesystem;
27 
28     fs::path dir(filePath);
29     if (!fs::exists(dir) || fs::is_empty(dir))
30     {
31         return;
32     }
33 
34     // Create error to notify user that a ramoops has been detected
35     createError();
36 
37     std::vector<std::string> files;
38     files.push_back(filePath);
39 
40     createHelper(files);
41 }
42 
43 void Manager::createError()
44 {
45     try
46     {
47         std::map<std::string, std::string> additionalData;
48 
49         // Always add the _PID on for some extra logging debug
50         additionalData.emplace("_PID", std::to_string(getpid()));
51 
52         auto bus = sdbusplus::bus::new_default();
53         auto method = bus.new_method_call(
54             "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
55             "xyz.openbmc_project.Logging.Create", "Create");
56 
57         method.append("xyz.openbmc_project.Dump.Error.Ramoops",
58                       sdbusplus::server::xyz::openbmc_project::logging::Entry::
59                           Level::Error,
60                       additionalData);
61         auto resp = bus.call(method);
62     }
63     catch (const sdbusplus::exception_t& e)
64     {
65         lg2::error(
66             "sdbusplus D-Bus call exception, error {ERROR} trying to create "
67             "an error for ramoops detection",
68             "ERROR", e);
69         // This is a best-effort logging situation so don't throw anything
70     }
71     catch (const std::exception& e)
72     {
73         lg2::error("D-bus call exception: {ERROR}", "ERROR", e);
74         // This is a best-effort logging situation so don't throw anything
75     }
76 }
77 
78 void Manager::createHelper(const std::vector<std::string>& files)
79 {
80     constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
81     constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
82     constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
83     constexpr auto DUMP_CREATE_IFACE = "xyz.openbmc_project.Dump.Create";
84 
85     auto b = sdbusplus::bus::new_default();
86     auto mapper = b.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
87                                     MAPPER_INTERFACE, "GetObject");
88     mapper.append(BMC_DUMP_OBJPATH, std::set<std::string>({DUMP_CREATE_IFACE}));
89 
90     std::map<std::string, std::set<std::string>> mapperResponse;
91     try
92     {
93         auto mapperResponseMsg = b.call(mapper);
94         mapperResponseMsg.read(mapperResponse);
95     }
96     catch (const sdbusplus::exception_t& e)
97     {
98         lg2::error("Failed to parse dump create message, error: {ERROR}",
99                    "ERROR", e);
100         return;
101     }
102     if (mapperResponse.empty())
103     {
104         lg2::error("Error reading mapper response");
105         return;
106     }
107 
108     const auto& host = mapperResponse.cbegin()->first;
109     auto m = b.new_method_call(host.c_str(), BMC_DUMP_OBJPATH,
110                                DUMP_CREATE_IFACE, "CreateDump");
111     phosphor::dump::DumpCreateParams params;
112     using CreateParameters =
113         sdbusplus::common::xyz::openbmc_project::dump::Create::CreateParameters;
114     using DumpType =
115         sdbusplus::common::xyz::openbmc_project::dump::Create::DumpType;
116     using DumpIntr = sdbusplus::common::xyz::openbmc_project::dump::Create;
117     params[DumpIntr::convertCreateParametersToString(
118         CreateParameters::DumpType)] =
119         DumpIntr::convertDumpTypeToString(DumpType::Ramoops);
120     params[DumpIntr::convertCreateParametersToString(
121         CreateParameters::FilePath)] = files.front();
122     m.append(params);
123     try
124     {
125         b.call_noreply(m);
126     }
127     catch (const sdbusplus::exception_t& e)
128     {
129         lg2::error("Failed to create ramoops dump, errormsg: {ERROR}", "ERROR",
130                    e);
131     }
132 }
133 
134 } // namespace ramoops
135 } // namespace dump
136 } // namespace phosphor
137