the following patch was just integrated into master:
commit 023e8294236d3bd7e39b7af0a4929137c30f089d
Author: Sol Boucher <solb(a)chromium.org>
Date: Wed Mar 18 10:13:48 2015 -0700
fmaptool: Add listing of annotated CBFS sections and generate header
The fmd compiler now processes "(CBFS)" annotations, distilling them
into a comma-separated list of the names of sections containing
CBFSes. This list is the only thing printed to standard output to
enable easy capture and machine consumption by other tools.
Additionally, the ability to generate a tiny header with a define for
the primary CBFS's size is implemented and can be requested via a
new command-line switch.
Here's an example of how to use the new features:
$ ./fmaptool -h layout.h layout_arm_8192.fmd layout.fmap 2>/dev/null
FW_MAIN_A,FW_MAIN_B,COREBOOT
The hypothetical fmd file contains three sections annotated as (CBFS),
the names of which are printed to standard output. As before, a binary
FMAP file named layout.fmap is created; however, because the command
was invoked with -h, a header #define ing the offset of its FMAP
section (i.e. where it will be relative to the base of flash once the
boot image is assembled) is also generated.
BUG=chromium:470407
TEST=Verify that fmd files without a "COREBOOT" section or with one
that isn't annotated as "(CBFS)" are not accepted. Ensure that the
list of CBFS sections matches the descriptor file's annotations and
is led by the "COREBOOT" section. Invoke with the header generation
switch and check that output file for reasonableness.
BRANCH=None
Change-Id: I496dd937f69467bfd9233c28df59c7608e89538f
Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Commit-Id: 9227698adecf675770b2983380eb570676c2b5d2
Original-Change-Id: I8b32f6ef19cabe2f6760106e676683c4565bbaad
Original-Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/262956
Original-Reviewed-by: Duncan Laurie <dlaurie(a)chromium.org>
Original-Reviewed-by: Julius Werner <jwerner(a)chromium.org>
Reviewed-on: http://review.coreboot.org/9967
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi(a)google.com>
See http://review.coreboot.org/9967 for details.
-gerrit
the following patch was just integrated into master:
commit b974081c13ad203a78fcdb28021706f55eaa5010
Author: Sol Boucher <solb(a)chromium.org>
Date: Wed Mar 18 10:13:48 2015 -0700
fmaptool: Conform to cbfstool's error message format
The tool now makes use of the ERROR() macros from common.h.
Change-Id: Ie38f40c65f7b6d3bc2adb97e246224cd38d4cb99
Signed-off-by: Sol Boucher <solb(a)chromium.org>
Reviewed-on: http://review.coreboot.org/10048
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter(a)users.sourceforge.net>
Reviewed-by: Patrick Georgi <pgeorgi(a)google.com>
See http://review.coreboot.org/10048 for details.
-gerrit
Sol Boucher (solb(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10136
-gerrit
commit 88470ed6bedd167f339d5bfbc88114f2f8ed5517
Author: Sol Boucher <solb(a)chromium.org>
Date: Thu May 7 02:39:22 2015 -0700
cbfstool: Support top-aligned addresses for new-format images
The cbfstool handling of new-style FMAP-driven "partitioned" images
originally disallowed the use of x86-style top-aligned addresses with
the add.* and layout actions because it wasn't obvious how they should
work, especially since the normal addressing is done relative to each
individual region for these types of images. Not surprisingly,
however, the x86 portions of the build system make copious use of
top-aligned addresses, so this allows their use with new images and
specifies their behavior as being relative to the *image* end---not
the region end---just as it is for legacy images.
Change-Id: Icecc843f4f8b6bb52aa0ea16df771faa278228d2
Signed-off-by: Sol Boucher <solb(a)chromium.org>
---
util/cbfstool/cbfs_image.c | 19 ++++++------------
util/cbfstool/cbfs_image.h | 4 +---
util/cbfstool/cbfstool.c | 43 ++++++++++++++++++++++++++++++----------
util/cbfstool/common.h | 2 ++
util/cbfstool/partitioned_file.c | 7 +++++++
util/cbfstool/partitioned_file.h | 3 +++
6 files changed, 52 insertions(+), 26 deletions(-)
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
index 4ecb461..8fb2a60 100644
--- a/util/cbfstool/cbfs_image.c
+++ b/util/cbfstool/cbfs_image.c
@@ -526,6 +526,12 @@ static int cbfs_add_entry_at(struct cbfs_image *image,
int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer,
const char *name, uint32_t type, uint32_t content_offset)
{
+ assert(image);
+ assert(buffer);
+ assert(buffer->data);
+ assert(name);
+ assert(!IS_TOP_ALIGNED_ADDRESS(content_offset));
+
uint32_t entry_type;
uint32_t addr, addr_next;
struct cbfs_file *entry, *next;
@@ -537,19 +543,6 @@ int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer,
DEBUG("cbfs_add_entry('%s'@0x%x) => need_size = %u+%zu=%u\n",
name, content_offset, header_size, buffer->size, need_size);
- if (IS_TOP_ALIGNED_ADDRESS(content_offset)) {
- if (!cbfs_is_legacy_cbfs(image)) {
- ERROR("Top-aligned offsets are only supported for legacy CBFSes (with master headers)\n");
- return -1;
- }
-
- // legacy cbfstool takes top-aligned address.
- uint32_t theromsize = image->header.romsize;
- INFO("Converting top-aligned address 0x%x to offset: 0x%x\n",
- content_offset, content_offset + theromsize);
- content_offset = theromsize + (int32_t)content_offset;
- }
-
// Merge empty entries.
DEBUG("(trying to merge empty entries...)\n");
cbfs_walk(image, cbfs_merge_empty_entry, NULL);
diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h
index 024edc5..5ff8a9a 100644
--- a/util/cbfstool/cbfs_image.h
+++ b/util/cbfstool/cbfs_image.h
@@ -22,8 +22,6 @@
#include "common.h"
#include "cbfs.h"
-#define IS_TOP_ALIGNED_ADDRESS(x) ((uint32_t)(x) > 0x80000000)
-
/* CBFS image processing */
struct cbfs_image {
@@ -88,7 +86,7 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
/* Adds an entry to CBFS image by given name and type. If content_offset is
* non-zero, try to align "content" (CBFS_SUBHEADER(p)) at content_offset.
- * Note that top-aligned addresses are only supported for legacy CBFSes.
+ * Never pass this function a top-aligned address: convert it to an offset.
* Returns 0 on success, otherwise non-zero. */
int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer,
const char *name, uint32_t type, uint32_t content_offset);
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c
index cb2f01a..36e27c6 100644
--- a/util/cbfstool/cbfstool.c
+++ b/util/cbfstool/cbfstool.c
@@ -98,6 +98,21 @@ static bool region_is_modern_cbfs(const char *region)
CBFS_FILE_MAGIC, strlen(CBFS_FILE_MAGIC));
}
+/*
+ * Converts between offsets from the start of the specified image region and
+ * "top-aligned" offsets from the top of the entire flash image. Works in either
+ * direction: pass in one type of offset and receive the other type.
+ * N.B. A top-aligned offset is always a positive number, and should not be
+ * confused with a top-aliged *address*, which is its arithmetic inverse. */
+static unsigned convert_to_from_top_aligned(const struct buffer *region,
+ unsigned offset)
+{
+ assert(region);
+
+ size_t image_size = partitioned_file_total_size(param.image_file);
+ return image_size - region->offset - offset;
+}
+
typedef int (*convert_buffer_t)(struct buffer *buffer, uint32_t *offset);
static int cbfs_add_integer_component(const char *name,
@@ -129,6 +144,10 @@ static int cbfs_add_integer_component(const char *name,
goto done;
}
+ if (IS_TOP_ALIGNED_ADDRESS(offset))
+ offset = convert_to_from_top_aligned(param.image_region,
+ -offset);
+
if (cbfs_add_entry(&image, &buffer, name, CBFS_COMPONENT_RAW, offset) !=
0) {
ERROR("Failed to add %llu into ROM image as '%s'.\n",
@@ -187,6 +206,10 @@ static int cbfs_add_component(const char *filename,
return 1;
}
+ if (IS_TOP_ALIGNED_ADDRESS(offset))
+ offset = convert_to_from_top_aligned(param.image_region,
+ -offset);
+
if (cbfs_add_entry(&image, &buffer, name, type, offset) != 0) {
ERROR("Failed to add '%s' into ROM image.\n", filename);
buffer_delete(&buffer);
@@ -439,11 +462,6 @@ static int cbfs_locate(void)
param.headeroffset))
return 1;
- if (!cbfs_is_legacy_cbfs(&image) && param.top_aligned) {
- ERROR("The -T switch is only valid on legacy images having CBFS master headers\n");
- return 1;
- }
-
if (cbfs_get_entry(&image, param.name))
WARN("'%s' already in CBFS.\n", param.name);
@@ -464,7 +482,8 @@ static int cbfs_locate(void)
}
if (param.top_aligned)
- address = address - image.header.romsize;
+ address = -convert_to_from_top_aligned(param.image_region,
+ address);
printf("0x%x\n", address);
return 0;
@@ -806,7 +825,7 @@ static void usage(char *name)
"USAGE:\n" " %s [-h]\n"
" %s FILE COMMAND [-v] [PARAMETERS]...\n\n" "OPTIONs:\n"
" -H header_offset Do not search for header; use this offset*\n"
- " -T Output top-aligned memory address*\n"
+ " -T Output top-aligned memory address\n"
" -u Accept short data; fill upward/from bottom\n"
" -d Accept short data; fill downward/from top\n"
" -v Provide verbose output\n"
@@ -857,8 +876,8 @@ static void usage(char *name)
"Updates the FIT table with microcode entries\n"
"\n"
"OFFSETs:\n"
- " Numbers accompanying -b, -H, and -o switches may be provided\n"
- " in two possible formats*: if their value is greater than\n"
+ " Numbers accompanying -b, -H, and -o switches* may be provided\n"
+ " in two possible formats: if their value is greater than\n"
" 0x80000000, they are interpreted as a top-aligned x86 memory\n"
" address; otherwise, they are treated as an offset into flash.\n"
"ARCHes:\n"
@@ -878,7 +897,11 @@ static void usage(char *name)
" that, when working with such images, the -F and -r switches\n"
" default to '%s' for convenience, and both the -b switch to\n"
" CBFS operations and the output of the locate action become\n"
- " relative to the selected CBFS region's lowest address.\n",
+ " relative to the selected CBFS region's lowest address.\n"
+ " The one exception to this rule is the top-aligned address,\n"
+ " which is always relative to the end of the entire image\n"
+ " rather than relative to the local region; this is true for\n"
+ " for both input (sufficiently large) and output (-T) data.\n",
SECTION_NAME_FMAP, SECTION_NAME_PRIMARY_CBFS,
SECTION_NAME_PRIMARY_CBFS
);
diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h
index 831d3eb..392ec80 100644
--- a/util/cbfstool/common.h
+++ b/util/cbfstool/common.h
@@ -50,6 +50,8 @@ extern int verbose;
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define IS_TOP_ALIGNED_ADDRESS(x) ((uint32_t)(x) > 0x80000000)
+
#define unused __attribute__((unused))
static inline uint32_t align_up(uint32_t value, uint32_t align)
diff --git a/util/cbfstool/partitioned_file.c b/util/cbfstool/partitioned_file.c
index 6473963..0b25272 100644
--- a/util/cbfstool/partitioned_file.c
+++ b/util/cbfstool/partitioned_file.c
@@ -290,6 +290,13 @@ bool partitioned_file_is_partitioned(const partitioned_file_t *file)
return partitioned_file_get_fmap(file) != NULL;
}
+size_t partitioned_file_total_size(const partitioned_file_t *file)
+{
+ assert(file);
+
+ return file->buffer.size;
+}
+
bool partitioned_file_region_check_magic(const partitioned_file_t *file,
const char *region, const char *magic, size_t magic_len)
{
diff --git a/util/cbfstool/partitioned_file.h b/util/cbfstool/partitioned_file.h
index 97d1b57..92f228e 100644
--- a/util/cbfstool/partitioned_file.h
+++ b/util/cbfstool/partitioned_file.h
@@ -133,6 +133,9 @@ void partitioned_file_close(partitioned_file_t *file);
/** @return Whether the file is partitioned (i.e. not flat). */
bool partitioned_file_is_partitioned(const partitioned_file_t *file);
+/** @return The image's overall filesize, regardless of whether it's flat. */
+size_t partitioned_file_total_size(const partitioned_file_t *file);
+
/** @return Whether the specified region begins with the magic bytes. */
bool partitioned_file_region_check_magic(const partitioned_file_t *file,
const char *region, const char *magic, size_t magic_len);
the following patch was just integrated into master:
commit e3260a042f438cedb446c5e7b3dc6f55a3b9aa95
Author: Sol Boucher <solb(a)chromium.org>
Date: Wed Mar 25 13:40:08 2015 -0700
cbfstool: Restructure around support for reading/writing portions of files
The buffer API that cbfstool uses to read and write files only directly supports
one-shot operations on whole files. This adds an intermediate partitioned_file
module that sits on top of the buffer system and has an awareness of FMAP
entries. It provides an easy way to get a buffer for an individual region of a
larger image file based on FMAP section name, as well as incrementally write
those smaller buffers back to the backing file at the appropriate offset. The
module has two distinct modes of operation:
- For new images whose layout is described exclusively by an FMAP section, all
the aforementioned functionality will be available.
- For images in the current format, where the CBFS master header serves as the
root of knowledge of the image's size and layout, the module falls back to a
legacy operation mode, where it only allows manipulation of the entire image
as one unit, but exposes this support through the same interface by mapping
the region named SECTION_NAME_PRIMARY_CBFS ("COREBOOT") to the whole file.
The tool is presently only ported onto the new module running in legacy mode:
higher-level support for true "partitioned" images will be forthcoming. However,
as part of this change, the crusty cbfs_image_from_file() and
cbfs_image_write_file() abstractions are removed and replaced with a single
cbfs_image function, cbfs_image_from_buffer(), as well as centralized image
reading/writing directly in cbfstool's main() function. This reduces the
boilerplate required to implement each new action, makes the create action much
more similar to the others, and will make implementing additional actions and
adding in support for the new format much easier.
BUG=chromium:470407
TEST=Build panther and nyan_big coreboot.rom images with and without this patch
and diff their hexdumps. Ensure that no differences occur at different locations
from the diffs between subsequent builds of an identical source tree. Then flash
a full new build onto nyan_big and watch it boot normally.
BRANCH=None
Change-Id: I25578c7b223bc8434c3074cb0dd8894534f8c500
Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Commit-Id: 7e1c96a48e7a27fc6b90289d35e6e169d5e7ad20
Original-Change-Id: Ia4a1a4c48df42b9ec2d6b9471b3a10eb7b24bb39
Original-Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/265581
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Reviewed-on: http://review.coreboot.org/10134
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi(a)google.com>
See http://review.coreboot.org/10134 for details.
-gerrit
the following patch was just integrated into master:
commit 64c6cd73f3567e893a9cde7d08eb5505c1a19c62
Author: Sol Boucher <solb(a)chromium.org>
Date: Sun Apr 26 02:32:43 2015 -0700
cbfstool: Add offset field to cbfstool directory's struct buffer
This allows calls to buffer_delete() to work on a buffer that has been
buffer_seek()ed or the buffer created by a buffer_splice(). The same
information could also be useful for other purposes, such as writing
slices back to a file at the offset they originally occupied.
BUG=chromium:470407
TEST=Attempt to perform the following sequence of buffer actions, then run it
through valgrind to check for memory errors:
for (int pos = 0; pos <= 3; ++pos) {
struct buffer seek_test;
buffer_create(&seek_test, 3, "seek_test");
if (pos == 0) {
buffer_delete(&seek_test);
continue;
}
buffer_seek(&seek_test, 1);
if (pos == 1) {
buffer_delete(&seek_test);
continue;
}
buffer_seek(&seek_test, 1);
if (pos == 2) {
buffer_delete(&seek_test);
continue;
}
buffer_seek(&seek_test, 1);
if (pos == 3) {
buffer_delete(&seek_test);
continue;
}
}
for (int pos = 0; pos <= 14; ++pos) {
struct buffer slice_test;
buffer_create(&slice_test, 3, "slice_test");
if (pos == 0) {
buffer_delete(&slice_test);
continue;
}
struct buffer sliced_once;
buffer_splice(&sliced_once, &slice_test, 1, 2);
if (pos == 1) {
buffer_delete(&slice_test);
continue;
}
if (pos == 2) {
buffer_delete(&sliced_once);
continue;
}
struct buffer sliced_twice;
buffer_splice(&sliced_twice, &sliced_once, 2, 1);
if (pos == 3) {
buffer_delete(&slice_test);
continue;
}
if (pos == 4) {
buffer_delete(&sliced_once);
continue;
}
if (pos == 5) {
buffer_delete(&sliced_twice);
continue;
}
struct buffer sliced_same;
buffer_splice(&sliced_same, &slice_test, 1, 1);
if (pos == 6) {
buffer_delete(&slice_test);
continue;
}
if (pos == 7) {
buffer_delete(&sliced_once);
continue;
}
if (pos == 8) {
buffer_delete(&sliced_twice);
continue;
}
if (pos == 9) {
buffer_delete(&sliced_same);
continue;
}
struct buffer sliced_thrice;
buffer_splice(&sliced_thrice, &sliced_twice, 1, 0);
if (pos == 10) {
buffer_delete(&slice_test);
continue;
}
if (pos == 11) {
buffer_delete(&sliced_once);
continue;
}
if (pos == 12) {
buffer_delete(&sliced_twice);
continue;
}
if (pos == 13) {
buffer_delete(&sliced_same);
continue;
}
if (pos == 14) {
buffer_delete(&sliced_thrice);
continue;
}
}
BRANCH=None
Change-Id: Id67734654a62302c0de37746d8a978d49b240505
Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi(a)google.com>
See http://review.coreboot.org/10133 for details.
-gerrit