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.
|
|
|
|
*/
|
|
|
|
|
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
|
|
|
|
2016-05-26 23:41:02 +02:00
|
|
|
#include <commonlib/helpers.h>
|
2015-10-01 21:25:19 +02:00
|
|
|
#include <console/console.h>
|
|
|
|
|
2018-08-23 18:08:20 +02:00
|
|
|
/* Endianness */
|
2011-10-21 23:24:57 +02:00
|
|
|
#include "swab.h"
|
2009-09-14 15:29:27 +02: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;
|
|
|
|
}
|
|
|
|
|
2016-01-26 16:01:14 +01:00
|
|
|
static inline size_t buffer_offset(const struct buffer *b)
|
|
|
|
{
|
|
|
|
return b->offset;
|
|
|
|
}
|
|
|
|
|
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-10-24 00:36:57 +02:00
|
|
|
b->offset = 0;
|
2014-03-27 04:57:55 +01:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-11-11 18:43:11 +01:00
|
|
|
/* Returns the start of the underlying buffer, with the offset undone */
|
|
|
|
static inline void *buffer_get_original_backing(const struct buffer *b)
|
|
|
|
{
|
|
|
|
if (!b)
|
|
|
|
return NULL;
|
2016-01-26 16:01:14 +01:00
|
|
|
return buffer_get(b) - buffer_offset(b);
|
2015-11-11 18:43:11 +01:00
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
*/
|
2015-10-24 00:38:40 +02:00
|
|
|
typedef int (*decomp_func_ptr) (char *in, int in_len, char *out, int out_len,
|
|
|
|
size_t *actual_size);
|
2015-08-26 12:53:41 +02:00
|
|
|
|
2015-09-29 22:51:35 +02:00
|
|
|
enum comp_algo {
|
|
|
|
CBFS_COMPRESS_NONE = 0,
|
|
|
|
CBFS_COMPRESS_LZMA = 1,
|
|
|
|
CBFS_COMPRESS_LZ4 = 2,
|
|
|
|
};
|
2009-09-14 15:29:27 +02:00
|
|
|
|
2017-01-11 15:26:58 +01:00
|
|
|
struct typedesc_t {
|
|
|
|
uint32_t type;
|
|
|
|
const char *name;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct typedesc_t types_cbfs_compression[] = {
|
|
|
|
{CBFS_COMPRESS_NONE, "none"},
|
|
|
|
{CBFS_COMPRESS_LZMA, "LZMA"},
|
|
|
|
{CBFS_COMPRESS_LZ4, "LZ4"},
|
|
|
|
{0, NULL},
|
|
|
|
};
|
|
|
|
|
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);
|
2018-04-26 09:35:13 +02:00
|
|
|
int parse_fit_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
|
|
|
|
2018-04-08 15:05:09 +02:00
|
|
|
void print_supported_architectures(void);
|
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);
|
2015-10-24 00:38:40 +02:00
|
|
|
int do_lzma_uncompress(char *dst, int dst_len, char *src, int src_len,
|
|
|
|
size_t *actual_size);
|
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
|
|
|
|
2015-10-01 15:52:56 +02:00
|
|
|
/* Returns a 0-terminated string containing a hex representation of
|
|
|
|
* len bytes starting at data.
|
|
|
|
* The string is malloc'd and it's the caller's responsibility to free
|
|
|
|
* the memory.
|
|
|
|
* On error, bintohex returns NULL.
|
|
|
|
*/
|
|
|
|
char *bintohex(uint8_t *data, size_t len);
|
2012-10-30 00:52:36 +01:00
|
|
|
#endif
|