diff options
author | Furquan Shaikh <furquan@google.com> | 2021-09-16 22:02:01 -0700 |
---|---|---|
committer | Furquan Shaikh <furquan@google.com> | 2021-10-19 16:08:03 +0000 |
commit | 796aeeba96fce7d6560c4d1994962a7107137666 (patch) | |
tree | bf0b79f0d0150488d7881dc44afb962a608a6777 /util/cbfstool/fpt_formats | |
parent | afd268a0cb440c1ccfaec5593bffbfe49bcfbf24 (diff) |
util/cse_fpt: Add a new tool for managing Intel CSE FPT binaries
This change adds a new tool `cse_fpt` which can be used to print and
dump CSE partitions in Flash Partition Table (FPT) format.
BUG=b:189167923
Change-Id: I93c8d33e9baa327cbdab918a14f2f7a039953be6
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55259
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Diffstat (limited to 'util/cbfstool/fpt_formats')
-rw-r--r-- | util/cbfstool/fpt_formats/Makefile.inc | 3 | ||||
-rw-r--r-- | util/cbfstool/fpt_formats/fpt_hdr_20.c | 106 | ||||
-rw-r--r-- | util/cbfstool/fpt_formats/fpt_hdr_21.c | 114 |
3 files changed, 223 insertions, 0 deletions
diff --git a/util/cbfstool/fpt_formats/Makefile.inc b/util/cbfstool/fpt_formats/Makefile.inc new file mode 100644 index 0000000000..865eaed5cd --- /dev/null +++ b/util/cbfstool/fpt_formats/Makefile.inc @@ -0,0 +1,3 @@ + +fpt_formats_obj += fpt_hdr_20.o +fpt_formats_obj += fpt_hdr_21.o diff --git a/util/cbfstool/fpt_formats/fpt_hdr_20.c b/util/cbfstool/fpt_formats/fpt_hdr_20.c new file mode 100644 index 0000000000..166d24cdf0 --- /dev/null +++ b/util/cbfstool/fpt_formats/fpt_hdr_20.c @@ -0,0 +1,106 @@ +/* CSE FPT header version 0x20 */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <sys/types.h> + +#include "cse_fpt.h" + +struct fpt_hdr { + uint8_t marker[4]; /* FPT_MARKER */ + uint32_t num_entries; + uint8_t hdr_version; /* FPT_HDR_VERSION_20 */ + uint8_t entry_version; /* FPT_ENTRY_VERSION */ + uint8_t hdr_length; + uint8_t hdr_checksum; + uint8_t rsvd[20]; +} __packed; + +static bool match_version(struct buffer *buff) +{ + const uint8_t *data = buffer_get(buff); + uint8_t version = read_at_le8(data, offsetof(struct fpt_hdr, hdr_version)); + + return version == FPT_HDR_VERSION_20; +} + +static bool validate_fpt_hdr(const struct fpt_hdr *h) +{ + if (memcmp(h->marker, FPT_MARKER, sizeof(h->marker))) { + ERROR("Invalid FPT header marker!\n"); + return false; + } + + if (h->hdr_version != FPT_HDR_VERSION_20) { + ERROR("Invalid FPT header version(0x%x)!\n", h->hdr_version); + return false; + } + + if (h->entry_version != FPT_ENTRY_VERSION) { + ERROR("Invalid FPT entry version(0x%x)!\n", h->entry_version); + return false; + } + + const uint8_t *data = (const uint8_t *)h; + uint8_t checksum = 0; + + for (size_t i = 0; i < sizeof(*h); i++) + checksum += data[i]; + + if (checksum != 0) { + ERROR("Invalid checksum (0x%x)!\n", h->hdr_checksum); + return false; + } + + return true; +} + +static fpt_hdr_ptr read_fpt_hdr(struct buffer *buff) +{ + struct fpt_hdr *h = malloc(sizeof(*h)); + if (!h) + return NULL; + + READ_MEMBER(buff, h->marker); + READ_MEMBER(buff, h->num_entries); + READ_MEMBER(buff, h->hdr_version); + READ_MEMBER(buff, h->entry_version); + READ_MEMBER(buff, h->hdr_length); + READ_MEMBER(buff, h->hdr_checksum); + READ_MEMBER(buff, h->rsvd); + + if (!validate_fpt_hdr(h)) { + free(h); + return NULL; + } + + return h; +} + +static void print_fpt_hdr(const fpt_hdr_ptr ptr) +{ + struct fpt_hdr *h = ptr; + + printf(" * FPT header\n"); + printf("%-25s: %.4s\n", "Marker", h->marker); + printf("%-25s: %d\n", "Number of entries", h->num_entries); + printf("%-25s: 0x%x\n", "Header version", h->hdr_version); + printf("%-25s: 0x%x\n", "Entry version", h->entry_version); + printf("%-25s: %d\n", "Header length", h->hdr_length); + printf("%-25s: 0x%x\n", "Header checksum", h->hdr_checksum); +} + +static size_t get_entry_count(const fpt_hdr_ptr ptr) +{ + struct fpt_hdr *h = ptr; + + return h->num_entries; +} + +const struct fpt_hdr_ops fpt_hdr_20_ops = { + .match_version = match_version, + + .read = read_fpt_hdr, + .print = print_fpt_hdr, + + .get_entry_count = get_entry_count, +}; diff --git a/util/cbfstool/fpt_formats/fpt_hdr_21.c b/util/cbfstool/fpt_formats/fpt_hdr_21.c new file mode 100644 index 0000000000..57746ddd74 --- /dev/null +++ b/util/cbfstool/fpt_formats/fpt_hdr_21.c @@ -0,0 +1,114 @@ +/* CSE FPT header version 0x21 */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <sys/types.h> + +#include "cse_fpt.h" + +struct fpt_hdr { + uint8_t marker[4]; /* FPT_MARKER */ + uint32_t num_entries; + uint8_t hdr_version; /* FPT_HDR_VERSION_21 */ + uint8_t entry_version; /* FPT_ENTRY_VERSION */ + uint8_t hdr_length; + uint8_t redundancy; + uint8_t reserved[8]; + uint32_t checksum; + struct { + uint16_t major; + uint16_t minor; + uint16_t build; + uint16_t hotfix; + } fit_tool_version; +} __packed; + +static bool match_version(struct buffer *buff) +{ + const uint8_t *data = buffer_get(buff); + uint8_t version = read_at_le8(data, offsetof(struct fpt_hdr, hdr_version)); + + return version == FPT_HDR_VERSION_21; +} + +static bool validate_fpt_hdr(const struct fpt_hdr *h) +{ + if (memcmp(h->marker, FPT_MARKER, sizeof(h->marker))) { + ERROR("Invalid FPT header marker!\n"); + return false; + } + + if (h->hdr_version != FPT_HDR_VERSION_21) { + ERROR("Invalid FPT header version(0x%x)!\n", h->hdr_version); + return false; + } + + if (h->entry_version != FPT_ENTRY_VERSION) { + ERROR("Invalid FPT entry version(0x%x)!\n", h->entry_version); + return false; + } + + return true; +} + +static fpt_hdr_ptr read_fpt_hdr(struct buffer *buff) +{ + struct fpt_hdr *h = malloc(sizeof(*h)); + if (!h) + return NULL; + + READ_MEMBER(buff, h->marker); + READ_MEMBER(buff, h->num_entries); + READ_MEMBER(buff, h->hdr_version); + READ_MEMBER(buff, h->entry_version); + READ_MEMBER(buff, h->hdr_length); + READ_MEMBER(buff, h->redundancy); + READ_MEMBER(buff, h->reserved); + READ_MEMBER(buff, h->checksum); + READ_MEMBER(buff, h->fit_tool_version); + + if (!validate_fpt_hdr(h)) { + free(h); + return NULL; + } + + return h; +} + +static void print_fpt_hdr(const fpt_hdr_ptr ptr) +{ + struct fpt_hdr *h = ptr; + + printf(" * FPT header\n"); + printf("%-25s: %.4s\n", "Marker", h->marker); + printf("%-25s: %d\n", "Number of entries", h->num_entries); + printf("%-25s: 0x%x\n", "Header version", h->hdr_version); + printf("%-25s: 0x%x\n", "Entry version", h->entry_version); + printf("%-25s: %d\n", "Header length", h->hdr_length); + printf("%-25s: 0x%x\n", "Redundancy", h->redundancy); + printf("%-25s: ", "Reserved"); + for (size_t i = 0; i < ARRAY_SIZE(h->reserved); i++) + printf("0x%x ", h->reserved[i]); + printf("\n"); + printf("%-25s: 0x%x\n", "Checksum", h->checksum); + printf("%-25s: %d.%d.%d.%d(%.2x.%.2x.%.2x.%.2x)\n", "FIT Tool Version", + h->fit_tool_version.major, h->fit_tool_version.minor, + h->fit_tool_version.build, h->fit_tool_version.hotfix, + h->fit_tool_version.major, h->fit_tool_version.minor, + h->fit_tool_version.build, h->fit_tool_version.hotfix); +} + +static size_t get_entry_count(const fpt_hdr_ptr ptr) +{ + struct fpt_hdr *h = ptr; + + return h->num_entries; +} + +const struct fpt_hdr_ops fpt_hdr_21_ops = { + .match_version = match_version, + + .read = read_fpt_hdr, + .print = print_fpt_hdr, + + .get_entry_count = get_entry_count, +}; |