xref: /openbmc/libpldm/include/libpldm/base.h (revision 96e2048575e4f9b8708d5a0d12f1bf034655726f)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #ifndef BASE_H
3 #define BASE_H
4 
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8 
9 #include <libpldm/compiler.h>
10 #include <libpldm/pldm_types.h>
11 #include <libpldm/utils.h>
12 
13 #include <asm/byteorder.h>
14 #include <stdalign.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <stdint.h>
18 
19 typedef uint8_t pldm_tid_t;
20 
21 /** @brief PLDM Types
22  */
23 enum pldm_supported_types {
24 	PLDM_BASE = 0x00,
25 	PLDM_SMBIOS = 0x01,
26 	PLDM_PLATFORM = 0x02,
27 	PLDM_BIOS = 0x03,
28 	PLDM_FRU = 0x04,
29 	PLDM_FWUP = 0x05,
30 	PLDM_RDE = 0x06,
31 	PLDM_FILE = 0x07,
32 	PLDM_OEM = 0x3f,
33 };
34 
35 /** @brief PLDM Commands
36  */
37 enum pldm_supported_commands {
38 	PLDM_SET_TID = 0x1,
39 	PLDM_GET_TID = 0x2,
40 	PLDM_GET_PLDM_VERSION = 0x3,
41 	PLDM_GET_PLDM_TYPES = 0x4,
42 	PLDM_GET_PLDM_COMMANDS = 0x5,
43 	PLDM_SELECT_PLDM_VERSION = 0x6,
44 	PLDM_NEGOTIATE_TRANSFER_PARAMETERS = 0x7,
45 	PLDM_MULTIPART_SEND = 0x8,
46 	PLDM_MULTIPART_RECEIVE = 0x9,
47 	PLDM_GET_MULTIPART_TRANSFER_SUPPORT = 0xa,
48 };
49 
50 /** @brief PLDM base codes
51  */
52 enum pldm_completion_codes {
53 	PLDM_SUCCESS = 0x00,
54 	PLDM_ERROR = 0x01,
55 	PLDM_ERROR_INVALID_DATA = 0x02,
56 	PLDM_ERROR_INVALID_LENGTH = 0x03,
57 	PLDM_ERROR_NOT_READY = 0x04,
58 	PLDM_ERROR_UNSUPPORTED_PLDM_CMD = 0x05,
59 	PLDM_ERROR_INVALID_PLDM_TYPE = 0x20,
60 	PLDM_ERROR_INVALID_TRANSFER_CONTEXT = 0x21,
61 	PLDM_ERROR_INVALID_DATA_TRANSFER_HANDLE = 0x22,
62 	PLDM_ERROR_UNEXPECTED_TRANSFER_FLAG_OPERATION = 0x23,
63 	PLDM_ERROR_INVALID_REQUESTED_SECTION_OFFSET = 0x24,
64 
65 	PLDM_GET_PLDM_VERSION_INVALID_DATA_TRANSFER_HANDLE = 0x80,
66 	PLDM_GET_PLDM_VERSION_INVALID_TRANSFER_OPERATION_FLAG = 0x81,
67 	PLDM_GET_PLDM_VERSION_INVALID_PLDM_TYPE_IN_REQUEST_DATA = 0x83,
68 
69 	PLDM_GET_PLDM_COMMANDS_INVALID_PLDM_TYPE_IN_REQUEST_DATA = 0x83,
70 	PLDM_GET_PLDM_COMMANDS_INVALID_PLDM_VERSION_IN_REQUEST_DATA = 0x84,
71 
72 	PLDM_SELECT_PLDM_VERSION_INVALID_PLDM_TYPE_IN_REQUEST_DATA = 0x83,
73 	PLDM_SELECT_PLDM_VERSION_INVALID_PLDM_VERSION_IN_REQUEST_DATA = 0x84,
74 
75 	PLDM_MULTIPART_SEND_NEGOTIATION_INCOMPLETE = 0x83,
76 	PLDM_MULTIPART_RECEIVE_NEGOTIATION_INCOMPLETE = 0x83,
77 
78 	PLDM_GET_MULTIPART_TRANSFER_SUPPORT_INVALID_PLDM_TYPE_IN_REQUEST_DATA =
79 		0x83,
80 	PLDM_GET_MULTIPART_TRANSFER_SUPPORT_INVALID_PLDM_VERSION_IN_REQUEST_DATA =
81 		0x84,
82 };
83 
84 enum transfer_op_flag {
85 	PLDM_GET_NEXTPART = 0,
86 	PLDM_GET_FIRSTPART = 1,
87 	PLDM_ACKNOWLEDGEMENT_ONLY = 2,
88 };
89 
90 enum transfer_multipart_op_flag {
91 	PLDM_XFER_FIRST_PART = 0,
92 	PLDM_XFER_NEXT_PART = 1,
93 	PLDM_XFER_ABORT = 2,
94 	PLDM_XFER_COMPLETE = 3,
95 	PLDM_XFER_CURRENT_PART = 4,
96 };
97 
98 enum pldm_base_multipart_receive_transfer_flag {
99 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_START = 0x01,
100 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_MIDDLE = 0x02,
101 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_END = 0x04,
102 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_START_AND_END = 0x05,
103 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_ACK_COMPLETION = 0x08,
104 };
105 
106 enum transfer_resp_flag {
107 	PLDM_START = 0x01,
108 	PLDM_MIDDLE = 0x02,
109 	PLDM_END = 0x04,
110 	PLDM_START_AND_END = 0x05,
111 	PLDM_ACKNOWLEDGE_COMPLETION = 0x08,
112 };
113 
114 /** @brief PLDM transport protocol type
115  */
116 enum pldm_transport_protocol_type {
117 	PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP = 0x00,
118 	PLDM_TRANSPORT_PROTOCOL_TYPE_OEM = 0xff,
119 };
120 
121 /** @enum MessageType
122  *
123  *  The different message types supported by the PLDM specification.
124  */
125 typedef enum {
126 	PLDM_RESPONSE,		   //!< PLDM response
127 	PLDM_REQUEST,		   //!< PLDM request
128 	PLDM_RESERVED,		   //!< Reserved
129 	PLDM_ASYNC_REQUEST_NOTIFY, //!< Unacknowledged PLDM request messages
130 } MessageType;
131 
132 #define PLDM_INSTANCE_MAX      31
133 #define PLDM_MAX_TYPES	       64
134 #define PLDM_MAX_CMDS_PER_TYPE 256
135 #define PLDM_MAX_TIDS	       256
136 #define PLDM_TID_UNASSIGNED    0x00
137 #define PLDM_TID_RESERVED      0xff
138 
139 /* Message payload lengths */
140 #define PLDM_GET_COMMANDS_REQ_BYTES 5
141 #define PLDM_GET_VERSION_REQ_BYTES  6
142 
143 /* Response lengths are inclusive of completion code */
144 #define PLDM_GET_TYPES_REQ_BYTES     0
145 #define PLDM_GET_TYPES_RESP_BYTES    9
146 #define PLDM_GET_TID_REQ_BYTES	     0
147 #define PLDM_GET_TID_RESP_BYTES	     2
148 #define PLDM_SET_TID_REQ_BYTES	     1
149 #define PLDM_SET_TID_RESP_BYTES	     1
150 #define PLDM_GET_COMMANDS_RESP_BYTES 33
151 /* Response data has only one version and does not contain the checksum */
152 #define PLDM_GET_VERSION_RESP_BYTES		   10
153 #define PLDM_MULTIPART_RECEIVE_REQ_BYTES	   18
154 #define PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES 10
155 
156 #define PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES  10
157 #define PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES 11
158 
159 #define PLDM_VERSION_0	     0
160 #define PLDM_CURRENT_VERSION PLDM_VERSION_0
161 
162 #define PLDM_TIMESTAMP104_SIZE 13
163 
164 /** @brief Minimum length of response for a optional PLDM command
165  *
166  *  For a optional PLDM command, the command handler might not be
167  *  implemented in a device's firmware, a response contains only CC
168  *  might come in, such as ERROR_UNSUPPORTED_PLDM_CMD.
169  *
170  *  The description can be found in DSP0240:
171  *  > For an unsupported PLDM command, the ERROR_UNSUPPORTED_PLDM_CMD
172  *  > completion code shall be returned unless the responder is in a
173  *  > transient state (not ready), in which it cannot process the PLDM
174  *  > command. If the responder is in a transient state, it may return
175  *  > the ERROR_NOT_READY completion code.
176  */
177 #define PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN 1
178 
179 /** @struct pldm_msg_hdr
180  *
181  * Structure representing PLDM message header fields
182  */
183 struct pldm_msg_hdr {
184 #if defined(__LITTLE_ENDIAN_BITFIELD)
185 	uint8_t instance_id : 5; //!< Instance ID
186 	uint8_t reserved : 1;	 //!< Reserved
187 	uint8_t datagram : 1;	 //!< Datagram bit
188 	uint8_t request : 1;	 //!< Request bit
189 #elif defined(__BIG_ENDIAN_BITFIELD)
190 	uint8_t request : 1;	 //!< Request bit
191 	uint8_t datagram : 1;	 //!< Datagram bit
192 	uint8_t reserved : 1;	 //!< Reserved
193 	uint8_t instance_id : 5; //!< Instance ID
194 #endif
195 
196 #if defined(__LITTLE_ENDIAN_BITFIELD)
197 	uint8_t type : 6;	//!< PLDM type
198 	uint8_t header_ver : 2; //!< Header version
199 #elif defined(__BIG_ENDIAN_BITFIELD)
200 	uint8_t header_ver : 2; //!< Header version
201 	uint8_t type : 6;	//!< PLDM type
202 #endif
203 	uint8_t command; //!< PLDM command code
204 } __attribute__((packed));
205 
206 // Macros for byte-swapping variables in-place
207 #define HTOLE32(X) ((X) = htole32(X))
208 #define HTOLE16(X) ((X) = htole16(X))
209 #define LE32TOH(X) ((X) = le32toh(X))
210 #define LE16TOH(X) ((X) = le16toh(X))
211 
212 /** @struct pldm_msg
213  *
214  * Structure representing PLDM message
215  */
216 struct pldm_msg {
217 	struct pldm_msg_hdr hdr; //!< PLDM message header
218 	uint8_t payload[1]; //!< &payload[0] is the beginning of the payload
219 } __attribute__((packed));
220 
221 /** @brief Determine the underlying object size for a @struct pldm_msg
222  *
223  * @pre @p size must be a constant expression
224  *
225  * @note Providing an expression for @p size that is not an integer constant
226  *       expression will force a compilation failure.
227  *
228  * @param size The desired size of the @struct pldm_msg payload
229  */
230 #define PLDM_MSG_SIZE(size)                                                    \
231 	(sizeof(char[(__builtin_constant_p(size)) ? 1 : -1])) *                \
232 		(sizeof(struct pldm_msg) -                                     \
233 		 sizeof(((struct pldm_msg *)NULL)->payload) + (size))
234 
235 /** @brief Stack-allocate a buffer to hold a @struct pldm_msg
236  *
237  * Allocate an appropriately aligned array named @p name of type unsigned char
238  * with the necessary length to hold a payload of the requested size.
239  *
240  * @param name - The variable name used to define the buffer
241  * @param size - The desired payload length for the intended @struct pldm_msg
242  */
243 #define PLDM_MSG_BUFFER(name, size)                                            \
244 	alignas(struct pldm_msg) unsigned char(name)[PLDM_MSG_SIZE(size)]
245 
246 /** @brief Create a pointer to a stack-allocated @struct pldm_msg
247  *
248  * Define a pointer named @p name of type @struct pldm_msg to an object on the
249  * stack of appropriate alignment and length to hold a @struct pldm_msg with a
250  * payload of @p size.
251  *
252  * @param name - The variable name for pointer
253  * @param size - The desired payload length for the underlying @struct pldm_msg
254  *        buffer
255  */
256 #ifdef __cplusplus
257 #define PLDM_MSG_DEFINE_P(name, size)                                          \
258 	PLDM_MSG_BUFFER(name##_buf, size);                                     \
259 	auto *(name) = new (name##_buf) pldm_msg()
260 #endif
261 
262 /**
263  * @brief Compare the headers from two PLDM messages to determine if the latter
264  * is a message representing a response to the former, where the former must be
265  * a request.
266  *
267  * @param[in] req - A pointer to a PLDM header object, which must represent a
268  *                  request
269  * @param[in] resp - A pointer to a PLDM header object, which may represent a
270  *		     response to the provided request.
271  *
272  * @return true if the header pointed to by resp represents a message that is a
273  *	   response to the header pointed to by req, otherwise false.
274  */
275 bool pldm_msg_hdr_correlate_response(const struct pldm_msg_hdr *req,
276 				     const struct pldm_msg_hdr *resp);
277 
278 /** @brief Convert ver32_t to string
279  *  @param[in] version - Pointer to ver32_t
280  *  @param[out] buffer - Pointer to the buffer
281  *  @param[in] buffer_size - Size of the buffer, up to SSIZE_MAX
282  *  @return The number of characters written to the buffer (excluding the null
283  * byte). The converted string may be truncated, and truncation is not
284  * considered an error. The result is negative if invalid arguments are supplied
285  * (NULL values for required pointers or the buffer size is beyond a
286  *  representable range).
287  */
288 ssize_t pldm_base_ver2str(const ver32_t *version, char *buffer,
289 			  size_t buffer_size);
290 
291 /** @struct pldm_header_info
292  *
293  *  The information needed to prepare PLDM header and this is passed to the
294  *  pack_pldm_header and unpack_pldm_header API.
295  */
296 struct pldm_header_info {
297 	MessageType msg_type;	 //!< PLDM message type
298 	uint8_t instance;	 //!< PLDM instance id
299 	uint8_t pldm_type;	 //!< PLDM type
300 	uint8_t command;	 //!< PLDM command code
301 	uint8_t completion_code; //!< PLDM completion code, applies for response
302 };
303 
304 /** @struct pldm_get_types_resp
305  *
306  *  Structure representing PLDM get types response.
307  */
308 struct pldm_get_types_resp {
309 	uint8_t completion_code; //!< completion code
310 	bitfield8_t types[8]; //!< each bit represents whether a given PLDM Type
311 			      //!< is supported
312 } __attribute__((packed));
313 
314 /** @struct pldm_get_commands_req
315  *
316  *  Structure representing PLDM get commands request.
317  */
318 struct pldm_get_commands_req {
319 	uint8_t type;	 //!< PLDM Type for which command support information is
320 			 //!< being requested
321 	ver32_t version; //!< version for the specified PLDM Type
322 } __attribute__((packed));
323 
324 /** @struct pldm_get_commands_resp
325  *
326  *  Structure representing PLDM get commands response.
327  */
328 struct pldm_get_commands_resp {
329 	uint8_t completion_code;  //!< completion code
330 	bitfield8_t commands[32]; //!< each bit represents whether a given PLDM
331 				  //!< command is supported
332 } __attribute__((packed));
333 
334 /** @struct pldm_get_version_req
335  *
336  *  Structure representing PLDM get version request.
337  */
338 struct pldm_get_version_req {
339 	uint32_t transfer_handle; //!< handle to identify PLDM version data transfer
340 	uint8_t transfer_opflag; //!< PLDM GetVersion operation flag
341 	uint8_t type; //!< PLDM Type for which version information is being requested
342 } __attribute__((packed));
343 
344 /** @struct pldm_get_version_resp
345  *
346  *  Structure representing PLDM get version response.
347  */
348 
349 struct pldm_get_version_resp {
350 	uint8_t completion_code;       //!< completion code
351 	uint32_t next_transfer_handle; //!< next portion of PLDM version data
352 				       //!< transfer
353 	uint8_t transfer_flag;	       //!< PLDM GetVersion transfer flag
354 	uint8_t version_data[1];       //!< PLDM GetVersion version field
355 } __attribute__((packed));
356 
357 /** @struct pldm_set_tid_req
358  *
359  *  Structure representing PLDM set tid request.
360  */
361 
362 struct pldm_set_tid_req {
363 	uint8_t tid; //!< PLDM SetTID TID field
364 } __attribute__((packed));
365 
366 /** @struct pldm_get_tid_resp
367  *
368  *  Structure representing PLDM get tid response.
369  */
370 
371 struct pldm_get_tid_resp {
372 	uint8_t completion_code; //!< completion code
373 	uint8_t tid;		 //!< PLDM GetTID TID field
374 } __attribute__((packed));
375 
376 /** @struct pldm_base_multipart_receive_req
377  *
378  * Structure representing PLDM multipart receive request.
379  */
380 struct pldm_base_multipart_receive_req {
381 	uint8_t pldm_type;	  //!< PLDM Type for the MultipartReceive
382 				  //!< command.
383 	uint8_t transfer_opflag;  //!< PLDM MultipartReceive operation flag.
384 	uint32_t transfer_ctx;	  //!< Protocol-specifc context for this
385 				  //!< transfer.
386 	uint32_t transfer_handle; //!< handle to identify the part of data to be
387 				  //!< received.
388 	uint32_t section_offset;  //!< The start offset for the requested
389 				  //!< section.
390 	uint32_t section_length;  //!< The length (in bytes) of the section
391 				  //!< requested.
392 };
393 
394 /** @struct pldm_base_multipart_receive_resp
395  *
396  * Structure representing PLDM multipart receive request.
397  */
398 struct pldm_base_multipart_receive_resp {
399 	uint8_t completion_code;       //!< Completion code of the command.
400 	uint8_t transfer_flag;	       //!< PLDM MultipartReceive transfer flag.
401 	uint32_t next_transfer_handle; //!< The handle for the next part of
402 				       //!< data for this section transfer.
403 	struct variable_field data;
404 };
405 
406 /** @struct pldm_base_negotiate_transfer_params_req
407  *
408  * Structure representing PLDM Negotiate Transfer Parameters request
409  */
410 struct pldm_base_negotiate_transfer_params_req {
411 	uint16_t requester_part_size;
412 	bitfield8_t requester_protocol_support[8];
413 };
414 
415 /** @struct pldm_base_negotiate_transfer_params_resp
416  *
417  * Structure representing PLDM Negotiate Transfer Parameters response
418  */
419 struct pldm_base_negotiate_transfer_params_resp {
420 	uint8_t completion_code;
421 	uint16_t responder_part_size;
422 	bitfield8_t responder_protocol_support[8];
423 };
424 
425 /**
426  * @brief Populate the PLDM message with the PLDM header.The caller of this API
427  *        allocates buffer for the PLDM header when forming the PLDM message.
428  *        The buffer is passed to this API to pack the PLDM header.
429  *
430  * @param[in] hdr - Pointer to the PLDM header information
431  * @param[out] msg - Pointer to PLDM message header
432  *
433  * @return 0 on success, otherwise PLDM error codes.
434  * @note   Caller is responsible for alloc and dealloc of msg
435  *         and hdr params
436  */
437 uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
438 			 struct pldm_msg_hdr *msg);
439 
440 /**
441  * @brief Unpack the PLDM header from the PLDM message.
442  *
443  * @param[in] msg - Pointer to the PLDM message header
444  * @param[out] hdr - Pointer to the PLDM header information
445  *
446  * @return 0 on success, otherwise PLDM error codes.
447  * @note   Caller is responsible for alloc and dealloc of msg
448  *         and hdr params
449  */
450 uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg,
451 			   struct pldm_header_info *hdr);
452 
453 /* Requester */
454 
455 /* GetPLDMTypes */
456 
457 /** @brief Create a PLDM request message for GetPLDMTypes
458  *
459  *  @param[in] instance_id - Message's instance id
460  *  @param[in,out] msg - Message will be written to this
461  *  @return pldm_completion_codes
462  *  @note  Caller is responsible for memory alloc and dealloc of param
463  *         'msg.payload'
464  */
465 int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg);
466 
467 /** @brief Decode a GetPLDMTypes response message
468  *
469  *  Note:
470  *  * If the return value is not PLDM_SUCCESS, it represents a
471  * transport layer error.
472  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
473  * protocol layer error and all the out-parameters are invalid.
474  *
475  *  @param[in] msg - Response message
476  *  @param[in] payload_length - Length of response message payload
477  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
478  *  @param[out] types - pointer to array bitfield8_t[8] containing supported
479  *              types (MAX_TYPES/8) = 8), as per DSP0240
480  *  @return pldm_completion_codes
481  */
482 int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
483 			  uint8_t *completion_code, bitfield8_t *types);
484 
485 /* GetPLDMCommands */
486 
487 /** @brief Create a PLDM request message for GetPLDMCommands
488  *
489  *  @param[in] instance_id - Message's instance id
490  *  @param[in] type - PLDM Type
491  *  @param[in] version - Version for PLDM Type
492  *  @param[in,out] msg - Message will be written to this
493  *  @return pldm_completion_codes
494  *  @note  Caller is responsible for memory alloc and dealloc of param
495  *         'msg.payload'
496  */
497 int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
498 			    struct pldm_msg *msg);
499 
500 /** @brief Decode a GetPLDMCommands response message
501  *
502  *  Note:
503  *  * If the return value is not PLDM_SUCCESS, it represents a
504  * transport layer error.
505  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
506  * protocol layer error and all the out-parameters are invalid.
507  *
508  *  @param[in] msg - Response message
509  *  @param[in] payload_length - Length of response message payload
510  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
511  *  @param[in] commands - pointer to array bitfield8_t[32] containing supported
512  *             commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
513  *  @return pldm_completion_codes
514  */
515 int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
516 			     uint8_t *completion_code, bitfield8_t *commands);
517 
518 /* GetPLDMVersion */
519 
520 /** @brief Create a PLDM request for GetPLDMVersion
521  *
522  *  @param[in] instance_id - Message's instance id
523  *  @param[in] transfer_handle - Handle to identify PLDM version data transfer.
524  *         This handle is ignored by the responder when the
525  *         transferop_flag is set to getFirstPart.
526  *  @param[in] transfer_opflag - flag to indicate whether it is start of
527  *         transfer
528  *  @param[in] type -  PLDM Type for which version is requested
529  *  @param[in,out] msg - Message will be written to this
530  *  @return pldm_completion_codes
531  *  @note  Caller is responsible for memory alloc and dealloc of param
532  *         'msg.payload'
533  */
534 int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
535 			   uint8_t transfer_opflag, uint8_t type,
536 			   struct pldm_msg *msg);
537 
538 /** @brief Decode a GetPLDMVersion response message
539  *
540  *  Note:
541  *  * If the return value is not PLDM_SUCCESS, it represents a
542  * transport layer error.
543  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
544  * protocol layer error and all the out-parameters are invalid.
545  *
546  *  @param[in] msg - Response message
547  *  @param[in] payload_length - Length of response message payload
548  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
549  *  @param[out] next_transfer_handle - the next handle for the next part of data
550  *  @param[out] transfer_flag - flag to indicate the part of data
551  *  @return pldm_completion_codes
552  */
553 int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
554 			    uint8_t *completion_code,
555 			    uint32_t *next_transfer_handle,
556 			    uint8_t *transfer_flag, ver32_t *version);
557 
558 /* GetTID */
559 
560 /** @brief Decode a GetTID response message
561  *
562  *  Note:
563  *  * If the return value is not PLDM_SUCCESS, it represents a
564  * transport layer error.
565  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
566  * protocol layer error and all the out-parameters are invalid.
567  *
568  *  @param[in] msg - Response message
569  *  @param[in] payload_length - Length of response message payload
570  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
571  *  @param[out] tid - Pointer to the terminus id
572  *  @return pldm_completion_codes
573  */
574 int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
575 			uint8_t *completion_code, uint8_t *tid);
576 
577 /* Responder */
578 
579 /* GetPLDMTypes */
580 
581 /** @brief Create a PLDM response message for GetPLDMTypes
582  *
583  *  @param[in] instance_id - Message's instance id
584  *  @param[in] completion_code - PLDM completion code
585  *  @param[in] types - pointer to array bitfield8_t[8] containing supported
586  *             types (MAX_TYPES/8) = 8), as per DSP0240
587  *  @param[in,out] msg - Message will be written to this
588  *  @return pldm_completion_codes
589  *  @note  Caller is responsible for memory alloc and dealloc of param
590  *         'msg.payload'
591  */
592 int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
593 			  const bitfield8_t *types, struct pldm_msg *msg);
594 
595 /* GetPLDMCommands */
596 
597 /** @brief Decode GetPLDMCommands' request data
598  *
599  *  @param[in] msg - Request message
600  *  @param[in] payload_length - Length of request message payload
601  *  @param[out] type - PLDM Type
602  *  @param[out] version - Version for PLDM Type
603  *  @return pldm_completion_codes
604  */
605 int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
606 			    uint8_t *type, ver32_t *version);
607 
608 /** @brief Create a PLDM response message for GetPLDMCommands
609  *
610  *  @param[in] instance_id - Message's instance id
611  *  @param[in] completion_code - PLDM completion code
612  *  @param[in] commands - pointer to array bitfield8_t[32] containing supported
613  *             commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
614  *  @param[in,out] msg - Message will be written to this
615  *  @return pldm_completion_codes
616  *  @note  Caller is responsible for memory alloc and dealloc of param
617  *         'msg.payload'
618  */
619 int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
620 			     const bitfield8_t *commands, struct pldm_msg *msg);
621 
622 /* GetPLDMVersion */
623 
624 /** @brief Create a PLDM response for GetPLDMVersion
625  *
626  *  @param[in] instance_id - Message's instance id
627  *  @param[in] completion_code - PLDM completion code
628  *  @param[in] next_transfer_handle - Handle to identify next portion of
629  *              data transfer
630  *  @param[in] transfer_flag - Represents the part of transfer
631  *  @param[in] version_data - the version data
632  *  @param[in] version_size - size of version data
633  *  @param[in,out] msg - Message will be written to this
634  *  @return pldm_completion_codes
635  *  @note  Caller is responsible for memory alloc and dealloc of param
636  *         'msg.payload'
637  */
638 int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
639 			    uint32_t next_transfer_handle,
640 			    uint8_t transfer_flag, const ver32_t *version_data,
641 			    size_t version_size, struct pldm_msg *msg);
642 
643 /** @brief Decode a GetPLDMVersion request message
644  *
645  *  @param[in] msg - Request message
646  *  @param[in] payload_length - length of request message payload
647  *  @param[out] transfer_handle - the handle of data
648  *  @param[out] transfer_opflag - Transfer Flag
649  *  @param[out] type - PLDM type for which version is requested
650  *  @return pldm_completion_codes
651  */
652 int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
653 			   uint32_t *transfer_handle, uint8_t *transfer_opflag,
654 			   uint8_t *type);
655 
656 /* Requester */
657 
658 /* GetTID */
659 
660 /** @brief Create a PLDM request message for GetTID
661  *
662  *  @param[in] instance_id - Message's instance id
663  *  @param[in,out] msg - Message will be written to this
664  *  @return pldm_completion_codes
665  *  @note  Caller is responsible for memory alloc and dealloc of param
666  *         'msg.payload'
667  */
668 int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg);
669 
670 /** @brief Create a PLDM response message for GetTID
671  *
672  *  @param[in] instance_id - Message's instance id
673  *  @param[in] completion_code - PLDM completion code
674  *  @param[in] tid - Terminus ID
675  *  @param[in,out] msg - Message will be written to this
676  *  @return pldm_completion_codes
677  *  @note  Caller is responsible for memory alloc and dealloc of param
678  *         'msg.payload'
679  */
680 int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
681 			uint8_t tid, struct pldm_msg *msg);
682 
683 /** @brief Create a PLDM request message for SetTID
684  *
685  *  @param[in] instance_id - Message's instance id
686  *  @param[in] tid - Terminus ID
687  *  @param[in,out] msg - Message will be written to this
688  *  @return pldm_completion_codes
689  *  @note  Caller is responsible for memory alloc and dealloc of param
690  *         'msg.payload'
691  */
692 int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg);
693 
694 /** @brief Decode a SetTID request message
695  *
696  *  @param[in] msg - Request message
697  *  @param[in] payload_length - length of request message payload
698  *  @param[out] tid - Terminus ID
699  *  @return 0 on success
700  *         -EINVAL if the input parameters' memory are not allocated,
701  *         or tid is invalid
702  *         -EOVERFLOW if the input message length is invalid
703  */
704 int decode_set_tid_req(const struct pldm_msg *msg, size_t payload_length,
705 		       uint8_t *tid);
706 
707 /* Responder */
708 
709 /* MultipartRecieve */
710 
711 /** @brief Decode a PLDM MultipartReceive request message
712  *
713  *  @param[in] msg - Request message
714  *  @param[in] payload_length - length of request message payload
715  *  @param[out] pldm_type - PLDM type for which version is requested
716  *  @param[out] transfer_opflag - Transfer Flag
717  *  @param[out] transfer_ctx - The context of the packet
718  *  @param[out] transfer_handle - The handle of data
719  *  @param[out] section_offset - The start of the requested section
720  *  @param[out] section_length - The length of the requested section
721  *  @return pldm_completion_codes
722  */
723 int decode_multipart_receive_req(const struct pldm_msg *msg,
724 				 size_t payload_length, uint8_t *pldm_type,
725 				 uint8_t *transfer_opflag,
726 				 uint32_t *transfer_ctx,
727 				 uint32_t *transfer_handle,
728 				 uint32_t *section_offset,
729 				 uint32_t *section_length);
730 
731 /** @brief Encode a PLDM MultipartReceive request message
732  *
733  *  @param[in] instance_id - Message's instance id
734  *  @param[in] req - The pointer to the request message to be encoded
735  *  @param[in,out] msg - Message will be written to this
736  *  @param[in, out] payload_length - length of request message payload
737  *  @return 0 on success
738  *          -EINVAL if the input parameters' memory are not allocated,
739  *          or message type or instance in request header is invalid
740  *          -ENOMSG if the PLDM type in the request header is invalid
741  *          -EOVERFLOW if the input message length is invalid
742  */
743 int encode_pldm_base_multipart_receive_req(
744 	uint8_t instance_id, const struct pldm_base_multipart_receive_req *req,
745 	struct pldm_msg *msg, size_t *payload_length);
746 
747 /** @brief Decode a PLDM MultipartReceive response message
748  *
749  *  @param[in] msg - Response message
750  *  @param[in] payload_length - length of request message payload
751  *  @param[out] resp - pointer to the decoded response message,
752  *         excluding the data integrity checksum
753  *  @param[out] data_integrity_checksum - The checksum of data field
754  *         of the decoded response message
755  *  @return 0 on success
756  *          -EINVAL if the input parameters' memory are not allocated
757  *          -EOVERFLOW if the input message buffer is too short for the output
758  *          response struct
759  *          -EBADMSG if the input message buffer is too large for the output
760  *          response struct
761  *  @note  Caller is responsible for memory alloc and dealloc of param
762  *         'msg.payload'
763  */
764 int decode_pldm_base_multipart_receive_resp(
765 	const struct pldm_msg *msg, size_t payload_length,
766 	struct pldm_base_multipart_receive_resp *resp,
767 	uint32_t *data_integrity_checksum);
768 
769 /** @brief Encode a PLDM MultipartReceive response message
770  *
771  *  @param[in] instance_id - Message's instance id
772  *  @param[in] resp - The pointer to the response message to be encoded
773  *  @param[in] checksum - Checksum of the entirely data payload
774  *  @param[in,out] msg - Message will be written to this
775  *  @param[in,out] payload_length - length of request message payload
776  *  @return 0 on success
777  *          -EINVAL if argument values are invalid for the invocation
778  *          -ENOMSG if the PLDM type in the request header is invalid
779  *          -EOVERFLOW if the input message length is invalid
780  *  @note  Caller is responsible for memory alloc and dealloc of param
781  *         'msg.payload'
782  */
783 int encode_base_multipart_receive_resp(
784 	uint8_t instance_id,
785 	const struct pldm_base_multipart_receive_resp *resp, uint32_t checksum,
786 	struct pldm_msg *msg, size_t *payload_length);
787 
788 /** @brief Create a PLDM response message containing only cc
789  *
790  *  @param[in] instance_id - Message's instance id
791  *  @param[in] type - PLDM Type
792  *  @param[in] command - PLDM Command
793  *  @param[in] cc - PLDM Completion Code
794  *  @param[out] msg - Message will be written to this
795  *  @return pldm_completion_codes
796  */
797 int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
798 			uint8_t cc, struct pldm_msg *msg);
799 
800 /** @brief Create a PLDM message only with the header
801  *
802  *	@param[in] msg_type - PLDM message type
803  *	@param[in] instance_id - Message's instance id
804  *	@param[in] pldm_type - PLDM Type
805  *	@param[in] command - PLDM Command
806  *	@param[out] msg - Message will be written to this
807  *
808  *	@return pldm_completion_codes
809  */
810 int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
811 			    uint8_t pldm_type, uint8_t command,
812 			    struct pldm_msg *msg);
813 
814 /** @brief Encode a PLDM Negotiate Transfer Parameters request message
815  *
816  *  @param[in] instance_id - Message's instance id
817  *  @param[in] req - The pointer to the request message to be encoded
818  *  @param[in,out] msg - Message will be written to this
819  *  @param[in, out] payload_length - length of request message payload
820  *  @return 0 on success
821  *          -EINVAL if the input parameters' memory are not allocated,
822  *          or message type or instance in request header is invalid
823  *          -ENOMSG if the PLDM type in the request header is invalid
824  *          -EOVERFLOW if the input message length is invalid
825  */
826 int encode_pldm_base_negotiate_transfer_params_req(
827 	uint8_t instance_id,
828 	const struct pldm_base_negotiate_transfer_params_req *req,
829 	struct pldm_msg *msg, size_t *payload_length);
830 
831 /** @brief Encode a PLDM Negotiate Transfer Parameters response message
832  *
833  *  @param[in] instance_id - Message's instance id
834  *  @param[in] resp - The pointer to the response message to be encoded
835  *  @param[out] msg - Message will be written to this
836  *  @param[in,out] payload_length - length of response message payload
837  *  @return 0 on success
838  *          -EINVAL if the input parameters' memory are not allocated,
839  *          or message type or instance in request header is invalid
840  *          -ENOMSG if the PLDM type in the request header is invalid
841  *          -EOVERFLOW if the input message length is invalid
842  */
843 int encode_pldm_base_negotiate_transfer_params_resp(
844 	uint8_t instance_id,
845 	const struct pldm_base_negotiate_transfer_params_resp *resp,
846 	struct pldm_msg *msg, size_t *payload_length);
847 
848 /** @brief Decode a PLDM Negotiate Transfer Parameters request message
849  *
850  *  @param[in] msg - Request message
851  *  @param[in] payload_length - length of request message payload
852  *  @param[out] req - pointer to the decoded request message
853  *  @return 0 on success
854  *          -EINVAL if the input parameters' memory are not allocated
855  *          -EOVERFLOW if the input message buffer is too short for the output
856  *          request struct
857  *          -EBADMSG if the input message buffer is too large for the output
858  *          request struct
859  *  @note  Caller is responsible for memory alloc and dealloc of param
860  *         'msg.payload'
861  */
862 int decode_pldm_base_negotiate_transfer_params_req(
863 	const struct pldm_msg *msg, size_t payload_length,
864 	struct pldm_base_negotiate_transfer_params_req *req);
865 
866 /** @brief Decode a PLDM Negotiate Transfer Parameters response message
867  *
868  *  @param[in] msg - Response message
869  *  @param[in] payload_length - length of request message payload
870  *  @param[out] resp - pointer to the decoded response message,
871  *         excluding the data integrity checksum
872  *  @return 0 on success
873  *          -EINVAL if the input parameters' memory are not allocated
874  *          -EOVERFLOW if the input message buffer is too short for the output
875  *          response struct
876  *          -EBADMSG if the input message buffer is too large for the output
877  *          response struct
878  *  @note  Caller is responsible for memory alloc and dealloc of param
879  *         'msg.payload'
880  */
881 int decode_pldm_base_negotiate_transfer_params_resp(
882 	const struct pldm_msg *msg, size_t payload_length,
883 	struct pldm_base_negotiate_transfer_params_resp *resp);
884 
885 #ifdef __cplusplus
886 }
887 #endif
888 
889 #endif /* BASE_H */
890