blob: 945cdbe924def3e4310179c9066e40e3faf8a853 [file] [log] [blame]
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301#include "config.h"
Manojkiran Eda9a8e4972022-11-28 16:38:21 +05302#include "bios_table.h"
3#include "base.h"
4#include "bios.h"
5#include "utils.h"
Andrew Jeffery9c766792022-08-10 23:12:49 +09306#include <assert.h>
7#include <endian.h>
8#include <stdbool.h>
9#include <stdint.h>
10#include <stdlib.h>
11#include <string.h>
12
Andrew Jeffery9c766792022-08-10 23:12:49 +093013#define POINTER_CHECK(pointer) \
14 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +093015 if ((pointer) == NULL) \
Andrew Jeffery9c766792022-08-10 23:12:49 +093016 return PLDM_ERROR_INVALID_DATA; \
17 } while (0)
18
19#define ATTR_TYPE_EXPECT(type, expected) \
20 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +093021 if ((type) != (expected) && (type) != ((expected) | 0x80)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +093022 return PLDM_ERROR_INVALID_DATA; \
23 } while (0)
24
25#define BUFFER_SIZE_EXPECT(current_size, expected_size) \
26 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +093027 if ((current_size) < (expected_size)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +093028 return PLDM_ERROR_INVALID_LENGTH; \
29 } while (0)
30
31#define MEMBER_SIZE(type, member) sizeof(((struct type *)0)->member)
32
33static void set_errmsg(const char **errmsg, const char *msg)
34{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093035 if (errmsg != NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093036 *errmsg = msg;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093037 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093038}
39
Andrew Jeffery319304f2023-04-05 13:53:18 +093040static uint16_t get_bios_string_handle(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +093041{
42 static uint16_t handle = 0;
43 assert(handle != UINT16_MAX);
44
45 return handle++;
46}
47
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093048LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093049size_t pldm_bios_table_string_entry_encode_length(uint16_t string_length)
50{
51 return sizeof(struct pldm_bios_string_table_entry) -
52 MEMBER_SIZE(pldm_bios_string_table_entry, name) + string_length;
53}
54
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093055LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093056void pldm_bios_table_string_entry_encode(void *entry, size_t entry_length,
57 const char *str, uint16_t str_length)
58{
59 size_t length = pldm_bios_table_string_entry_encode_length(str_length);
60 assert(length <= entry_length);
61 struct pldm_bios_string_table_entry *string_entry = entry;
62 string_entry->string_handle = htole16(get_bios_string_handle());
63 string_entry->string_length = htole16(str_length);
64 memcpy(string_entry->name, str, str_length);
65}
66
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093067LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093068int pldm_bios_table_string_entry_encode_check(void *entry, size_t entry_length,
69 const char *str,
70 uint16_t str_length)
71{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093072 if (str_length == 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +093073 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +093074 }
Andrew Jeffery9c766792022-08-10 23:12:49 +093075 POINTER_CHECK(entry);
76 POINTER_CHECK(str);
77 size_t length = pldm_bios_table_string_entry_encode_length(str_length);
78 BUFFER_SIZE_EXPECT(entry_length, length);
79 pldm_bios_table_string_entry_encode(entry, entry_length, str,
80 str_length);
81 return PLDM_SUCCESS;
82}
83
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093084LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093085uint16_t pldm_bios_table_string_entry_decode_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093086 const struct pldm_bios_string_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +093087{
88 return le16toh(entry->string_handle);
89}
90
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093091LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093092uint16_t pldm_bios_table_string_entry_decode_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093093 const struct pldm_bios_string_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +093094{
95 return le16toh(entry->string_length);
96}
97
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +093098LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +093099uint16_t pldm_bios_table_string_entry_decode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930100 const struct pldm_bios_string_table_entry *entry, char *buffer,
101 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930102{
103 uint16_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930104 pldm_bios_table_string_entry_decode_string_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930105 length = length < (size - 1) ? length : (size - 1);
106 memcpy(buffer, entry->name, length);
107 buffer[length] = 0;
108 return length;
109}
110
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930111LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930112int pldm_bios_table_string_entry_decode_string_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930113 const struct pldm_bios_string_table_entry *entry, char *buffer,
114 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930115{
116 POINTER_CHECK(entry);
117 POINTER_CHECK(buffer);
118 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930119 pldm_bios_table_string_entry_decode_string_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930120 BUFFER_SIZE_EXPECT(size, length + 1);
121 pldm_bios_table_string_entry_decode_string(entry, buffer, size);
122 return PLDM_SUCCESS;
123}
124
125static size_t string_table_entry_length(const void *table_entry)
126{
127 const struct pldm_bios_string_table_entry *entry = table_entry;
128 return sizeof(*entry) - sizeof(entry->name) +
129 pldm_bios_table_string_entry_decode_string_length(entry);
130}
131
Andrew Jeffery319304f2023-04-05 13:53:18 +0930132static uint16_t get_bios_attr_handle(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930133{
134 static uint16_t handle = 0;
135 assert(handle != UINT16_MAX);
136
137 return handle++;
138}
139
140static void attr_table_entry_encode_header(void *entry, size_t length,
141 uint8_t attr_type,
142 uint16_t string_handle)
143{
144 struct pldm_bios_attr_table_entry *attr_entry = entry;
145 assert(sizeof(*attr_entry) <= length);
146 attr_entry->attr_handle = htole16(get_bios_attr_handle());
147 attr_entry->attr_type = attr_type;
148 attr_entry->string_handle = htole16(string_handle);
149}
150
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930151LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930152uint16_t pldm_bios_table_attr_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930153 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930154{
155 return le16toh(entry->attr_handle);
156}
157
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930158LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930159uint8_t pldm_bios_table_attr_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930160 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930161{
162 return entry->attr_type;
163}
164
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930165LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930166uint16_t pldm_bios_table_attr_entry_decode_string_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930167 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930168{
169 return le16toh(entry->string_handle);
170}
171
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930172LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930173size_t pldm_bios_table_attr_entry_enum_encode_length(uint8_t pv_num,
174 uint8_t def_num)
175{
176 return sizeof(struct pldm_bios_attr_table_entry) -
177 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
178 sizeof(pv_num) + pv_num * sizeof(uint16_t) + sizeof(def_num) +
179 def_num;
180}
181
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930182LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930183void pldm_bios_table_attr_entry_enum_encode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930184 void *entry, size_t entry_length,
185 const struct pldm_bios_table_attr_entry_enum_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930186{
187 size_t length = pldm_bios_table_attr_entry_enum_encode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930188 info->pv_num, info->def_num);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930189 assert(length <= entry_length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930190 uint8_t attr_type = info->read_only ? PLDM_BIOS_ENUMERATION_READ_ONLY :
191 PLDM_BIOS_ENUMERATION;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930192 attr_table_entry_encode_header(entry, entry_length, attr_type,
193 info->name_handle);
194 struct pldm_bios_attr_table_entry *attr_entry = entry;
195 attr_entry->metadata[0] = info->pv_num;
196 uint16_t *pv_hdls =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930197 (uint16_t *)(attr_entry->metadata + 1 /* sizeof(pv num) */);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930198 size_t i;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930199 for (i = 0; i < info->pv_num; i++) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930200 pv_hdls[i] = htole16(info->pv_handle[i]);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930201 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930202 attr_entry->metadata[1 + info->pv_num * sizeof(uint16_t)] =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930203 info->def_num;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930204 memcpy(attr_entry->metadata + 1 /* sizeof(pv num) */ +
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930205 info->pv_num * sizeof(uint16_t) + 1 /* sizeof(def num)*/,
Andrew Jeffery9c766792022-08-10 23:12:49 +0930206 info->def_index, info->def_num);
207}
208
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930209LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930210int pldm_bios_table_attr_entry_enum_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930211 void *entry, size_t entry_length,
212 const struct pldm_bios_table_attr_entry_enum_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930213{
214 POINTER_CHECK(entry);
215 POINTER_CHECK(info);
216 size_t length = pldm_bios_table_attr_entry_enum_encode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930217 info->pv_num, info->def_num);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930218 BUFFER_SIZE_EXPECT(entry_length, length);
219 pldm_bios_table_attr_entry_enum_encode(entry, entry_length, info);
220 return PLDM_SUCCESS;
221}
222
223#define ATTR_TYPE_EXPECT(type, expected) \
224 do { \
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930225 if ((type) != (expected) && (type) != ((expected) | 0x80)) \
Andrew Jeffery9c766792022-08-10 23:12:49 +0930226 return PLDM_ERROR_INVALID_DATA; \
227 } while (0)
228
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930229LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930230uint8_t pldm_bios_table_attr_entry_enum_decode_pv_num(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930231 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930232{
233 return entry->metadata[0];
234}
235
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930236LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930237int pldm_bios_table_attr_entry_enum_decode_pv_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930238 const struct pldm_bios_attr_table_entry *entry, uint8_t *pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930239{
240 POINTER_CHECK(entry);
241 POINTER_CHECK(pv_num);
242 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
243 *pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
244 return PLDM_SUCCESS;
245}
246
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930247LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930248uint8_t pldm_bios_table_attr_entry_enum_decode_def_num(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930249 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930250{
251 uint8_t pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
252 return entry->metadata[sizeof(uint8_t) /* pv_num */ +
253 sizeof(uint16_t) * pv_num];
254}
255
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930256LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930257int pldm_bios_table_attr_entry_enum_decode_def_num_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930258 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930259{
260 POINTER_CHECK(entry);
261 POINTER_CHECK(def_num);
262 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
263 *def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
264 return PLDM_SUCCESS;
265}
266
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930267LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930268uint8_t pldm_bios_table_attr_entry_enum_decode_pv_hdls(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930269 const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
270 uint8_t pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930271{
272 uint8_t num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
273 num = num < pv_num ? num : pv_num;
274 size_t i;
275 for (i = 0; i < num; i++) {
276 uint16_t *hdl = (uint16_t *)(entry->metadata + sizeof(uint8_t) +
277 i * sizeof(uint16_t));
278 pv_hdls[i] = le16toh(*hdl);
279 }
280 return num;
281}
282
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930283LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930284int pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930285 const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
286 uint8_t pv_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930287{
288 POINTER_CHECK(entry);
289 POINTER_CHECK(pv_hdls);
290 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
291 uint8_t num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930292 if (num != pv_num) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930293 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930294 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930295 pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pv_hdls, pv_num);
296 return PLDM_SUCCESS;
297}
298
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930299LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930300uint8_t pldm_bios_table_attr_entry_enum_decode_def_indices(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930301 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_indices,
302 uint8_t def_num)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930303{
304 uint8_t num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
305 num = num < def_num ? num : def_num;
306 uint8_t pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
307 const uint8_t *p = entry->metadata +
308 sizeof(uint8_t) /* number of possible values*/
309 + pv_num * sizeof(uint16_t) /* possible values */
310 + sizeof(uint8_t); /* number of default values */
311 memcpy(def_indices, p, num);
312 return num;
313}
314
315/** @brief Get length of an enum attribute entry
316 */
317static size_t attr_table_entry_length_enum(const void *entry)
318{
319 uint8_t pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
320 uint8_t def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
321 return pldm_bios_table_attr_entry_enum_encode_length(pv_num, def_num);
322}
323
324struct attr_table_string_entry_fields {
325 uint8_t string_type;
326 uint16_t min_length;
327 uint16_t max_length;
328 uint16_t def_length;
329 uint8_t def_string[1];
330} __attribute__((packed));
331
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930332LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930333size_t pldm_bios_table_attr_entry_string_encode_length(uint16_t def_str_len)
334{
335 return sizeof(struct pldm_bios_attr_table_entry) -
336 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
337 sizeof(struct attr_table_string_entry_fields) -
338 MEMBER_SIZE(attr_table_string_entry_fields, def_string) +
339 def_str_len;
340}
341
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930342LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930343void pldm_bios_table_attr_entry_string_encode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930344 void *entry, size_t entry_length,
345 const struct pldm_bios_table_attr_entry_string_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930346{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930347 size_t length = pldm_bios_table_attr_entry_string_encode_length(
348 info->def_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930349 assert(length <= entry_length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930350 uint8_t attr_type = info->read_only ? PLDM_BIOS_STRING_READ_ONLY :
351 PLDM_BIOS_STRING;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930352 attr_table_entry_encode_header(entry, entry_length, attr_type,
353 info->name_handle);
354 struct pldm_bios_attr_table_entry *attr_entry = entry;
355 struct attr_table_string_entry_fields *attr_fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930356 (struct attr_table_string_entry_fields *)attr_entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930357 attr_fields->string_type = info->string_type;
358 attr_fields->min_length = htole16(info->min_length);
359 attr_fields->max_length = htole16(info->max_length);
360 attr_fields->def_length = htole16(info->def_length);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930361 if (info->def_length != 0 && info->def_string != NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930362 memcpy(attr_fields->def_string, info->def_string,
363 info->def_length);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930364 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930365}
366
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930367#define PLDM_STRING_TYPE_MAX 5
Andrew Jeffery9c766792022-08-10 23:12:49 +0930368#define PLDM_STRING_TYPE_VENDOR 0xff
369
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930370LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930371int pldm_bios_table_attr_entry_string_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930372 const struct pldm_bios_table_attr_entry_string_info *info,
373 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930374{
375 if (info->min_length > info->max_length) {
376 set_errmsg(errmsg, "MinimumStingLength should not be greater "
377 "than MaximumStringLength");
378 return PLDM_ERROR_INVALID_DATA;
379 }
380 if (info->min_length == info->max_length &&
381 info->def_length != info->min_length) {
382 set_errmsg(errmsg, "Wrong DefaultStringLength");
383 return PLDM_ERROR_INVALID_DATA;
384 }
385 if (info->def_length > info->max_length ||
386 info->def_length < info->min_length) {
387 set_errmsg(errmsg, "Wrong DefaultStringLength");
388 return PLDM_ERROR_INVALID_DATA;
389 }
390 if (info->string_type > PLDM_STRING_TYPE_MAX &&
391 info->string_type != PLDM_STRING_TYPE_VENDOR) {
392 set_errmsg(errmsg, "Wrong StringType");
393 return PLDM_ERROR_INVALID_DATA;
394 }
395 if (info->def_length != strlen(info->def_string)) {
396 set_errmsg(errmsg, "Length of DefaultString should be equal to "
397 "DefaultStringLength");
398 return PLDM_ERROR_INVALID_DATA;
399 }
400
401 return PLDM_SUCCESS;
402}
403
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930404LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930405int pldm_bios_table_attr_entry_string_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930406 void *entry, size_t entry_length,
407 const struct pldm_bios_table_attr_entry_string_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930408{
409 POINTER_CHECK(entry);
410 POINTER_CHECK(info);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930411 size_t length = pldm_bios_table_attr_entry_string_encode_length(
412 info->def_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930413 BUFFER_SIZE_EXPECT(entry_length, length);
414 if (pldm_bios_table_attr_entry_string_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930415 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930416 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930417 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930418 pldm_bios_table_attr_entry_string_encode(entry, entry_length, info);
419 return PLDM_SUCCESS;
420}
421
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930422LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930423uint16_t pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930424 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930425{
426 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930427 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930428 return le16toh(fields->def_length);
429}
430
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930431LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930432int pldm_bios_table_attr_entry_string_decode_def_string_length_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930433 const struct pldm_bios_attr_table_entry *entry,
434 uint16_t *def_string_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930435{
436 POINTER_CHECK(entry);
437 POINTER_CHECK(def_string_length);
438 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_STRING);
439 *def_string_length =
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_SUCCESS;
443}
444
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930445LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930446uint8_t pldm_bios_table_attr_entry_string_decode_string_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930447 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930448{
449 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930450 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930451 return fields->string_type;
452}
453
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930454LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930455uint16_t pldm_bios_table_attr_entry_string_decode_max_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930456 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930457{
458 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930459 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930460 return le16toh(fields->max_length);
461}
462
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930463LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930464uint16_t pldm_bios_table_attr_entry_string_decode_min_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930465 const struct pldm_bios_attr_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930466{
467 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930468 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930469 return le16toh(fields->min_length);
470}
471
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930472LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930473uint16_t pldm_bios_table_attr_entry_string_decode_def_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930474 const struct pldm_bios_attr_table_entry *entry, char *buffer,
475 size_t size)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930476{
477 uint16_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930478 pldm_bios_table_attr_entry_string_decode_def_string_length(
479 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930480 length = length < (size - 1) ? length : (size - 1);
481 struct attr_table_string_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930482 (struct attr_table_string_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930483 memcpy(buffer, fields->def_string, length);
484 buffer[length] = 0;
485 return length;
486}
487
488/** @brief Get length of a string attribute entry
489 */
490static size_t attr_table_entry_length_string(const void *entry)
491{
492 uint16_t def_str_len =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930493 pldm_bios_table_attr_entry_string_decode_def_string_length(
494 entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930495 return pldm_bios_table_attr_entry_string_encode_length(def_str_len);
496}
497
498struct attr_table_integer_entry_fields {
499 uint64_t lower_bound;
500 uint64_t upper_bound;
501 uint32_t scalar_increment;
502 uint64_t default_value;
503} __attribute__((packed));
504
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930505LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930506size_t pldm_bios_table_attr_entry_integer_encode_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930507{
508 return sizeof(struct pldm_bios_attr_table_entry) - 1 +
509 sizeof(struct attr_table_integer_entry_fields);
510}
511
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930512LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930513void pldm_bios_table_attr_entry_integer_encode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930514 void *entry, size_t entry_length,
515 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930516{
517 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
518 assert(length <= entry_length);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930519 uint8_t attr_type = info->read_only ? PLDM_BIOS_INTEGER_READ_ONLY :
520 PLDM_BIOS_INTEGER;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930521 attr_table_entry_encode_header(entry, entry_length, attr_type,
522 info->name_handle);
523 struct pldm_bios_attr_table_entry *attr_entry = entry;
524 struct attr_table_integer_entry_fields *attr_fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930525 (struct attr_table_integer_entry_fields *)attr_entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930526 attr_fields->lower_bound = htole64(info->lower_bound);
527 attr_fields->upper_bound = htole64(info->upper_bound);
528 attr_fields->scalar_increment = htole32(info->scalar_increment);
529 attr_fields->default_value = htole64(info->default_value);
530}
531
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930532LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930533int pldm_bios_table_attr_entry_integer_info_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930534 const struct pldm_bios_table_attr_entry_integer_info *info,
535 const char **errmsg)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930536{
537 if (info->lower_bound == info->upper_bound) {
538 if (info->default_value != info->lower_bound) {
539 set_errmsg(errmsg, "Wrong DefaultValue");
540 return PLDM_ERROR_INVALID_DATA;
541 }
542 if (info->scalar_increment != 0) {
543 set_errmsg(errmsg, "Wrong ScalarIncrement");
544 return PLDM_ERROR_INVALID_DATA;
545 }
546 return PLDM_SUCCESS;
547 }
548 if (info->lower_bound > info->upper_bound) {
549 set_errmsg(errmsg,
550 "LowerBound should not be greater than UpperBound");
551 return PLDM_ERROR_INVALID_DATA;
552 }
553 if (info->default_value > info->upper_bound ||
554 info->default_value < info->lower_bound) {
555 set_errmsg(errmsg, "Wrong DefaultValue");
556 return PLDM_ERROR_INVALID_DATA;
557 }
558 if (info->scalar_increment == 0) {
559 set_errmsg(errmsg, "ScalarIncrement should not be zero when "
560 "lower_bound != upper_bound");
561 return PLDM_ERROR_INVALID_DATA;
562 }
563 if ((info->default_value - info->lower_bound) %
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930564 info->scalar_increment !=
Andrew Jeffery9c766792022-08-10 23:12:49 +0930565 0) {
566 set_errmsg(errmsg, "Wrong DefaultValue or ScalarIncrement");
567 return PLDM_ERROR_INVALID_DATA;
568 }
569 return PLDM_SUCCESS;
570}
571
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930572LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930573int pldm_bios_table_attr_entry_integer_encode_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930574 void *entry, size_t entry_length,
575 const struct pldm_bios_table_attr_entry_integer_info *info)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930576{
577 POINTER_CHECK(entry);
578 POINTER_CHECK(info);
579 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
580 BUFFER_SIZE_EXPECT(entry_length, length);
581 if (pldm_bios_table_attr_entry_integer_info_check(info, NULL) !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930582 PLDM_SUCCESS) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930583 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930584 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930585 pldm_bios_table_attr_entry_integer_encode(entry, entry_length, info);
586 return PLDM_SUCCESS;
587}
588
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930589LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930590void pldm_bios_table_attr_entry_integer_decode(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930591 const struct pldm_bios_attr_table_entry *entry, uint64_t *lower,
592 uint64_t *upper, uint32_t *scalar, uint64_t *def)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930593{
594 struct attr_table_integer_entry_fields *fields =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930595 (struct attr_table_integer_entry_fields *)entry->metadata;
Andrew Jeffery9c766792022-08-10 23:12:49 +0930596 *lower = le64toh(fields->lower_bound);
597 *upper = le64toh(fields->upper_bound);
598 *scalar = le32toh(fields->scalar_increment);
599 *def = le64toh(fields->default_value);
600}
601
602static size_t attr_table_entry_length_integer(const void *entry)
603{
604 (void)entry;
605 return pldm_bios_table_attr_entry_integer_encode_length();
606}
607
608struct table_entry_length {
609 uint8_t attr_type;
610 size_t (*entry_length_handler)(const void *);
611};
612
Andrew Jeffery0a05b122023-04-05 14:03:36 +0930613#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
Andrew Jeffery9c766792022-08-10 23:12:49 +0930614
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930615static const struct table_entry_length *
616find_table_entry_length_by_type(uint8_t attr_type,
617 const struct table_entry_length *handlers,
618 size_t count)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930619{
620 size_t i;
621 for (i = 0; i < count; i++) {
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930622 if (attr_type == handlers[i].attr_type) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930623 return &handlers[i];
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930624 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930625 }
626 return NULL;
627}
628
629static const struct table_entry_length attr_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930630 { .attr_type = PLDM_BIOS_ENUMERATION,
631 .entry_length_handler = attr_table_entry_length_enum },
632 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
633 .entry_length_handler = attr_table_entry_length_enum },
634 { .attr_type = PLDM_BIOS_STRING,
635 .entry_length_handler = attr_table_entry_length_string },
636 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
637 .entry_length_handler = attr_table_entry_length_string },
638 { .attr_type = PLDM_BIOS_INTEGER,
639 .entry_length_handler = attr_table_entry_length_integer },
640 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
641 .entry_length_handler = attr_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930642};
643
644static size_t attr_table_entry_length(const void *table_entry)
645{
646 const struct pldm_bios_attr_table_entry *entry = table_entry;
647 const struct table_entry_length *attr_table_entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930648 find_table_entry_length_by_type(entry->attr_type,
649 attr_table_entries,
650 ARRAY_SIZE(attr_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930651 assert(attr_table_entry != NULL);
652 assert(attr_table_entry->entry_length_handler != NULL);
653
654 return attr_table_entry->entry_length_handler(entry);
655}
656
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930657LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930658uint16_t pldm_bios_table_attr_value_entry_decode_attribute_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930659 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930660{
661 return le16toh(entry->attr_handle);
662}
663
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930664LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930665uint8_t pldm_bios_table_attr_value_entry_decode_attribute_type(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930666 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930667{
668 return entry->attr_type;
669}
670
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930671LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930672size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count)
673{
674 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
675 sizeof(count) + count;
676}
677
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930678LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930679void pldm_bios_table_attr_value_entry_encode_enum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930680 void *entry, size_t entry_length, uint16_t attr_handle,
681 uint8_t attr_type, uint8_t count, const uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930682{
683 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930684 pldm_bios_table_attr_value_entry_encode_enum_length(count);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930685 assert(length <= entry_length);
686
687 struct pldm_bios_attr_val_table_entry *table_entry = entry;
688 table_entry->attr_handle = htole16(attr_handle);
689 table_entry->attr_type = attr_type;
690 table_entry->value[0] = count;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930691 if (count != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930692 memcpy(&table_entry->value[1], handles, count);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930693 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930694}
695
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930696LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930697uint8_t pldm_bios_table_attr_value_entry_enum_decode_number(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930698 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930699{
700 return entry->value[0];
701}
702
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930703LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930704uint8_t pldm_bios_table_attr_value_entry_enum_decode_handles(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930705 const struct pldm_bios_attr_val_table_entry *entry, uint8_t *handles,
706 uint8_t number)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930707{
708 uint8_t curr_num =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930709 pldm_bios_table_attr_value_entry_enum_decode_number(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930710 number = number < curr_num ? number : curr_num;
711 memcpy(handles, &entry->value[1], number);
712
713 return number;
714}
715
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930716LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930717int pldm_bios_table_attr_value_entry_encode_enum_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930718 void *entry, size_t entry_length, uint16_t attr_handle,
719 uint8_t attr_type, uint8_t count, uint8_t *handles)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930720{
721 POINTER_CHECK(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930722 if (count != 0 && handles == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930723 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930724 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930725 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_ENUMERATION);
726 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930727 pldm_bios_table_attr_value_entry_encode_enum_length(count);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930728 BUFFER_SIZE_EXPECT(entry_length, length);
729 pldm_bios_table_attr_value_entry_encode_enum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930730 entry, entry_length, attr_handle, attr_type, count, handles);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930731 return PLDM_SUCCESS;
732}
733
734static size_t attr_value_table_entry_length_enum(const void *entry)
735{
736 uint8_t number =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930737 pldm_bios_table_attr_value_entry_enum_decode_number(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930738 return pldm_bios_table_attr_value_entry_encode_enum_length(number);
739}
740
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930741LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930742size_t
743pldm_bios_table_attr_value_entry_encode_string_length(uint16_t string_length)
744{
745 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
746 sizeof(string_length) + string_length;
747}
748
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930749LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930750void pldm_bios_table_attr_value_entry_encode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930751 void *entry, size_t entry_length, uint16_t attr_handle,
752 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930753{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930754 size_t length = pldm_bios_table_attr_value_entry_encode_string_length(
755 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930756 assert(length <= entry_length);
757
758 struct pldm_bios_attr_val_table_entry *table_entry = entry;
759 table_entry->attr_handle = htole16(attr_handle);
760 table_entry->attr_type = attr_type;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930761 if (str_length != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930762 memcpy(table_entry->value + sizeof(str_length), str,
763 str_length);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930764 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930765 str_length = htole16(str_length);
766 memcpy(table_entry->value, &str_length, sizeof(str_length));
767}
768
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930769LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930770uint16_t pldm_bios_table_attr_value_entry_string_decode_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930771 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930772{
773 uint16_t str_length = 0;
774 memcpy(&str_length, entry->value, sizeof(str_length));
775 return le16toh(str_length);
776}
777
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930778LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930779void pldm_bios_table_attr_value_entry_string_decode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930780 const struct pldm_bios_attr_val_table_entry *entry,
781 struct variable_field *current_string)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930782{
783 current_string->length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930784 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930785 current_string->ptr =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930786 entry->value + sizeof(uint16_t); // sizeof(CurrentStringLength)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930787}
788
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930789LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930790int pldm_bios_table_attr_value_entry_encode_string_check(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930791 void *entry, size_t entry_length, uint16_t attr_handle,
792 uint8_t attr_type, uint16_t str_length, const char *str)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930793{
794 POINTER_CHECK(entry);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930795 if (str_length != 0 && str == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930796 return PLDM_ERROR_INVALID_DATA;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930797 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930798 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_STRING);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930799 size_t length = pldm_bios_table_attr_value_entry_encode_string_length(
800 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930801 BUFFER_SIZE_EXPECT(entry_length, length);
802 pldm_bios_table_attr_value_entry_encode_string(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930803 entry, entry_length, attr_handle, attr_type, str_length, str);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930804 return PLDM_SUCCESS;
805}
806
807static size_t attr_value_table_entry_length_string(const void *entry)
808{
809 uint16_t str_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930810 pldm_bios_table_attr_value_entry_string_decode_length(entry);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930811 return pldm_bios_table_attr_value_entry_encode_string_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930812 str_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930813}
814
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930815LIBPLDM_ABI_STABLE
Andrew Jeffery319304f2023-04-05 13:53:18 +0930816size_t pldm_bios_table_attr_value_entry_encode_integer_length(void)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930817{
818 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
819 sizeof(uint64_t);
820}
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930821
822LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930823void pldm_bios_table_attr_value_entry_encode_integer(void *entry,
824 size_t entry_length,
825 uint16_t attr_handle,
826 uint8_t attr_type,
827 uint64_t cv)
828{
829 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930830 pldm_bios_table_attr_value_entry_encode_integer_length();
Andrew Jeffery9c766792022-08-10 23:12:49 +0930831 assert(length <= entry_length);
832
833 struct pldm_bios_attr_val_table_entry *table_entry = entry;
834 table_entry->attr_handle = htole16(attr_handle);
835 table_entry->attr_type = attr_type;
836 cv = htole64(cv);
837 memcpy(table_entry->value, &cv, sizeof(uint64_t));
838}
839
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930840LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930841int pldm_bios_table_attr_value_entry_encode_integer_check(void *entry,
842 size_t entry_length,
843 uint16_t attr_handle,
844 uint8_t attr_type,
845 uint64_t cv)
846{
847 POINTER_CHECK(entry);
848 size_t length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930849 pldm_bios_table_attr_value_entry_encode_integer_length();
Andrew Jeffery9c766792022-08-10 23:12:49 +0930850 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_INTEGER);
851 BUFFER_SIZE_EXPECT(entry_length, length);
852 pldm_bios_table_attr_value_entry_encode_integer(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930853 entry, entry_length, attr_handle, attr_type, cv);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930854 return PLDM_SUCCESS;
855}
856
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930857LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930858uint64_t pldm_bios_table_attr_value_entry_integer_decode_cv(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930859 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930860{
861 uint64_t cv = 0;
862 memcpy(&cv, entry->value, sizeof(cv));
863 cv = le64toh(cv);
864 return cv;
865}
866
867static size_t attr_value_table_entry_length_integer(const void *entry)
868{
869 (void)entry;
870 return pldm_bios_table_attr_value_entry_encode_integer_length();
871}
872
873static const struct table_entry_length attr_value_table_entries[] = {
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930874 { .attr_type = PLDM_BIOS_ENUMERATION,
875 .entry_length_handler = attr_value_table_entry_length_enum },
876 { .attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
877 .entry_length_handler = attr_value_table_entry_length_enum },
878 { .attr_type = PLDM_BIOS_STRING,
879 .entry_length_handler = attr_value_table_entry_length_string },
880 { .attr_type = PLDM_BIOS_STRING_READ_ONLY,
881 .entry_length_handler = attr_value_table_entry_length_string },
882 { .attr_type = PLDM_BIOS_INTEGER,
883 .entry_length_handler = attr_value_table_entry_length_integer },
884 { .attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
885 .entry_length_handler = attr_value_table_entry_length_integer },
Andrew Jeffery9c766792022-08-10 23:12:49 +0930886};
887
888static size_t attr_value_table_entry_length(const void *table_entry)
889{
890 const struct pldm_bios_attr_val_table_entry *entry = table_entry;
891 const struct table_entry_length *entry_length =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930892 find_table_entry_length_by_type(
893 entry->attr_type, attr_value_table_entries,
894 ARRAY_SIZE(attr_value_table_entries));
Andrew Jeffery9c766792022-08-10 23:12:49 +0930895 assert(entry_length != NULL);
896 assert(entry_length->entry_length_handler != NULL);
897
898 return entry_length->entry_length_handler(entry);
899}
900
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930901LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930902size_t pldm_bios_table_attr_value_entry_length(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930903 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930904{
905 return attr_value_table_entry_length(entry);
906}
907
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930908LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930909uint16_t pldm_bios_table_attr_value_entry_decode_handle(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930910 const struct pldm_bios_attr_val_table_entry *entry)
Andrew Jeffery9c766792022-08-10 23:12:49 +0930911{
912 return le16toh(entry->attr_handle);
913}
914
915static size_t pad_size_get(size_t size_without_pad)
916{
917 return ((size_without_pad % 4) ? (4 - size_without_pad % 4) : 0);
918}
919
920static uint8_t *pad_append(uint8_t *table_end, size_t pad_size)
921{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930922 while (pad_size--) {
Andrew Jeffery9c766792022-08-10 23:12:49 +0930923 *table_end++ = 0;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +0930924 }
Andrew Jeffery9c766792022-08-10 23:12:49 +0930925
926 return table_end;
927}
928
929static uint8_t *checksum_append(uint8_t *table_end, uint32_t checksum)
930{
931 checksum = htole32(checksum);
932 memcpy(table_end, &checksum, sizeof(checksum));
933
934 return table_end + sizeof(checksum);
935}
936
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930937LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930938size_t pldm_bios_table_pad_checksum_size(size_t size_without_pad)
939{
940 size_t size = pad_size_get(size_without_pad) +
941 sizeof(uint32_t) /*sizeof(checksum)*/;
942 return size;
943}
944
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930945LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930946size_t pldm_bios_table_append_pad_checksum(void *table, size_t size,
947 size_t size_without_pad)
948{
Andrew Jeffery9c766792022-08-10 23:12:49 +0930949 size_t pad_checksum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930950 pldm_bios_table_pad_checksum_size(size_without_pad);
Andrew Jeffery9c766792022-08-10 23:12:49 +0930951 size_t total_length = size_without_pad + pad_checksum_size;
952 assert(size >= total_length);
953
954 uint8_t *table_end = (uint8_t *)table + size_without_pad;
955 size_t pad_size = pad_size_get(size_without_pad);
956 table_end = pad_append(table_end, pad_size);
957
958 uint32_t checksum = crc32(table, size_without_pad + pad_size);
959 checksum_append(table_end, checksum);
960
961 return total_length;
962}
963
964struct pldm_bios_table_iter {
965 const uint8_t *table_data;
966 size_t table_len;
967 size_t current_pos;
968 size_t (*entry_length_handler)(const void *table_entry);
969};
970
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930971LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930972struct pldm_bios_table_iter *
973pldm_bios_table_iter_create(const void *table, size_t length,
974 enum pldm_bios_table_types type)
975{
976 struct pldm_bios_table_iter *iter = malloc(sizeof(*iter));
977 assert(iter != NULL);
978 iter->table_data = table;
979 iter->table_len = length;
980 iter->current_pos = 0;
981 iter->entry_length_handler = NULL;
982 switch (type) {
983 case PLDM_BIOS_STRING_TABLE:
984 iter->entry_length_handler = string_table_entry_length;
985 break;
986 case PLDM_BIOS_ATTR_TABLE:
987 iter->entry_length_handler = attr_table_entry_length;
988 break;
989 case PLDM_BIOS_ATTR_VAL_TABLE:
990 iter->entry_length_handler = attr_value_table_entry_length;
991 break;
992 }
993
994 return iter;
995}
996
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +0930997LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +0930998void pldm_bios_table_iter_free(struct pldm_bios_table_iter *iter)
999{
1000 free(iter);
1001}
1002
1003#define pad_and_check_max 7
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301004LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301005bool pldm_bios_table_iter_is_end(const struct pldm_bios_table_iter *iter)
1006{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301007 if (iter->table_len - iter->current_pos <= pad_and_check_max) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301008 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301009 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301010 return false;
1011}
1012
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301013LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301014void pldm_bios_table_iter_next(struct pldm_bios_table_iter *iter)
1015{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301016 if (pldm_bios_table_iter_is_end(iter)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301017 return;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301018 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301019 const void *entry = iter->table_data + iter->current_pos;
1020 iter->current_pos += iter->entry_length_handler(entry);
1021}
1022
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301023LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301024const void *pldm_bios_table_iter_value(struct pldm_bios_table_iter *iter)
1025{
1026 return iter->table_data + iter->current_pos;
1027}
1028
1029typedef bool (*equal_handler)(const void *entry, const void *key);
1030
1031static const void *
1032pldm_bios_table_entry_find_by_iter(struct pldm_bios_table_iter *iter,
1033 const void *key, equal_handler equal)
1034{
1035 const void *entry;
1036 while (!pldm_bios_table_iter_is_end(iter)) {
1037 entry = pldm_bios_table_iter_value(iter);
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301038 if (equal(entry, key)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301039 return entry;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301040 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301041 pldm_bios_table_iter_next(iter);
1042 }
1043 return NULL;
1044}
1045
1046static const void *
1047pldm_bios_table_entry_find_from_table(const void *table, size_t length,
1048 enum pldm_bios_table_types type,
1049 equal_handler equal, const void *key)
1050{
1051 struct pldm_bios_table_iter *iter =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301052 pldm_bios_table_iter_create(table, length, type);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301053 const void *entry =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301054 pldm_bios_table_entry_find_by_iter(iter, key, equal);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301055 pldm_bios_table_iter_free(iter);
1056 return entry;
1057}
1058
1059static bool string_table_handle_equal(const void *entry, const void *key)
1060{
1061 const struct pldm_bios_string_table_entry *string_entry = entry;
1062 uint16_t handle = *(uint16_t *)key;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301063 if (pldm_bios_table_string_entry_decode_handle(string_entry) ==
1064 handle) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301065 return true;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301066 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301067 return false;
1068}
1069
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301070LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301071const struct pldm_bios_string_table_entry *
1072pldm_bios_table_string_find_by_handle(const void *table, size_t length,
1073 uint16_t handle)
1074{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301075 return pldm_bios_table_entry_find_from_table(table, length,
1076 PLDM_BIOS_STRING_TABLE,
1077 string_table_handle_equal,
1078 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301079}
1080
1081struct string_equal_arg {
1082 uint16_t str_length;
1083 const char *str;
1084};
1085
1086static bool string_table_string_equal(const void *entry, const void *key)
1087{
1088 const struct pldm_bios_string_table_entry *string_entry = entry;
1089 const struct string_equal_arg *arg = key;
1090 if (arg->str_length !=
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301091 pldm_bios_table_string_entry_decode_string_length(string_entry)) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301092 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301093 }
1094 if (memcmp(string_entry->name, arg->str, arg->str_length) != 0) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301095 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301096 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301097 return true;
1098}
1099
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301100LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301101const struct pldm_bios_string_table_entry *
1102pldm_bios_table_string_find_by_string(const void *table, size_t length,
1103 const char *str)
1104{
1105 uint16_t str_length = strlen(str);
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301106 struct string_equal_arg arg = { str_length, str };
1107 return pldm_bios_table_entry_find_from_table(table, length,
1108 PLDM_BIOS_STRING_TABLE,
1109 string_table_string_equal,
1110 &arg);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301111}
1112
1113static bool attr_table_handle_equal(const void *entry, const void *key)
1114{
1115 uint16_t handle = *(uint16_t *)key;
1116 return pldm_bios_table_attr_entry_decode_attribute_handle(entry) ==
1117 handle;
1118}
1119
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301120LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301121const struct pldm_bios_attr_table_entry *
1122pldm_bios_table_attr_find_by_handle(const void *table, size_t length,
1123 uint16_t handle)
1124{
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301125 return pldm_bios_table_entry_find_from_table(table, length,
1126 PLDM_BIOS_ATTR_TABLE,
1127 attr_table_handle_equal,
1128 &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301129}
1130
1131static bool attr_table_string_handle_equal(const void *entry, const void *key)
1132{
1133 uint16_t handle = *(uint16_t *)key;
1134 return pldm_bios_table_attr_entry_decode_string_handle(entry) == handle;
1135}
1136
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301137LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301138const struct pldm_bios_attr_table_entry *
1139pldm_bios_table_attr_find_by_string_handle(const void *table, size_t length,
1140 uint16_t handle)
1141{
1142 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301143 table, length, PLDM_BIOS_ATTR_TABLE,
1144 attr_table_string_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301145}
1146
1147static bool attr_value_table_handle_equal(const void *entry, const void *key)
1148{
1149 uint16_t handle = *(uint16_t *)key;
1150 return pldm_bios_table_attr_value_entry_decode_handle(entry) == handle;
1151}
1152
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301153LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301154const struct pldm_bios_attr_val_table_entry *
1155pldm_bios_table_attr_value_find_by_handle(const void *table, size_t length,
1156 uint16_t handle)
1157{
1158 return pldm_bios_table_entry_find_from_table(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301159 table, length, PLDM_BIOS_ATTR_VAL_TABLE,
1160 attr_value_table_handle_equal, &handle);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301161}
1162
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301163LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301164int pldm_bios_table_attr_value_copy_and_update(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301165 const void *src_table, size_t src_length, void *dest_table,
1166 size_t *dest_length, const void *entry, size_t entry_length)
Andrew Jeffery9c766792022-08-10 23:12:49 +09301167{
1168 struct pldm_bios_table_iter *iter = pldm_bios_table_iter_create(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301169 src_table, src_length, PLDM_BIOS_ATTR_VAL_TABLE);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301170
1171 int rc = PLDM_SUCCESS;
Andrew Jefferyfbe61d72023-04-05 20:28:23 +09301172 const struct pldm_bios_attr_val_table_entry *tmp;
1173 const struct pldm_bios_attr_val_table_entry *to_update = entry;
1174 size_t buffer_length = *dest_length;
1175 size_t copied_length = 0;
1176 size_t length = 0;
Andrew Jeffery9c766792022-08-10 23:12:49 +09301177 while (!pldm_bios_table_iter_is_end(iter)) {
1178 tmp = pldm_bios_table_iter_attr_value_entry_value(iter);
1179 length = attr_value_table_entry_length(tmp);
1180
1181 /* we need the tmp's entry_length here, iter_next will calculate
1182 * it too, use current_pos directly to avoid calculating it
1183 * twice */
1184 iter->current_pos += length;
1185 if (tmp->attr_handle == to_update->attr_handle) {
1186 if (tmp->attr_type != to_update->attr_type) {
1187 rc = PLDM_ERROR_INVALID_DATA;
1188 goto out;
1189 }
1190 length = entry_length;
1191 tmp = entry;
1192 }
1193 if (copied_length + length > buffer_length) {
1194 rc = PLDM_ERROR_INVALID_LENGTH;
1195 goto out;
1196 }
1197 memcpy((uint8_t *)dest_table + copied_length, tmp, length);
1198 copied_length += length;
1199 }
1200
1201 size_t pad_checksum_size =
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301202 pldm_bios_table_pad_checksum_size(copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301203 if ((pad_checksum_size + copied_length) > buffer_length) {
1204 rc = PLDM_ERROR_INVALID_LENGTH;
1205 goto out;
1206 }
1207
1208 *dest_length = pldm_bios_table_append_pad_checksum(
Andrew Jeffery37dd6a32023-05-12 16:04:06 +09301209 dest_table, buffer_length, copied_length);
Andrew Jeffery9c766792022-08-10 23:12:49 +09301210out:
1211 pldm_bios_table_iter_free(iter);
1212 return rc;
1213}
1214
Andrew Jeffery9d2a1c62023-06-05 13:02:16 +09301215LIBPLDM_ABI_STABLE
Andrew Jeffery9c766792022-08-10 23:12:49 +09301216bool pldm_bios_table_checksum(const uint8_t *table, size_t size)
1217{
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301218 if (table == NULL) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301219 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301220 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301221
1222 // 12: BIOSStringHandle(uint16) + BIOSStringLength(uint16) +
1223 // Variable(4) + checksum(uint32)
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301224 if (size < 12) {
Andrew Jeffery9c766792022-08-10 23:12:49 +09301225 return false;
Andrew Jefferyd2c64cb2023-04-05 19:51:39 +09301226 }
Andrew Jeffery9c766792022-08-10 23:12:49 +09301227
1228 uint32_t src_crc = le32toh(*(uint32_t *)(table + size - 4));
1229 uint32_t dst_crc = crc32(table, size - 4);
1230
1231 return src_crc == dst_crc;
1232}