xref: /openbmc/libpldm/include/libpldm/fru.h (revision 9e3a5d45)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #ifndef FRU_H
3 #define FRU_H
4 
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8 
9 #include <libpldm/base.h>
10 #include <libpldm/utils.h>
11 
12 #include <asm/byteorder.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #define PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES  0
17 #define PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES 19
18 #define PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES	      5
19 #define PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES      6
20 #define PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES  6
21 #define PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES	      5
22 #define PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES	      5
23 
24 #define FRU_TABLE_CHECKSUM_SIZE 4
25 
26 enum pldm_fru_completion_codes {
27 	PLDM_FRU_INVALID_DATA_TRANSFER_HANDLE = 0x80,
28 	PLDM_FRU_INVALID_TRANSFER_FLAG = 0x82,
29 	PLDM_FRU_DATA_INVALID_DATA_INTEGRITY_CHECK = 0x84,
30 	PLDM_FRU_DATA_STRUCTURE_TABLE_UNAVAILABLE = 0x85,
31 };
32 
33 /** @brief PLDM FRU commands
34  */
35 enum pldm_fru_commands {
36 	PLDM_GET_FRU_RECORD_TABLE_METADATA = 0x01,
37 	PLDM_GET_FRU_RECORD_TABLE = 0x02,
38 	PLDM_SET_FRU_RECORD_TABLE = 0x03,
39 	PLDM_GET_FRU_RECORD_BY_OPTION = 0x04
40 };
41 
42 /** @brief FRU record types
43  */
44 enum pldm_fru_record_type {
45 	PLDM_FRU_RECORD_TYPE_GENERAL = 0x01,
46 	PLDM_FRU_RECORD_TYPE_OEM = 0xfe,
47 };
48 
49 /** @brief Encoding type for FRU fields
50  */
51 enum pldm_fru_field_encoding {
52 	PLDM_FRU_ENCODING_UNSPECIFIED = 0x00,
53 	PLDM_FRU_ENCODING_ASCII = 0x01,
54 	PLDM_FRU_ENCODING_UTF8 = 0x02,
55 	PLDM_FRU_ENCODING_UTF16 = 0x03,
56 	PLDM_FRU_ENCODING_UTF16LE = 0x04,
57 	PLDM_FRU_ENCODING_UTF16BE = 0x05,
58 };
59 
60 /** @brief FRU field types
61  */
62 enum pldm_fru_field_type {
63 	PLDM_FRU_FIELD_TYPE_CHASSIS = 0x01,
64 	PLDM_FRU_FIELD_TYPE_MODEL = 0x02,
65 	PLDM_FRU_FIELD_TYPE_PN = 0x03,
66 	PLDM_FRU_FIELD_TYPE_SN = 0x04,
67 	PLDM_FRU_FIELD_TYPE_MANUFAC = 0x05,
68 	PLDM_FRU_FIELD_TYPE_MANUFAC_DATE = 0x06,
69 	PLDM_FRU_FIELD_TYPE_VENDOR = 0x07,
70 	PLDM_FRU_FIELD_TYPE_NAME = 0x08,
71 	PLDM_FRU_FIELD_TYPE_SKU = 0x09,
72 	PLDM_FRU_FIELD_TYPE_VERSION = 0x0a,
73 	PLDM_FRU_FIELD_TYPE_ASSET_TAG = 0x0b,
74 	PLDM_FRU_FIELD_TYPE_DESC = 0x0c,
75 	PLDM_FRU_FIELD_TYPE_EC_LVL = 0x0d,
76 	PLDM_FRU_FIELD_TYPE_OTHER = 0x0e,
77 	PLDM_FRU_FIELD_TYPE_IANA = 0x0f,
78 };
79 
80 /** @struct pldm_get_fru_record_table_metadata_resp
81  *
82  *  Structure representing PLDM get FRU table metadata response.
83  */
84 struct pldm_get_fru_record_table_metadata_resp {
85 	uint8_t completion_code;	//!< completion code
86 	uint8_t fru_data_major_version; //!< The major version of the FRU Record
87 	uint8_t fru_data_minor_version; //!< The minor version of the FRU Record
88 	uint32_t fru_table_maximum_size; //!< The size of the largest FRU Record data
89 	uint32_t fru_table_length; //!< The total length of the FRU Record Table
90 	uint16_t total_record_set_identifiers; //!< The total number of FRU
91 					       //!< Record Data structures
92 	uint16_t total_table_records; //!< The total number of records in the table
93 	uint32_t checksum; //!< The integrity checksum on the FRU Record Table data
94 } __attribute__((packed));
95 
96 /** @struct pldm_get_fru_record_table_req
97  *
98  *  Structure representing PLDM get FRU record table request.
99  */
100 struct pldm_get_fru_record_table_req {
101 	uint32_t data_transfer_handle;
102 	uint8_t transfer_operation_flag;
103 } __attribute__((packed));
104 
105 /** @struct pldm_get_fru_record_table_resp
106  *
107  *  Structure representing PLDM get FRU record table response.
108  */
109 struct pldm_get_fru_record_table_resp {
110 	uint8_t completion_code;
111 	uint32_t next_data_transfer_handle;
112 	uint8_t transfer_flag;
113 	uint8_t fru_record_table_data[1];
114 } __attribute__((packed));
115 
116 struct pldm_get_fru_record_by_option_req {
117 	uint32_t data_transfer_handle;
118 	uint16_t fru_table_handle;
119 	uint16_t record_set_identifier;
120 	uint8_t record_type;
121 	uint8_t field_type;
122 	uint8_t transfer_op_flag;
123 } __attribute__((packed));
124 
125 struct pldm_get_fru_record_by_option_resp {
126 	uint8_t completion_code;
127 	uint32_t next_data_transfer_handle;
128 	uint8_t transfer_flag;
129 	uint8_t fru_structure_data[1];
130 } __attribute__((packed));
131 
132 struct pldm_set_fru_record_table_req {
133 	uint32_t data_transfer_handle;
134 	uint8_t transfer_flag;
135 	uint8_t fru_record_table_data[1];
136 } __attribute__((packed));
137 
138 struct pldm_set_fru_record_table_resp {
139 	uint8_t completion_code;
140 	uint32_t next_data_transfer_handle;
141 } __attribute__((packed));
142 
143 /** @struct pldm_fru_record_tlv
144  *
145  *  Structure representing each FRU field entry (type, length, value)
146  */
147 struct pldm_fru_record_tlv {
148 	uint8_t type;
149 	uint8_t length;
150 	uint8_t value[1];
151 } __attribute__((packed));
152 
153 /** @struct pldm_fru_record_data_format
154  *
155  *  Structure representing the FRU record data format
156  */
157 struct pldm_fru_record_data_format {
158 	uint16_t record_set_id;
159 	uint8_t record_type;
160 	uint8_t num_fru_fields;
161 	uint8_t encoding_type;
162 	struct pldm_fru_record_tlv tlvs[1];
163 } __attribute__((packed));
164 
165 /* Requester */
166 
167 /* GetFRURecordTableMetadata */
168 
169 /** @brief Create a PLDM request message for GetFRURecordTableMetadata
170  *
171  *  @param[in] instance_id - Message's instance id
172  *  @param[in,out] msg - Message will be written to this
173  *  @param[in] payload_length - Length of the request message payload
174  *  @return pldm_completion_codes
175  *  @note  Caller is responsible for memory alloc and dealloc of param
176  *         'msg.payload'
177  */
178 int encode_get_fru_record_table_metadata_req(uint8_t instance_id,
179 					     struct pldm_msg *msg,
180 					     size_t payload_length);
181 
182 /** @brief Decode GetFruRecordTable response data
183  *
184  *  Note:
185  *  * If the return value is not PLDM_SUCCESS, it represents a
186  * transport layer error.
187  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
188  * protocol layer error and all the out-parameters are invalid.
189  *
190  *  @param[in] msg - Response message
191  *  @param[in] payload_length - Length of response message payload
192  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
193  *  @param[out] fru_data_major_version - Major version of the FRU Record
194  *  @param[out] fru_data_minor_version - Minor version of the FRU Record
195  *  @param[out] fru_table_maximum_size - Size of the largest FRU Record data
196  *  @param[out] fru_table_length - Total length of the FRU Record Table
197  *  @param[out] total_Record_Set_Identifiers - Total number of FRU Record Data
198  * structures
199  *  @param[out] total_table_records - Total number of records in the table
200  *  @param[out] checksum - integrity checksum on the FRU Record Table data
201  *  @return pldm_completion_codes
202  */
203 int decode_get_fru_record_table_metadata_resp(
204 	const struct pldm_msg *msg, size_t payload_length,
205 	uint8_t *completion_code, uint8_t *fru_data_major_version,
206 	uint8_t *fru_data_minor_version, uint32_t *fru_table_maximum_size,
207 	uint32_t *fru_table_length, uint16_t *total_record_set_identifiers,
208 	uint16_t *total_table_records, uint32_t *checksum);
209 
210 /* Responder */
211 
212 /* GetFRURecordTableMetadata */
213 
214 /** @brief Create a PLDM response message for GetFRURecordTableMetadata
215  *
216  *  @param[in] instance_id - Message's instance id
217  *  @param[in] completion_code - PLDM completion code
218  *  @param[in] fru_data_major_version - Major version of the FRU Record
219  *  @param[in] fru_data_minor_version - Minor version of the FRU Record
220  *  @param[in] fru_table_maximum_size - Size of the largest FRU Record data
221  *  @param[in] fru_table_length - Total length of the FRU Record Table
222  *  @param[in] total_Record_Set_Identifiers - Total number of FRU Record Data
223  * structures
224  *  @param[in] total_table_records - Total number of records in the table
225  *  @param[in] checksum - integrity checksum on the FRU Record Table data
226  *  @param[in,out] msg - Message will be written to this
227  *  @return pldm_completion_codes
228  *  @note  Caller is responsible for memory alloc and dealloc of param
229  *         'msg.payload'
230  */
231 
232 int encode_get_fru_record_table_metadata_resp(
233 	uint8_t instance_id, uint8_t completion_code,
234 	uint8_t fru_data_major_version, uint8_t fru_data_minor_version,
235 	uint32_t fru_table_maximum_size, uint32_t fru_table_length,
236 	uint16_t total_record_set_identifiers, uint16_t total_table_records,
237 	uint32_t checksum, struct pldm_msg *msg);
238 
239 /* GetFruRecordTable */
240 
241 /** @brief Decode GetFruRecordTable request data
242  *
243  *  @param[in] msg - PLDM request message payload
244  *  @param[in] payload_length - Length of request payload
245  *  @param[out] data_transfer_handle - A handle, used to identify a FRU Record
246  *  Table data transfer
247  *  @param[out] transfer_operation_flag - A flag that indicates whether this is
248  *  the start of the transfer
249  *  @return pldm_completion_codes
250  */
251 int decode_get_fru_record_table_req(const struct pldm_msg *msg,
252 				    size_t payload_length,
253 				    uint32_t *data_transfer_handle,
254 				    uint8_t *transfer_operation_flag);
255 
256 /** @brief Create a PLDM response message for GetFruRecordTable
257  *
258  *  @param[in] instance_id - Message's instance id
259  *  @param[in] completion_code - PLDM completion code
260  *  @param[in] next_data_transfer_handle - A handle that is used to identify the
261  *  next portion of the transfer
262  *  @param[in] transfer_flag - The transfer flag that indicates what part of the
263  *  transfer this response represents
264  *  @param[in,out] msg - Message will be written to this
265  *  @return pldm_completion_codes
266  *  @note  Caller is responsible for memory alloc and dealloc of param 'msg',
267  *         and for appending the FRU table to the msg.
268  */
269 int encode_get_fru_record_table_resp(uint8_t instance_id,
270 				     uint8_t completion_code,
271 				     uint32_t next_data_transfer_handle,
272 				     uint8_t transfer_flag,
273 				     struct pldm_msg *msg);
274 
275 /* GetFRURecordByOption */
276 
277 /** @brief Decode GetFRURecordByOption request data
278  *
279  *  @param[in] msg - PLDM request message payload
280  *  @param[in] payload_length - Length of request payload
281  *  @param[out] data_transfer_handle - A handle, used to identify a FRU Record
282  *              Table data transfer
283  *  @param[out] fru_table_handle - A handle, used to identify a FRU DATA
284  *              records
285  *  @param[out] record_set_identifier - FRU record set identifier
286  *  @param[out] record_type - FRU record type
287  *  @param[out] field_type - FRU field type
288  *  @param[out] transfer_op_flag - A flag that indicates whether this is
289  *              the start of the transfer
290  *  @return pldm_completion_codes
291  */
292 int decode_get_fru_record_by_option_req(
293 	const struct pldm_msg *msg, size_t payload_length,
294 	uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
295 	uint16_t *record_set_identifier, uint8_t *record_type,
296 	uint8_t *field_type, uint8_t *transfer_op_flag);
297 
298 /** @brief Encode GetFRURecordByOption response data
299  *
300  *  @param[in] instance_id - Message's instance id
301  *  @param[in] completion_code - PLDM completion code
302  *  @param[in] next_data_transfer_handle - A handle that is used to identify the
303  *             next portion of the transfer
304  *  @param[in] transfer_flag - The transfer flag that indicates what part of the
305  *             transfer this response represents
306  *  @param[in] fru_structure_data - FRU Structure Data
307  *  @param[in] data_size - Size of FRU Structure Data
308  *  @param[in,out] msg - Message will be written to this
309  *  @return pldm_completion_codes
310  *  @note  Caller is responsible for memory alloc and dealloc of param 'msg',
311  *         and for appending the FRU table to the msg.
312  */
313 int encode_get_fru_record_by_option_resp(uint8_t instance_id,
314 					 uint8_t completion_code,
315 					 uint32_t next_data_transfer_handle,
316 					 uint8_t transfer_flag,
317 					 const void *fru_structure_data,
318 					 size_t data_size, struct pldm_msg *msg,
319 					 size_t payload_length);
320 
321 /* Requester */
322 
323 /* GetFruRecordTable */
324 
325 /** @brief Create a PLDM request message for GetFruRecordTable
326  *
327  *  @param[in] instance_id - Message's instance id
328  *  @param[in] data_transfer_handle - A handle, used to identify a FRU Record
329  *  Table data transfer
330  *  @param[in] transfer_operation_flag - A flag that indicates whether this is
331  *  the start of the transfer
332  *  @param[in,out] msg - Message will be written to this
333  *  @param[in] payload_length - Length of request message payload
334  *  @return pldm_completion_codes
335  *  @note  Caller is responsible for memory alloc and dealloc of param
336  *         'msg.payload'
337  */
338 
339 int encode_get_fru_record_table_req(uint8_t instance_id,
340 				    uint32_t data_transfer_handle,
341 				    uint8_t transfer_operation_flag,
342 				    struct pldm_msg *msg,
343 				    size_t payload_length);
344 
345 /** @brief Decode GetFruRecordTable response data
346  *
347  *  @param[in] msg - Response message
348  *  @param[in] payload_length - Length of response message payload
349  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
350  *  @param[out] next_data_transfer_handle - A handle used to identify the next
351  *  portion of the transfer
352  *  @param[out] transfer_flag - The transfer flag that indicates what part of
353  * the transfer this response represents
354  *  @param[out] fru_record_table_data - This data is a portion of the overall
355  * FRU Record Table
356  *  @param[out] fru_record_table_length - Length of the FRU record table data
357  *  @return pldm_completion_codes
358  */
359 
360 int decode_get_fru_record_table_resp(const struct pldm_msg *msg,
361 				     size_t payload_length,
362 				     uint8_t *completion_code,
363 				     uint32_t *next_data_transfer_handle,
364 				     uint8_t *transfer_flag,
365 				     uint8_t *fru_record_table_data,
366 				     size_t *fru_record_table_length);
367 
368 /** @brief Decode GetFruRecordTable response data, ensuring that the fru
369  *         record table section is small enough to fit in the provided buffer.
370  *
371  *  @param[in] msg - Response message
372  *  @param[in] payload_length - Length of response message payload
373  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
374  *  @param[out] next_data_transfer_handle - A handle used to identify the next
375  *  portion of the transfer
376  *  @param[out] transfer_flag - The transfer flag that indicates what part of
377  * the transfer this response represents
378  *  @param[out] fru_record_table_data - This data is a portion of the overall
379  * FRU Record Table
380  *  @param[out] fru_record_table_length - Length of the FRU record table data
381  *  @param[in] max_fru_record_table_length - Maximum length of the FRU record
382  * table data. If the response contains more data than this,
383  * return PLDM_ERROR_INVALID_LENGTH.
384  *  @return pldm_completion_codes
385  */
386 
387 int decode_get_fru_record_table_resp_safe(
388 	const struct pldm_msg *msg, size_t payload_length,
389 	uint8_t *completion_code, uint32_t *next_data_transfer_handle,
390 	uint8_t *transfer_flag, uint8_t *fru_record_table_data,
391 	size_t *fru_record_table_length, size_t max_fru_record_table_length);
392 
393 /** @brief Encode the FRU record in the FRU table
394  *
395  *  @param[in/out] fru_table - Pointer to the FRU table
396  *  @param[in] total_size - The size of the table,including the size of FRU
397  *                          record to be added to the table.
398  *  @param[in/out] curr_size - The size of the table, excluding the size of FRU
399  *                          record to be added to the table.
400  *  @param[in] record_set_id - FRU record set identifier
401  *  @param[in] record_type - FRU record type
402  *  @param[in] num_frus - Number of FRU fields
403  *  @param[in] encoding - Encoding type for FRU fields
404  *  @param[in] tlvs - Pointer to the buffer with all the FRU fields
405  *  @param[in] tlvs_size - Size of the  buffer with all the FRU fields
406  *
407  *  @return pldm_completion_codes
408  */
409 int encode_fru_record(uint8_t *fru_table, size_t total_size, size_t *curr_size,
410 		      uint16_t record_set_id, uint8_t record_type,
411 		      uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
412 		      size_t tlvs_size);
413 
414 /* GetFRURecordByOption */
415 
416 /** @brief Create a PLDM request message for GetFRURecordByOption
417  *
418  *  @param[in] instance_id - Message's instance id
419  *  @param[in] data_transfer_handle - A handle, used to identify a FRU Record
420  *             Table data transfer
421  *  @param[in] fru_table_handle - A handle, used to identify a FRU DATA records
422  *  @param[in] record_set_identifier - FRU record set identifier
423  *  @param[in] record_type - FRU record type
424  *  @param[in] field_type - FRU field type
425  *  @param[in] transfer_op_flag - A flag that indicates whether this is
426  *             the start of the transfer
427  *  @param[in,out] msg - Message will be written to this
428  *  @param[in] payload_length - Length of request message payload
429  *  @return pldm_completion_codes
430  *  @note  Caller is responsible for memory alloc and dealloc of param
431  *         'msg.payload'
432  */
433 int encode_get_fru_record_by_option_req(
434 	uint8_t instance_id, uint32_t data_transfer_handle,
435 	uint16_t fru_table_handle, uint16_t record_set_identifier,
436 	uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
437 	struct pldm_msg *msg, size_t payload_length);
438 
439 /** @brief Decode GetFRURecordByOption response data
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] next_data_transfer_handle - A handle used to identify the next
445  *              portion of the transfer
446  *  @param[out] transfer_flag - The transfer flag that indicates what part of
447  *              the transfer this response represents
448  *  @param[out] fru_structure_data - FRU Structure Data
449  *  @return pldm_completion_codes
450  */
451 int decode_get_fru_record_by_option_resp(
452 	const struct pldm_msg *msg, size_t payload_length,
453 	uint8_t *completion_code, uint32_t *next_transfer_handle,
454 	uint8_t *transfer_flag, struct variable_field *fru_structure_data);
455 
456 /** @brief Get FRU Record Table By Option or return an error
457  *  @param[in] table - The source fru record table
458  *  @param[in] table_size - Size of the source fru record table
459  *  @param[out] record_table - Fru table fetched based on the input option
460  *  @param[in/out] record_size - Size of the table fetched by fru record option
461  *  @param[in] rsi - FRU record set identifier
462  *  @param[in] rt - FRU record type
463  *  @param[in] ft - FRU field type
464  *
465  *  @return PLDM_SUCCESS if no error occurs. PLDM_ERROR_INVALID_LENGTH if record_size lacks capacity
466  *  	    to encode the relevant records.
467  */
468 int get_fru_record_by_option(const uint8_t *table, size_t table_size,
469 			     uint8_t *record_table, size_t *record_size,
470 			     uint16_t rsi, uint8_t rt, uint8_t ft);
471 int get_fru_record_by_option_check(const uint8_t *table, size_t table_size,
472 				   uint8_t *record_table, size_t *record_size,
473 				   uint16_t rsi, uint8_t rt, uint8_t ft);
474 
475 /* SetFruRecordTable */
476 
477 /** @brief Decode SetFruRecordTable request data
478  *
479  *  @param[in] msg - PLDM request message payload
480  *  @param[in] payload_length - Length of request payload
481  *  @param[out] data_transfer_handle - A handle used to identify a FRU Record
482  *                                     table data transfer
483  *  @param[out] transfer_flag - Flag to indicate what part of the transfer
484  *                              this request represents
485  *  @param[out] fru_table_data - Struct variable_field, contains data specific
486  *                               to the fru record table and the length of table
487  *                               data
488  *  @return pldm_completion_codes
489  */
490 int decode_set_fru_record_table_req(const struct pldm_msg *msg,
491 				    size_t payload_length,
492 				    uint32_t *data_transfer_handle,
493 				    uint8_t *transfer_flag,
494 				    struct variable_field *fru_table_data);
495 
496 /** @brief Create a PLDM response message for SetFruRecordTable
497  *
498  *  @param[in] instance_id - Message's instance id
499  *  @param[in] completion_code - PLDM completion code
500  *  @param[in] next_transfer_handle - handle to identify the next portion of the
501  *                                    transfer
502  *  @param[in] payload_length - Length of payload message
503  *  @param[out] msg - Argument to capture the Message
504  */
505 int encode_set_fru_record_table_resp(uint8_t instance_id,
506 				     uint8_t completion_code,
507 				     uint32_t next_data_transfer_handle,
508 				     size_t payload_length,
509 				     struct pldm_msg *msg);
510 
511 #ifdef __cplusplus
512 }
513 #endif
514 
515 #endif
516