2009-09-14 15:29:27 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2009 coresystems GmbH
|
|
|
|
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
2012-11-16 23:48:22 +01:00
|
|
|
* Copyright (C) 2012 Google, Inc.
|
2009-09-14 15:29:27 +02:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; version 2 of the License.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
Remove address from GPLv2 headers
As per discussion with lawyers[tm], it's not a good idea to
shorten the license header too much - not for legal reasons
but because there are tools that look for them, and giving
them a standard pattern simplifies things.
However, we got confirmation that we don't have to update
every file ever added to coreboot whenever the FSF gets a
new lease, but can drop the address instead.
util/kconfig is excluded because that's imported code that
we may want to synchronize every now and then.
$ find * -type f -exec sed -i "s:Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *MA[, ]*02110-1301[, ]*USA:Foundation, Inc.:" {} +
$ find * -type f -exec sed -i "s:Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA:Foundation, Inc.:" {} +
$ find * -type f -exec sed -i "s:Foundation, Inc., 59 Temple Place[-, ]*Suite 330, Boston, MA *02111-1307[, ]*USA:Foundation, Inc.:" {} +
$ find * -type f -exec sed -i "s:Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.:Foundation, Inc.:" {} +
$ find * -type f
-a \! -name \*.patch \
-a \! -name \*_shipped \
-a \! -name LICENSE_GPL \
-a \! -name LGPL.txt \
-a \! -name COPYING \
-a \! -name DISCLAIMER \
-exec sed -i "/Foundation, Inc./ N;s:Foundation, Inc.* USA\.* *:Foundation, Inc. :;s:Foundation, Inc. $:Foundation, Inc.:" {} +
Change-Id: Icc968a5a5f3a5df8d32b940f9cdb35350654bef9
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Reviewed-on: http://review.coreboot.org/9233
Tested-by: build bot (Jenkins)
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
2015-03-26 15:17:45 +01:00
|
|
|
* Foundation, Inc.
|
2009-09-14 15:29:27 +02:00
|
|
|
*/
|
|
|
|
|
2012-10-30 00:52:36 +01:00
|
|
|
#ifndef __CBFSTOOL_COMMON_H
|
|
|
|
#define __CBFSTOOL_COMMON_H
|
|
|
|
|
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@chromium.org>
Original-Commit-Id: 7e1c96a48e7a27fc6b90289d35e6e169d5e7ad20
Original-Change-Id: Ia4a1a4c48df42b9ec2d6b9471b3a10eb7b24bb39
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/265581
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10134
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-03-25 21:40:08 +01:00
|
|
|
#include <stdbool.h>
|
2015-02-26 20:47:19 +01:00
|
|
|
#include <stddef.h>
|
2009-09-14 15:29:27 +02:00
|
|
|
#include <stdint.h>
|
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@chromium.org>
Original-Commit-Id: 7e1c96a48e7a27fc6b90289d35e6e169d5e7ad20
Original-Change-Id: Ia4a1a4c48df42b9ec2d6b9471b3a10eb7b24bb39
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/265581
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10134
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-03-25 21:40:08 +01:00
|
|
|
#include <string.h>
|
2013-01-29 17:43:46 +01:00
|
|
|
#include <assert.h>
|
2013-01-28 08:53:34 +01:00
|
|
|
|
|
|
|
/* Endianess */
|
2011-10-21 23:24:57 +02:00
|
|
|
#include "swab.h"
|
2009-09-14 15:29:27 +02:00
|
|
|
|
2013-01-28 07:39:43 +01:00
|
|
|
/* Message output */
|
|
|
|
extern int verbose;
|
2015-03-06 00:38:03 +01:00
|
|
|
#define ERROR(...) { fprintf(stderr, "E: " __VA_ARGS__); }
|
|
|
|
#define WARN(...) { fprintf(stderr, "W: " __VA_ARGS__); }
|
|
|
|
#define LOG(...) { fprintf(stderr, __VA_ARGS__); }
|
|
|
|
#define INFO(...) { if (verbose > 0) fprintf(stderr, "INFO: " __VA_ARGS__); }
|
|
|
|
#define DEBUG(...) { if (verbose > 1) fprintf(stderr, "DEBUG: " __VA_ARGS__); }
|
2013-01-28 07:39:43 +01:00
|
|
|
|
2015-03-04 00:55:03 +01:00
|
|
|
/* Helpers */
|
|
|
|
#define ARRAY_SIZE(a) (int)(sizeof(a) / sizeof((a)[0]))
|
|
|
|
#define ALIGN(val, by) (((val) + (by)-1)&~((by)-1))
|
cbfstool: New image format w/ required FMAP and w/o CBFS master header
These new-style firmware images use the FMAP of the root of knowledge
about their layout, which allows them to have sections containing raw
data whose offset and size can easily be determined at runtime or when
modifying or flashing the image. Furthermore, they can even have
multiple CBFSes, each of which occupies a different FMAP region. It is
assumed that the first entry of each CBFS, including the primary one,
will be located right at the start of its region. This means that the
bootblock needs to be moved into its own FMAP region, but makes the
CBFS master header obsolete because, with the exception of the version
and alignment, all its fields are redundant once its CBFS has an entry
in the FMAP. The version code will be addressed in a future commit
before the new format comes into use, while the alignment will just be
defined to 64 bytes in both cbfstool and coreboot itself, since
there's almost no reason to ever change it in practice. The version
code field and all necessary coreboot changes will come separately.
BUG=chromium:470407
TEST=Build panther and nyan_big coreboot.rom and image.bin images with
and without this patch, diff their hexdumps, and note that no
locations differ except for those that do between subsequent builds of
the same codebase. Try working with new-style images: use fmaptool to
produce an FMAP section from an fmd file having raw sections and
multiple CBFSes, pass the resulting file to cbfstool create -M -F,
then try printing its layout and CBFSes' contents, add and remove CBFS
files, and read and write raw sections.
BRANCH=None
Change-Id: I7dd2578d2143d0cedd652fdba5b22221fcc2184a
Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Commit-Id: 8a670322297f83135b929a5b20ff2bd0e7d2abd3
Original-Change-Id: Ib86fb50edc66632f4e6f717909bbe4efb6c874e5
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/265863
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10135
Tested-by: build bot (Jenkins)
2015-03-18 20:36:27 +01:00
|
|
|
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
|
|
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
2015-03-04 00:55:03 +01:00
|
|
|
|
2015-05-07 11:39:22 +02:00
|
|
|
#define IS_TOP_ALIGNED_ADDRESS(x) ((uint32_t)(x) > 0x80000000)
|
|
|
|
|
2015-03-04 00:55:03 +01:00
|
|
|
#define unused __attribute__((unused))
|
|
|
|
|
2014-11-10 22:14:24 +01:00
|
|
|
static inline uint32_t align_up(uint32_t value, uint32_t align)
|
|
|
|
{
|
|
|
|
if (value % align)
|
|
|
|
value += align - (value % align);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2013-01-29 17:43:46 +01:00
|
|
|
/* Buffer and file I/O */
|
|
|
|
struct buffer {
|
|
|
|
char *name;
|
|
|
|
char *data;
|
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@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-04-26 11:32:43 +02:00
|
|
|
size_t offset;
|
2013-01-29 17:43:46 +01:00
|
|
|
size_t size;
|
|
|
|
};
|
|
|
|
|
2014-03-05 05:01:12 +01:00
|
|
|
static inline void *buffer_get(const struct buffer *b)
|
|
|
|
{
|
|
|
|
return b->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline size_t buffer_size(const struct buffer *b)
|
|
|
|
{
|
|
|
|
return b->size;
|
|
|
|
}
|
|
|
|
|
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@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-04-26 11:32:43 +02:00
|
|
|
/*
|
|
|
|
* Shrink a buffer toward the beginning of its previous space.
|
|
|
|
* Afterward, buffer_delete() remains the means of cleaning it up. */
|
2014-03-05 05:01:12 +01:00
|
|
|
static inline void buffer_set_size(struct buffer *b, size_t size)
|
|
|
|
{
|
|
|
|
b->size = size;
|
|
|
|
}
|
|
|
|
|
2014-03-27 04:57:55 +01:00
|
|
|
/* Initialize a buffer with the given constraints. */
|
|
|
|
static inline void buffer_init(struct buffer *b, char *name, void *data,
|
|
|
|
size_t size)
|
|
|
|
{
|
|
|
|
b->name = name;
|
|
|
|
b->data = data;
|
|
|
|
b->size = size;
|
|
|
|
}
|
|
|
|
|
2015-05-06 03:25:18 +02:00
|
|
|
/* Splice a buffer into another buffer. Note that it's up to the caller to
|
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@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-04-26 11:32:43 +02:00
|
|
|
* bounds check the offset and size. The resulting buffer is backed by the same
|
|
|
|
* storage as the original, so although it is valid to buffer_delete() either
|
|
|
|
* one of them, doing so releases both simultaneously. */
|
2014-03-05 05:01:12 +01:00
|
|
|
static inline void buffer_splice(struct buffer *dest, const struct buffer *src,
|
|
|
|
size_t offset, size_t size)
|
|
|
|
{
|
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@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-04-26 11:32:43 +02:00
|
|
|
dest->name = src->name;
|
|
|
|
dest->data = src->data + offset;
|
|
|
|
dest->offset = src->offset + offset;
|
|
|
|
dest->size = size;
|
2014-03-05 05:01:12 +01:00
|
|
|
}
|
|
|
|
|
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@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-04-26 11:32:43 +02:00
|
|
|
/*
|
|
|
|
* Shallow copy a buffer. To clean up the resources, buffer_delete()
|
|
|
|
* either one, but not both. */
|
2014-03-05 05:01:12 +01:00
|
|
|
static inline void buffer_clone(struct buffer *dest, const struct buffer *src)
|
|
|
|
{
|
2015-05-06 03:25:18 +02:00
|
|
|
buffer_splice(dest, src, 0, src->size);
|
2014-03-05 05:01:12 +01:00
|
|
|
}
|
|
|
|
|
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@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-04-26 11:32:43 +02:00
|
|
|
/*
|
|
|
|
* Shrink a buffer toward the end of its previous space.
|
|
|
|
* Afterward, buffer_delete() remains the means of cleaning it up. */
|
2014-03-05 05:01:12 +01:00
|
|
|
static inline void buffer_seek(struct buffer *b, size_t size)
|
|
|
|
{
|
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@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-04-26 11:32:43 +02:00
|
|
|
b->offset += size;
|
2014-03-05 05:01:12 +01:00
|
|
|
b->size -= size;
|
|
|
|
b->data += size;
|
|
|
|
}
|
|
|
|
|
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@chromium.org>
Original-Commit-Id: 7e1c96a48e7a27fc6b90289d35e6e169d5e7ad20
Original-Change-Id: Ia4a1a4c48df42b9ec2d6b9471b3a10eb7b24bb39
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/265581
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10134
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-03-25 21:40:08 +01:00
|
|
|
/* Returns whether the buffer begins with the specified magic bytes. */
|
|
|
|
static inline bool buffer_check_magic(const struct buffer *b, const char *magic,
|
|
|
|
size_t magic_len)
|
|
|
|
{
|
|
|
|
assert(magic);
|
|
|
|
return b && b->size >= magic_len &&
|
|
|
|
memcmp(b->data, magic, magic_len) == 0;
|
|
|
|
}
|
|
|
|
|
2013-01-29 17:43:46 +01:00
|
|
|
/* Creates an empty memory buffer with given size.
|
|
|
|
* Returns 0 on success, otherwise non-zero. */
|
|
|
|
int buffer_create(struct buffer *buffer, size_t size, const char *name);
|
|
|
|
|
|
|
|
/* Loads a file into memory buffer. Returns 0 on success, otherwise non-zero. */
|
|
|
|
int buffer_from_file(struct buffer *buffer, const char *filename);
|
|
|
|
|
|
|
|
/* Writes memory buffer content into file.
|
|
|
|
* Returns 0 on success, otherwise non-zero. */
|
|
|
|
int buffer_write_file(struct buffer *buffer, const char *filename);
|
|
|
|
|
|
|
|
/* Destroys a memory buffer. */
|
|
|
|
void buffer_delete(struct buffer *buffer);
|
|
|
|
|
2013-11-13 23:34:57 +01:00
|
|
|
const char *arch_to_string(uint32_t a);
|
2012-11-16 23:48:22 +01:00
|
|
|
uint32_t string_to_arch(const char *arch_string);
|
2009-09-14 15:29:27 +02:00
|
|
|
|
2015-08-26 12:53:41 +02:00
|
|
|
/* Compress in_len bytes from in, storing the result at out, returning the
|
|
|
|
* resulting length in out_len.
|
|
|
|
* Returns 0 on error,
|
|
|
|
* != 0 otherwise, depending on the compressing function.
|
|
|
|
*/
|
|
|
|
typedef int (*comp_func_ptr) (char *in, int in_len, char *out, int *out_len);
|
|
|
|
|
|
|
|
/* Decompress in_len bytes from in, storing the result at out, up to out_len
|
|
|
|
* bytes.
|
|
|
|
* Returns 0 on error,
|
|
|
|
* != 0 otherwise, depending on the decompressing function.
|
|
|
|
*/
|
|
|
|
typedef int (*decomp_func_ptr) (char *in, int in_len, char *out, int out_len);
|
|
|
|
|
2015-05-08 06:12:28 +02:00
|
|
|
enum comp_algo { CBFS_COMPRESS_NONE = 0, CBFS_COMPRESS_LZMA = 1 };
|
2009-09-14 15:29:27 +02:00
|
|
|
|
2015-05-08 06:12:28 +02:00
|
|
|
comp_func_ptr compression_function(enum comp_algo algo);
|
2015-08-26 12:53:41 +02:00
|
|
|
decomp_func_ptr decompression_function(enum comp_algo algo);
|
2009-09-14 15:29:27 +02:00
|
|
|
|
|
|
|
uint64_t intfiletype(const char *name);
|
|
|
|
|
2013-01-28 08:04:30 +01:00
|
|
|
/* cbfs-mkpayload.c */
|
2015-03-06 00:38:03 +01:00
|
|
|
int parse_elf_to_payload(const struct buffer *input, struct buffer *output,
|
2015-05-08 06:12:28 +02:00
|
|
|
enum comp_algo algo);
|
|
|
|
int parse_fv_to_payload(const struct buffer *input, struct buffer *output,
|
|
|
|
enum comp_algo algo);
|
2013-08-27 20:22:21 +02:00
|
|
|
int parse_bzImage_to_payload(const struct buffer *input,
|
|
|
|
struct buffer *output, const char *initrd,
|
2015-05-08 06:12:28 +02:00
|
|
|
char *cmdline, enum comp_algo algo);
|
2013-01-29 08:22:11 +01:00
|
|
|
int parse_flat_binary_to_payload(const struct buffer *input,
|
|
|
|
struct buffer *output,
|
|
|
|
uint32_t loadaddress,
|
|
|
|
uint32_t entrypoint,
|
2015-05-08 06:12:28 +02:00
|
|
|
enum comp_algo algo);
|
2013-01-28 08:04:30 +01:00
|
|
|
/* cbfs-mkstage.c */
|
2013-01-29 08:22:11 +01:00
|
|
|
int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
|
2015-05-08 06:12:28 +02:00
|
|
|
enum comp_algo algo, uint32_t *location,
|
2014-10-30 19:44:20 +01:00
|
|
|
const char *ignore_section);
|
2015-09-16 00:00:23 +02:00
|
|
|
/* location is TOP aligned. */
|
|
|
|
int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output,
|
|
|
|
uint32_t *location, const char *ignore_section);
|
2009-09-14 15:29:27 +02:00
|
|
|
|
2010-04-24 23:24:06 +02:00
|
|
|
void print_supported_filetypes(void);
|
|
|
|
|
2013-12-03 20:13:35 +01:00
|
|
|
/* lzma/lzma.c */
|
2014-02-21 08:38:49 +01:00
|
|
|
int do_lzma_compress(char *in, int in_len, char *out, int *out_len);
|
|
|
|
int do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len);
|
2015-03-04 00:55:03 +01:00
|
|
|
|
2013-12-03 20:13:35 +01:00
|
|
|
/* xdr.c */
|
|
|
|
struct xdr {
|
2014-03-05 23:38:26 +01:00
|
|
|
uint8_t (*get8)(struct buffer *input);
|
2013-12-03 20:13:35 +01:00
|
|
|
uint16_t (*get16)(struct buffer *input);
|
|
|
|
uint32_t (*get32)(struct buffer *input);
|
|
|
|
uint64_t (*get64)(struct buffer *input);
|
2014-03-05 23:38:26 +01:00
|
|
|
void (*put8)(struct buffer *input, uint8_t val);
|
2013-12-03 20:13:35 +01:00
|
|
|
void (*put16)(struct buffer *input, uint16_t val);
|
|
|
|
void (*put32)(struct buffer *input, uint32_t val);
|
|
|
|
void (*put64)(struct buffer *input, uint64_t val);
|
|
|
|
};
|
|
|
|
|
|
|
|
extern struct xdr xdr_le, xdr_be;
|
2014-03-10 20:13:27 +01:00
|
|
|
size_t bgets(struct buffer *input, void *output, size_t len);
|
|
|
|
size_t bputs(struct buffer *b, const void *data, size_t len);
|
2012-10-30 00:52:36 +01:00
|
|
|
|
|
|
|
#endif
|