blob: 2fe75b26d6789865d4021a7589390886d401ef3d [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 Jeffery319304f2023-04-05 13:53:18 +093039static uint16_t get_bios_string_handle(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +093040{
41 static uint16_t handle = 0;
42 assert(handle != UINT16_MAX);
43
44 return handle++;
45}
46
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093047LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093048size_t pldm_bios_table_string_entry_encode_length(uint16_t string_length)
49{
50 return sizeof(struct pldm_bios_string_table_entry) -
51 MEMBER_SIZE(pldm_bios_string_table_entry, name) + string_length;
52}
53
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093054LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093055int pldm_bios_table_string_entry_encode_check(void *entry, size_t entry_length,
56 const char *str,
57 uint16_t str_length)
58{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093059 if (str_length == 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093060 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093061 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093062 POINTER_CHECK(entry);
63 POINTER_CHECK(str);
64 size_t length = pldm_bios_table_string_entry_encode_length(str_length);
65 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +093066 struct pldm_bios_string_table_entry *string_entry = entry;
67 string_entry->string_handle = htole16(get_bios_string_handle());
68 string_entry->string_length = htole16(str_length);
69 memcpy(string_entry->name, str, str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +093070 return PLDM_SUCCESS;
71}
72
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093073LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093074uint16_t pldm_bios_table_string_entry_decode_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093075 const struct pldm_bios_string_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +093076{
77 return le16toh(entry->string_handle);
78}
79
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093080LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093081uint16_t pldm_bios_table_string_entry_decode_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093082 const struct pldm_bios_string_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +093083{
84 return le16toh(entry->string_length);
85}
86
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093087LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093088int pldm_bios_table_string_entry_decode_string_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093089 const struct pldm_bios_string_table_entry *entry, char *buffer,
90 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +093091{
92 POINTER_CHECK(entry);
93 POINTER_CHECK(buffer);
Andrew Jeffery98c1e692023-06-14 14:41:19 +093094 if (size == 0) {
95 return PLDM_ERROR_INVALID_LENGTH;
96 }
Andrew Jeffery6409c8a2023-06-14 11:38:31 +093097 size_t length =
98 pldm_bios_table_string_entry_decode_string_length(entry);
99 length = length < (size - 1) ? length : (size - 1);
100 memcpy(buffer, entry->name, length);
101 buffer[length] = 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930102 return PLDM_SUCCESS;
103}
104
105static size_t string_table_entry_length(const void *table_entry)
106{
107 const struct pldm_bios_string_table_entry *entry = table_entry;
108 return sizeof(*entry) - sizeof(entry->name) +
109 pldm_bios_table_string_entry_decode_string_length(entry);
110}
111
Andrew Jeffery319304f2023-04-05 13:53:18 +0930112static uint16_t get_bios_attr_handle(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930113{
114 static uint16_t handle = 0;
115 assert(handle != UINT16_MAX);
116
117 return handle++;
118}
119
120static void attr_table_entry_encode_header(void *entry, size_t length,
121 uint8_t attr_type,
122 uint16_t string_handle)
123{
124 struct pldm_bios_attr_table_entry *attr_entry = entry;
125 assert(sizeof(*attr_entry) <= length);
126 attr_entry->attr_handle = htole16(get_bios_attr_handle());
127 attr_entry->attr_type = attr_type;
128 attr_entry->string_handle = htole16(string_handle);
129}
130
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930131LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930132uint16_t pldm_bios_table_attr_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930133 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930134{
135 return le16toh(entry->attr_handle);
136}
137
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930138LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930139uint8_t pldm_bios_table_attr_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930140 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930141{
142 return entry->attr_type;
143}
144
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930145LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930146uint16_t pldm_bios_table_attr_entry_decode_string_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930147 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930148{
149 return le16toh(entry->string_handle);
150}
151
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930152LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930153size_t pldm_bios_table_attr_entry_enum_encode_length(uint8_t pv_num,
154 uint8_t def_num)
155{
156 return sizeof(struct pldm_bios_attr_table_entry) -
157 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
158 sizeof(pv_num) + pv_num * sizeof(uint16_t) + sizeof(def_num) +
159 def_num;
160}
161
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930162LIBPLDM_ABI_STABLE
163int pldm_bios_table_attr_entry_enum_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930164 void *entry, size_t entry_length,
165 const struct pldm_bios_table_attr_entry_enum_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930166{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930167 POINTER_CHECK(entry);
168 POINTER_CHECK(info);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930169 size_t length = pldm_bios_table_attr_entry_enum_encode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930170 info->pv_num, info->def_num);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930171 BUFFER_SIZE_EXPECT(entry_length, length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930172 assert(length <= entry_length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930173 uint8_t attr_type = info->read_only ? PLDM_BIOS_ENUMERATION_READ_ONLY :
174 PLDM_BIOS_ENUMERATION;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930175 attr_table_entry_encode_header(entry, entry_length, attr_type,
176 info->name_handle);
177 struct pldm_bios_attr_table_entry *attr_entry = entry;
178 attr_entry->metadata[0] = info->pv_num;
179 uint16_t *pv_hdls =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930180 (uint16_t *)(attr_entry->metadata + 1 /* sizeof(pv num) */);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930181 size_t i;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930182 for (i = 0; i < info->pv_num; i++) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930183 pv_hdls[i] = htole16(info->pv_handle[i]);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930184 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930185 attr_entry->metadata[1 + info->pv_num * sizeof(uint16_t)] =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930186 info->def_num;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930187 memcpy(attr_entry->metadata + 1 /* sizeof(pv num) */ +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930188 info->pv_num * sizeof(uint16_t) + 1 /* sizeof(def num)*/,
Andrew Jeffery9c766792022-08-10 23:12:49 +0930189 info->def_index, info->def_num);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930190 return PLDM_SUCCESS;
191}
192
193#define ATTR_TYPE_EXPECT(type, expected) \
194 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930195 if ((type) != (expected) && (type) != ((expected) | 0x80)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +0930196 return PLDM_ERROR_INVALID_DATA; \
197 } while (0)
198
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930199LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930200int pldm_bios_table_attr_entry_enum_decode_pv_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930201 const struct pldm_bios_attr_table_entry *entry, uint8_t *pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930202{
203 POINTER_CHECK(entry);
204 POINTER_CHECK(pv_num);
205 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930206 *pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930207 return PLDM_SUCCESS;
208}
209
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930210static uint8_t pldm_bios_table_attr_entry_enum_decode_def_num(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930211 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930212{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930213 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930214 return entry->metadata[sizeof(uint8_t) /* pv_num */ +
215 sizeof(uint16_t) * pv_num];
216}
217
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930218LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930219int pldm_bios_table_attr_entry_enum_decode_def_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930220 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930221{
222 POINTER_CHECK(entry);
223 POINTER_CHECK(def_num);
224 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
225 *def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
226 return PLDM_SUCCESS;
227}
228
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930229LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930230int pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930231 const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
232 uint8_t pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930233{
234 POINTER_CHECK(entry);
235 POINTER_CHECK(pv_hdls);
236 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930237 uint8_t num = entry->metadata[0];
238 num = num < pv_num ? num : pv_num;
239 size_t i;
240 for (i = 0; i < num; i++) {
241 uint16_t *hdl = (uint16_t *)(entry->metadata + sizeof(uint8_t) +
242 i * sizeof(uint16_t));
243 pv_hdls[i] = le16toh(*hdl);
244 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930245 return PLDM_SUCCESS;
246}
247
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930248LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930249uint8_t pldm_bios_table_attr_entry_enum_decode_def_indices(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930250 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_indices,
251 uint8_t def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930252{
253 uint8_t num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
254 num = num < def_num ? num : def_num;
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930255 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930256 const uint8_t *p = entry->metadata +
257 sizeof(uint8_t) /* number of possible values*/
258 + pv_num * sizeof(uint16_t) /* possible values */
259 + sizeof(uint8_t); /* number of default values */
260 memcpy(def_indices, p, num);
261 return num;
262}
263
264/** @brief Get length of an enum attribute entry
265 */
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930266static size_t attr_table_entry_length_enum(const void *arg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930267{
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930268 const struct pldm_bios_attr_table_entry *entry = arg;
269 uint8_t pv_num = entry->metadata[0];
Andrew Jeffery9c766792022-08-10 23:12:49 +0930270 uint8_t def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
271 return pldm_bios_table_attr_entry_enum_encode_length(pv_num, def_num);
272}
273
274struct attr_table_string_entry_fields {
275 uint8_t string_type;
276 uint16_t min_length;
277 uint16_t max_length;
278 uint16_t def_length;
279 uint8_t def_string[1];
280} __attribute__((packed));
281
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930282LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930283size_t pldm_bios_table_attr_entry_string_encode_length(uint16_t def_str_len)
284{
285 return sizeof(struct pldm_bios_attr_table_entry) -
286 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
287 sizeof(struct attr_table_string_entry_fields) -
288 MEMBER_SIZE(attr_table_string_entry_fields, def_string) +
289 def_str_len;
290}
291
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930292#define PLDM_STRING_TYPE_MAX 5
Andrew Jeffery9c766792022-08-10 23:12:49 +0930293#define PLDM_STRING_TYPE_VENDOR 0xff
294
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930295LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930296int pldm_bios_table_attr_entry_string_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930297 const struct pldm_bios_table_attr_entry_string_info *info,
298 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930299{
300 if (info->min_length > info->max_length) {
301 set_errmsg(errmsg, "MinimumStingLength should not be greater "
302 "than MaximumStringLength");
303 return PLDM_ERROR_INVALID_DATA;
304 }
305 if (info->min_length == info->max_length &&
306 info->def_length != info->min_length) {
307 set_errmsg(errmsg, "Wrong DefaultStringLength");
308 return PLDM_ERROR_INVALID_DATA;
309 }
310 if (info->def_length > info->max_length ||
311 info->def_length < info->min_length) {
312 set_errmsg(errmsg, "Wrong DefaultStringLength");
313 return PLDM_ERROR_INVALID_DATA;
314 }
315 if (info->string_type > PLDM_STRING_TYPE_MAX &&
316 info->string_type != PLDM_STRING_TYPE_VENDOR) {
317 set_errmsg(errmsg, "Wrong StringType");
318 return PLDM_ERROR_INVALID_DATA;
319 }
Andrew Jefferydf02e362023-06-14 14:52:25 +0930320 if (info->def_string && info->def_length != strlen(info->def_string)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930321 set_errmsg(errmsg, "Length of DefaultString should be equal to "
322 "DefaultStringLength");
323 return PLDM_ERROR_INVALID_DATA;
324 }
325
326 return PLDM_SUCCESS;
327}
328
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930329LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930330int pldm_bios_table_attr_entry_string_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930331 void *entry, size_t entry_length,
332 const struct pldm_bios_table_attr_entry_string_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930333{
334 POINTER_CHECK(entry);
335 POINTER_CHECK(info);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930336 size_t length = pldm_bios_table_attr_entry_string_encode_length(
337 info->def_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930338 BUFFER_SIZE_EXPECT(entry_length, length);
339 if (pldm_bios_table_attr_entry_string_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930340 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930341 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930342 }
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930343 uint8_t attr_type = info->read_only ? PLDM_BIOS_STRING_READ_ONLY :
344 PLDM_BIOS_STRING;
345 attr_table_entry_encode_header(entry, entry_length, attr_type,
346 info->name_handle);
347 struct pldm_bios_attr_table_entry *attr_entry = entry;
348 struct attr_table_string_entry_fields *attr_fields =
349 (struct attr_table_string_entry_fields *)attr_entry->metadata;
350 attr_fields->string_type = info->string_type;
351 attr_fields->min_length = htole16(info->min_length);
352 attr_fields->max_length = htole16(info->max_length);
353 attr_fields->def_length = htole16(info->def_length);
354 if (info->def_length != 0 && info->def_string != NULL) {
355 memcpy(attr_fields->def_string, info->def_string,
356 info->def_length);
357 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930358 return PLDM_SUCCESS;
359}
360
Andrew Jeffery6409c8a2023-06-14 11:38:31 +0930361static uint16_t pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930362 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930363{
364 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930365 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930366 return le16toh(fields->def_length);
367}
368
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930369LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930370int pldm_bios_table_attr_entry_string_decode_def_string_length_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930371 const struct pldm_bios_attr_table_entry *entry,
372 uint16_t *def_string_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930373{
374 POINTER_CHECK(entry);
375 POINTER_CHECK(def_string_length);
376 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_STRING);
377 *def_string_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930378 pldm_bios_table_attr_entry_string_decode_def_string_length(
379 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930380 return PLDM_SUCCESS;
381}
382
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930383LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930384uint8_t pldm_bios_table_attr_entry_string_decode_string_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930385 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930386{
387 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930388 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930389 return fields->string_type;
390}
391
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930392LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930393uint16_t pldm_bios_table_attr_entry_string_decode_max_length(
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 le16toh(fields->max_length);
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_min_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->min_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_def_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930412 const struct pldm_bios_attr_table_entry *entry, char *buffer,
413 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930414{
415 uint16_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930416 pldm_bios_table_attr_entry_string_decode_def_string_length(
417 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930418 length = length < (size - 1) ? length : (size - 1);
419 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930420 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930421 memcpy(buffer, fields->def_string, length);
422 buffer[length] = 0;
423 return length;
424}
425
426/** @brief Get length of a string attribute entry
427 */
428static size_t attr_table_entry_length_string(const void *entry)
429{
430 uint16_t def_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930431 pldm_bios_table_attr_entry_string_decode_def_string_length(
432 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930433 return pldm_bios_table_attr_entry_string_encode_length(def_str_len);
434}
435
436struct attr_table_integer_entry_fields {
437 uint64_t lower_bound;
438 uint64_t upper_bound;
439 uint32_t scalar_increment;
440 uint64_t default_value;
441} __attribute__((packed));
442
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930443LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930444size_t pldm_bios_table_attr_entry_integer_encode_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930445{
446 return sizeof(struct pldm_bios_attr_table_entry) - 1 +
447 sizeof(struct attr_table_integer_entry_fields);
448}
449
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930450LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930451void pldm_bios_table_attr_entry_integer_encode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930452 void *entry, size_t entry_length,
453 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930454{
455 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
456 assert(length <= entry_length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930457 uint8_t attr_type = info->read_only ? PLDM_BIOS_INTEGER_READ_ONLY :
458 PLDM_BIOS_INTEGER;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930459 attr_table_entry_encode_header(entry, entry_length, attr_type,
460 info->name_handle);
461 struct pldm_bios_attr_table_entry *attr_entry = entry;
462 struct attr_table_integer_entry_fields *attr_fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930463 (struct attr_table_integer_entry_fields *)attr_entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930464 attr_fields->lower_bound = htole64(info->lower_bound);
465 attr_fields->upper_bound = htole64(info->upper_bound);
466 attr_fields->scalar_increment = htole32(info->scalar_increment);
467 attr_fields->default_value = htole64(info->default_value);
468}
469
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930470LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930471int pldm_bios_table_attr_entry_integer_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930472 const struct pldm_bios_table_attr_entry_integer_info *info,
473 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930474{
475 if (info->lower_bound == info->upper_bound) {
476 if (info->default_value != info->lower_bound) {
477 set_errmsg(errmsg, "Wrong DefaultValue");
478 return PLDM_ERROR_INVALID_DATA;
479 }
480 if (info->scalar_increment != 0) {
481 set_errmsg(errmsg, "Wrong ScalarIncrement");
482 return PLDM_ERROR_INVALID_DATA;
483 }
484 return PLDM_SUCCESS;
485 }
486 if (info->lower_bound > info->upper_bound) {
487 set_errmsg(errmsg,
488 "LowerBound should not be greater than UpperBound");
489 return PLDM_ERROR_INVALID_DATA;
490 }
491 if (info->default_value > info->upper_bound ||
492 info->default_value < info->lower_bound) {
493 set_errmsg(errmsg, "Wrong DefaultValue");
494 return PLDM_ERROR_INVALID_DATA;
495 }
496 if (info->scalar_increment == 0) {
497 set_errmsg(errmsg, "ScalarIncrement should not be zero when "
498 "lower_bound != upper_bound");
499 return PLDM_ERROR_INVALID_DATA;
500 }
501 if ((info->default_value - info->lower_bound) %
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930502 info->scalar_increment !=
Andrew Jeffery9c766792022-08-10 23:12:49 +0930503 0) {
504 set_errmsg(errmsg, "Wrong DefaultValue or ScalarIncrement");
505 return PLDM_ERROR_INVALID_DATA;
506 }
507 return PLDM_SUCCESS;
508}
509
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930510LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930511int pldm_bios_table_attr_entry_integer_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930512 void *entry, size_t entry_length,
513 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930514{
515 POINTER_CHECK(entry);
516 POINTER_CHECK(info);
517 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
518 BUFFER_SIZE_EXPECT(entry_length, length);
519 if (pldm_bios_table_attr_entry_integer_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930520 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930521 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930522 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930523 pldm_bios_table_attr_entry_integer_encode(entry, entry_length, info);
524 return PLDM_SUCCESS;
525}
526
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930527LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930528void pldm_bios_table_attr_entry_integer_decode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930529 const struct pldm_bios_attr_table_entry *entry, uint64_t *lower,
530 uint64_t *upper, uint32_t *scalar, uint64_t *def)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930531{
532 struct attr_table_integer_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930533 (struct attr_table_integer_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930534 *lower = le64toh(fields->lower_bound);
535 *upper = le64toh(fields->upper_bound);
536 *scalar = le32toh(fields->scalar_increment);
537 *def = le64toh(fields->default_value);
538}
539
540static size_t attr_table_entry_length_integer(const void *entry)
541{
542 (void)entry;
543 return pldm_bios_table_attr_entry_integer_encode_length();
544}
545
546struct table_entry_length {
547 uint8_t attr_type;
548 size_t (*entry_length_handler)(const void *);
549};
550
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930551#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
Andrew Jeffery9c766792022-08-10 23:12:49 +0930552
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930553static const struct table_entry_length *
554find_table_entry_length_by_type(uint8_t attr_type,
555 const struct table_entry_length *handlers,
556 size_t count)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930557{
558 size_t i;
559 for (i = 0; i < count; i++) {
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930560 if (attr_type == handlers[i].attr_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930561 return &handlers[i];
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930562 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930563 }
564 return NULL;
565}
566
567static const struct table_entry_length attr_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930568 { .attr_type = PLDM_BIOS_ENUMERATION,
569 .entry_length_handler = attr_table_entry_length_enum },
570 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
571 .entry_length_handler = attr_table_entry_length_enum },
572 { .attr_type = PLDM_BIOS_STRING,
573 .entry_length_handler = attr_table_entry_length_string },
574 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
575 .entry_length_handler = attr_table_entry_length_string },
576 { .attr_type = PLDM_BIOS_INTEGER,
577 .entry_length_handler = attr_table_entry_length_integer },
578 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
579 .entry_length_handler = attr_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930580};
581
582static size_t attr_table_entry_length(const void *table_entry)
583{
584 const struct pldm_bios_attr_table_entry *entry = table_entry;
585 const struct table_entry_length *attr_table_entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930586 find_table_entry_length_by_type(entry->attr_type,
587 attr_table_entries,
588 ARRAY_SIZE(attr_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930589 assert(attr_table_entry != NULL);
590 assert(attr_table_entry->entry_length_handler != NULL);
591
592 return attr_table_entry->entry_length_handler(entry);
593}
594
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930595LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930596uint16_t pldm_bios_table_attr_value_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930597 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930598{
599 return le16toh(entry->attr_handle);
600}
601
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930602LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930603uint8_t pldm_bios_table_attr_value_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930604 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930605{
606 return entry->attr_type;
607}
608
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930609LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930610size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count)
611{
612 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
613 sizeof(count) + count;
614}
615
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930616LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930617void pldm_bios_table_attr_value_entry_encode_enum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930618 void *entry, size_t entry_length, uint16_t attr_handle,
619 uint8_t attr_type, uint8_t count, const uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930620{
621 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930622 pldm_bios_table_attr_value_entry_encode_enum_length(count);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930623 assert(length <= entry_length);
624
625 struct pldm_bios_attr_val_table_entry *table_entry = entry;
626 table_entry->attr_handle = htole16(attr_handle);
627 table_entry->attr_type = attr_type;
628 table_entry->value[0] = count;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930629 if (count != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930630 memcpy(&table_entry->value[1], handles, count);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930631 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930632}
633
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930634LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930635uint8_t pldm_bios_table_attr_value_entry_enum_decode_number(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930636 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930637{
638 return entry->value[0];
639}
640
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930641LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930642uint8_t pldm_bios_table_attr_value_entry_enum_decode_handles(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930643 const struct pldm_bios_attr_val_table_entry *entry, uint8_t *handles,
644 uint8_t number)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930645{
646 uint8_t curr_num =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930647 pldm_bios_table_attr_value_entry_enum_decode_number(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930648 number = number < curr_num ? number : curr_num;
649 memcpy(handles, &entry->value[1], number);
650
651 return number;
652}
653
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930654LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930655int pldm_bios_table_attr_value_entry_encode_enum_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930656 void *entry, size_t entry_length, uint16_t attr_handle,
657 uint8_t attr_type, uint8_t count, uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930658{
659 POINTER_CHECK(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930660 if (count != 0 && handles == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930661 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930662 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930663 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_ENUMERATION);
664 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930665 pldm_bios_table_attr_value_entry_encode_enum_length(count);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930666 BUFFER_SIZE_EXPECT(entry_length, length);
667 pldm_bios_table_attr_value_entry_encode_enum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930668 entry, entry_length, attr_handle, attr_type, count, handles);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930669 return PLDM_SUCCESS;
670}
671
672static size_t attr_value_table_entry_length_enum(const void *entry)
673{
674 uint8_t number =
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 return pldm_bios_table_attr_value_entry_encode_enum_length(number);
677}
678
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930679LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930680size_t
681pldm_bios_table_attr_value_entry_encode_string_length(uint16_t string_length)
682{
683 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
684 sizeof(string_length) + string_length;
685}
686
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930687LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930688void pldm_bios_table_attr_value_entry_encode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930689 void *entry, size_t entry_length, uint16_t attr_handle,
690 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930691{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930692 size_t length = pldm_bios_table_attr_value_entry_encode_string_length(
693 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930694 assert(length <= entry_length);
695
696 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;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930699 if (str_length != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930700 memcpy(table_entry->value + sizeof(str_length), str,
701 str_length);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930702 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930703 str_length = htole16(str_length);
704 memcpy(table_entry->value, &str_length, sizeof(str_length));
705}
706
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930707LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930708uint16_t pldm_bios_table_attr_value_entry_string_decode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930709 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930710{
711 uint16_t str_length = 0;
712 memcpy(&str_length, entry->value, sizeof(str_length));
713 return le16toh(str_length);
714}
715
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930716LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930717void pldm_bios_table_attr_value_entry_string_decode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930718 const struct pldm_bios_attr_val_table_entry *entry,
719 struct variable_field *current_string)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930720{
721 current_string->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930722 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930723 current_string->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930724 entry->value + sizeof(uint16_t); // sizeof(CurrentStringLength)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930725}
726
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930727LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930728int pldm_bios_table_attr_value_entry_encode_string_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930729 void *entry, size_t entry_length, uint16_t attr_handle,
730 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930731{
732 POINTER_CHECK(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930733 if (str_length != 0 && str == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930734 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930735 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930736 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_STRING);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930737 size_t length = pldm_bios_table_attr_value_entry_encode_string_length(
738 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930739 BUFFER_SIZE_EXPECT(entry_length, length);
740 pldm_bios_table_attr_value_entry_encode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930741 entry, entry_length, attr_handle, attr_type, str_length, str);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930742 return PLDM_SUCCESS;
743}
744
745static size_t attr_value_table_entry_length_string(const void *entry)
746{
747 uint16_t str_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930748 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930749 return pldm_bios_table_attr_value_entry_encode_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930750 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930751}
752
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930753LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930754size_t pldm_bios_table_attr_value_entry_encode_integer_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930755{
756 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
757 sizeof(uint64_t);
758}
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930759
760LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930761void pldm_bios_table_attr_value_entry_encode_integer(void *entry,
762 size_t entry_length,
763 uint16_t attr_handle,
764 uint8_t attr_type,
765 uint64_t cv)
766{
767 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930768 pldm_bios_table_attr_value_entry_encode_integer_length();
Andrew Jeffery9c766792022-08-10 23:12:49 +0930769 assert(length <= entry_length);
770
771 struct pldm_bios_attr_val_table_entry *table_entry = entry;
772 table_entry->attr_handle = htole16(attr_handle);
773 table_entry->attr_type = attr_type;
774 cv = htole64(cv);
775 memcpy(table_entry->value, &cv, sizeof(uint64_t));
776}
777
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930778LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930779int pldm_bios_table_attr_value_entry_encode_integer_check(void *entry,
780 size_t entry_length,
781 uint16_t attr_handle,
782 uint8_t attr_type,
783 uint64_t cv)
784{
785 POINTER_CHECK(entry);
786 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930787 pldm_bios_table_attr_value_entry_encode_integer_length();
Andrew Jeffery9c766792022-08-10 23:12:49 +0930788 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_INTEGER);
789 BUFFER_SIZE_EXPECT(entry_length, length);
790 pldm_bios_table_attr_value_entry_encode_integer(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930791 entry, entry_length, attr_handle, attr_type, cv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930792 return PLDM_SUCCESS;
793}
794
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930795LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930796uint64_t pldm_bios_table_attr_value_entry_integer_decode_cv(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930797 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930798{
799 uint64_t cv = 0;
800 memcpy(&cv, entry->value, sizeof(cv));
801 cv = le64toh(cv);
802 return cv;
803}
804
805static size_t attr_value_table_entry_length_integer(const void *entry)
806{
807 (void)entry;
808 return pldm_bios_table_attr_value_entry_encode_integer_length();
809}
810
811static const struct table_entry_length attr_value_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930812 { .attr_type = PLDM_BIOS_ENUMERATION,
813 .entry_length_handler = attr_value_table_entry_length_enum },
814 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
815 .entry_length_handler = attr_value_table_entry_length_enum },
816 { .attr_type = PLDM_BIOS_STRING,
817 .entry_length_handler = attr_value_table_entry_length_string },
818 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
819 .entry_length_handler = attr_value_table_entry_length_string },
820 { .attr_type = PLDM_BIOS_INTEGER,
821 .entry_length_handler = attr_value_table_entry_length_integer },
822 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
823 .entry_length_handler = attr_value_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930824};
825
826static size_t attr_value_table_entry_length(const void *table_entry)
827{
828 const struct pldm_bios_attr_val_table_entry *entry = table_entry;
829 const struct table_entry_length *entry_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930830 find_table_entry_length_by_type(
831 entry->attr_type, attr_value_table_entries,
832 ARRAY_SIZE(attr_value_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930833 assert(entry_length != NULL);
834 assert(entry_length->entry_length_handler != NULL);
835
836 return entry_length->entry_length_handler(entry);
837}
838
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930839LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930840size_t pldm_bios_table_attr_value_entry_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930841 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930842{
843 return attr_value_table_entry_length(entry);
844}
845
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930846LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930847uint16_t pldm_bios_table_attr_value_entry_decode_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930848 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930849{
850 return le16toh(entry->attr_handle);
851}
852
853static size_t pad_size_get(size_t size_without_pad)
854{
855 return ((size_without_pad % 4) ? (4 - size_without_pad % 4) : 0);
856}
857
858static uint8_t *pad_append(uint8_t *table_end, size_t pad_size)
859{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930860 while (pad_size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930861 *table_end++ = 0;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930862 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930863
864 return table_end;
865}
866
867static uint8_t *checksum_append(uint8_t *table_end, uint32_t checksum)
868{
869 checksum = htole32(checksum);
870 memcpy(table_end, &checksum, sizeof(checksum));
871
872 return table_end + sizeof(checksum);
873}
874
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930875LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930876size_t pldm_bios_table_pad_checksum_size(size_t size_without_pad)
877{
878 size_t size = pad_size_get(size_without_pad) +
879 sizeof(uint32_t) /*sizeof(checksum)*/;
880 return size;
881}
882
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930883LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930884size_t pldm_bios_table_append_pad_checksum(void *table, size_t size,
885 size_t size_without_pad)
886{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930887 size_t pad_checksum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930888 pldm_bios_table_pad_checksum_size(size_without_pad);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930889 size_t total_length = size_without_pad + pad_checksum_size;
890 assert(size >= total_length);
891
892 uint8_t *table_end = (uint8_t *)table + size_without_pad;
893 size_t pad_size = pad_size_get(size_without_pad);
894 table_end = pad_append(table_end, pad_size);
895
896 uint32_t checksum = crc32(table, size_without_pad + pad_size);
897 checksum_append(table_end, checksum);
898
899 return total_length;
900}
901
902struct pldm_bios_table_iter {
903 const uint8_t *table_data;
904 size_t table_len;
905 size_t current_pos;
906 size_t (*entry_length_handler)(const void *table_entry);
907};
908
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930909LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930910struct pldm_bios_table_iter *
911pldm_bios_table_iter_create(const void *table, size_t length,
912 enum pldm_bios_table_types type)
913{
914 struct pldm_bios_table_iter *iter = malloc(sizeof(*iter));
915 assert(iter != NULL);
916 iter->table_data = table;
917 iter->table_len = length;
918 iter->current_pos = 0;
919 iter->entry_length_handler = NULL;
920 switch (type) {
921 case PLDM_BIOS_STRING_TABLE:
922 iter->entry_length_handler = string_table_entry_length;
923 break;
924 case PLDM_BIOS_ATTR_TABLE:
925 iter->entry_length_handler = attr_table_entry_length;
926 break;
927 case PLDM_BIOS_ATTR_VAL_TABLE:
928 iter->entry_length_handler = attr_value_table_entry_length;
929 break;
930 }
931
932 return iter;
933}
934
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930935LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930936void pldm_bios_table_iter_free(struct pldm_bios_table_iter *iter)
937{
938 free(iter);
939}
940
941#define pad_and_check_max 7
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930942LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930943bool pldm_bios_table_iter_is_end(const struct pldm_bios_table_iter *iter)
944{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930945 if (iter->table_len - iter->current_pos <= pad_and_check_max) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930946 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930947 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930948 return false;
949}
950
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930951LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930952void pldm_bios_table_iter_next(struct pldm_bios_table_iter *iter)
953{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930954 if (pldm_bios_table_iter_is_end(iter)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930955 return;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930956 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930957 const void *entry = iter->table_data + iter->current_pos;
958 iter->current_pos += iter->entry_length_handler(entry);
959}
960
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930961LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930962const void *pldm_bios_table_iter_value(struct pldm_bios_table_iter *iter)
963{
964 return iter->table_data + iter->current_pos;
965}
966
967typedef bool (*equal_handler)(const void *entry, const void *key);
968
969static const void *
970pldm_bios_table_entry_find_by_iter(struct pldm_bios_table_iter *iter,
971 const void *key, equal_handler equal)
972{
973 const void *entry;
974 while (!pldm_bios_table_iter_is_end(iter)) {
975 entry = pldm_bios_table_iter_value(iter);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930976 if (equal(entry, key)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930977 return entry;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930978 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930979 pldm_bios_table_iter_next(iter);
980 }
981 return NULL;
982}
983
984static const void *
985pldm_bios_table_entry_find_from_table(const void *table, size_t length,
986 enum pldm_bios_table_types type,
987 equal_handler equal, const void *key)
988{
989 struct pldm_bios_table_iter *iter =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930990 pldm_bios_table_iter_create(table, length, type);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930991 const void *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930992 pldm_bios_table_entry_find_by_iter(iter, key, equal);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930993 pldm_bios_table_iter_free(iter);
994 return entry;
995}
996
997static bool string_table_handle_equal(const void *entry, const void *key)
998{
999 const struct pldm_bios_string_table_entry *string_entry = entry;
1000 uint16_t handle = *(uint16_t *)key;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301001 if (pldm_bios_table_string_entry_decode_handle(string_entry) ==
1002 handle) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301003 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301004 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301005 return false;
1006}
1007
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301008LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301009const struct pldm_bios_string_table_entry *
1010pldm_bios_table_string_find_by_handle(const void *table, size_t length,
1011 uint16_t handle)
1012{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301013 return pldm_bios_table_entry_find_from_table(table, length,
1014 PLDM_BIOS_STRING_TABLE,
1015 string_table_handle_equal,
1016 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301017}
1018
1019struct string_equal_arg {
1020 uint16_t str_length;
1021 const char *str;
1022};
1023
1024static bool string_table_string_equal(const void *entry, const void *key)
1025{
1026 const struct pldm_bios_string_table_entry *string_entry = entry;
1027 const struct string_equal_arg *arg = key;
1028 if (arg->str_length !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301029 pldm_bios_table_string_entry_decode_string_length(string_entry)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301030 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301031 }
1032 if (memcmp(string_entry->name, arg->str, arg->str_length) != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301033 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301034 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301035 return true;
1036}
1037
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301038LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301039const struct pldm_bios_string_table_entry *
1040pldm_bios_table_string_find_by_string(const void *table, size_t length,
1041 const char *str)
1042{
1043 uint16_t str_length = strlen(str);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301044 struct string_equal_arg arg = { str_length, str };
1045 return pldm_bios_table_entry_find_from_table(table, length,
1046 PLDM_BIOS_STRING_TABLE,
1047 string_table_string_equal,
1048 &arg);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301049}
1050
1051static bool attr_table_handle_equal(const void *entry, const void *key)
1052{
1053 uint16_t handle = *(uint16_t *)key;
1054 return pldm_bios_table_attr_entry_decode_attribute_handle(entry) ==
1055 handle;
1056}
1057
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301058LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301059const struct pldm_bios_attr_table_entry *
1060pldm_bios_table_attr_find_by_handle(const void *table, size_t length,
1061 uint16_t handle)
1062{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301063 return pldm_bios_table_entry_find_from_table(table, length,
1064 PLDM_BIOS_ATTR_TABLE,
1065 attr_table_handle_equal,
1066 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301067}
1068
1069static bool attr_table_string_handle_equal(const void *entry, const void *key)
1070{
1071 uint16_t handle = *(uint16_t *)key;
1072 return pldm_bios_table_attr_entry_decode_string_handle(entry) == handle;
1073}
1074
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301075LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301076const struct pldm_bios_attr_table_entry *
1077pldm_bios_table_attr_find_by_string_handle(const void *table, size_t length,
1078 uint16_t handle)
1079{
1080 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301081 table, length, PLDM_BIOS_ATTR_TABLE,
1082 attr_table_string_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301083}
1084
1085static bool attr_value_table_handle_equal(const void *entry, const void *key)
1086{
1087 uint16_t handle = *(uint16_t *)key;
1088 return pldm_bios_table_attr_value_entry_decode_handle(entry) == handle;
1089}
1090
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301091LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301092const struct pldm_bios_attr_val_table_entry *
1093pldm_bios_table_attr_value_find_by_handle(const void *table, size_t length,
1094 uint16_t handle)
1095{
1096 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301097 table, length, PLDM_BIOS_ATTR_VAL_TABLE,
1098 attr_value_table_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301099}
1100
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301101LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301102int pldm_bios_table_attr_value_copy_and_update(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301103 const void *src_table, size_t src_length, void *dest_table,
1104 size_t *dest_length, const void *entry, size_t entry_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301105{
1106 struct pldm_bios_table_iter *iter = pldm_bios_table_iter_create(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301107 src_table, src_length, PLDM_BIOS_ATTR_VAL_TABLE);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301108
1109 int rc = PLDM_SUCCESS;
Andrew Jefferyfbe61d72023-04-05 20:28:23 +09301110 const struct pldm_bios_attr_val_table_entry *tmp;
1111 const struct pldm_bios_attr_val_table_entry *to_update = entry;
1112 size_t buffer_length = *dest_length;
1113 size_t copied_length = 0;
1114 size_t length = 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301115 while (!pldm_bios_table_iter_is_end(iter)) {
1116 tmp = pldm_bios_table_iter_attr_value_entry_value(iter);
1117 length = attr_value_table_entry_length(tmp);
1118
1119 /* we need the tmp's entry_length here, iter_next will calculate
1120 * it too, use current_pos directly to avoid calculating it
1121 * twice */
1122 iter->current_pos += length;
1123 if (tmp->attr_handle == to_update->attr_handle) {
1124 if (tmp->attr_type != to_update->attr_type) {
1125 rc = PLDM_ERROR_INVALID_DATA;
1126 goto out;
1127 }
1128 length = entry_length;
1129 tmp = entry;
1130 }
1131 if (copied_length + length > buffer_length) {
1132 rc = PLDM_ERROR_INVALID_LENGTH;
1133 goto out;
1134 }
1135 memcpy((uint8_t *)dest_table + copied_length, tmp, length);
1136 copied_length += length;
1137 }
1138
1139 size_t pad_checksum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301140 pldm_bios_table_pad_checksum_size(copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301141 if ((pad_checksum_size + copied_length) > buffer_length) {
1142 rc = PLDM_ERROR_INVALID_LENGTH;
1143 goto out;
1144 }
1145
1146 *dest_length = pldm_bios_table_append_pad_checksum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301147 dest_table, buffer_length, copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301148out:
1149 pldm_bios_table_iter_free(iter);
1150 return rc;
1151}
1152
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301153LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301154bool pldm_bios_table_checksum(const uint8_t *table, size_t size)
1155{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301156 if (table == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301157 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301158 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301159
1160 // 12: BIOSStringHandle(uint16) + BIOSStringLength(uint16) +
1161 // Variable(4) + checksum(uint32)
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301162 if (size < 12) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301163 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301164 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301165
1166 uint32_t src_crc = le32toh(*(uint32_t *)(table + size - 4));
1167 uint32_t dst_crc = crc32(table, size - 4);
1168
1169 return src_crc == dst_crc;
1170}