--- /dev/null
+# 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
+ fname, tmpdir = self.fetch_from_drive(
+ '1IOnE0Qvy97d-0WOCwF64xBGpKSY2sMtJ')
+ return fname, tmpdir