blob: 4f6c496bc9effbd1c471bfb5b9dadcdaa8226c74 [file] [log] [blame]
Andrew Jeffery9c766792022-08-10 23:12:49 +09301#include <assert.h>
2#include <endian.h>
3#include <stdbool.h>
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05304#include <stdint.h>
Andrew Jeffery9c766792022-08-10 23:12:49 +09305#include <string.h>
6
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05307#include "base.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09308#include "fru.h"
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05309#include "utils.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +093010
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093011LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093012int encode_get_fru_record_table_metadata_req(uint8_t instance_id,
13 struct pldm_msg *msg,
14 size_t payload_length)
15{
16 if (msg == NULL) {
17 return PLDM_ERROR_INVALID_DATA;
18 }
19
20 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES) {
21 return PLDM_ERROR_INVALID_LENGTH;
22 }
23
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093024 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +093025 header.instance = instance_id;
26 header.msg_type = PLDM_REQUEST;
27 header.pldm_type = PLDM_FRU;
28 header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
29
30 return pack_pldm_header(&header, &(msg->hdr));
31}
32
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093033LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093034int decode_get_fru_record_table_metadata_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093035 const struct pldm_msg *msg, size_t payload_length,
36 uint8_t *completion_code, uint8_t *fru_data_major_version,
37 uint8_t *fru_data_minor_version, uint32_t *fru_table_maximum_size,
38 uint32_t *fru_table_length, uint16_t *total_record_set_identifiers,
39 uint16_t *total_table_records, uint32_t *checksum)
Andrew Jeffery9c766792022-08-10 23:12:49 +093040{
41 if (msg == NULL || completion_code == NULL ||
42 fru_data_major_version == NULL || fru_data_minor_version == NULL ||
43 fru_table_maximum_size == NULL || fru_table_length == NULL ||
44 total_record_set_identifiers == NULL ||
45 total_table_records == NULL || checksum == NULL) {
46 return PLDM_ERROR_INVALID_DATA;
47 }
48
49 *completion_code = msg->payload[0];
50 if (PLDM_SUCCESS != *completion_code) {
51 return PLDM_SUCCESS;
52 }
53
54 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES) {
55 return PLDM_ERROR_INVALID_LENGTH;
56 }
57
58 struct pldm_get_fru_record_table_metadata_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093059 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +093060
61 *fru_data_major_version = response->fru_data_major_version;
62 *fru_data_minor_version = response->fru_data_minor_version;
63 *fru_table_maximum_size = le32toh(response->fru_table_maximum_size);
64 *fru_table_length = le32toh(response->fru_table_length);
65 *total_record_set_identifiers =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093066 le16toh(response->total_record_set_identifiers);
Andrew Jeffery9c766792022-08-10 23:12:49 +093067 *total_table_records = le16toh(response->total_table_records);
68 *checksum = le32toh(response->checksum);
69
70 return PLDM_SUCCESS;
71}
72
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093073LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093074int encode_get_fru_record_table_metadata_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093075 uint8_t instance_id, uint8_t completion_code,
76 uint8_t fru_data_major_version, uint8_t fru_data_minor_version,
77 uint32_t fru_table_maximum_size, uint32_t fru_table_length,
78 uint16_t total_record_set_identifiers, uint16_t total_table_records,
79 uint32_t checksum, struct pldm_msg *msg)
Andrew Jeffery9c766792022-08-10 23:12:49 +093080{
81 if (msg == NULL) {
82 return PLDM_ERROR_INVALID_DATA;
83 }
84
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093085 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +093086 header.msg_type = PLDM_RESPONSE;
87 header.instance = instance_id;
88 header.pldm_type = PLDM_FRU;
89 header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
90
91 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
92 if (PLDM_SUCCESS != rc) {
93 return rc;
94 }
95
96 struct pldm_get_fru_record_table_metadata_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093097 (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +093098 response->completion_code = completion_code;
99 if (response->completion_code == PLDM_SUCCESS) {
100 response->fru_data_major_version = fru_data_major_version;
101 response->fru_data_minor_version = fru_data_minor_version;
102 response->fru_table_maximum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930103 htole32(fru_table_maximum_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930104 response->fru_table_length = htole32(fru_table_length);
105 response->total_record_set_identifiers =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930106 htole16(total_record_set_identifiers);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930107 response->total_table_records = htole16(total_table_records);
108 response->checksum = htole32(checksum);
109 }
110
111 return PLDM_SUCCESS;
112}
113
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930114LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930115int decode_get_fru_record_table_req(const struct pldm_msg *msg,
116 size_t payload_length,
117 uint32_t *data_transfer_handle,
118 uint8_t *transfer_operation_flag)
119{
120 if (msg == NULL || data_transfer_handle == NULL ||
121 transfer_operation_flag == NULL) {
122 return PLDM_ERROR_INVALID_DATA;
123 }
124
125 if (payload_length != PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES) {
126 return PLDM_ERROR_INVALID_LENGTH;
127 }
128
129 struct pldm_get_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930130 (struct pldm_get_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930131
132 *data_transfer_handle = le32toh(req->data_transfer_handle);
133 *transfer_operation_flag = req->transfer_operation_flag;
134
135 return PLDM_SUCCESS;
136}
137
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930138LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930139int encode_get_fru_record_table_resp(uint8_t instance_id,
140 uint8_t completion_code,
141 uint32_t next_data_transfer_handle,
142 uint8_t transfer_flag,
143 struct pldm_msg *msg)
144{
145 if (msg == NULL) {
146 return PLDM_ERROR_INVALID_DATA;
147 }
148
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930149 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930150 header.msg_type = PLDM_RESPONSE;
151 header.instance = instance_id;
152 header.pldm_type = PLDM_FRU;
153 header.command = PLDM_GET_FRU_RECORD_TABLE;
154
155 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
156 if (rc > PLDM_SUCCESS) {
157 return rc;
158 }
159
160 struct pldm_get_fru_record_table_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930161 (struct pldm_get_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930162
163 resp->completion_code = completion_code;
164
165 if (resp->completion_code == PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930166 resp->next_data_transfer_handle =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930167 htole32(next_data_transfer_handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930168 resp->transfer_flag = transfer_flag;
169 }
170
171 return PLDM_SUCCESS;
172}
173
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930174LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930175int encode_fru_record(uint8_t *fru_table, size_t total_size, size_t *curr_size,
176 uint16_t record_set_id, uint8_t record_type,
177 uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
178 size_t tlvs_size)
179{
180 size_t record_hdr_size = sizeof(struct pldm_fru_record_data_format) -
181 sizeof(struct pldm_fru_record_tlv);
182
183 if (fru_table == NULL || curr_size == NULL || !tlvs_size) {
184 return PLDM_ERROR_INVALID_DATA;
185 }
186 if ((*curr_size + record_hdr_size + tlvs_size) != total_size) {
187 return PLDM_ERROR_INVALID_LENGTH;
188 }
189
190 struct pldm_fru_record_data_format *record =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930191 (struct pldm_fru_record_data_format *)(fru_table + *curr_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930192 record->record_set_id = htole16(record_set_id);
193 record->record_type = record_type;
194 record->num_fru_fields = num_frus;
195 record->encoding_type = encoding;
196 *curr_size += record_hdr_size;
197
198 if (tlvs) {
199 memcpy(fru_table + *curr_size, tlvs, tlvs_size);
200 *curr_size += tlvs_size;
201 }
202
203 return PLDM_SUCCESS;
204}
205
206static bool is_table_end(const struct pldm_fru_record_data_format *p,
207 const void *table, size_t table_size)
208{
Andrew Jefferya26f2272023-07-14 11:01:43 +0930209 return p >=
Andrew Jeffery9c766792022-08-10 23:12:49 +0930210 (const struct pldm_fru_record_data_format *)((uint8_t *)table +
211 table_size);
212}
213
Andrew Jeffery962fcec2023-07-07 10:10:19 +0930214LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930215void get_fru_record_by_option(const uint8_t *table, size_t table_size,
216 uint8_t *record_table, size_t *record_size,
217 uint16_t rsi, uint8_t rt, uint8_t ft)
218{
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930219 int rc = get_fru_record_by_option_check(table, table_size, record_table,
220 record_size, rsi, rt, ft);
221 (void)rc;
222 assert(rc == PLDM_SUCCESS);
223}
224
Andrew Jeffery962fcec2023-07-07 10:10:19 +0930225LIBPLDM_ABI_STABLE
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930226int get_fru_record_by_option_check(const uint8_t *table, size_t table_size,
227 uint8_t *record_table, size_t *record_size,
228 uint16_t rsi, uint8_t rt, uint8_t ft)
229{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930230 const struct pldm_fru_record_data_format *record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930231 (const struct pldm_fru_record_data_format *)table;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930232 struct pldm_fru_record_data_format *record_data_dest;
233 int count = 0;
234
235 const struct pldm_fru_record_tlv *tlv;
236 size_t len;
237 uint8_t *pos = record_table;
238
239 while (!is_table_end(record_data_src, table, table_size)) {
240 if ((record_data_src->record_set_id != htole16(rsi) &&
241 rsi != 0) ||
242 (record_data_src->record_type != rt && rt != 0)) {
243 tlv = record_data_src->tlvs;
244 for (int i = 0; i < record_data_src->num_fru_fields;
245 i++) {
246 len = sizeof(*tlv) - 1 + tlv->length;
247 tlv = (const struct pldm_fru_record_tlv
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930248 *)((char *)tlv + len);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930249 }
250 record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930251 (const struct pldm_fru_record_data_format
252 *)(tlv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930253 continue;
254 }
255
256 len = sizeof(struct pldm_fru_record_data_format) -
257 sizeof(struct pldm_fru_record_tlv);
258
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930259 if (pos - record_table + len >= *record_size) {
260 return PLDM_ERROR_INVALID_LENGTH;
261 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930262 memcpy(pos, record_data_src, len);
263
264 record_data_dest = (struct pldm_fru_record_data_format *)pos;
265 pos += len;
266
267 tlv = record_data_src->tlvs;
268 count = 0;
269 for (int i = 0; i < record_data_src->num_fru_fields; i++) {
270 len = sizeof(*tlv) - 1 + tlv->length;
271 if (tlv->type == ft || ft == 0) {
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930272 if (pos - record_table + len >= *record_size) {
273 return PLDM_ERROR_INVALID_LENGTH;
274 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930275 memcpy(pos, tlv, len);
276 pos += len;
277 count++;
278 }
279 tlv = (const struct pldm_fru_record_tlv *)((char *)tlv +
280 len);
281 }
282 record_data_dest->num_fru_fields = count;
283 record_data_src =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930284 (const struct pldm_fru_record_data_format *)(tlv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930285 }
286
287 *record_size = pos - record_table;
Andrew Jeffery7cd16ff2023-06-28 21:03:03 +0930288
289 return PLDM_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930290}
291
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930292LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930293int encode_get_fru_record_by_option_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930294 uint8_t instance_id, uint32_t data_transfer_handle,
295 uint16_t fru_table_handle, uint16_t record_set_identifier,
296 uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
297 struct pldm_msg *msg, size_t payload_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930298{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930299 if (msg == NULL) {
300 return PLDM_ERROR_INVALID_DATA;
301 }
302
303 if (payload_length !=
304 sizeof(struct pldm_get_fru_record_by_option_req)) {
305 return PLDM_ERROR_INVALID_LENGTH;
306 }
307
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930308 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930309 header.instance = instance_id;
310 header.msg_type = PLDM_REQUEST;
311 header.pldm_type = PLDM_FRU;
312 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
313 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
314 if (rc != PLDM_SUCCESS) {
315 return rc;
316 }
317
318 struct pldm_get_fru_record_by_option_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930319 (struct pldm_get_fru_record_by_option_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930320
321 req->data_transfer_handle = htole32(data_transfer_handle);
322 req->fru_table_handle = htole16(fru_table_handle);
323 req->record_set_identifier = htole16(record_set_identifier);
324 req->record_type = record_type;
325 req->field_type = field_type;
326 req->transfer_op_flag = transfer_op_flag;
327
328 return PLDM_SUCCESS;
329}
330
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930331LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930332int decode_get_fru_record_by_option_req(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930333 const struct pldm_msg *msg, size_t payload_length,
334 uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
335 uint16_t *record_set_identifier, uint8_t *record_type,
336 uint8_t *field_type, uint8_t *transfer_op_flag)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930337{
338 if (msg == NULL || data_transfer_handle == NULL ||
339 fru_table_handle == NULL || record_set_identifier == NULL ||
340 record_type == NULL || field_type == NULL ||
341 transfer_op_flag == NULL) {
342 return PLDM_ERROR_INVALID_DATA;
343 }
344
345 if (payload_length !=
346 sizeof(struct pldm_get_fru_record_by_option_req)) {
347 return PLDM_ERROR_INVALID_LENGTH;
348 }
349
350 struct pldm_get_fru_record_by_option_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930351 (struct pldm_get_fru_record_by_option_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930352
353 *data_transfer_handle = le32toh(req->data_transfer_handle);
354 *fru_table_handle = le16toh(req->fru_table_handle);
355 *record_set_identifier = le16toh(req->record_set_identifier);
356 *record_type = req->record_type;
357 *field_type = req->field_type;
358 *transfer_op_flag = req->transfer_op_flag;
359 return PLDM_SUCCESS;
360}
361
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930362LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930363int encode_get_fru_record_by_option_resp(uint8_t instance_id,
364 uint8_t completion_code,
365 uint32_t next_data_transfer_handle,
366 uint8_t transfer_flag,
367 const void *fru_structure_data,
368 size_t data_size, struct pldm_msg *msg,
369 size_t payload_length)
370{
371 if (msg == NULL || fru_structure_data == NULL) {
372 return PLDM_ERROR_INVALID_DATA;
373 }
374
375 if (payload_length !=
376 PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES + data_size) {
377 return PLDM_ERROR_INVALID_LENGTH;
378 }
379
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930380 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930381 header.instance = instance_id;
382 header.msg_type = PLDM_RESPONSE;
383 header.pldm_type = PLDM_FRU;
384 header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
385 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
386 if (rc != PLDM_SUCCESS) {
387 return rc;
388 }
389
390 struct pldm_get_fru_record_by_option_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930391 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930392
393 resp->completion_code = completion_code;
394 resp->next_data_transfer_handle = htole32(next_data_transfer_handle);
395 resp->transfer_flag = transfer_flag;
396
397 if (completion_code == PLDM_SUCCESS) {
398 memcpy(resp->fru_structure_data, fru_structure_data, data_size);
399 }
400
401 return PLDM_SUCCESS;
402}
403
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930404LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930405int decode_get_fru_record_by_option_resp(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930406 const struct pldm_msg *msg, size_t payload_length,
407 uint8_t *completion_code, uint32_t *next_transfer_handle,
408 uint8_t *transfer_flag, struct variable_field *fru_structure_data)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930409{
410 if (msg == NULL || completion_code == NULL ||
411 next_transfer_handle == NULL || transfer_flag == NULL ||
412 fru_structure_data == NULL) {
413 return PLDM_ERROR_INVALID_DATA;
414 }
415
416 *completion_code = msg->payload[0];
417 if (PLDM_SUCCESS != *completion_code) {
418 return PLDM_SUCCESS;
419 }
420
421 if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
422 return PLDM_ERROR_INVALID_LENGTH;
423 }
424
425 struct pldm_get_fru_record_by_option_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930426 (struct pldm_get_fru_record_by_option_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427
428 *next_transfer_handle = le32toh(resp->next_data_transfer_handle);
429 *transfer_flag = resp->transfer_flag;
430 fru_structure_data->ptr = resp->fru_structure_data;
431 fru_structure_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930432 payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930433
434 return PLDM_SUCCESS;
435}
436
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930437LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930438int encode_get_fru_record_table_req(uint8_t instance_id,
439 uint32_t data_transfer_handle,
440 uint8_t transfer_operation_flag,
441 struct pldm_msg *msg, size_t payload_length)
442
443{
444 if (msg == NULL) {
445 return PLDM_ERROR_INVALID_DATA;
446 }
447 if (payload_length != sizeof(struct pldm_get_fru_record_table_req)) {
448 return PLDM_ERROR_INVALID_LENGTH;
449 }
450
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930451 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930452 header.msg_type = PLDM_REQUEST;
453 header.instance = instance_id;
454 header.pldm_type = PLDM_FRU;
455 header.command = PLDM_GET_FRU_RECORD_TABLE;
456
457 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
458 if (rc != PLDM_SUCCESS) {
459 return rc;
460 }
461
462 struct pldm_get_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930463 (struct pldm_get_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930464 req->data_transfer_handle = htole32(data_transfer_handle);
465 req->transfer_operation_flag = transfer_operation_flag;
466
467 return PLDM_SUCCESS;
468}
469
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930470LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930471int decode_get_fru_record_table_resp_safe(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930472 const struct pldm_msg *msg, size_t payload_length,
473 uint8_t *completion_code, uint32_t *next_data_transfer_handle,
474 uint8_t *transfer_flag, uint8_t *fru_record_table_data,
475 size_t *fru_record_table_length, size_t max_fru_record_table_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930476{
477 if (msg == NULL || completion_code == NULL ||
478 next_data_transfer_handle == NULL || transfer_flag == NULL ||
479 fru_record_table_data == NULL || fru_record_table_length == NULL) {
480 return PLDM_ERROR_INVALID_DATA;
481 }
482
483 *completion_code = msg->payload[0];
484 if (PLDM_SUCCESS != *completion_code) {
485 return PLDM_SUCCESS;
486 }
487 if (payload_length <= PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES) {
488 return PLDM_ERROR_INVALID_LENGTH;
489 }
490
491 struct pldm_get_fru_record_table_resp *resp =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930492 (struct pldm_get_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930493
494 *next_data_transfer_handle = le32toh(resp->next_data_transfer_handle);
495 *transfer_flag = resp->transfer_flag;
496
497 *fru_record_table_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930498 payload_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930499
500 if (*fru_record_table_length > max_fru_record_table_length) {
501 return PLDM_ERROR_INVALID_LENGTH;
502 }
503
504 memcpy(fru_record_table_data, resp->fru_record_table_data,
505 *fru_record_table_length);
506
507 return PLDM_SUCCESS;
508}
509
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930510LIBPLDM_ABI_STABLE
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930511int decode_get_fru_record_table_resp(const struct pldm_msg *msg,
512 size_t payload_length,
513 uint8_t *completion_code,
514 uint32_t *next_data_transfer_handle,
515 uint8_t *transfer_flag,
516 uint8_t *fru_record_table_data,
517 size_t *fru_record_table_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930518{
519 return decode_get_fru_record_table_resp_safe(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930520 msg, payload_length, completion_code, next_data_transfer_handle,
521 transfer_flag, fru_record_table_data, fru_record_table_length,
522 (size_t)-1);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930523}
524
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930525LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930526int decode_set_fru_record_table_req(const struct pldm_msg *msg,
527 size_t payload_length,
528 uint32_t *data_transfer_handle,
529 uint8_t *transfer_flag,
530 struct variable_field *fru_table_data)
531
532{
533 if (msg == NULL || data_transfer_handle == NULL ||
534 transfer_flag == NULL || fru_table_data == NULL) {
535 return PLDM_ERROR_INVALID_DATA;
536 }
537
538 if (payload_length <= PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES) {
539 return PLDM_ERROR_INVALID_LENGTH;
540 }
541
542 struct pldm_set_fru_record_table_req *req =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930543 (struct pldm_set_fru_record_table_req *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930544
545 *data_transfer_handle = le32toh(req->data_transfer_handle);
546 *transfer_flag = req->transfer_flag;
547 fru_table_data->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930548 payload_length - PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930549 fru_table_data->ptr = req->fru_record_table_data;
550
551 return PLDM_SUCCESS;
552}
553
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930554LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930555int encode_set_fru_record_table_resp(uint8_t instance_id,
556 uint8_t completion_code,
557 uint32_t next_data_transfer_handle,
558 size_t payload_length,
559 struct pldm_msg *msg)
560{
561 if (msg == NULL) {
562 return PLDM_ERROR_INVALID_DATA;
563 }
564 if (payload_length != PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES) {
565 return PLDM_ERROR_INVALID_LENGTH;
566 }
567
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930568 struct pldm_header_info header = { 0 };
Andrew Jeffery9c766792022-08-10 23:12:49 +0930569 header.instance = instance_id;
570 header.msg_type = PLDM_RESPONSE;
571 header.pldm_type = PLDM_FRU;
572 header.command = PLDM_SET_FRU_RECORD_TABLE;
573
574 uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
575 if (PLDM_SUCCESS != rc) {
576 return rc;
577 }
578
579 struct pldm_set_fru_record_table_resp *response =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930580 (struct pldm_set_fru_record_table_resp *)msg->payload;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930581 response->completion_code = completion_code;
582 response->next_data_transfer_handle =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930583 htole32(next_data_transfer_handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930584
585 return PLDM_SUCCESS;
586}