drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / util / cbfstool / fit.c
blobd4e48f19462f4a990e54e8a663147e992ed14a84
1 /* Firmware Interface Table support */
2 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <inttypes.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #include "fit.h"
12 /* FIXME: This code assumes it is being executed on a little endian machine. */
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_PLATFORM_BOOT_POLICY_VERSION 0x0100
21 #define FIT_TXT_VERSION 0x0100
23 #define FIT_SIZE_ALIGNMENT 16
25 struct fit_entry {
26 /**
27 * Address is the base address of the firmware component
28 * must be aligned on 16 byte boundary
30 uint64_t address;
31 /**
32 * Size is the span of the component in multiple of 16 bytes
33 * Bits [24:31] are reserved and must be set to 0
35 uint32_t size_reserved;
36 /**
37 * Component's version number in binary coded decimal (BCD) format.
38 * For the FIT header entry, the value in this field will indicate the
39 * revision number of the FIT data structure. The upper byte of the
40 * revision field indicates the major revision and the lower byte
41 * indicates the minor revision.
43 uint16_t version;
44 /**
45 * FIT types 0x00 to 0x7F
46 * Bit 7 (C_V) indicates whether component has valid checksum.
48 uint8_t type_checksum_valid;
49 /**
50 * Component's checksum. The modulo sum of all the bytes in the
51 * component and the value in this field (Chksum) must add up to zero.
52 * This field is only valid if the C_V flag is non-zero.
54 uint8_t checksum;
55 } __packed;
57 struct fit_table {
58 struct fit_entry header;
59 struct fit_entry entries[];
60 } __packed;
62 struct microcode_header {
63 uint32_t version;
64 uint32_t revision;
65 uint32_t date;
66 uint32_t processor_signature;
67 uint32_t checksum;
68 uint32_t loader_revision;
69 uint32_t processor_flags;
70 uint32_t data_size;
71 uint32_t total_size;
72 uint8_t reserved[12];
73 } __packed;
75 struct microcode_entry {
76 int offset;
77 int size;
80 static inline void *rom_buffer_pointer(struct buffer *buffer, int offset)
82 return &buffer->data[offset];
85 static inline size_t fit_entry_size_bytes(const struct fit_entry *entry)
87 return (entry->size_reserved & 0xffffff) << 4;
90 static inline void fit_entry_update_size(struct fit_entry *entry,
91 const int size_bytes)
93 /* Size is multiples of 16 bytes. */
94 entry->size_reserved = (size_bytes >> 4) & 0xffffff;
97 static inline void fit_entry_add_size(struct fit_entry *entry,
98 const int size_bytes)
100 int size = fit_entry_size_bytes(entry);
101 size += size_bytes;
102 fit_entry_update_size(entry, size);
105 static inline int fit_entry_type(struct fit_entry *entry)
107 return entry->type_checksum_valid & ~FIT_ENTRY_CHECKSUM_VALID;
111 * Get an offset from a host pointer. This function assumes the ROM is located
112 * in the host address space at [4G - romsize -> 4G). It also assume all
113 * pointers have values within this address range.
115 static inline int ptr_to_offset(fit_offset_converter_t helper,
116 const struct buffer *region, uint32_t host_ptr)
118 return helper(region, -host_ptr);
122 * Get a pointer from an offset. This function assumes the ROM is located
123 * in the host address space at [4G - romsize -> 4G). It also assume all
124 * pointers have values within this address range.
126 static inline uint32_t offset_to_ptr(fit_offset_converter_t helper,
127 const struct buffer *region, int offset)
129 return -helper(region, offset);
133 * Return the number of FIT entries.
135 static inline size_t fit_table_entries(const struct fit_table *fit)
137 if (!fit)
138 return 0;
140 return (fit_entry_size_bytes(&fit->header) / FIT_SIZE_ALIGNMENT) - 1;
144 * Return the number of unused entries.
146 static inline size_t fit_free_space(struct fit_table *fit,
147 const size_t max_entries)
149 if (!fit)
150 return 0;
152 return max_entries - fit_table_entries(fit);
156 * Sort entries by type and fill gaps (entries with type unused).
157 * To be called after adding or deleting entries.
159 * This one is critical, as mentioned in Chapter 1.2.1 "FIT Ordering Rules"
160 * "Firmware Interface Table BIOS Specification".
162 * We need to use a stable sorting algorithm, as the order of
163 * FIT_TYPE_BIOS_STARTUP matter for measurements.
165 static void sort_fit_table(struct fit_table *fit)
167 struct fit_entry tmp;
168 size_t i, j;
169 int swapped;
171 /* Bubble sort entries */
172 for (j = 0; j < fit_table_entries(fit) - 1; j++) {
173 swapped = 0;
174 for (i = 0; i < fit_table_entries(fit) - j - 1; i++) {
175 if (fit->entries[i].type_checksum_valid <=
176 fit->entries[i + 1].type_checksum_valid)
177 continue;
178 /* SWAP entries */
179 memcpy(&tmp, &fit->entries[i], sizeof(tmp));
180 memcpy(&fit->entries[i], &fit->entries[i + 1],
181 sizeof(fit->entries[i]));
182 memcpy(&fit->entries[i + 1], &tmp,
183 sizeof(fit->entries[i + 1]));
184 swapped = 1;
186 if (!swapped)
187 break;
191 static int fit_table_verified(struct fit_table *table)
193 if (!table)
194 return 0;
196 /* Check that the address field has the proper signature. */
197 if (strncmp((const char *)&table->header.address, FIT_HEADER_ADDRESS,
198 sizeof(table->header.address)))
199 return 0;
201 if (table->header.version != FIT_HEADER_VERSION)
202 return 0;
204 if (fit_entry_type(&table->header) != FIT_TYPE_HEADER)
205 return 0;
207 /* Assume that the FIT table contains at least the header */
208 if (fit_entry_size_bytes(&table->header) < sizeof(struct fit_entry))
209 return 0;
211 return 1;
215 * Update the FIT checksum.
216 * To be called after modifiying the table.
218 static void update_fit_checksum(struct fit_table *fit)
220 int size_bytes;
221 uint8_t *buffer;
222 uint8_t result;
223 int i;
225 if (!fit)
226 return;
228 fit->header.checksum = 0;
229 size_bytes = fit_entry_size_bytes(&fit->header);
230 result = 0;
231 buffer = (void *)fit;
232 for (i = 0; i < size_bytes; i++)
233 result += buffer[i];
234 fit->header.checksum = -result;
238 * Return a pointer to the next free entry.
239 * Caller must take care if enough space is available.
241 static struct fit_entry *get_next_free_entry(struct fit_table *fit)
243 return &fit->entries[fit_table_entries(fit)];
246 static void fit_location_from_cbfs_header(uint32_t *current_offset,
247 uint32_t *file_length, void *ptr)
249 struct buffer buf;
250 struct cbfs_file header;
251 memset(&buf, 0, sizeof(buf));
253 buf.data = ptr;
254 buf.size = sizeof(header);
256 bgets(&buf, header.magic, sizeof(header.magic));
257 header.len = xdr_be.get32(&buf);
258 header.type = xdr_be.get32(&buf);
259 header.attributes_offset = xdr_be.get32(&buf);
260 header.offset = xdr_be.get32(&buf);
262 *current_offset = header.offset;
263 *file_length = header.len;
266 static int
267 parse_microcode_blob(struct cbfs_image *image,
268 const char *blob_name,
269 size_t *mcus_found,
270 struct microcode_entry *mcus,
271 const size_t max_fit_entries)
273 size_t num_mcus;
274 uint32_t current_offset;
275 uint32_t file_length;
276 struct cbfs_file *mcode_file;
278 mcode_file = cbfs_get_entry(image, blob_name);
279 if (!mcode_file) {
280 ERROR("Couldn't find microcode blob.\n");
281 return 1;
284 fit_location_from_cbfs_header(&current_offset, &file_length,
285 mcode_file);
286 current_offset += cbfs_get_entry_addr(image, mcode_file);
288 num_mcus = 0;
289 while (file_length > sizeof(struct microcode_header)) {
290 const struct microcode_header *mcu_header;
292 mcu_header = rom_buffer_pointer(&image->buffer, current_offset);
293 if (!mcu_header) {
294 ERROR("Couldn't parse microcode header.\n");
295 return 1;
298 /* Newer microcode updates include a size field, whereas older
299 * containers set it at 0 and are exactly 2048 bytes long */
300 uint32_t total_size = mcu_header->total_size ?: 2048;
302 /* Quickly sanity check a prospective microcode update. */
303 if (total_size < sizeof(*mcu_header) ||
304 total_size > file_length)
305 break;
307 if (num_mcus == max_fit_entries) {
308 ERROR("Maximum of FIT entries reached.\n");
309 return 1;
312 /* FIXME: Should the checksum be validated? */
313 mcus[num_mcus].offset = current_offset;
314 mcus[num_mcus].size = total_size;
316 /* Proceed to next payload. */
317 current_offset += mcus[num_mcus].size;
318 file_length -= mcus[num_mcus].size;
319 num_mcus++;
320 if (file_length < sizeof(struct microcode_header))
321 break;
324 /* Update how many microcode updates we found. */
325 *mcus_found = num_mcus;
327 return 0;
330 /* There can be zero or more FIT_TYPE_MICROCODE entries */
331 static void update_fit_ucode_entry(struct fit_table *fit,
332 struct fit_entry *entry,
333 const uint64_t mcu_addr)
335 entry->address = mcu_addr;
337 * While loading MCU, its size is not referred from FIT and
338 * rather from the MCU header, hence we can assign zero here.
340 entry->size_reserved = 0;
341 entry->type_checksum_valid = FIT_TYPE_MICROCODE;
342 entry->version = FIT_MICROCODE_VERSION;
343 entry->checksum = 0;
344 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
348 * There can be zero or one FIT_TYPE_BIOS_ACM entry per table.
349 * In case there's a FIT_TYPE_BIOS_ACM entry, at least one
350 * FIT_TYPE_BIOS_STARTUP entry must exist.
352 * The caller has to provide valid arguments as those aren't verfied.
354 static void update_fit_bios_acm_entry(struct fit_table *fit,
355 struct fit_entry *entry,
356 const uint64_t acm_addr)
358 entry->address = acm_addr;
360 * The Address field points to a BIOS ACM. The Address field points to
361 * the first byte of the AC module header. When BIOS ACM is loaded in
362 * Authenticated Code RAM, one MTRR base/limit pair is used to map it.
364 entry->size_reserved = 0;
365 entry->type_checksum_valid = FIT_TYPE_BIOS_ACM;
366 entry->version = FIT_TXT_VERSION;
367 entry->checksum = 0;
368 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
371 static void update_fit_pbp_entry(struct fit_table *fit,
372 struct fit_entry *entry,
373 const uint64_t pbp_addr)
375 entry->address = pbp_addr;
376 entry->size_reserved = 0;
377 entry->type_checksum_valid = FIT_TYPE_PLATFORM_BOOT_POLICY;
378 entry->version = FIT_PLATFORM_BOOT_POLICY_VERSION;
379 entry->checksum = 0;
380 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
384 * In case there's a FIT_TYPE_BIOS_ACM entry, at least one
385 * FIT_TYPE_BIOS_STARTUP entry must exist.
387 * The caller has to provide valid arguments as those aren't verfied.
389 static void update_fit_bios_startup_entry(struct fit_table *fit,
390 struct fit_entry *entry,
391 const uint64_t sm_addr,
392 const uint32_t sm_size)
394 entry->address = sm_addr;
395 assert(sm_size % 16 == 0);
397 * BIOS Startup code is defined as the code that gets control at the
398 * reset vector and continues the chain of trust in TCG-compliant
399 * fashion. In addition, this code may also configure memory and SMRAM.
401 fit_entry_update_size(entry, sm_size);
402 entry->type_checksum_valid = FIT_TYPE_BIOS_STARTUP;
403 entry->version = FIT_TXT_VERSION;
404 entry->checksum = 0;
405 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
409 * There can be zero or one FIT_TYPE_BIOS_POLICY Record in the FIT.
410 * If the platform uses the hash comparison method and employs a
411 * failsafe bootblock, one FIT_TYPE_BIOS_POLICY entry is needed to
412 * contain the failsafe hash.
413 * If the platform uses the Signature verification method, one
414 * FIT_TYPE_BIOS_POLICY entry is needed. In this case, the entry
415 * contains the OEM key, hash of the BIOS and signature over the hash
416 * using the OEM key.
417 * In all other cases, the FIT_TYPE_BIOS_POLICY record is not required.
419 * The caller has to provide valid arguments as those aren't verfied.
421 static void update_fit_bios_policy_entry(struct fit_table *fit,
422 struct fit_entry *entry,
423 const uint64_t lcp_policy_addr,
424 const uint32_t lcp_policy_size)
426 entry->address = lcp_policy_addr;
427 fit_entry_update_size(entry, lcp_policy_size);
428 entry->type_checksum_valid = FIT_TYPE_BIOS_POLICY;
429 entry->version = FIT_TXT_VERSION;
430 entry->checksum = 0;
431 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
435 * There can be zero or one FIT_TYPE_TXT_POLICY entries
437 * The caller has to provide valid arguments as those aren't verfied.
439 static void update_fit_txt_policy_entry(struct fit_table *fit,
440 struct fit_entry *entry,
441 uint64_t txt_policy_addr)
443 entry->address = txt_policy_addr;
445 * Points to the flag indicating if TXT is enabled on this platform.
446 * If not present, TXT is not disabled by FIT.
448 entry->size_reserved = 0;
449 entry->type_checksum_valid = FIT_TYPE_TXT_POLICY;
450 entry->version = 0x1;
451 entry->checksum = 0;
452 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
456 * There can be zero or one FIT_TYPE_BOOT_POLICY entries
458 * The caller has to provide valid arguments as those aren't verified.
460 static void update_fit_boot_policy_entry(struct fit_table *fit,
461 struct fit_entry *entry,
462 uint64_t boot_policy_addr,
463 uint32_t boot_policy_size)
465 entry->address = boot_policy_addr;
466 entry->type_checksum_valid = FIT_TYPE_BOOT_POLICY;
467 entry->size_reserved = boot_policy_size;
468 entry->version = FIT_TXT_VERSION;
469 entry->checksum = 0;
470 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
474 * There can be zero or one FIT_TYPE_KEY_MANIFEST entries
476 * The caller has to provide valid arguments as those aren't verified.
478 static void update_fit_key_manifest_entry(struct fit_table *fit,
479 struct fit_entry *entry,
480 uint64_t key_manifest_addr,
481 uint32_t key_manifest_size)
483 entry->address = key_manifest_addr;
485 entry->type_checksum_valid = FIT_TYPE_KEY_MANIFEST;
486 entry->size_reserved = key_manifest_size;
487 entry->version = FIT_TXT_VERSION;
488 entry->checksum = 0;
489 fit_entry_add_size(&fit->header, sizeof(struct fit_entry));
492 /* Special case for ucode CBFS file, as it might contain more than one ucode */
493 int fit_add_microcode_file(struct fit_table *fit,
494 struct cbfs_image *image,
495 const char *blob_name,
496 fit_offset_converter_t offset_helper,
497 const size_t max_fit_entries)
499 struct microcode_entry *mcus;
501 size_t i;
502 size_t mcus_found;
504 mcus = malloc(sizeof(*mcus) * max_fit_entries);
505 if (!mcus) {
506 ERROR("Couldn't allocate memory for microcode entries.\n");
507 return 1;
510 if (parse_microcode_blob(image, blob_name, &mcus_found, mcus,
511 max_fit_entries)) {
512 free(mcus);
513 return 1;
516 for (i = 0; i < mcus_found; i++) {
517 if (fit_add_entry(fit,
518 offset_to_ptr(offset_helper, &image->buffer,
519 mcus[i].offset),
521 FIT_TYPE_MICROCODE,
522 max_fit_entries)) {
524 free(mcus);
525 return 1;
529 free(mcus);
530 return 0;
533 static uint32_t *get_fit_ptr(struct buffer *bootblock, fit_offset_converter_t offset_fn,
534 uint32_t topswap_size)
536 return rom_buffer_pointer(bootblock,
537 ptr_to_offset(offset_fn, bootblock,
538 FIT_POINTER_LOCATION - topswap_size));
541 /* Set the FIT pointer to a FIT table. */
542 int set_fit_pointer(struct buffer *bootblock,
543 const uint32_t fit_address,
544 fit_offset_converter_t offset_fn,
545 uint32_t topswap_size)
547 struct fit_table *fit;
548 uint32_t *fit_pointer = get_fit_ptr(bootblock, offset_fn, topswap_size);
550 fit = rom_buffer_pointer(bootblock, ptr_to_offset(offset_fn, bootblock, fit_address));
552 if (fit_address < FIT_TABLE_LOWEST_ADDRESS) {
553 ERROR("FIT must be reside in the top 16MiB.\n");
554 return 1;
557 if (!fit_table_verified(fit)) {
558 ERROR("FIT not found at address.\n");
559 return 1;
562 fit_pointer[0] = fit_address;
563 fit_pointer[1] = 0;
564 return 0;
568 * Return a pointer to the active FIT.
570 struct fit_table *fit_get_table(struct buffer *bootblock,
571 fit_offset_converter_t offset_fn,
572 uint32_t topswap_size)
574 struct fit_table *fit;
575 uint32_t *fit_pointer = get_fit_ptr(bootblock, offset_fn, topswap_size);
577 /* Ensure pointer is below 4GiB and within 16MiB of 4GiB */
578 if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) {
579 ERROR("FIT not found.\n");
580 return NULL;
583 fit = rom_buffer_pointer(bootblock,
584 ptr_to_offset(offset_fn, bootblock, *fit_pointer));
585 if (!fit_table_verified(fit)) {
586 ERROR("FIT not found.\n");
587 return NULL;
590 return fit;
594 * Dump the current FIT in human readable format to stdout.
596 int fit_dump(struct fit_table *fit)
598 size_t i;
600 if (!fit)
601 return 1;
603 printf("\n");
604 printf(" FIT table:\n");
606 if (fit_table_entries(fit) < 1) {
607 printf(" empty\n\n");
608 return 0;
611 printf(" %-6s %-20s %-16s %-8s\n", "Index", "Type", "Addr", "Size");
613 for (i = 0; i < fit_table_entries(fit); i++) {
614 const char *name;
616 switch (fit->entries[i].type_checksum_valid) {
617 case FIT_TYPE_MICROCODE:
618 name = "Microcode";
619 break;
620 case FIT_TYPE_BIOS_ACM:
621 name = "BIOS ACM";
622 break;
623 case FIT_TYPE_PLATFORM_BOOT_POLICY:
624 name = "Platform Boot Policy";
625 break;
626 case FIT_TYPE_BIOS_STARTUP:
627 name = "BIOS Startup Module";
628 break;
629 case FIT_TYPE_TPM_POLICY:
630 name = "TPM Policy";
631 break;
632 case FIT_TYPE_BIOS_POLICY:
633 name = "BIOS Policy";
634 break;
635 case FIT_TYPE_TXT_POLICY:
636 name = "TXT Policy";
637 break;
638 case FIT_TYPE_KEY_MANIFEST:
639 name = "Key Manifest";
640 break;
641 case FIT_TYPE_BOOT_POLICY:
642 name = "Boot Policy";
643 break;
644 case FIT_TYPE_CSE_SECURE_BOOT:
645 name = "CSE SecureBoot";
646 break;
647 case FIT_TYPE_TXTSX_POLICY:
648 name = "TXTSX policy";
649 break;
650 case FIT_TYPE_JMP_DEBUG_POLICY:
651 name = "JMP debug policy";
652 break;
653 case FIT_TYPE_UNUSED:
654 name = "unused";
655 break;
656 default:
657 name = "unknown";
660 printf(" %6zd %-20s 0x%08"PRIx64" 0x%08zx\n", i, name,
661 fit->entries[i].address,
662 fit_entry_size_bytes(&fit->entries[i]));
664 printf("\n");
665 return 0;
669 * Remove all entries from table.
671 int fit_clear_table(struct fit_table *fit)
673 if (!fit)
674 return 1;
676 memset(fit->entries, 0,
677 sizeof(struct fit_entry) * fit_table_entries(fit));
679 /* Reset entry counter in header */
680 fit_entry_update_size(&fit->header, sizeof(fit->header));
682 update_fit_checksum(fit);
684 return 0;
688 * Returns true if the FIT type is know and can be added to the table.
690 int fit_is_supported_type(const enum fit_type type)
692 switch (type) {
693 case FIT_TYPE_MICROCODE:
694 case FIT_TYPE_BIOS_ACM:
695 case FIT_TYPE_PLATFORM_BOOT_POLICY:
696 case FIT_TYPE_BIOS_STARTUP:
697 case FIT_TYPE_BIOS_POLICY:
698 case FIT_TYPE_TXT_POLICY:
699 case FIT_TYPE_KEY_MANIFEST:
700 case FIT_TYPE_BOOT_POLICY:
701 return 1;
702 case FIT_TYPE_TPM_POLICY:
703 default:
704 return 0;
709 * Adds an known entry to the FIT.
710 * len is optional for same types and might be zero.
711 * offset is an absolute address in 32-bit protected mode address space.
713 int fit_add_entry(struct fit_table *fit,
714 const uint32_t offset,
715 const uint32_t len,
716 const enum fit_type type,
717 const size_t max_fit_entries)
719 struct fit_entry *entry;
721 if (!fit) {
722 ERROR("Internal error.");
723 return 1;
726 if (fit_free_space(fit, max_fit_entries) < 1) {
727 ERROR("No space left in FIT.");
728 return 1;
731 if (!fit_is_supported_type(type)) {
732 ERROR("Unsupported FIT type %u\n", type);
733 return 1;
736 DEBUG("Adding new entry type %u at offset %zd\n", type,
737 fit_table_entries(fit));
739 entry = get_next_free_entry(fit);
741 switch (type) {
742 case FIT_TYPE_MICROCODE:
743 update_fit_ucode_entry(fit, entry, offset);
744 break;
745 case FIT_TYPE_BIOS_ACM:
746 update_fit_bios_acm_entry(fit, entry, offset);
747 break;
748 case FIT_TYPE_PLATFORM_BOOT_POLICY:
749 update_fit_pbp_entry(fit, entry, offset);
750 break;
751 case FIT_TYPE_BIOS_STARTUP:
752 update_fit_bios_startup_entry(fit, entry, offset, len);
753 break;
754 case FIT_TYPE_BIOS_POLICY:
755 update_fit_bios_policy_entry(fit, entry, offset, len);
756 break;
757 case FIT_TYPE_TXT_POLICY:
758 update_fit_txt_policy_entry(fit, entry, offset);
759 break;
760 case FIT_TYPE_KEY_MANIFEST:
761 update_fit_key_manifest_entry(fit, entry, offset, len);
762 break;
763 case FIT_TYPE_BOOT_POLICY:
764 update_fit_boot_policy_entry(fit, entry, offset, len);
765 break;
766 default:
767 return 1;
770 sort_fit_table(fit);
772 update_fit_checksum(fit);
774 return 0;
778 * Delete one entry from table.
780 int fit_delete_entry(struct fit_table *fit,
781 const size_t idx)
783 if (!fit) {
784 ERROR("Internal error.");
785 return 1;
788 if (idx >= fit_table_entries(fit)) {
789 ERROR("Index out of range.");
790 return 1;
793 memset(&fit->entries[idx], 0, sizeof(struct fit_entry));
795 fit->entries[idx].type_checksum_valid = FIT_TYPE_UNUSED;
797 sort_fit_table(fit);
799 /* The unused entry is now the last one */
800 fit_entry_add_size(&fit->header, -(int)sizeof(struct fit_entry));
802 update_fit_checksum(fit);
804 return 0;