diff options
Diffstat (limited to 'util/cbfstool/fit.c')
-rw-r--r-- | util/cbfstool/fit.c | 707 |
1 files changed, 590 insertions, 117 deletions
diff --git a/util/cbfstool/fit.c b/util/cbfstool/fit.c index aeb1755032..86dde4d23d 100644 --- a/util/cbfstool/fit.c +++ b/util/cbfstool/fit.c @@ -2,6 +2,8 @@ * Firmware Interface Table support. * * Copyright (C) 2012 Google Inc. + * Copyright (C) 2019 9elements Agency GmbH + * Copyright (C) 2019 Facebook Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,17 +27,42 @@ #define FIT_POINTER_LOCATION 0xffffffc0 #define FIT_TABLE_LOWEST_ADDRESS ((uint32_t)(-(16 << 20))) #define FIT_ENTRY_CHECKSUM_VALID 0x80 -#define FIT_TYPE_HEADER 0x0 -#define FIT_HEADER_VERSION 0x0100 -#define FIT_HEADER_ADDRESS "_FIT_ " -#define FIT_TYPE_MICROCODE 0x1 -#define FIT_MICROCODE_VERSION 0x0100 +#define FIT_HEADER_VERSION 0x0100 +#define FIT_HEADER_ADDRESS "_FIT_ " +#define FIT_MICROCODE_VERSION 0x0100 +#define FIT_TXT_VERSION 0x0100 + +#define FIT_SIZE_ALIGNMENT 16 struct fit_entry { + /** + * Address is the base address of the firmware component + * must be aligned on 16 byte boundary + */ uint64_t address; + /** + * Size is the span of the component in multiple of 16 bytes + * Bits [24:31] are reserved and must be set to 0 + */ uint32_t size_reserved; + /** + * Component's version number in binary coded decimal (BCD) format. + * For the FIT header entry, the value in this field will indicate the + * revision number of the FIT data structure. The upper byte of the + * revision field indicates the major revision and the lower byte + * indicates the minor revision. + */ uint16_t version; + /** + * FIT types 0x00 to 0x7F + * Bit 7 (C_V) indicates whether component has valid checksum. + */ uint8_t type_checksum_valid; + /** + * Component's checksum. The modulo sum of all the bytes in the + * component and the value in this field (Chksum) must add up to zero. + * This field is only valid if the C_V flag is non-zero. + */ uint8_t checksum; } __packed; @@ -67,20 +94,20 @@ static inline void *rom_buffer_pointer(struct buffer *buffer, int offset) return &buffer->data[offset]; } -static inline int fit_entry_size_bytes(struct fit_entry *entry) +static inline size_t fit_entry_size_bytes(const struct fit_entry *entry) { return (entry->size_reserved & 0xffffff) << 4; } static inline void fit_entry_update_size(struct fit_entry *entry, - int size_bytes) + const int size_bytes) { /* Size is multiples of 16 bytes. */ entry->size_reserved = (size_bytes >> 4) & 0xffffff; } static inline void fit_entry_add_size(struct fit_entry *entry, - int size_bytes) + const int size_bytes) { int size = fit_entry_size_bytes(entry); size += size_bytes; @@ -114,8 +141,70 @@ static inline uint32_t offset_to_ptr(fit_offset_converter_t helper, return -helper(region, offset); } +/* + * Return the number of FIT entries. + */ +static inline size_t fit_table_entries(const struct fit_table *fit) +{ + if (!fit) + return 0; + + return (fit_entry_size_bytes(&fit->header) / FIT_SIZE_ALIGNMENT) - 1; +} + +/* + * Return the number of unused entries. + */ +static inline size_t fit_free_space(struct fit_table *fit, + const size_t max_entries) +{ + if (!fit) + return 0; + + return max_entries - fit_table_entries(fit); +} + +/* + * Sort entries by type and fill gaps (entries with type unused). + * To be called after adding or deleting entries. + * + * This one is critical, as mentioned in Chapter 1.2.1 "FIT Ordering Rules" + * "Firmware Interface Table BIOS Specification". + * + * We need to use a stable sorting algortihm, as the order of + * FIT_TYPE_BIOS_STARTUP matter for measurements. + */ +static void sort_fit_table(struct fit_table *fit) +{ + struct fit_entry tmp; + size_t i, j; + int swapped; + + /* Bubble sort entries */ + for (j = 0; j < fit_table_entries(fit) - 1; j++) { + swapped = 0; + for (i = 0; i < fit_table_entries(fit) - j - 1; i++) { + if (fit->entries[i].type_checksum_valid <= + fit->entries[i + 1].type_checksum_valid) + continue; + /* SWAP entries */ + memcpy(&tmp, &fit->entries[i], sizeof(tmp)); + memcpy(&fit->entries[i], &fit->entries[i + 1], + sizeof(fit->entries[i])); + memcpy(&fit->entries[i + 1], &tmp, + sizeof(fit->entries[i + 1])); + swapped = 1; + } + if (!swapped) + break; + } +} + static int fit_table_verified(struct fit_table *table) { + if (!table) + return 0; + /* Check that the address field has the proper signature. */ if (strncmp((const char *)&table->header.address, FIT_HEADER_ADDRESS, sizeof(table->header.address))) @@ -127,35 +216,17 @@ static int fit_table_verified(struct fit_table *table) if (fit_entry_type(&table->header) != FIT_TYPE_HEADER) return 0; - /* Assume that the FIT table only contains the header */ - if (fit_entry_size_bytes(&table->header) != sizeof(struct fit_entry)) + /* Assume that the FIT table contains at least the header */ + if (fit_entry_size_bytes(&table->header) < sizeof(struct fit_entry)) return 0; return 1; } -static struct fit_table *locate_fit_table(fit_offset_converter_t offset_helper, - struct buffer *buffer) -{ - struct fit_table *table; - uint32_t *fit_pointer; - - fit_pointer = rom_buffer_pointer(buffer, - ptr_to_offset(offset_helper, buffer, - FIT_POINTER_LOCATION)); - - /* Ensure pointer is below 4GiB and within 16MiB of 4GiB */ - if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) - return NULL; - - table = rom_buffer_pointer(buffer, - ptr_to_offset(offset_helper, buffer, *fit_pointer)); - if (!fit_table_verified(table)) - return NULL; - else - return table; -} - +/* + * Update the FIT checksum. + * To be called after modifiying the table. + */ static void update_fit_checksum(struct fit_table *fit) { int size_bytes; @@ -163,6 +234,9 @@ static void update_fit_checksum(struct fit_table *fit) uint8_t result; int i; + if (!fit) + return; + fit->header.checksum = 0; size_bytes = fit_entry_size_bytes(&fit->header); result = 0; @@ -172,92 +246,68 @@ static void update_fit_checksum(struct fit_table *fit) fit->header.checksum = -result; } -static void update_fit_ucode_entry(struct fit_table *fit, - struct fit_entry *entry, uint64_t mcu_addr) -{ - entry->address = mcu_addr; - /* - * While loading MCU, its size is not referred from FIT and - * rather from the MCU header, hence we can assign zero here - */ - entry->size_reserved = 0x0000; - entry->type_checksum_valid = FIT_TYPE_MICROCODE; - entry->version = FIT_MICROCODE_VERSION; - entry->checksum = 0; - fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); -} - -static void add_microcodde_entries(struct fit_table *fit, - const struct cbfs_image *image, - int num_mcus, struct microcode_entry *mcus, - fit_offset_converter_t offset_helper, - uint32_t first_mcu_addr) -{ - int i = 0; - /* - * Check if an entry has to be forced into the FIT at index 0. - * first_mcu_addr is an address (in ROM) that will point to a - * microcode patch. - */ - if (first_mcu_addr) { - struct fit_entry *entry = &fit->entries[0]; - update_fit_ucode_entry(fit, entry, first_mcu_addr); - i = 1; - } - - struct microcode_entry *mcu = &mcus[0]; - for (; i < num_mcus; i++) { - struct fit_entry *entry = &fit->entries[i]; - update_fit_ucode_entry(fit, entry, offset_to_ptr(offset_helper, - &image->buffer, mcu->offset)); - mcu++; - } -} - -static void cbfs_file_get_header(struct buffer *buf, struct cbfs_file *file) +/* + * Return a pointer to the next free entry. + * Caller must take care if enough space is available. + */ +static struct fit_entry *get_next_free_entry(struct fit_table *fit) { - bgets(buf, &file->magic, sizeof(file->magic)); - file->len = xdr_be.get32(buf); - file->type = xdr_be.get32(buf); - file->attributes_offset = xdr_be.get32(buf); - file->offset = xdr_be.get32(buf); + return &fit->entries[fit_table_entries(fit)]; } -static int fit_header(void *ptr, uint32_t *current_offset, uint32_t *file_length) +static void fit_location_from_cbfs_header(uint32_t *current_offset, + uint32_t *file_length, void *ptr) { struct buffer buf; struct cbfs_file header; + memset(&buf, 0, sizeof(buf)); + buf.data = ptr; buf.size = sizeof(header); - cbfs_file_get_header(&buf, &header); + + bgets(&buf, header.magic, sizeof(header.magic)); + header.len = xdr_be.get32(&buf); + header.type = xdr_be.get32(&buf); + header.attributes_offset = xdr_be.get32(&buf); + header.offset = xdr_be.get32(&buf); + *current_offset = header.offset; *file_length = header.len; - return 0; } -static int parse_microcode_blob(struct cbfs_image *image, - struct cbfs_file *mcode_file, - struct microcode_entry *mcus, - int total_entries, int *mcus_found) +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) { - int num_mcus; + size_t num_mcus; uint32_t current_offset; uint32_t file_length; + struct cbfs_file *mcode_file; + + mcode_file = cbfs_get_entry(image, blob_name); + if (!mcode_file) + return 1; - fit_header(mcode_file, ¤t_offset, &file_length); - current_offset += (int)((char *)mcode_file - image->buffer.data); + fit_location_from_cbfs_header(¤t_offset, &file_length, + mcode_file); + current_offset += cbfs_get_entry_addr(image, mcode_file); num_mcus = 0; - while (file_length > sizeof(struct microcode_header)) - { + while (file_length > sizeof(struct microcode_header)) { const struct microcode_header *mcu_header; mcu_header = rom_buffer_pointer(&image->buffer, current_offset); + if (!mcu_header) { + ERROR("Couldn't parse microcode header.\n"); + return 1; + } /* Newer microcode updates include a size field, whereas older * containers set it at 0 and are exactly 2048 bytes long */ - uint32_t total_size = mcu_header->total_size - ? mcu_header->total_size : 2048; + uint32_t total_size = mcu_header->total_size ?: 2048; /* Quickly sanity check a prospective microcode update. */ if (total_size < sizeof(*mcu_header)) @@ -271,9 +321,8 @@ static int parse_microcode_blob(struct cbfs_image *image, current_offset += mcus[num_mcus].size; file_length -= mcus[num_mcus].size; num_mcus++; - /* Reached limit of FIT entries. */ - if (num_mcus == total_entries) + if (num_mcus == max_fit_entries) break; if (file_length < sizeof(struct microcode_header)) break; @@ -285,42 +334,466 @@ static int parse_microcode_blob(struct cbfs_image *image, return 0; } +/* There can be zero or more FIT_TYPE_MICROCODE entries */ +static void update_fit_ucode_entry(struct fit_table *fit, + struct fit_entry *entry, + const uint64_t mcu_addr) +{ + entry->address = mcu_addr; + /* + * While loading MCU, its size is not referred from FIT and + * rather from the MCU header, hence we can assign zero here. + */ + entry->size_reserved = 0; + entry->type_checksum_valid = FIT_TYPE_MICROCODE; + entry->version = FIT_MICROCODE_VERSION; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* + * There can be zero or one FIT_TYPE_BIOS_ACM entry per table. + * In case there's a FIT_TYPE_BIOS_ACM entry, at least one + * FIT_TYPE_BIOS_STARTUP entry must exist. + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void update_fit_bios_acm_entry(struct fit_table *fit, + struct fit_entry *entry, + const uint64_t acm_addr) +{ + entry->address = acm_addr; + /* + * The Address field points to a BIOS ACM. The Address field points to + * the first byte of the AC module header. When BIOS ACM is loaded in + * Authenticated Code RAM, one MTRR base/limit pair is used to map it. + */ + entry->size_reserved = 0; + entry->type_checksum_valid = FIT_TYPE_BIOS_ACM; + entry->version = FIT_TXT_VERSION; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* + * In case there's a FIT_TYPE_BIOS_ACM entry, at least one + * FIT_TYPE_BIOS_STARTUP entry must exist. + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void update_fit_bios_startup_entry(struct fit_table *fit, + struct fit_entry *entry, + const uint64_t sm_addr, + const uint32_t sm_size) +{ + entry->address = sm_addr; + assert(sm_size % 16 == 0); + /* + * BIOS Startup code is defined as the code that gets control at the + * reset vector and continues the chain of trust in TCG-compliant + * fashion. In addition, this code may also configure memory and SMRAM. + */ + fit_entry_update_size(entry, sm_size); + entry->type_checksum_valid = FIT_TYPE_BIOS_STARTUP; + entry->version = FIT_TXT_VERSION; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* + * There can be zero or one FIT_TYPE_BIOS_POLICY Record in the FIT. + * If the platform uses the hash comparison method and employs a + * failsafe bootblock, one FIT_TYPE_BIOS_POLICY entry is needed to + * contain the failsafe hash. + * If the platform uses the Signature verification method, one + * FIT_TYPE_BIOS_POLICY entry is needed. In this case, the entry + * contains the OEM key, hash of the BIOS and signature over the hash + * using the OEM key. + * In all other cases, the FIT_TYPE_BIOS_POLICY record is not required. + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void 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) +{ + entry->address = lcp_policy_addr; + fit_entry_update_size(entry, lcp_policy_size); + entry->type_checksum_valid = FIT_TYPE_BIOS_POLICY; + entry->version = FIT_TXT_VERSION; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* + * There can be zero or one FIT_TYPE_TXT_POLICY entries + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void update_fit_txt_policy_entry(struct fit_table *fit, + struct fit_entry *entry, + uint64_t txt_policy_addr) +{ + entry->address = txt_policy_addr; + /* + * Points to the flag indicating if TXT is enabled on this platform. + * If not present, TXT is not disabled by FIT. + */ + entry->size_reserved = 0; + entry->type_checksum_valid = FIT_TYPE_TXT_POLICY; + entry->version = 0x1; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* Special case for ucode CBFS file, as it might contain more than one ucode */ +int 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) +{ + struct microcode_entry *mcus; + + size_t i; + size_t mcus_found; + + mcus = malloc(sizeof(*mcus) * max_fit_entries); + if (!mcus) { + ERROR("Couldn't allocate memory for microcode entries.\n"); + return 1; + } + + if (parse_microcode_blob(image, blob_name, &mcus_found, mcus, + max_fit_entries)) { + ERROR("Couldn't parse microcode blob.\n"); + free(mcus); + return 1; + } + + if (mcus_found > fit_free_space(fit, max_fit_entries)) { + ERROR("Maximum of FIT entries reached.\n"); + free(mcus); + return 1; + } + + for (i = 0; i < mcus_found; i++) { + if (fit_add_entry(fit, + offset_to_ptr(offset_helper, &image->buffer, + mcus[i].offset), + 0, + FIT_TYPE_MICROCODE, + max_fit_entries)) { + + free(mcus); + return 1; + } + } + + free(mcus); + return 0; +} + +/* + * Return a pointer to the active FIT. + */ +struct fit_table *fit_get_table(struct buffer *bootblock, + fit_offset_converter_t offset_fn, + uint32_t topswap_size) +{ + struct fit_table *fit; + uint32_t *fit_pointer; + + fit_pointer = rom_buffer_pointer(bootblock, + ptr_to_offset(offset_fn, bootblock, + FIT_POINTER_LOCATION)); + + /* Ensure pointer is below 4GiB and within 16MiB of 4GiB */ + if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) { + ERROR("FIT not found.\n"); + return NULL; + } + + fit = rom_buffer_pointer(bootblock, + ptr_to_offset(offset_fn, bootblock, *fit_pointer)); + if (!fit_table_verified(fit)) { + ERROR("FIT not found.\n"); + return NULL; + } + + if (topswap_size) { + struct fit_table *fit2 = (struct fit_table *)((uintptr_t)fit - + topswap_size); + if (!fit_table_verified(fit2)) { + ERROR("second FIT is invalid\n"); + return NULL; + } + fit = fit2; + } + + DEBUG("Operating on table (0x%x)\n", *fit_pointer - topswap_size); + + return fit; +} + +/* + * Dump the current FIT in human readable format to stdout. + */ +int fit_dump(struct fit_table *fit) +{ + size_t i; + + if (!fit) + return 1; + + printf("\n"); + printf(" FIT table:\n"); + + if (fit_table_entries(fit) < 1) { + printf(" empty\n\n"); + return 0; + } + + printf(" %-6s %-20s %-16s %-8s\n", "Index", "Type", "Addr", "Size"); + + for (i = 0; i < fit_table_entries(fit); i++) { + const char *name; + + switch (fit->entries[i].type_checksum_valid) { + case FIT_TYPE_MICROCODE: + name = "Microcode"; + break; + case FIT_TYPE_BIOS_ACM: + name = "BIOS ACM"; + break; + case FIT_TYPE_BIOS_STARTUP: + name = "BIOS Startup Module"; + break; + case FIT_TYPE_TPM_POLICY: + name = "TPM Policy"; + break; + case FIT_TYPE_BIOS_POLICY: + name = "BIOS Policy"; + break; + case FIT_TYPE_TXT_POLICY: + name = "TXT Policy"; + break; + case FIT_TYPE_KEY_MANIFEST: + name = "Key Manifest"; + break; + case FIT_TYPE_BOOT_POLICY: + name = "Boot Policy"; + break; + case FIT_TYPE_CSE_SECURE_BOOT: + name = "CSE SecureBoot"; + break; + case FIT_TYPE_TXTSX_POLICY: + name = "TXTSX policy"; + break; + case FIT_TYPE_JMP_DEBUG_POLICY: + name = "JMP debug policy"; + break; + case FIT_TYPE_UNUSED: + name = "unused"; + break; + default: + name = "unknown"; + } + + printf(" %6zd %-20s 0x%08"PRIx64" 0x%08zx\n", i, name, + fit->entries[i].address, + fit_entry_size_bytes(&fit->entries[i])); + } + printf("\n"); + return 0; +} + +/* + * Remove all entries from table. + */ +int fit_clear_table(struct fit_table *fit) +{ + if (!fit) + return 1; + + memset(fit->entries, 0, + sizeof(struct fit_entry) * fit_table_entries(fit)); + + /* Reset entry counter in header */ + fit_entry_update_size(&fit->header, sizeof(fit->header)); + + update_fit_checksum(fit); + + return 0; +} + +/* + * Returns true if the FIT type is know and can be added to the table. + */ +int fit_is_supported_type(const enum fit_type type) +{ + switch (type) { + case FIT_TYPE_MICROCODE: + case FIT_TYPE_BIOS_ACM: + case FIT_TYPE_BIOS_STARTUP: + case FIT_TYPE_BIOS_POLICY: + case FIT_TYPE_TXT_POLICY: + return 1; + case FIT_TYPE_TPM_POLICY: + case FIT_TYPE_KEY_MANIFEST: + case FIT_TYPE_BOOT_POLICY: + default: + return 0; + } +} + +/* + * Adds an known entry to the FIT. + * len is optional for same types and might be zero. + * offset is an absolute address in 32-bit protected mode address space. + */ +int 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) +{ + struct fit_entry *entry; + + if (!fit) { + ERROR("Internal error."); + return 1; + } + + if (fit_free_space(fit, max_fit_entries) < 1) { + ERROR("No space left in FIT."); + return 1; + } + + if (!fit_is_supported_type(type)) { + ERROR("Unsupported FIT type %u\n", type); + return 1; + } + + DEBUG("Adding new entry type %u at offset %zd\n", type, + fit_table_entries(fit)); + + entry = get_next_free_entry(fit); + + switch (type) { + case FIT_TYPE_MICROCODE: + update_fit_ucode_entry(fit, entry, offset); + break; + case FIT_TYPE_BIOS_ACM: + update_fit_bios_acm_entry(fit, entry, offset); + break; + case FIT_TYPE_BIOS_STARTUP: + update_fit_bios_startup_entry(fit, entry, offset, len); + break; + case FIT_TYPE_BIOS_POLICY: + update_fit_bios_policy_entry(fit, entry, offset, len); + break; + case FIT_TYPE_TXT_POLICY: + update_fit_txt_policy_entry(fit, entry, offset); + break; + default: + return 1; + } + + sort_fit_table(fit); + + update_fit_checksum(fit); + + return 0; +} + +/* + * Delete one entry from table. + */ +int fit_delete_entry(struct fit_table *fit, + const size_t idx) +{ + if (!fit) { + ERROR("Internal error."); + return 1; + } + + if (idx >= fit_table_entries(fit)) { + ERROR("Index out of range."); + return 1; + } + + memset(&fit->entries[idx], 0, sizeof(struct fit_entry)); + + fit->entries[idx].type_checksum_valid = FIT_TYPE_UNUSED; + + sort_fit_table(fit); + + /* The unused entry is now the last one */ + fit_entry_add_size(&fit->header, -(int)sizeof(struct fit_entry)); + + update_fit_checksum(fit); + + return 0; +} + +/* Legacy code. TODO: Remove once ifittool is merged. */ + +static void add_microcodde_entries(struct fit_table *fit, + const struct cbfs_image *image, + ssize_t num_mcus, + struct microcode_entry *mcus, + fit_offset_converter_t offset_helper, + uint32_t first_mcu_addr) +{ + int i = 0; + /* + * Check if an entry has to be forced into the FIT at index 0. + * first_mcu_addr is an address (in ROM) that will point to a + * microcode patch. + */ + if (first_mcu_addr) { + struct fit_entry *entry = &fit->entries[0]; + update_fit_ucode_entry(fit, entry, first_mcu_addr); + i = 1; + } + + struct microcode_entry *mcu = &mcus[0]; + for (; i < num_mcus; i++) { + struct fit_entry *entry = &fit->entries[i]; + update_fit_ucode_entry(fit, entry, offset_to_ptr(offset_helper, + &image->buffer, mcu->offset)); + mcu++; + } +} + int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, - const char *microcode_blob_name, int empty_entries, + const char *microcode_blob_name, + unsigned int empty_entries, fit_offset_converter_t offset_fn, uint32_t topswap_size, - uint32_t first_mcu_addr) + uint32_t first_mcu_addr) { struct fit_table *fit, *fit2; - struct cbfs_file *mcode_file; struct microcode_entry *mcus; - int mcus_found; + size_t mcus_found; int ret = 0; - // struct rom_image image = { .rom = rom, .size = romsize, }; - - fit = locate_fit_table(offset_fn, bootblock); + fit = fit_get_table(bootblock, offset_fn, 0); if (!fit) { ERROR("FIT not found.\n"); return 1; } - mcode_file = cbfs_get_entry(image, microcode_blob_name); - if (!mcode_file) { - ERROR("File '%s' not found in CBFS.\n", - microcode_blob_name); - return 1; - } - mcus = malloc(sizeof(*mcus) * empty_entries); - if (!mcus) { - ERROR("Couldn't allocate memory for microcode update entries.\n"); + ERROR("Couldn't allocate memory for microcode entries.\n"); return 1; } - if (parse_microcode_blob(image, mcode_file, mcus, empty_entries, - &mcus_found)) { + if (parse_microcode_blob(image, microcode_blob_name, &mcus_found, + mcus, empty_entries)) { ERROR("Couldn't parse microcode blob.\n"); ret = 1; goto out; @@ -333,7 +806,7 @@ int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, /* A second fit is exactly topswap size away from the bottom one */ if (topswap_size) { - fit2 = (struct fit_table *)((uintptr_t)fit - topswap_size); + fit2 = fit_get_table(bootblock, offset_fn, topswap_size); if (!fit_table_verified(fit2)) { ERROR("second FIT is invalid\n"); @@ -343,8 +816,8 @@ int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, /* Check if we have room for first entry */ if (first_mcu_addr) { if (mcus_found >= empty_entries) { - ERROR("No room, blob mcus = %d, total entries = %d\n", - mcus_found, empty_entries); + ERROR("No room, blob mcus = %zd, total entries" + " = %d\n", mcus_found, empty_entries); ret = 1; goto out; } |