util/cse_serger: Add a new tool for stitching CSE components
This change adds a new tool `cse_serger` which can be used to print, dump and stitch together different components for the CSE region. BUG=b:189177186 Change-Id: I90dd809b47fd16afdc80e66431312721082496aa Signed-off-by: Furquan Shaikh <furquan@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/55503 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
8
util/cbfstool/bpdt_formats/Makefile.inc
Normal file
8
util/cbfstool/bpdt_formats/Makefile.inc
Normal file
@@ -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
|
272
util/cbfstool/bpdt_formats/bpdt_1_6.c
Normal file
272
util/cbfstool/bpdt_formats/bpdt_1_6.c
Normal file
@@ -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,
|
||||
};
|
367
util/cbfstool/bpdt_formats/bpdt_1_7.c
Normal file
367
util/cbfstool/bpdt_formats/bpdt_1_7.c
Normal file
@@ -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,
|
||||
};
|
66
util/cbfstool/bpdt_formats/subpart_entry_1.c
Normal file
66
util/cbfstool/bpdt_formats/subpart_entry_1.c
Normal file
@@ -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,
|
||||
};
|
69
util/cbfstool/bpdt_formats/subpart_hdr_1.c
Normal file
69
util/cbfstool/bpdt_formats/subpart_hdr_1.c
Normal file
@@ -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,
|
||||
};
|
72
util/cbfstool/bpdt_formats/subpart_hdr_2.c
Normal file
72
util/cbfstool/bpdt_formats/subpart_hdr_2.c
Normal file
@@ -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,
|
||||
};
|
Reference in New Issue
Block a user