blob: 57d7a2c1e6dbf67513c0192595df7d9a6f31ce5f [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{
34namespace pldm
35{
36
37using namespace phosphor::logging;
38
39constexpr auto eidPath = "/usr/share/pldm/host_eid";
40constexpr mctp_eid_t defaultEIDValue = 9;
41
42using InternalFailure =
43 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
44
45void closeFD(int fd)
46{
47 if (fd >= 0)
48 {
49 close(fd);
50 }
51}
52
53mctp_eid_t readEID()
54{
55 mctp_eid_t eid = defaultEIDValue;
56
57 std::ifstream eidFile{eidPath};
58 if (!eidFile.good())
59 {
60 log<level::ERR>("Could not open host EID file");
61 elog<InternalFailure>();
62 }
63 else
64 {
65 std::string eid;
66 eidFile >> eid;
67 if (!eid.empty())
68 {
69 eid = strtol(eid.c_str(), nullptr, 10);
70 }
71 else
72 {
73 log<level::ERR>("EID file was empty");
74 elog<InternalFailure>();
75 }
76 }
77
78 return eid;
79}
80
81int open()
82{
83 auto fd = pldm_open();
84 if (fd < 0)
85 {
86 auto e = errno;
87 log<level::ERR>("pldm_open failed", entry("ERRNO=%d", e),
88 entry("FD=%d\n", fd));
89 elog<InternalFailure>();
90 }
91 return fd;
92}
93
94void requestOffload(uint32_t id)
95{
96 uint16_t effecterId = 0x05; // TODO PhyP temporary Hardcoded value.
97
98 std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(id) +
99 sizeof(uint8_t)>
100 requestMsg{};
101 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
102
103 std::array<uint8_t, sizeof(id)> effecterValue{};
104
105 memcpy(effecterValue.data(), &id, sizeof(id));
106
107 mctp_eid_t eid = readEID();
108
109 auto instanceID = getPLDMInstanceID(eid);
110
111 auto rc = encode_set_numeric_effecter_value_req(
112 instanceID, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
113 effecterValue.data(), request,
114 requestMsg.size() - sizeof(pldm_msg_hdr));
115
116 if (rc != PLDM_SUCCESS)
117 {
118 log<level::ERR>("Message encode failure. ", entry("RC=%d", rc));
119 elog<InternalFailure>();
120 }
121
122 uint8_t* responseMsg = nullptr;
123 size_t responseMsgSize{};
124
125 auto fd = open();
126
127 rc = pldm_send_recv(eid, fd, requestMsg.data(), requestMsg.size(),
128 &responseMsg, &responseMsgSize);
129 if (rc < 0)
130 {
131 closeFD(fd);
132 auto e = errno;
133 log<level::ERR>("pldm_send failed", entry("RC=%d", rc),
134 entry("ERRNO=%d", e));
135 elog<InternalFailure>();
136 }
137 pldm_msg* response = reinterpret_cast<pldm_msg*>(responseMsg);
138 log<level::INFO>(
139 "Done. PLDM message",
140 entry("RC=%d", static_cast<uint16_t>(response->payload[0])));
141
142 closeFD(fd);
143}
144
145uint8_t getPLDMInstanceID(uint8_t eid)
146{
147
148 constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
149 constexpr auto pldm = "/xyz/openbmc_project/pldm";
150
151 auto bus = sdbusplus::bus::new_default();
152 auto service = phosphor::dump::getService(bus, pldm, pldmRequester);
153
154 auto method = bus.new_method_call(service.c_str(), pldm, pldmRequester,
155 "GetInstanceId");
156 method.append(eid);
157 auto reply = bus.call(method);
158
159 uint8_t instanceID = 0;
160 reply.read(instanceID);
161
162 return instanceID;
163}
164} // namespace pldm
165} // namespace dump
166} // namespace phosphor