blob: 9f01782a3331843a08aa3c4e33e1ba6a7fd419ba [file] [log] [blame]
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +05301#pragma once
2
3#include <stdint.h>
4#include <unistd.h>
5
6#include <filesystem>
7
8#include "libpldm/base.h"
9#include "libpldm/file_io.h"
10
11namespace pldm
12{
13
14namespace responder
15{
16
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050017namespace oem_ibm
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053018{
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050019/** @brief Register handlers for command from the platform spec
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053020 */
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050021void registerHandlers();
22} // namespace oem_ibm
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053023
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050024using Response = std::vector<uint8_t>;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053025
26namespace dma
27{
28
29// The minimum data size of dma transfer in bytes
30constexpr uint32_t minSize = 16;
31
32// 16MB - 4096B (16773120 bytes) is the maximum data size of DMA transfer
33constexpr size_t maxSize = (16 * 1024 * 1024) - 4096;
34
35namespace fs = std::filesystem;
36
37/**
38 * @class DMA
39 *
40 * Expose API to initiate transfer of data by DMA
41 *
42 * This class only exposes the public API transferDataHost to transfer data
43 * between BMC and host using DMA. This allows for mocking the transferDataHost
44 * for unit testing purposes.
45 */
46class DMA
47{
48 public:
49 /** @brief API to transfer data between BMC and host using DMA
50 *
51 * @param[in] path - pathname of the file to transfer data from or to
52 * @param[in] offset - offset in the file
53 * @param[in] length - length of the data to transfer
54 * @param[in] address - DMA address on the host
55 * @param[in] upstream - indicates direction of the transfer; true indicates
56 * transfer to the host
57 *
58 * @return returns 0 on success, negative errno on failure
59 */
60 int transferDataHost(const fs::path& path, uint32_t offset, uint32_t length,
61 uint64_t address, bool upstream);
62};
63
64/** @brief Transfer the data between BMC and host using DMA.
65 *
66 * There is a max size for each DMA operation, transferAll API abstracts this
67 * and the requested length is broken down into multiple DMA operations if the
68 * length exceed max size.
69 *
70 * @tparam[in] T - DMA interface type
71 * @param[in] intf - interface passed to invoke DMA transfer
72 * @param[in] command - PLDM command
73 * @param[in] path - pathname of the file to transfer data from or to
74 * @param[in] offset - offset in the file
75 * @param[in] length - length of the data to transfer
76 * @param[in] address - DMA address on the host
77 * @param[in] upstream - indicates direction of the transfer; true indicates
78 * transfer to the host
79 * @return PLDM response message
80 */
81
82template <class DMAInterface>
83Response transferAll(DMAInterface* intf, uint8_t command, fs::path& path,
84 uint32_t offset, uint32_t length, uint64_t address,
85 bool upstream)
86{
87 uint32_t origLength = length;
88 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0);
89 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
90
91 while (length > dma::maxSize)
92 {
93 auto rc = intf->transferDataHost(path, offset, dma::maxSize, address,
94 upstream);
95 if (rc < 0)
96 {
97 encode_rw_file_memory_resp(0, command, PLDM_ERROR, 0, responsePtr);
98 return response;
99 }
100
101 offset += dma::maxSize;
102 length -= dma::maxSize;
103 address += dma::maxSize;
104 }
105
106 auto rc = intf->transferDataHost(path, offset, length, address, upstream);
107 if (rc < 0)
108 {
109 encode_rw_file_memory_resp(0, command, PLDM_ERROR, 0, responsePtr);
110 return response;
111 }
112
113 encode_rw_file_memory_resp(0, command, PLDM_SUCCESS, origLength,
114 responsePtr);
115 return response;
116}
117
118} // namespace dma
119
120/** @brief Handler for readFileIntoMemory command
121 *
122 * @param[in] request - pointer to PLDM request payload
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500123 * @param[in] payloadLength - length of the message
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530124 *
125 * @return PLDM response message
126 */
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500127Response readFileIntoMemory(const pldm_msg* request, size_t payloadLength);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530128
129/** @brief Handler for writeFileIntoMemory command
130 *
131 * @param[in] request - pointer to PLDM request payload
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500132 * @param[in] payloadLength - length of the message
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530133 *
134 * @return PLDM response message
135 */
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500136Response writeFileFromMemory(const pldm_msg* request, size_t payloadLength);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530137} // namespace responder
138} // namespace pldm