Stefan Reinauer (stefan.reina...@coreboot.org) just uploaded a new patch set to 
gerrit, which you can find at http://review.coreboot.org/2214

-gerrit

commit 31bd2dc2eac41f1ab266832ca74be60935bee910
Author: Hung-Te Lin <hun...@chromium.org>
Date:   Tue Jan 29 09:45:12 2013 +0800

    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 <hun...@chromium.org>
---
 src/arch/armv7/Makefile.inc |  3 +-
 util/cbfstool/cbfs_image.c  | 88 +++++++++++++++++++++++++++++++++++++++++++++
 util/cbfstool/cbfs_image.h  | 16 +++++++++
 util/cbfstool/cbfstool.c    | 69 ++++++++++++++++++++++++++++++++---
 4 files changed, 171 insertions(+), 5 deletions(-)

diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc
index 715ce1e..f2f4a47 100644
--- a/src/arch/armv7/Makefile.inc
+++ b/src/arch/armv7/Makefile.inc
@@ -45,9 +45,10 @@ prebuild-files = \
        $(if $(call extract_nth,4,$(file)),-b $(call extract_nth,4,$(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)
        $(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
        mv $@.tmp $@
 else
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
index 2f38cec..83e8a9d 100644
--- a/util/cbfstool/cbfs_image.c
+++ b/util/cbfstool/cbfs_image.c
@@ -130,6 +130,94 @@ static int cbfs_fix_legacy_size(struct cbfs_image *image) {
        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) {
        if (buffer_from_file(&image->buffer, filename) != 0)
                return -1;
diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h
index d99bee8..5e1c871 100644
--- a/util/cbfstool/cbfs_image.h
+++ b/util/cbfstool/cbfs_image.h
@@ -22,6 +22,8 @@
 #include "common.h"
 #include "cbfs.h"
 
+#define IS_TOP_ALIGNED_ADDRESS(x)      ((uint32_t)(x) > 0x80000000)
+
 /* CBFS image processing */
 
 struct cbfs_image {
@@ -29,6 +31,20 @@ struct cbfs_image {
        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. */
 int cbfs_image_from_file(struct cbfs_image *image, const char *filename);
 
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c
index 98f6b62..2aa1df0 100644
--- a/util/cbfstool/cbfstool.c
+++ b/util/cbfstool/cbfstool.c
@@ -43,7 +43,10 @@ static struct param {
        char *bootblock;
        uint32_t type;
        uint32_t baseaddress;
+       uint32_t baseaddress_assigned;
        uint32_t loadaddress;
+       uint32_t headeroffset;
+       uint32_t headeroffset_assigned;
        uint32_t entrypoint;
        uint32_t size;
        uint32_t alignment;
@@ -343,23 +346,72 @@ static int cbfs_remove(void)
 
 static int cbfs_create(void)
 {
+       struct cbfs_image image;
+       struct buffer bootblock;
+
        if (param.size == 0) {
                ERROR("You need to specify a valid -s/--size.\n");
                return 1;
        }
 
        if (!param.bootblock) {
-               ERROR("You need to specify -b/--bootblock.\n");
+               ERROR("You need to specify -B/--bootblock.\n");
                return 1;
        }
 
+       // TODO Remove arch or pack into param.
        if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
                ERROR("You need to specify -m/--machine arch\n");
                return 1;
        }
 
-       return create_cbfs_image(param.cbfs_name, param.size, param.bootblock,
-                                               param.alignment, param.offset);
+       if (buffer_from_file(&bootblock, param.bootblock) != 0) {
+               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)
@@ -458,7 +510,7 @@ static const struct command commands[] = {
        {"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},
        {"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},
        {"print", "vh?", cbfs_print},
        {"extract", "n:f:vh?", cbfs_extract},
@@ -579,6 +631,10 @@ int main(int argc, char **argv)
                                break;
                        case 'b':
                                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;
                        case 'l':
                                param.loadaddress = strtoul(optarg, NULL, 0);
@@ -598,6 +654,11 @@ int main(int argc, char **argv)
                        case 'B':
                                param.bootblock = optarg;
                                break;
+                       case 'H':
+                               param.headeroffset = strtoul(
+                                               optarg, NULL, 0);
+                               param.headeroffset_assigned = 1;
+                               break;
                        case 'a':
                                param.alignment = strtoul(optarg, NULL, 0);
                                break;

-- 
coreboot mailing list: coreboot@coreboot.org
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to