blob: 271d1797cd38ef2a7447679f11a011b646a285b5 [file] [log] [blame]
John Wang02700402019-10-06 16:34:29 +08001#include <assert.h>
2#include <endian.h>
3#include <stdbool.h>
4#include <stdint.h>
5#include <stdlib.h>
6#include <string.h>
7
8#include "bios.h"
9#include "bios_table.h"
10
11#define POINTER_CHECK(pointer) \
12 do { \
13 if (pointer == NULL) \
14 return PLDM_ERROR_INVALID_DATA; \
15 } while (0)
16
17#define ATTR_TYPE_EXPECT(type, expected) \
18 do { \
19 if (type != expected && type != (expected | 0x80)) \
20 return PLDM_ERROR_INVALID_DATA; \
21 } while (0)
22
John Wang3ad21752019-10-06 16:42:21 +080023#define BUFFER_SIZE_EXPECT(current_size, expected_size) \
24 do { \
25 if (current_size < expected_size) \
26 return PLDM_ERROR_INVALID_LENGTH; \
27 } while (0)
28
John Wangdd9a6282019-10-11 18:52:46 +080029#define MEMBER_SIZE(type, member) sizeof(((struct type *)0)->member)
30
31static uint16_t get_bios_string_handle()
32{
33 static uint16_t handle = 0;
34 assert(handle != UINT16_MAX);
35
36 return handle++;
37}
38
39size_t pldm_bios_table_string_entry_encode_length(uint16_t string_length)
40{
41 return sizeof(struct pldm_bios_string_table_entry) -
42 MEMBER_SIZE(pldm_bios_string_table_entry, name) + string_length;
43}
44
45void pldm_bios_table_string_entry_encode(void *entry, size_t entry_length,
46 const char *str, uint16_t str_length)
47{
48 size_t length = pldm_bios_table_string_entry_encode_length(str_length);
49 assert(length <= entry_length);
50 struct pldm_bios_string_table_entry *string_entry = entry;
51 string_entry->string_handle = htole16(get_bios_string_handle());
52 string_entry->string_length = htole16(str_length);
53 memcpy(string_entry->name, str, str_length);
54}
55
56int pldm_bios_table_string_entry_encode_check(void *entry, size_t entry_length,
57 const char *str,
58 uint16_t str_length)
59{
60 if (str_length == 0)
61 return PLDM_ERROR_INVALID_DATA;
62 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);
66 pldm_bios_table_string_entry_encode(entry, entry_length, str,
67 str_length);
68 return PLDM_SUCCESS;
69}
70
71uint16_t pldm_bios_table_string_entry_decode_handle(
72 const struct pldm_bios_string_table_entry *entry)
73{
74 return le16toh(entry->string_handle);
75}
76
77uint16_t pldm_bios_table_string_entry_decode_string_length(
78 const struct pldm_bios_string_table_entry *entry)
79{
80 return le16toh(entry->string_length);
81}
82
83uint16_t pldm_bios_table_string_entry_decode_string(
84 const struct pldm_bios_string_table_entry *entry, char *buffer, size_t size)
85{
86 uint16_t length =
87 pldm_bios_table_string_entry_decode_string_length(entry);
88 length = length < size ? length : size;
89 memcpy(buffer, entry->name, length);
90 buffer[length] = 0;
91 return length;
92}
93
94int pldm_bios_table_string_entry_decode_string_check(
95 const struct pldm_bios_string_table_entry *entry, char *buffer, size_t size)
96{
97 POINTER_CHECK(entry);
98 POINTER_CHECK(buffer);
99 size_t length =
100 pldm_bios_table_string_entry_decode_string_length(entry);
101 BUFFER_SIZE_EXPECT(size, length + 1);
102 pldm_bios_table_string_entry_decode_string(entry, buffer, size);
103 return PLDM_SUCCESS;
104}
105
106static size_t string_table_entry_length(const void *table_entry)
107{
108 const struct pldm_bios_string_table_entry *entry = table_entry;
109 return sizeof(*entry) - sizeof(entry->name) +
110 pldm_bios_table_string_entry_decode_string_length(entry);
111}
112
John Wangccc04552019-10-14 14:28:25 +0800113static uint16_t get_bios_attr_handle()
114{
115 static uint16_t handle = 0;
116 assert(handle != UINT16_MAX);
117
118 return handle++;
119}
120
121static void attr_table_entry_encode_header(void *entry, size_t length,
122 uint8_t attr_type,
123 uint16_t string_handle)
124{
125 struct pldm_bios_attr_table_entry *attr_entry = entry;
126 assert(sizeof(*attr_entry) <= length);
127 attr_entry->attr_handle = htole16(get_bios_attr_handle());
128 attr_entry->attr_type = attr_type;
129 attr_entry->string_handle = htole16(string_handle);
130}
131
132size_t pldm_bios_table_attr_entry_enum_encode_length(uint8_t pv_num,
133 uint8_t def_num)
134{
135 return sizeof(struct pldm_bios_attr_table_entry) -
136 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
137 sizeof(pv_num) + pv_num * sizeof(uint16_t) + sizeof(def_num) +
138 def_num;
139}
140
141void pldm_bios_table_attr_entry_enum_encode(
142 void *entry, size_t entry_length,
143 const struct pldm_bios_table_attr_entry_enum_info *info)
144{
145 size_t length = pldm_bios_table_attr_entry_enum_encode_length(
146 info->pv_num, info->def_num);
147 assert(length <= entry_length);
148 uint8_t attr_type = info->read_only ? PLDM_BIOS_ENUMERATION_READ_ONLY
149 : PLDM_BIOS_ENUMERATION;
150 attr_table_entry_encode_header(entry, entry_length, attr_type,
151 info->name_handle);
152 struct pldm_bios_attr_table_entry *attr_entry = entry;
153 attr_entry->metadata[0] = info->pv_num;
154 uint16_t *pv_hdls =
155 (uint16_t *)(attr_entry->metadata + 1 /* sizeof(pv num) */);
156 size_t i;
157 for (i = 0; i < info->pv_num; i++)
158 pv_hdls[i] = htole16(info->pv_handle[i]);
159 attr_entry->metadata[1 + info->pv_num * sizeof(uint16_t)] =
160 info->def_num;
161 memcpy(attr_entry->metadata + 1 /* sizeof(pv num) */ +
162 info->pv_num * sizeof(uint16_t) + 1 /* sizeof(def num)*/,
163 info->def_index, info->def_num);
164}
165
166int pldm_bios_table_attr_entry_enum_encode_check(
167 void *entry, size_t entry_length,
168 const struct pldm_bios_table_attr_entry_enum_info *info)
169{
170 POINTER_CHECK(entry);
171 POINTER_CHECK(info);
172 size_t length = pldm_bios_table_attr_entry_enum_encode_length(
173 info->pv_num, info->def_num);
174 BUFFER_SIZE_EXPECT(entry_length, length);
175 pldm_bios_table_attr_entry_enum_encode(entry, entry_length, info);
176 return PLDM_SUCCESS;
177}
178
John Wangdd9a6282019-10-11 18:52:46 +0800179#define ATTR_TYPE_EXPECT(type, expected) \
180 do { \
181 if (type != expected && type != (expected | 0x80)) \
182 return PLDM_ERROR_INVALID_DATA; \
183 } while (0)
184
John Wang02700402019-10-06 16:34:29 +0800185uint8_t pldm_bios_table_attr_entry_enum_decode_pv_num(
186 const struct pldm_bios_attr_table_entry *entry)
187{
188 return entry->metadata[0];
189}
190
191int pldm_bios_table_attr_entry_enum_decode_pv_num_check(
192 const struct pldm_bios_attr_table_entry *entry, uint8_t *pv_num)
193{
194 POINTER_CHECK(entry);
195 POINTER_CHECK(pv_num);
196 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
197 *pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
198 return PLDM_SUCCESS;
199}
200
201uint8_t pldm_bios_table_attr_entry_enum_decode_def_num(
202 const struct pldm_bios_attr_table_entry *entry)
203{
204 uint8_t pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
205 return entry->metadata[sizeof(uint8_t) /* pv_num */ +
206 sizeof(uint16_t) * pv_num];
207}
208
209int pldm_bios_table_attr_entry_enum_decode_def_num_check(
210 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_num)
211{
212 POINTER_CHECK(entry);
213 POINTER_CHECK(def_num);
214 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
215 *def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
216 return PLDM_SUCCESS;
217}
218
John Wang3ad21752019-10-06 16:42:21 +0800219uint8_t pldm_bios_table_attr_entry_enum_decode_pv_hdls(
220 const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
221 uint8_t pv_num)
222{
223 uint8_t num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
224 num = num < pv_num ? num : pv_num;
225 size_t i;
226 for (i = 0; i < num; i++) {
227 uint16_t *hdl = (uint16_t *)(entry->metadata + sizeof(uint8_t) +
228 i * sizeof(uint16_t));
229 pv_hdls[i] = le16toh(*hdl);
230 }
231 return num;
232}
233
234int pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
235 const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
236 uint8_t pv_num)
237{
238 POINTER_CHECK(entry);
239 POINTER_CHECK(pv_hdls);
240 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
241 uint8_t num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
242 if (num != pv_num)
243 return PLDM_ERROR_INVALID_DATA;
244 pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pv_hdls, pv_num);
245 return PLDM_SUCCESS;
246}
247
John Wang02700402019-10-06 16:34:29 +0800248/** @brief Get length of an enum attribute entry
249 */
250static size_t
251attr_table_entry_length_enum(const struct pldm_bios_attr_table_entry *entry)
252{
253 uint8_t pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
254 uint8_t def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
John Wangccc04552019-10-14 14:28:25 +0800255 return pldm_bios_table_attr_entry_enum_encode_length(pv_num, def_num);
John Wang02700402019-10-06 16:34:29 +0800256}
257
John Wangccc04552019-10-14 14:28:25 +0800258struct attr_table_string_entry_fields {
259 uint8_t string_type;
260 uint16_t min_length;
261 uint16_t max_length;
262 uint16_t def_length;
263 uint8_t def_string[1];
264} __attribute__((packed));
265
266size_t pldm_bios_table_attr_entry_string_encode_length(uint16_t def_str_len)
267{
268 return sizeof(struct pldm_bios_attr_table_entry) -
269 MEMBER_SIZE(pldm_bios_attr_table_entry, metadata) +
270 sizeof(struct attr_table_string_entry_fields) -
271 MEMBER_SIZE(attr_table_string_entry_fields, def_string) +
272 def_str_len;
273}
274
275void pldm_bios_table_attr_entry_string_encode(
276 void *entry, size_t entry_length,
277 const struct pldm_bios_table_attr_entry_string_info *info)
278{
279 size_t length =
280 pldm_bios_table_attr_entry_string_encode_length(info->def_length);
281 assert(length <= entry_length);
282 uint8_t attr_type =
283 info->read_only ? PLDM_BIOS_STRING_READ_ONLY : PLDM_BIOS_STRING;
284 attr_table_entry_encode_header(entry, entry_length, attr_type,
285 info->name_handle);
286 struct pldm_bios_attr_table_entry *attr_entry = entry;
287 struct attr_table_string_entry_fields *attr_fields =
288 (struct attr_table_string_entry_fields *)attr_entry->metadata;
289 attr_fields->string_type = info->string_type;
290 attr_fields->min_length = htole16(info->min_length);
291 attr_fields->max_length = htole16(info->max_length);
292 attr_fields->def_length = htole16(info->def_length);
293 if (info->def_length != 0 && info->def_string != NULL)
294 memcpy(attr_fields->def_string, info->def_string,
295 info->def_length);
296}
297
298int pldm_bios_table_attr_entry_string_encode_check(
299 void *entry, size_t entry_length,
300 const struct pldm_bios_table_attr_entry_string_info *info)
301{
302 POINTER_CHECK(entry);
303 POINTER_CHECK(info);
304 size_t length =
305 pldm_bios_table_attr_entry_string_encode_length(info->def_length);
306 BUFFER_SIZE_EXPECT(entry_length, length);
307 if (info->def_length > info->max_length ||
308 info->def_length < info->min_length ||
309 info->min_length > info->max_length)
310 return PLDM_ERROR_INVALID_DATA;
311 if (info->string_type > 5 && info->string_type != 0xFF)
312 return PLDM_ERROR_INVALID_DATA;
313 pldm_bios_table_attr_entry_string_encode(entry, entry_length, info);
314 return PLDM_SUCCESS;
315}
John Wang02700402019-10-06 16:34:29 +0800316
317uint16_t pldm_bios_table_attr_entry_string_decode_def_string_length(
318 const struct pldm_bios_attr_table_entry *entry)
319{
John Wangccc04552019-10-14 14:28:25 +0800320 struct attr_table_string_entry_fields *fields =
321 (struct attr_table_string_entry_fields *)entry->metadata;
322 return le16toh(fields->def_length);
John Wang02700402019-10-06 16:34:29 +0800323}
324
325int pldm_bios_table_attr_entry_string_decode_def_string_length_check(
326 const struct pldm_bios_attr_table_entry *entry, uint16_t *def_string_length)
327{
328 POINTER_CHECK(entry);
329 POINTER_CHECK(def_string_length);
330 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_STRING);
331 *def_string_length =
332 pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
333 return PLDM_SUCCESS;
334}
335
336/** @brief Get length of a string attribute entry
337 */
338static size_t
339attr_table_entry_length_string(const struct pldm_bios_attr_table_entry *entry)
340{
John Wangccc04552019-10-14 14:28:25 +0800341 uint16_t def_str_len =
John Wang02700402019-10-06 16:34:29 +0800342 pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
John Wangccc04552019-10-14 14:28:25 +0800343 return pldm_bios_table_attr_entry_string_encode_length(def_str_len);
John Wang02700402019-10-06 16:34:29 +0800344}
345
John Wangca230822019-10-16 11:39:27 +0800346struct attr_table_integer_entry_fields {
347 uint64_t lower_bound;
348 uint64_t upper_bound;
349 uint32_t scalar_increment;
350 uint64_t default_value;
351} __attribute__((packed));
352
353size_t pldm_bios_table_attr_entry_integer_encode_length()
354{
355 return sizeof(struct pldm_bios_attr_table_entry) - 1 +
356 sizeof(struct attr_table_integer_entry_fields);
357}
358
359void pldm_bios_table_attr_entry_integer_encode(
360 void *entry, size_t entry_length,
361 const struct pldm_bios_table_attr_entry_integer_info *info)
362{
363 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
364 assert(length <= entry_length);
365 uint8_t attr_type =
366 info->read_only ? PLDM_BIOS_INTEGER_READ_ONLY : PLDM_BIOS_INTEGER;
367 attr_table_entry_encode_header(entry, entry_length, attr_type,
368 info->name_handle);
369 struct pldm_bios_attr_table_entry *attr_entry = entry;
370 struct attr_table_integer_entry_fields *attr_fields =
371 (struct attr_table_integer_entry_fields *)attr_entry->metadata;
372 attr_fields->lower_bound = htole64(info->lower_bound);
373 attr_fields->upper_bound = htole64(info->upper_bound);
374 attr_fields->scalar_increment = htole32(info->scalar_increment);
375 attr_fields->default_value = htole64(info->default_value);
376}
377
378int pldm_bios_table_attr_entry_integer_encode_check(
379 void *entry, size_t entry_length,
380 const struct pldm_bios_table_attr_entry_integer_info *info)
381{
382 POINTER_CHECK(entry);
383 POINTER_CHECK(info);
384 size_t length = pldm_bios_table_attr_entry_integer_encode_length();
385 BUFFER_SIZE_EXPECT(entry_length, length);
386 if (info->lower_bound > info->upper_bound ||
387 info->default_value > info->upper_bound ||
388 info->default_value < info->lower_bound ||
389 (info->default_value - info->lower_bound) %
390 info->scalar_increment !=
391 0)
392 return PLDM_ERROR_INVALID_DATA;
393 pldm_bios_table_attr_entry_integer_encode(entry, entry_length, info);
394 return PLDM_SUCCESS;
395}
396
397static size_t
398attr_table_entry_length_integer(const struct pldm_bios_attr_table_entry *entry)
399{
400 (void)entry;
401 return pldm_bios_table_attr_entry_integer_encode_length();
402}
403
John Wang02700402019-10-06 16:34:29 +0800404struct attr_table_entry {
405 uint8_t attr_type;
406 size_t (*entry_length_handler)(
407 const struct pldm_bios_attr_table_entry *);
408};
409
410static struct attr_table_entry attr_table_entrys[] = {
411 {.attr_type = PLDM_BIOS_ENUMERATION,
412 .entry_length_handler = attr_table_entry_length_enum},
413 {.attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
414 .entry_length_handler = attr_table_entry_length_enum},
415 {.attr_type = PLDM_BIOS_STRING,
416 .entry_length_handler = attr_table_entry_length_string},
417 {.attr_type = PLDM_BIOS_STRING_READ_ONLY,
418 .entry_length_handler = attr_table_entry_length_string},
John Wangca230822019-10-16 11:39:27 +0800419 {.attr_type = PLDM_BIOS_INTEGER,
420 .entry_length_handler = attr_table_entry_length_integer},
421 {.attr_type = PLDM_BIOS_INTEGER_READ_ONLY,
422 .entry_length_handler = attr_table_entry_length_integer},
John Wang02700402019-10-06 16:34:29 +0800423};
424
425#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
426
427static struct attr_table_entry *find_attr_table_entry_by_type(uint8_t attr_type)
428{
429 size_t i;
430 for (i = 0; i < ARRAY_SIZE(attr_table_entrys); i++) {
431 if (attr_type == attr_table_entrys[i].attr_type)
432 return &attr_table_entrys[i];
433 }
434 return NULL;
435}
436
437static size_t attr_table_entry_length(const void *table_entry)
438{
439 const struct pldm_bios_attr_table_entry *entry = table_entry;
440 struct attr_table_entry *attr_table_entry =
441 find_attr_table_entry_by_type(entry->attr_type);
442 assert(attr_table_entry != NULL);
443 assert(attr_table_entry->entry_length_handler != NULL);
444
445 return attr_table_entry->entry_length_handler(entry);
446}
447
John Wang3ad21752019-10-06 16:42:21 +0800448size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count)
449{
450 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
451 sizeof(count) + count;
452}
453
454void pldm_bios_table_attr_value_entry_encode_enum(
455 void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
456 uint8_t count, uint8_t *handles)
457{
458 size_t length =
459 pldm_bios_table_attr_value_entry_encode_enum_length(count);
460 assert(length <= entry_length);
461
462 struct pldm_bios_attr_val_table_entry *table_entry = entry;
463 table_entry->attr_handle = htole16(attr_handle);
464 table_entry->attr_type = attr_type;
465 table_entry->value[0] = count;
466 if (count != 0)
467 memcpy(&table_entry->value[1], handles, count);
468}
469
470int pldm_bios_table_attr_value_entry_encode_enum_check(
471 void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
472 uint8_t count, uint8_t *handles)
473{
474 POINTER_CHECK(entry);
475 if (count != 0 && handles == NULL)
476 return PLDM_ERROR_INVALID_DATA;
477 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_ENUMERATION);
478 size_t length =
479 pldm_bios_table_attr_value_entry_encode_enum_length(count);
480 BUFFER_SIZE_EXPECT(entry_length, length);
481 pldm_bios_table_attr_value_entry_encode_enum(
482 entry, entry_length, attr_handle, attr_type, count, handles);
483 return PLDM_SUCCESS;
484}
485
486size_t
487pldm_bios_table_attr_value_entry_encode_string_length(uint16_t string_length)
488{
489 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
490 sizeof(string_length) + string_length;
491}
492
493void pldm_bios_table_attr_value_entry_encode_string(
494 void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
495 uint16_t str_length, const char *str)
496{
497 size_t length =
498 pldm_bios_table_attr_value_entry_encode_string_length(str_length);
499 assert(length <= entry_length);
500
501 struct pldm_bios_attr_val_table_entry *table_entry = entry;
502 table_entry->attr_handle = htole16(attr_handle);
503 table_entry->attr_type = attr_type;
504 if (str_length != 0)
505 memcpy(table_entry->value + sizeof(str_length), str,
506 str_length);
507 str_length = htole16(str_length);
508 memcpy(table_entry->value, &str_length, sizeof(str_length));
509}
510
511int pldm_bios_table_attr_value_entry_encode_string_check(
512 void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
513 uint16_t str_length, const char *str)
514{
515 POINTER_CHECK(entry);
516 if (str_length != 0 && str == NULL)
517 return PLDM_ERROR_INVALID_DATA;
518 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_STRING);
519 size_t length =
520 pldm_bios_table_attr_value_entry_encode_string_length(str_length);
521 BUFFER_SIZE_EXPECT(entry_length, length);
522 pldm_bios_table_attr_value_entry_encode_string(
523 entry, entry_length, attr_handle, attr_type, str_length, str);
524 return PLDM_SUCCESS;
525}
526
John Wangca230822019-10-16 11:39:27 +0800527size_t pldm_bios_table_attr_value_entry_encode_integer_length()
528{
529 return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
530 sizeof(uint64_t);
531}
532void pldm_bios_table_attr_value_entry_encode_integer(void *entry,
533 size_t entry_length,
534 uint16_t attr_handle,
535 uint8_t attr_type,
536 uint64_t cv)
537{
538 size_t length =
539 pldm_bios_table_attr_value_entry_encode_integer_length();
540 assert(length <= entry_length);
541
542 struct pldm_bios_attr_val_table_entry *table_entry = entry;
543 table_entry->attr_handle = htole16(attr_handle);
544 table_entry->attr_type = attr_type;
545 cv = htole64(cv);
546 memcpy(table_entry->value, &cv, sizeof(uint64_t));
547}
548
549int pldm_bios_table_attr_value_entry_encode_integer_check(void *entry,
550 size_t entry_length,
551 uint16_t attr_handle,
552 uint8_t attr_type,
553 uint64_t cv)
554{
555 POINTER_CHECK(entry);
556 size_t length =
557 pldm_bios_table_attr_value_entry_encode_integer_length();
558 ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_INTEGER);
559 BUFFER_SIZE_EXPECT(entry_length, length);
560 pldm_bios_table_attr_value_entry_encode_integer(
561 entry, entry_length, attr_handle, attr_type, cv);
562 return PLDM_SUCCESS;
563}
564
John Wang02700402019-10-06 16:34:29 +0800565struct pldm_bios_table_iter {
566 const uint8_t *table_data;
567 size_t table_len;
568 size_t current_pos;
569 size_t (*entry_length_handler)(const void *table_entry);
570};
571
572struct pldm_bios_table_iter *
573pldm_bios_table_iter_create(const void *table, size_t length,
574 enum pldm_bios_table_types type)
575{
576 struct pldm_bios_table_iter *iter = malloc(sizeof(*iter));
577 assert(iter != NULL);
578 iter->table_data = table;
579 iter->table_len = length;
580 iter->current_pos = 0;
581 iter->entry_length_handler = NULL;
582 switch (type) {
583 case PLDM_BIOS_STRING_TABLE:
John Wangdd9a6282019-10-11 18:52:46 +0800584 iter->entry_length_handler = string_table_entry_length;
John Wang02700402019-10-06 16:34:29 +0800585 break;
586 case PLDM_BIOS_ATTR_TABLE:
587 iter->entry_length_handler = attr_table_entry_length;
588 break;
589 case PLDM_BIOS_ATTR_VAL_TABLE:
590 break;
591 }
592
593 return iter;
594}
595
596void pldm_bios_table_iter_free(struct pldm_bios_table_iter *iter)
597{
598 free(iter);
599}
600
601#define pad_and_check_max 7
602bool pldm_bios_table_iter_is_end(const struct pldm_bios_table_iter *iter)
603{
604 if (iter->table_len - iter->current_pos <= pad_and_check_max)
605 return true;
606 return false;
607}
608
609void pldm_bios_table_iter_next(struct pldm_bios_table_iter *iter)
610{
611 if (pldm_bios_table_iter_is_end(iter))
612 return;
613 const void *entry = iter->table_data + iter->current_pos;
614 iter->current_pos += iter->entry_length_handler(entry);
615}
616
617const void *pldm_bios_table_iter_value(struct pldm_bios_table_iter *iter)
618{
619 return iter->table_data + iter->current_pos;
John Wang3ad21752019-10-06 16:42:21 +0800620}
John Wangdd9a6282019-10-11 18:52:46 +0800621
622static const void *
623pldm_bios_table_entry_find(struct pldm_bios_table_iter *iter, const void *key,
624 int (*equal)(const void *entry, const void *key))
625{
626 const void *entry;
627 while (!pldm_bios_table_iter_is_end(iter)) {
628 entry = pldm_bios_table_iter_value(iter);
629 if (equal(entry, key))
630 return entry;
631 pldm_bios_table_iter_next(iter);
632 }
633 return NULL;
634}
635
636static int string_table_handle_equal(const void *entry, const void *key)
637{
638 const struct pldm_bios_string_table_entry *string_entry = entry;
639 uint16_t handle = *(uint16_t *)key;
640 if (pldm_bios_table_string_entry_decode_handle(string_entry) == handle)
641 return true;
642 return false;
643}
644
645struct string_equal_arg {
646 uint16_t str_length;
647 const char *str;
648};
649
650static int string_table_string_equal(const void *entry, const void *key)
651{
652 const struct pldm_bios_string_table_entry *string_entry = entry;
653 const struct string_equal_arg *arg = key;
654 if (arg->str_length !=
655 pldm_bios_table_string_entry_decode_string_length(string_entry))
656 return false;
657 if (memcmp(string_entry->name, arg->str, arg->str_length) != 0)
658 return false;
659 return true;
660}
661
662const struct pldm_bios_string_table_entry *
663pldm_bios_table_string_find_by_string(const void *table, size_t length,
664 const char *str)
665{
666 uint16_t str_length = strlen(str);
667 struct string_equal_arg arg = {str_length, str};
668 struct pldm_bios_table_iter *iter =
669 pldm_bios_table_iter_create(table, length, PLDM_BIOS_STRING_TABLE);
670 const void *entry =
671 pldm_bios_table_entry_find(iter, &arg, string_table_string_equal);
672 pldm_bios_table_iter_free(iter);
673 return entry;
674}
675
676const struct pldm_bios_string_table_entry *
677pldm_bios_table_string_find_by_handle(const void *table, size_t length,
678 uint16_t handle)
679{
680 struct pldm_bios_table_iter *iter =
681 pldm_bios_table_iter_create(table, length, PLDM_BIOS_STRING_TABLE);
682 const void *entry = pldm_bios_table_entry_find(
683 iter, &handle, string_table_handle_equal);
684 pldm_bios_table_iter_free(iter);
685 return entry;
686}