blob: dfff10346af5d24e0150eb89dab506041aa6b10a [file] [log] [blame]
Jayanth Othayothd31be2c2020-02-04 02:56:45 -06001/**
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_interface.hpp"
17
18#include "dump_utils.hpp"
19#include "xyz/openbmc_project/Common/error.hpp"
20
21#include <libpldm/base.h>
22#include <libpldm/platform.h>
23#include <unistd.h>
24
25#include <fstream>
26#include <phosphor-logging/elog-errors.hpp>
27#include <phosphor-logging/log.hpp>
28#include <sdbusplus/bus.hpp>
29
30namespace phosphor
31{
32namespace dump
33{
Dhruvaraj Subhashchandran59642e22020-03-19 03:37:44 -050034namespace host
35{
36/**
37 * @brief Initiate offload of the dump with provided id
38 *
39 * @param[in] id - The Dump Source ID.
40 *
41 */
42void requestOffload(uint32_t id)
43{
44 pldm::requestOffload(id);
45}
46} // namespace host
47
Jayanth Othayothd31be2c2020-02-04 02:56:45 -060048namespace pldm
49{
50
51using namespace phosphor::logging;
52
53constexpr auto eidPath = "/usr/share/pldm/host_eid";
54constexpr mctp_eid_t defaultEIDValue = 9;
55
56using InternalFailure =
57 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
58
59void closeFD(int fd)
60{
61 if (fd >= 0)
62 {
63 close(fd);
64 }
65}
66
67mctp_eid_t readEID()
68{
69 mctp_eid_t eid = defaultEIDValue;
70
71 std::ifstream eidFile{eidPath};
72 if (!eidFile.good())
73 {
74 log<level::ERR>("Could not open host EID file");
75 elog<InternalFailure>();
76 }
77 else
78 {
79 std::string eid;
80 eidFile >> eid;
81 if (!eid.empty())
82 {
83 eid = strtol(eid.c_str(), nullptr, 10);
84 }
85 else
86 {
87 log<level::ERR>("EID file was empty");
88 elog<InternalFailure>();
89 }
90 }
91
92 return eid;
93}
94
95int open()
96{
97 auto fd = pldm_open();
98 if (fd < 0)
99 {
100 auto e = errno;
101 log<level::ERR>("pldm_open failed", entry("ERRNO=%d", e),
102 entry("FD=%d\n", fd));
103 elog<InternalFailure>();
104 }
105 return fd;
106}
107
108void requestOffload(uint32_t id)
109{
110 uint16_t effecterId = 0x05; // TODO PhyP temporary Hardcoded value.
111
112 std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(id) +
113 sizeof(uint8_t)>
114 requestMsg{};
115 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
116
117 std::array<uint8_t, sizeof(id)> effecterValue{};
118
119 memcpy(effecterValue.data(), &id, sizeof(id));
120
121 mctp_eid_t eid = readEID();
122
123 auto instanceID = getPLDMInstanceID(eid);
124
125 auto rc = encode_set_numeric_effecter_value_req(
126 instanceID, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
127 effecterValue.data(), request,
128 requestMsg.size() - sizeof(pldm_msg_hdr));
129
130 if (rc != PLDM_SUCCESS)
131 {
132 log<level::ERR>("Message encode failure. ", entry("RC=%d", rc));
133 elog<InternalFailure>();
134 }
135
136 uint8_t* responseMsg = nullptr;
137 size_t responseMsgSize{};
138
139 auto fd = open();
140
141 rc = pldm_send_recv(eid, fd, requestMsg.data(), requestMsg.size(),
142 &responseMsg, &responseMsgSize);
143 if (rc < 0)
144 {
145 closeFD(fd);
146 auto e = errno;
147 log<level::ERR>("pldm_send failed", entry("RC=%d", rc),
148 entry("ERRNO=%d", e));
149 elog<InternalFailure>();
150 }
151 pldm_msg* response = reinterpret_cast<pldm_msg*>(responseMsg);
152 log<level::INFO>(
153 "Done. PLDM message",
154 entry("RC=%d", static_cast<uint16_t>(response->payload[0])));
155
156 closeFD(fd);
157}
158
159uint8_t getPLDMInstanceID(uint8_t eid)
160{
161
162 constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
163 constexpr auto pldm = "/xyz/openbmc_project/pldm";
164
165 auto bus = sdbusplus::bus::new_default();
166 auto service = phosphor::dump::getService(bus, pldm, pldmRequester);
167
168 auto method = bus.new_method_call(service.c_str(), pldm, pldmRequester,
169 "GetInstanceId");
170 method.append(eid);
171 auto reply = bus.call(method);
172
173 uint8_t instanceID = 0;
174 reply.read(instanceID);
175
176 return instanceID;
177}
178} // namespace pldm
179} // namespace dump
180} // namespace phosphor