blob: c3d1ac96a935bdefb4ed357c6c7528e9be3fe092 [file] [log] [blame]
Andrew Jeffery9c766792022-08-10 23:12:49 +09301#ifndef BASE_H
2#define BASE_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include <asm/byteorder.h>
9#include <stddef.h>
10#include <stdint.h>
11
12#include "pldm_types.h"
13
Rashmica Gupta36af84c2023-04-12 16:16:28 +100014typedef uint8_t pldm_tid_t;
15
Andrew Jeffery9c766792022-08-10 23:12:49 +093016/** @brief PLDM Types
17 */
18enum pldm_supported_types {
19 PLDM_BASE = 0x00,
20 PLDM_PLATFORM = 0x02,
21 PLDM_BIOS = 0x03,
22 PLDM_FRU = 0x04,
23 PLDM_FWUP = 0x05,
24 PLDM_OEM = 0x3F,
25};
26
27/** @brief PLDM Commands
28 */
29enum pldm_supported_commands {
Gilbert Chen6c9c9172022-10-18 17:07:29 +080030 PLDM_SET_TID = 0x1,
Andrew Jeffery9c766792022-08-10 23:12:49 +093031 PLDM_GET_TID = 0x2,
32 PLDM_GET_PLDM_VERSION = 0x3,
33 PLDM_GET_PLDM_TYPES = 0x4,
34 PLDM_GET_PLDM_COMMANDS = 0x5,
35 PLDM_MULTIPART_RECEIVE = 0x9,
36};
37
38/** @brief PLDM base codes
39 */
40enum pldm_completion_codes {
41 PLDM_SUCCESS = 0x00,
42 PLDM_ERROR = 0x01,
43 PLDM_ERROR_INVALID_DATA = 0x02,
44 PLDM_ERROR_INVALID_LENGTH = 0x03,
45 PLDM_ERROR_NOT_READY = 0x04,
46 PLDM_ERROR_UNSUPPORTED_PLDM_CMD = 0x05,
47 PLDM_ERROR_INVALID_PLDM_TYPE = 0x20,
48 PLDM_INVALID_TRANSFER_OPERATION_FLAG = 0x21
49};
50
51enum transfer_op_flag {
52 PLDM_GET_NEXTPART = 0,
53 PLDM_GET_FIRSTPART = 1,
Thu Nguyen8eb20f22022-11-16 22:34:55 +070054 PLDM_ACKNOWLEDGEMENT_ONLY = 2,
Andrew Jeffery9c766792022-08-10 23:12:49 +093055};
56
57enum transfer_multipart_op_flag {
58 PLDM_XFER_FIRST_PART = 0,
59 PLDM_XFER_NEXT_PART = 1,
60 PLDM_XFER_ABORT = 2,
61 PLDM_XFER_COMPLETE = 3,
62 PLDM_XFER_CURRENT_PART = 4,
63};
64
65enum transfer_resp_flag {
66 PLDM_START = 0x01,
67 PLDM_MIDDLE = 0x02,
68 PLDM_END = 0x04,
69 PLDM_START_AND_END = 0x05,
70};
71
72/** @brief PLDM transport protocol type
73 */
74enum pldm_transport_protocol_type {
75 PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP = 0x00,
76 PLDM_TRANSPORT_PROTOCOL_TYPE_OEM = 0xFF,
77};
78
79/** @enum MessageType
80 *
81 * The different message types supported by the PLDM specification.
82 */
83typedef enum {
84 PLDM_RESPONSE, //!< PLDM response
85 PLDM_REQUEST, //!< PLDM request
86 PLDM_RESERVED, //!< Reserved
87 PLDM_ASYNC_REQUEST_NOTIFY, //!< Unacknowledged PLDM request messages
88} MessageType;
89
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093090#define PLDM_INSTANCE_MAX 31
91#define PLDM_MAX_TYPES 64
Andrew Jeffery9c766792022-08-10 23:12:49 +093092#define PLDM_MAX_CMDS_PER_TYPE 256
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093093#define PLDM_MAX_TIDS 256
Andrew Jeffery9c766792022-08-10 23:12:49 +093094
95/* Message payload lengths */
96#define PLDM_GET_COMMANDS_REQ_BYTES 5
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093097#define PLDM_GET_VERSION_REQ_BYTES 6
Andrew Jeffery9c766792022-08-10 23:12:49 +093098
99/* Response lengths are inclusive of completion code */
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930100#define PLDM_GET_TYPES_RESP_BYTES 9
101#define PLDM_GET_TID_RESP_BYTES 2
102#define PLDM_SET_TID_RESP_BYTES 1
Andrew Jeffery9c766792022-08-10 23:12:49 +0930103#define PLDM_GET_COMMANDS_RESP_BYTES 33
104/* Response data has only one version and does not contain the checksum */
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930105#define PLDM_GET_VERSION_RESP_BYTES 10
Andrew Jeffery9c766792022-08-10 23:12:49 +0930106#define PLDM_MULTIPART_RECEIVE_REQ_BYTES 18
107
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930108#define PLDM_VERSION_0 0
Andrew Jeffery9c766792022-08-10 23:12:49 +0930109#define PLDM_CURRENT_VERSION PLDM_VERSION_0
110
111#define PLDM_TIMESTAMP104_SIZE 13
112
113/** @struct pldm_msg_hdr
114 *
115 * Structure representing PLDM message header fields
116 */
117struct pldm_msg_hdr {
118#if defined(__LITTLE_ENDIAN_BITFIELD)
119 uint8_t instance_id : 5; //!< Instance ID
120 uint8_t reserved : 1; //!< Reserved
121 uint8_t datagram : 1; //!< Datagram bit
122 uint8_t request : 1; //!< Request bit
123#elif defined(__BIG_ENDIAN_BITFIELD)
124 uint8_t request : 1; //!< Request bit
125 uint8_t datagram : 1; //!< Datagram bit
126 uint8_t reserved : 1; //!< Reserved
127 uint8_t instance_id : 5; //!< Instance ID
128#endif
129
130#if defined(__LITTLE_ENDIAN_BITFIELD)
131 uint8_t type : 6; //!< PLDM type
132 uint8_t header_ver : 2; //!< Header version
133#elif defined(__BIG_ENDIAN_BITFIELD)
134 uint8_t header_ver : 2; //!< Header version
135 uint8_t type : 6; //!< PLDM type
136#endif
137 uint8_t command; //!< PLDM command code
138} __attribute__((packed));
139
140// Macros for byte-swapping variables in-place
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930141#define HTOLE32(X) ((X) = htole32(X))
142#define HTOLE16(X) ((X) = htole16(X))
143#define LE32TOH(X) ((X) = le32toh(X))
144#define LE16TOH(X) ((X) = le16toh(X))
Andrew Jeffery9c766792022-08-10 23:12:49 +0930145
146/** @struct pldm_msg
147 *
148 * Structure representing PLDM message
149 */
150struct pldm_msg {
151 struct pldm_msg_hdr hdr; //!< PLDM message header
152 uint8_t payload[1]; //!< &payload[0] is the beginning of the payload
153} __attribute__((packed));
154
155/** @struct pldm_header_info
156 *
157 * The information needed to prepare PLDM header and this is passed to the
158 * pack_pldm_header and unpack_pldm_header API.
159 */
160struct pldm_header_info {
161 MessageType msg_type; //!< PLDM message type
162 uint8_t instance; //!< PLDM instance id
163 uint8_t pldm_type; //!< PLDM type
164 uint8_t command; //!< PLDM command code
165 uint8_t completion_code; //!< PLDM completion code, applies for response
166};
167
168/** @struct pldm_get_types_resp
169 *
170 * Structure representing PLDM get types response.
171 */
172struct pldm_get_types_resp {
173 uint8_t completion_code; //!< completion code
174 bitfield8_t types[8]; //!< each bit represents whether a given PLDM Type
175 //!< is supported
176} __attribute__((packed));
177
178/** @struct pldm_get_commands_req
179 *
180 * Structure representing PLDM get commands request.
181 */
182struct pldm_get_commands_req {
183 uint8_t type; //!< PLDM Type for which command support information is
184 //!< being requested
185 ver32_t version; //!< version for the specified PLDM Type
186} __attribute__((packed));
187
188/** @struct pldm_get_commands_resp
189 *
190 * Structure representing PLDM get commands response.
191 */
192struct pldm_get_commands_resp {
193 uint8_t completion_code; //!< completion code
194 bitfield8_t commands[32]; //!< each bit represents whether a given PLDM
195 //!< command is supported
196} __attribute__((packed));
197
198/** @struct pldm_get_version_req
199 *
200 * Structure representing PLDM get version request.
201 */
202struct pldm_get_version_req {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930203 uint32_t transfer_handle; //!< handle to identify PLDM version data transfer
Andrew Jeffery9c766792022-08-10 23:12:49 +0930204 uint8_t transfer_opflag; //!< PLDM GetVersion operation flag
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930205 uint8_t type; //!< PLDM Type for which version information is being requested
Andrew Jeffery9c766792022-08-10 23:12:49 +0930206} __attribute__((packed));
207
208/** @struct pldm_get_version_resp
209 *
210 * Structure representing PLDM get version response.
211 */
212
213struct pldm_get_version_resp {
214 uint8_t completion_code; //!< completion code
215 uint32_t next_transfer_handle; //!< next portion of PLDM version data
216 //!< transfer
217 uint8_t transfer_flag; //!< PLDM GetVersion transfer flag
218 uint8_t version_data[1]; //!< PLDM GetVersion version field
219} __attribute__((packed));
220
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800221/** @struct pldm_set_tid_req
222 *
223 * Structure representing PLDM set tid request.
224 */
225
226struct pldm_set_tid_req {
227 uint8_t tid; //!< PLDM SetTID TID field
228} __attribute__((packed));
229
Andrew Jeffery9c766792022-08-10 23:12:49 +0930230/** @struct pldm_get_tid_resp
231 *
232 * Structure representing PLDM get tid response.
233 */
234
235struct pldm_get_tid_resp {
236 uint8_t completion_code; //!< completion code
237 uint8_t tid; //!< PLDM GetTID TID field
238} __attribute__((packed));
239
240/** @struct pldm_multipart_receive_req
241 *
242 * Structure representing PLDM multipart receive request.
243 */
244struct pldm_multipart_receive_req {
245 uint8_t pldm_type; //!< PLDM Type for the MultipartReceive
246 //!< command.
247 uint8_t transfer_opflag; //!< PLDM MultipartReceive operation flag.
248 uint32_t transfer_ctx; //!< Protocol-specifc context for this
249 //!< transfer.
250 uint32_t transfer_handle; //!< handle to identify the part of data to be
251 //!< received.
252 uint32_t section_offset; //!< The start offset for the requested
253 //!< section.
254 uint32_t section_length; //!< The length (in bytes) of the section
255 //!< requested.
256} __attribute__((packed));
257/**
258 * @brief Populate the PLDM message with the PLDM header.The caller of this API
259 * allocates buffer for the PLDM header when forming the PLDM message.
260 * The buffer is passed to this API to pack the PLDM header.
261 *
262 * @param[in] hdr - Pointer to the PLDM header information
263 * @param[out] msg - Pointer to PLDM message header
264 *
265 * @return 0 on success, otherwise PLDM error codes.
266 * @note Caller is responsible for alloc and dealloc of msg
267 * and hdr params
268 */
269uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
270 struct pldm_msg_hdr *msg);
271
272/**
273 * @brief Unpack the PLDM header from the PLDM message.
274 *
275 * @param[in] msg - Pointer to the PLDM message header
276 * @param[out] hdr - Pointer to the PLDM header information
277 *
278 * @return 0 on success, otherwise PLDM error codes.
279 * @note Caller is responsible for alloc and dealloc of msg
280 * and hdr params
281 */
282uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg,
283 struct pldm_header_info *hdr);
284
285/* Requester */
286
287/* GetPLDMTypes */
288
289/** @brief Create a PLDM request message for GetPLDMTypes
290 *
291 * @param[in] instance_id - Message's instance id
292 * @param[in,out] msg - Message will be written to this
293 * @return pldm_completion_codes
294 * @note Caller is responsible for memory alloc and dealloc of param
295 * 'msg.payload'
296 */
297int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg);
298
299/** @brief Decode a GetPLDMTypes response message
300 *
301 * Note:
302 * * If the return value is not PLDM_SUCCESS, it represents a
303 * transport layer error.
304 * * If the completion_code value is not PLDM_SUCCESS, it represents a
305 * protocol layer error and all the out-parameters are invalid.
306 *
307 * @param[in] msg - Response message
308 * @param[in] payload_length - Length of response message payload
309 * @param[out] completion_code - Pointer to response msg's PLDM completion code
310 * @param[out] types - pointer to array bitfield8_t[8] containing supported
311 * types (MAX_TYPES/8) = 8), as per DSP0240
312 * @return pldm_completion_codes
313 */
314int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
315 uint8_t *completion_code, bitfield8_t *types);
316
317/* GetPLDMCommands */
318
319/** @brief Create a PLDM request message for GetPLDMCommands
320 *
321 * @param[in] instance_id - Message's instance id
322 * @param[in] type - PLDM Type
323 * @param[in] version - Version for PLDM Type
324 * @param[in,out] msg - Message will be written to this
325 * @return pldm_completion_codes
326 * @note Caller is responsible for memory alloc and dealloc of param
327 * 'msg.payload'
328 */
329int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
330 struct pldm_msg *msg);
331
332/** @brief Decode a GetPLDMCommands response message
333 *
334 * Note:
335 * * If the return value is not PLDM_SUCCESS, it represents a
336 * transport layer error.
337 * * If the completion_code value is not PLDM_SUCCESS, it represents a
338 * protocol layer error and all the out-parameters are invalid.
339 *
340 * @param[in] msg - Response message
341 * @param[in] payload_length - Length of reponse message payload
342 * @param[out] completion_code - Pointer to response msg's PLDM completion code
343 * @param[in] commands - pointer to array bitfield8_t[32] containing supported
344 * commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
345 * @return pldm_completion_codes
346 */
347int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
348 uint8_t *completion_code, bitfield8_t *commands);
349
350/* GetPLDMVersion */
351
352/** @brief Create a PLDM request for GetPLDMVersion
353 *
354 * @param[in] instance_id - Message's instance id
355 * @param[in] transfer_handle - Handle to identify PLDM version data transfer.
356 * This handle is ignored by the responder when the
357 * transferop_flag is set to getFirstPart.
358 * @param[in] transfer_opflag - flag to indicate whether it is start of
359 * transfer
360 * @param[in] type - PLDM Type for which version is requested
361 * @param[in,out] msg - Message will be written to this
362 * @return pldm_completion_codes
363 * @note Caller is responsible for memory alloc and dealloc of param
364 * 'msg.payload'
365 */
366int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
367 uint8_t transfer_opflag, uint8_t type,
368 struct pldm_msg *msg);
369
370/** @brief Decode a GetPLDMVersion response message
371 *
372 * Note:
373 * * If the return value is not PLDM_SUCCESS, it represents a
374 * transport layer error.
375 * * If the completion_code value is not PLDM_SUCCESS, it represents a
376 * protocol layer error and all the out-parameters are invalid.
377 *
378 * @param[in] msg - Response message
379 * @param[in] payload_length - Length of reponse message payload
380 * @param[out] completion_code - Pointer to response msg's PLDM completion code
381 * @param[out] next_transfer_handle - the next handle for the next part of data
382 * @param[out] transfer_flag - flag to indicate the part of data
383 * @return pldm_completion_codes
384 */
385int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
386 uint8_t *completion_code,
387 uint32_t *next_transfer_handle,
388 uint8_t *transfer_flag, ver32_t *version);
389
390/* GetTID */
391
392/** @brief Decode a GetTID response message
393 *
394 * Note:
395 * * If the return value is not PLDM_SUCCESS, it represents a
396 * transport layer error.
397 * * If the completion_code value is not PLDM_SUCCESS, it represents a
398 * protocol layer error and all the out-parameters are invalid.
399 *
400 * @param[in] msg - Response message
401 * @param[in] payload_length - Length of response message payload
402 * @param[out] completion_code - Pointer to response msg's PLDM completion code
403 * @param[out] tid - Pointer to the terminus id
404 * @return pldm_completion_codes
405 */
406int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
407 uint8_t *completion_code, uint8_t *tid);
408
409/* Responder */
410
411/* GetPLDMTypes */
412
413/** @brief Create a PLDM response message for GetPLDMTypes
414 *
415 * @param[in] instance_id - Message's instance id
416 * @param[in] completion_code - PLDM completion code
417 * @param[in] types - pointer to array bitfield8_t[8] containing supported
418 * types (MAX_TYPES/8) = 8), as per DSP0240
419 * @param[in,out] msg - Message will be written to this
420 * @return pldm_completion_codes
421 * @note Caller is responsible for memory alloc and dealloc of param
422 * 'msg.payload'
423 */
424int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
425 const bitfield8_t *types, struct pldm_msg *msg);
426
427/* GetPLDMCommands */
428
429/** @brief Decode GetPLDMCommands' request data
430 *
431 * @param[in] msg - Request message
432 * @param[in] payload_length - Length of request message payload
433 * @param[out] type - PLDM Type
434 * @param[out] version - Version for PLDM Type
435 * @return pldm_completion_codes
436 */
437int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
438 uint8_t *type, ver32_t *version);
439
440/** @brief Create a PLDM response message for GetPLDMCommands
441 *
442 * @param[in] instance_id - Message's instance id
443 * @param[in] completion_code - PLDM completion code
444 * @param[in] commands - pointer to array bitfield8_t[32] containing supported
445 * commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
446 * @param[in,out] msg - Message will be written to this
447 * @return pldm_completion_codes
448 * @note Caller is responsible for memory alloc and dealloc of param
449 * 'msg.payload'
450 */
451int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
452 const bitfield8_t *commands, struct pldm_msg *msg);
453
454/* GetPLDMVersion */
455
456/** @brief Create a PLDM response for GetPLDMVersion
457 *
458 * @param[in] instance_id - Message's instance id
459 * @param[in] completion_code - PLDM completion code
460 * @param[in] next_transfer_handle - Handle to identify next portion of
461 * data transfer
462 * @param[in] transfer_flag - Represents the part of transfer
463 * @param[in] version_data - the version data
464 * @param[in] version_size - size of version data
465 * @param[in,out] msg - Message will be written to this
466 * @return pldm_completion_codes
467 * @note Caller is responsible for memory alloc and dealloc of param
468 * 'msg.payload'
469 */
470int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
471 uint32_t next_transfer_handle,
472 uint8_t transfer_flag, const ver32_t *version_data,
473 size_t version_size, struct pldm_msg *msg);
474
475/** @brief Decode a GetPLDMVersion request message
476 *
477 * @param[in] msg - Request message
478 * @param[in] payload_length - length of request message payload
479 * @param[out] transfer_handle - the handle of data
480 * @param[out] transfer_opflag - Transfer Flag
481 * @param[out] type - PLDM type for which version is requested
482 * @return pldm_completion_codes
483 */
484int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
485 uint32_t *transfer_handle, uint8_t *transfer_opflag,
486 uint8_t *type);
487
488/* Requester */
489
490/* GetTID */
491
492/** @brief Create a PLDM request message for GetTID
493 *
494 * @param[in] instance_id - Message's instance id
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 */
500int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg);
501
502/** @brief Create a PLDM response message for GetTID
503 *
504 * @param[in] instance_id - Message's instance id
505 * @param[in] completion_code - PLDM completion code
506 * @param[in] tid - Terminus ID
507 * @param[in,out] msg - Message will be written to this
508 * @return pldm_completion_codes
509 * @note Caller is responsible for memory alloc and dealloc of param
510 * 'msg.payload'
511 */
512int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
513 uint8_t tid, struct pldm_msg *msg);
514
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800515/** @brief Create a PLDM request message for SetTID
516 *
517 * @param[in] instance_id - Message's instance id
518 * @param[in] tid - Terminus ID
519 * @param[in,out] msg - Message will be written to this
520 * @return pldm_completion_codes
521 * @note Caller is responsible for memory alloc and dealloc of param
522 * 'msg.payload'
523 */
524int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg);
525
Andrew Jeffery9c766792022-08-10 23:12:49 +0930526/* Responder */
527
528/* MultipartRecieve */
529
530/** @brief Decode a PLDM MultipartReceive request message
531 *
532 * @param[in] msg - Request message
533 * @param[in] payload_length - length of request message payload
534 * @param[out] pldm_type - PLDM type for which version is requested
535 * @param[out] transfer_opflag - Transfer Flag
536 * @param[out] transfer_ctx - The context of the packet
537 * @param[out] transfer_handle - The handle of data
538 * @param[out] section_offset - The start of the requested section
539 * @param[out] section_length - The length of the requested section
540 * @return pldm_completion_codes
541 */
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930542int decode_multipart_receive_req(const struct pldm_msg *msg,
543 size_t payload_length, uint8_t *pldm_type,
544 uint8_t *transfer_opflag,
545 uint32_t *transfer_ctx,
546 uint32_t *transfer_handle,
547 uint32_t *section_offset,
548 uint32_t *section_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930549
550/** @brief Create a PLDM response message containing only cc
551 *
552 * @param[in] instance_id - Message's instance id
553 * @param[in] type - PLDM Type
554 * @param[in] command - PLDM Command
555 * @param[in] cc - PLDM Completion Code
556 * @param[out] msg - Message will be written to this
557 * @return pldm_completion_codes
558 */
559int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
560 uint8_t cc, struct pldm_msg *msg);
561
562/** @brief Create a PLDM message only with the header
563 *
564 * @param[in] msg_type - PLDM message type
565 * @param[in] instance_id - Message's instance id
566 * @param[in] pldm_type - PLDM Type
567 * @param[in] command - PLDM Command
568 * @param[out] msg - Message will be written to this
569 *
570 * @return pldm_completion_codes
571 */
572int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
573 uint8_t pldm_type, uint8_t command,
574 struct pldm_msg *msg);
575
576#ifdef __cplusplus
577}
578#endif
579
580#endif /* BASE_H */