blob: 26d30bf431cebfdad128ab7782e4c00fced0be2c [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
23uint8_t pldm_bios_table_attr_entry_enum_decode_pv_num(
24 const struct pldm_bios_attr_table_entry *entry)
25{
26 return entry->metadata[0];
27}
28
29int pldm_bios_table_attr_entry_enum_decode_pv_num_check(
30 const struct pldm_bios_attr_table_entry *entry, uint8_t *pv_num)
31{
32 POINTER_CHECK(entry);
33 POINTER_CHECK(pv_num);
34 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
35 *pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
36 return PLDM_SUCCESS;
37}
38
39uint8_t pldm_bios_table_attr_entry_enum_decode_def_num(
40 const struct pldm_bios_attr_table_entry *entry)
41{
42 uint8_t pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
43 return entry->metadata[sizeof(uint8_t) /* pv_num */ +
44 sizeof(uint16_t) * pv_num];
45}
46
47int pldm_bios_table_attr_entry_enum_decode_def_num_check(
48 const struct pldm_bios_attr_table_entry *entry, uint8_t *def_num)
49{
50 POINTER_CHECK(entry);
51 POINTER_CHECK(def_num);
52 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
53 *def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
54 return PLDM_SUCCESS;
55}
56
57/** @brief Get length of an enum attribute entry
58 */
59static size_t
60attr_table_entry_length_enum(const struct pldm_bios_attr_table_entry *entry)
61{
62 uint8_t pv_num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
63 uint8_t def_num = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
64 return sizeof(*entry) - 1 + sizeof(pv_num) + pv_num * sizeof(uint16_t) +
65 sizeof(def_num) + def_num;
66}
67
68#define ATTR_ENTRY_STRING_LENGTH_MIN \
69 sizeof(uint8_t) /* string type */ + \
70 sizeof(uint16_t) /* minimum string length */ + \
71 sizeof(uint16_t) /* maximum string length */ + \
72 sizeof(uint16_t) /* default string length */
73
74uint16_t pldm_bios_table_attr_entry_string_decode_def_string_length(
75 const struct pldm_bios_attr_table_entry *entry)
76{
77 int def_string_pos = ATTR_ENTRY_STRING_LENGTH_MIN - sizeof(uint16_t);
78 uint16_t def_string_length =
79 *(uint16_t *)(entry->metadata + def_string_pos);
80 return le16toh(def_string_length);
81}
82
83int pldm_bios_table_attr_entry_string_decode_def_string_length_check(
84 const struct pldm_bios_attr_table_entry *entry, uint16_t *def_string_length)
85{
86 POINTER_CHECK(entry);
87 POINTER_CHECK(def_string_length);
88 ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_STRING);
89 *def_string_length =
90 pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
91 return PLDM_SUCCESS;
92}
93
94/** @brief Get length of a string attribute entry
95 */
96static size_t
97attr_table_entry_length_string(const struct pldm_bios_attr_table_entry *entry)
98{
99 uint16_t def_string_len =
100 pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
101 return sizeof(*entry) - 1 + ATTR_ENTRY_STRING_LENGTH_MIN +
102 def_string_len;
103}
104
105struct attr_table_entry {
106 uint8_t attr_type;
107 size_t (*entry_length_handler)(
108 const struct pldm_bios_attr_table_entry *);
109};
110
111static struct attr_table_entry attr_table_entrys[] = {
112 {.attr_type = PLDM_BIOS_ENUMERATION,
113 .entry_length_handler = attr_table_entry_length_enum},
114 {.attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY,
115 .entry_length_handler = attr_table_entry_length_enum},
116 {.attr_type = PLDM_BIOS_STRING,
117 .entry_length_handler = attr_table_entry_length_string},
118 {.attr_type = PLDM_BIOS_STRING_READ_ONLY,
119 .entry_length_handler = attr_table_entry_length_string},
120};
121
122#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
123
124static struct attr_table_entry *find_attr_table_entry_by_type(uint8_t attr_type)
125{
126 size_t i;
127 for (i = 0; i < ARRAY_SIZE(attr_table_entrys); i++) {
128 if (attr_type == attr_table_entrys[i].attr_type)
129 return &attr_table_entrys[i];
130 }
131 return NULL;
132}
133
134static size_t attr_table_entry_length(const void *table_entry)
135{
136 const struct pldm_bios_attr_table_entry *entry = table_entry;
137 struct attr_table_entry *attr_table_entry =
138 find_attr_table_entry_by_type(entry->attr_type);
139 assert(attr_table_entry != NULL);
140 assert(attr_table_entry->entry_length_handler != NULL);
141
142 return attr_table_entry->entry_length_handler(entry);
143}
144
145struct pldm_bios_table_iter {
146 const uint8_t *table_data;
147 size_t table_len;
148 size_t current_pos;
149 size_t (*entry_length_handler)(const void *table_entry);
150};
151
152struct pldm_bios_table_iter *
153pldm_bios_table_iter_create(const void *table, size_t length,
154 enum pldm_bios_table_types type)
155{
156 struct pldm_bios_table_iter *iter = malloc(sizeof(*iter));
157 assert(iter != NULL);
158 iter->table_data = table;
159 iter->table_len = length;
160 iter->current_pos = 0;
161 iter->entry_length_handler = NULL;
162 switch (type) {
163 case PLDM_BIOS_STRING_TABLE:
164 break;
165 case PLDM_BIOS_ATTR_TABLE:
166 iter->entry_length_handler = attr_table_entry_length;
167 break;
168 case PLDM_BIOS_ATTR_VAL_TABLE:
169 break;
170 }
171
172 return iter;
173}
174
175void pldm_bios_table_iter_free(struct pldm_bios_table_iter *iter)
176{
177 free(iter);
178}
179
180#define pad_and_check_max 7
181bool pldm_bios_table_iter_is_end(const struct pldm_bios_table_iter *iter)
182{
183 if (iter->table_len - iter->current_pos <= pad_and_check_max)
184 return true;
185 return false;
186}
187
188void pldm_bios_table_iter_next(struct pldm_bios_table_iter *iter)
189{
190 if (pldm_bios_table_iter_is_end(iter))
191 return;
192 const void *entry = iter->table_data + iter->current_pos;
193 iter->current_pos += iter->entry_length_handler(entry);
194}
195
196const void *pldm_bios_table_iter_value(struct pldm_bios_table_iter *iter)
197{
198 return iter->table_data + iter->current_pos;
199}