1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #include <libpldm/base.h>
3 #include <libpldm/fru.h>
4 #include <libpldm/utils.h>
5
6 #include <assert.h>
7 #include <endian.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <string.h>
11
12 LIBPLDM_ABI_STABLE
encode_get_fru_record_table_metadata_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)13 int encode_get_fru_record_table_metadata_req(uint8_t instance_id,
14 struct pldm_msg *msg,
15 size_t payload_length)
16 {
17 if (msg == NULL) {
18 return PLDM_ERROR_INVALID_DATA;
19 }
20
21 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES) {
22 return PLDM_ERROR_INVALID_LENGTH;
23 }
24
25 struct pldm_header_info header = { 0 };
26 header.instance = instance_id;
27 header.msg_type = PLDM_REQUEST;
28 header.pldm_type = PLDM_FRU;
29 header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
30
31 return pack_pldm_header(&header, &(msg->hdr));
32 }
33
34 LIBPLDM_ABI_STABLE
decode_get_fru_record_table_metadata_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * fru_data_major_version,uint8_t * fru_data_minor_version,uint32_t * fru_table_maximum_size,uint32_t * fru_table_length,uint16_t * total_record_set_identifiers,uint16_t * total_table_records,uint32_t * checksum)35 int decode_get_fru_record_table_metadata_resp(
36 const struct pldm_msg *msg, size_t payload_length,
37 uint8_t *completion_code, uint8_t *fru_data_major_version,
38 uint8_t *fru_data_minor_version, uint32_t *fru_table_maximum_size,
39 uint32_t *fru_table_length, uint16_t *total_record_set_identifiers,
40 uint16_t *total_table_records, uint32_t *checksum)
41 {
42 if (msg == NULL || completion_code == NULL ||
43 fru_data_major_version == NULL || fru_data_minor_version == NULL ||
44 fru_table_maximum_size == NULL || fru_table_length == NULL ||
45 total_record_set_identifiers == NULL ||
46 total_table_records == NULL || checksum == NULL) {
47 return PLDM_ERROR_INVALID_DATA;
48 }
49
50 *completion_code = msg->payload[0];
51 if (PLDM_SUCCESS != *completion_code) {
52 return PLDM_SUCCESS;
53 }
54
55 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES) {
56 return PLDM_ERROR_INVALID_LENGTH;
57 }
58
59 struct pldm_get_fru_record_table_metadata_resp *response =
60 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
61
62 *fru_data_major_version = response->fru_data_major_version;
63 *fru_data_minor_version = response->fru_data_minor_version;
64 *fru_table_maximum_size = le32toh(response->fru_table_maximum_size);
65 *fru_table_length = le32toh(response->fru_table_length);
66 *total_record_set_identifiers =
67 le16toh(response->total_record_set_identifiers);
68 *total_table_records = le16toh(response->total_table_records);
69 *checksum = le32toh(response->checksum);
70
71 return PLDM_SUCCESS;
72 }
73
74 LIBPLDM_ABI_STABLE
encode_get_fru_record_table_metadata_resp(uint8_t instance_id,uint8_t completion_code,uint8_t fru_data_major_version,uint8_t fru_data_minor_version,uint32_t fru_table_maximum_size,uint32_t fru_table_length,uint16_t total_record_set_identifiers,uint16_t total_table_records,uint32_t checksum,struct pldm_msg * msg)75 int encode_get_fru_record_table_metadata_resp(
76 uint8_t instance_id, uint8_t completion_code,
77 uint8_t fru_data_major_version, uint8_t fru_data_minor_version,
78 uint32_t fru_table_maximum_size, uint32_t fru_table_length,
79 uint16_t total_record_set_identifiers, uint16_t total_table_records,
80 uint32_t checksum, struct pldm_msg *msg)
81 {
82 if (msg == NULL) {
83 return PLDM_ERROR_INVALID_DATA;
84 }
85
86 struct pldm_header_info header = { 0 };
87 header.msg_type = PLDM_RESPONSE;
88 header.instance = instance_id;
89 header.pldm_type = PLDM_FRU;
90 header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
91
92 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
93 if (PLDM_SUCCESS != rc) {
94 return rc;
95 }
96
97 struct pldm_get_fru_record_table_metadata_resp *response =
98 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
99 response->completion_code = completion_code;
100 if (response->completion_code == PLDM_SUCCESS) {
101 response->fru_data_major_version = fru_data_major_version;
102 response->fru_data_minor_version = fru_data_minor_version;
103 response->fru_table_maximum_size =
104 htole32(fru_table_maximum_size);
105 response->fru_table_length = htole32(fru_table_length);
106 response->total_record_set_identifiers =
107 htole16(total_record_set_identifiers);
108 response->total_table_records = htole16(total_table_records);
109 response->checksum = htole32(checksum);
110 }
111
112 return PLDM_SUCCESS;
113 }
114
115 LIBPLDM_ABI_STABLE
decode_get_fru_record_table_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * data_transfer_handle,uint8_t * transfer_operation_flag)116 int decode_get_fru_record_table_req(const struct pldm_msg *msg,
117 size_t payload_length,
118 uint32_t *data_transfer_handle,
119 uint8_t *transfer_operation_flag)
120 {
121 if (msg == NULL || data_transfer_handle == NULL ||
122 transfer_operation_flag == NULL) {
123 return PLDM_ERROR_INVALID_DATA;
124 }
125
126 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES) {
127 return PLDM_ERROR_INVALID_LENGTH;
128 }
129
130 struct pldm_get_fru_record_table_req *req =
131 (struct pldm_get_fru_record_table_req *)msg->payload;
132
133 *data_transfer_handle = le32toh(req->data_transfer_handle);
134 *transfer_operation_flag = req->transfer_operation_flag;
135
136 return PLDM_SUCCESS;
137 }
138
139 LIBPLDM_ABI_STABLE
encode_get_fru_record_table_resp(uint8_t instance_id,uint8_t completion_code,uint32_t next_data_transfer_handle,uint8_t transfer_flag,struct pldm_msg * msg)140 int encode_get_fru_record_table_resp(uint8_t instance_id,
141 uint8_t completion_code,
142 uint32_t next_data_transfer_handle,
143 uint8_t transfer_flag,
144 struct pldm_msg *msg)
145 {
146 if (msg == NULL) {
147 return PLDM_ERROR_INVALID_DATA;
148 }
149
150 struct pldm_header_info header = { 0 };
151 header.msg_type = PLDM_RESPONSE;
152 header.instance = instance_id;
153 header.pldm_type = PLDM_FRU;
154 header.command = PLDM_GET_FRU_RECORD_TABLE;
155
156 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
157 if (rc > PLDM_SUCCESS) {
158 return rc;
159 }
160
161 struct pldm_get_fru_record_table_resp *resp =
162 (struct pldm_get_fru_record_table_resp *)msg->payload;
163
164 resp->completion_code = completion_code;
165
166 if (resp->completion_code == PLDM_SUCCESS) {
167 resp->next_data_transfer_handle =
168 htole32(next_data_transfer_handle);
169 resp->transfer_flag = transfer_flag;
170 }
171
172 return PLDM_SUCCESS;
173 }
174
175 LIBPLDM_ABI_DEPRECATED_UNSAFE
encode_fru_record(uint8_t * fru_table,size_t total_size,size_t * curr_size,uint16_t record_set_id,uint8_t record_type,uint8_t num_frus,uint8_t encoding,uint8_t * tlvs,size_t tlvs_size)176 int encode_fru_record(uint8_t *fru_table, size_t total_size, size_t *curr_size,
177 uint16_t record_set_id, uint8_t record_type,
178 uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
179 size_t tlvs_size)
180 {
181 size_t record_hdr_size = sizeof(struct pldm_fru_record_data_format) -
182 sizeof(struct pldm_fru_record_tlv);
183
184 if (fru_table == NULL || curr_size == NULL || !tlvs_size) {
185 return PLDM_ERROR_INVALID_DATA;
186 }
187
188 if (SIZE_MAX - *curr_size < record_hdr_size) {
189 return PLDM_ERROR_INVALID_LENGTH;
190 }
191
192 if (SIZE_MAX - (*curr_size + record_hdr_size) < tlvs_size) {
193 return PLDM_ERROR_INVALID_LENGTH;
194 }
195
196 if (total_size < *curr_size + record_hdr_size) {
197 return PLDM_ERROR_INVALID_LENGTH;
198 }
199
200 if (total_size - (*curr_size + record_hdr_size) < tlvs_size) {
201 return PLDM_ERROR_INVALID_LENGTH;
202 }
203
204 struct pldm_fru_record_data_format *record =
205 (struct pldm_fru_record_data_format *)(fru_table + *curr_size);
206 record->record_set_id = htole16(record_set_id);
207 record->record_type = record_type;
208 record->num_fru_fields = num_frus;
209 record->encoding_type = encoding;
210 *curr_size += record_hdr_size;
211
212 if (tlvs) {
213 memcpy(fru_table + *curr_size, tlvs, tlvs_size);
214 *curr_size += tlvs_size;
215 }
216
217 return PLDM_SUCCESS;
218 }
219
is_table_end(const struct pldm_fru_record_data_format * p,const void * table,size_t table_size)220 static bool is_table_end(const struct pldm_fru_record_data_format *p,
221 const void *table, size_t table_size)
222 {
223 return p >=
224 (const struct pldm_fru_record_data_format *)((uint8_t *)table +
225 table_size);
226 }
227
228 LIBPLDM_ABI_STABLE
get_fru_record_by_option(const uint8_t * table,size_t table_size,uint8_t * record_table,size_t * record_size,uint16_t rsi,uint8_t rt,uint8_t ft)229 int get_fru_record_by_option(const uint8_t *table, size_t table_size,
230 uint8_t *record_table, size_t *record_size,
231 uint16_t rsi, uint8_t rt, uint8_t ft)
232 {
233 const struct pldm_fru_record_data_format *record_data_src =
234 (const struct pldm_fru_record_data_format *)table;
235 struct pldm_fru_record_data_format *record_data_dest;
236 int count = 0;
237
238 const struct pldm_fru_record_tlv *tlv;
239 size_t len;
240 uint8_t *pos = record_table;
241
242 while (!is_table_end(record_data_src, table, table_size)) {
243 if ((record_data_src->record_set_id != htole16(rsi) &&
244 rsi != 0) ||
245 (record_data_src->record_type != rt && rt != 0)) {
246 tlv = record_data_src->tlvs;
247 for (int i = 0; i < record_data_src->num_fru_fields;
248 i++) {
249 len = sizeof(*tlv) - 1 + tlv->length;
250 tlv = (const struct pldm_fru_record_tlv
251 *)((char *)tlv + len);
252 }
253 record_data_src =
254 (const struct pldm_fru_record_data_format
255 *)(tlv);
256 continue;
257 }
258
259 len = sizeof(struct pldm_fru_record_data_format) -
260 sizeof(struct pldm_fru_record_tlv);
261
262 if (pos - record_table + len >= *record_size) {
263 return PLDM_ERROR_INVALID_LENGTH;
264 }
265 memcpy(pos, record_data_src, len);
266
267 record_data_dest = (struct pldm_fru_record_data_format *)pos;
268 pos += len;
269
270 tlv = record_data_src->tlvs;
271 count = 0;
272 for (int i = 0; i < record_data_src->num_fru_fields; i++) {
273 len = sizeof(*tlv) - 1 + tlv->length;
274 if (tlv->type == ft || ft == 0) {
275 if (pos - record_table + len >= *record_size) {
276 return PLDM_ERROR_INVALID_LENGTH;
277 }
278 memcpy(pos, tlv, len);
279 pos += len;
280 count++;
281 }
282 tlv = (const struct pldm_fru_record_tlv *)((char *)tlv +
283 len);
284 }
285 record_data_dest->num_fru_fields = count;
286 record_data_src =
287 (const struct pldm_fru_record_data_format *)(tlv);
288 }
289
290 *record_size = pos - record_table;
291
292 return PLDM_SUCCESS;
293 }
294
295 LIBPLDM_ABI_STABLE
encode_get_fru_record_by_option_req(uint8_t instance_id,uint32_t data_transfer_handle,uint16_t fru_table_handle,uint16_t record_set_identifier,uint8_t record_type,uint8_t field_type,uint8_t transfer_op_flag,struct pldm_msg * msg,size_t payload_length)296 int encode_get_fru_record_by_option_req(
297 uint8_t instance_id, uint32_t data_transfer_handle,
298 uint16_t fru_table_handle, uint16_t record_set_identifier,
299 uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
300 struct pldm_msg *msg, size_t payload_length)
301 {
302 if (msg == NULL) {
303 return PLDM_ERROR_INVALID_DATA;
304 }
305
306 if (payload_length !=
307 sizeof(struct pldm_get_fru_record_by_option_req)) {
308 return PLDM_ERROR_INVALID_LENGTH;
309 }
310
311 struct pldm_header_info header = { 0 };
312 header.instance = instance_id;
313 header.msg_type = PLDM_REQUEST;
314 header.pldm_type = PLDM_FRU;
315 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
316 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
317 if (rc != PLDM_SUCCESS) {
318 return rc;
319 }
320
321 struct pldm_get_fru_record_by_option_req *req =
322 (struct pldm_get_fru_record_by_option_req *)msg->payload;
323
324 req->data_transfer_handle = htole32(data_transfer_handle);
325 req->fru_table_handle = htole16(fru_table_handle);
326 req->record_set_identifier = htole16(record_set_identifier);
327 req->record_type = record_type;
328 req->field_type = field_type;
329 req->transfer_op_flag = transfer_op_flag;
330
331 return PLDM_SUCCESS;
332 }
333
334 LIBPLDM_ABI_STABLE
decode_get_fru_record_by_option_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * data_transfer_handle,uint16_t * fru_table_handle,uint16_t * record_set_identifier,uint8_t * record_type,uint8_t * field_type,uint8_t * transfer_op_flag)335 int decode_get_fru_record_by_option_req(
336 const struct pldm_msg *msg, size_t payload_length,
337 uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
338 uint16_t *record_set_identifier, uint8_t *record_type,
339 uint8_t *field_type, uint8_t *transfer_op_flag)
340 {
341 if (msg == NULL || data_transfer_handle == NULL ||
342 fru_table_handle == NULL || record_set_identifier == NULL ||
343 record_type == NULL || field_type == NULL ||
344 transfer_op_flag == NULL) {
345 return PLDM_ERROR_INVALID_DATA;
346 }
347
348 if (payload_length !=
349 sizeof(struct pldm_get_fru_record_by_option_req)) {
350 return PLDM_ERROR_INVALID_LENGTH;
351 }
352
353 struct pldm_get_fru_record_by_option_req *req =
354 (struct pldm_get_fru_record_by_option_req *)msg->payload;
355
356 *data_transfer_handle = le32toh(req->data_transfer_handle);
357 *fru_table_handle = le16toh(req->fru_table_handle);
358 *record_set_identifier = le16toh(req->record_set_identifier);
359 *record_type = req->record_type;
360 *field_type = req->field_type;
361 *transfer_op_flag = req->transfer_op_flag;
362 return PLDM_SUCCESS;
363 }
364
365 LIBPLDM_ABI_STABLE
encode_get_fru_record_by_option_resp(uint8_t instance_id,uint8_t completion_code,uint32_t next_data_transfer_handle,uint8_t transfer_flag,const void * fru_structure_data,size_t data_size,struct pldm_msg * msg,size_t payload_length)366 int encode_get_fru_record_by_option_resp(uint8_t instance_id,
367 uint8_t completion_code,
368 uint32_t next_data_transfer_handle,
369 uint8_t transfer_flag,
370 const void *fru_structure_data,
371 size_t data_size, struct pldm_msg *msg,
372 size_t payload_length)
373 {
374 if (msg == NULL || fru_structure_data == NULL) {
375 return PLDM_ERROR_INVALID_DATA;
376 }
377
378 if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
379 return PLDM_ERROR_INVALID_LENGTH;
380 }
381
382 if (payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES <
383 data_size) {
384 return PLDM_ERROR_INVALID_LENGTH;
385 }
386
387 struct pldm_header_info header = { 0 };
388 header.instance = instance_id;
389 header.msg_type = PLDM_RESPONSE;
390 header.pldm_type = PLDM_FRU;
391 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
392 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
393 if (rc != PLDM_SUCCESS) {
394 return rc;
395 }
396
397 struct pldm_get_fru_record_by_option_resp *resp =
398 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
399
400 resp->completion_code = completion_code;
401 resp->next_data_transfer_handle = htole32(next_data_transfer_handle);
402 resp->transfer_flag = transfer_flag;
403
404 if (completion_code == PLDM_SUCCESS) {
405 memcpy(resp->fru_structure_data, fru_structure_data, data_size);
406 }
407
408 return PLDM_SUCCESS;
409 }
410
411 LIBPLDM_ABI_STABLE
decode_get_fru_record_by_option_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * next_transfer_handle,uint8_t * transfer_flag,struct variable_field * fru_structure_data)412 int decode_get_fru_record_by_option_resp(
413 const struct pldm_msg *msg, size_t payload_length,
414 uint8_t *completion_code, uint32_t *next_transfer_handle,
415 uint8_t *transfer_flag, struct variable_field *fru_structure_data)
416 {
417 if (msg == NULL || completion_code == NULL ||
418 next_transfer_handle == NULL || transfer_flag == NULL ||
419 fru_structure_data == NULL) {
420 return PLDM_ERROR_INVALID_DATA;
421 }
422
423 *completion_code = msg->payload[0];
424 if (PLDM_SUCCESS != *completion_code) {
425 return PLDM_SUCCESS;
426 }
427
428 if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
429 return PLDM_ERROR_INVALID_LENGTH;
430 }
431
432 struct pldm_get_fru_record_by_option_resp *resp =
433 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
434
435 *next_transfer_handle = le32toh(resp->next_data_transfer_handle);
436 *transfer_flag = resp->transfer_flag;
437 fru_structure_data->ptr = resp->fru_structure_data;
438 fru_structure_data->length =
439 payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES;
440
441 return PLDM_SUCCESS;
442 }
443
444 LIBPLDM_ABI_STABLE
encode_get_fru_record_table_req(uint8_t instance_id,uint32_t data_transfer_handle,uint8_t transfer_operation_flag,struct pldm_msg * msg,size_t payload_length)445 int encode_get_fru_record_table_req(uint8_t instance_id,
446 uint32_t data_transfer_handle,
447 uint8_t transfer_operation_flag,
448 struct pldm_msg *msg, size_t payload_length)
449
450 {
451 if (msg == NULL) {
452 return PLDM_ERROR_INVALID_DATA;
453 }
454 if (payload_length != sizeof(struct pldm_get_fru_record_table_req)) {
455 return PLDM_ERROR_INVALID_LENGTH;
456 }
457
458 struct pldm_header_info header = { 0 };
459 header.msg_type = PLDM_REQUEST;
460 header.instance = instance_id;
461 header.pldm_type = PLDM_FRU;
462 header.command = PLDM_GET_FRU_RECORD_TABLE;
463
464 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
465 if (rc != PLDM_SUCCESS) {
466 return rc;
467 }
468
469 struct pldm_get_fru_record_table_req *req =
470 (struct pldm_get_fru_record_table_req *)msg->payload;
471 req->data_transfer_handle = htole32(data_transfer_handle);
472 req->transfer_operation_flag = transfer_operation_flag;
473
474 return PLDM_SUCCESS;
475 }
476
477 LIBPLDM_ABI_STABLE
decode_get_fru_record_table_resp_safe(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * next_data_transfer_handle,uint8_t * transfer_flag,uint8_t * fru_record_table_data,size_t * fru_record_table_length,size_t max_fru_record_table_length)478 int decode_get_fru_record_table_resp_safe(
479 const struct pldm_msg *msg, size_t payload_length,
480 uint8_t *completion_code, uint32_t *next_data_transfer_handle,
481 uint8_t *transfer_flag, uint8_t *fru_record_table_data,
482 size_t *fru_record_table_length, size_t max_fru_record_table_length)
483 {
484 if (msg == NULL || completion_code == NULL ||
485 next_data_transfer_handle == NULL || transfer_flag == NULL ||
486 fru_record_table_data == NULL || fru_record_table_length == NULL) {
487 return PLDM_ERROR_INVALID_DATA;
488 }
489
490 *completion_code = msg->payload[0];
491 if (PLDM_SUCCESS != *completion_code) {
492 return PLDM_SUCCESS;
493 }
494 if (payload_length <= PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES) {
495 return PLDM_ERROR_INVALID_LENGTH;
496 }
497
498 struct pldm_get_fru_record_table_resp *resp =
499 (struct pldm_get_fru_record_table_resp *)msg->payload;
500
501 *next_data_transfer_handle = le32toh(resp->next_data_transfer_handle);
502 *transfer_flag = resp->transfer_flag;
503
504 *fru_record_table_length =
505 payload_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES;
506
507 if (*fru_record_table_length > max_fru_record_table_length) {
508 return PLDM_ERROR_INVALID_LENGTH;
509 }
510
511 memcpy(fru_record_table_data, resp->fru_record_table_data,
512 *fru_record_table_length);
513
514 return PLDM_SUCCESS;
515 }
516
517 LIBPLDM_ABI_STABLE
decode_get_fru_record_table_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * next_data_transfer_handle,uint8_t * transfer_flag,uint8_t * fru_record_table_data,size_t * fru_record_table_length)518 int decode_get_fru_record_table_resp(const struct pldm_msg *msg,
519 size_t payload_length,
520 uint8_t *completion_code,
521 uint32_t *next_data_transfer_handle,
522 uint8_t *transfer_flag,
523 uint8_t *fru_record_table_data,
524 size_t *fru_record_table_length)
525 {
526 return decode_get_fru_record_table_resp_safe(
527 msg, payload_length, completion_code, next_data_transfer_handle,
528 transfer_flag, fru_record_table_data, fru_record_table_length,
529 (size_t)-1);
530 }
531
532 LIBPLDM_ABI_STABLE
decode_set_fru_record_table_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * data_transfer_handle,uint8_t * transfer_flag,struct variable_field * fru_table_data)533 int decode_set_fru_record_table_req(const struct pldm_msg *msg,
534 size_t payload_length,
535 uint32_t *data_transfer_handle,
536 uint8_t *transfer_flag,
537 struct variable_field *fru_table_data)
538
539 {
540 if (msg == NULL || data_transfer_handle == NULL ||
541 transfer_flag == NULL || fru_table_data == NULL) {
542 return PLDM_ERROR_INVALID_DATA;
543 }
544
545 if (payload_length <= PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES) {
546 return PLDM_ERROR_INVALID_LENGTH;
547 }
548
549 struct pldm_set_fru_record_table_req *req =
550 (struct pldm_set_fru_record_table_req *)msg->payload;
551
552 *data_transfer_handle = le32toh(req->data_transfer_handle);
553 *transfer_flag = req->transfer_flag;
554 fru_table_data->length =
555 payload_length - PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES;
556 fru_table_data->ptr = req->fru_record_table_data;
557
558 return PLDM_SUCCESS;
559 }
560
561 LIBPLDM_ABI_STABLE
encode_set_fru_record_table_resp(uint8_t instance_id,uint8_t completion_code,uint32_t next_data_transfer_handle,size_t payload_length,struct pldm_msg * msg)562 int encode_set_fru_record_table_resp(uint8_t instance_id,
563 uint8_t completion_code,
564 uint32_t next_data_transfer_handle,
565 size_t payload_length,
566 struct pldm_msg *msg)
567 {
568 if (msg == NULL) {
569 return PLDM_ERROR_INVALID_DATA;
570 }
571 if (payload_length != PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES) {
572 return PLDM_ERROR_INVALID_LENGTH;
573 }
574
575 struct pldm_header_info header = { 0 };
576 header.instance = instance_id;
577 header.msg_type = PLDM_RESPONSE;
578 header.pldm_type = PLDM_FRU;
579 header.command = PLDM_SET_FRU_RECORD_TABLE;
580
581 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
582 if (PLDM_SUCCESS != rc) {
583 return rc;
584 }
585
586 struct pldm_set_fru_record_table_resp *response =
587 (struct pldm_set_fru_record_table_resp *)msg->payload;
588 response->completion_code = completion_code;
589 response->next_data_transfer_handle =
590 htole32(next_data_transfer_handle);
591
592 return PLDM_SUCCESS;
593 }
594