util/amdfwtool: Streamline functions with context
Replace variables and function arguments with a context that may be maintained and passed. Add macros to clarify the pointer math. Add functions to generate tables instead of relying on correct ordering and math. Use defined sizes for tables instead of arbitrary additions to an index. TEST=Verify no difference in amdfw.rom for google/grunt before and after, and verify a grunt build with PSP_COMBO=1 runs. Change-Id: I7ad12fa5d615d1aa3648db40e3ea75f8cf2ed59a Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/31734 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
parent
8e0dca05fb
commit
2794a86b1b
|
@ -77,6 +77,8 @@
|
||||||
#define MIN_ROM_KB 256
|
#define MIN_ROM_KB 256
|
||||||
|
|
||||||
#define ALIGN(val, by) (((val) + (by) - 1) & ~((by) - 1))
|
#define ALIGN(val, by) (((val) + (by) - 1) & ~((by) - 1))
|
||||||
|
#define TABLE_ALIGNMENT 0x1000U
|
||||||
|
#define BLOB_ALIGNMENT 0x100U
|
||||||
|
|
||||||
#define EMBEDDED_FW_SIGNATURE 0x55aa55aa
|
#define EMBEDDED_FW_SIGNATURE 0x55aa55aa
|
||||||
#define PSP_COOKIE 0x50535024 /* 'PSP$' */
|
#define PSP_COOKIE 0x50535024 /* 'PSP$' */
|
||||||
|
@ -275,6 +277,8 @@ typedef struct _psp_directory_table {
|
||||||
psp_directory_entry entries[];
|
psp_directory_entry entries[];
|
||||||
} __attribute__((packed)) psp_directory_table;
|
} __attribute__((packed)) psp_directory_table;
|
||||||
|
|
||||||
|
#define MAX_PSP_ENTRIES 0x1f
|
||||||
|
|
||||||
typedef struct _psp_combo_header {
|
typedef struct _psp_combo_header {
|
||||||
uint32_t cookie;
|
uint32_t cookie;
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
|
@ -294,6 +298,44 @@ typedef struct _psp_combo_directory {
|
||||||
psp_combo_entry entries[];
|
psp_combo_entry entries[];
|
||||||
} __attribute__((packed)) psp_combo_directory;
|
} __attribute__((packed)) psp_combo_directory;
|
||||||
|
|
||||||
|
#define MAX_COMBO_ENTRIES 1
|
||||||
|
|
||||||
|
typedef struct _context {
|
||||||
|
char *rom; /* target buffer, size of flash device */
|
||||||
|
uint32_t rom_size; /* size of flash device */
|
||||||
|
uint32_t current; /* pointer within flash & proxy buffer */
|
||||||
|
} context;
|
||||||
|
|
||||||
|
#define RUN_BASE(ctx) (0xFFFFFFFF - (ctx).rom_size + 1)
|
||||||
|
#define RUN_OFFSET(ctx, offset) (RUN_BASE(ctx) + (offset))
|
||||||
|
#define RUN_CURRENT(ctx) RUN_OFFSET((ctx), (ctx).current)
|
||||||
|
#define BUFF_OFFSET(ctx, offset) ((void *)((ctx).rom + (offset)))
|
||||||
|
#define BUFF_CURRENT(ctx) BUFF_OFFSET((ctx), (ctx).current)
|
||||||
|
#define BUFF_TO_RUN(ctx, ptr) RUN_OFFSET((ctx), ((char *)(ptr) - (ctx).rom))
|
||||||
|
#define BUFF_ROOM(ctx) ((ctx).rom_size - (ctx).current)
|
||||||
|
|
||||||
|
static void *new_psp_dir(context *ctx)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
|
||||||
|
ptr = BUFF_CURRENT(*ctx);
|
||||||
|
ctx->current += sizeof(psp_directory_header)
|
||||||
|
+ MAX_PSP_ENTRIES * sizeof(psp_directory_entry);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *new_combo_dir(context *ctx)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT);
|
||||||
|
ptr = BUFF_CURRENT(*ctx);
|
||||||
|
ctx->current += sizeof(psp_combo_header)
|
||||||
|
+ MAX_COMBO_ENTRIES * sizeof(psp_combo_entry);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie)
|
static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie)
|
||||||
{
|
{
|
||||||
if (cookie == PSP2_COOKIE) {
|
if (cookie == PSP2_COOKIE) {
|
||||||
|
@ -354,54 +396,55 @@ static ssize_t copy_blob(void *dest, const char *src_file, size_t room)
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t integrate_firmwares(char *base, uint32_t pos,
|
static void integrate_firmwares(context *ctx,
|
||||||
embedded_firmware *romsig,
|
embedded_firmware *romsig,
|
||||||
amd_fw_entry *fw_table, uint32_t rom_size)
|
amd_fw_entry *fw_table)
|
||||||
{
|
{
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
int i;
|
int i;
|
||||||
uint32_t rom_base_address = 0xFFFFFFFF - rom_size + 1;
|
|
||||||
|
ctx->current += sizeof(embedded_firmware);
|
||||||
|
ctx->current = ALIGN(ctx->current, BLOB_ALIGNMENT);
|
||||||
|
|
||||||
for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
|
for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
|
||||||
if (fw_table[i].filename != NULL) {
|
if (fw_table[i].filename != NULL) {
|
||||||
switch (fw_table[i].type) {
|
switch (fw_table[i].type) {
|
||||||
case AMD_FW_IMC:
|
case AMD_FW_IMC:
|
||||||
pos = ALIGN(pos, 0x10000U);
|
ctx->current = ALIGN(ctx->current, 0x10000U);
|
||||||
romsig->imc_entry = pos + rom_base_address;
|
romsig->imc_entry = RUN_CURRENT(*ctx);
|
||||||
break;
|
break;
|
||||||
case AMD_FW_GEC:
|
case AMD_FW_GEC:
|
||||||
romsig->gec_entry = pos + rom_base_address;
|
romsig->gec_entry = RUN_CURRENT(*ctx);
|
||||||
break;
|
break;
|
||||||
case AMD_FW_XHCI:
|
case AMD_FW_XHCI:
|
||||||
romsig->xhci_entry = pos + rom_base_address;
|
romsig->xhci_entry = RUN_CURRENT(*ctx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Error */
|
/* Error */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes = copy_blob(base + pos,
|
bytes = copy_blob(BUFF_CURRENT(*ctx),
|
||||||
fw_table[i].filename, rom_size - pos);
|
fw_table[i].filename, BUFF_ROOM(*ctx));
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
free(base);
|
free(ctx->rom);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = ALIGN(pos + bytes, 0x100U);
|
ctx->current = ALIGN(ctx->current + bytes,
|
||||||
|
BLOB_ALIGNMENT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos;
|
static void integrate_psp_firmwares(context *ctx,
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t integrate_psp_firmwares(char *base, uint32_t pos,
|
|
||||||
psp_directory_table *pspdir,
|
psp_directory_table *pspdir,
|
||||||
amd_fw_entry *fw_table,
|
amd_fw_entry *fw_table)
|
||||||
uint32_t rom_size)
|
|
||||||
{
|
{
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
unsigned int i, count;
|
unsigned int i, count;
|
||||||
uint32_t rom_base_address = 0xFFFFFFFF - rom_size + 1;
|
|
||||||
|
ctx->current = ALIGN(ctx->current, BLOB_ALIGNMENT);
|
||||||
|
|
||||||
for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
|
for (i = 0, count = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
|
||||||
if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
|
if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
|
||||||
|
@ -410,25 +453,32 @@ static uint32_t integrate_psp_firmwares(char *base, uint32_t pos,
|
||||||
pspdir->entries[count].addr = 1;
|
pspdir->entries[count].addr = 1;
|
||||||
count++;
|
count++;
|
||||||
} else if (fw_table[i].filename != NULL) {
|
} else if (fw_table[i].filename != NULL) {
|
||||||
bytes = copy_blob(base + pos,
|
bytes = copy_blob(BUFF_CURRENT(*ctx),
|
||||||
fw_table[i].filename, rom_size - pos);
|
fw_table[i].filename, BUFF_ROOM(*ctx));
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
free(base);
|
free(ctx->rom);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pspdir->entries[count].type = fw_table[i].type;
|
pspdir->entries[count].type = fw_table[i].type;
|
||||||
pspdir->entries[count].size = (uint32_t)bytes;
|
pspdir->entries[count].size = (uint32_t)bytes;
|
||||||
pspdir->entries[count].addr = rom_base_address + pos;
|
pspdir->entries[count].addr = RUN_CURRENT(*ctx);
|
||||||
|
|
||||||
pos = ALIGN(pos + bytes, 0x100U);
|
ctx->current = ALIGN(ctx->current + bytes,
|
||||||
|
BLOB_ALIGNMENT);
|
||||||
count++;
|
count++;
|
||||||
} else {
|
} else {
|
||||||
/* This APU doesn't have this firmware. */
|
/* This APU doesn't have this firmware. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count > MAX_PSP_ENTRIES) {
|
||||||
|
printf("Error: PSP entries exceed max allowed items\n");
|
||||||
|
free(ctx->rom);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
fill_dir_header(pspdir, count, PSP_COOKIE);
|
fill_dir_header(pspdir, count, PSP_COOKIE);
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *optstring = "x:i:g:Ap:b:s:r:k:c:n:d:t:u:w:e:j:m:o:f:l:h";
|
static const char *optstring = "x:i:g:Ap:b:s:r:k:c:n:d:t:u:w:e:j:m:o:f:l:h";
|
||||||
|
@ -486,14 +536,14 @@ int main(int argc, char **argv)
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
char *rom = NULL;
|
char *rom = NULL;
|
||||||
uint32_t current;
|
|
||||||
embedded_firmware *amd_romsig;
|
embedded_firmware *amd_romsig;
|
||||||
psp_directory_table *pspdir;
|
psp_directory_table *pspdir;
|
||||||
int comboable = 0;
|
int comboable = 0;
|
||||||
|
|
||||||
int targetfd;
|
int targetfd;
|
||||||
char *output = NULL;
|
char *output = NULL;
|
||||||
uint32_t rom_size = CONFIG_ROM_SIZE;
|
context ctx = {
|
||||||
|
.rom_size = CONFIG_ROM_SIZE,
|
||||||
|
};
|
||||||
uint32_t dir_location = 0;
|
uint32_t dir_location = 0;
|
||||||
uint32_t romsig_offset;
|
uint32_t romsig_offset;
|
||||||
uint32_t rom_base_address;
|
uint32_t rom_base_address;
|
||||||
|
@ -567,7 +617,7 @@ int main(int argc, char **argv)
|
||||||
output = optarg;
|
output = optarg;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
|
ctx.rom_size = (uint32_t)strtoul(optarg, &tmp, 16);
|
||||||
if (*tmp != '\0') {
|
if (*tmp != '\0') {
|
||||||
printf("Error: ROM size specified"
|
printf("Error: ROM size specified"
|
||||||
" incorrectly (%s)\n\n", optarg);
|
" incorrectly (%s)\n\n", optarg);
|
||||||
|
@ -596,20 +646,15 @@ int main(int argc, char **argv)
|
||||||
retval = 1;
|
retval = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rom_size) {
|
if (ctx.rom_size % 1024 != 0) {
|
||||||
printf("Error: ROM Size is not specified.\n\n");
|
|
||||||
retval = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rom_size % 1024 != 0) {
|
|
||||||
printf("Error: ROM Size (%d bytes) should be a multiple of"
|
printf("Error: ROM Size (%d bytes) should be a multiple of"
|
||||||
" 1024 bytes.\n\n", rom_size);
|
" 1024 bytes.\n\n", ctx.rom_size);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rom_size < MIN_ROM_KB * 1024) {
|
if (ctx.rom_size < MIN_ROM_KB * 1024) {
|
||||||
printf("Error: ROM Size (%dKB) must be at least %dKB.\n\n",
|
printf("Error: ROM Size (%dKB) must be at least %dKB.\n\n",
|
||||||
rom_size / 1024, MIN_ROM_KB);
|
ctx.rom_size / 1024, MIN_ROM_KB);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,9 +663,9 @@ int main(int argc, char **argv)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" AMDFWTOOL Using ROM size of %dKB\n", rom_size / 1024);
|
printf(" AMDFWTOOL Using ROM size of %dKB\n", ctx.rom_size / 1024);
|
||||||
|
|
||||||
rom_base_address = 0xFFFFFFFF - rom_size + 1;
|
rom_base_address = 0xFFFFFFFF - ctx.rom_size + 1;
|
||||||
if (dir_location && (dir_location < rom_base_address)) {
|
if (dir_location && (dir_location < rom_base_address)) {
|
||||||
printf("Error: Directory location outside of ROM.\n\n");
|
printf("Error: Directory location outside of ROM.\n\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -642,60 +687,54 @@ int main(int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rom = malloc(rom_size);
|
ctx.rom = malloc(ctx.rom_size);
|
||||||
if (!rom)
|
if (!ctx.rom) {
|
||||||
|
printf("Error: Failed to allocate memory\n");
|
||||||
return 1;
|
return 1;
|
||||||
memset(rom, 0xFF, rom_size);
|
}
|
||||||
|
memset(ctx.rom, 0xFF, ctx.rom_size);
|
||||||
|
|
||||||
if (dir_location)
|
if (dir_location)
|
||||||
romsig_offset = current = dir_location - rom_base_address;
|
romsig_offset = ctx.current = dir_location - rom_base_address;
|
||||||
else
|
else
|
||||||
romsig_offset = current = AMD_ROMSIG_OFFSET;
|
romsig_offset = ctx.current = AMD_ROMSIG_OFFSET;
|
||||||
printf(" AMDFWTOOL Using firmware directory location of %08lx\n",
|
printf(" AMDFWTOOL Using firmware directory location of 0x%08x\n",
|
||||||
(unsigned long)rom_base_address + current);
|
RUN_CURRENT(ctx));
|
||||||
|
|
||||||
amd_romsig = (embedded_firmware *)(rom + romsig_offset);
|
amd_romsig = BUFF_OFFSET(ctx, romsig_offset);
|
||||||
amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
|
amd_romsig->signature = EMBEDDED_FW_SIGNATURE;
|
||||||
amd_romsig->imc_entry = 0;
|
amd_romsig->imc_entry = 0;
|
||||||
amd_romsig->gec_entry = 0;
|
amd_romsig->gec_entry = 0;
|
||||||
amd_romsig->xhci_entry = 0;
|
amd_romsig->xhci_entry = 0;
|
||||||
|
|
||||||
current += sizeof(embedded_firmware);
|
integrate_firmwares(&ctx, amd_romsig, amd_fw_table);
|
||||||
current = ALIGN(current, 0x1000U);
|
|
||||||
current = integrate_firmwares(rom, current, amd_romsig,
|
ctx.current = ALIGN(ctx.current, 0x10000U); /* todo: is necessary? */
|
||||||
amd_fw_table, rom_size);
|
|
||||||
|
pspdir = new_psp_dir(&ctx);
|
||||||
|
integrate_psp_firmwares(&ctx, pspdir, amd_psp_fw_table);
|
||||||
|
|
||||||
current = ALIGN(current, 0x10000U);
|
|
||||||
if (comboable)
|
if (comboable)
|
||||||
amd_romsig->comboable = current + rom_base_address;
|
amd_romsig->comboable = BUFF_TO_RUN(ctx, pspdir);
|
||||||
else
|
else
|
||||||
amd_romsig->psp_entry = current + rom_base_address;
|
amd_romsig->psp_entry = BUFF_TO_RUN(ctx, pspdir);
|
||||||
|
|
||||||
#if PSP_COMBO
|
#if PSP_COMBO
|
||||||
/* TODO: remove the hardcode. */
|
psp_combo_directory *combo_dir = new_combo_dir(&ctx);
|
||||||
psp_combo_directory *combo_dir =
|
amd_romsig->comboable = BUFF_TO_RUN(ctx, combo_dir);
|
||||||
(psp_combo_directory *)(rom + current);
|
|
||||||
current = ALIGN(current + sizeof(psp_combo_header)
|
|
||||||
+ 1 * sizeof(psp_combo_entry), 0x1000);
|
|
||||||
/* 0 -Compare PSP ID, 1 -Compare chip family ID */
|
/* 0 -Compare PSP ID, 1 -Compare chip family ID */
|
||||||
combo_dir->entries[0].id_sel = 0;
|
combo_dir->entries[0].id_sel = 0;
|
||||||
/* TODO: PSP ID. Documentation is needed. */
|
/* TODO: PSP ID. Documentation is needed. */
|
||||||
combo_dir->entries[0].id = 0x10220B00;
|
combo_dir->entries[0].id = 0x10220B00;
|
||||||
combo_dir->entries[0].lvl2_addr = current + rom_base_address;
|
combo_dir->entries[0].lvl2_addr = BUFF_TO_RUN(ctx, pspdir);
|
||||||
|
|
||||||
combo_dir->header.lookup = 1;
|
combo_dir->header.lookup = 1;
|
||||||
fill_dir_header(combo_dir, 1, PSP2_COOKIE);
|
fill_dir_header(combo_dir, 1, PSP2_COOKIE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pspdir = (void *)(rom + current);
|
|
||||||
current += 0x200; /* Conservative size of pspdir */
|
|
||||||
current = integrate_psp_firmwares(rom, current, pspdir,
|
|
||||||
amd_psp_fw_table, rom_size);
|
|
||||||
|
|
||||||
|
|
||||||
targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||||
if (targetfd >= 0) {
|
if (targetfd >= 0) {
|
||||||
write(targetfd, amd_romsig, current - romsig_offset);
|
write(targetfd, amd_romsig, ctx.current - romsig_offset);
|
||||||
close(targetfd);
|
close(targetfd);
|
||||||
} else {
|
} else {
|
||||||
printf("Error: could not open file: %s\n", output);
|
printf("Error: could not open file: %s\n", output);
|
||||||
|
|
Loading…
Reference in New Issue