blob: dd7b09e9bbae7d7509c904c4ae94f557b0d7fbbe [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 Jeffery319304f2023-04-05 13:53:18 +0930121static uint16_t get_bios_attr_handle(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930122{
123 static uint16_t handle = 0;
124 assert(handle != UINT16_MAX);
125
126 return handle++;
127}
128
129static void attr_table_entry_encode_header(void *entry, size_t length,
130 uint8_t attr_type,
131 uint16_t string_handle)
132{
133 struct pldm_bios_attr_table_entry *attr_entry = entry;
134 assert(sizeof(*attr_entry) <= length);
135 attr_entry->attr_handle = htole16(get_bios_attr_handle());
136 attr_entry->attr_type = attr_type;
137 attr_entry->string_handle = htole16(string_handle);
138}
139
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930140LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930141uint16_t pldm_bios_table_attr_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930142 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930143{
144 return le16toh(entry->attr_handle);
145}
146
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930147LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930148uint8_t pldm_bios_table_attr_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930149 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930150{
151 return entry->attr_type;
152}
153
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930154LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930155uint16_t pldm_bios_table_attr_entry_decode_string_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930156 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930157{
158 return le16toh(entry->string_handle);
159}
160
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930161LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930162size_t pldm_bios_table_attr_entry_enum_encode_length(uint8_t pv_num,
163 uint8_t def_num)
164{
165 return sizeof(struct pldm_bios_attr_table_entry) -
166 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
167 sizeof(pv_num) + pv_num * sizeof(uint16_t) + sizeof(def_num) +
168 def_num;
169}
170
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930171LIBPLDM_ABI_STABLE
172int pldm_bios_table_attr_entry_enum_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930173 void *entry, size_t entry_length,
174 const struct pldm_bios_table_attr_entry_enum_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930175{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930176 POINTER_CHECK(entry);
177 POINTER_CHECK(info);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930178 size_t length = pldm_bios_table_attr_entry_enum_encode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930179 info->pv_num, info->def_num);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930180 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930181 assert(length <= entry_length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930182 uint8_t attr_type = info->read_only ? PLDM_BIOS_ENUMERATION_READ_ONLY :
183 PLDM_BIOS_ENUMERATION;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930184 attr_table_entry_encode_header(entry, entry_length, attr_type,
185 info->name_handle);
186 struct pldm_bios_attr_table_entry *attr_entry = entry;
187 attr_entry->metadata[0] = info->pv_num;
188 uint16_t *pv_hdls =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930189 (uint16_t *)(attr_entry->metadata + 1 /* sizeof(pv num) */);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930190 size_t i;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930191 for (i = 0; i < info->pv_num; i++) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930192 pv_hdls[i] = htole16(info->pv_handle[i]);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930193 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930194 attr_entry->metadata[1 + info->pv_num * sizeof(uint16_t)] =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930195 info->def_num;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930196 memcpy(attr_entry->metadata + 1 /* sizeof(pv num) */ +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930197 info->pv_num * sizeof(uint16_t) + 1 /* sizeof(def num)*/,
Andrew Jeffery9c766792022-08-10 23:12:49 +0930198 info->def_index, info->def_num);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930199 return PLDM_SUCCESS;
200}
201
202#define ATTR_TYPE_EXPECT(type, expected) \
203 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930204 if ((type) != (expected) && (type) != ((expected) | 0x80)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +0930205 return PLDM_ERROR_INVALID_DATA; \
206 } while (0)
207
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930208LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930209int pldm_bios_table_attr_entry_enum_decode_pv_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930210 const struct pldm_bios_attr_table_entry *entry, uint8_t *pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930211{
212 POINTER_CHECK(entry);
213 POINTER_CHECK(pv_num);
214 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930215 *pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930216 return PLDM_SUCCESS;
217}
218
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930219static uint8_t pldm_bios_table_attr_entry_enum_decode_def_num(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930220 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930221{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930222 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930223 return entry->metadata[sizeof(uint8_t) /* pv_num */ +
224 sizeof(uint16_t) * pv_num];
225}
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_def_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930229 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930230{
231 POINTER_CHECK(entry);
232 POINTER_CHECK(def_num);
233 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
234 *def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
235 return PLDM_SUCCESS;
236}
237
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930238LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930239int pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930240 const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
241 uint8_t pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930242{
243 POINTER_CHECK(entry);
244 POINTER_CHECK(pv_hdls);
245 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930246 uint8_t num = entry->metadata[0];
247 num = num < pv_num ? num : pv_num;
248 size_t i;
249 for (i = 0; i < num; i++) {
250 uint16_t *hdl = (uint16_t *)(entry->metadata + sizeof(uint8_t) +
251 i * sizeof(uint16_t));
252 pv_hdls[i] = le16toh(*hdl);
253 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930254 return PLDM_SUCCESS;
255}
256
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930257LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930258uint8_t pldm_bios_table_attr_entry_enum_decode_def_indices(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930259 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_indices,
260 uint8_t def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930261{
262 uint8_t num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
263 num = num < def_num ? num : def_num;
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930264 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930265 const uint8_t *p = entry->metadata +
266 sizeof(uint8_t) /* number of possible values*/
267 + pv_num * sizeof(uint16_t) /* possible values */
268 + sizeof(uint8_t); /* number of default values */
269 memcpy(def_indices, p, num);
270 return num;
271}
272
273/** @brief Get length of an enum attribute entry
274 */
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930275static size_t attr_table_entry_length_enum(const void *arg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930276{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930277 const struct pldm_bios_attr_table_entry *entry = arg;
278 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930279 uint8_t def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
280 return pldm_bios_table_attr_entry_enum_encode_length(pv_num, def_num);
281}
282
283struct attr_table_string_entry_fields {
284 uint8_t string_type;
285 uint16_t min_length;
286 uint16_t max_length;
287 uint16_t def_length;
288 uint8_t def_string[1];
289} __attribute__((packed));
290
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930291LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930292size_t pldm_bios_table_attr_entry_string_encode_length(uint16_t def_str_len)
293{
294 return sizeof(struct pldm_bios_attr_table_entry) -
295 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
296 sizeof(struct attr_table_string_entry_fields) -
297 MEMBER_SIZE(attr_table_string_entry_fields, def_string) +
298 def_str_len;
299}
300
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930301#define PLDM_STRING_TYPE_MAX 5
Andrew Jeffery9c766792022-08-10 23:12:49 +0930302#define PLDM_STRING_TYPE_VENDOR 0xff
303
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930304LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930305int pldm_bios_table_attr_entry_string_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930306 const struct pldm_bios_table_attr_entry_string_info *info,
307 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930308{
309 if (info->min_length > info->max_length) {
310 set_errmsg(errmsg, "MinimumStingLength should not be greater "
311 "than MaximumStringLength");
312 return PLDM_ERROR_INVALID_DATA;
313 }
314 if (info->min_length == info->max_length &&
315 info->def_length != info->min_length) {
316 set_errmsg(errmsg, "Wrong DefaultStringLength");
317 return PLDM_ERROR_INVALID_DATA;
318 }
319 if (info->def_length > info->max_length ||
320 info->def_length < info->min_length) {
321 set_errmsg(errmsg, "Wrong DefaultStringLength");
322 return PLDM_ERROR_INVALID_DATA;
323 }
324 if (info->string_type > PLDM_STRING_TYPE_MAX &&
325 info->string_type != PLDM_STRING_TYPE_VENDOR) {
326 set_errmsg(errmsg, "Wrong StringType");
327 return PLDM_ERROR_INVALID_DATA;
328 }
Andrew Jefferydf02e362023-06-14 14:52:25 +0930329 if (info->def_string && info->def_length != strlen(info->def_string)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930330 set_errmsg(errmsg, "Length of DefaultString should be equal to "
331 "DefaultStringLength");
332 return PLDM_ERROR_INVALID_DATA;
333 }
334
335 return PLDM_SUCCESS;
336}
337
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930338LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930339int pldm_bios_table_attr_entry_string_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930340 void *entry, size_t entry_length,
341 const struct pldm_bios_table_attr_entry_string_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930342{
343 POINTER_CHECK(entry);
344 POINTER_CHECK(info);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930345 size_t length = pldm_bios_table_attr_entry_string_encode_length(
346 info->def_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930347 BUFFER_SIZE_EXPECT(entry_length, length);
348 if (pldm_bios_table_attr_entry_string_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930349 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930350 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930351 }
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930352 uint8_t attr_type = info->read_only ? PLDM_BIOS_STRING_READ_ONLY :
353 PLDM_BIOS_STRING;
354 attr_table_entry_encode_header(entry, entry_length, attr_type,
355 info->name_handle);
356 struct pldm_bios_attr_table_entry *attr_entry = entry;
357 struct attr_table_string_entry_fields *attr_fields =
358 (struct attr_table_string_entry_fields *)attr_entry->metadata;
359 attr_fields->string_type = info->string_type;
360 attr_fields->min_length = htole16(info->min_length);
361 attr_fields->max_length = htole16(info->max_length);
362 attr_fields->def_length = htole16(info->def_length);
363 if (info->def_length != 0 && info->def_string != NULL) {
364 memcpy(attr_fields->def_string, info->def_string,
365 info->def_length);
366 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930367 return PLDM_SUCCESS;
368}
369
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930370static uint16_t pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930371 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930372{
373 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930374 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930375 return le16toh(fields->def_length);
376}
377
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930378LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930379int pldm_bios_table_attr_entry_string_decode_def_string_length_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930380 const struct pldm_bios_attr_table_entry *entry,
381 uint16_t *def_string_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930382{
383 POINTER_CHECK(entry);
384 POINTER_CHECK(def_string_length);
385 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_STRING);
386 *def_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930387 pldm_bios_table_attr_entry_string_decode_def_string_length(
388 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930389 return PLDM_SUCCESS;
390}
391
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930392LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930393uint8_t pldm_bios_table_attr_entry_string_decode_string_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930394 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930395{
396 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930397 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930398 return fields->string_type;
399}
400
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930401LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930402uint16_t pldm_bios_table_attr_entry_string_decode_max_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930403 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930404{
405 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930406 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930407 return le16toh(fields->max_length);
408}
409
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930410LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930411uint16_t pldm_bios_table_attr_entry_string_decode_min_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930412 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930413{
414 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930415 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930416 return le16toh(fields->min_length);
417}
418
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930419LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930420uint16_t pldm_bios_table_attr_entry_string_decode_def_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930421 const struct pldm_bios_attr_table_entry *entry, char *buffer,
422 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930423{
424 uint16_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930425 pldm_bios_table_attr_entry_string_decode_def_string_length(
426 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930427 length = length < (size - 1) ? length : (size - 1);
428 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930429 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930430 memcpy(buffer, fields->def_string, length);
431 buffer[length] = 0;
432 return length;
433}
434
435/** @brief Get length of a string attribute entry
436 */
437static size_t attr_table_entry_length_string(const void *entry)
438{
439 uint16_t def_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930440 pldm_bios_table_attr_entry_string_decode_def_string_length(
441 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930442 return pldm_bios_table_attr_entry_string_encode_length(def_str_len);
443}
444
445struct attr_table_integer_entry_fields {
446 uint64_t lower_bound;
447 uint64_t upper_bound;
448 uint32_t scalar_increment;
449 uint64_t default_value;
450} __attribute__((packed));
451
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930452LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930453size_t pldm_bios_table_attr_entry_integer_encode_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930454{
455 return sizeof(struct pldm_bios_attr_table_entry) - 1 +
456 sizeof(struct attr_table_integer_entry_fields);
457}
458
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930459LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930460void pldm_bios_table_attr_entry_integer_encode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930461 void *entry, size_t entry_length,
462 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930463{
464 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
465 assert(length <= entry_length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930466 uint8_t attr_type = info->read_only ? PLDM_BIOS_INTEGER_READ_ONLY :
467 PLDM_BIOS_INTEGER;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930468 attr_table_entry_encode_header(entry, entry_length, attr_type,
469 info->name_handle);
470 struct pldm_bios_attr_table_entry *attr_entry = entry;
471 struct attr_table_integer_entry_fields *attr_fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930472 (struct attr_table_integer_entry_fields *)attr_entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930473 attr_fields->lower_bound = htole64(info->lower_bound);
474 attr_fields->upper_bound = htole64(info->upper_bound);
475 attr_fields->scalar_increment = htole32(info->scalar_increment);
476 attr_fields->default_value = htole64(info->default_value);
477}
478
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930479LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930480int pldm_bios_table_attr_entry_integer_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930481 const struct pldm_bios_table_attr_entry_integer_info *info,
482 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930483{
484 if (info->lower_bound == info->upper_bound) {
485 if (info->default_value != info->lower_bound) {
486 set_errmsg(errmsg, "Wrong DefaultValue");
487 return PLDM_ERROR_INVALID_DATA;
488 }
489 if (info->scalar_increment != 0) {
490 set_errmsg(errmsg, "Wrong ScalarIncrement");
491 return PLDM_ERROR_INVALID_DATA;
492 }
493 return PLDM_SUCCESS;
494 }
495 if (info->lower_bound > info->upper_bound) {
496 set_errmsg(errmsg,
497 "LowerBound should not be greater than UpperBound");
498 return PLDM_ERROR_INVALID_DATA;
499 }
500 if (info->default_value > info->upper_bound ||
501 info->default_value < info->lower_bound) {
502 set_errmsg(errmsg, "Wrong DefaultValue");
503 return PLDM_ERROR_INVALID_DATA;
504 }
505 if (info->scalar_increment == 0) {
506 set_errmsg(errmsg, "ScalarIncrement should not be zero when "
507 "lower_bound != upper_bound");
508 return PLDM_ERROR_INVALID_DATA;
509 }
510 if ((info->default_value - info->lower_bound) %
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930511 info->scalar_increment !=
Andrew Jeffery9c766792022-08-10 23:12:49 +0930512 0) {
513 set_errmsg(errmsg, "Wrong DefaultValue or ScalarIncrement");
514 return PLDM_ERROR_INVALID_DATA;
515 }
516 return PLDM_SUCCESS;
517}
518
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930519LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930520int pldm_bios_table_attr_entry_integer_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930521 void *entry, size_t entry_length,
522 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930523{
524 POINTER_CHECK(entry);
525 POINTER_CHECK(info);
526 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
527 BUFFER_SIZE_EXPECT(entry_length, length);
528 if (pldm_bios_table_attr_entry_integer_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930529 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930530 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930531 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930532 pldm_bios_table_attr_entry_integer_encode(entry, entry_length, info);
533 return PLDM_SUCCESS;
534}
535
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930536LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930537void pldm_bios_table_attr_entry_integer_decode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930538 const struct pldm_bios_attr_table_entry *entry, uint64_t *lower,
539 uint64_t *upper, uint32_t *scalar, uint64_t *def)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930540{
541 struct attr_table_integer_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930542 (struct attr_table_integer_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930543 *lower = le64toh(fields->lower_bound);
544 *upper = le64toh(fields->upper_bound);
545 *scalar = le32toh(fields->scalar_increment);
546 *def = le64toh(fields->default_value);
547}
548
549static size_t attr_table_entry_length_integer(const void *entry)
550{
551 (void)entry;
552 return pldm_bios_table_attr_entry_integer_encode_length();
553}
554
555struct table_entry_length {
556 uint8_t attr_type;
557 size_t (*entry_length_handler)(const void *);
558};
559
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930560#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
Andrew Jeffery9c766792022-08-10 23:12:49 +0930561
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930562static const struct table_entry_length *
563find_table_entry_length_by_type(uint8_t attr_type,
564 const struct table_entry_length *handlers,
565 size_t count)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930566{
567 size_t i;
568 for (i = 0; i < count; i++) {
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930569 if (attr_type == handlers[i].attr_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930570 return &handlers[i];
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930571 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930572 }
573 return NULL;
574}
575
576static const struct table_entry_length attr_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930577 { .attr_type = PLDM_BIOS_ENUMERATION,
578 .entry_length_handler = attr_table_entry_length_enum },
579 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
580 .entry_length_handler = attr_table_entry_length_enum },
581 { .attr_type = PLDM_BIOS_STRING,
582 .entry_length_handler = attr_table_entry_length_string },
583 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
584 .entry_length_handler = attr_table_entry_length_string },
585 { .attr_type = PLDM_BIOS_INTEGER,
586 .entry_length_handler = attr_table_entry_length_integer },
587 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
588 .entry_length_handler = attr_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930589};
590
591static size_t attr_table_entry_length(const void *table_entry)
592{
593 const struct pldm_bios_attr_table_entry *entry = table_entry;
594 const struct table_entry_length *attr_table_entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930595 find_table_entry_length_by_type(entry->attr_type,
596 attr_table_entries,
597 ARRAY_SIZE(attr_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930598 assert(attr_table_entry != NULL);
599 assert(attr_table_entry->entry_length_handler != NULL);
600
601 return attr_table_entry->entry_length_handler(entry);
602}
603
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930604LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930605uint16_t pldm_bios_table_attr_value_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930606 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930607{
608 return le16toh(entry->attr_handle);
609}
610
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930611LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930612uint8_t pldm_bios_table_attr_value_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930613 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930614{
615 return entry->attr_type;
616}
617
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930618LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930619size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count)
620{
621 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
622 sizeof(count) + count;
623}
624
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930625LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930626void pldm_bios_table_attr_value_entry_encode_enum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930627 void *entry, size_t entry_length, uint16_t attr_handle,
628 uint8_t attr_type, uint8_t count, const uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930629{
630 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930631 pldm_bios_table_attr_value_entry_encode_enum_length(count);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930632 assert(length <= entry_length);
633
634 struct pldm_bios_attr_val_table_entry *table_entry = entry;
635 table_entry->attr_handle = htole16(attr_handle);
636 table_entry->attr_type = attr_type;
637 table_entry->value[0] = count;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930638 if (count != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930639 memcpy(&table_entry->value[1], handles, count);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930640 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930641}
642
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930643LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930644uint8_t pldm_bios_table_attr_value_entry_enum_decode_number(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930645 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930646{
647 return entry->value[0];
648}
649
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930650LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930651uint8_t pldm_bios_table_attr_value_entry_enum_decode_handles(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930652 const struct pldm_bios_attr_val_table_entry *entry, uint8_t *handles,
653 uint8_t number)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930654{
655 uint8_t curr_num =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930656 pldm_bios_table_attr_value_entry_enum_decode_number(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930657 number = number < curr_num ? number : curr_num;
658 memcpy(handles, &entry->value[1], number);
659
660 return number;
661}
662
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930663LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930664int pldm_bios_table_attr_value_entry_encode_enum_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930665 void *entry, size_t entry_length, uint16_t attr_handle,
666 uint8_t attr_type, uint8_t count, uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930667{
668 POINTER_CHECK(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930669 if (count != 0 && handles == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930670 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930671 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930672 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_ENUMERATION);
673 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930674 pldm_bios_table_attr_value_entry_encode_enum_length(count);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930675 BUFFER_SIZE_EXPECT(entry_length, length);
676 pldm_bios_table_attr_value_entry_encode_enum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930677 entry, entry_length, attr_handle, attr_type, count, handles);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930678 return PLDM_SUCCESS;
679}
680
681static size_t attr_value_table_entry_length_enum(const void *entry)
682{
683 uint8_t number =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930684 pldm_bios_table_attr_value_entry_enum_decode_number(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930685 return pldm_bios_table_attr_value_entry_encode_enum_length(number);
686}
687
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930688LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930689size_t
690pldm_bios_table_attr_value_entry_encode_string_length(uint16_t string_length)
691{
692 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
693 sizeof(string_length) + string_length;
694}
695
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930696LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930697void pldm_bios_table_attr_value_entry_encode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930698 void *entry, size_t entry_length, uint16_t attr_handle,
699 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930700{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930701 size_t length = pldm_bios_table_attr_value_entry_encode_string_length(
702 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930703 assert(length <= entry_length);
704
705 struct pldm_bios_attr_val_table_entry *table_entry = entry;
706 table_entry->attr_handle = htole16(attr_handle);
707 table_entry->attr_type = attr_type;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930708 if (str_length != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930709 memcpy(table_entry->value + sizeof(str_length), str,
710 str_length);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930711 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930712 str_length = htole16(str_length);
713 memcpy(table_entry->value, &str_length, sizeof(str_length));
714}
715
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930716LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930717uint16_t pldm_bios_table_attr_value_entry_string_decode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930718 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930719{
720 uint16_t str_length = 0;
721 memcpy(&str_length, entry->value, sizeof(str_length));
722 return le16toh(str_length);
723}
724
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930725LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930726void pldm_bios_table_attr_value_entry_string_decode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930727 const struct pldm_bios_attr_val_table_entry *entry,
728 struct variable_field *current_string)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930729{
730 current_string->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930731 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930732 current_string->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930733 entry->value + sizeof(uint16_t); // sizeof(CurrentStringLength)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930734}
735
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930736LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930737int pldm_bios_table_attr_value_entry_encode_string_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930738 void *entry, size_t entry_length, uint16_t attr_handle,
739 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930740{
741 POINTER_CHECK(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930742 if (str_length != 0 && str == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930743 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930744 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930745 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_STRING);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930746 size_t length = pldm_bios_table_attr_value_entry_encode_string_length(
747 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930748 BUFFER_SIZE_EXPECT(entry_length, length);
749 pldm_bios_table_attr_value_entry_encode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930750 entry, entry_length, attr_handle, attr_type, str_length, str);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930751 return PLDM_SUCCESS;
752}
753
754static size_t attr_value_table_entry_length_string(const void *entry)
755{
756 uint16_t str_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930757 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930758 return pldm_bios_table_attr_value_entry_encode_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930759 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930760}
761
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930762LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930763size_t pldm_bios_table_attr_value_entry_encode_integer_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930764{
765 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
766 sizeof(uint64_t);
767}
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930768
769LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930770void pldm_bios_table_attr_value_entry_encode_integer(void *entry,
771 size_t entry_length,
772 uint16_t attr_handle,
773 uint8_t attr_type,
774 uint64_t cv)
775{
776 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930777 pldm_bios_table_attr_value_entry_encode_integer_length();
Andrew Jeffery9c766792022-08-10 23:12:49 +0930778 assert(length <= entry_length);
779
780 struct pldm_bios_attr_val_table_entry *table_entry = entry;
781 table_entry->attr_handle = htole16(attr_handle);
782 table_entry->attr_type = attr_type;
783 cv = htole64(cv);
784 memcpy(table_entry->value, &cv, sizeof(uint64_t));
785}
786
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930787LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930788int pldm_bios_table_attr_value_entry_encode_integer_check(void *entry,
789 size_t entry_length,
790 uint16_t attr_handle,
791 uint8_t attr_type,
792 uint64_t cv)
793{
794 POINTER_CHECK(entry);
795 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930796 pldm_bios_table_attr_value_entry_encode_integer_length();
Andrew Jeffery9c766792022-08-10 23:12:49 +0930797 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_INTEGER);
798 BUFFER_SIZE_EXPECT(entry_length, length);
799 pldm_bios_table_attr_value_entry_encode_integer(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930800 entry, entry_length, attr_handle, attr_type, cv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930801 return PLDM_SUCCESS;
802}
803
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930804LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930805uint64_t pldm_bios_table_attr_value_entry_integer_decode_cv(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930806 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930807{
808 uint64_t cv = 0;
809 memcpy(&cv, entry->value, sizeof(cv));
810 cv = le64toh(cv);
811 return cv;
812}
813
814static size_t attr_value_table_entry_length_integer(const void *entry)
815{
816 (void)entry;
817 return pldm_bios_table_attr_value_entry_encode_integer_length();
818}
819
820static const struct table_entry_length attr_value_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930821 { .attr_type = PLDM_BIOS_ENUMERATION,
822 .entry_length_handler = attr_value_table_entry_length_enum },
823 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
824 .entry_length_handler = attr_value_table_entry_length_enum },
825 { .attr_type = PLDM_BIOS_STRING,
826 .entry_length_handler = attr_value_table_entry_length_string },
827 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
828 .entry_length_handler = attr_value_table_entry_length_string },
829 { .attr_type = PLDM_BIOS_INTEGER,
830 .entry_length_handler = attr_value_table_entry_length_integer },
831 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
832 .entry_length_handler = attr_value_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930833};
834
835static size_t attr_value_table_entry_length(const void *table_entry)
836{
837 const struct pldm_bios_attr_val_table_entry *entry = table_entry;
838 const struct table_entry_length *entry_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930839 find_table_entry_length_by_type(
840 entry->attr_type, attr_value_table_entries,
841 ARRAY_SIZE(attr_value_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930842 assert(entry_length != NULL);
843 assert(entry_length->entry_length_handler != NULL);
844
845 return entry_length->entry_length_handler(entry);
846}
847
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930848LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930849size_t pldm_bios_table_attr_value_entry_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930850 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930851{
852 return attr_value_table_entry_length(entry);
853}
854
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930855LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930856uint16_t pldm_bios_table_attr_value_entry_decode_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930857 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930858{
859 return le16toh(entry->attr_handle);
860}
861
862static size_t pad_size_get(size_t size_without_pad)
863{
864 return ((size_without_pad % 4) ? (4 - size_without_pad % 4) : 0);
865}
866
867static uint8_t *pad_append(uint8_t *table_end, size_t pad_size)
868{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930869 while (pad_size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930870 *table_end++ = 0;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930871 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930872
873 return table_end;
874}
875
876static uint8_t *checksum_append(uint8_t *table_end, uint32_t checksum)
877{
878 checksum = htole32(checksum);
879 memcpy(table_end, &checksum, sizeof(checksum));
880
881 return table_end + sizeof(checksum);
882}
883
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930884LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930885size_t pldm_bios_table_pad_checksum_size(size_t size_without_pad)
886{
887 size_t size = pad_size_get(size_without_pad) +
888 sizeof(uint32_t) /*sizeof(checksum)*/;
889 return size;
890}
891
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930892LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930893size_t pldm_bios_table_append_pad_checksum(void *table, size_t size,
894 size_t size_without_pad)
895{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930896 size_t pad_checksum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930897 pldm_bios_table_pad_checksum_size(size_without_pad);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930898 size_t total_length = size_without_pad + pad_checksum_size;
899 assert(size >= total_length);
900
901 uint8_t *table_end = (uint8_t *)table + size_without_pad;
902 size_t pad_size = pad_size_get(size_without_pad);
903 table_end = pad_append(table_end, pad_size);
904
905 uint32_t checksum = crc32(table, size_without_pad + pad_size);
906 checksum_append(table_end, checksum);
907
908 return total_length;
909}
910
911struct pldm_bios_table_iter {
912 const uint8_t *table_data;
913 size_t table_len;
914 size_t current_pos;
915 size_t (*entry_length_handler)(const void *table_entry);
916};
917
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930918LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930919struct pldm_bios_table_iter *
920pldm_bios_table_iter_create(const void *table, size_t length,
921 enum pldm_bios_table_types type)
922{
923 struct pldm_bios_table_iter *iter = malloc(sizeof(*iter));
924 assert(iter != NULL);
925 iter->table_data = table;
926 iter->table_len = length;
927 iter->current_pos = 0;
928 iter->entry_length_handler = NULL;
929 switch (type) {
930 case PLDM_BIOS_STRING_TABLE:
931 iter->entry_length_handler = string_table_entry_length;
932 break;
933 case PLDM_BIOS_ATTR_TABLE:
934 iter->entry_length_handler = attr_table_entry_length;
935 break;
936 case PLDM_BIOS_ATTR_VAL_TABLE:
937 iter->entry_length_handler = attr_value_table_entry_length;
938 break;
939 }
940
941 return iter;
942}
943
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930944LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930945void pldm_bios_table_iter_free(struct pldm_bios_table_iter *iter)
946{
947 free(iter);
948}
949
950#define pad_and_check_max 7
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930951LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930952bool pldm_bios_table_iter_is_end(const struct pldm_bios_table_iter *iter)
953{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930954 if (iter->table_len - iter->current_pos <= pad_and_check_max) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930955 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930956 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930957 return false;
958}
959
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930960LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930961void pldm_bios_table_iter_next(struct pldm_bios_table_iter *iter)
962{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930963 if (pldm_bios_table_iter_is_end(iter)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930964 return;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930965 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930966 const void *entry = iter->table_data + iter->current_pos;
967 iter->current_pos += iter->entry_length_handler(entry);
968}
969
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930970LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930971const void *pldm_bios_table_iter_value(struct pldm_bios_table_iter *iter)
972{
973 return iter->table_data + iter->current_pos;
974}
975
976typedef bool (*equal_handler)(const void *entry, const void *key);
977
978static const void *
979pldm_bios_table_entry_find_by_iter(struct pldm_bios_table_iter *iter,
980 const void *key, equal_handler equal)
981{
982 const void *entry;
983 while (!pldm_bios_table_iter_is_end(iter)) {
984 entry = pldm_bios_table_iter_value(iter);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930985 if (equal(entry, key)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930986 return entry;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930987 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930988 pldm_bios_table_iter_next(iter);
989 }
990 return NULL;
991}
992
993static const void *
994pldm_bios_table_entry_find_from_table(const void *table, size_t length,
995 enum pldm_bios_table_types type,
996 equal_handler equal, const void *key)
997{
998 struct pldm_bios_table_iter *iter =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930999 pldm_bios_table_iter_create(table, length, type);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301000 const void *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301001 pldm_bios_table_entry_find_by_iter(iter, key, equal);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301002 pldm_bios_table_iter_free(iter);
1003 return entry;
1004}
1005
1006static bool string_table_handle_equal(const void *entry, const void *key)
1007{
1008 const struct pldm_bios_string_table_entry *string_entry = entry;
1009 uint16_t handle = *(uint16_t *)key;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301010 if (pldm_bios_table_string_entry_decode_handle(string_entry) ==
1011 handle) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301012 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301013 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301014 return false;
1015}
1016
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301017LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301018const struct pldm_bios_string_table_entry *
1019pldm_bios_table_string_find_by_handle(const void *table, size_t length,
1020 uint16_t handle)
1021{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301022 return pldm_bios_table_entry_find_from_table(table, length,
1023 PLDM_BIOS_STRING_TABLE,
1024 string_table_handle_equal,
1025 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301026}
1027
1028struct string_equal_arg {
1029 uint16_t str_length;
1030 const char *str;
1031};
1032
1033static bool string_table_string_equal(const void *entry, const void *key)
1034{
1035 const struct pldm_bios_string_table_entry *string_entry = entry;
1036 const struct string_equal_arg *arg = key;
1037 if (arg->str_length !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301038 pldm_bios_table_string_entry_decode_string_length(string_entry)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301039 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301040 }
1041 if (memcmp(string_entry->name, arg->str, arg->str_length) != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301042 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301043 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301044 return true;
1045}
1046
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301047LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301048const struct pldm_bios_string_table_entry *
1049pldm_bios_table_string_find_by_string(const void *table, size_t length,
1050 const char *str)
1051{
1052 uint16_t str_length = strlen(str);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301053 struct string_equal_arg arg = { str_length, str };
1054 return pldm_bios_table_entry_find_from_table(table, length,
1055 PLDM_BIOS_STRING_TABLE,
1056 string_table_string_equal,
1057 &arg);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301058}
1059
1060static bool attr_table_handle_equal(const void *entry, const void *key)
1061{
1062 uint16_t handle = *(uint16_t *)key;
1063 return pldm_bios_table_attr_entry_decode_attribute_handle(entry) ==
1064 handle;
1065}
1066
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301067LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301068const struct pldm_bios_attr_table_entry *
1069pldm_bios_table_attr_find_by_handle(const void *table, size_t length,
1070 uint16_t handle)
1071{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301072 return pldm_bios_table_entry_find_from_table(table, length,
1073 PLDM_BIOS_ATTR_TABLE,
1074 attr_table_handle_equal,
1075 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301076}
1077
1078static bool attr_table_string_handle_equal(const void *entry, const void *key)
1079{
1080 uint16_t handle = *(uint16_t *)key;
1081 return pldm_bios_table_attr_entry_decode_string_handle(entry) == handle;
1082}
1083
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301084LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301085const struct pldm_bios_attr_table_entry *
1086pldm_bios_table_attr_find_by_string_handle(const void *table, size_t length,
1087 uint16_t handle)
1088{
1089 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301090 table, length, PLDM_BIOS_ATTR_TABLE,
1091 attr_table_string_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301092}
1093
1094static bool attr_value_table_handle_equal(const void *entry, const void *key)
1095{
1096 uint16_t handle = *(uint16_t *)key;
1097 return pldm_bios_table_attr_value_entry_decode_handle(entry) == handle;
1098}
1099
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301100LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301101const struct pldm_bios_attr_val_table_entry *
1102pldm_bios_table_attr_value_find_by_handle(const void *table, size_t length,
1103 uint16_t handle)
1104{
1105 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301106 table, length, PLDM_BIOS_ATTR_VAL_TABLE,
1107 attr_value_table_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301108}
1109
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301110LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301111int pldm_bios_table_attr_value_copy_and_update(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301112 const void *src_table, size_t src_length, void *dest_table,
1113 size_t *dest_length, const void *entry, size_t entry_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301114{
1115 struct pldm_bios_table_iter *iter = pldm_bios_table_iter_create(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301116 src_table, src_length, PLDM_BIOS_ATTR_VAL_TABLE);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301117
1118 int rc = PLDM_SUCCESS;
Andrew Jefferyfbe61d72023-04-05 20:28:23 +09301119 const struct pldm_bios_attr_val_table_entry *tmp;
1120 const struct pldm_bios_attr_val_table_entry *to_update = entry;
1121 size_t buffer_length = *dest_length;
1122 size_t copied_length = 0;
1123 size_t length = 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301124 while (!pldm_bios_table_iter_is_end(iter)) {
1125 tmp = pldm_bios_table_iter_attr_value_entry_value(iter);
1126 length = attr_value_table_entry_length(tmp);
1127
1128 /* we need the tmp's entry_length here, iter_next will calculate
1129 * it too, use current_pos directly to avoid calculating it
1130 * twice */
1131 iter->current_pos += length;
1132 if (tmp->attr_handle == to_update->attr_handle) {
1133 if (tmp->attr_type != to_update->attr_type) {
1134 rc = PLDM_ERROR_INVALID_DATA;
1135 goto out;
1136 }
1137 length = entry_length;
1138 tmp = entry;
1139 }
1140 if (copied_length + length > buffer_length) {
1141 rc = PLDM_ERROR_INVALID_LENGTH;
1142 goto out;
1143 }
1144 memcpy((uint8_t *)dest_table + copied_length, tmp, length);
1145 copied_length += length;
1146 }
1147
1148 size_t pad_checksum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301149 pldm_bios_table_pad_checksum_size(copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301150 if ((pad_checksum_size + copied_length) > buffer_length) {
1151 rc = PLDM_ERROR_INVALID_LENGTH;
1152 goto out;
1153 }
1154
1155 *dest_length = pldm_bios_table_append_pad_checksum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301156 dest_table, buffer_length, copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301157out:
1158 pldm_bios_table_iter_free(iter);
1159 return rc;
1160}
1161
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301162LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301163bool pldm_bios_table_checksum(const uint8_t *table, size_t size)
1164{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301165 if (table == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301166 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301167 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301168
1169 // 12: BIOSStringHandle(uint16) + BIOSStringLength(uint16) +
1170 // Variable(4) + checksum(uint32)
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301171 if (size < 12) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301172 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301173 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301174
1175 uint32_t src_crc = le32toh(*(uint32_t *)(table + size - 4));
1176 uint32_t dst_crc = crc32(table, size - 4);
1177
1178 return src_crc == dst_crc;
1179}