Simon Glass | 7a1c101 | 2022-01-09 20:13:54 -0700 | [diff] [blame] | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | # Copyright 2022 Google LLC |
| 3 | # |
| 4 | """Bintool implementation for futility |
| 5 | |
| 6 | futility (flash utility) is a tool for working with Chromium OS flash images. |
| 7 | This implements just the features used by Binman. |
| 8 | |
| 9 | Documentation is at: |
| 10 | https://chromium.googlesource.com/chromiumos/platform/vboot/+/refs/heads/main/_vboot_reference/README |
| 11 | |
| 12 | Source code: |
| 13 | https://chromium.googlesource.com/chromiumos/platform/vboot/+/refs/heads/master/_vboot_reference/futility |
| 14 | |
| 15 | Here is the help: |
| 16 | Usage: futility [options] COMMAND [args...] |
| 17 | |
| 18 | This is the unified firmware utility, which will eventually replace |
| 19 | most of the distinct verified boot tools formerly produced by the |
| 20 | vboot_reference package. |
| 21 | |
| 22 | When symlinked under the name of one of those previous tools, it should |
| 23 | fully implement the original behavior. It can also be invoked directly |
| 24 | as futility, followed by the original name as the first argument. |
| 25 | |
| 26 | Global options: |
| 27 | |
| 28 | --vb1 Use only vboot v1.0 binary formats |
| 29 | --vb21 Use only vboot v2.1 binary formats |
| 30 | --debug Be noisy about what's going on |
| 31 | |
| 32 | The following commands are built-in: |
| 33 | |
| 34 | bdb Common boot flow utility |
| 35 | create Create a keypair from an RSA .pem file |
| 36 | dump_fmap Display FMAP contents from a firmware image |
| 37 | dump_kernel_config Prints the kernel command line |
| 38 | gbb Manipulate the Google Binary Block (GBB) |
| 39 | gbb_utility Legacy name for `gbb` command |
| 40 | help Show a bit of help (you're looking at it) |
| 41 | load_fmap Replace the contents of specified FMAP areas |
| 42 | pcr Simulate a TPM PCR extension operation |
| 43 | show Display the content of various binary components |
| 44 | sign Sign / resign various binary components |
| 45 | update Update system firmware |
| 46 | validate_rec_mrc Validates content of Recovery MRC cache |
| 47 | vbutil_firmware Verified boot firmware utility |
| 48 | vbutil_kernel Creates, signs, and verifies the kernel partition |
| 49 | vbutil_key Wraps RSA keys with vboot headers |
| 50 | vbutil_keyblock Creates, signs, and verifies a keyblock |
| 51 | verify Verify the signatures of various binary components |
| 52 | version Show the futility source revision and build date |
| 53 | """ |
| 54 | |
| 55 | from binman import bintool |
| 56 | |
| 57 | class Bintoolfutility(bintool.Bintool): |
| 58 | """Handles the 'futility' tool |
| 59 | |
| 60 | futility (flash utility) is a tool for working with Chromium OS flash |
| 61 | images. This Bintool implements just the features used by Binman, related to |
| 62 | GBB creation and firmware signing. |
| 63 | |
| 64 | A binary version of the tool can be fetched. |
| 65 | |
| 66 | See `Chromium OS vboot documentation`_ for more information. |
| 67 | |
| 68 | .. _`Chromium OS vboot documentation`: |
| 69 | https://chromium.googlesource.com/chromiumos/platform/vboot/+/refs/heads/main/_vboot_reference/README |
| 70 | """ |
| 71 | def __init__(self, name): |
| 72 | super().__init__(name, 'Chromium OS firmware utility') |
| 73 | |
| 74 | def gbb_create(self, fname, sizes): |
| 75 | """Create a new Google Binary Block |
| 76 | |
| 77 | Args: |
| 78 | fname (str): Filename to write to |
| 79 | sizes (list of int): Sizes of each regions: |
| 80 | hwid_size, rootkey_size, bmpfv_size, recoverykey_size |
| 81 | |
| 82 | Returns: |
| 83 | str: Tool output |
| 84 | """ |
| 85 | args = [ |
| 86 | 'gbb_utility', |
| 87 | '-c', |
| 88 | ','.join(['%#x' % size for size in sizes]), |
| 89 | fname |
| 90 | ] |
| 91 | return self.run_cmd(*args) |
| 92 | |
| 93 | # pylint: disable=R0913 |
| 94 | def gbb_set(self, fname, hwid, rootkey, recoverykey, flags, bmpfv): |
| 95 | """Set the parameters in a Google Binary Block |
| 96 | |
| 97 | Args: |
| 98 | fname (str): Filename to update |
| 99 | hwid (str): Hardware ID to use |
| 100 | rootkey (str): Filename of root key, e.g. 'root_key.vbpubk' |
| 101 | recoverykey (str): Filename of recovery key, |
| 102 | e.g. 'recovery_key.vbpubk' |
| 103 | flags (int): GBB flags to use |
| 104 | bmpfv (str): Filename of firmware bitmaps (bmpblk file) |
| 105 | |
| 106 | Returns: |
| 107 | str: Tool output |
| 108 | """ |
Simon Glass | a7b096f | 2022-02-28 12:08:20 -0700 | [diff] [blame] | 109 | args = ['gbb_utility', |
Simon Glass | 7a1c101 | 2022-01-09 20:13:54 -0700 | [diff] [blame] | 110 | '-s', |
| 111 | f'--hwid={hwid}', |
| 112 | f'--rootkey={rootkey}', |
| 113 | f'--recoverykey={recoverykey}', |
| 114 | f'--flags={flags}', |
| 115 | f'--bmpfv={bmpfv}', |
| 116 | fname |
| 117 | ] |
| 118 | return self.run_cmd(*args) |
| 119 | |
| 120 | def sign_firmware(self, vblock, keyblock, signprivate, version, firmware, |
| 121 | kernelkey, flags): |
| 122 | """Sign firmware to create a vblock file |
| 123 | |
| 124 | Args: |
| 125 | vblock (str): Filename to write the vblock too |
| 126 | keyblock (str): Filename of keyblock file |
| 127 | signprivate (str): Filename of private key |
| 128 | version (int): Version number |
| 129 | firmware (str): Filename of firmware binary to sign |
| 130 | kernelkey (str): Filename of kernel key |
| 131 | flags (int): Preamble flags |
| 132 | |
| 133 | Returns: |
| 134 | str: Tool output |
| 135 | """ |
| 136 | args = [ |
| 137 | 'vbutil_firmware', |
| 138 | '--vblock', vblock, |
| 139 | '--keyblock', keyblock, |
| 140 | '--signprivate', signprivate, |
| 141 | '--version', version, |
Simon Glass | a7b096f | 2022-02-28 12:08:20 -0700 | [diff] [blame] | 142 | '--fv', firmware, |
Simon Glass | 7a1c101 | 2022-01-09 20:13:54 -0700 | [diff] [blame] | 143 | '--kernelkey', kernelkey, |
| 144 | '--flags', flags |
| 145 | ] |
| 146 | return self.run_cmd(*args) |
| 147 | |
| 148 | def fetch(self, method): |
| 149 | """Fetch handler for futility |
| 150 | |
| 151 | This installs futility using a binary download. |
| 152 | |
| 153 | Args: |
| 154 | method (FETCH_...): Method to use |
| 155 | |
| 156 | Returns: |
| 157 | True if the file was fetched, None if a method other than FETCH_BIN |
| 158 | was requested |
| 159 | |
| 160 | Raises: |
| 161 | Valuerror: Fetching could not be completed |
| 162 | """ |
| 163 | if method != bintool.FETCH_BIN: |
| 164 | return None |
| 165 | fname, tmpdir = self.fetch_from_drive( |
| 166 | '1hdsInzsE4aJbmBeJ663kYgjOQyW1I-E0') |
| 167 | return fname, tmpdir |
| 168 | |
| 169 | def version(self): |
| 170 | """Version handler for futility |
| 171 | |
| 172 | Returns: |
| 173 | str: Version string for futility |
| 174 | """ |
| 175 | out = self.run_cmd('version').strip() |
| 176 | if not out: |
| 177 | return super().version() |
| 178 | return out |