xref: /aosp_15_r20/external/coreboot/util/cbfstool/fit.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* Firmware Interface Table support */
2 /* SPDX-License-Identifier: GPL-2.0-only */
3 
4 #include <inttypes.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include "fit.h"
11 
12 /* FIXME: This code assumes it is being executed on a little endian machine. */
13 
14 #define FIT_POINTER_LOCATION 0xffffffc0
15 #define FIT_TABLE_LOWEST_ADDRESS ((uint32_t)(-(16 << 20)))
16 #define FIT_ENTRY_CHECKSUM_VALID 0x80
17 #define FIT_HEADER_VERSION 0x0100
18 #define FIT_HEADER_ADDRESS "_FIT_   "
19 #define FIT_MICROCODE_VERSION 0x0100
20 #define FIT_TXT_VERSION 0x0100
21 
22 #define FIT_SIZE_ALIGNMENT 16
23 
24 struct fit_entry {
25 	/**
26 	 * Address is the base address of the firmware component
27 	 * must be aligned on 16 byte boundary
28 	 */
29 	uint64_t address;
30 	/**
31 	 * Size is the span of the component in multiple of 16 bytes
32 	 * Bits [24:31] are reserved and  must be set to 0
33 	 */
34 	uint32_t size_reserved;
35 	/**
36 	 * Component's version number in binary coded decimal (BCD) format.
37 	 * For the FIT header entry, the value in this field will indicate the
38 	 * revision number of the FIT data structure. The upper byte of the
39 	 * revision field indicates the major revision and the lower byte
40 	 * indicates the minor revision.
41 	 */
42 	uint16_t version;
43 	/**
44 	 * FIT types 0x00 to 0x7F
45 	 * Bit 7 (C_V) indicates whether component has valid checksum.
46 	 */
47 	uint8_t  type_checksum_valid;
48 	/**
49 	 * Component's checksum. The modulo sum of all the bytes in the
50 	 * component and the value in this field (Chksum) must add up to zero.
51 	 * This field is only valid if the C_V flag is non-zero.
52 	 */
53 	uint8_t  checksum;
54 } __packed;
55 
56 struct fit_table {
57 	struct fit_entry header;
58 	struct fit_entry entries[];
59 } __packed;
60 
61 struct microcode_header {
62 	uint32_t version;
63 	uint32_t revision;
64 	uint32_t date;
65 	uint32_t processor_signature;
66 	uint32_t checksum;
67 	uint32_t loader_revision;
68 	uint32_t processor_flags;
69 	uint32_t data_size;
70 	uint32_t total_size;
71 	uint8_t  reserved[12];
72 } __packed;
73 
74 struct microcode_entry {
75 	int offset;
76 	int size;
77 };
78 
rom_buffer_pointer(struct buffer * buffer,int offset)79 static inline void *rom_buffer_pointer(struct buffer *buffer, int offset)
80 {
81 	return &buffer->data[offset];
82 }
83 
fit_entry_size_bytes(const struct fit_entry * entry)84 static inline size_t fit_entry_size_bytes(const struct fit_entry *entry)
85 {
86 	return (entry->size_reserved & 0xffffff) << 4;
87 }
88 
fit_entry_update_size(struct fit_entry * entry,const int size_bytes)89 static inline void fit_entry_update_size(struct fit_entry *entry,
90 					 const int size_bytes)
91 {
92 	/* Size is multiples of 16 bytes. */
93 	entry->size_reserved = (size_bytes >> 4) & 0xffffff;
94 }
95 
fit_entry_add_size(struct fit_entry * entry,const int size_bytes)96 static inline void fit_entry_add_size(struct fit_entry *entry,
97 				      const int size_bytes)
98 {
99 	int size = fit_entry_size_bytes(entry);
100 	size += size_bytes;
101 	fit_entry_update_size(entry, size);
102 }
103 
fit_entry_type(struct fit_entry * entry)104 static inline int fit_entry_type(struct fit_entry *entry)
105 {
106 	return entry->type_checksum_valid & ~FIT_ENTRY_CHECKSUM_VALID;
107 }
108 
109 /*
110  * Get an offset from a host pointer. This function assumes the ROM is located
111  * in the host address space at [4G - romsize -> 4G). It also assume all
112  * pointers have values within this address range.
113  */
ptr_to_offset(fit_offset_converter_t helper,const struct buffer * region,uint32_t host_ptr)114 static inline int ptr_to_offset(fit_offset_converter_t helper,
115 				const struct buffer *region, uint32_t host_ptr)
116 {
117 	return helper(region, -host_ptr);
118 }
119 
120 /*
121  * Get a pointer from an offset. This function assumes the ROM is located
122  * in the host address space at [4G - romsize -> 4G). It also assume all
123  * pointers have values within this address range.
124  */
offset_to_ptr(fit_offset_converter_t helper,const struct buffer * region,int offset)125 static inline uint32_t offset_to_ptr(fit_offset_converter_t helper,
126 				     const struct buffer *region, int offset)
127 {
128 	return -helper(region, offset);
129 }
130 
131 /*
132  * Return the number of FIT entries.
133  */
fit_table_entries(const struct fit_table * fit)134 static inline size_t fit_table_entries(const struct fit_table *fit)
135 {
136 	if (!fit)
137 		return 0;
138 
139 	return (fit_entry_size_bytes(&fit->header) / FIT_SIZE_ALIGNMENT) - 1;
140 }
141 
142 /*
143  * Return the number of unused entries.
144  */
fit_free_space(struct fit_table * fit,const size_t max_entries)145 static inline size_t fit_free_space(struct fit_table *fit,
146 				 const size_t max_entries)
147 {
148 	if (!fit)
149 		return 0;
150 
151 	return max_entries - fit_table_entries(fit);
152 }
153 
154 /*
155  * Sort entries by type and fill gaps (entries with type unused).
156  * To be called after adding or deleting entries.
157  *
158  * This one is critical, as mentioned in Chapter 1.2.1 "FIT Ordering Rules"
159  * "Firmware Interface Table BIOS Specification".
160  *
161  * We need to use a stable sorting algorithm, as the order of
162  * FIT_TYPE_BIOS_STARTUP matter for measurements.
163  */
sort_fit_table(struct fit_table * fit)164 static void sort_fit_table(struct fit_table *fit)
165 {
166 	struct fit_entry tmp;
167 	size_t i, j;
168 	int swapped;
169 
170 	/* Bubble sort entries */
171 	for (j = 0; j < fit_table_entries(fit) - 1; j++) {
172 		swapped = 0;
173 		for (i = 0; i < fit_table_entries(fit) - j - 1; i++) {
174 			if (fit->entries[i].type_checksum_valid <=
175 			    fit->entries[i + 1].type_checksum_valid)
176 				continue;
177 			/* SWAP entries */
178 			memcpy(&tmp, &fit->entries[i], sizeof(tmp));
179 			memcpy(&fit->entries[i], &fit->entries[i + 1],
180 			       sizeof(fit->entries[i]));
181 			memcpy(&fit->entries[i + 1], &tmp,
182 			       sizeof(fit->entries[i + 1]));
183 			swapped = 1;
184 		}
185 		if (!swapped)
186 			break;
187 	}
188 }
189 
fit_table_verified(struct fit_table * table)190 static int fit_table_verified(struct fit_table *table)
191 {
192 	if (!table)
193 		return 0;
194 
195 	/* Check that the address field has the proper signature. */
196 	if (strncmp((const char *)&table->header.address, FIT_HEADER_ADDRESS,
197 			sizeof(table->header.address)))
198 		return 0;
199 
200 	if (table->header.version != FIT_HEADER_VERSION)
201 		return 0;
202 
203 	if (fit_entry_type(&table->header) != FIT_TYPE_HEADER)
204 		return 0;
205 
206 	/* Assume that the FIT table contains at least the header */
207 	if (fit_entry_size_bytes(&table->header) < sizeof(struct fit_entry))
208 		return 0;
209 
210 	return 1;
211 }
212 
213 /*
214  * Update the FIT checksum.
215  * To be called after modifiying the table.
216  */
update_fit_checksum(struct fit_table * fit)217 static void update_fit_checksum(struct fit_table *fit)
218 {
219 	int size_bytes;
220 	uint8_t *buffer;
221 	uint8_t result;
222 	int i;
223 
224 	if (!fit)
225 		return;
226 
227 	fit->header.checksum = 0;
228 	size_bytes = fit_entry_size_bytes(&fit->header);
229 	result = 0;
230 	buffer = (void *)fit;
231 	for (i = 0; i < size_bytes; i++)
232 		result += buffer[i];
233 	fit->header.checksum = -result;
234 }
235 
236 /*
237  * Return a pointer to the next free entry.
238  * Caller must take care if enough space is available.
239  */
get_next_free_entry(struct fit_table * fit)240 static struct fit_entry *get_next_free_entry(struct fit_table *fit)
241 {
242 	return &fit->entries[fit_table_entries(fit)];
243 }
244 
fit_location_from_cbfs_header(uint32_t * current_offset,uint32_t * file_length,void * ptr)245 static void fit_location_from_cbfs_header(uint32_t *current_offset,
246 					  uint32_t *file_length, void *ptr)
247 {
248 	struct buffer buf;
249 	struct cbfs_file header;
250 	memset(&buf, 0, sizeof(buf));
251 
252 	buf.data = ptr;
253 	buf.size = sizeof(header);
254 
255 	bgets(&buf, header.magic, sizeof(header.magic));
256 	header.len = xdr_be.get32(&buf);
257 	header.type = xdr_be.get32(&buf);
258 	header.attributes_offset = xdr_be.get32(&buf);
259 	header.offset = xdr_be.get32(&buf);
260 
261 	*current_offset = header.offset;
262 	*file_length = header.len;
263 }
264 
265 static int
parse_microcode_blob(struct cbfs_image * image,const char * blob_name,size_t * mcus_found,struct microcode_entry * mcus,const size_t max_fit_entries)266 parse_microcode_blob(struct cbfs_image *image,
267 		     const char *blob_name,
268 		     size_t *mcus_found,
269 		     struct microcode_entry *mcus,
270 		     const size_t max_fit_entries)
271 {
272 	size_t num_mcus;
273 	uint32_t current_offset;
274 	uint32_t file_length;
275 	struct cbfs_file *mcode_file;
276 
277 	mcode_file = cbfs_get_entry(image, blob_name);
278 	if (!mcode_file) {
279 		ERROR("Couldn't find microcode blob.\n");
280 		return 1;
281 	}
282 
283 	fit_location_from_cbfs_header(&current_offset, &file_length,
284 				      mcode_file);
285 	current_offset += cbfs_get_entry_addr(image, mcode_file);
286 
287 	num_mcus = 0;
288 	while (file_length > sizeof(struct microcode_header)) {
289 		const struct microcode_header *mcu_header;
290 
291 		mcu_header = rom_buffer_pointer(&image->buffer, current_offset);
292 		if (!mcu_header) {
293 			ERROR("Couldn't parse microcode header.\n");
294 			return 1;
295 		}
296 
297 		/* Newer microcode updates include a size field, whereas older
298 		 * containers set it at 0 and are exactly 2048 bytes long */
299 		uint32_t total_size = mcu_header->total_size ?: 2048;
300 
301 		/* Quickly sanity check a prospective microcode update. */
302 		if (total_size < sizeof(*mcu_header) ||
303 		    total_size > file_length)
304 			break;
305 
306 		if (num_mcus == max_fit_entries) {
307 			ERROR("Maximum of FIT entries reached.\n");
308 			return 1;
309 		}
310 
311 		/* FIXME: Should the checksum be validated? */
312 		mcus[num_mcus].offset = current_offset;
313 		mcus[num_mcus].size = total_size;
314 
315 		/* Proceed to next payload. */
316 		current_offset += mcus[num_mcus].size;
317 		file_length -= mcus[num_mcus].size;
318 		num_mcus++;
319 		if (file_length < sizeof(struct microcode_header))
320 			break;
321 	}
322 
323 	/* Update how many microcode updates we found. */
324 	*mcus_found = num_mcus;
325 
326 	return 0;
327 }
328 
329 /* There can be zero or more FIT_TYPE_MICROCODE entries */
update_fit_ucode_entry(struct fit_table * fit,struct fit_entry * entry,const uint64_t mcu_addr)330 static void update_fit_ucode_entry(struct fit_table *fit,
331 				   struct fit_entry *entry,
332 				   const uint64_t mcu_addr)
333 {
334 	entry->address = mcu_addr;
335 	/*
336 	 * While loading MCU, its size is not referred from FIT and
337 	 * rather from the MCU header, hence we can assign zero here.
338 	 */
339 	entry->size_reserved = 0;
340 	entry->type_checksum_valid = FIT_TYPE_MICROCODE;
341 	entry->version = FIT_MICROCODE_VERSION;
342 	entry->checksum = 0;
343 	fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
344 }
345 
346 /*
347  * There can be zero or one FIT_TYPE_BIOS_ACM entry per table.
348  * In case there's a FIT_TYPE_BIOS_ACM entry, at least one
349  * FIT_TYPE_BIOS_STARTUP entry must exist.
350  *
351  * The caller has to provide valid arguments as those aren't verfied.
352  */
update_fit_bios_acm_entry(struct fit_table * fit,struct fit_entry * entry,const uint64_t acm_addr)353 static void update_fit_bios_acm_entry(struct fit_table *fit,
354 				      struct fit_entry *entry,
355 				      const uint64_t acm_addr)
356 {
357 	entry->address = acm_addr;
358 	/*
359 	 * The Address field points to a BIOS ACM. The Address field points to
360 	 * the first byte of the AC module header. When BIOS ACM is loaded in
361 	 * Authenticated Code RAM, one MTRR base/limit pair is used to map it.
362 	 */
363 	entry->size_reserved = 0;
364 	entry->type_checksum_valid = FIT_TYPE_BIOS_ACM;
365 	entry->version = FIT_TXT_VERSION;
366 	entry->checksum = 0;
367 	fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
368 }
369 
370 /*
371  * In case there's a FIT_TYPE_BIOS_ACM entry, at least one
372  * FIT_TYPE_BIOS_STARTUP entry must exist.
373  *
374  * The caller has to provide valid arguments as those aren't verfied.
375  */
update_fit_bios_startup_entry(struct fit_table * fit,struct fit_entry * entry,const uint64_t sm_addr,const uint32_t sm_size)376 static void update_fit_bios_startup_entry(struct fit_table *fit,
377 					  struct fit_entry *entry,
378 					  const uint64_t sm_addr,
379 					  const uint32_t sm_size)
380 {
381 	entry->address = sm_addr;
382 	assert(sm_size % 16 == 0);
383 	/*
384 	 * BIOS Startup code is defined as the code that gets control at the
385 	 * reset vector and continues the chain of trust in TCG-compliant
386 	 * fashion. In addition, this code may also configure memory and SMRAM.
387 	 */
388 	fit_entry_update_size(entry, sm_size);
389 	entry->type_checksum_valid = FIT_TYPE_BIOS_STARTUP;
390 	entry->version = FIT_TXT_VERSION;
391 	entry->checksum = 0;
392 	fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
393 }
394 
395 /*
396  * There can be zero or one FIT_TYPE_BIOS_POLICY Record in the FIT.
397  * If the platform uses the hash comparison method and employs a
398  * failsafe bootblock, one FIT_TYPE_BIOS_POLICY entry is needed to
399  * contain the failsafe hash.
400  * If the platform uses the Signature verification method, one
401  * FIT_TYPE_BIOS_POLICY entry is needed. In this case, the entry
402  * contains the OEM key, hash of the BIOS and signature over the hash
403  * using the OEM key.
404  * In all other cases, the FIT_TYPE_BIOS_POLICY record is not required.
405  *
406  * The caller has to provide valid arguments as those aren't verfied.
407  */
update_fit_bios_policy_entry(struct fit_table * fit,struct fit_entry * entry,const uint64_t lcp_policy_addr,const uint32_t lcp_policy_size)408 static void update_fit_bios_policy_entry(struct fit_table *fit,
409 					 struct fit_entry *entry,
410 					 const uint64_t lcp_policy_addr,
411 					 const uint32_t lcp_policy_size)
412 {
413 	entry->address = lcp_policy_addr;
414 	fit_entry_update_size(entry, lcp_policy_size);
415 	entry->type_checksum_valid = FIT_TYPE_BIOS_POLICY;
416 	entry->version = FIT_TXT_VERSION;
417 	entry->checksum = 0;
418 	fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
419 }
420 
421 /*
422  * There can be zero or one FIT_TYPE_TXT_POLICY entries
423  *
424  * The caller has to provide valid arguments as those aren't verfied.
425  */
update_fit_txt_policy_entry(struct fit_table * fit,struct fit_entry * entry,uint64_t txt_policy_addr)426 static void update_fit_txt_policy_entry(struct fit_table *fit,
427 					struct fit_entry *entry,
428 					uint64_t txt_policy_addr)
429 {
430 	entry->address = txt_policy_addr;
431 	/*
432 	 * Points to the flag indicating if TXT is enabled on this platform.
433 	 * If not present, TXT is not disabled by FIT.
434 	 */
435 	entry->size_reserved = 0;
436 	entry->type_checksum_valid = FIT_TYPE_TXT_POLICY;
437 	entry->version = 0x1;
438 	entry->checksum = 0;
439 	fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
440 }
441 
442 /*
443  * There can be zero or one FIT_TYPE_BOOT_POLICY entries
444  *
445  * The caller has to provide valid arguments as those aren't verified.
446  */
update_fit_boot_policy_entry(struct fit_table * fit,struct fit_entry * entry,uint64_t boot_policy_addr,uint32_t boot_policy_size)447 static void update_fit_boot_policy_entry(struct fit_table *fit,
448 					struct fit_entry *entry,
449 					uint64_t boot_policy_addr,
450 					uint32_t boot_policy_size)
451 {
452 	entry->address = boot_policy_addr;
453 	entry->type_checksum_valid = FIT_TYPE_BOOT_POLICY;
454 	entry->size_reserved = boot_policy_size;
455 	entry->version = FIT_TXT_VERSION;
456 	entry->checksum = 0;
457 	fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
458 }
459 
460 /*
461  * There can be zero or one FIT_TYPE_KEY_MANIFEST entries
462  *
463  * The caller has to provide valid arguments as those aren't verified.
464  */
update_fit_key_manifest_entry(struct fit_table * fit,struct fit_entry * entry,uint64_t key_manifest_addr,uint32_t key_manifest_size)465 static void update_fit_key_manifest_entry(struct fit_table *fit,
466 					struct fit_entry *entry,
467 					uint64_t key_manifest_addr,
468 					uint32_t key_manifest_size)
469 {
470 	entry->address = key_manifest_addr;
471 
472 	entry->type_checksum_valid = FIT_TYPE_KEY_MANIFEST;
473 	entry->size_reserved = key_manifest_size;
474 	entry->version = FIT_TXT_VERSION;
475 	entry->checksum = 0;
476 	fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
477 }
478 
479 /* Special case for ucode CBFS file, as it might contain more than one ucode */
fit_add_microcode_file(struct fit_table * fit,struct cbfs_image * image,const char * blob_name,fit_offset_converter_t offset_helper,const size_t max_fit_entries)480 int fit_add_microcode_file(struct fit_table *fit,
481 			   struct cbfs_image *image,
482 			   const char *blob_name,
483 			   fit_offset_converter_t offset_helper,
484 			   const size_t max_fit_entries)
485 {
486 	struct microcode_entry *mcus;
487 
488 	size_t i;
489 	size_t mcus_found;
490 
491 	mcus = malloc(sizeof(*mcus) * max_fit_entries);
492 	if (!mcus) {
493 		ERROR("Couldn't allocate memory for microcode entries.\n");
494 		return 1;
495 	}
496 
497 	if (parse_microcode_blob(image, blob_name, &mcus_found, mcus,
498 				 max_fit_entries)) {
499 		free(mcus);
500 		return 1;
501 	}
502 
503 	for (i = 0; i < mcus_found; i++) {
504 		if (fit_add_entry(fit,
505 				  offset_to_ptr(offset_helper, &image->buffer,
506 						mcus[i].offset),
507 				  0,
508 				  FIT_TYPE_MICROCODE,
509 				  max_fit_entries)) {
510 
511 			free(mcus);
512 			return 1;
513 		}
514 	}
515 
516 	free(mcus);
517 	return 0;
518 }
519 
get_fit_ptr(struct buffer * bootblock,fit_offset_converter_t offset_fn,uint32_t topswap_size)520 static uint32_t *get_fit_ptr(struct buffer *bootblock, fit_offset_converter_t offset_fn,
521 		      uint32_t topswap_size)
522 {
523 	return rom_buffer_pointer(bootblock,
524 				  ptr_to_offset(offset_fn, bootblock,
525 						FIT_POINTER_LOCATION - topswap_size));
526 }
527 
528 /* Set the FIT pointer to a FIT table. */
set_fit_pointer(struct buffer * bootblock,const uint32_t fit_address,fit_offset_converter_t offset_fn,uint32_t topswap_size)529 int set_fit_pointer(struct buffer *bootblock,
530 		    const uint32_t fit_address,
531 		    fit_offset_converter_t offset_fn,
532 		    uint32_t topswap_size)
533 {
534 	struct fit_table *fit;
535 	uint32_t *fit_pointer = get_fit_ptr(bootblock, offset_fn, topswap_size);
536 
537 	fit = rom_buffer_pointer(bootblock, ptr_to_offset(offset_fn, bootblock, fit_address));
538 
539 	if (fit_address < FIT_TABLE_LOWEST_ADDRESS) {
540 		ERROR("FIT must be reside in the top 16MiB.\n");
541 		return 1;
542 	}
543 
544 	if (!fit_table_verified(fit)) {
545 		ERROR("FIT not found at address.\n");
546 		return 1;
547 	}
548 
549 	fit_pointer[0] = fit_address;
550 	fit_pointer[1] = 0;
551 	return 0;
552 }
553 
554 /*
555  * Return a pointer to the active FIT.
556  */
fit_get_table(struct buffer * bootblock,fit_offset_converter_t offset_fn,uint32_t topswap_size)557 struct fit_table *fit_get_table(struct buffer *bootblock,
558 				fit_offset_converter_t offset_fn,
559 				uint32_t topswap_size)
560 {
561 	struct fit_table *fit;
562 	uint32_t *fit_pointer = get_fit_ptr(bootblock, offset_fn, topswap_size);
563 
564 	/* Ensure pointer is below 4GiB and within 16MiB of 4GiB */
565 	if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) {
566 		ERROR("FIT not found.\n");
567 		return NULL;
568 	}
569 
570 	fit = rom_buffer_pointer(bootblock,
571 			   ptr_to_offset(offset_fn, bootblock, *fit_pointer));
572 	if (!fit_table_verified(fit)) {
573 		ERROR("FIT not found.\n");
574 		return NULL;
575 	}
576 
577 	return fit;
578 }
579 
580 /*
581  * Dump the current FIT in human readable format to stdout.
582  */
fit_dump(struct fit_table * fit)583 int fit_dump(struct fit_table *fit)
584 {
585 	size_t i;
586 
587 	if (!fit)
588 		return 1;
589 
590 	printf("\n");
591 	printf("    FIT table:\n");
592 
593 	if (fit_table_entries(fit) < 1) {
594 		printf("    empty\n\n");
595 		return 0;
596 	}
597 
598 	printf("    %-6s %-20s %-16s %-8s\n", "Index", "Type", "Addr", "Size");
599 
600 	for (i = 0; i < fit_table_entries(fit); i++) {
601 		const char *name;
602 
603 		switch (fit->entries[i].type_checksum_valid) {
604 		case FIT_TYPE_MICROCODE:
605 			name = "Microcode";
606 			break;
607 		case FIT_TYPE_BIOS_ACM:
608 			name = "BIOS ACM";
609 			break;
610 		case FIT_TYPE_BIOS_STARTUP:
611 			name = "BIOS Startup Module";
612 			break;
613 		case FIT_TYPE_TPM_POLICY:
614 			name = "TPM Policy";
615 			break;
616 		case FIT_TYPE_BIOS_POLICY:
617 			name = "BIOS Policy";
618 			break;
619 		case FIT_TYPE_TXT_POLICY:
620 			name = "TXT Policy";
621 			break;
622 		case FIT_TYPE_KEY_MANIFEST:
623 			name = "Key Manifest";
624 			break;
625 		case FIT_TYPE_BOOT_POLICY:
626 			name = "Boot Policy";
627 			break;
628 		case FIT_TYPE_CSE_SECURE_BOOT:
629 			name = "CSE SecureBoot";
630 			break;
631 		case FIT_TYPE_TXTSX_POLICY:
632 			name = "TXTSX policy";
633 			break;
634 		case FIT_TYPE_JMP_DEBUG_POLICY:
635 			name = "JMP debug policy";
636 			break;
637 		case FIT_TYPE_UNUSED:
638 			name = "unused";
639 			break;
640 		default:
641 			name = "unknown";
642 		}
643 
644 		printf("    %6zd %-20s 0x%08"PRIx64"      0x%08zx\n", i, name,
645 			fit->entries[i].address,
646 			fit_entry_size_bytes(&fit->entries[i]));
647 	}
648 	printf("\n");
649 	return 0;
650 }
651 
652 /*
653  * Remove all entries from table.
654  */
fit_clear_table(struct fit_table * fit)655 int fit_clear_table(struct fit_table *fit)
656 {
657 	if (!fit)
658 		return 1;
659 
660 	memset(fit->entries, 0,
661 	       sizeof(struct fit_entry) * fit_table_entries(fit));
662 
663 	/* Reset entry counter in header */
664 	fit_entry_update_size(&fit->header, sizeof(fit->header));
665 
666 	update_fit_checksum(fit);
667 
668 	return 0;
669 }
670 
671 /*
672  * Returns true if the FIT type is know and can be added to the table.
673  */
fit_is_supported_type(const enum fit_type type)674 int fit_is_supported_type(const enum fit_type type)
675 {
676 	switch (type) {
677 	case FIT_TYPE_MICROCODE:
678 	case FIT_TYPE_BIOS_ACM:
679 	case FIT_TYPE_BIOS_STARTUP:
680 	case FIT_TYPE_BIOS_POLICY:
681 	case FIT_TYPE_TXT_POLICY:
682 	case FIT_TYPE_KEY_MANIFEST:
683 	case FIT_TYPE_BOOT_POLICY:
684 		return 1;
685 	case FIT_TYPE_TPM_POLICY:
686 	default:
687 		return 0;
688 	}
689 }
690 
691 /*
692  * Adds an known entry to the FIT.
693  * len is optional for same types and might be zero.
694  * offset is an absolute address in 32-bit protected mode address space.
695  */
fit_add_entry(struct fit_table * fit,const uint32_t offset,const uint32_t len,const enum fit_type type,const size_t max_fit_entries)696 int fit_add_entry(struct fit_table *fit,
697 		  const uint32_t offset,
698 		  const uint32_t len,
699 		  const enum fit_type type,
700 		  const size_t max_fit_entries)
701 {
702 	struct fit_entry *entry;
703 
704 	if (!fit) {
705 		ERROR("Internal error.");
706 		return 1;
707 	}
708 
709 	if (fit_free_space(fit, max_fit_entries) < 1) {
710 		ERROR("No space left in FIT.");
711 		return 1;
712 	}
713 
714 	if (!fit_is_supported_type(type)) {
715 		ERROR("Unsupported FIT type %u\n", type);
716 		return 1;
717 	}
718 
719 	DEBUG("Adding new entry type %u at offset %zd\n", type,
720 	      fit_table_entries(fit));
721 
722 	entry = get_next_free_entry(fit);
723 
724 	switch (type) {
725 	case FIT_TYPE_MICROCODE:
726 		update_fit_ucode_entry(fit, entry, offset);
727 		break;
728 	case FIT_TYPE_BIOS_ACM:
729 		update_fit_bios_acm_entry(fit, entry, offset);
730 		break;
731 	case FIT_TYPE_BIOS_STARTUP:
732 		update_fit_bios_startup_entry(fit, entry, offset, len);
733 		break;
734 	case FIT_TYPE_BIOS_POLICY:
735 		update_fit_bios_policy_entry(fit, entry, offset, len);
736 		break;
737 	case FIT_TYPE_TXT_POLICY:
738 		update_fit_txt_policy_entry(fit, entry, offset);
739 		break;
740 	case FIT_TYPE_KEY_MANIFEST:
741 		update_fit_key_manifest_entry(fit, entry, offset, len);
742 		break;
743 	case FIT_TYPE_BOOT_POLICY:
744 		update_fit_boot_policy_entry(fit, entry, offset, len);
745 		break;
746 	default:
747 		return 1;
748 	}
749 
750 	sort_fit_table(fit);
751 
752 	update_fit_checksum(fit);
753 
754 	return 0;
755 }
756 
757 /*
758  * Delete one entry from table.
759  */
fit_delete_entry(struct fit_table * fit,const size_t idx)760 int fit_delete_entry(struct fit_table *fit,
761 		     const size_t idx)
762 {
763 	if (!fit) {
764 		ERROR("Internal error.");
765 		return 1;
766 	}
767 
768 	if (idx >= fit_table_entries(fit)) {
769 		ERROR("Index out of range.");
770 		return 1;
771 	}
772 
773 	memset(&fit->entries[idx], 0, sizeof(struct fit_entry));
774 
775 	fit->entries[idx].type_checksum_valid = FIT_TYPE_UNUSED;
776 
777 	sort_fit_table(fit);
778 
779 	/* The unused entry is now the last one */
780 	fit_entry_add_size(&fit->header, -(int)sizeof(struct fit_entry));
781 
782 	update_fit_checksum(fit);
783 
784 	return 0;
785 }
786