148761c62SAndrew Jeffery /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
248761c62SAndrew Jeffery #include <libpldm/base.h>
348761c62SAndrew Jeffery #include <libpldm/fru.h>
448761c62SAndrew Jeffery #include <libpldm/utils.h>
548761c62SAndrew Jeffery
648761c62SAndrew Jeffery #include <assert.h>
748761c62SAndrew Jeffery #include <endian.h>
848761c62SAndrew Jeffery #include <stdbool.h>
948761c62SAndrew Jeffery #include <stdint.h>
1048761c62SAndrew Jeffery #include <string.h>
1148761c62SAndrew Jeffery
1248761c62SAndrew Jeffery LIBPLDM_ABI_STABLE
encode_get_fru_record_table_metadata_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)1348761c62SAndrew Jeffery int encode_get_fru_record_table_metadata_req(uint8_t instance_id,
1448761c62SAndrew Jeffery struct pldm_msg *msg,
1548761c62SAndrew Jeffery size_t payload_length)
1648761c62SAndrew Jeffery {
1748761c62SAndrew Jeffery if (msg == NULL) {
1848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
1948761c62SAndrew Jeffery }
2048761c62SAndrew Jeffery
2148761c62SAndrew Jeffery if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_REQ_BYTES) {
2248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
2348761c62SAndrew Jeffery }
2448761c62SAndrew Jeffery
2548761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
2648761c62SAndrew Jeffery header.instance = instance_id;
2748761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
2848761c62SAndrew Jeffery header.pldm_type = PLDM_FRU;
2948761c62SAndrew Jeffery header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
3048761c62SAndrew Jeffery
3148761c62SAndrew Jeffery return pack_pldm_header(&header, &(msg->hdr));
3248761c62SAndrew Jeffery }
3348761c62SAndrew Jeffery
3448761c62SAndrew Jeffery 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)3548761c62SAndrew Jeffery int decode_get_fru_record_table_metadata_resp(
3648761c62SAndrew Jeffery const struct pldm_msg *msg, size_t payload_length,
3748761c62SAndrew Jeffery uint8_t *completion_code, uint8_t *fru_data_major_version,
3848761c62SAndrew Jeffery uint8_t *fru_data_minor_version, uint32_t *fru_table_maximum_size,
3948761c62SAndrew Jeffery uint32_t *fru_table_length, uint16_t *total_record_set_identifiers,
4048761c62SAndrew Jeffery uint16_t *total_table_records, uint32_t *checksum)
4148761c62SAndrew Jeffery {
4248761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
4348761c62SAndrew Jeffery fru_data_major_version == NULL || fru_data_minor_version == NULL ||
4448761c62SAndrew Jeffery fru_table_maximum_size == NULL || fru_table_length == NULL ||
4548761c62SAndrew Jeffery total_record_set_identifiers == NULL ||
4648761c62SAndrew Jeffery total_table_records == NULL || checksum == NULL) {
4748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
4848761c62SAndrew Jeffery }
4948761c62SAndrew Jeffery
5048761c62SAndrew Jeffery *completion_code = msg->payload[0];
5148761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
5248761c62SAndrew Jeffery return PLDM_SUCCESS;
5348761c62SAndrew Jeffery }
5448761c62SAndrew Jeffery
5548761c62SAndrew Jeffery if (payload_length != PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES) {
5648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
5748761c62SAndrew Jeffery }
5848761c62SAndrew Jeffery
5948761c62SAndrew Jeffery struct pldm_get_fru_record_table_metadata_resp *response =
6048761c62SAndrew Jeffery (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
6148761c62SAndrew Jeffery
6248761c62SAndrew Jeffery *fru_data_major_version = response->fru_data_major_version;
6348761c62SAndrew Jeffery *fru_data_minor_version = response->fru_data_minor_version;
6448761c62SAndrew Jeffery *fru_table_maximum_size = le32toh(response->fru_table_maximum_size);
6548761c62SAndrew Jeffery *fru_table_length = le32toh(response->fru_table_length);
6648761c62SAndrew Jeffery *total_record_set_identifiers =
6748761c62SAndrew Jeffery le16toh(response->total_record_set_identifiers);
6848761c62SAndrew Jeffery *total_table_records = le16toh(response->total_table_records);
6948761c62SAndrew Jeffery *checksum = le32toh(response->checksum);
7048761c62SAndrew Jeffery
7148761c62SAndrew Jeffery return PLDM_SUCCESS;
7248761c62SAndrew Jeffery }
7348761c62SAndrew Jeffery
7448761c62SAndrew Jeffery 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)7548761c62SAndrew Jeffery int encode_get_fru_record_table_metadata_resp(
7648761c62SAndrew Jeffery uint8_t instance_id, uint8_t completion_code,
7748761c62SAndrew Jeffery uint8_t fru_data_major_version, uint8_t fru_data_minor_version,
7848761c62SAndrew Jeffery uint32_t fru_table_maximum_size, uint32_t fru_table_length,
7948761c62SAndrew Jeffery uint16_t total_record_set_identifiers, uint16_t total_table_records,
8048761c62SAndrew Jeffery uint32_t checksum, struct pldm_msg *msg)
8148761c62SAndrew Jeffery {
8248761c62SAndrew Jeffery if (msg == NULL) {
8348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
8448761c62SAndrew Jeffery }
8548761c62SAndrew Jeffery
8648761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
8748761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
8848761c62SAndrew Jeffery header.instance = instance_id;
8948761c62SAndrew Jeffery header.pldm_type = PLDM_FRU;
9048761c62SAndrew Jeffery header.command = PLDM_GET_FRU_RECORD_TABLE_METADATA;
9148761c62SAndrew Jeffery
9248761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
9348761c62SAndrew Jeffery if (PLDM_SUCCESS != rc) {
9448761c62SAndrew Jeffery return rc;
9548761c62SAndrew Jeffery }
9648761c62SAndrew Jeffery
9748761c62SAndrew Jeffery struct pldm_get_fru_record_table_metadata_resp *response =
9848761c62SAndrew Jeffery (struct pldm_get_fru_record_table_metadata_resp *)msg->payload;
9948761c62SAndrew Jeffery response->completion_code = completion_code;
10048761c62SAndrew Jeffery if (response->completion_code == PLDM_SUCCESS) {
10148761c62SAndrew Jeffery response->fru_data_major_version = fru_data_major_version;
10248761c62SAndrew Jeffery response->fru_data_minor_version = fru_data_minor_version;
10348761c62SAndrew Jeffery response->fru_table_maximum_size =
10448761c62SAndrew Jeffery htole32(fru_table_maximum_size);
10548761c62SAndrew Jeffery response->fru_table_length = htole32(fru_table_length);
10648761c62SAndrew Jeffery response->total_record_set_identifiers =
10748761c62SAndrew Jeffery htole16(total_record_set_identifiers);
10848761c62SAndrew Jeffery response->total_table_records = htole16(total_table_records);
10948761c62SAndrew Jeffery response->checksum = htole32(checksum);
11048761c62SAndrew Jeffery }
11148761c62SAndrew Jeffery
11248761c62SAndrew Jeffery return PLDM_SUCCESS;
11348761c62SAndrew Jeffery }
11448761c62SAndrew Jeffery
11548761c62SAndrew Jeffery 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)11648761c62SAndrew Jeffery int decode_get_fru_record_table_req(const struct pldm_msg *msg,
11748761c62SAndrew Jeffery size_t payload_length,
11848761c62SAndrew Jeffery uint32_t *data_transfer_handle,
11948761c62SAndrew Jeffery uint8_t *transfer_operation_flag)
12048761c62SAndrew Jeffery {
12148761c62SAndrew Jeffery if (msg == NULL || data_transfer_handle == NULL ||
12248761c62SAndrew Jeffery transfer_operation_flag == NULL) {
12348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
12448761c62SAndrew Jeffery }
12548761c62SAndrew Jeffery
12648761c62SAndrew Jeffery if (payload_length != PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES) {
12748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
12848761c62SAndrew Jeffery }
12948761c62SAndrew Jeffery
13048761c62SAndrew Jeffery struct pldm_get_fru_record_table_req *req =
13148761c62SAndrew Jeffery (struct pldm_get_fru_record_table_req *)msg->payload;
13248761c62SAndrew Jeffery
13348761c62SAndrew Jeffery *data_transfer_handle = le32toh(req->data_transfer_handle);
13448761c62SAndrew Jeffery *transfer_operation_flag = req->transfer_operation_flag;
13548761c62SAndrew Jeffery
13648761c62SAndrew Jeffery return PLDM_SUCCESS;
13748761c62SAndrew Jeffery }
13848761c62SAndrew Jeffery
13948761c62SAndrew Jeffery 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)14048761c62SAndrew Jeffery int encode_get_fru_record_table_resp(uint8_t instance_id,
14148761c62SAndrew Jeffery uint8_t completion_code,
14248761c62SAndrew Jeffery uint32_t next_data_transfer_handle,
14348761c62SAndrew Jeffery uint8_t transfer_flag,
14448761c62SAndrew Jeffery struct pldm_msg *msg)
14548761c62SAndrew Jeffery {
14648761c62SAndrew Jeffery if (msg == NULL) {
14748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
14848761c62SAndrew Jeffery }
14948761c62SAndrew Jeffery
15048761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
15148761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
15248761c62SAndrew Jeffery header.instance = instance_id;
15348761c62SAndrew Jeffery header.pldm_type = PLDM_FRU;
15448761c62SAndrew Jeffery header.command = PLDM_GET_FRU_RECORD_TABLE;
15548761c62SAndrew Jeffery
15648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
15748761c62SAndrew Jeffery if (rc > PLDM_SUCCESS) {
15848761c62SAndrew Jeffery return rc;
15948761c62SAndrew Jeffery }
16048761c62SAndrew Jeffery
16148761c62SAndrew Jeffery struct pldm_get_fru_record_table_resp *resp =
16248761c62SAndrew Jeffery (struct pldm_get_fru_record_table_resp *)msg->payload;
16348761c62SAndrew Jeffery
16448761c62SAndrew Jeffery resp->completion_code = completion_code;
16548761c62SAndrew Jeffery
16648761c62SAndrew Jeffery if (resp->completion_code == PLDM_SUCCESS) {
16748761c62SAndrew Jeffery resp->next_data_transfer_handle =
16848761c62SAndrew Jeffery htole32(next_data_transfer_handle);
16948761c62SAndrew Jeffery resp->transfer_flag = transfer_flag;
17048761c62SAndrew Jeffery }
17148761c62SAndrew Jeffery
17248761c62SAndrew Jeffery return PLDM_SUCCESS;
17348761c62SAndrew Jeffery }
17448761c62SAndrew Jeffery
175*36324f6bSAndrew Jeffery 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)17648761c62SAndrew Jeffery int encode_fru_record(uint8_t *fru_table, size_t total_size, size_t *curr_size,
17748761c62SAndrew Jeffery uint16_t record_set_id, uint8_t record_type,
17848761c62SAndrew Jeffery uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
17948761c62SAndrew Jeffery size_t tlvs_size)
18048761c62SAndrew Jeffery {
18148761c62SAndrew Jeffery size_t record_hdr_size = sizeof(struct pldm_fru_record_data_format) -
18248761c62SAndrew Jeffery sizeof(struct pldm_fru_record_tlv);
18348761c62SAndrew Jeffery
18448761c62SAndrew Jeffery if (fru_table == NULL || curr_size == NULL || !tlvs_size) {
18548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
18648761c62SAndrew Jeffery }
187d7d08f65SAndrew Jeffery
188d7d08f65SAndrew Jeffery if (SIZE_MAX - *curr_size < record_hdr_size) {
189d7d08f65SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
190d7d08f65SAndrew Jeffery }
191d7d08f65SAndrew Jeffery
192d7d08f65SAndrew Jeffery if (SIZE_MAX - (*curr_size + record_hdr_size) < tlvs_size) {
193d7d08f65SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
194d7d08f65SAndrew Jeffery }
195d7d08f65SAndrew Jeffery
196d7d08f65SAndrew Jeffery if (total_size < *curr_size + record_hdr_size) {
197d7d08f65SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
198d7d08f65SAndrew Jeffery }
199d7d08f65SAndrew Jeffery
200d7d08f65SAndrew Jeffery if (total_size - (*curr_size + record_hdr_size) < tlvs_size) {
20148761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
20248761c62SAndrew Jeffery }
20348761c62SAndrew Jeffery
20448761c62SAndrew Jeffery struct pldm_fru_record_data_format *record =
20548761c62SAndrew Jeffery (struct pldm_fru_record_data_format *)(fru_table + *curr_size);
20648761c62SAndrew Jeffery record->record_set_id = htole16(record_set_id);
20748761c62SAndrew Jeffery record->record_type = record_type;
20848761c62SAndrew Jeffery record->num_fru_fields = num_frus;
20948761c62SAndrew Jeffery record->encoding_type = encoding;
21048761c62SAndrew Jeffery *curr_size += record_hdr_size;
21148761c62SAndrew Jeffery
21248761c62SAndrew Jeffery if (tlvs) {
21348761c62SAndrew Jeffery memcpy(fru_table + *curr_size, tlvs, tlvs_size);
21448761c62SAndrew Jeffery *curr_size += tlvs_size;
21548761c62SAndrew Jeffery }
21648761c62SAndrew Jeffery
21748761c62SAndrew Jeffery return PLDM_SUCCESS;
21848761c62SAndrew Jeffery }
21948761c62SAndrew Jeffery
is_table_end(const struct pldm_fru_record_data_format * p,const void * table,size_t table_size)22048761c62SAndrew Jeffery static bool is_table_end(const struct pldm_fru_record_data_format *p,
22148761c62SAndrew Jeffery const void *table, size_t table_size)
22248761c62SAndrew Jeffery {
22348761c62SAndrew Jeffery return p >=
22448761c62SAndrew Jeffery (const struct pldm_fru_record_data_format *)((uint8_t *)table +
22548761c62SAndrew Jeffery table_size);
22648761c62SAndrew Jeffery }
22748761c62SAndrew Jeffery
22848761c62SAndrew Jeffery 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)229d9b70ba7SAndrew Jeffery int get_fru_record_by_option(const uint8_t *table, size_t table_size,
23048761c62SAndrew Jeffery uint8_t *record_table, size_t *record_size,
23148761c62SAndrew Jeffery uint16_t rsi, uint8_t rt, uint8_t ft)
23248761c62SAndrew Jeffery {
23348761c62SAndrew Jeffery const struct pldm_fru_record_data_format *record_data_src =
23448761c62SAndrew Jeffery (const struct pldm_fru_record_data_format *)table;
23548761c62SAndrew Jeffery struct pldm_fru_record_data_format *record_data_dest;
23648761c62SAndrew Jeffery int count = 0;
23748761c62SAndrew Jeffery
23848761c62SAndrew Jeffery const struct pldm_fru_record_tlv *tlv;
23948761c62SAndrew Jeffery size_t len;
24048761c62SAndrew Jeffery uint8_t *pos = record_table;
24148761c62SAndrew Jeffery
24248761c62SAndrew Jeffery while (!is_table_end(record_data_src, table, table_size)) {
24348761c62SAndrew Jeffery if ((record_data_src->record_set_id != htole16(rsi) &&
24448761c62SAndrew Jeffery rsi != 0) ||
24548761c62SAndrew Jeffery (record_data_src->record_type != rt && rt != 0)) {
24648761c62SAndrew Jeffery tlv = record_data_src->tlvs;
24748761c62SAndrew Jeffery for (int i = 0; i < record_data_src->num_fru_fields;
24848761c62SAndrew Jeffery i++) {
24948761c62SAndrew Jeffery len = sizeof(*tlv) - 1 + tlv->length;
25048761c62SAndrew Jeffery tlv = (const struct pldm_fru_record_tlv
25148761c62SAndrew Jeffery *)((char *)tlv + len);
25248761c62SAndrew Jeffery }
25348761c62SAndrew Jeffery record_data_src =
25448761c62SAndrew Jeffery (const struct pldm_fru_record_data_format
25548761c62SAndrew Jeffery *)(tlv);
25648761c62SAndrew Jeffery continue;
25748761c62SAndrew Jeffery }
25848761c62SAndrew Jeffery
25948761c62SAndrew Jeffery len = sizeof(struct pldm_fru_record_data_format) -
26048761c62SAndrew Jeffery sizeof(struct pldm_fru_record_tlv);
26148761c62SAndrew Jeffery
26248761c62SAndrew Jeffery if (pos - record_table + len >= *record_size) {
26348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
26448761c62SAndrew Jeffery }
26548761c62SAndrew Jeffery memcpy(pos, record_data_src, len);
26648761c62SAndrew Jeffery
26748761c62SAndrew Jeffery record_data_dest = (struct pldm_fru_record_data_format *)pos;
26848761c62SAndrew Jeffery pos += len;
26948761c62SAndrew Jeffery
27048761c62SAndrew Jeffery tlv = record_data_src->tlvs;
27148761c62SAndrew Jeffery count = 0;
27248761c62SAndrew Jeffery for (int i = 0; i < record_data_src->num_fru_fields; i++) {
27348761c62SAndrew Jeffery len = sizeof(*tlv) - 1 + tlv->length;
27448761c62SAndrew Jeffery if (tlv->type == ft || ft == 0) {
27548761c62SAndrew Jeffery if (pos - record_table + len >= *record_size) {
27648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
27748761c62SAndrew Jeffery }
27848761c62SAndrew Jeffery memcpy(pos, tlv, len);
27948761c62SAndrew Jeffery pos += len;
28048761c62SAndrew Jeffery count++;
28148761c62SAndrew Jeffery }
28248761c62SAndrew Jeffery tlv = (const struct pldm_fru_record_tlv *)((char *)tlv +
28348761c62SAndrew Jeffery len);
28448761c62SAndrew Jeffery }
28548761c62SAndrew Jeffery record_data_dest->num_fru_fields = count;
28648761c62SAndrew Jeffery record_data_src =
28748761c62SAndrew Jeffery (const struct pldm_fru_record_data_format *)(tlv);
28848761c62SAndrew Jeffery }
28948761c62SAndrew Jeffery
29048761c62SAndrew Jeffery *record_size = pos - record_table;
29148761c62SAndrew Jeffery
29248761c62SAndrew Jeffery return PLDM_SUCCESS;
29348761c62SAndrew Jeffery }
29448761c62SAndrew Jeffery
29548761c62SAndrew Jeffery 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)29648761c62SAndrew Jeffery int encode_get_fru_record_by_option_req(
29748761c62SAndrew Jeffery uint8_t instance_id, uint32_t data_transfer_handle,
29848761c62SAndrew Jeffery uint16_t fru_table_handle, uint16_t record_set_identifier,
29948761c62SAndrew Jeffery uint8_t record_type, uint8_t field_type, uint8_t transfer_op_flag,
30048761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
30148761c62SAndrew Jeffery {
30248761c62SAndrew Jeffery if (msg == NULL) {
30348761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
30448761c62SAndrew Jeffery }
30548761c62SAndrew Jeffery
30648761c62SAndrew Jeffery if (payload_length !=
30748761c62SAndrew Jeffery sizeof(struct pldm_get_fru_record_by_option_req)) {
30848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
30948761c62SAndrew Jeffery }
31048761c62SAndrew Jeffery
31148761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
31248761c62SAndrew Jeffery header.instance = instance_id;
31348761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
31448761c62SAndrew Jeffery header.pldm_type = PLDM_FRU;
31548761c62SAndrew Jeffery header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
31648761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
31748761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
31848761c62SAndrew Jeffery return rc;
31948761c62SAndrew Jeffery }
32048761c62SAndrew Jeffery
32148761c62SAndrew Jeffery struct pldm_get_fru_record_by_option_req *req =
32248761c62SAndrew Jeffery (struct pldm_get_fru_record_by_option_req *)msg->payload;
32348761c62SAndrew Jeffery
32448761c62SAndrew Jeffery req->data_transfer_handle = htole32(data_transfer_handle);
32548761c62SAndrew Jeffery req->fru_table_handle = htole16(fru_table_handle);
32648761c62SAndrew Jeffery req->record_set_identifier = htole16(record_set_identifier);
32748761c62SAndrew Jeffery req->record_type = record_type;
32848761c62SAndrew Jeffery req->field_type = field_type;
32948761c62SAndrew Jeffery req->transfer_op_flag = transfer_op_flag;
33048761c62SAndrew Jeffery
33148761c62SAndrew Jeffery return PLDM_SUCCESS;
33248761c62SAndrew Jeffery }
33348761c62SAndrew Jeffery
33448761c62SAndrew Jeffery 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)33548761c62SAndrew Jeffery int decode_get_fru_record_by_option_req(
33648761c62SAndrew Jeffery const struct pldm_msg *msg, size_t payload_length,
33748761c62SAndrew Jeffery uint32_t *data_transfer_handle, uint16_t *fru_table_handle,
33848761c62SAndrew Jeffery uint16_t *record_set_identifier, uint8_t *record_type,
33948761c62SAndrew Jeffery uint8_t *field_type, uint8_t *transfer_op_flag)
34048761c62SAndrew Jeffery {
34148761c62SAndrew Jeffery if (msg == NULL || data_transfer_handle == NULL ||
34248761c62SAndrew Jeffery fru_table_handle == NULL || record_set_identifier == NULL ||
34348761c62SAndrew Jeffery record_type == NULL || field_type == NULL ||
34448761c62SAndrew Jeffery transfer_op_flag == NULL) {
34548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
34648761c62SAndrew Jeffery }
34748761c62SAndrew Jeffery
34848761c62SAndrew Jeffery if (payload_length !=
34948761c62SAndrew Jeffery sizeof(struct pldm_get_fru_record_by_option_req)) {
35048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
35148761c62SAndrew Jeffery }
35248761c62SAndrew Jeffery
35348761c62SAndrew Jeffery struct pldm_get_fru_record_by_option_req *req =
35448761c62SAndrew Jeffery (struct pldm_get_fru_record_by_option_req *)msg->payload;
35548761c62SAndrew Jeffery
35648761c62SAndrew Jeffery *data_transfer_handle = le32toh(req->data_transfer_handle);
35748761c62SAndrew Jeffery *fru_table_handle = le16toh(req->fru_table_handle);
35848761c62SAndrew Jeffery *record_set_identifier = le16toh(req->record_set_identifier);
35948761c62SAndrew Jeffery *record_type = req->record_type;
36048761c62SAndrew Jeffery *field_type = req->field_type;
36148761c62SAndrew Jeffery *transfer_op_flag = req->transfer_op_flag;
36248761c62SAndrew Jeffery return PLDM_SUCCESS;
36348761c62SAndrew Jeffery }
36448761c62SAndrew Jeffery
36548761c62SAndrew Jeffery 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)36648761c62SAndrew Jeffery int encode_get_fru_record_by_option_resp(uint8_t instance_id,
36748761c62SAndrew Jeffery uint8_t completion_code,
36848761c62SAndrew Jeffery uint32_t next_data_transfer_handle,
36948761c62SAndrew Jeffery uint8_t transfer_flag,
37048761c62SAndrew Jeffery const void *fru_structure_data,
37148761c62SAndrew Jeffery size_t data_size, struct pldm_msg *msg,
37248761c62SAndrew Jeffery size_t payload_length)
37348761c62SAndrew Jeffery {
37448761c62SAndrew Jeffery if (msg == NULL || fru_structure_data == NULL) {
37548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
37648761c62SAndrew Jeffery }
37748761c62SAndrew Jeffery
37882c34815SAndrew Jeffery if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
37982c34815SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
38082c34815SAndrew Jeffery }
38182c34815SAndrew Jeffery
38282c34815SAndrew Jeffery if (payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES <
38382c34815SAndrew Jeffery data_size) {
38448761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
38548761c62SAndrew Jeffery }
38648761c62SAndrew Jeffery
38748761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
38848761c62SAndrew Jeffery header.instance = instance_id;
38948761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
39048761c62SAndrew Jeffery header.pldm_type = PLDM_FRU;
39148761c62SAndrew Jeffery header.command = PLDM_GET_FRU_RECORD_BY_OPTION;
39248761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
39348761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
39448761c62SAndrew Jeffery return rc;
39548761c62SAndrew Jeffery }
39648761c62SAndrew Jeffery
39748761c62SAndrew Jeffery struct pldm_get_fru_record_by_option_resp *resp =
39848761c62SAndrew Jeffery (struct pldm_get_fru_record_by_option_resp *)msg->payload;
39948761c62SAndrew Jeffery
40048761c62SAndrew Jeffery resp->completion_code = completion_code;
40148761c62SAndrew Jeffery resp->next_data_transfer_handle = htole32(next_data_transfer_handle);
40248761c62SAndrew Jeffery resp->transfer_flag = transfer_flag;
40348761c62SAndrew Jeffery
40448761c62SAndrew Jeffery if (completion_code == PLDM_SUCCESS) {
40548761c62SAndrew Jeffery memcpy(resp->fru_structure_data, fru_structure_data, data_size);
40648761c62SAndrew Jeffery }
40748761c62SAndrew Jeffery
40848761c62SAndrew Jeffery return PLDM_SUCCESS;
40948761c62SAndrew Jeffery }
41048761c62SAndrew Jeffery
41148761c62SAndrew Jeffery 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)41248761c62SAndrew Jeffery int decode_get_fru_record_by_option_resp(
41348761c62SAndrew Jeffery const struct pldm_msg *msg, size_t payload_length,
41448761c62SAndrew Jeffery uint8_t *completion_code, uint32_t *next_transfer_handle,
41548761c62SAndrew Jeffery uint8_t *transfer_flag, struct variable_field *fru_structure_data)
41648761c62SAndrew Jeffery {
41748761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
41848761c62SAndrew Jeffery next_transfer_handle == NULL || transfer_flag == NULL ||
41948761c62SAndrew Jeffery fru_structure_data == NULL) {
42048761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
42148761c62SAndrew Jeffery }
42248761c62SAndrew Jeffery
42348761c62SAndrew Jeffery *completion_code = msg->payload[0];
42448761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
42548761c62SAndrew Jeffery return PLDM_SUCCESS;
42648761c62SAndrew Jeffery }
42748761c62SAndrew Jeffery
42848761c62SAndrew Jeffery if (payload_length < PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES) {
42948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
43048761c62SAndrew Jeffery }
43148761c62SAndrew Jeffery
43248761c62SAndrew Jeffery struct pldm_get_fru_record_by_option_resp *resp =
43348761c62SAndrew Jeffery (struct pldm_get_fru_record_by_option_resp *)msg->payload;
43448761c62SAndrew Jeffery
43548761c62SAndrew Jeffery *next_transfer_handle = le32toh(resp->next_data_transfer_handle);
43648761c62SAndrew Jeffery *transfer_flag = resp->transfer_flag;
43748761c62SAndrew Jeffery fru_structure_data->ptr = resp->fru_structure_data;
43848761c62SAndrew Jeffery fru_structure_data->length =
43948761c62SAndrew Jeffery payload_length - PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES;
44048761c62SAndrew Jeffery
44148761c62SAndrew Jeffery return PLDM_SUCCESS;
44248761c62SAndrew Jeffery }
44348761c62SAndrew Jeffery
44448761c62SAndrew Jeffery 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)44548761c62SAndrew Jeffery int encode_get_fru_record_table_req(uint8_t instance_id,
44648761c62SAndrew Jeffery uint32_t data_transfer_handle,
44748761c62SAndrew Jeffery uint8_t transfer_operation_flag,
44848761c62SAndrew Jeffery struct pldm_msg *msg, size_t payload_length)
44948761c62SAndrew Jeffery
45048761c62SAndrew Jeffery {
45148761c62SAndrew Jeffery if (msg == NULL) {
45248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
45348761c62SAndrew Jeffery }
45448761c62SAndrew Jeffery if (payload_length != sizeof(struct pldm_get_fru_record_table_req)) {
45548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
45648761c62SAndrew Jeffery }
45748761c62SAndrew Jeffery
45848761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
45948761c62SAndrew Jeffery header.msg_type = PLDM_REQUEST;
46048761c62SAndrew Jeffery header.instance = instance_id;
46148761c62SAndrew Jeffery header.pldm_type = PLDM_FRU;
46248761c62SAndrew Jeffery header.command = PLDM_GET_FRU_RECORD_TABLE;
46348761c62SAndrew Jeffery
46448761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
46548761c62SAndrew Jeffery if (rc != PLDM_SUCCESS) {
46648761c62SAndrew Jeffery return rc;
46748761c62SAndrew Jeffery }
46848761c62SAndrew Jeffery
46948761c62SAndrew Jeffery struct pldm_get_fru_record_table_req *req =
47048761c62SAndrew Jeffery (struct pldm_get_fru_record_table_req *)msg->payload;
47148761c62SAndrew Jeffery req->data_transfer_handle = htole32(data_transfer_handle);
47248761c62SAndrew Jeffery req->transfer_operation_flag = transfer_operation_flag;
47348761c62SAndrew Jeffery
47448761c62SAndrew Jeffery return PLDM_SUCCESS;
47548761c62SAndrew Jeffery }
47648761c62SAndrew Jeffery
47748761c62SAndrew Jeffery 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)47848761c62SAndrew Jeffery int decode_get_fru_record_table_resp_safe(
47948761c62SAndrew Jeffery const struct pldm_msg *msg, size_t payload_length,
48048761c62SAndrew Jeffery uint8_t *completion_code, uint32_t *next_data_transfer_handle,
48148761c62SAndrew Jeffery uint8_t *transfer_flag, uint8_t *fru_record_table_data,
48248761c62SAndrew Jeffery size_t *fru_record_table_length, size_t max_fru_record_table_length)
48348761c62SAndrew Jeffery {
48448761c62SAndrew Jeffery if (msg == NULL || completion_code == NULL ||
48548761c62SAndrew Jeffery next_data_transfer_handle == NULL || transfer_flag == NULL ||
48648761c62SAndrew Jeffery fru_record_table_data == NULL || fru_record_table_length == NULL) {
48748761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
48848761c62SAndrew Jeffery }
48948761c62SAndrew Jeffery
49048761c62SAndrew Jeffery *completion_code = msg->payload[0];
49148761c62SAndrew Jeffery if (PLDM_SUCCESS != *completion_code) {
49248761c62SAndrew Jeffery return PLDM_SUCCESS;
49348761c62SAndrew Jeffery }
49448761c62SAndrew Jeffery if (payload_length <= PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES) {
49548761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
49648761c62SAndrew Jeffery }
49748761c62SAndrew Jeffery
49848761c62SAndrew Jeffery struct pldm_get_fru_record_table_resp *resp =
49948761c62SAndrew Jeffery (struct pldm_get_fru_record_table_resp *)msg->payload;
50048761c62SAndrew Jeffery
50148761c62SAndrew Jeffery *next_data_transfer_handle = le32toh(resp->next_data_transfer_handle);
50248761c62SAndrew Jeffery *transfer_flag = resp->transfer_flag;
50348761c62SAndrew Jeffery
50448761c62SAndrew Jeffery *fru_record_table_length =
50548761c62SAndrew Jeffery payload_length - PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES;
50648761c62SAndrew Jeffery
50748761c62SAndrew Jeffery if (*fru_record_table_length > max_fru_record_table_length) {
50848761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
50948761c62SAndrew Jeffery }
51048761c62SAndrew Jeffery
51148761c62SAndrew Jeffery memcpy(fru_record_table_data, resp->fru_record_table_data,
51248761c62SAndrew Jeffery *fru_record_table_length);
51348761c62SAndrew Jeffery
51448761c62SAndrew Jeffery return PLDM_SUCCESS;
51548761c62SAndrew Jeffery }
51648761c62SAndrew Jeffery
51748761c62SAndrew Jeffery 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)51848761c62SAndrew Jeffery int decode_get_fru_record_table_resp(const struct pldm_msg *msg,
51948761c62SAndrew Jeffery size_t payload_length,
52048761c62SAndrew Jeffery uint8_t *completion_code,
52148761c62SAndrew Jeffery uint32_t *next_data_transfer_handle,
52248761c62SAndrew Jeffery uint8_t *transfer_flag,
52348761c62SAndrew Jeffery uint8_t *fru_record_table_data,
52448761c62SAndrew Jeffery size_t *fru_record_table_length)
52548761c62SAndrew Jeffery {
52648761c62SAndrew Jeffery return decode_get_fru_record_table_resp_safe(
52748761c62SAndrew Jeffery msg, payload_length, completion_code, next_data_transfer_handle,
52848761c62SAndrew Jeffery transfer_flag, fru_record_table_data, fru_record_table_length,
52948761c62SAndrew Jeffery (size_t)-1);
53048761c62SAndrew Jeffery }
53148761c62SAndrew Jeffery
53248761c62SAndrew Jeffery 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)53348761c62SAndrew Jeffery int decode_set_fru_record_table_req(const struct pldm_msg *msg,
53448761c62SAndrew Jeffery size_t payload_length,
53548761c62SAndrew Jeffery uint32_t *data_transfer_handle,
53648761c62SAndrew Jeffery uint8_t *transfer_flag,
53748761c62SAndrew Jeffery struct variable_field *fru_table_data)
53848761c62SAndrew Jeffery
53948761c62SAndrew Jeffery {
54048761c62SAndrew Jeffery if (msg == NULL || data_transfer_handle == NULL ||
54148761c62SAndrew Jeffery transfer_flag == NULL || fru_table_data == NULL) {
54248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
54348761c62SAndrew Jeffery }
54448761c62SAndrew Jeffery
54548761c62SAndrew Jeffery if (payload_length <= PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES) {
54648761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
54748761c62SAndrew Jeffery }
54848761c62SAndrew Jeffery
54948761c62SAndrew Jeffery struct pldm_set_fru_record_table_req *req =
55048761c62SAndrew Jeffery (struct pldm_set_fru_record_table_req *)msg->payload;
55148761c62SAndrew Jeffery
55248761c62SAndrew Jeffery *data_transfer_handle = le32toh(req->data_transfer_handle);
55348761c62SAndrew Jeffery *transfer_flag = req->transfer_flag;
55448761c62SAndrew Jeffery fru_table_data->length =
55548761c62SAndrew Jeffery payload_length - PLDM_SET_FRU_RECORD_TABLE_MIN_REQ_BYTES;
55648761c62SAndrew Jeffery fru_table_data->ptr = req->fru_record_table_data;
55748761c62SAndrew Jeffery
55848761c62SAndrew Jeffery return PLDM_SUCCESS;
55948761c62SAndrew Jeffery }
56048761c62SAndrew Jeffery
56148761c62SAndrew Jeffery 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)56248761c62SAndrew Jeffery int encode_set_fru_record_table_resp(uint8_t instance_id,
56348761c62SAndrew Jeffery uint8_t completion_code,
56448761c62SAndrew Jeffery uint32_t next_data_transfer_handle,
56548761c62SAndrew Jeffery size_t payload_length,
56648761c62SAndrew Jeffery struct pldm_msg *msg)
56748761c62SAndrew Jeffery {
56848761c62SAndrew Jeffery if (msg == NULL) {
56948761c62SAndrew Jeffery return PLDM_ERROR_INVALID_DATA;
57048761c62SAndrew Jeffery }
57148761c62SAndrew Jeffery if (payload_length != PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES) {
57248761c62SAndrew Jeffery return PLDM_ERROR_INVALID_LENGTH;
57348761c62SAndrew Jeffery }
57448761c62SAndrew Jeffery
57548761c62SAndrew Jeffery struct pldm_header_info header = { 0 };
57648761c62SAndrew Jeffery header.instance = instance_id;
57748761c62SAndrew Jeffery header.msg_type = PLDM_RESPONSE;
57848761c62SAndrew Jeffery header.pldm_type = PLDM_FRU;
57948761c62SAndrew Jeffery header.command = PLDM_SET_FRU_RECORD_TABLE;
58048761c62SAndrew Jeffery
58148761c62SAndrew Jeffery uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
58248761c62SAndrew Jeffery if (PLDM_SUCCESS != rc) {
58348761c62SAndrew Jeffery return rc;
58448761c62SAndrew Jeffery }
58548761c62SAndrew Jeffery
58648761c62SAndrew Jeffery struct pldm_set_fru_record_table_resp *response =
58748761c62SAndrew Jeffery (struct pldm_set_fru_record_table_resp *)msg->payload;
58848761c62SAndrew Jeffery response->completion_code = completion_code;
58948761c62SAndrew Jeffery response->next_data_transfer_handle =
59048761c62SAndrew Jeffery htole32(next_data_transfer_handle);
59148761c62SAndrew Jeffery
59248761c62SAndrew Jeffery return PLDM_SUCCESS;
59348761c62SAndrew Jeffery }
594