cbfstool: Use cbfs_image API for "create" command.
Usage Changes: To support platforms with different memory layout, "create" takes two extra optional parameters: "-b": base address (or offset) for bootblock. When omitted, put bootblock in end of ROM (x86 style). "-H": header offset. When omitted, put header right before bootblock, and update a top-aligned virtual address reference in end of ROM. Example: (can be found in ARM MAkefile): cbfstool coreboot.rom create -m armv7 -s 4096K -B bootblock.bin \ -a 64 -b 0x0000 -H 0x2040 -o 0x5000 Verified to boot on ARM (Snow) and X86 (QEMU). Change-Id: Ida2a9e32f9a459787b577db5e6581550d9d7017b Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: http://review.coreboot.org/2214 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
215d1d7c9b
commit
f56c73f1e1
@ -45,9 +45,10 @@ prebuild-files = \
|
|||||||
$(if $(call extract_nth,4,$(file)),-b $(call extract_nth,4,$(file))) &&)
|
$(if $(call extract_nth,4,$(file)),-b $(call extract_nth,4,$(file))) &&)
|
||||||
prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file)))
|
prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file)))
|
||||||
|
|
||||||
|
# TODO Change -b, -H, -o to Kconfig variables.
|
||||||
$(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL)
|
$(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL)
|
||||||
$(CBFSTOOL) $@.tmp create -m armv7 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \
|
$(CBFSTOOL) $@.tmp create -m armv7 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \
|
||||||
-B $(objcbfs)/bootblock.bin -a 64
|
-B $(objcbfs)/bootblock.bin -a 64 -b 0x0000 -H 0x2040 -o 0x5000
|
||||||
$(prebuild-files) true
|
$(prebuild-files) true
|
||||||
mv $@.tmp $@
|
mv $@.tmp $@
|
||||||
else
|
else
|
||||||
|
@ -130,6 +130,94 @@ static int cbfs_fix_legacy_size(struct cbfs_image *image) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cbfs_image_create(struct cbfs_image *image,
|
||||||
|
uint32_t arch,
|
||||||
|
size_t size,
|
||||||
|
uint32_t align,
|
||||||
|
struct buffer *bootblock,
|
||||||
|
int32_t bootblock_offset,
|
||||||
|
int32_t header_offset,
|
||||||
|
int32_t entries_offset)
|
||||||
|
{
|
||||||
|
struct cbfs_header *header;
|
||||||
|
struct cbfs_file *entry;
|
||||||
|
uint32_t cbfs_len;
|
||||||
|
|
||||||
|
DEBUG("cbfs_image_create: bootblock=0x%x+0x%zx, "
|
||||||
|
"header=0x%x+0x%zx, entries_offset=0x%x\n",
|
||||||
|
bootblock_offset, bootblock->size,
|
||||||
|
header_offset, sizeof(*header), entries_offset);
|
||||||
|
|
||||||
|
if (buffer_create(&image->buffer, size, "(new)") != 0)
|
||||||
|
return -1;
|
||||||
|
image->header = NULL;
|
||||||
|
memset(image->buffer.data, CBFS_CONTENT_DEFAULT_VALUE, size);
|
||||||
|
|
||||||
|
// Adjust legcay top-aligned address to ROM offset.
|
||||||
|
if (IS_TOP_ALIGNED_ADDRESS(entries_offset))
|
||||||
|
entries_offset += (int32_t)size;
|
||||||
|
if (IS_TOP_ALIGNED_ADDRESS(bootblock_offset))
|
||||||
|
bootblock_offset += (int32_t)size;
|
||||||
|
if (IS_TOP_ALIGNED_ADDRESS(header_offset))
|
||||||
|
header_offset += (int32_t) size;
|
||||||
|
|
||||||
|
DEBUG("cbfs_create_image: (real offset) bootblock=0x%x, "
|
||||||
|
"header=0x%x, entries_offset=0x%x\n",
|
||||||
|
bootblock_offset, header_offset, entries_offset);
|
||||||
|
|
||||||
|
if (align == 0)
|
||||||
|
align = 64; // default align size.
|
||||||
|
|
||||||
|
// Prepare bootblock
|
||||||
|
if (bootblock_offset + bootblock->size > size) {
|
||||||
|
ERROR("Bootblock (0x%x+0x%zx) exceed ROM size (0x%zx)\n",
|
||||||
|
bootblock_offset, bootblock->size, size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(image->buffer.data + bootblock_offset, bootblock->data,
|
||||||
|
bootblock->size);
|
||||||
|
|
||||||
|
// Prepare header
|
||||||
|
if (header_offset + sizeof(*header) > size) {
|
||||||
|
ERROR("Header (0x%x+0x%zx) exceed ROM size (0x%zx)\n",
|
||||||
|
header_offset, sizeof(*header), size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
header = (struct cbfs_header *)(image->buffer.data + header_offset);
|
||||||
|
image->header = header;
|
||||||
|
header->magic = htonl(CBFS_HEADER_MAGIC);
|
||||||
|
header->version = htonl(CBFS_HEADER_VERSION);
|
||||||
|
header->romsize = htonl(size);
|
||||||
|
header->bootblocksize = htonl(bootblock->size);
|
||||||
|
header->align = htonl(align);
|
||||||
|
header->offset = htonl(entries_offset);
|
||||||
|
header->architecture = htonl(arch);
|
||||||
|
|
||||||
|
// Prepare entries
|
||||||
|
if (align_up(entries_offset, align) != entries_offset) {
|
||||||
|
ERROR("Offset (0x%x) must be aligned to 0x%x.\n",
|
||||||
|
entries_offset, align);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (entries_offset + sizeof(*entry) > size) {
|
||||||
|
ERROR("Offset (0x%x+0x%zx) exceed ROM size(0x%zx)\n",
|
||||||
|
entries_offset, sizeof(*entry), size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
entry = (struct cbfs_file *)(image->buffer.data + entries_offset);
|
||||||
|
// To calculate available length, find
|
||||||
|
// e = min(bootblock, header, size) where e > entries_offset.
|
||||||
|
cbfs_len = size;
|
||||||
|
if (bootblock_offset > entries_offset && bootblock_offset < cbfs_len)
|
||||||
|
cbfs_len = bootblock_offset;
|
||||||
|
if (header_offset > entries_offset && header_offset < cbfs_len)
|
||||||
|
cbfs_len = header_offset;
|
||||||
|
cbfs_len -= entries_offset + align;
|
||||||
|
cbfs_create_empty_entry(image, entry, cbfs_len, "");
|
||||||
|
LOG("Created CBFS image (capacity = %d bytes)\n", cbfs_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cbfs_image_from_file(struct cbfs_image *image, const char *filename) {
|
int cbfs_image_from_file(struct cbfs_image *image, const char *filename) {
|
||||||
if (buffer_from_file(&image->buffer, filename) != 0)
|
if (buffer_from_file(&image->buffer, filename) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "cbfs.h"
|
#include "cbfs.h"
|
||||||
|
|
||||||
|
#define IS_TOP_ALIGNED_ADDRESS(x) ((uint32_t)(x) > 0x80000000)
|
||||||
|
|
||||||
/* CBFS image processing */
|
/* CBFS image processing */
|
||||||
|
|
||||||
struct cbfs_image {
|
struct cbfs_image {
|
||||||
@ -29,6 +31,20 @@ struct cbfs_image {
|
|||||||
struct cbfs_header *header;
|
struct cbfs_header *header;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Creates an empty CBFS image by given size, and description to its content
|
||||||
|
* (bootblock, align, header location, starting offset of CBFS entries.
|
||||||
|
* The output image will contain a valid cbfs_header, with one cbfs_file
|
||||||
|
* entry with type CBFS_COMPONENT_NULL, with max available size.
|
||||||
|
* Returns 0 on success, otherwise none-zero. */
|
||||||
|
int cbfs_image_create(struct cbfs_image *image,
|
||||||
|
uint32_t arch,
|
||||||
|
size_t size,
|
||||||
|
uint32_t align,
|
||||||
|
struct buffer *bootblock,
|
||||||
|
int32_t bootblock_offset,
|
||||||
|
int32_t header_offset,
|
||||||
|
int32_t entries_offset);
|
||||||
|
|
||||||
/* Loads a CBFS image from file. Returns 0 on success, otherwise non-zero. */
|
/* Loads a CBFS image from file. Returns 0 on success, otherwise non-zero. */
|
||||||
int cbfs_image_from_file(struct cbfs_image *image, const char *filename);
|
int cbfs_image_from_file(struct cbfs_image *image, const char *filename);
|
||||||
|
|
||||||
|
@ -43,7 +43,10 @@ static struct param {
|
|||||||
char *bootblock;
|
char *bootblock;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t baseaddress;
|
uint32_t baseaddress;
|
||||||
|
uint32_t baseaddress_assigned;
|
||||||
uint32_t loadaddress;
|
uint32_t loadaddress;
|
||||||
|
uint32_t headeroffset;
|
||||||
|
uint32_t headeroffset_assigned;
|
||||||
uint32_t entrypoint;
|
uint32_t entrypoint;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t alignment;
|
uint32_t alignment;
|
||||||
@ -343,23 +346,72 @@ static int cbfs_remove(void)
|
|||||||
|
|
||||||
static int cbfs_create(void)
|
static int cbfs_create(void)
|
||||||
{
|
{
|
||||||
|
struct cbfs_image image;
|
||||||
|
struct buffer bootblock;
|
||||||
|
|
||||||
if (param.size == 0) {
|
if (param.size == 0) {
|
||||||
ERROR("You need to specify a valid -s/--size.\n");
|
ERROR("You need to specify a valid -s/--size.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!param.bootblock) {
|
if (!param.bootblock) {
|
||||||
ERROR("You need to specify -b/--bootblock.\n");
|
ERROR("You need to specify -B/--bootblock.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Remove arch or pack into param.
|
||||||
if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
|
if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
|
||||||
ERROR("You need to specify -m/--machine arch\n");
|
ERROR("You need to specify -m/--machine arch\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create_cbfs_image(param.cbfs_name, param.size, param.bootblock,
|
if (buffer_from_file(&bootblock, param.bootblock) != 0) {
|
||||||
param.alignment, param.offset);
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup default boot offset and header offset.
|
||||||
|
if (!param.baseaddress_assigned) {
|
||||||
|
// put boot block before end of ROM.
|
||||||
|
param.baseaddress = param.size - bootblock.size;
|
||||||
|
DEBUG("bootblock in end of ROM.\n");
|
||||||
|
}
|
||||||
|
if (!param.headeroffset_assigned) {
|
||||||
|
// Put header before bootblock, and make a reference in end of
|
||||||
|
// bootblock.
|
||||||
|
param.headeroffset = (
|
||||||
|
param.baseaddress -
|
||||||
|
sizeof(struct cbfs_header));
|
||||||
|
if (bootblock.size >= sizeof(uint32_t)) {
|
||||||
|
// TODO this only works for 32b top-aligned system now...
|
||||||
|
uint32_t ptr = param.headeroffset - param.size;
|
||||||
|
uint32_t *sig = (uint32_t *)(bootblock.data +
|
||||||
|
bootblock.size -
|
||||||
|
sizeof(ptr));
|
||||||
|
*sig = ptr;
|
||||||
|
DEBUG("CBFS header reference in end of bootblock.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbfs_image_create(&image,
|
||||||
|
arch,
|
||||||
|
param.size,
|
||||||
|
param.alignment,
|
||||||
|
&bootblock,
|
||||||
|
param.baseaddress,
|
||||||
|
param.headeroffset,
|
||||||
|
param.offset) != 0) {
|
||||||
|
ERROR("Failed to create %s.\n", param.cbfs_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
buffer_delete(&bootblock);
|
||||||
|
|
||||||
|
if (cbfs_image_write_file(&image, param.cbfs_name) != 0) {
|
||||||
|
ERROR("Failed to write %s.\n", param.cbfs_name);
|
||||||
|
cbfs_image_delete(&image);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cbfs_image_delete(&image);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cbfs_locate(void)
|
static int cbfs_locate(void)
|
||||||
@ -458,7 +510,7 @@ static const struct command commands[] = {
|
|||||||
{"add-stage", "f:n:t:c:b:vh?", cbfs_add_stage},
|
{"add-stage", "f:n:t:c:b:vh?", cbfs_add_stage},
|
||||||
{"add-flat-binary", "f:n:l:e:c:b:vh?", cbfs_add_flat_binary},
|
{"add-flat-binary", "f:n:l:e:c:b:vh?", cbfs_add_flat_binary},
|
||||||
{"remove", "n:vh?", cbfs_remove},
|
{"remove", "n:vh?", cbfs_remove},
|
||||||
{"create", "s:B:a:o:m:vh?", cbfs_create},
|
{"create", "s:B:b:H:a:o:m:vh?", cbfs_create},
|
||||||
{"locate", "f:n:a:Tvh?", cbfs_locate},
|
{"locate", "f:n:a:Tvh?", cbfs_locate},
|
||||||
{"print", "vh?", cbfs_print},
|
{"print", "vh?", cbfs_print},
|
||||||
{"extract", "n:f:vh?", cbfs_extract},
|
{"extract", "n:f:vh?", cbfs_extract},
|
||||||
@ -579,6 +631,10 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
param.baseaddress = strtoul(optarg, NULL, 0);
|
param.baseaddress = strtoul(optarg, NULL, 0);
|
||||||
|
// baseaddress may be zero on non-x86, so we
|
||||||
|
// need an explicit "baseaddress_assigned".
|
||||||
|
param.baseaddress = strtoul(optarg, NULL, 0);
|
||||||
|
param.baseaddress_assigned = 1;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
param.loadaddress = strtoul(optarg, NULL, 0);
|
param.loadaddress = strtoul(optarg, NULL, 0);
|
||||||
@ -598,6 +654,11 @@ int main(int argc, char **argv)
|
|||||||
case 'B':
|
case 'B':
|
||||||
param.bootblock = optarg;
|
param.bootblock = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'H':
|
||||||
|
param.headeroffset = strtoul(
|
||||||
|
optarg, NULL, 0);
|
||||||
|
param.headeroffset_assigned = 1;
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
param.alignment = strtoul(optarg, NULL, 0);
|
param.alignment = strtoul(optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user