blob: 7d1906c25bc5d3c00a11764c8db154bb91e7ffd8 [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jefferyb0c1d202023-11-07 22:08:44 +10302#include <libpldm/base.h>
3#include <libpldm/fru.h>
4#include <libpldm/utils.h>
5
Andrew Jeffery9c766792022-08-10 23:12:49 +09306#include <assert.h>
7#include <endian.h>
8#include <stdbool.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include <stdint.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +093010#include <string.h>
11
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093012LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093013int 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
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093025 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +093026 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
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093034LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093035int decode_get_fru_record_table_metadata_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093036 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)
Andrew Jeffery9c766792022-08-10 23:12:49 +093041{
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 =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093060 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +093061
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 =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093067 le16toh(response->total_record_set_identifiers);
Andrew Jeffery9c766792022-08-10 23:12:49 +093068 *total_table_records = le16toh(response->total_table_records);
69 *checksum = le32toh(response->checksum);
70
71 return PLDM_SUCCESS;
72}
73
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093074LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093075int encode_get_fru_record_table_metadata_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093076 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)
Andrew Jeffery9c766792022-08-10 23:12:49 +093081{
82 if (msg == NULL) {
83 return PLDM_ERROR_INVALID_DATA;
84 }
85
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093086 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +093087 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 =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093098 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +093099 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 =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930104 htole32(fru_table_maximum_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930105 response->fru_table_length = htole32(fru_table_length);
106 response->total_record_set_identifiers =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930107 htole16(total_record_set_identifiers);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930108 response->total_table_records = htole16(total_table_records);
109 response->checksum = htole32(checksum);
110 }
111
112 return PLDM_SUCCESS;
113}
114
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930115LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930116int 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 =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930131 (struct pldm_get_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930132
133 *data_transfer_handle = le32toh(req->data_transfer_handle);
134 *transfer_operation_flag = req->transfer_operation_flag;
135
136 return PLDM_SUCCESS;
137}
138
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930139LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930140int 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
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930150 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930151 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 =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930162 (struct pldm_get_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930163
164 resp->completion_code = completion_code;
165
166 if (resp->completion_code == PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930167 resp->next_data_transfer_handle =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930168 htole32(next_data_transfer_handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930169 resp->transfer_flag = transfer_flag;
170 }
171
172 return PLDM_SUCCESS;
173}
174
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930175LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930176int 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 if ((*curr_size + record_hdr_size + tlvs_size) != total_size) {
188 return PLDM_ERROR_INVALID_LENGTH;
189 }
190
191 struct pldm_fru_record_data_format *record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930192 (struct pldm_fru_record_data_format *)(fru_table + *curr_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930193 record->record_set_id = htole16(record_set_id);
194 record->record_type = record_type;
195 record->num_fru_fields = num_frus;
196 record->encoding_type = encoding;
197 *curr_size += record_hdr_size;
198
199 if (tlvs) {
200 memcpy(fru_table + *curr_size, tlvs, tlvs_size);
201 *curr_size += tlvs_size;
202 }
203
204 return PLDM_SUCCESS;
205}
206
207static bool is_table_end(const struct pldm_fru_record_data_format *p,
208 const void *table, size_t table_size)
209{
Andrew Jefferya26f2272023-07-14 11:01:43 +0930210 return p >=
Andrew Jeffery9c766792022-08-10 23:12:49 +0930211 (const struct pldm_fru_record_data_format *)((uint8_t *)table +
212 table_size);
213}
214
Andrew Jeffery962fcec2023-07-07 10:10:19 +0930215LIBPLDM_ABI_STABLE
Andrew Jefferyd9b70ba2024-06-08 22:14:49 +0930216int get_fru_record_by_option(const uint8_t *table, size_t table_size,
217 uint8_t *record_table, size_t *record_size,
218 uint16_t rsi, uint8_t rt, uint8_t ft)
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930219{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930220 const struct pldm_fru_record_data_format *record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930221 (const struct pldm_fru_record_data_format *)table;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930222 struct pldm_fru_record_data_format *record_data_dest;
223 int count = 0;
224
225 const struct pldm_fru_record_tlv *tlv;
226 size_t len;
227 uint8_t *pos = record_table;
228
229 while (!is_table_end(record_data_src, table, table_size)) {
230 if ((record_data_src->record_set_id != htole16(rsi) &&
231 rsi != 0) ||
232 (record_data_src->record_type != rt && rt != 0)) {
233 tlv = record_data_src->tlvs;
234 for (int i = 0; i < record_data_src->num_fru_fields;
235 i++) {
236 len = sizeof(*tlv) - 1 + tlv->length;
237 tlv = (const struct pldm_fru_record_tlv
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930238 *)((char *)tlv + len);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930239 }
240 record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930241 (const struct pldm_fru_record_data_format
242 *)(tlv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930243 continue;
244 }
245
246 len = sizeof(struct pldm_fru_record_data_format) -
247 sizeof(struct pldm_fru_record_tlv);
248
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930249 if (pos - record_table + len >= *record_size) {
250 return PLDM_ERROR_INVALID_LENGTH;
251 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930252 memcpy(pos, record_data_src, len);
253
254 record_data_dest = (struct pldm_fru_record_data_format *)pos;
255 pos += len;
256
257 tlv = record_data_src->tlvs;
258 count = 0;
259 for (int i = 0; i < record_data_src->num_fru_fields; i++) {
260 len = sizeof(*tlv) - 1 + tlv->length;
261 if (tlv->type == ft || ft == 0) {
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930262 if (pos - record_table + len >= *record_size) {
263 return PLDM_ERROR_INVALID_LENGTH;
264 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930265 memcpy(pos, tlv, len);
266 pos += len;
267 count++;
268 }
269 tlv = (const struct pldm_fru_record_tlv *)((char *)tlv +
270 len);
271 }
272 record_data_dest->num_fru_fields = count;
273 record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930274 (const struct pldm_fru_record_data_format *)(tlv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930275 }
276
277 *record_size = pos - record_table;
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930278
279 return PLDM_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930280}
281
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930282LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930283int encode_get_fru_record_by_option_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930284 uint8_t instance_id, uint32_t data_transfer_handle,
285 uint16_t fru_table_handle, uint16_t record_set_identifier,
286 uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
287 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930288{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930289 if (msg == NULL) {
290 return PLDM_ERROR_INVALID_DATA;
291 }
292
293 if (payload_length !=
294 sizeof(struct pldm_get_fru_record_by_option_req)) {
295 return PLDM_ERROR_INVALID_LENGTH;
296 }
297
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930298 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930299 header.instance = instance_id;
300 header.msg_type = PLDM_REQUEST;
301 header.pldm_type = PLDM_FRU;
302 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
303 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
304 if (rc != PLDM_SUCCESS) {
305 return rc;
306 }
307
308 struct pldm_get_fru_record_by_option_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930309 (struct pldm_get_fru_record_by_option_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930310
311 req->data_transfer_handle = htole32(data_transfer_handle);
312 req->fru_table_handle = htole16(fru_table_handle);
313 req->record_set_identifier = htole16(record_set_identifier);
314 req->record_type = record_type;
315 req->field_type = field_type;
316 req->transfer_op_flag = transfer_op_flag;
317
318 return PLDM_SUCCESS;
319}
320
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930321LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930322int decode_get_fru_record_by_option_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930323 const struct pldm_msg *msg, size_t payload_length,
324 uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
325 uint16_t *record_set_identifier, uint8_t *record_type,
326 uint8_t *field_type, uint8_t *transfer_op_flag)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930327{
328 if (msg == NULL || data_transfer_handle == NULL ||
329 fru_table_handle == NULL || record_set_identifier == NULL ||
330 record_type == NULL || field_type == NULL ||
331 transfer_op_flag == NULL) {
332 return PLDM_ERROR_INVALID_DATA;
333 }
334
335 if (payload_length !=
336 sizeof(struct pldm_get_fru_record_by_option_req)) {
337 return PLDM_ERROR_INVALID_LENGTH;
338 }
339
340 struct pldm_get_fru_record_by_option_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930341 (struct pldm_get_fru_record_by_option_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930342
343 *data_transfer_handle = le32toh(req->data_transfer_handle);
344 *fru_table_handle = le16toh(req->fru_table_handle);
345 *record_set_identifier = le16toh(req->record_set_identifier);
346 *record_type = req->record_type;
347 *field_type = req->field_type;
348 *transfer_op_flag = req->transfer_op_flag;
349 return PLDM_SUCCESS;
350}
351
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930352LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930353int encode_get_fru_record_by_option_resp(uint8_t instance_id,
354 uint8_t completion_code,
355 uint32_t next_data_transfer_handle,
356 uint8_t transfer_flag,
357 const void *fru_structure_data,
358 size_t data_size, struct pldm_msg *msg,
359 size_t payload_length)
360{
361 if (msg == NULL || fru_structure_data == NULL) {
362 return PLDM_ERROR_INVALID_DATA;
363 }
364
Andrew Jeffery82c34812024-10-03 15:09:39 +0930365 if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
366 return PLDM_ERROR_INVALID_LENGTH;
367 }
368
369 if (payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES <
370 data_size) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930371 return PLDM_ERROR_INVALID_LENGTH;
372 }
373
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930374 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930375 header.instance = instance_id;
376 header.msg_type = PLDM_RESPONSE;
377 header.pldm_type = PLDM_FRU;
378 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
379 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
380 if (rc != PLDM_SUCCESS) {
381 return rc;
382 }
383
384 struct pldm_get_fru_record_by_option_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930385 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930386
387 resp->completion_code = completion_code;
388 resp->next_data_transfer_handle = htole32(next_data_transfer_handle);
389 resp->transfer_flag = transfer_flag;
390
391 if (completion_code == PLDM_SUCCESS) {
392 memcpy(resp->fru_structure_data, fru_structure_data, data_size);
393 }
394
395 return PLDM_SUCCESS;
396}
397
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930398LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930399int decode_get_fru_record_by_option_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930400 const struct pldm_msg *msg, size_t payload_length,
401 uint8_t *completion_code, uint32_t *next_transfer_handle,
402 uint8_t *transfer_flag, struct variable_field *fru_structure_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930403{
404 if (msg == NULL || completion_code == NULL ||
405 next_transfer_handle == NULL || transfer_flag == NULL ||
406 fru_structure_data == NULL) {
407 return PLDM_ERROR_INVALID_DATA;
408 }
409
410 *completion_code = msg->payload[0];
411 if (PLDM_SUCCESS != *completion_code) {
412 return PLDM_SUCCESS;
413 }
414
415 if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
416 return PLDM_ERROR_INVALID_LENGTH;
417 }
418
419 struct pldm_get_fru_record_by_option_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930420 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930421
422 *next_transfer_handle = le32toh(resp->next_data_transfer_handle);
423 *transfer_flag = resp->transfer_flag;
424 fru_structure_data->ptr = resp->fru_structure_data;
425 fru_structure_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930426 payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427
428 return PLDM_SUCCESS;
429}
430
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930431LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930432int encode_get_fru_record_table_req(uint8_t instance_id,
433 uint32_t data_transfer_handle,
434 uint8_t transfer_operation_flag,
435 struct pldm_msg *msg, size_t payload_length)
436
437{
438 if (msg == NULL) {
439 return PLDM_ERROR_INVALID_DATA;
440 }
441 if (payload_length != sizeof(struct pldm_get_fru_record_table_req)) {
442 return PLDM_ERROR_INVALID_LENGTH;
443 }
444
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930445 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930446 header.msg_type = PLDM_REQUEST;
447 header.instance = instance_id;
448 header.pldm_type = PLDM_FRU;
449 header.command = PLDM_GET_FRU_RECORD_TABLE;
450
451 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
452 if (rc != PLDM_SUCCESS) {
453 return rc;
454 }
455
456 struct pldm_get_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930457 (struct pldm_get_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930458 req->data_transfer_handle = htole32(data_transfer_handle);
459 req->transfer_operation_flag = transfer_operation_flag;
460
461 return PLDM_SUCCESS;
462}
463
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930464LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930465int decode_get_fru_record_table_resp_safe(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930466 const struct pldm_msg *msg, size_t payload_length,
467 uint8_t *completion_code, uint32_t *next_data_transfer_handle,
468 uint8_t *transfer_flag, uint8_t *fru_record_table_data,
469 size_t *fru_record_table_length, size_t max_fru_record_table_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930470{
471 if (msg == NULL || completion_code == NULL ||
472 next_data_transfer_handle == NULL || transfer_flag == NULL ||
473 fru_record_table_data == NULL || fru_record_table_length == NULL) {
474 return PLDM_ERROR_INVALID_DATA;
475 }
476
477 *completion_code = msg->payload[0];
478 if (PLDM_SUCCESS != *completion_code) {
479 return PLDM_SUCCESS;
480 }
481 if (payload_length <= PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES) {
482 return PLDM_ERROR_INVALID_LENGTH;
483 }
484
485 struct pldm_get_fru_record_table_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930486 (struct pldm_get_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930487
488 *next_data_transfer_handle = le32toh(resp->next_data_transfer_handle);
489 *transfer_flag = resp->transfer_flag;
490
491 *fru_record_table_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930492 payload_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930493
494 if (*fru_record_table_length > max_fru_record_table_length) {
495 return PLDM_ERROR_INVALID_LENGTH;
496 }
497
498 memcpy(fru_record_table_data, resp->fru_record_table_data,
499 *fru_record_table_length);
500
501 return PLDM_SUCCESS;
502}
503
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930504LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930505int decode_get_fru_record_table_resp(const struct pldm_msg *msg,
506 size_t payload_length,
507 uint8_t *completion_code,
508 uint32_t *next_data_transfer_handle,
509 uint8_t *transfer_flag,
510 uint8_t *fru_record_table_data,
511 size_t *fru_record_table_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930512{
513 return decode_get_fru_record_table_resp_safe(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930514 msg, payload_length, completion_code, next_data_transfer_handle,
515 transfer_flag, fru_record_table_data, fru_record_table_length,
516 (size_t)-1);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930517}
518
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930519LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930520int decode_set_fru_record_table_req(const struct pldm_msg *msg,
521 size_t payload_length,
522 uint32_t *data_transfer_handle,
523 uint8_t *transfer_flag,
524 struct variable_field *fru_table_data)
525
526{
527 if (msg == NULL || data_transfer_handle == NULL ||
528 transfer_flag == NULL || fru_table_data == NULL) {
529 return PLDM_ERROR_INVALID_DATA;
530 }
531
532 if (payload_length <= PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES) {
533 return PLDM_ERROR_INVALID_LENGTH;
534 }
535
536 struct pldm_set_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930537 (struct pldm_set_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930538
539 *data_transfer_handle = le32toh(req->data_transfer_handle);
540 *transfer_flag = req->transfer_flag;
541 fru_table_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930542 payload_length - PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930543 fru_table_data->ptr = req->fru_record_table_data;
544
545 return PLDM_SUCCESS;
546}
547
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930548LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930549int encode_set_fru_record_table_resp(uint8_t instance_id,
550 uint8_t completion_code,
551 uint32_t next_data_transfer_handle,
552 size_t payload_length,
553 struct pldm_msg *msg)
554{
555 if (msg == NULL) {
556 return PLDM_ERROR_INVALID_DATA;
557 }
558 if (payload_length != PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES) {
559 return PLDM_ERROR_INVALID_LENGTH;
560 }
561
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930562 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930563 header.instance = instance_id;
564 header.msg_type = PLDM_RESPONSE;
565 header.pldm_type = PLDM_FRU;
566 header.command = PLDM_SET_FRU_RECORD_TABLE;
567
568 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
569 if (PLDM_SUCCESS != rc) {
570 return rc;
571 }
572
573 struct pldm_set_fru_record_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930574 (struct pldm_set_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930575 response->completion_code = completion_code;
576 response->next_data_transfer_handle =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930577 htole32(next_data_transfer_handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930578
579 return PLDM_SUCCESS;
580}