cbfstool.py 7.8 KB

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