blob: de66074a3446f6ece9c79ad6a7ea49a9dcded085 [file] [log] [blame]
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301#include "config.h"
2
Andrew Jeffery9c766792022-08-10 23:12:49 +09303#include <assert.h>
4#include <endian.h>
5#include <stdbool.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05306#include <stdint.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09307#include <string.h>
8
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include "base.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +093010#include "fru.h"
Manojkiran Eda9a8e4972022-11-28 16:38:21 +053011#include "utils.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +093012
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093013LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093014int encode_get_fru_record_table_metadata_req(uint8_t instance_id,
15 struct pldm_msg *msg,
16 size_t payload_length)
17{
18 if (msg == NULL) {
19 return PLDM_ERROR_INVALID_DATA;
20 }
21
22 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES) {
23 return PLDM_ERROR_INVALID_LENGTH;
24 }
25
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093026 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +093027 header.instance = instance_id;
28 header.msg_type = PLDM_REQUEST;
29 header.pldm_type = PLDM_FRU;
30 header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
31
32 return pack_pldm_header(&header, &(msg->hdr));
33}
34
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093035LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093036int decode_get_fru_record_table_metadata_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093037 const struct pldm_msg *msg, size_t payload_length,
38 uint8_t *completion_code, uint8_t *fru_data_major_version,
39 uint8_t *fru_data_minor_version, uint32_t *fru_table_maximum_size,
40 uint32_t *fru_table_length, uint16_t *total_record_set_identifiers,
41 uint16_t *total_table_records, uint32_t *checksum)
Andrew Jeffery9c766792022-08-10 23:12:49 +093042{
43 if (msg == NULL || completion_code == NULL ||
44 fru_data_major_version == NULL || fru_data_minor_version == NULL ||
45 fru_table_maximum_size == NULL || fru_table_length == NULL ||
46 total_record_set_identifiers == NULL ||
47 total_table_records == NULL || checksum == NULL) {
48 return PLDM_ERROR_INVALID_DATA;
49 }
50
51 *completion_code = msg->payload[0];
52 if (PLDM_SUCCESS != *completion_code) {
53 return PLDM_SUCCESS;
54 }
55
56 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES) {
57 return PLDM_ERROR_INVALID_LENGTH;
58 }
59
60 struct pldm_get_fru_record_table_metadata_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093061 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +093062
63 *fru_data_major_version = response->fru_data_major_version;
64 *fru_data_minor_version = response->fru_data_minor_version;
65 *fru_table_maximum_size = le32toh(response->fru_table_maximum_size);
66 *fru_table_length = le32toh(response->fru_table_length);
67 *total_record_set_identifiers =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093068 le16toh(response->total_record_set_identifiers);
Andrew Jeffery9c766792022-08-10 23:12:49 +093069 *total_table_records = le16toh(response->total_table_records);
70 *checksum = le32toh(response->checksum);
71
72 return PLDM_SUCCESS;
73}
74
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093075LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093076int encode_get_fru_record_table_metadata_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093077 uint8_t instance_id, uint8_t completion_code,
78 uint8_t fru_data_major_version, uint8_t fru_data_minor_version,
79 uint32_t fru_table_maximum_size, uint32_t fru_table_length,
80 uint16_t total_record_set_identifiers, uint16_t total_table_records,
81 uint32_t checksum, struct pldm_msg *msg)
Andrew Jeffery9c766792022-08-10 23:12:49 +093082{
83 if (msg == NULL) {
84 return PLDM_ERROR_INVALID_DATA;
85 }
86
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093087 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +093088 header.msg_type = PLDM_RESPONSE;
89 header.instance = instance_id;
90 header.pldm_type = PLDM_FRU;
91 header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
92
93 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
94 if (PLDM_SUCCESS != rc) {
95 return rc;
96 }
97
98 struct pldm_get_fru_record_table_metadata_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093099 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930100 response->completion_code = completion_code;
101 if (response->completion_code == PLDM_SUCCESS) {
102 response->fru_data_major_version = fru_data_major_version;
103 response->fru_data_minor_version = fru_data_minor_version;
104 response->fru_table_maximum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930105 htole32(fru_table_maximum_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930106 response->fru_table_length = htole32(fru_table_length);
107 response->total_record_set_identifiers =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930108 htole16(total_record_set_identifiers);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930109 response->total_table_records = htole16(total_table_records);
110 response->checksum = htole32(checksum);
111 }
112
113 return PLDM_SUCCESS;
114}
115
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930116LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930117int decode_get_fru_record_table_req(const struct pldm_msg *msg,
118 size_t payload_length,
119 uint32_t *data_transfer_handle,
120 uint8_t *transfer_operation_flag)
121{
122 if (msg == NULL || data_transfer_handle == NULL ||
123 transfer_operation_flag == NULL) {
124 return PLDM_ERROR_INVALID_DATA;
125 }
126
127 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES) {
128 return PLDM_ERROR_INVALID_LENGTH;
129 }
130
131 struct pldm_get_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930132 (struct pldm_get_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930133
134 *data_transfer_handle = le32toh(req->data_transfer_handle);
135 *transfer_operation_flag = req->transfer_operation_flag;
136
137 return PLDM_SUCCESS;
138}
139
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930140LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930141int encode_get_fru_record_table_resp(uint8_t instance_id,
142 uint8_t completion_code,
143 uint32_t next_data_transfer_handle,
144 uint8_t transfer_flag,
145 struct pldm_msg *msg)
146{
147 if (msg == NULL) {
148 return PLDM_ERROR_INVALID_DATA;
149 }
150
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930151 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930152 header.msg_type = PLDM_RESPONSE;
153 header.instance = instance_id;
154 header.pldm_type = PLDM_FRU;
155 header.command = PLDM_GET_FRU_RECORD_TABLE;
156
157 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
158 if (rc > PLDM_SUCCESS) {
159 return rc;
160 }
161
162 struct pldm_get_fru_record_table_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930163 (struct pldm_get_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930164
165 resp->completion_code = completion_code;
166
167 if (resp->completion_code == PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930168 resp->next_data_transfer_handle =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930169 htole32(next_data_transfer_handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930170 resp->transfer_flag = transfer_flag;
171 }
172
173 return PLDM_SUCCESS;
174}
175
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930176LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930177int encode_fru_record(uint8_t *fru_table, size_t total_size, size_t *curr_size,
178 uint16_t record_set_id, uint8_t record_type,
179 uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
180 size_t tlvs_size)
181{
182 size_t record_hdr_size = sizeof(struct pldm_fru_record_data_format) -
183 sizeof(struct pldm_fru_record_tlv);
184
185 if (fru_table == NULL || curr_size == NULL || !tlvs_size) {
186 return PLDM_ERROR_INVALID_DATA;
187 }
188 if ((*curr_size + record_hdr_size + tlvs_size) != total_size) {
189 return PLDM_ERROR_INVALID_LENGTH;
190 }
191
192 struct pldm_fru_record_data_format *record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930193 (struct pldm_fru_record_data_format *)(fru_table + *curr_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930194 record->record_set_id = htole16(record_set_id);
195 record->record_type = record_type;
196 record->num_fru_fields = num_frus;
197 record->encoding_type = encoding;
198 *curr_size += record_hdr_size;
199
200 if (tlvs) {
201 memcpy(fru_table + *curr_size, tlvs, tlvs_size);
202 *curr_size += tlvs_size;
203 }
204
205 return PLDM_SUCCESS;
206}
207
208static bool is_table_end(const struct pldm_fru_record_data_format *p,
209 const void *table, size_t table_size)
210{
211 return p ==
212 (const struct pldm_fru_record_data_format *)((uint8_t *)table +
213 table_size);
214}
215
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930216LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930217void get_fru_record_by_option(const uint8_t *table, size_t table_size,
218 uint8_t *record_table, size_t *record_size,
219 uint16_t rsi, uint8_t rt, uint8_t ft)
220{
221 const struct pldm_fru_record_data_format *record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930222 (const struct pldm_fru_record_data_format *)table;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930223 struct pldm_fru_record_data_format *record_data_dest;
224 int count = 0;
225
226 const struct pldm_fru_record_tlv *tlv;
227 size_t len;
228 uint8_t *pos = record_table;
229
230 while (!is_table_end(record_data_src, table, table_size)) {
231 if ((record_data_src->record_set_id != htole16(rsi) &&
232 rsi != 0) ||
233 (record_data_src->record_type != rt && rt != 0)) {
234 tlv = record_data_src->tlvs;
235 for (int i = 0; i < record_data_src->num_fru_fields;
236 i++) {
237 len = sizeof(*tlv) - 1 + tlv->length;
238 tlv = (const struct pldm_fru_record_tlv
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930239 *)((char *)tlv + len);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930240 }
241 record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930242 (const struct pldm_fru_record_data_format
243 *)(tlv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930244 continue;
245 }
246
247 len = sizeof(struct pldm_fru_record_data_format) -
248 sizeof(struct pldm_fru_record_tlv);
249
250 assert(pos - record_table + len < *record_size);
251 memcpy(pos, record_data_src, len);
252
253 record_data_dest = (struct pldm_fru_record_data_format *)pos;
254 pos += len;
255
256 tlv = record_data_src->tlvs;
257 count = 0;
258 for (int i = 0; i < record_data_src->num_fru_fields; i++) {
259 len = sizeof(*tlv) - 1 + tlv->length;
260 if (tlv->type == ft || ft == 0) {
261 assert(pos - record_table + len < *record_size);
262 memcpy(pos, tlv, len);
263 pos += len;
264 count++;
265 }
266 tlv = (const struct pldm_fru_record_tlv *)((char *)tlv +
267 len);
268 }
269 record_data_dest->num_fru_fields = count;
270 record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930271 (const struct pldm_fru_record_data_format *)(tlv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930272 }
273
274 *record_size = pos - record_table;
275}
276
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930277LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930278int encode_get_fru_record_by_option_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930279 uint8_t instance_id, uint32_t data_transfer_handle,
280 uint16_t fru_table_handle, uint16_t record_set_identifier,
281 uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
282 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930283{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930284 if (msg == NULL) {
285 return PLDM_ERROR_INVALID_DATA;
286 }
287
288 if (payload_length !=
289 sizeof(struct pldm_get_fru_record_by_option_req)) {
290 return PLDM_ERROR_INVALID_LENGTH;
291 }
292
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930293 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930294 header.instance = instance_id;
295 header.msg_type = PLDM_REQUEST;
296 header.pldm_type = PLDM_FRU;
297 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
298 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
299 if (rc != PLDM_SUCCESS) {
300 return rc;
301 }
302
303 struct pldm_get_fru_record_by_option_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930304 (struct pldm_get_fru_record_by_option_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930305
306 req->data_transfer_handle = htole32(data_transfer_handle);
307 req->fru_table_handle = htole16(fru_table_handle);
308 req->record_set_identifier = htole16(record_set_identifier);
309 req->record_type = record_type;
310 req->field_type = field_type;
311 req->transfer_op_flag = transfer_op_flag;
312
313 return PLDM_SUCCESS;
314}
315
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930316LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930317int decode_get_fru_record_by_option_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930318 const struct pldm_msg *msg, size_t payload_length,
319 uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
320 uint16_t *record_set_identifier, uint8_t *record_type,
321 uint8_t *field_type, uint8_t *transfer_op_flag)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930322{
323 if (msg == NULL || data_transfer_handle == NULL ||
324 fru_table_handle == NULL || record_set_identifier == NULL ||
325 record_type == NULL || field_type == NULL ||
326 transfer_op_flag == NULL) {
327 return PLDM_ERROR_INVALID_DATA;
328 }
329
330 if (payload_length !=
331 sizeof(struct pldm_get_fru_record_by_option_req)) {
332 return PLDM_ERROR_INVALID_LENGTH;
333 }
334
335 struct pldm_get_fru_record_by_option_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930336 (struct pldm_get_fru_record_by_option_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930337
338 *data_transfer_handle = le32toh(req->data_transfer_handle);
339 *fru_table_handle = le16toh(req->fru_table_handle);
340 *record_set_identifier = le16toh(req->record_set_identifier);
341 *record_type = req->record_type;
342 *field_type = req->field_type;
343 *transfer_op_flag = req->transfer_op_flag;
344 return PLDM_SUCCESS;
345}
346
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930347LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930348int encode_get_fru_record_by_option_resp(uint8_t instance_id,
349 uint8_t completion_code,
350 uint32_t next_data_transfer_handle,
351 uint8_t transfer_flag,
352 const void *fru_structure_data,
353 size_t data_size, struct pldm_msg *msg,
354 size_t payload_length)
355{
356 if (msg == NULL || fru_structure_data == NULL) {
357 return PLDM_ERROR_INVALID_DATA;
358 }
359
360 if (payload_length !=
361 PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES + data_size) {
362 return PLDM_ERROR_INVALID_LENGTH;
363 }
364
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930365 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930366 header.instance = instance_id;
367 header.msg_type = PLDM_RESPONSE;
368 header.pldm_type = PLDM_FRU;
369 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
370 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
371 if (rc != PLDM_SUCCESS) {
372 return rc;
373 }
374
375 struct pldm_get_fru_record_by_option_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930376 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930377
378 resp->completion_code = completion_code;
379 resp->next_data_transfer_handle = htole32(next_data_transfer_handle);
380 resp->transfer_flag = transfer_flag;
381
382 if (completion_code == PLDM_SUCCESS) {
383 memcpy(resp->fru_structure_data, fru_structure_data, data_size);
384 }
385
386 return PLDM_SUCCESS;
387}
388
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930389LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930390int decode_get_fru_record_by_option_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930391 const struct pldm_msg *msg, size_t payload_length,
392 uint8_t *completion_code, uint32_t *next_transfer_handle,
393 uint8_t *transfer_flag, struct variable_field *fru_structure_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930394{
395 if (msg == NULL || completion_code == NULL ||
396 next_transfer_handle == NULL || transfer_flag == NULL ||
397 fru_structure_data == NULL) {
398 return PLDM_ERROR_INVALID_DATA;
399 }
400
401 *completion_code = msg->payload[0];
402 if (PLDM_SUCCESS != *completion_code) {
403 return PLDM_SUCCESS;
404 }
405
406 if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
407 return PLDM_ERROR_INVALID_LENGTH;
408 }
409
410 struct pldm_get_fru_record_by_option_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930411 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930412
413 *next_transfer_handle = le32toh(resp->next_data_transfer_handle);
414 *transfer_flag = resp->transfer_flag;
415 fru_structure_data->ptr = resp->fru_structure_data;
416 fru_structure_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930417 payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930418
419 return PLDM_SUCCESS;
420}
421
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930422LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930423int encode_get_fru_record_table_req(uint8_t instance_id,
424 uint32_t data_transfer_handle,
425 uint8_t transfer_operation_flag,
426 struct pldm_msg *msg, size_t payload_length)
427
428{
429 if (msg == NULL) {
430 return PLDM_ERROR_INVALID_DATA;
431 }
432 if (payload_length != sizeof(struct pldm_get_fru_record_table_req)) {
433 return PLDM_ERROR_INVALID_LENGTH;
434 }
435
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930436 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930437 header.msg_type = PLDM_REQUEST;
438 header.instance = instance_id;
439 header.pldm_type = PLDM_FRU;
440 header.command = PLDM_GET_FRU_RECORD_TABLE;
441
442 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
443 if (rc != PLDM_SUCCESS) {
444 return rc;
445 }
446
447 struct pldm_get_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930448 (struct pldm_get_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930449 req->data_transfer_handle = htole32(data_transfer_handle);
450 req->transfer_operation_flag = transfer_operation_flag;
451
452 return PLDM_SUCCESS;
453}
454
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930455LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930456int decode_get_fru_record_table_resp_safe(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930457 const struct pldm_msg *msg, size_t payload_length,
458 uint8_t *completion_code, uint32_t *next_data_transfer_handle,
459 uint8_t *transfer_flag, uint8_t *fru_record_table_data,
460 size_t *fru_record_table_length, size_t max_fru_record_table_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930461{
462 if (msg == NULL || completion_code == NULL ||
463 next_data_transfer_handle == NULL || transfer_flag == NULL ||
464 fru_record_table_data == NULL || fru_record_table_length == NULL) {
465 return PLDM_ERROR_INVALID_DATA;
466 }
467
468 *completion_code = msg->payload[0];
469 if (PLDM_SUCCESS != *completion_code) {
470 return PLDM_SUCCESS;
471 }
472 if (payload_length <= PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES) {
473 return PLDM_ERROR_INVALID_LENGTH;
474 }
475
476 struct pldm_get_fru_record_table_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930477 (struct pldm_get_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930478
479 *next_data_transfer_handle = le32toh(resp->next_data_transfer_handle);
480 *transfer_flag = resp->transfer_flag;
481
482 *fru_record_table_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930483 payload_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930484
485 if (*fru_record_table_length > max_fru_record_table_length) {
486 return PLDM_ERROR_INVALID_LENGTH;
487 }
488
489 memcpy(fru_record_table_data, resp->fru_record_table_data,
490 *fru_record_table_length);
491
492 return PLDM_SUCCESS;
493}
494
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930495LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930496int decode_get_fru_record_table_resp(const struct pldm_msg *msg,
497 size_t payload_length,
498 uint8_t *completion_code,
499 uint32_t *next_data_transfer_handle,
500 uint8_t *transfer_flag,
501 uint8_t *fru_record_table_data,
502 size_t *fru_record_table_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930503{
504 return decode_get_fru_record_table_resp_safe(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930505 msg, payload_length, completion_code, next_data_transfer_handle,
506 transfer_flag, fru_record_table_data, fru_record_table_length,
507 (size_t)-1);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930508}
509
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930510LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930511int decode_set_fru_record_table_req(const struct pldm_msg *msg,
512 size_t payload_length,
513 uint32_t *data_transfer_handle,
514 uint8_t *transfer_flag,
515 struct variable_field *fru_table_data)
516
517{
518 if (msg == NULL || data_transfer_handle == NULL ||
519 transfer_flag == NULL || fru_table_data == NULL) {
520 return PLDM_ERROR_INVALID_DATA;
521 }
522
523 if (payload_length <= PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES) {
524 return PLDM_ERROR_INVALID_LENGTH;
525 }
526
527 struct pldm_set_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930528 (struct pldm_set_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930529
530 *data_transfer_handle = le32toh(req->data_transfer_handle);
531 *transfer_flag = req->transfer_flag;
532 fru_table_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930533 payload_length - PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930534 fru_table_data->ptr = req->fru_record_table_data;
535
536 return PLDM_SUCCESS;
537}
538
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930539LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930540int encode_set_fru_record_table_resp(uint8_t instance_id,
541 uint8_t completion_code,
542 uint32_t next_data_transfer_handle,
543 size_t payload_length,
544 struct pldm_msg *msg)
545{
546 if (msg == NULL) {
547 return PLDM_ERROR_INVALID_DATA;
548 }
549 if (payload_length != PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES) {
550 return PLDM_ERROR_INVALID_LENGTH;
551 }
552
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930553 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930554 header.instance = instance_id;
555 header.msg_type = PLDM_RESPONSE;
556 header.pldm_type = PLDM_FRU;
557 header.command = PLDM_SET_FRU_RECORD_TABLE;
558
559 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
560 if (PLDM_SUCCESS != rc) {
561 return rc;
562 }
563
564 struct pldm_set_fru_record_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930565 (struct pldm_set_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566 response->completion_code = completion_code;
567 response->next_data_transfer_handle =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930568 htole32(next_data_transfer_handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930569
570 return PLDM_SUCCESS;
571}