acpi: Add IORT helper functions
[coreboot2.git] / util / cbfstool / bpdt_formats / bpdt_1_7.c
blob7e42a7b1273076bb8e2c3960ff14f10697cb8d44
1 /* BPDT version 1.7 support */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <sys/types.h>
6 #include "cse_serger.h"
8 enum bpdt_flags {
9 BPDT_FLAGS_REDUNDANCY_SUPPORTED = 1 << 0,
12 struct bpdt_header {
13 uint32_t signature; /* BPDT_SIGNATURE */
14 uint16_t descriptor_count;
15 uint8_t version; /* Layout 1.7 = 2 */
16 uint8_t flags; /* See enum bpdt_flags */
17 uint32_t checksum;
18 uint32_t ifwi_version;
19 struct {
20 uint16_t major;
21 uint16_t minor;
22 uint16_t build;
23 uint16_t hotfix;
24 } fit_tool_version;
25 } __packed;
27 struct cse_layout {
28 uint8_t rom_bypass[16];
29 uint16_t size;
30 uint16_t redundancy;
31 uint32_t checksum;
32 uint32_t data_offset;
33 uint32_t data_size;
34 uint32_t bp1_offset;
35 uint32_t bp1_size;
36 uint32_t bp2_offset;
37 uint32_t bp2_size;
38 uint32_t bp3_offset;
39 uint32_t bp3_size;
40 uint32_t bp4_offset;
41 uint32_t bp4_size;
42 uint32_t bp5_offset;
43 uint32_t bp5_size;
44 uint32_t temp_base_addr;
45 uint32_t temp_base_size;
46 uint32_t flog_offset;
47 uint32_t flog_size;
48 } __packed;
50 static bool match_version(const struct buffer *buff)
52 const uint8_t *data = buffer_get(buff);
53 const uint32_t sig = read_le32(data);
54 const uint8_t version = read_at_le8(data, offsetof(struct bpdt_header, version));
56 if (sig != BPDT_SIGNATURE) {
57 ERROR("Invalid BPDT signature(0x%x)!\n", sig);
58 return false;
61 return version == BPDT_VERSION_1_7;
64 static bpdt_hdr_ptr create_bpdt_hdr(void)
66 struct bpdt_header *h = calloc(1, sizeof(*h));
68 if (!h)
69 return NULL;
71 h->signature = BPDT_SIGNATURE;
72 h->descriptor_count = 0;
73 h->version = BPDT_VERSION_1_7;
74 h->flags = 0;
75 h->checksum = 0;
76 h->ifwi_version = 0;
77 h->fit_tool_version.major = 0;
78 h->fit_tool_version.minor = 0;
79 h->fit_tool_version.build = 0;
80 h->fit_tool_version.hotfix = 0;
82 return h;
85 static void print_bpdt_hdr(const bpdt_hdr_ptr ptr)
87 struct bpdt_header *h = ptr;
89 printf(" * BPDT header\n");
90 printf("%-25s 0x%-23.8x\n", "Signature", h->signature);
91 printf("%-25s %-25d\n", "Descriptor count", h->descriptor_count);
92 printf("%-25s %d (Layout 1.7)\n", "BPDT Version", h->version);
93 printf("%-25s 0x%-23x\n", "Flags", h->flags);
94 printf("%-25s 0x%-23x\n", "Checksum", h->checksum);
95 printf("%-25s 0x%-23x\n", "IFWI Version", h->ifwi_version);
96 printf("%-25s %d.%d.%d.%d(%.2x.%.2x.%.2x.%.2x)\n", "FIT Tool Version",
97 h->fit_tool_version.major, h->fit_tool_version.minor,
98 h->fit_tool_version.build, h->fit_tool_version.hotfix,
99 h->fit_tool_version.major, h->fit_tool_version.minor,
100 h->fit_tool_version.build, h->fit_tool_version.hotfix);
103 static bpdt_hdr_ptr read_bpdt_hdr(struct buffer *buff)
105 struct bpdt_header *h = calloc(1, sizeof(*h));
107 if (!h)
108 return NULL;
110 READ_MEMBER(buff, h->signature);
111 READ_MEMBER(buff, h->descriptor_count);
112 READ_MEMBER(buff, h->version);
113 READ_MEMBER(buff, h->flags);
114 READ_MEMBER(buff, h->checksum);
115 READ_MEMBER(buff, h->ifwi_version);
116 READ_MEMBER(buff, h->fit_tool_version);
118 return h;
121 static int write_bpdt_hdr(struct buffer *buff, const bpdt_hdr_ptr ptr)
123 struct bpdt_header *h = ptr;
125 if (buffer_size(buff) < sizeof(struct bpdt_header)) {
126 ERROR("Not enough size in buffer for BPDT header!\n");
127 return -1;
130 WRITE_MEMBER(buff, h->signature);
131 WRITE_MEMBER(buff, h->descriptor_count);
132 WRITE_MEMBER(buff, h->version);
133 WRITE_MEMBER(buff, h->flags);
134 WRITE_MEMBER(buff, h->checksum);
135 WRITE_MEMBER(buff, h->ifwi_version);
136 WRITE_MEMBER(buff, h->fit_tool_version);
138 return 0;
141 static size_t get_bpdt_entry_count(const bpdt_hdr_ptr ptr)
143 return ((const struct bpdt_header *)ptr)->descriptor_count;
146 static void inc_bpdt_entry_count(bpdt_hdr_ptr ptr)
148 struct bpdt_header *h = ptr;
149 h->descriptor_count++;
152 static uint32_t crc32(uint32_t seed, const uint8_t *data, size_t len)
154 uint32_t crc = seed;
156 for (size_t i = 0; i < len; i++) {
157 crc ^= *data++;
159 for (size_t b = 0; b < 8; b++) {
160 if (crc & 1)
161 crc = (crc >> 1) ^ 0xedb88320;
162 else
163 crc = crc >> 1;
167 return crc;
171 * Calculate checksum by:
172 * a. stashing l->checksum in curr_checksum and setting l->checksum to 0
173 * b. calculating checksum
174 * c. restoring l->checksum and return calculated checksum value.
176 static uint32_t calculate_layout_checksum(struct cse_layout *l)
178 uint32_t curr_checksum = l->checksum;
179 uint32_t calc_checksum;
181 l->checksum = 0;
182 calc_checksum = ~crc32(0xffffffff, (void *)&l->size, l->size);
183 l->checksum = curr_checksum;
185 return calc_checksum;
188 static cse_layout_ptr create_cse_layout(const struct region *r)
190 struct cse_layout *l = calloc(1, sizeof(*l));
192 if (!l)
193 return NULL;
195 memset(l->rom_bypass, 0xff, sizeof(l->rom_bypass));
196 l->size = sizeof(struct cse_layout) - sizeof(l->rom_bypass);
197 l->redundancy = 0;
198 l->checksum = 0;
199 l->data_offset = region_offset(&r[DP]);
200 l->data_size = region_sz(&r[DP]);
201 l->bp1_offset = region_offset(&r[BP1]);
202 l->bp1_size = region_sz(&r[BP1]);
203 l->bp2_offset = region_offset(&r[BP2]);
204 l->bp2_size = region_sz(&r[BP2]);
205 l->bp3_offset = region_offset(&r[BP3]);
206 l->bp3_size = region_sz(&r[BP3]);
207 l->bp4_offset = region_offset(&r[BP4]);
208 l->bp4_size = region_sz(&r[BP4]);
209 l->bp5_offset = 0;
210 l->bp5_size = 0;
211 l->temp_base_addr = 0;
212 l->temp_base_size = 0;
213 l->flog_offset = 0;
214 l->flog_size = 0;
216 l->checksum = calculate_layout_checksum(l);
218 return l;
221 static void print_cse_layout(const cse_layout_ptr ptr)
223 struct cse_layout *l = ptr;
225 printf(" * CSE Layout\n\n");
226 printf("ROM Bypass: ");
227 for (size_t i = 0; i < sizeof(l->rom_bypass); i++)
228 printf("0x%x ", l->rom_bypass[i]);
229 printf("\n");
230 printf("Size: 0x%x\n", l->size);
231 printf("Redundancy: 0x%x\n", l->redundancy);
232 printf("Checksum: 0x%x\n", l->checksum);
233 printf("Data partition offset: 0x%x\n", l->data_offset);
234 printf("Data partition size: 0x%x\n", l->data_size);
235 printf("BP1 offset: 0x%x\n", l->bp1_offset);
236 printf("BP1 size: 0x%x\n", l->bp1_size);
237 printf("BP2 offset: 0x%x\n", l->bp2_offset);
238 printf("BP2 size: 0x%x\n", l->bp2_size);
239 printf("BP3 offset: 0x%x\n", l->bp3_offset);
240 printf("BP3 size: 0x%x\n", l->bp3_size);
241 printf("BP4 offset: 0x%x\n", l->bp4_offset);
242 printf("BP4 size: 0x%x\n", l->bp4_size);
243 printf("BP5 offset: 0x%x\n", l->bp5_offset);
244 printf("BP5 size: 0x%x\n", l->bp5_size);
245 printf("Temp base addr: 0x%x\n", l->temp_base_addr);
246 printf("Temp base size: 0x%x\n", l->temp_base_size);
247 printf("FLOG offset: 0x%x\n", l->flog_offset);
248 printf("FLOG size: 0x%x\n", l->flog_size);
251 static cse_layout_ptr read_cse_layout(struct buffer *buff)
253 struct cse_layout *l = calloc(1, sizeof(*l));
255 if (!l)
256 return NULL;
258 READ_MEMBER(buff, l->rom_bypass);
259 READ_MEMBER(buff, l->size);
260 READ_MEMBER(buff, l->redundancy);
261 READ_MEMBER(buff, l->checksum);
262 READ_MEMBER(buff, l->data_offset);
263 READ_MEMBER(buff, l->data_size);
264 READ_MEMBER(buff, l->bp1_offset);
265 READ_MEMBER(buff, l->bp1_size);
266 READ_MEMBER(buff, l->bp2_offset);
267 READ_MEMBER(buff, l->bp2_size);
268 READ_MEMBER(buff, l->bp3_offset);
269 READ_MEMBER(buff, l->bp3_size);
270 READ_MEMBER(buff, l->bp4_offset);
271 READ_MEMBER(buff, l->bp4_size);
272 READ_MEMBER(buff, l->bp5_offset);
273 READ_MEMBER(buff, l->bp5_size);
274 READ_MEMBER(buff, l->temp_base_addr);
275 READ_MEMBER(buff, l->temp_base_size);
276 READ_MEMBER(buff, l->flog_offset);
277 READ_MEMBER(buff, l->flog_size);
279 return l;
282 static int write_cse_layout(struct buffer *buff, const cse_layout_ptr ptr)
284 struct cse_layout *l = ptr;
286 if (buffer_size(buff) < sizeof(struct cse_layout)) {
287 ERROR("Not enough size in buffer for CSE layout!\n");
288 return -1;
291 WRITE_MEMBER(buff, l->rom_bypass);
292 WRITE_MEMBER(buff, l->size);
293 WRITE_MEMBER(buff, l->redundancy);
294 WRITE_MEMBER(buff, l->checksum);
295 WRITE_MEMBER(buff, l->data_offset);
296 WRITE_MEMBER(buff, l->data_size);
297 WRITE_MEMBER(buff, l->bp1_offset);
298 WRITE_MEMBER(buff, l->bp1_size);
299 WRITE_MEMBER(buff, l->bp2_offset);
300 WRITE_MEMBER(buff, l->bp2_size);
301 WRITE_MEMBER(buff, l->bp3_offset);
302 WRITE_MEMBER(buff, l->bp3_size);
303 WRITE_MEMBER(buff, l->bp4_offset);
304 WRITE_MEMBER(buff, l->bp4_size);
305 WRITE_MEMBER(buff, l->bp5_offset);
306 WRITE_MEMBER(buff, l->bp5_size);
307 WRITE_MEMBER(buff, l->temp_base_addr);
308 WRITE_MEMBER(buff, l->temp_base_size);
309 WRITE_MEMBER(buff, l->flog_offset);
310 WRITE_MEMBER(buff, l->flog_size);
312 return 0;
315 static uint32_t calculate_bpdt_checksum(struct bpdt_header *h, struct bpdt_entry *e)
317 uint32_t calc_checksum;
318 uint32_t curr_checksum = h->checksum;
320 h->checksum = 0;
322 calc_checksum = crc32(0xffffffff, (void *)&h->descriptor_count,
323 sizeof(*h) - sizeof(h->signature));
325 if (e && h->descriptor_count)
326 calc_checksum = crc32(calc_checksum, (void *)e,
327 h->descriptor_count * sizeof(struct bpdt_entry));
329 h->checksum = curr_checksum;
331 return ~calc_checksum;
334 static void update_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e)
336 struct bpdt_header *h = ptr;
337 h->checksum = calculate_bpdt_checksum(h, e);
340 static bool validate_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e)
342 struct bpdt_header *h = ptr;
343 return calculate_bpdt_checksum(h, e) == h->checksum;
346 const struct bpdt_ops bpdt_1_7_ops = {
347 .match_version = match_version,
349 .create_hdr = create_bpdt_hdr,
350 .print_hdr = print_bpdt_hdr,
351 .read_hdr = read_bpdt_hdr,
352 .write_hdr = write_bpdt_hdr,
354 .get_entry_count = get_bpdt_entry_count,
355 .inc_entry_count = inc_bpdt_entry_count,
357 .create_layout = create_cse_layout,
358 .print_layout = print_cse_layout,
359 .read_layout = read_cse_layout,
360 .write_layout = write_cse_layout,
362 .update_checksum = update_checksum,
363 .validate_checksum = validate_checksum,
365 .subpart_hdr_version = SUBPART_HDR_VERSION_2,
366 .subpart_entry_version = SUBPART_ENTRY_VERSION_1,