| # SPDX-License-Identifier: GPL-2.0+ | |
| # Copyright 2022 Google LLC | |
| # | |
| """Bintool implementation for cbfstool | |
| cfstool provides a number of features useful with Coreboot Filesystem binaries. | |
| Documentation is at https://www.coreboot.org/CBFS | |
| Source code is at https://github.com/coreboot/coreboot/blob/master/util/cbfstool/cbfstool.c | |
| Here is the help: | |
| cbfstool: Management utility for CBFS formatted ROM images | |
| USAGE: | |
| cbfstool [-h] | |
| cbfstool FILE COMMAND [-v] [PARAMETERS]... | |
| OPTIONs: | |
| -H header_offset Do not search for header; use this offset* | |
| -T Output top-aligned memory address | |
| -u Accept short data; fill upward/from bottom | |
| -d Accept short data; fill downward/from top | |
| -F Force action | |
| -g Generate position and alignment arguments | |
| -U Unprocessed; don't decompress or make ELF | |
| -v Provide verbose output | |
| -h Display this help message | |
| COMMANDs: | |
| add [-r image,regions] -f FILE -n NAME -t TYPE [-A hash] \ | |
| [-c compression] [-b base-address | -a alignment] \ | |
| [-p padding size] [-y|--xip if TYPE is FSP] \ | |
| [-j topswap-size] (Intel CPUs only) [--ibb] | |
| Add a component | |
| -j valid size: 0x10000 0x20000 0x40000 0x80000 0x100000 | |
| add-payload [-r image,regions] -f FILE -n NAME [-A hash] \ | |
| [-c compression] [-b base-address] \ | |
| (linux specific: [-C cmdline] [-I initrd]) | |
| Add a payload to the ROM | |
| add-stage [-r image,regions] -f FILE -n NAME [-A hash] \ | |
| [-c compression] [-b base] [-S section-to-ignore] \ | |
| [-a alignment] [-y|--xip] [-P page-size] [--ibb] | |
| Add a stage to the ROM | |
| add-flat-binary [-r image,regions] -f FILE -n NAME \ | |
| [-A hash] -l load-address -e entry-point \ | |
| [-c compression] [-b base] | |
| Add a 32bit flat mode binary | |
| add-int [-r image,regions] -i INTEGER -n NAME [-b base] | |
| Add a raw 64-bit integer value | |
| add-master-header [-r image,regions] \ | |
| [-j topswap-size] (Intel CPUs only) | |
| Add a legacy CBFS master header | |
| remove [-r image,regions] -n NAME | |
| Remove a component | |
| compact -r image,regions | |
| Defragment CBFS image. | |
| copy -r image,regions -R source-region | |
| Create a copy (duplicate) cbfs instance in fmap | |
| create -m ARCH -s size [-b bootblock offset] \ | |
| [-o CBFS offset] [-H header offset] [-B bootblock] | |
| Create a legacy ROM file with CBFS master header* | |
| create -M flashmap [-r list,of,regions,containing,cbfses] | |
| Create a new-style partitioned firmware image | |
| locate [-r image,regions] -f FILE -n NAME [-P page-size] \ | |
| [-a align] [-T] | |
| Find a place for a file of that size | |
| layout [-w] | |
| List mutable (or, with -w, readable) image regions | |
| print [-r image,regions] | |
| Show the contents of the ROM | |
| extract [-r image,regions] [-m ARCH] -n NAME -f FILE [-U] | |
| Extracts a file from ROM | |
| write [-F] -r image,regions -f file [-u | -d] [-i int] | |
| Write file into same-size [or larger] raw region | |
| read [-r fmap-region] -f file | |
| Extract raw region contents into binary file | |
| truncate [-r fmap-region] | |
| Truncate CBFS and print new size on stdout | |
| expand [-r fmap-region] | |
| Expand CBFS to span entire region | |
| OFFSETs: | |
| Numbers accompanying -b, -H, and -o switches* may be provided | |
| in two possible formats: if their value is greater than | |
| 0x80000000, they are interpreted as a top-aligned x86 memory | |
| address; otherwise, they are treated as an offset into flash. | |
| ARCHes: | |
| arm64, arm, mips, ppc64, power8, riscv, x86, unknown | |
| TYPEs: | |
| bootblock, cbfs header, stage, simple elf, fit, optionrom, bootsplash, raw, | |
| vsa, mbi, microcode, fsp, mrc, cmos_default, cmos_layout, spd, | |
| mrc_cache, mma, efi, struct, deleted, null | |
| * Note that these actions and switches are only valid when | |
| working with legacy images whose structure is described | |
| primarily by a CBFS master header. New-style images, in | |
| contrast, exclusively make use of an FMAP to describe their | |
| layout: this must minimally contain an 'FMAP' section | |
| specifying the location of this FMAP itself and a 'COREBOOT' | |
| section describing the primary CBFS. It should also be noted | |
| that, when working with such images, the -F and -r switches | |
| default to 'COREBOOT' for convenience, and both the -b switch to | |
| CBFS operations and the output of the locate action become | |
| relative to the selected CBFS region's lowest address. | |
| The one exception to this rule is the top-aligned address, | |
| which is always relative to the end of the entire image | |
| rather than relative to the local region; this is true for | |
| for both input (sufficiently large) and output (-T) data. | |
| Since binman has a native implementation of CBFS (see cbfs_util.py), we don't | |
| actually need this tool, except for sanity checks in the tests. | |
| """ | |
| from binman import bintool | |
| class Bintoolcbfstool(bintool.Bintool): | |
| """Coreboot filesystem (CBFS) tool | |
| This bintool supports creating new CBFS images and adding files to an | |
| existing image, i.e. the features needed by binman. | |
| It also supports fetching a binary cbfstool, since building it from source | |
| is fairly slow. | |
| Documentation about CBFS is at https://www.coreboot.org/CBFS | |
| """ | |
| def __init__(self, name): | |
| super().__init__(name, 'Manipulate CBFS files') | |
| def create_new(self, cbfs_fname, size, arch='x86'): | |
| """Create a new CBFS | |
| Args: | |
| cbfs_fname (str): Filename of CBFS to create | |
| size (int): Size of CBFS in bytes | |
| arch (str): Architecture for which this CBFS is intended | |
| Returns: | |
| str: Tool output | |
| """ | |
| args = [cbfs_fname, 'create', '-s', f'{size:#x}', '-m', arch] | |
| return self.run_cmd(*args) | |
| # pylint: disable=R0913 | |
| def add_raw(self, cbfs_fname, name, fname, compress=None, base=None): | |
| """Add a raw file to the CBFS | |
| Args: | |
| cbfs_fname (str): Filename of CBFS to create | |
| name (str): Name to use inside the CBFS | |
| fname (str): Filename of file to add | |
| compress (str): Compression to use (cbfs_util.COMPRESS_NAMES) or | |
| None for None | |
| base (int): Address to place the file, or None for anywhere | |
| Returns: | |
| str: Tool output | |
| """ | |
| args = [cbfs_fname, | |
| 'add', | |
| '-n', name, | |
| '-t', 'raw', | |
| '-f', fname, | |
| '-c', compress or 'none'] | |
| if base: | |
| args += ['-b', f'{base:#x}'] | |
| return self.run_cmd(*args) | |
| def add_stage(self, cbfs_fname, name, fname): | |
| """Add a stage file to the CBFS | |
| Args: | |
| cbfs_fname (str): Filename of CBFS to create | |
| name (str): Name to use inside the CBFS | |
| fname (str): Filename of file to add | |
| Returns: | |
| str: Tool output | |
| """ | |
| args = [cbfs_fname, | |
| 'add-stage', | |
| '-n', name, | |
| '-f', fname | |
| ] | |
| return self.run_cmd(*args) | |
| def fail(self): | |
| """Run cbfstool with invalid arguments to check it reports failure | |
| This is really just a sanity check | |
| Returns: | |
| CommandResult: Result from running the bad command | |
| """ | |
| args = ['missing-file', 'bad-command'] | |
| return self.run_cmd_result(*args) | |
| def fetch(self, method): | |
| """Fetch handler for cbfstool | |
| This installs cbfstool by downloading from Google Drive. | |
| Args: | |
| method (FETCH_...): Method to use | |
| Returns: | |
| True if the file was fetched and now installed, None if a method | |
| other than FETCH_BIN was requested | |
| Raises: | |
| Valuerror: Fetching could not be completed | |
| """ | |
| if method != bintool.FETCH_BIN: | |
| return None | |
| # Version 4.22.01 | |
| fname, tmpdir = self.fetch_from_drive( | |
| '1gxNxRuJgD0Iiy9LAPCSB_0959eJCp98g') | |
| return fname, tmpdir |