blob: 910a4995125946b8b4827aa21d6f7404d10b0d70 [file] [log] [blame]
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05301#include "bios_table.h"
2#include "base.h"
3#include "bios.h"
4#include "utils.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09305#include <assert.h>
6#include <endian.h>
7#include <stdbool.h>
8#include <stdint.h>
9#include <stdlib.h>
10#include <string.h>
11
Andrew Jeffery9c766792022-08-10 23:12:49 +093012#define POINTER_CHECK(pointer) \
13 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +093014 if ((pointer) == NULL) \
Andrew Jeffery9c766792022-08-10 23:12:49 +093015 return PLDM_ERROR_INVALID_DATA; \
16 } while (0)
17
18#define ATTR_TYPE_EXPECT(type, expected) \
19 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +093020 if ((type) != (expected) && (type) != ((expected) | 0x80)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +093021 return PLDM_ERROR_INVALID_DATA; \
22 } while (0)
23
24#define BUFFER_SIZE_EXPECT(current_size, expected_size) \
25 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +093026 if ((current_size) < (expected_size)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +093027 return PLDM_ERROR_INVALID_LENGTH; \
28 } while (0)
29
30#define MEMBER_SIZE(type, member) sizeof(((struct type *)0)->member)
31
32static void set_errmsg(const char **errmsg, const char *msg)
33{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093034 if (errmsg != NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093035 *errmsg = msg;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093036 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093037}
38
Andrew Jefferya873eca2023-06-26 17:25:37 +093039static int get_bios_string_handle(uint16_t *val)
Andrew Jeffery9c766792022-08-10 23:12:49 +093040{
41 static uint16_t handle = 0;
42 assert(handle != UINT16_MAX);
Andrew Jefferya873eca2023-06-26 17:25:37 +093043 if (handle == UINT16_MAX) {
44 return PLDM_ERROR_INVALID_DATA;
45 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093046
Andrew Jefferya873eca2023-06-26 17:25:37 +093047 *val = handle++;
48 return PLDM_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +093049}
50
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093051LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093052size_t pldm_bios_table_string_entry_encode_length(uint16_t string_length)
53{
54 return sizeof(struct pldm_bios_string_table_entry) -
55 MEMBER_SIZE(pldm_bios_string_table_entry, name) + string_length;
56}
57
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093058LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093059int pldm_bios_table_string_entry_encode_check(void *entry, size_t entry_length,
60 const char *str,
61 uint16_t str_length)
62{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093063 if (str_length == 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093064 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093065 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093066 POINTER_CHECK(entry);
67 POINTER_CHECK(str);
68 size_t length = pldm_bios_table_string_entry_encode_length(str_length);
69 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +093070 struct pldm_bios_string_table_entry *string_entry = entry;
Andrew Jefferya873eca2023-06-26 17:25:37 +093071 uint16_t handle;
72 int rc = get_bios_string_handle(&handle);
73 if (rc != PLDM_SUCCESS) {
74 return rc;
75 }
76 string_entry->string_handle = htole16(handle);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +093077 string_entry->string_length = htole16(str_length);
78 memcpy(string_entry->name, str, str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +093079 return PLDM_SUCCESS;
80}
81
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093082LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093083uint16_t pldm_bios_table_string_entry_decode_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093084 const struct pldm_bios_string_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +093085{
86 return le16toh(entry->string_handle);
87}
88
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093089LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093090uint16_t pldm_bios_table_string_entry_decode_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093091 const struct pldm_bios_string_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +093092{
93 return le16toh(entry->string_length);
94}
95
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093096LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093097int pldm_bios_table_string_entry_decode_string_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093098 const struct pldm_bios_string_table_entry *entry, char *buffer,
99 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930100{
101 POINTER_CHECK(entry);
102 POINTER_CHECK(buffer);
Andrew Jeffery98c1e692023-06-14 14:41:19 +0930103 if (size == 0) {
104 return PLDM_ERROR_INVALID_LENGTH;
105 }
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930106 size_t length =
107 pldm_bios_table_string_entry_decode_string_length(entry);
108 length = length < (size - 1) ? length : (size - 1);
109 memcpy(buffer, entry->name, length);
110 buffer[length] = 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930111 return PLDM_SUCCESS;
112}
113
114static size_t string_table_entry_length(const void *table_entry)
115{
116 const struct pldm_bios_string_table_entry *entry = table_entry;
117 return sizeof(*entry) - sizeof(entry->name) +
118 pldm_bios_table_string_entry_decode_string_length(entry);
119}
120
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930121static int get_bios_attr_handle(uint16_t *val)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930122{
123 static uint16_t handle = 0;
124 assert(handle != UINT16_MAX);
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930125 if (handle == UINT16_MAX) {
126 return PLDM_ERROR_INVALID_DATA;
127 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930128
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930129 *val = handle++;
130 return PLDM_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930131}
132
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930133static int attr_table_entry_encode_header(void *entry, size_t length,
134 uint8_t attr_type,
135 uint16_t string_handle)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930136{
137 struct pldm_bios_attr_table_entry *attr_entry = entry;
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930138
Andrew Jeffery9c766792022-08-10 23:12:49 +0930139 assert(sizeof(*attr_entry) <= length);
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930140 if (sizeof(*attr_entry) > length) {
141 return PLDM_ERROR_INVALID_LENGTH;
142 }
143
144 uint16_t handle;
145 int rc = get_bios_attr_handle(&handle);
146 if (rc != PLDM_SUCCESS) {
147 return rc;
148 }
149
150 attr_entry->attr_handle = htole16(handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930151 attr_entry->attr_type = attr_type;
152 attr_entry->string_handle = htole16(string_handle);
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930153
154 return PLDM_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930155}
156
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930157LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930158uint16_t pldm_bios_table_attr_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930159 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930160{
161 return le16toh(entry->attr_handle);
162}
163
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930164LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930165uint8_t pldm_bios_table_attr_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930166 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930167{
168 return entry->attr_type;
169}
170
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930171LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930172uint16_t pldm_bios_table_attr_entry_decode_string_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930173 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930174{
175 return le16toh(entry->string_handle);
176}
177
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930178LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930179size_t pldm_bios_table_attr_entry_enum_encode_length(uint8_t pv_num,
180 uint8_t def_num)
181{
182 return sizeof(struct pldm_bios_attr_table_entry) -
183 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
184 sizeof(pv_num) + pv_num * sizeof(uint16_t) + sizeof(def_num) +
185 def_num;
186}
187
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930188LIBPLDM_ABI_STABLE
189int pldm_bios_table_attr_entry_enum_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930190 void *entry, size_t entry_length,
191 const struct pldm_bios_table_attr_entry_enum_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930192{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930193 POINTER_CHECK(entry);
194 POINTER_CHECK(info);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930195 size_t length = pldm_bios_table_attr_entry_enum_encode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930196 info->pv_num, info->def_num);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930197 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930198 uint8_t attr_type = info->read_only ? PLDM_BIOS_ENUMERATION_READ_ONLY :
199 PLDM_BIOS_ENUMERATION;
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930200 int rc = attr_table_entry_encode_header(entry, entry_length, attr_type,
201 info->name_handle);
202 if (rc != PLDM_SUCCESS) {
203 return rc;
204 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930205 struct pldm_bios_attr_table_entry *attr_entry = entry;
206 attr_entry->metadata[0] = info->pv_num;
207 uint16_t *pv_hdls =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930208 (uint16_t *)(attr_entry->metadata + 1 /* sizeof(pv num) */);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930209 size_t i;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930210 for (i = 0; i < info->pv_num; i++) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930211 pv_hdls[i] = htole16(info->pv_handle[i]);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930212 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930213 attr_entry->metadata[1 + info->pv_num * sizeof(uint16_t)] =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930214 info->def_num;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930215 memcpy(attr_entry->metadata + 1 /* sizeof(pv num) */ +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930216 info->pv_num * sizeof(uint16_t) + 1 /* sizeof(def num)*/,
Andrew Jeffery9c766792022-08-10 23:12:49 +0930217 info->def_index, info->def_num);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930218 return PLDM_SUCCESS;
219}
220
221#define ATTR_TYPE_EXPECT(type, expected) \
222 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930223 if ((type) != (expected) && (type) != ((expected) | 0x80)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +0930224 return PLDM_ERROR_INVALID_DATA; \
225 } while (0)
226
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930227LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930228int pldm_bios_table_attr_entry_enum_decode_pv_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930229 const struct pldm_bios_attr_table_entry *entry, uint8_t *pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930230{
231 POINTER_CHECK(entry);
232 POINTER_CHECK(pv_num);
233 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930234 *pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930235 return PLDM_SUCCESS;
236}
237
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930238static uint8_t pldm_bios_table_attr_entry_enum_decode_def_num(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930239 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930240{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930241 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930242 return entry->metadata[sizeof(uint8_t) /* pv_num */ +
243 sizeof(uint16_t) * pv_num];
244}
245
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930246LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930247int pldm_bios_table_attr_entry_enum_decode_def_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930248 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930249{
250 POINTER_CHECK(entry);
251 POINTER_CHECK(def_num);
252 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
253 *def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
254 return PLDM_SUCCESS;
255}
256
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930257LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930258int pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930259 const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
260 uint8_t pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930261{
262 POINTER_CHECK(entry);
263 POINTER_CHECK(pv_hdls);
264 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930265 uint8_t num = entry->metadata[0];
266 num = num < pv_num ? num : pv_num;
267 size_t i;
268 for (i = 0; i < num; i++) {
269 uint16_t *hdl = (uint16_t *)(entry->metadata + sizeof(uint8_t) +
270 i * sizeof(uint16_t));
271 pv_hdls[i] = le16toh(*hdl);
272 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930273 return PLDM_SUCCESS;
274}
275
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930276LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930277uint8_t pldm_bios_table_attr_entry_enum_decode_def_indices(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930278 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_indices,
279 uint8_t def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930280{
281 uint8_t num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
282 num = num < def_num ? num : def_num;
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930283 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930284 const uint8_t *p = entry->metadata +
285 sizeof(uint8_t) /* number of possible values*/
286 + pv_num * sizeof(uint16_t) /* possible values */
287 + sizeof(uint8_t); /* number of default values */
288 memcpy(def_indices, p, num);
289 return num;
290}
291
292/** @brief Get length of an enum attribute entry
293 */
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930294static size_t attr_table_entry_length_enum(const void *arg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930295{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930296 const struct pldm_bios_attr_table_entry *entry = arg;
297 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930298 uint8_t def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
299 return pldm_bios_table_attr_entry_enum_encode_length(pv_num, def_num);
300}
301
302struct attr_table_string_entry_fields {
303 uint8_t string_type;
304 uint16_t min_length;
305 uint16_t max_length;
306 uint16_t def_length;
307 uint8_t def_string[1];
308} __attribute__((packed));
309
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930310LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930311size_t pldm_bios_table_attr_entry_string_encode_length(uint16_t def_str_len)
312{
313 return sizeof(struct pldm_bios_attr_table_entry) -
314 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
315 sizeof(struct attr_table_string_entry_fields) -
316 MEMBER_SIZE(attr_table_string_entry_fields, def_string) +
317 def_str_len;
318}
319
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930320#define PLDM_STRING_TYPE_MAX 5
Andrew Jeffery9c766792022-08-10 23:12:49 +0930321#define PLDM_STRING_TYPE_VENDOR 0xff
322
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930323LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930324int pldm_bios_table_attr_entry_string_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930325 const struct pldm_bios_table_attr_entry_string_info *info,
326 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930327{
328 if (info->min_length > info->max_length) {
329 set_errmsg(errmsg, "MinimumStingLength should not be greater "
330 "than MaximumStringLength");
331 return PLDM_ERROR_INVALID_DATA;
332 }
333 if (info->min_length == info->max_length &&
334 info->def_length != info->min_length) {
335 set_errmsg(errmsg, "Wrong DefaultStringLength");
336 return PLDM_ERROR_INVALID_DATA;
337 }
338 if (info->def_length > info->max_length ||
339 info->def_length < info->min_length) {
340 set_errmsg(errmsg, "Wrong DefaultStringLength");
341 return PLDM_ERROR_INVALID_DATA;
342 }
343 if (info->string_type > PLDM_STRING_TYPE_MAX &&
344 info->string_type != PLDM_STRING_TYPE_VENDOR) {
345 set_errmsg(errmsg, "Wrong StringType");
346 return PLDM_ERROR_INVALID_DATA;
347 }
Andrew Jefferydf02e362023-06-14 14:52:25 +0930348 if (info->def_string && info->def_length != strlen(info->def_string)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930349 set_errmsg(errmsg, "Length of DefaultString should be equal to "
350 "DefaultStringLength");
351 return PLDM_ERROR_INVALID_DATA;
352 }
353
354 return PLDM_SUCCESS;
355}
356
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930357LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930358int pldm_bios_table_attr_entry_string_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930359 void *entry, size_t entry_length,
360 const struct pldm_bios_table_attr_entry_string_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930361{
362 POINTER_CHECK(entry);
363 POINTER_CHECK(info);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930364 size_t length = pldm_bios_table_attr_entry_string_encode_length(
365 info->def_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930366 BUFFER_SIZE_EXPECT(entry_length, length);
367 if (pldm_bios_table_attr_entry_string_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930368 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930369 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930370 }
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930371 uint8_t attr_type = info->read_only ? PLDM_BIOS_STRING_READ_ONLY :
372 PLDM_BIOS_STRING;
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930373 int rc = attr_table_entry_encode_header(entry, entry_length, attr_type,
374 info->name_handle);
375 if (rc != PLDM_SUCCESS) {
376 return rc;
377 }
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930378 struct pldm_bios_attr_table_entry *attr_entry = entry;
379 struct attr_table_string_entry_fields *attr_fields =
380 (struct attr_table_string_entry_fields *)attr_entry->metadata;
381 attr_fields->string_type = info->string_type;
382 attr_fields->min_length = htole16(info->min_length);
383 attr_fields->max_length = htole16(info->max_length);
384 attr_fields->def_length = htole16(info->def_length);
385 if (info->def_length != 0 && info->def_string != NULL) {
386 memcpy(attr_fields->def_string, info->def_string,
387 info->def_length);
388 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930389 return PLDM_SUCCESS;
390}
391
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930392static uint16_t pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930393 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930394{
395 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930396 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930397 return le16toh(fields->def_length);
398}
399
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930400LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930401int pldm_bios_table_attr_entry_string_decode_def_string_length_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930402 const struct pldm_bios_attr_table_entry *entry,
403 uint16_t *def_string_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930404{
405 POINTER_CHECK(entry);
406 POINTER_CHECK(def_string_length);
407 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_STRING);
408 *def_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930409 pldm_bios_table_attr_entry_string_decode_def_string_length(
410 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930411 return PLDM_SUCCESS;
412}
413
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930414LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930415uint8_t pldm_bios_table_attr_entry_string_decode_string_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930416 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930417{
418 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930419 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930420 return fields->string_type;
421}
422
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930423LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930424uint16_t pldm_bios_table_attr_entry_string_decode_max_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930425 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930426{
427 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930428 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930429 return le16toh(fields->max_length);
430}
431
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930432LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930433uint16_t pldm_bios_table_attr_entry_string_decode_min_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930434 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930435{
436 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930437 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930438 return le16toh(fields->min_length);
439}
440
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930441LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930442uint16_t pldm_bios_table_attr_entry_string_decode_def_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930443 const struct pldm_bios_attr_table_entry *entry, char *buffer,
444 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930445{
446 uint16_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930447 pldm_bios_table_attr_entry_string_decode_def_string_length(
448 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930449 length = length < (size - 1) ? length : (size - 1);
450 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930451 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930452 memcpy(buffer, fields->def_string, length);
453 buffer[length] = 0;
454 return length;
455}
456
457/** @brief Get length of a string attribute entry
458 */
459static size_t attr_table_entry_length_string(const void *entry)
460{
461 uint16_t def_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930462 pldm_bios_table_attr_entry_string_decode_def_string_length(
463 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930464 return pldm_bios_table_attr_entry_string_encode_length(def_str_len);
465}
466
467struct attr_table_integer_entry_fields {
468 uint64_t lower_bound;
469 uint64_t upper_bound;
470 uint32_t scalar_increment;
471 uint64_t default_value;
472} __attribute__((packed));
473
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930474LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930475size_t pldm_bios_table_attr_entry_integer_encode_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930476{
477 return sizeof(struct pldm_bios_attr_table_entry) - 1 +
478 sizeof(struct attr_table_integer_entry_fields);
479}
480
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930481LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930482void pldm_bios_table_attr_entry_integer_encode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930483 void *entry, size_t entry_length,
484 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930485{
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930486 int rc = pldm_bios_table_attr_entry_integer_encode_check(
487 entry, entry_length, info);
488 (void)rc;
489 assert(rc == PLDM_SUCCESS);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930490}
491
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930492LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930493int pldm_bios_table_attr_entry_integer_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930494 const struct pldm_bios_table_attr_entry_integer_info *info,
495 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930496{
497 if (info->lower_bound == info->upper_bound) {
498 if (info->default_value != info->lower_bound) {
499 set_errmsg(errmsg, "Wrong DefaultValue");
500 return PLDM_ERROR_INVALID_DATA;
501 }
502 if (info->scalar_increment != 0) {
503 set_errmsg(errmsg, "Wrong ScalarIncrement");
504 return PLDM_ERROR_INVALID_DATA;
505 }
506 return PLDM_SUCCESS;
507 }
508 if (info->lower_bound > info->upper_bound) {
509 set_errmsg(errmsg,
510 "LowerBound should not be greater than UpperBound");
511 return PLDM_ERROR_INVALID_DATA;
512 }
513 if (info->default_value > info->upper_bound ||
514 info->default_value < info->lower_bound) {
515 set_errmsg(errmsg, "Wrong DefaultValue");
516 return PLDM_ERROR_INVALID_DATA;
517 }
518 if (info->scalar_increment == 0) {
519 set_errmsg(errmsg, "ScalarIncrement should not be zero when "
520 "lower_bound != upper_bound");
521 return PLDM_ERROR_INVALID_DATA;
522 }
523 if ((info->default_value - info->lower_bound) %
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930524 info->scalar_increment !=
Andrew Jeffery9c766792022-08-10 23:12:49 +0930525 0) {
526 set_errmsg(errmsg, "Wrong DefaultValue or ScalarIncrement");
527 return PLDM_ERROR_INVALID_DATA;
528 }
529 return PLDM_SUCCESS;
530}
531
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930532LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930533int pldm_bios_table_attr_entry_integer_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930534 void *entry, size_t entry_length,
535 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930536{
537 POINTER_CHECK(entry);
538 POINTER_CHECK(info);
539 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
540 BUFFER_SIZE_EXPECT(entry_length, length);
541 if (pldm_bios_table_attr_entry_integer_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930542 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930543 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930544 }
Andrew Jefferyfe0f01d2023-06-27 11:51:58 +0930545 uint8_t attr_type = info->read_only ? PLDM_BIOS_INTEGER_READ_ONLY :
546 PLDM_BIOS_INTEGER;
547 int rc = attr_table_entry_encode_header(entry, entry_length, attr_type,
548 info->name_handle);
549 if (rc != PLDM_SUCCESS) {
550 return rc;
551 }
552 struct pldm_bios_attr_table_entry *attr_entry = entry;
553 struct attr_table_integer_entry_fields *attr_fields =
554 (struct attr_table_integer_entry_fields *)attr_entry->metadata;
555 attr_fields->lower_bound = htole64(info->lower_bound);
556 attr_fields->upper_bound = htole64(info->upper_bound);
557 attr_fields->scalar_increment = htole32(info->scalar_increment);
558 attr_fields->default_value = htole64(info->default_value);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930559 return PLDM_SUCCESS;
560}
561
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930562LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930563void pldm_bios_table_attr_entry_integer_decode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930564 const struct pldm_bios_attr_table_entry *entry, uint64_t *lower,
565 uint64_t *upper, uint32_t *scalar, uint64_t *def)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566{
567 struct attr_table_integer_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930568 (struct attr_table_integer_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930569 *lower = le64toh(fields->lower_bound);
570 *upper = le64toh(fields->upper_bound);
571 *scalar = le32toh(fields->scalar_increment);
572 *def = le64toh(fields->default_value);
573}
574
575static size_t attr_table_entry_length_integer(const void *entry)
576{
577 (void)entry;
578 return pldm_bios_table_attr_entry_integer_encode_length();
579}
580
581struct table_entry_length {
582 uint8_t attr_type;
583 size_t (*entry_length_handler)(const void *);
584};
585
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930586#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
Andrew Jeffery9c766792022-08-10 23:12:49 +0930587
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930588static const struct table_entry_length *
589find_table_entry_length_by_type(uint8_t attr_type,
590 const struct table_entry_length *handlers,
591 size_t count)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930592{
593 size_t i;
594 for (i = 0; i < count; i++) {
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930595 if (attr_type == handlers[i].attr_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930596 return &handlers[i];
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930597 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930598 }
599 return NULL;
600}
601
602static const struct table_entry_length attr_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930603 { .attr_type = PLDM_BIOS_ENUMERATION,
604 .entry_length_handler = attr_table_entry_length_enum },
605 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
606 .entry_length_handler = attr_table_entry_length_enum },
607 { .attr_type = PLDM_BIOS_STRING,
608 .entry_length_handler = attr_table_entry_length_string },
609 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
610 .entry_length_handler = attr_table_entry_length_string },
611 { .attr_type = PLDM_BIOS_INTEGER,
612 .entry_length_handler = attr_table_entry_length_integer },
613 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
614 .entry_length_handler = attr_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930615};
616
617static size_t attr_table_entry_length(const void *table_entry)
618{
619 const struct pldm_bios_attr_table_entry *entry = table_entry;
620 const struct table_entry_length *attr_table_entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930621 find_table_entry_length_by_type(entry->attr_type,
622 attr_table_entries,
623 ARRAY_SIZE(attr_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930624 assert(attr_table_entry != NULL);
625 assert(attr_table_entry->entry_length_handler != NULL);
626
627 return attr_table_entry->entry_length_handler(entry);
628}
629
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930630LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930631uint16_t pldm_bios_table_attr_value_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930632 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930633{
634 return le16toh(entry->attr_handle);
635}
636
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930637LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930638uint8_t pldm_bios_table_attr_value_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930639 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930640{
641 return entry->attr_type;
642}
643
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930644LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930645size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count)
646{
647 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
648 sizeof(count) + count;
649}
650
Andrew Jeffery7aeb7ed2023-06-27 13:13:36 +0930651LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930652void pldm_bios_table_attr_value_entry_encode_enum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930653 void *entry, size_t entry_length, uint16_t attr_handle,
654 uint8_t attr_type, uint8_t count, const uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930655{
Andrew Jeffery7aeb7ed2023-06-27 13:13:36 +0930656 int rc = pldm_bios_table_attr_value_entry_encode_enum_check(
657 entry, entry_length, attr_handle, attr_type, count, handles);
658 (void)rc;
659 assert(rc == PLDM_SUCCESS);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930660}
661
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930662LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930663uint8_t pldm_bios_table_attr_value_entry_enum_decode_number(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930664 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930665{
666 return entry->value[0];
667}
668
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930669LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930670uint8_t pldm_bios_table_attr_value_entry_enum_decode_handles(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930671 const struct pldm_bios_attr_val_table_entry *entry, uint8_t *handles,
672 uint8_t number)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930673{
674 uint8_t curr_num =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930675 pldm_bios_table_attr_value_entry_enum_decode_number(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930676 number = number < curr_num ? number : curr_num;
677 memcpy(handles, &entry->value[1], number);
678
679 return number;
680}
681
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930682LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930683int pldm_bios_table_attr_value_entry_encode_enum_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930684 void *entry, size_t entry_length, uint16_t attr_handle,
Andrew Jeffery7aeb7ed2023-06-27 13:13:36 +0930685 uint8_t attr_type, uint8_t count, const uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930686{
687 POINTER_CHECK(entry);
Andrew Jeffery7aeb7ed2023-06-27 13:13:36 +0930688 POINTER_CHECK(handles);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930689 if (count != 0 && handles == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930690 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930691 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930692 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_ENUMERATION);
693 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930694 pldm_bios_table_attr_value_entry_encode_enum_length(count);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930695 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery7aeb7ed2023-06-27 13:13:36 +0930696 struct pldm_bios_attr_val_table_entry *table_entry = entry;
697 table_entry->attr_handle = htole16(attr_handle);
698 table_entry->attr_type = attr_type;
699 table_entry->value[0] = count;
700 if (count != 0) {
701 memcpy(&table_entry->value[1], handles, count);
702 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930703 return PLDM_SUCCESS;
704}
705
706static size_t attr_value_table_entry_length_enum(const void *entry)
707{
708 uint8_t number =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930709 pldm_bios_table_attr_value_entry_enum_decode_number(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930710 return pldm_bios_table_attr_value_entry_encode_enum_length(number);
711}
712
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930713LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930714size_t
715pldm_bios_table_attr_value_entry_encode_string_length(uint16_t string_length)
716{
717 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
718 sizeof(string_length) + string_length;
719}
720
Andrew Jeffery2d663932023-06-27 14:19:15 +0930721LIBPLDM_ABI_DEPRECATED
Andrew Jeffery9c766792022-08-10 23:12:49 +0930722void pldm_bios_table_attr_value_entry_encode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930723 void *entry, size_t entry_length, uint16_t attr_handle,
724 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930725{
Andrew Jeffery2d663932023-06-27 14:19:15 +0930726 int rc = pldm_bios_table_attr_value_entry_encode_string_check(
727 entry, entry_length, attr_handle, attr_type, str_length, str);
728 (void)rc;
729 assert(rc == PLDM_SUCCESS);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930730}
731
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930732LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930733uint16_t pldm_bios_table_attr_value_entry_string_decode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930734 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930735{
736 uint16_t str_length = 0;
737 memcpy(&str_length, entry->value, sizeof(str_length));
738 return le16toh(str_length);
739}
740
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930741LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930742void pldm_bios_table_attr_value_entry_string_decode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930743 const struct pldm_bios_attr_val_table_entry *entry,
744 struct variable_field *current_string)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930745{
746 current_string->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930747 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930748 current_string->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930749 entry->value + sizeof(uint16_t); // sizeof(CurrentStringLength)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930750}
751
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930752LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930753int pldm_bios_table_attr_value_entry_encode_string_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930754 void *entry, size_t entry_length, uint16_t attr_handle,
755 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930756{
757 POINTER_CHECK(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930758 if (str_length != 0 && str == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930759 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930760 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930761 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_STRING);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930762 size_t length = pldm_bios_table_attr_value_entry_encode_string_length(
763 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930764 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery2d663932023-06-27 14:19:15 +0930765 struct pldm_bios_attr_val_table_entry *table_entry = entry;
766 table_entry->attr_handle = htole16(attr_handle);
767 table_entry->attr_type = attr_type;
768 if (str_length != 0) {
769 memcpy(table_entry->value + sizeof(str_length), str,
770 str_length);
771 }
772 str_length = htole16(str_length);
773 memcpy(table_entry->value, &str_length, sizeof(str_length));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930774 return PLDM_SUCCESS;
775}
776
777static size_t attr_value_table_entry_length_string(const void *entry)
778{
779 uint16_t str_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930780 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930781 return pldm_bios_table_attr_value_entry_encode_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930782 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930783}
784
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930785LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930786size_t pldm_bios_table_attr_value_entry_encode_integer_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930787{
788 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
789 sizeof(uint64_t);
790}
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930791
792LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930793void pldm_bios_table_attr_value_entry_encode_integer(void *entry,
794 size_t entry_length,
795 uint16_t attr_handle,
796 uint8_t attr_type,
797 uint64_t cv)
798{
Andrew Jeffery0088a6a2023-06-27 15:06:45 +0930799 int rc = pldm_bios_table_attr_value_entry_encode_integer_check(
800 entry, entry_length, attr_handle, attr_type, cv);
801 (void)rc;
802 assert(rc == PLDM_SUCCESS);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930803}
804
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930805LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930806int pldm_bios_table_attr_value_entry_encode_integer_check(void *entry,
807 size_t entry_length,
808 uint16_t attr_handle,
809 uint8_t attr_type,
810 uint64_t cv)
811{
812 POINTER_CHECK(entry);
813 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930814 pldm_bios_table_attr_value_entry_encode_integer_length();
Andrew Jeffery9c766792022-08-10 23:12:49 +0930815 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_INTEGER);
816 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery0088a6a2023-06-27 15:06:45 +0930817 struct pldm_bios_attr_val_table_entry *table_entry = entry;
818 table_entry->attr_handle = htole16(attr_handle);
819 table_entry->attr_type = attr_type;
820 cv = htole64(cv);
821 memcpy(table_entry->value, &cv, sizeof(uint64_t));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930822 return PLDM_SUCCESS;
823}
824
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930825LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930826uint64_t pldm_bios_table_attr_value_entry_integer_decode_cv(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930827 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930828{
829 uint64_t cv = 0;
830 memcpy(&cv, entry->value, sizeof(cv));
831 cv = le64toh(cv);
832 return cv;
833}
834
835static size_t attr_value_table_entry_length_integer(const void *entry)
836{
837 (void)entry;
838 return pldm_bios_table_attr_value_entry_encode_integer_length();
839}
840
841static const struct table_entry_length attr_value_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930842 { .attr_type = PLDM_BIOS_ENUMERATION,
843 .entry_length_handler = attr_value_table_entry_length_enum },
844 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
845 .entry_length_handler = attr_value_table_entry_length_enum },
846 { .attr_type = PLDM_BIOS_STRING,
847 .entry_length_handler = attr_value_table_entry_length_string },
848 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
849 .entry_length_handler = attr_value_table_entry_length_string },
850 { .attr_type = PLDM_BIOS_INTEGER,
851 .entry_length_handler = attr_value_table_entry_length_integer },
852 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
853 .entry_length_handler = attr_value_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930854};
855
856static size_t attr_value_table_entry_length(const void *table_entry)
857{
858 const struct pldm_bios_attr_val_table_entry *entry = table_entry;
859 const struct table_entry_length *entry_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930860 find_table_entry_length_by_type(
861 entry->attr_type, attr_value_table_entries,
862 ARRAY_SIZE(attr_value_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930863 assert(entry_length != NULL);
864 assert(entry_length->entry_length_handler != NULL);
865
866 return entry_length->entry_length_handler(entry);
867}
868
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930869LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930870size_t pldm_bios_table_attr_value_entry_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930871 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930872{
873 return attr_value_table_entry_length(entry);
874}
875
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930876LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930877uint16_t pldm_bios_table_attr_value_entry_decode_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930878 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930879{
880 return le16toh(entry->attr_handle);
881}
882
883static size_t pad_size_get(size_t size_without_pad)
884{
885 return ((size_without_pad % 4) ? (4 - size_without_pad % 4) : 0);
886}
887
888static uint8_t *pad_append(uint8_t *table_end, size_t pad_size)
889{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930890 while (pad_size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930891 *table_end++ = 0;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930892 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930893
894 return table_end;
895}
896
897static uint8_t *checksum_append(uint8_t *table_end, uint32_t checksum)
898{
899 checksum = htole32(checksum);
900 memcpy(table_end, &checksum, sizeof(checksum));
901
902 return table_end + sizeof(checksum);
903}
904
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930905LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930906size_t pldm_bios_table_pad_checksum_size(size_t size_without_pad)
907{
908 size_t size = pad_size_get(size_without_pad) +
909 sizeof(uint32_t) /*sizeof(checksum)*/;
910 return size;
911}
912
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930913LIBPLDM_ABI_STABLE
Andrew Jeffery044ee192023-06-28 11:26:00 +0930914size_t pldm_bios_table_append_pad_checksum(void *table, size_t capacity,
915 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930916{
Andrew Jeffery044ee192023-06-28 11:26:00 +0930917 int rc = pldm_bios_table_append_pad_checksum_check(table, capacity,
918 &size);
919 (void)rc;
920 assert(rc == PLDM_SUCCESS);
921 return size;
922}
Andrew Jeffery9c766792022-08-10 23:12:49 +0930923
Andrew Jeffery044ee192023-06-28 11:26:00 +0930924LIBPLDM_ABI_TESTING
925int pldm_bios_table_append_pad_checksum_check(void *table, size_t capacity,
926 size_t *size)
927{
928 if (!table || !size) {
929 return PLDM_ERROR_INVALID_DATA;
930 }
931
932 size_t pad_checksum_size = pldm_bios_table_pad_checksum_size(*size);
933 size_t total_length = *size + pad_checksum_size;
934 assert(capacity >= total_length);
935 if (capacity < total_length) {
936 return PLDM_ERROR_INVALID_LENGTH;
937 }
938
939 uint8_t *table_end = (uint8_t *)table + *size;
940 size_t pad_size = pad_size_get(*size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930941 table_end = pad_append(table_end, pad_size);
942
Andrew Jeffery044ee192023-06-28 11:26:00 +0930943 uint32_t checksum = crc32(table, *size + pad_size);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930944 checksum_append(table_end, checksum);
Andrew Jeffery044ee192023-06-28 11:26:00 +0930945 *size = total_length;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930946
Andrew Jeffery044ee192023-06-28 11:26:00 +0930947 return PLDM_SUCCESS;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930948}
949
950struct pldm_bios_table_iter {
951 const uint8_t *table_data;
952 size_t table_len;
953 size_t current_pos;
954 size_t (*entry_length_handler)(const void *table_entry);
955};
956
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930957LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930958struct pldm_bios_table_iter *
959pldm_bios_table_iter_create(const void *table, size_t length,
960 enum pldm_bios_table_types type)
961{
962 struct pldm_bios_table_iter *iter = malloc(sizeof(*iter));
963 assert(iter != NULL);
Andrew Jeffery757e81a2023-06-28 12:15:59 +0930964 if (!iter) {
965 return NULL;
966 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930967 iter->table_data = table;
968 iter->table_len = length;
969 iter->current_pos = 0;
970 iter->entry_length_handler = NULL;
971 switch (type) {
972 case PLDM_BIOS_STRING_TABLE:
973 iter->entry_length_handler = string_table_entry_length;
974 break;
975 case PLDM_BIOS_ATTR_TABLE:
976 iter->entry_length_handler = attr_table_entry_length;
977 break;
978 case PLDM_BIOS_ATTR_VAL_TABLE:
979 iter->entry_length_handler = attr_value_table_entry_length;
980 break;
981 }
982
983 return iter;
984}
985
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930986LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930987void pldm_bios_table_iter_free(struct pldm_bios_table_iter *iter)
988{
989 free(iter);
990}
991
992#define pad_and_check_max 7
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930993LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930994bool pldm_bios_table_iter_is_end(const struct pldm_bios_table_iter *iter)
995{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930996 if (iter->table_len - iter->current_pos <= pad_and_check_max) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930997 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930998 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930999 return false;
1000}
1001
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301002LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301003void pldm_bios_table_iter_next(struct pldm_bios_table_iter *iter)
1004{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301005 if (pldm_bios_table_iter_is_end(iter)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301006 return;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301007 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301008 const void *entry = iter->table_data + iter->current_pos;
1009 iter->current_pos += iter->entry_length_handler(entry);
1010}
1011
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301012LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301013const void *pldm_bios_table_iter_value(struct pldm_bios_table_iter *iter)
1014{
1015 return iter->table_data + iter->current_pos;
1016}
1017
1018typedef bool (*equal_handler)(const void *entry, const void *key);
1019
1020static const void *
1021pldm_bios_table_entry_find_by_iter(struct pldm_bios_table_iter *iter,
1022 const void *key, equal_handler equal)
1023{
1024 const void *entry;
1025 while (!pldm_bios_table_iter_is_end(iter)) {
1026 entry = pldm_bios_table_iter_value(iter);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301027 if (equal(entry, key)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301028 return entry;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301029 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301030 pldm_bios_table_iter_next(iter);
1031 }
1032 return NULL;
1033}
1034
1035static const void *
1036pldm_bios_table_entry_find_from_table(const void *table, size_t length,
1037 enum pldm_bios_table_types type,
1038 equal_handler equal, const void *key)
1039{
1040 struct pldm_bios_table_iter *iter =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301041 pldm_bios_table_iter_create(table, length, type);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301042 const void *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301043 pldm_bios_table_entry_find_by_iter(iter, key, equal);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301044 pldm_bios_table_iter_free(iter);
1045 return entry;
1046}
1047
1048static bool string_table_handle_equal(const void *entry, const void *key)
1049{
1050 const struct pldm_bios_string_table_entry *string_entry = entry;
1051 uint16_t handle = *(uint16_t *)key;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301052 if (pldm_bios_table_string_entry_decode_handle(string_entry) ==
1053 handle) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301054 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301055 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301056 return false;
1057}
1058
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301059LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301060const struct pldm_bios_string_table_entry *
1061pldm_bios_table_string_find_by_handle(const void *table, size_t length,
1062 uint16_t handle)
1063{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301064 return pldm_bios_table_entry_find_from_table(table, length,
1065 PLDM_BIOS_STRING_TABLE,
1066 string_table_handle_equal,
1067 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301068}
1069
1070struct string_equal_arg {
1071 uint16_t str_length;
1072 const char *str;
1073};
1074
1075static bool string_table_string_equal(const void *entry, const void *key)
1076{
1077 const struct pldm_bios_string_table_entry *string_entry = entry;
1078 const struct string_equal_arg *arg = key;
1079 if (arg->str_length !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301080 pldm_bios_table_string_entry_decode_string_length(string_entry)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301081 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301082 }
1083 if (memcmp(string_entry->name, arg->str, arg->str_length) != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301084 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301085 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301086 return true;
1087}
1088
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301089LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301090const struct pldm_bios_string_table_entry *
1091pldm_bios_table_string_find_by_string(const void *table, size_t length,
1092 const char *str)
1093{
1094 uint16_t str_length = strlen(str);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301095 struct string_equal_arg arg = { str_length, str };
1096 return pldm_bios_table_entry_find_from_table(table, length,
1097 PLDM_BIOS_STRING_TABLE,
1098 string_table_string_equal,
1099 &arg);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301100}
1101
1102static bool attr_table_handle_equal(const void *entry, const void *key)
1103{
1104 uint16_t handle = *(uint16_t *)key;
1105 return pldm_bios_table_attr_entry_decode_attribute_handle(entry) ==
1106 handle;
1107}
1108
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301109LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301110const struct pldm_bios_attr_table_entry *
1111pldm_bios_table_attr_find_by_handle(const void *table, size_t length,
1112 uint16_t handle)
1113{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301114 return pldm_bios_table_entry_find_from_table(table, length,
1115 PLDM_BIOS_ATTR_TABLE,
1116 attr_table_handle_equal,
1117 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301118}
1119
1120static bool attr_table_string_handle_equal(const void *entry, const void *key)
1121{
1122 uint16_t handle = *(uint16_t *)key;
1123 return pldm_bios_table_attr_entry_decode_string_handle(entry) == handle;
1124}
1125
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301126LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301127const struct pldm_bios_attr_table_entry *
1128pldm_bios_table_attr_find_by_string_handle(const void *table, size_t length,
1129 uint16_t handle)
1130{
1131 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301132 table, length, PLDM_BIOS_ATTR_TABLE,
1133 attr_table_string_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301134}
1135
1136static bool attr_value_table_handle_equal(const void *entry, const void *key)
1137{
1138 uint16_t handle = *(uint16_t *)key;
1139 return pldm_bios_table_attr_value_entry_decode_handle(entry) == handle;
1140}
1141
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301142LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301143const struct pldm_bios_attr_val_table_entry *
1144pldm_bios_table_attr_value_find_by_handle(const void *table, size_t length,
1145 uint16_t handle)
1146{
1147 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301148 table, length, PLDM_BIOS_ATTR_VAL_TABLE,
1149 attr_value_table_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301150}
1151
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301152LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301153int pldm_bios_table_attr_value_copy_and_update(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301154 const void *src_table, size_t src_length, void *dest_table,
1155 size_t *dest_length, const void *entry, size_t entry_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301156{
1157 struct pldm_bios_table_iter *iter = pldm_bios_table_iter_create(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301158 src_table, src_length, PLDM_BIOS_ATTR_VAL_TABLE);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301159
1160 int rc = PLDM_SUCCESS;
Andrew Jefferyfbe61d72023-04-05 20:28:23 +09301161 const struct pldm_bios_attr_val_table_entry *tmp;
1162 const struct pldm_bios_attr_val_table_entry *to_update = entry;
1163 size_t buffer_length = *dest_length;
1164 size_t copied_length = 0;
1165 size_t length = 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301166 while (!pldm_bios_table_iter_is_end(iter)) {
1167 tmp = pldm_bios_table_iter_attr_value_entry_value(iter);
1168 length = attr_value_table_entry_length(tmp);
1169
1170 /* we need the tmp's entry_length here, iter_next will calculate
1171 * it too, use current_pos directly to avoid calculating it
1172 * twice */
1173 iter->current_pos += length;
1174 if (tmp->attr_handle == to_update->attr_handle) {
1175 if (tmp->attr_type != to_update->attr_type) {
1176 rc = PLDM_ERROR_INVALID_DATA;
1177 goto out;
1178 }
1179 length = entry_length;
1180 tmp = entry;
1181 }
1182 if (copied_length + length > buffer_length) {
1183 rc = PLDM_ERROR_INVALID_LENGTH;
1184 goto out;
1185 }
1186 memcpy((uint8_t *)dest_table + copied_length, tmp, length);
1187 copied_length += length;
1188 }
1189
1190 size_t pad_checksum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301191 pldm_bios_table_pad_checksum_size(copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301192 if ((pad_checksum_size + copied_length) > buffer_length) {
1193 rc = PLDM_ERROR_INVALID_LENGTH;
1194 goto out;
1195 }
1196
1197 *dest_length = pldm_bios_table_append_pad_checksum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301198 dest_table, buffer_length, copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301199out:
1200 pldm_bios_table_iter_free(iter);
1201 return rc;
1202}
1203
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301204LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301205bool pldm_bios_table_checksum(const uint8_t *table, size_t size)
1206{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301207 if (table == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301208 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301209 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301210
1211 // 12: BIOSStringHandle(uint16) + BIOSStringLength(uint16) +
1212 // Variable(4) + checksum(uint32)
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301213 if (size < 12) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301214 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301215 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301216
1217 uint32_t src_crc = le32toh(*(uint32_t *)(table + size - 4));
1218 uint32_t dst_crc = crc32(table, size - 4);
1219
1220 return src_crc == dst_crc;
1221}