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