1# SPDX-License-Identifier: GPL-2.0+ 2# Copyright 2022 Google LLC 3# 4"""Bintool implementation for cbfstool 5 6cfstool provides a number of features useful with Coreboot Filesystem binaries. 7 8Documentation is at https://www.coreboot.org/CBFS 9 10Source code is at https://github.com/coreboot/coreboot/blob/master/util/cbfstool/cbfstool.c 11 12Here is the help: 13 14cbfstool: Management utility for CBFS formatted ROM images 15 16USAGE: 17 cbfstool [-h] 18 cbfstool FILE COMMAND [-v] [PARAMETERS]... 19 20OPTIONs: 21 -H header_offset Do not search for header; use this offset* 22 -T Output top-aligned memory address 23 -u Accept short data; fill upward/from bottom 24 -d Accept short data; fill downward/from top 25 -F Force action 26 -g Generate position and alignment arguments 27 -U Unprocessed; don't decompress or make ELF 28 -v Provide verbose output 29 -h Display this help message 30 31COMMANDs: 32 add [-r image,regions] -f FILE -n NAME -t TYPE [-A hash] \ 33 [-c compression] [-b base-address | -a alignment] \ 34 [-p padding size] [-y|--xip if TYPE is FSP] \ 35 [-j topswap-size] (Intel CPUs only) [--ibb] 36 Add a component 37 -j valid size: 0x10000 0x20000 0x40000 0x80000 0x100000 38 add-payload [-r image,regions] -f FILE -n NAME [-A hash] \ 39 [-c compression] [-b base-address] \ 40 (linux specific: [-C cmdline] [-I initrd]) 41 Add a payload to the ROM 42 add-stage [-r image,regions] -f FILE -n NAME [-A hash] \ 43 [-c compression] [-b base] [-S section-to-ignore] \ 44 [-a alignment] [-y|--xip] [-P page-size] [--ibb] 45 Add a stage to the ROM 46 add-flat-binary [-r image,regions] -f FILE -n NAME \ 47 [-A hash] -l load-address -e entry-point \ 48 [-c compression] [-b base] 49 Add a 32bit flat mode binary 50 add-int [-r image,regions] -i INTEGER -n NAME [-b base] 51 Add a raw 64-bit integer value 52 add-master-header [-r image,regions] \ 53 [-j topswap-size] (Intel CPUs only) 54 Add a legacy CBFS master header 55 remove [-r image,regions] -n NAME 56 Remove a component 57 compact -r image,regions 58 Defragment CBFS image. 59 copy -r image,regions -R source-region 60 Create a copy (duplicate) cbfs instance in fmap 61 create -m ARCH -s size [-b bootblock offset] \ 62 [-o CBFS offset] [-H header offset] [-B bootblock] 63 Create a legacy ROM file with CBFS master header* 64 create -M flashmap [-r list,of,regions,containing,cbfses] 65 Create a new-style partitioned firmware image 66 locate [-r image,regions] -f FILE -n NAME [-P page-size] \ 67 [-a align] [-T] 68 Find a place for a file of that size 69 layout [-w] 70 List mutable (or, with -w, readable) image regions 71 print [-r image,regions] 72 Show the contents of the ROM 73 extract [-r image,regions] [-m ARCH] -n NAME -f FILE [-U] 74 Extracts a file from ROM 75 write [-F] -r image,regions -f file [-u | -d] [-i int] 76 Write file into same-size [or larger] raw region 77 read [-r fmap-region] -f file 78 Extract raw region contents into binary file 79 truncate [-r fmap-region] 80 Truncate CBFS and print new size on stdout 81 expand [-r fmap-region] 82 Expand CBFS to span entire region 83OFFSETs: 84 Numbers accompanying -b, -H, and -o switches* may be provided 85 in two possible formats: if their value is greater than 86 0x80000000, they are interpreted as a top-aligned x86 memory 87 address; otherwise, they are treated as an offset into flash. 88ARCHes: 89 arm64, arm, mips, ppc64, power8, riscv, x86, unknown 90TYPEs: 91 bootblock, cbfs header, stage, simple elf, fit, optionrom, bootsplash, raw, 92 vsa, mbi, microcode, fsp, mrc, cmos_default, cmos_layout, spd, 93 mrc_cache, mma, efi, struct, deleted, null 94 95* Note that these actions and switches are only valid when 96 working with legacy images whose structure is described 97 primarily by a CBFS master header. New-style images, in 98 contrast, exclusively make use of an FMAP to describe their 99 layout: this must minimally contain an 'FMAP' section 100 specifying the location of this FMAP itself and a 'COREBOOT' 101 section describing the primary CBFS. It should also be noted 102 that, when working with such images, the -F and -r switches 103 default to 'COREBOOT' for convenience, and both the -b switch to 104 CBFS operations and the output of the locate action become 105 relative to the selected CBFS region's lowest address. 106 The one exception to this rule is the top-aligned address, 107 which is always relative to the end of the entire image 108 rather than relative to the local region; this is true for 109 for both input (sufficiently large) and output (-T) data. 110 111 112Since binman has a native implementation of CBFS (see cbfs_util.py), we don't 113actually need this tool, except for sanity checks in the tests. 114""" 115 116from binman import bintool 117 118class Bintoolcbfstool(bintool.Bintool): 119 """Coreboot filesystem (CBFS) tool 120 121 This bintool supports creating new CBFS images and adding files to an 122 existing image, i.e. the features needed by binman. 123 124 It also supports fetching a binary cbfstool, since building it from source 125 is fairly slow. 126 127 Documentation about CBFS is at https://www.coreboot.org/CBFS 128 """ 129 def __init__(self, name): 130 super().__init__(name, 'Manipulate CBFS files') 131 132 def create_new(self, cbfs_fname, size, arch='x86'): 133 """Create a new CBFS 134 135 Args: 136 cbfs_fname (str): Filename of CBFS to create 137 size (int): Size of CBFS in bytes 138 arch (str): Architecture for which this CBFS is intended 139 140 Returns: 141 str: Tool output 142 """ 143 args = [cbfs_fname, 'create', '-s', f'{size:#x}', '-m', arch] 144 return self.run_cmd(*args) 145 146 # pylint: disable=R0913 147 def add_raw(self, cbfs_fname, name, fname, compress=None, base=None): 148 """Add a raw file to the CBFS 149 150 Args: 151 cbfs_fname (str): Filename of CBFS to create 152 name (str): Name to use inside the CBFS 153 fname (str): Filename of file to add 154 compress (str): Compression to use (cbfs_util.COMPRESS_NAMES) or 155 None for None 156 base (int): Address to place the file, or None for anywhere 157 158 Returns: 159 str: Tool output 160 """ 161 args = [cbfs_fname, 162 'add', 163 '-n', name, 164 '-t', 'raw', 165 '-f', fname, 166 '-c', compress or 'none'] 167 if base: 168 args += ['-b', f'{base:#x}'] 169 return self.run_cmd(*args) 170 171 def add_stage(self, cbfs_fname, name, fname): 172 """Add a stage file to the CBFS 173 174 Args: 175 cbfs_fname (str): Filename of CBFS to create 176 name (str): Name to use inside the CBFS 177 fname (str): Filename of file to add 178 179 Returns: 180 str: Tool output 181 """ 182 args = [cbfs_fname, 183 'add-stage', 184 '-n', name, 185 '-f', fname 186 ] 187 return self.run_cmd(*args) 188 189 def fail(self): 190 """Run cbfstool with invalid arguments to check it reports failure 191 192 This is really just a sanity check 193 194 Returns: 195 CommandResult: Result from running the bad command 196 """ 197 args = ['missing-file', 'bad-command'] 198 return self.run_cmd_result(*args) 199 200 def fetch(self, method): 201 """Fetch handler for cbfstool 202 203 This installs cbfstool by downloading from Google Drive. 204 205 Args: 206 method (FETCH_...): Method to use 207 208 Returns: 209 True if the file was fetched and now installed, None if a method 210 other than FETCH_BIN was requested 211 212 Raises: 213 Valuerror: Fetching could not be completed 214 """ 215 if method != bintool.FETCH_BIN: 216 return None 217 fname, tmpdir = self.fetch_from_drive( 218 '1IOnE0Qvy97d-0WOCwF64xBGpKSY2sMtJ') 219 return fname, tmpdir 220