1 /**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "pldm_oem_cmds.hpp"
17
18 #include "dump_utils.hpp"
19 #include "pldm_utils.hpp"
20 #include "xyz/openbmc_project/Common/error.hpp"
21
22 #include <libpldm/base.h>
23 #include <libpldm/oem/ibm/file_io.h>
24 #include <libpldm/platform.h>
25 #include <unistd.h>
26
27 #include <phosphor-logging/elog-errors.hpp>
28 #include <phosphor-logging/lg2.hpp>
29 #include <sdbusplus/bus.hpp>
30
31 #include <fstream>
32
33 namespace phosphor
34 {
35 namespace dump
36 {
37 namespace host
38 {
39 /**
40 * @brief Initiate offload of the dump with provided id
41 *
42 * @param[in] id - The Dump Source ID.
43 *
44 */
requestOffload(uint32_t id)45 void requestOffload(uint32_t id)
46 {
47 pldm::requestOffload(id);
48 }
49
requestDelete(uint32_t id,uint32_t dumpType)50 void requestDelete(uint32_t id, uint32_t dumpType)
51 {
52 pldm::requestDelete(id, dumpType);
53 }
54 } // namespace host
55
56 namespace pldm
57 {
58
59 using namespace phosphor::logging;
60
61 constexpr auto eidPath = "/usr/share/pldm/host_eid";
62 constexpr mctp_eid_t defaultEIDValue = 9;
63
64 using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
65 using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
66
readEID()67 mctp_eid_t readEID()
68 {
69 mctp_eid_t eid = defaultEIDValue;
70
71 std::ifstream eidFile{eidPath};
72 if (!eidFile.good())
73 {
74 lg2::error("Could not open host EID file");
75 elog<NotAllowed>(Reason("Required host dump action via pldm is not "
76 "allowed due to mctp end point read failed"));
77 }
78 else
79 {
80 std::string eid;
81 eidFile >> eid;
82 if (!eid.empty())
83 {
84 eid = strtol(eid.c_str(), nullptr, 10);
85 }
86 else
87 {
88 lg2::error("EID file was empty");
89 elog<NotAllowed>(
90 Reason("Required host dump action via pldm is not "
91 "allowed due to mctp end point read failed"));
92 }
93 }
94
95 return eid;
96 }
97
requestOffload(uint32_t id)98 void requestOffload(uint32_t id)
99 {
100 uint16_t effecterId = 0x05; // TODO PhyP temporary Hardcoded value.
101
102 std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(id) +
103 sizeof(uint8_t)>
104 requestMsg{};
105 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
106
107 std::array<uint8_t, sizeof(id)> effecterValue{};
108
109 memcpy(effecterValue.data(), &id, sizeof(id));
110
111 mctp_eid_t eid = readEID();
112
113 auto instanceID = getPLDMInstanceID(eid);
114
115 auto rc = encode_set_numeric_effecter_value_req(
116 instanceID, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
117 effecterValue.data(), request,
118 requestMsg.size() - sizeof(pldm_msg_hdr));
119
120 if (rc != PLDM_SUCCESS)
121 {
122 lg2::error("Message encode failure. RC: {RC}", "RC", rc);
123 elog<NotAllowed>(Reason("Host dump offload via pldm is not "
124 "allowed due to encode failed"));
125 }
126
127 CustomFd fd(openPLDM());
128
129 lg2::info("Sending request to offload dump id: {ID}, eid: {EID}", "ID", id,
130 "EID", eid);
131
132 rc = pldm_send(eid, fd(), requestMsg.data(), requestMsg.size());
133 if (rc < 0)
134 {
135 auto e = errno;
136 lg2::error("pldm_send failed, RC: {RC}, errno: {ERRNO}", "RC", rc,
137 "ERRNO", e);
138 elog<NotAllowed>(Reason("Host dump offload via pldm is not "
139 "allowed due to fileack send failed"));
140 }
141 lg2::info("Done. PLDM message, id: {ID}, RC: {RC}", "ID", id, "RC", rc);
142 }
143
requestDelete(uint32_t dumpId,uint32_t dumpType)144 void requestDelete(uint32_t dumpId, uint32_t dumpType)
145 {
146 pldm_fileio_file_type pldmDumpType;
147 switch (dumpType)
148 {
149 case PLDM_FILE_TYPE_DUMP:
150 pldmDumpType = PLDM_FILE_TYPE_DUMP;
151 break;
152 case PLDM_FILE_TYPE_RESOURCE_DUMP:
153 pldmDumpType = PLDM_FILE_TYPE_RESOURCE_DUMP;
154 break;
155 default:
156 throw std::runtime_error("Unknown pldm dump file-io type to delete "
157 "host dump");
158 }
159 const size_t pldmMsgHdrSize = sizeof(pldm_msg_hdr);
160 std::array<uint8_t, pldmMsgHdrSize + PLDM_FILE_ACK_REQ_BYTES> fileAckReqMsg;
161
162 mctp_eid_t mctpEndPointId = readEID();
163
164 auto pldmInstanceId = getPLDMInstanceID(mctpEndPointId);
165
166 // - PLDM_SUCCESS - To indicate dump was readed (offloaded) or user decided,
167 // no longer host dump is not required so, initiate deletion from
168 // host memory
169 int retCode =
170 encode_file_ack_req(pldmInstanceId, pldmDumpType, dumpId, PLDM_SUCCESS,
171 reinterpret_cast<pldm_msg*>(fileAckReqMsg.data()));
172
173 if (retCode != PLDM_SUCCESS)
174 {
175 lg2::error(
176 "Failed to encode pldm FileAck to delete host dump, "
177 "SRC_DUMP_ID: {SRC_DUMP_ID}, PLDM_FILE_IO_TYPE: {PLDM_DUMP_TYPE}, "
178 "PLDM_RETURN_CODE: {RET_CODE}",
179 "SRC_DUMP_ID", dumpId, "PLDM_DUMP_TYPE", pldmDumpType, "RET_CODE",
180 retCode);
181 elog<NotAllowed>(Reason("Host dump deletion via pldm is not "
182 "allowed due to encode fileack failed"));
183 }
184
185 CustomFd pldmFd(openPLDM());
186
187 retCode = pldm_send(mctpEndPointId, pldmFd(), fileAckReqMsg.data(),
188 fileAckReqMsg.size());
189 if (retCode != PLDM_REQUESTER_SUCCESS)
190 {
191 auto errorNumber = errno;
192 lg2::error(
193 "Failed to send pldm FileAck to delete host dump, "
194 "SRC_DUMP_ID: {SRC_DUMP_ID}, PLDM_FILE_IO_TYPE: {PLDM_DUMP_TYPE}, "
195 "PLDM_RETURN_CODE: {RET_CODE}, ERRNO: {ERRNO}, ERRMSG: {ERRMSG}",
196 "SRC_DUMP_ID", dumpId, "PLDM_DUMP_TYPE",
197 static_cast<std::underlying_type<pldm_fileio_file_type>::type>(
198 pldmDumpType),
199 "RET_CODE", retCode, "ERRNO", errorNumber, "ERRMSG",
200 strerror(errorNumber));
201 elog<NotAllowed>(Reason("Host dump deletion via pldm is not "
202 "allowed due to fileack send failed"));
203 }
204
205 lg2::info(
206 "Sent request to host to delete the dump, SRC_DUMP_ID: {SRC_DUMP_ID}",
207 "SRC_DUMP_ID", dumpId);
208 }
209 } // namespace pldm
210 } // namespace dump
211 } // namespace phosphor
212