diff options
Diffstat (limited to 'util/cbfstool/bpdt_formats')
-rw-r--r-- | util/cbfstool/bpdt_formats/Makefile.inc | 8 | ||||
-rw-r--r-- | util/cbfstool/bpdt_formats/bpdt_1_6.c | 272 | ||||
-rw-r--r-- | util/cbfstool/bpdt_formats/bpdt_1_7.c | 367 | ||||
-rw-r--r-- | util/cbfstool/bpdt_formats/subpart_entry_1.c | 66 | ||||
-rw-r--r-- | util/cbfstool/bpdt_formats/subpart_hdr_1.c | 69 | ||||
-rw-r--r-- | util/cbfstool/bpdt_formats/subpart_hdr_2.c | 72 |
6 files changed, 854 insertions, 0 deletions
diff --git a/util/cbfstool/bpdt_formats/Makefile.inc b/util/cbfstool/bpdt_formats/Makefile.inc new file mode 100644 index 0000000000..c676489e9f --- /dev/null +++ b/util/cbfstool/bpdt_formats/Makefile.inc @@ -0,0 +1,8 @@ + +bpdt_formats_obj += bpdt_1_6.o +bpdt_formats_obj += bpdt_1_7.o + +bpdt_formats_obj += subpart_hdr_1.o +bpdt_formats_obj += subpart_hdr_2.o + +bpdt_formats_obj += subpart_entry_1.o diff --git a/util/cbfstool/bpdt_formats/bpdt_1_6.c b/util/cbfstool/bpdt_formats/bpdt_1_6.c new file mode 100644 index 0000000000..eaa2902670 --- /dev/null +++ b/util/cbfstool/bpdt_formats/bpdt_1_6.c @@ -0,0 +1,272 @@ +/* BPDT version 1.6 support */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <sys/types.h> + +#include "cse_serger.h" + +struct bpdt_header { + uint32_t signature; /* BPDT_SIGNATURE */ + uint16_t descriptor_count; + uint16_t version; /* Layout 1.6 = 1 */ + uint16_t reserved; + uint8_t whole_checksum; + uint8_t rom_checksum; + uint32_t ifwi_version; + struct { + uint16_t major; + uint16_t minor; + uint16_t build; + uint16_t hotfix; + } fit_tool_version; +} __packed; + +struct cse_layout { + uint8_t rom_bypass[16]; + uint32_t data_offset; + uint32_t data_size; + uint32_t bp1_offset; + uint32_t bp1_size; + uint32_t bp2_offset; + uint32_t bp2_size; + uint32_t bp3_offset; + uint32_t bp3_size; + uint32_t reserved[16]; + uint8_t checksum; +} __packed; + +static bool match_version(const struct buffer *buff) +{ + const uint8_t *data = buffer_get(buff); + const uint32_t sig = read_le32(data); + const uint16_t version = read_at_le16(data, offsetof(struct bpdt_header, version)); + + if (sig != BPDT_SIGNATURE) { + ERROR("Invalid BPDT signature(0x%x)!\n", sig); + return false; + } + + return version == BPDT_VERSION_1_6; +} + +static bpdt_hdr_ptr create_bpdt_hdr(void) +{ + struct bpdt_header *h = malloc(sizeof(*h)); + + if (!h) + return NULL; + + h->signature = BPDT_SIGNATURE; + h->descriptor_count = 0; + h->version = BPDT_VERSION_1_6; + h->reserved = 0; + /* TODO(b/202549343): Need to calculate checksum */ + h->whole_checksum = 0; + h->rom_checksum = 0; + h->ifwi_version = 0; + h->fit_tool_version.major = 0; + h->fit_tool_version.minor = 0; + h->fit_tool_version.build = 0; + h->fit_tool_version.hotfix = 0; + + return 0; +} + +static void print_bpdt_hdr(const bpdt_hdr_ptr ptr) +{ + struct bpdt_header *h = ptr; + + printf(" * BPDT header\n"); + printf("%-25s 0x%-23.8x\n", "Signature", h->signature); + printf("%-25s %-25d\n", "Descriptor count", h->descriptor_count); + printf("%-25s %d (Layout 1.6)\n", "BPDT Version", h->version); + printf("%-25s 0x%-23x\n", "Reserved", h->reserved); + printf("%-25s 0x%-23x\n", "Whole Checksum", h->whole_checksum); + printf("%-25s 0x%-23x\n", "ROM Checksum", h->rom_checksum); + printf("%-25s 0x%-23x\n", "IFWI Version", h->ifwi_version); + 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 bpdt_hdr_ptr read_bpdt_hdr(struct buffer *buff) +{ + struct bpdt_header *h = malloc(sizeof(*h)); + + if (!h) + return NULL; + + READ_MEMBER(buff, h->signature); + READ_MEMBER(buff, h->descriptor_count); + READ_MEMBER(buff, h->version); + READ_MEMBER(buff, h->reserved); + READ_MEMBER(buff, h->whole_checksum); + READ_MEMBER(buff, h->rom_checksum); + READ_MEMBER(buff, h->ifwi_version); + READ_MEMBER(buff, h->fit_tool_version); + + return h; +} + +static int write_bpdt_hdr(struct buffer *buff, const bpdt_hdr_ptr ptr) +{ + struct bpdt_header *h = ptr; + + if (buffer_size(buff) < sizeof(struct bpdt_header)) { + ERROR("Not enough size in buffer for BPDT header!\n"); + return -1; + } + + WRITE_MEMBER(buff, h->signature); + WRITE_MEMBER(buff, h->descriptor_count); + WRITE_MEMBER(buff, h->version); + WRITE_MEMBER(buff, h->reserved); + WRITE_MEMBER(buff, h->whole_checksum); + WRITE_MEMBER(buff, h->rom_checksum); + WRITE_MEMBER(buff, h->ifwi_version); + WRITE_MEMBER(buff, h->fit_tool_version); + + return 0; +} + +static size_t get_bpdt_entry_count(const bpdt_hdr_ptr ptr) +{ + return ((const struct bpdt_header *)ptr)->descriptor_count; +} + +static void inc_bpdt_entry_count(bpdt_hdr_ptr ptr) +{ + struct bpdt_header *h = ptr; + h->descriptor_count++; +} + +static cse_layout_ptr create_cse_layout(const struct cse_layout_regions *r) +{ + struct cse_layout *l = malloc(sizeof(*l)); + + if (!l) + return NULL; + + l->data_offset = r->data_partition.offset; + l->data_size = r->data_partition.size; + l->bp1_offset = r->bp1.offset; + l->bp1_size = r->bp1.size; + l->bp2_offset = r->bp2.offset; + l->bp2_size = r->bp2.size; + l->bp3_offset = r->bp3.offset; + l->bp3_size = r->bp3.size; + l->checksum = 0; /* unused */ + + return 0; +} + +static void print_cse_layout(const cse_layout_ptr ptr) +{ + struct cse_layout *l = ptr; + + printf(" * CSE Layout\n\n"); + printf("ROM Bypass: "); + for (size_t i = 0; i < sizeof(l->rom_bypass); i++) + printf("0x%x ", l->rom_bypass[i]); + printf("\n"); + printf("Data partition offset: 0x%x\n", l->data_offset); + printf("Data partition size: 0x%x\n", l->data_size); + printf("BP1 offset: 0x%x\n", l->bp1_offset); + printf("BP1 size: 0x%x\n", l->bp1_size); + printf("BP2 offset: 0x%x\n", l->bp2_offset); + printf("BP2 size: 0x%x\n", l->bp2_size); + printf("BP3 offset: 0x%x\n", l->bp3_offset); + printf("BP3 size: 0x%x\n", l->bp3_size); + printf("Checksum: 0x%x\n", l->checksum); +} + +static cse_layout_ptr read_cse_layout(struct buffer *buff) +{ + struct cse_layout *l = malloc(sizeof(*l)); + + if (!l) + return NULL; + + READ_MEMBER(buff, l->rom_bypass); + READ_MEMBER(buff, l->data_offset); + READ_MEMBER(buff, l->data_size); + READ_MEMBER(buff, l->bp1_offset); + READ_MEMBER(buff, l->bp1_size); + READ_MEMBER(buff, l->bp2_offset); + READ_MEMBER(buff, l->bp2_size); + READ_MEMBER(buff, l->bp3_offset); + READ_MEMBER(buff, l->bp3_size); + READ_MEMBER(buff, l->reserved); + READ_MEMBER(buff, l->checksum); + + return l; +} + +static int write_cse_layout(struct buffer *buff, const cse_layout_ptr ptr) +{ + struct cse_layout *l = ptr; + + if (buffer_size(buff) < sizeof(struct cse_layout)) { + ERROR("Not enough size in buffer for CSE layout!\n"); + return -1; + } + + WRITE_MEMBER(buff, l->rom_bypass); + WRITE_MEMBER(buff, l->data_offset); + WRITE_MEMBER(buff, l->data_size); + WRITE_MEMBER(buff, l->bp1_offset); + WRITE_MEMBER(buff, l->bp1_size); + WRITE_MEMBER(buff, l->bp2_offset); + WRITE_MEMBER(buff, l->bp2_size); + WRITE_MEMBER(buff, l->bp3_offset); + WRITE_MEMBER(buff, l->bp3_size); + WRITE_MEMBER(buff, l->reserved); + WRITE_MEMBER(buff, l->checksum); + + return 0; +} + +static void update_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e) +{ + (void)ptr; + (void)e; + + /* TODO(b/202549343) */ + ERROR("Update checksum is not supported for 1.6!\n"); +} + +static bool validate_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e) +{ + (void)e; + (void)ptr; + + /* TODO(b/202549343) */ + ERROR("Validate checksum is not supported for 1.6!\n"); + + return true; +} + +const struct bpdt_ops bpdt_1_6_ops = { + .match_version = match_version, + + .create_hdr = create_bpdt_hdr, + .print_hdr = print_bpdt_hdr, + .read_hdr = read_bpdt_hdr, + .write_hdr = write_bpdt_hdr, + + .get_entry_count = get_bpdt_entry_count, + .inc_entry_count = inc_bpdt_entry_count, + + .create_layout = create_cse_layout, + .print_layout = print_cse_layout, + .read_layout = read_cse_layout, + .write_layout = write_cse_layout, + + .update_checksum = update_checksum, + .validate_checksum = validate_checksum, + + .subpart_hdr_version = SUBPART_HDR_VERSION_1, + .subpart_entry_version = SUBPART_ENTRY_VERSION_1, +}; diff --git a/util/cbfstool/bpdt_formats/bpdt_1_7.c b/util/cbfstool/bpdt_formats/bpdt_1_7.c new file mode 100644 index 0000000000..53294242ca --- /dev/null +++ b/util/cbfstool/bpdt_formats/bpdt_1_7.c @@ -0,0 +1,367 @@ +/* BPDT version 1.7 support */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <sys/types.h> + +#include "cse_serger.h" + +enum bpdt_flags { + BPDT_FLAGS_REDUNDANCY_SUPPORTED = 1 << 0, +}; + +struct bpdt_header { + uint32_t signature; /* BPDT_SIGNATURE */ + uint16_t descriptor_count; + uint8_t version; /* Layout 1.7 = 2 */ + uint8_t flags; /* See enum bpdt_flags */ + uint32_t checksum; + uint32_t ifwi_version; + struct { + uint16_t major; + uint16_t minor; + uint16_t build; + uint16_t hotfix; + } fit_tool_version; +} __packed; + +struct cse_layout { + uint8_t rom_bypass[16]; + uint16_t size; + uint16_t redundancy; + uint32_t checksum; + uint32_t data_offset; + uint32_t data_size; + uint32_t bp1_offset; + uint32_t bp1_size; + uint32_t bp2_offset; + uint32_t bp2_size; + uint32_t bp3_offset; + uint32_t bp3_size; + uint32_t bp4_offset; + uint32_t bp4_size; + uint32_t bp5_offset; + uint32_t bp5_size; + uint32_t temp_base_addr; + uint32_t temp_base_size; + uint32_t flog_offset; + uint32_t flog_size; +} __packed; + +static bool match_version(const struct buffer *buff) +{ + const uint8_t *data = buffer_get(buff); + const uint32_t sig = read_le32(data); + const uint8_t version = read_at_le8(data, offsetof(struct bpdt_header, version)); + + if (sig != BPDT_SIGNATURE) { + ERROR("Invalid BPDT signature(0x%x)!\n", sig); + return false; + } + + return version == BPDT_VERSION_1_7; +} + +static bpdt_hdr_ptr create_bpdt_hdr(void) +{ + struct bpdt_header *h = calloc(1, sizeof(*h)); + + if (!h) + return NULL; + + h->signature = BPDT_SIGNATURE; + h->descriptor_count = 0; + h->version = BPDT_VERSION_1_7; + h->flags = 0; + h->checksum = 0; + h->ifwi_version = 0; + h->fit_tool_version.major = 0; + h->fit_tool_version.minor = 0; + h->fit_tool_version.build = 0; + h->fit_tool_version.hotfix = 0; + + return h; +} + +static void print_bpdt_hdr(const bpdt_hdr_ptr ptr) +{ + struct bpdt_header *h = ptr; + + printf(" * BPDT header\n"); + printf("%-25s 0x%-23.8x\n", "Signature", h->signature); + printf("%-25s %-25d\n", "Descriptor count", h->descriptor_count); + printf("%-25s %d (Layout 1.7)\n", "BPDT Version", h->version); + printf("%-25s 0x%-23x\n", "Flags", h->flags); + printf("%-25s 0x%-23x\n", "Checksum", h->checksum); + printf("%-25s 0x%-23x\n", "IFWI Version", h->ifwi_version); + 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 bpdt_hdr_ptr read_bpdt_hdr(struct buffer *buff) +{ + struct bpdt_header *h = calloc(1, sizeof(*h)); + + if (!h) + return NULL; + + READ_MEMBER(buff, h->signature); + READ_MEMBER(buff, h->descriptor_count); + READ_MEMBER(buff, h->version); + READ_MEMBER(buff, h->flags); + READ_MEMBER(buff, h->checksum); + READ_MEMBER(buff, h->ifwi_version); + READ_MEMBER(buff, h->fit_tool_version); + + return h; +} + +static int write_bpdt_hdr(struct buffer *buff, const bpdt_hdr_ptr ptr) +{ + struct bpdt_header *h = ptr; + + if (buffer_size(buff) < sizeof(struct bpdt_header)) { + ERROR("Not enough size in buffer for BPDT header!\n"); + return -1; + } + + WRITE_MEMBER(buff, h->signature); + WRITE_MEMBER(buff, h->descriptor_count); + WRITE_MEMBER(buff, h->version); + WRITE_MEMBER(buff, h->flags); + WRITE_MEMBER(buff, h->checksum); + WRITE_MEMBER(buff, h->ifwi_version); + WRITE_MEMBER(buff, h->fit_tool_version); + + return 0; +} + +static size_t get_bpdt_entry_count(const bpdt_hdr_ptr ptr) +{ + return ((const struct bpdt_header *)ptr)->descriptor_count; +} + +static void inc_bpdt_entry_count(bpdt_hdr_ptr ptr) +{ + struct bpdt_header *h = ptr; + h->descriptor_count++; +} + +static uint32_t crc32(uint32_t seed, const uint8_t *data, size_t len) +{ + uint32_t crc = seed; + + for (size_t i = 0; i < len; i++) { + crc ^= *data++; + + for (size_t b = 0; b < 8; b++) { + if (crc & 1) + crc = (crc >> 1) ^ 0xedb88320; + else + crc = crc >> 1; + } + } + + return crc; +} + +/* + * Calculate checksum by: + * a. stashing l->checksum in curr_checksum and setting l->checksum to 0 + * b. calculating checksum + * c. restoring l->checksum and return calculated checksum value. + */ +static uint32_t calculate_layout_checksum(struct cse_layout *l) +{ + uint32_t curr_checksum = l->checksum; + uint32_t calc_checksum; + + l->checksum = 0; + calc_checksum = ~crc32(0xffffffff, (void *)&l->size, l->size); + l->checksum = curr_checksum; + + return calc_checksum; +} + +static cse_layout_ptr create_cse_layout(const struct cse_layout_regions *r) +{ + struct cse_layout *l = calloc(1, sizeof(*l)); + + if (!l) + return NULL; + + memset(l->rom_bypass, 0xff, sizeof(l->rom_bypass)); + l->size = sizeof(struct cse_layout) - sizeof(l->rom_bypass); + l->redundancy = 0; + l->checksum = 0; + l->data_offset = r->data_partition.offset; + l->data_size = r->data_partition.size; + l->bp1_offset = r->bp1.offset; + l->bp1_size = r->bp1.size; + l->bp2_offset = r->bp2.offset; + l->bp2_size = r->bp2.size; + l->bp3_offset = r->bp3.offset; + l->bp3_size = r->bp3.size; + l->bp4_offset = r->bp4.offset; + l->bp4_size = r->bp4.size; + l->bp5_offset = 0; + l->bp5_size = 0; + l->temp_base_addr = 0; + l->temp_base_size = 0; + l->flog_offset = 0; + l->flog_size = 0; + + l->checksum = calculate_layout_checksum(l); + + return l; +} + +static void print_cse_layout(const cse_layout_ptr ptr) +{ + struct cse_layout *l = ptr; + + printf(" * CSE Layout\n\n"); + printf("ROM Bypass: "); + for (size_t i = 0; i < sizeof(l->rom_bypass); i++) + printf("0x%x ", l->rom_bypass[i]); + printf("\n"); + printf("Size: 0x%x\n", l->size); + printf("Redundancy: 0x%x\n", l->redundancy); + printf("Checksum: 0x%x\n", l->checksum); + printf("Data partition offset: 0x%x\n", l->data_offset); + printf("Data partition size: 0x%x\n", l->data_size); + printf("BP1 offset: 0x%x\n", l->bp1_offset); + printf("BP1 size: 0x%x\n", l->bp1_size); + printf("BP2 offset: 0x%x\n", l->bp2_offset); + printf("BP2 size: 0x%x\n", l->bp2_size); + printf("BP3 offset: 0x%x\n", l->bp3_offset); + printf("BP3 size: 0x%x\n", l->bp3_size); + printf("BP4 offset: 0x%x\n", l->bp4_offset); + printf("BP4 size: 0x%x\n", l->bp4_size); + printf("BP5 offset: 0x%x\n", l->bp5_offset); + printf("BP5 size: 0x%x\n", l->bp5_size); + printf("Temp base addr: 0x%x\n", l->temp_base_addr); + printf("Temp base size: 0x%x\n", l->temp_base_size); + printf("FLOG offset: 0x%x\n", l->flog_offset); + printf("FLOG size: 0x%x\n", l->flog_size); +} + +static cse_layout_ptr read_cse_layout(struct buffer *buff) +{ + struct cse_layout *l = calloc(1, sizeof(*l)); + + if (!l) + return NULL; + + READ_MEMBER(buff, l->rom_bypass); + READ_MEMBER(buff, l->size); + READ_MEMBER(buff, l->redundancy); + READ_MEMBER(buff, l->checksum); + READ_MEMBER(buff, l->data_offset); + READ_MEMBER(buff, l->data_size); + READ_MEMBER(buff, l->bp1_offset); + READ_MEMBER(buff, l->bp1_size); + READ_MEMBER(buff, l->bp2_offset); + READ_MEMBER(buff, l->bp2_size); + READ_MEMBER(buff, l->bp3_offset); + READ_MEMBER(buff, l->bp3_size); + READ_MEMBER(buff, l->bp4_offset); + READ_MEMBER(buff, l->bp4_size); + READ_MEMBER(buff, l->bp5_offset); + READ_MEMBER(buff, l->bp5_size); + READ_MEMBER(buff, l->temp_base_addr); + READ_MEMBER(buff, l->temp_base_size); + READ_MEMBER(buff, l->flog_offset); + READ_MEMBER(buff, l->flog_size); + + return l; +} + +static int write_cse_layout(struct buffer *buff, const cse_layout_ptr ptr) +{ + struct cse_layout *l = ptr; + + if (buffer_size(buff) < sizeof(struct cse_layout)) { + ERROR("Not enough size in buffer for CSE layout!\n"); + return -1; + } + + WRITE_MEMBER(buff, l->rom_bypass); + WRITE_MEMBER(buff, l->size); + WRITE_MEMBER(buff, l->redundancy); + WRITE_MEMBER(buff, l->checksum); + WRITE_MEMBER(buff, l->data_offset); + WRITE_MEMBER(buff, l->data_size); + WRITE_MEMBER(buff, l->bp1_offset); + WRITE_MEMBER(buff, l->bp1_size); + WRITE_MEMBER(buff, l->bp2_offset); + WRITE_MEMBER(buff, l->bp2_size); + WRITE_MEMBER(buff, l->bp3_offset); + WRITE_MEMBER(buff, l->bp3_size); + WRITE_MEMBER(buff, l->bp4_offset); + WRITE_MEMBER(buff, l->bp4_size); + WRITE_MEMBER(buff, l->bp5_offset); + WRITE_MEMBER(buff, l->bp5_size); + WRITE_MEMBER(buff, l->temp_base_addr); + WRITE_MEMBER(buff, l->temp_base_size); + WRITE_MEMBER(buff, l->flog_offset); + WRITE_MEMBER(buff, l->flog_size); + + return 0; +} + +static uint32_t calculate_bpdt_checksum(struct bpdt_header *h, struct bpdt_entry *e) +{ + uint32_t calc_checksum; + uint32_t curr_checksum = h->checksum; + + h->checksum = 0; + + calc_checksum = crc32(0xffffffff, (void *)&h->descriptor_count, + sizeof(*h) - sizeof(h->signature)); + + if (e && h->descriptor_count) + calc_checksum = crc32(calc_checksum, (void *)e, + h->descriptor_count * sizeof(struct bpdt_entry)); + + h->checksum = curr_checksum; + + return ~calc_checksum; +} + +static void update_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e) +{ + struct bpdt_header *h = ptr; + h->checksum = calculate_bpdt_checksum(h, e); +} + +static bool validate_checksum(bpdt_hdr_ptr ptr, struct bpdt_entry *e) +{ + struct bpdt_header *h = ptr; + return calculate_bpdt_checksum(h, e) == h->checksum; +} + +const struct bpdt_ops bpdt_1_7_ops = { + .match_version = match_version, + + .create_hdr = create_bpdt_hdr, + .print_hdr = print_bpdt_hdr, + .read_hdr = read_bpdt_hdr, + .write_hdr = write_bpdt_hdr, + + .get_entry_count = get_bpdt_entry_count, + .inc_entry_count = inc_bpdt_entry_count, + + .create_layout = create_cse_layout, + .print_layout = print_cse_layout, + .read_layout = read_cse_layout, + .write_layout = write_cse_layout, + + .update_checksum = update_checksum, + .validate_checksum = validate_checksum, + + .subpart_hdr_version = SUBPART_HDR_VERSION_2, + .subpart_entry_version = SUBPART_ENTRY_VERSION_1, +}; diff --git a/util/cbfstool/bpdt_formats/subpart_entry_1.c b/util/cbfstool/bpdt_formats/subpart_entry_1.c new file mode 100644 index 0000000000..a5982ff132 --- /dev/null +++ b/util/cbfstool/bpdt_formats/subpart_entry_1.c @@ -0,0 +1,66 @@ +/* Subpart directory entry version 1 support */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <sys/types.h> + +#include "cse_serger.h" + +#define SUBPART_OFFSET_SHIFT 0 +#define SUBPART_OFFSET_MASK 0x1ffffff +#define SUBPART_OFFSET(x) (((x) >> SUBPART_OFFSET_SHIFT) & SUBPART_OFFSET_MASK) +#define SUBPART_COMPRESSED_SHIFT 25 +#define SUBPART_COMPRESSED_MASK 1 +#define SUBPART_COMPRESSED(x) \ + (((x) >> SUBPART_COMPRESSED_SHIFT) & SUBPART_COMPRESSED_MASK) + +struct subpart_entry { + uint8_t name[12]; + uint32_t offset_bytes; + uint32_t length; + uint32_t rsvd2; +} __packed; + +static void subpart_read_entry(struct buffer *buff, struct subpart_entry *e) +{ + READ_MEMBER(buff, e->name); + READ_MEMBER(buff, e->offset_bytes); + READ_MEMBER(buff, e->length); + READ_MEMBER(buff, e->rsvd2); +} + +static void subpart_print_entry(const struct subpart_entry *e, size_t index) +{ + printf("%-25zd%-25.12s0x%-23x%-25c0x%-23x0x%-23x\n", index, + e->name, SUBPART_OFFSET(e->offset_bytes), + SUBPART_COMPRESSED(e->offset_bytes) ? 'Y' : 'N', + e->length, e->rsvd2); +} + +static void subpart_print_entries(struct buffer *buff, size_t count) +{ + struct subpart_entry *e = malloc(count * sizeof(*e)); + + if (!e) + return; + + for (size_t i = 0; i < count; i++) + subpart_read_entry(buff, &e[i]); + + printf("%-25s%-25s%-25s%-25s%-25s%-25s\n", "Entry #", "Name", "Offset", + "Huffman Compressed?", "Length", "Rsvd"); + + printf("=====================================================================" + "=====================================================================\n"); + + for (size_t i = 0; i < count; i++) + subpart_print_entry(&e[i], i + 1); + + printf("=====================================================================" + "=====================================================================\n"); + + free(e); +} + +const struct subpart_entry_ops subpart_entry_1_ops = { + .print = subpart_print_entries, +}; diff --git a/util/cbfstool/bpdt_formats/subpart_hdr_1.c b/util/cbfstool/bpdt_formats/subpart_hdr_1.c new file mode 100644 index 0000000000..5335c7a844 --- /dev/null +++ b/util/cbfstool/bpdt_formats/subpart_hdr_1.c @@ -0,0 +1,69 @@ +/* Subpart directory header version 1 support */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <sys/types.h> + +#include "cse_serger.h" + +struct subpart_hdr { + uint32_t signature; /* SUBPART_SIGNATURE */ + uint32_t count; + uint8_t hdr_version; /* Header version = 1 */ + uint8_t entry_version; /* Entry version = 1 */ + uint8_t length; + uint8_t checksum; + uint8_t name[4]; +} __packed; + +static void subpart_hdr_print(const subpart_hdr_ptr ptr) +{ + const struct subpart_hdr *hdr = ptr; + + printf("%-25s %.4s\n", "Signature", (const char *)&hdr->signature); + printf("%-25s %-25d\n", "Count", hdr->count); + printf("%-25s %-25d\n", "Header Version", hdr->hdr_version); + printf("%-25s %-25d\n", "Entry Version", hdr->entry_version); + printf("%-25s 0x%-23x\n", "Header Length", hdr->length); + printf("%-25s 0x%-23x\n", "Checksum", hdr->checksum); + printf("%-25s ", "Name"); + for (size_t i = 0; i < sizeof(hdr->name); i++) + printf("%c", hdr->name[i]); + printf("\n"); +} + +static subpart_hdr_ptr subpart_hdr_read(struct buffer *buff) +{ + struct subpart_hdr *hdr = malloc(sizeof(*hdr)); + + if (!hdr) + return NULL; + + READ_MEMBER(buff, hdr->signature); + READ_MEMBER(buff, hdr->count); + READ_MEMBER(buff, hdr->hdr_version); + READ_MEMBER(buff, hdr->entry_version); + READ_MEMBER(buff, hdr->length); + READ_MEMBER(buff, hdr->checksum); + READ_MEMBER(buff, hdr->name); + + return hdr; +} + +static size_t subpart_get_count(const subpart_hdr_ptr ptr) +{ + const struct subpart_hdr *hdr = ptr; + + return hdr->count; +} + +static void subpart_hdr_free(subpart_hdr_ptr ptr) +{ + free(ptr); +} + +const struct subpart_hdr_ops subpart_hdr_1_ops = { + .read = subpart_hdr_read, + .print = subpart_hdr_print, + .get_entry_count = subpart_get_count, + .free = subpart_hdr_free, +}; diff --git a/util/cbfstool/bpdt_formats/subpart_hdr_2.c b/util/cbfstool/bpdt_formats/subpart_hdr_2.c new file mode 100644 index 0000000000..17304dc447 --- /dev/null +++ b/util/cbfstool/bpdt_formats/subpart_hdr_2.c @@ -0,0 +1,72 @@ +/* Subpart directory header version 2 support */ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <sys/types.h> + +#include "cse_serger.h" + +struct subpart_hdr { + uint32_t signature; /* SUBPART_SIGNATURE */ + uint32_t count; + uint8_t hdr_version; /* Header version = 2 */ + uint8_t entry_version; /* Entry version = 1 */ + uint8_t length; + uint8_t reserved; + uint8_t name[4]; + uint32_t checksum; +} __packed; + +static subpart_hdr_ptr subpart_hdr_read(struct buffer *buff) +{ + struct subpart_hdr *hdr = malloc(sizeof(*hdr)); + + if (!hdr) + return NULL; + + READ_MEMBER(buff, hdr->signature); + READ_MEMBER(buff, hdr->count); + READ_MEMBER(buff, hdr->hdr_version); + READ_MEMBER(buff, hdr->entry_version); + READ_MEMBER(buff, hdr->length); + READ_MEMBER(buff, hdr->reserved); + READ_MEMBER(buff, hdr->name); + READ_MEMBER(buff, hdr->checksum); + + return hdr; +} + +static void subpart_hdr_print(const subpart_hdr_ptr ptr) +{ + const struct subpart_hdr *hdr = ptr; + + printf("%-25s %.4s\n", "Signature", (const char *)&hdr->signature); + printf("%-25s %-25d\n", "Count", hdr->count); + printf("%-25s %-25d\n", "Header Version", hdr->hdr_version); + printf("%-25s %-25d\n", "Entry Version", hdr->entry_version); + printf("%-25s 0x%-23x\n", "Header Length", hdr->length); + printf("%-25s 0x%-23x\n", "Reserved", hdr->reserved); + printf("%-25s ", "Name"); + for (size_t i = 0; i < sizeof(hdr->name); i++) + printf("%c", hdr->name[i]); + printf("\n"); + printf("%-25s 0x%-23x\n", "Checksum", hdr->checksum); +} + +static size_t subpart_get_count(const subpart_hdr_ptr ptr) +{ + const struct subpart_hdr *hdr = ptr; + + return hdr->count; +} + +static void subpart_hdr_free(subpart_hdr_ptr ptr) +{ + free(ptr); +} + +const struct subpart_hdr_ops subpart_hdr_2_ops = { + .read = subpart_hdr_read, + .print = subpart_hdr_print, + .get_entry_count = subpart_get_count, + .free = subpart_hdr_free, +}; |