xref: /openbmc/libpldm/include/libpldm/base.h (revision ae7410c359dc98ae28e9b7f7693c7b7b75b0e79d)
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 /** @struct pldm_header_info
279  *
280  *  The information needed to prepare PLDM header and this is passed to the
281  *  pack_pldm_header and unpack_pldm_header API.
282  */
283 struct pldm_header_info {
284 	MessageType msg_type;	 //!< PLDM message type
285 	uint8_t instance;	 //!< PLDM instance id
286 	uint8_t pldm_type;	 //!< PLDM type
287 	uint8_t command;	 //!< PLDM command code
288 	uint8_t completion_code; //!< PLDM completion code, applies for response
289 };
290 
291 /** @struct pldm_get_types_resp
292  *
293  *  Structure representing PLDM get types response.
294  */
295 struct pldm_get_types_resp {
296 	uint8_t completion_code; //!< completion code
297 	bitfield8_t types[8]; //!< each bit represents whether a given PLDM Type
298 			      //!< is supported
299 } __attribute__((packed));
300 
301 /** @struct pldm_get_commands_req
302  *
303  *  Structure representing PLDM get commands request.
304  */
305 struct pldm_get_commands_req {
306 	uint8_t type;	 //!< PLDM Type for which command support information is
307 			 //!< being requested
308 	ver32_t version; //!< version for the specified PLDM Type
309 } __attribute__((packed));
310 
311 /** @struct pldm_get_commands_resp
312  *
313  *  Structure representing PLDM get commands response.
314  */
315 struct pldm_get_commands_resp {
316 	uint8_t completion_code;  //!< completion code
317 	bitfield8_t commands[32]; //!< each bit represents whether a given PLDM
318 				  //!< command is supported
319 } __attribute__((packed));
320 
321 /** @struct pldm_get_version_req
322  *
323  *  Structure representing PLDM get version request.
324  */
325 struct pldm_get_version_req {
326 	uint32_t transfer_handle; //!< handle to identify PLDM version data transfer
327 	uint8_t transfer_opflag; //!< PLDM GetVersion operation flag
328 	uint8_t type; //!< PLDM Type for which version information is being requested
329 } __attribute__((packed));
330 
331 /** @struct pldm_get_version_resp
332  *
333  *  Structure representing PLDM get version response.
334  */
335 
336 struct pldm_get_version_resp {
337 	uint8_t completion_code;       //!< completion code
338 	uint32_t next_transfer_handle; //!< next portion of PLDM version data
339 				       //!< transfer
340 	uint8_t transfer_flag;	       //!< PLDM GetVersion transfer flag
341 	uint8_t version_data[1];       //!< PLDM GetVersion version field
342 } __attribute__((packed));
343 
344 /** @struct pldm_set_tid_req
345  *
346  *  Structure representing PLDM set tid request.
347  */
348 
349 struct pldm_set_tid_req {
350 	uint8_t tid; //!< PLDM SetTID TID field
351 } __attribute__((packed));
352 
353 /** @struct pldm_get_tid_resp
354  *
355  *  Structure representing PLDM get tid response.
356  */
357 
358 struct pldm_get_tid_resp {
359 	uint8_t completion_code; //!< completion code
360 	uint8_t tid;		 //!< PLDM GetTID TID field
361 } __attribute__((packed));
362 
363 /** @struct pldm_base_multipart_receive_req
364  *
365  * Structure representing PLDM multipart receive request.
366  */
367 struct pldm_base_multipart_receive_req {
368 	uint8_t pldm_type;	  //!< PLDM Type for the MultipartReceive
369 				  //!< command.
370 	uint8_t transfer_opflag;  //!< PLDM MultipartReceive operation flag.
371 	uint32_t transfer_ctx;	  //!< Protocol-specifc context for this
372 				  //!< transfer.
373 	uint32_t transfer_handle; //!< handle to identify the part of data to be
374 				  //!< received.
375 	uint32_t section_offset;  //!< The start offset for the requested
376 				  //!< section.
377 	uint32_t section_length;  //!< The length (in bytes) of the section
378 				  //!< requested.
379 };
380 
381 /** @struct pldm_base_multipart_receive_resp
382  *
383  * Structure representing PLDM multipart receive request.
384  */
385 struct pldm_base_multipart_receive_resp {
386 	uint8_t completion_code;       //!< Completion code of the command.
387 	uint8_t transfer_flag;	       //!< PLDM MultipartReceive transfer flag.
388 	uint32_t next_transfer_handle; //!< The handle for the next part of
389 				       //!< data for this section transfer.
390 	struct variable_field data;
391 };
392 
393 /** @struct pldm_base_negotiate_transfer_params_req
394  *
395  * Structure representing PLDM Negotiate Transfer Parameters request
396  */
397 struct pldm_base_negotiate_transfer_params_req {
398 	uint16_t requester_part_size;
399 	bitfield8_t requester_protocol_support[8];
400 };
401 
402 /** @struct pldm_base_negotiate_transfer_params_resp
403  *
404  * Structure representing PLDM Negotiate Transfer Parameters response
405  */
406 struct pldm_base_negotiate_transfer_params_resp {
407 	uint8_t completion_code;
408 	uint16_t responder_part_size;
409 	bitfield8_t responder_protocol_support[8];
410 };
411 
412 /**
413  * @brief Populate the PLDM message with the PLDM header.The caller of this API
414  *        allocates buffer for the PLDM header when forming the PLDM message.
415  *        The buffer is passed to this API to pack the PLDM header.
416  *
417  * @param[in] hdr - Pointer to the PLDM header information
418  * @param[out] msg - Pointer to PLDM message header
419  *
420  * @return 0 on success, otherwise PLDM error codes.
421  * @note   Caller is responsible for alloc and dealloc of msg
422  *         and hdr params
423  */
424 uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
425 			 struct pldm_msg_hdr *msg);
426 
427 /**
428  * @brief Unpack the PLDM header from the PLDM message.
429  *
430  * @param[in] msg - Pointer to the PLDM message header
431  * @param[out] hdr - Pointer to the PLDM header information
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 unpack_pldm_header(const struct pldm_msg_hdr *msg,
438 			   struct pldm_header_info *hdr);
439 
440 /* Requester */
441 
442 /* GetPLDMTypes */
443 
444 /** @brief Create a PLDM request message for GetPLDMTypes
445  *
446  *  @param[in] instance_id - Message's instance id
447  *  @param[in,out] msg - Message will be written to this
448  *  @return pldm_completion_codes
449  *  @note  Caller is responsible for memory alloc and dealloc of param
450  *         'msg.payload'
451  */
452 int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg);
453 
454 /** @brief Decode a GetPLDMTypes response message
455  *
456  *  Note:
457  *  * If the return value is not PLDM_SUCCESS, it represents a
458  * transport layer error.
459  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
460  * protocol layer error and all the out-parameters are invalid.
461  *
462  *  @param[in] msg - Response message
463  *  @param[in] payload_length - Length of response message payload
464  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
465  *  @param[out] types - pointer to array bitfield8_t[8] containing supported
466  *              types (MAX_TYPES/8) = 8), as per DSP0240
467  *  @return pldm_completion_codes
468  */
469 int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
470 			  uint8_t *completion_code, bitfield8_t *types);
471 
472 /* GetPLDMCommands */
473 
474 /** @brief Create a PLDM request message for GetPLDMCommands
475  *
476  *  @param[in] instance_id - Message's instance id
477  *  @param[in] type - PLDM Type
478  *  @param[in] version - Version for PLDM Type
479  *  @param[in,out] msg - Message will be written to this
480  *  @return pldm_completion_codes
481  *  @note  Caller is responsible for memory alloc and dealloc of param
482  *         'msg.payload'
483  */
484 int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
485 			    struct pldm_msg *msg);
486 
487 /** @brief Decode a GetPLDMCommands response message
488  *
489  *  Note:
490  *  * If the return value is not PLDM_SUCCESS, it represents a
491  * transport layer error.
492  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
493  * protocol layer error and all the out-parameters are invalid.
494  *
495  *  @param[in] msg - Response message
496  *  @param[in] payload_length - Length of response message payload
497  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
498  *  @param[in] commands - pointer to array bitfield8_t[32] containing supported
499  *             commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
500  *  @return pldm_completion_codes
501  */
502 int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
503 			     uint8_t *completion_code, bitfield8_t *commands);
504 
505 /* GetPLDMVersion */
506 
507 /** @brief Create a PLDM request for GetPLDMVersion
508  *
509  *  @param[in] instance_id - Message's instance id
510  *  @param[in] transfer_handle - Handle to identify PLDM version data transfer.
511  *         This handle is ignored by the responder when the
512  *         transferop_flag is set to getFirstPart.
513  *  @param[in] transfer_opflag - flag to indicate whether it is start of
514  *         transfer
515  *  @param[in] type -  PLDM Type for which version is requested
516  *  @param[in,out] msg - Message will be written to this
517  *  @return pldm_completion_codes
518  *  @note  Caller is responsible for memory alloc and dealloc of param
519  *         'msg.payload'
520  */
521 int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
522 			   uint8_t transfer_opflag, uint8_t type,
523 			   struct pldm_msg *msg);
524 
525 /** @brief Decode a GetPLDMVersion response message
526  *
527  *  Note:
528  *  * If the return value is not PLDM_SUCCESS, it represents a
529  * transport layer error.
530  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
531  * protocol layer error and all the out-parameters are invalid.
532  *
533  *  @param[in] msg - Response message
534  *  @param[in] payload_length - Length of response message payload
535  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
536  *  @param[out] next_transfer_handle - the next handle for the next part of data
537  *  @param[out] transfer_flag - flag to indicate the part of data
538  *  @return pldm_completion_codes
539  */
540 int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
541 			    uint8_t *completion_code,
542 			    uint32_t *next_transfer_handle,
543 			    uint8_t *transfer_flag, ver32_t *version);
544 
545 /* GetTID */
546 
547 /** @brief Decode a GetTID response message
548  *
549  *  Note:
550  *  * If the return value is not PLDM_SUCCESS, it represents a
551  * transport layer error.
552  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
553  * protocol layer error and all the out-parameters are invalid.
554  *
555  *  @param[in] msg - Response message
556  *  @param[in] payload_length - Length of response message payload
557  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
558  *  @param[out] tid - Pointer to the terminus id
559  *  @return pldm_completion_codes
560  */
561 int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
562 			uint8_t *completion_code, uint8_t *tid);
563 
564 /* Responder */
565 
566 /* GetPLDMTypes */
567 
568 /** @brief Create a PLDM response message for GetPLDMTypes
569  *
570  *  @param[in] instance_id - Message's instance id
571  *  @param[in] completion_code - PLDM completion code
572  *  @param[in] types - pointer to array bitfield8_t[8] containing supported
573  *             types (MAX_TYPES/8) = 8), as per DSP0240
574  *  @param[in,out] msg - Message will be written to this
575  *  @return pldm_completion_codes
576  *  @note  Caller is responsible for memory alloc and dealloc of param
577  *         'msg.payload'
578  */
579 int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
580 			  const bitfield8_t *types, struct pldm_msg *msg);
581 
582 /* GetPLDMCommands */
583 
584 /** @brief Decode GetPLDMCommands' request data
585  *
586  *  @param[in] msg - Request message
587  *  @param[in] payload_length - Length of request message payload
588  *  @param[out] type - PLDM Type
589  *  @param[out] version - Version for PLDM Type
590  *  @return pldm_completion_codes
591  */
592 int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
593 			    uint8_t *type, ver32_t *version);
594 
595 /** @brief Create a PLDM response message for GetPLDMCommands
596  *
597  *  @param[in] instance_id - Message's instance id
598  *  @param[in] completion_code - PLDM completion code
599  *  @param[in] commands - pointer to array bitfield8_t[32] containing supported
600  *             commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
601  *  @param[in,out] msg - Message will be written to this
602  *  @return pldm_completion_codes
603  *  @note  Caller is responsible for memory alloc and dealloc of param
604  *         'msg.payload'
605  */
606 int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
607 			     const bitfield8_t *commands, struct pldm_msg *msg);
608 
609 /* GetPLDMVersion */
610 
611 /** @brief Create a PLDM response for GetPLDMVersion
612  *
613  *  @param[in] instance_id - Message's instance id
614  *  @param[in] completion_code - PLDM completion code
615  *  @param[in] next_transfer_handle - Handle to identify next portion of
616  *              data transfer
617  *  @param[in] transfer_flag - Represents the part of transfer
618  *  @param[in] version_data - the version data
619  *  @param[in] version_size - size of version data
620  *  @param[in,out] msg - Message will be written to this
621  *  @return pldm_completion_codes
622  *  @note  Caller is responsible for memory alloc and dealloc of param
623  *         'msg.payload'
624  */
625 int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
626 			    uint32_t next_transfer_handle,
627 			    uint8_t transfer_flag, const ver32_t *version_data,
628 			    size_t version_size, struct pldm_msg *msg);
629 
630 /** @brief Decode a GetPLDMVersion request message
631  *
632  *  @param[in] msg - Request message
633  *  @param[in] payload_length - length of request message payload
634  *  @param[out] transfer_handle - the handle of data
635  *  @param[out] transfer_opflag - Transfer Flag
636  *  @param[out] type - PLDM type for which version is requested
637  *  @return pldm_completion_codes
638  */
639 int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
640 			   uint32_t *transfer_handle, uint8_t *transfer_opflag,
641 			   uint8_t *type);
642 
643 /* Requester */
644 
645 /* GetTID */
646 
647 /** @brief Create a PLDM request message for GetTID
648  *
649  *  @param[in] instance_id - Message's instance id
650  *  @param[in,out] msg - Message will be written to this
651  *  @return pldm_completion_codes
652  *  @note  Caller is responsible for memory alloc and dealloc of param
653  *         'msg.payload'
654  */
655 int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg);
656 
657 /** @brief Create a PLDM response message for GetTID
658  *
659  *  @param[in] instance_id - Message's instance id
660  *  @param[in] completion_code - PLDM completion code
661  *  @param[in] tid - Terminus ID
662  *  @param[in,out] msg - Message will be written to this
663  *  @return pldm_completion_codes
664  *  @note  Caller is responsible for memory alloc and dealloc of param
665  *         'msg.payload'
666  */
667 int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
668 			uint8_t tid, struct pldm_msg *msg);
669 
670 /** @brief Create a PLDM request message for SetTID
671  *
672  *  @param[in] instance_id - Message's instance id
673  *  @param[in] tid - Terminus ID
674  *  @param[in,out] msg - Message will be written to this
675  *  @return pldm_completion_codes
676  *  @note  Caller is responsible for memory alloc and dealloc of param
677  *         'msg.payload'
678  */
679 int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg);
680 
681 /** @brief Decode a SetTID request message
682  *
683  *  @param[in] msg - Request message
684  *  @param[in] payload_length - length of request message payload
685  *  @param[out] tid - Terminus ID
686  *  @return 0 on success
687  *         -EINVAL if the input parameters' memory are not allocated,
688  *         or tid is invalid
689  *         -EOVERFLOW if the input message length is invalid
690  */
691 int decode_set_tid_req(const struct pldm_msg *msg, size_t payload_length,
692 		       uint8_t *tid);
693 
694 /* Responder */
695 
696 /* MultipartRecieve */
697 
698 /** @brief Decode a PLDM MultipartReceive request message
699  *
700  *  @param[in] msg - Request message
701  *  @param[in] payload_length - length of request message payload
702  *  @param[out] pldm_type - PLDM type for which version is requested
703  *  @param[out] transfer_opflag - Transfer Flag
704  *  @param[out] transfer_ctx - The context of the packet
705  *  @param[out] transfer_handle - The handle of data
706  *  @param[out] section_offset - The start of the requested section
707  *  @param[out] section_length - The length of the requested section
708  *  @return pldm_completion_codes
709  */
710 int decode_multipart_receive_req(const struct pldm_msg *msg,
711 				 size_t payload_length, uint8_t *pldm_type,
712 				 uint8_t *transfer_opflag,
713 				 uint32_t *transfer_ctx,
714 				 uint32_t *transfer_handle,
715 				 uint32_t *section_offset,
716 				 uint32_t *section_length);
717 
718 /** @brief Encode a PLDM MultipartReceive request message
719  *
720  *  @param[in] instance_id - Message's instance id
721  *  @param[in] req - The pointer to the request message to be encoded
722  *  @param[in,out] msg - Message will be written to this
723  *  @param[in, out] payload_length - length of request message payload
724  *  @return 0 on success
725  *          -EINVAL if the input parameters' memory are not allocated,
726  *          or message type or instance in request header is invalid
727  *          -ENOMSG if the PLDM type in the request header is invalid
728  *          -EOVERFLOW if the input message length is invalid
729  */
730 int encode_pldm_base_multipart_receive_req(
731 	uint8_t instance_id, const struct pldm_base_multipart_receive_req *req,
732 	struct pldm_msg *msg, size_t *payload_length);
733 
734 /** @brief Decode a PLDM MultipartReceive response message
735  *
736  *  @param[in] msg - Response message
737  *  @param[in] payload_length - length of request message payload
738  *  @param[out] resp - pointer to the decoded response message,
739  *         excluding the data integrity checksum
740  *  @param[out] data_integrity_checksum - The checksum of data field
741  *         of the decoded response message
742  *  @return 0 on success
743  *          -EINVAL if the input parameters' memory are not allocated
744  *          -EOVERFLOW if the input message buffer is too short for the output
745  *          response struct
746  *          -EBADMSG if the input message buffer is too large for the output
747  *          response struct
748  *  @note  Caller is responsible for memory alloc and dealloc of param
749  *         'msg.payload'
750  */
751 int decode_pldm_base_multipart_receive_resp(
752 	const struct pldm_msg *msg, size_t payload_length,
753 	struct pldm_base_multipart_receive_resp *resp,
754 	uint32_t *data_integrity_checksum);
755 
756 /** @brief Encode a PLDM MultipartReceive response message
757  *
758  *  @param[in] instance_id - Message's instance id
759  *  @param[in] resp - The pointer to the response message to be encoded
760  *  @param[in] checksum - Checksum of the entirely data payload
761  *  @param[in,out] msg - Message will be written to this
762  *  @param[in,out] payload_length - length of request message payload
763  *  @return 0 on success
764  *          -EINVAL if argument values are invalid for the invocation
765  *          -ENOMSG if the PLDM type in the request header is invalid
766  *          -EOVERFLOW if the input message length is invalid
767  *  @note  Caller is responsible for memory alloc and dealloc of param
768  *         'msg.payload'
769  */
770 int encode_base_multipart_receive_resp(
771 	uint8_t instance_id,
772 	const struct pldm_base_multipart_receive_resp *resp, uint32_t checksum,
773 	struct pldm_msg *msg, size_t *payload_length);
774 
775 /** @brief Create a PLDM response message containing only cc
776  *
777  *  @param[in] instance_id - Message's instance id
778  *  @param[in] type - PLDM Type
779  *  @param[in] command - PLDM Command
780  *  @param[in] cc - PLDM Completion Code
781  *  @param[out] msg - Message will be written to this
782  *  @return pldm_completion_codes
783  */
784 int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
785 			uint8_t cc, struct pldm_msg *msg);
786 
787 /** @brief Create a PLDM message only with the header
788  *
789  *	@param[in] msg_type - PLDM message type
790  *	@param[in] instance_id - Message's instance id
791  *	@param[in] pldm_type - PLDM Type
792  *	@param[in] command - PLDM Command
793  *	@param[out] msg - Message will be written to this
794  *
795  *	@return pldm_completion_codes
796  */
797 int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
798 			    uint8_t pldm_type, uint8_t command,
799 			    struct pldm_msg *msg);
800 
801 /** @brief Encode a PLDM Negotiate Transfer Parameters request message
802  *
803  *  @param[in] instance_id - Message's instance id
804  *  @param[in] req - The pointer to the request message to be encoded
805  *  @param[in,out] msg - Message will be written to this
806  *  @param[in, out] payload_length - length of request message payload
807  *  @return 0 on success
808  *          -EINVAL if the input parameters' memory are not allocated,
809  *          or message type or instance in request header is invalid
810  *          -ENOMSG if the PLDM type in the request header is invalid
811  *          -EOVERFLOW if the input message length is invalid
812  */
813 int encode_pldm_base_negotiate_transfer_params_req(
814 	uint8_t instance_id,
815 	const struct pldm_base_negotiate_transfer_params_req *req,
816 	struct pldm_msg *msg, size_t *payload_length);
817 
818 /** @brief Encode a PLDM Negotiate Transfer Parameters response message
819  *
820  *  @param[in] instance_id - Message's instance id
821  *  @param[in] resp - The pointer to the response message to be encoded
822  *  @param[out] msg - Message will be written to this
823  *  @param[in,out] payload_length - length of response message payload
824  *  @return 0 on success
825  *          -EINVAL if the input parameters' memory are not allocated,
826  *          or message type or instance in request header is invalid
827  *          -ENOMSG if the PLDM type in the request header is invalid
828  *          -EOVERFLOW if the input message length is invalid
829  */
830 int encode_pldm_base_negotiate_transfer_params_resp(
831 	uint8_t instance_id,
832 	const struct pldm_base_negotiate_transfer_params_resp *resp,
833 	struct pldm_msg *msg, size_t *payload_length);
834 
835 /** @brief Decode a PLDM Negotiate Transfer Parameters request message
836  *
837  *  @param[in] msg - Request message
838  *  @param[in] payload_length - length of request message payload
839  *  @param[out] req - pointer to the decoded request message
840  *  @return 0 on success
841  *          -EINVAL if the input parameters' memory are not allocated
842  *          -EOVERFLOW if the input message buffer is too short for the output
843  *          request struct
844  *          -EBADMSG if the input message buffer is too large for the output
845  *          request struct
846  *  @note  Caller is responsible for memory alloc and dealloc of param
847  *         'msg.payload'
848  */
849 int decode_pldm_base_negotiate_transfer_params_req(
850 	const struct pldm_msg *msg, size_t payload_length,
851 	struct pldm_base_negotiate_transfer_params_req *req);
852 
853 /** @brief Decode a PLDM Negotiate Transfer Parameters response message
854  *
855  *  @param[in] msg - Response message
856  *  @param[in] payload_length - length of request message payload
857  *  @param[out] resp - pointer to the decoded response message,
858  *         excluding the data integrity checksum
859  *  @return 0 on success
860  *          -EINVAL if the input parameters' memory are not allocated
861  *          -EOVERFLOW if the input message buffer is too short for the output
862  *          response struct
863  *          -EBADMSG if the input message buffer is too large for the output
864  *          response struct
865  *  @note  Caller is responsible for memory alloc and dealloc of param
866  *         'msg.payload'
867  */
868 int decode_pldm_base_negotiate_transfer_params_resp(
869 	const struct pldm_msg *msg, size_t payload_length,
870 	struct pldm_base_negotiate_transfer_params_resp *resp);
871 
872 #ifdef __cplusplus
873 }
874 #endif
875 
876 #endif /* BASE_H */
877