Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | # SPDX-License-Identifier: GPL-2.0+ |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 2 | # Copyright (c) 2016 Google, Inc |
| 3 | # Written by Simon Glass <sjg@chromium.org> |
| 4 | # |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 5 | |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 6 | """Command-line parser for binman""" |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 7 | |
Simon Glass | 88e04da | 2021-11-23 11:03:42 -0700 | [diff] [blame] | 8 | import argparse |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 9 | from argparse import ArgumentParser |
Simon Glass | 9a1c726 | 2023-02-22 12:14:49 -0700 | [diff] [blame] | 10 | import os |
Simon Glass | 2a0fa98 | 2022-02-11 13:23:21 -0700 | [diff] [blame] | 11 | from binman import state |
Simon Glass | cd6d633 | 2023-02-23 18:18:19 -0700 | [diff] [blame] | 12 | import os |
| 13 | import pathlib |
| 14 | |
| 15 | BINMAN_DIR = pathlib.Path(__file__).parent |
| 16 | HAS_TESTS = (BINMAN_DIR / "ftest.py").exists() |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 17 | |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 18 | def make_extract_parser(subparsers): |
| 19 | """make_extract_parser: Make a subparser for the 'extract' command |
| 20 | |
| 21 | Args: |
| 22 | subparsers (ArgumentParser): parser to add this one to |
| 23 | """ |
| 24 | extract_parser = subparsers.add_parser('extract', |
| 25 | help='Extract files from an image') |
Simon Glass | 637958f | 2021-11-23 21:09:50 -0700 | [diff] [blame] | 26 | extract_parser.add_argument('-F', '--format', type=str, |
| 27 | help='Select an alternative format for extracted data') |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 28 | extract_parser.add_argument('-i', '--image', type=str, required=True, |
| 29 | help='Image filename to extract') |
| 30 | extract_parser.add_argument('-f', '--filename', type=str, |
| 31 | help='Output filename to write to') |
| 32 | extract_parser.add_argument('-O', '--outdir', type=str, default='', |
| 33 | help='Path to directory to use for output files') |
| 34 | extract_parser.add_argument('paths', type=str, nargs='*', |
| 35 | help='Paths within file to extract (wildcard)') |
| 36 | extract_parser.add_argument('-U', '--uncompressed', action='store_true', |
| 37 | help='Output raw uncompressed data for compressed entries') |
| 38 | |
Simon Glass | 88e04da | 2021-11-23 11:03:42 -0700 | [diff] [blame] | 39 | |
| 40 | #pylint: disable=R0903 |
| 41 | class BinmanVersion(argparse.Action): |
| 42 | """Handles the -V option to binman |
| 43 | |
| 44 | This reads the version information from a file called 'version' in the same |
| 45 | directory as this file. |
| 46 | |
| 47 | If not present it assumes this is running from the U-Boot tree and collects |
| 48 | the version from the Makefile. |
| 49 | |
| 50 | The format of the version information is three VAR = VALUE lines, for |
| 51 | example: |
| 52 | |
| 53 | VERSION = 2022 |
| 54 | PATCHLEVEL = 01 |
| 55 | EXTRAVERSION = -rc2 |
| 56 | """ |
| 57 | def __init__(self, nargs=0, **kwargs): |
| 58 | super().__init__(nargs=nargs, **kwargs) |
| 59 | |
| 60 | def __call__(self, parser, namespace, values, option_string=None): |
| 61 | parser._print_message(f'Binman {state.GetVersion()}\n') |
| 62 | parser.exit() |
| 63 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 64 | |
| 65 | def ParseArgs(argv): |
| 66 | """Parse the binman command-line arguments |
| 67 | |
| 68 | Args: |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 69 | argv (list of str): List of string arguments |
| 70 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 71 | Returns: |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 72 | tuple: (options, args) with the command-line options and arugments. |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 73 | options provides access to the options (e.g. option.debug) |
| 74 | args is a list of string arguments |
| 75 | """ |
Simon Glass | b9b9b27 | 2023-03-02 17:02:42 -0700 | [diff] [blame] | 76 | def _AddPreserve(pars): |
| 77 | pars.add_argument('-O', '--outdir', type=str, |
| 78 | action='store', help='Path to directory to use for intermediate ' |
| 79 | 'and output files') |
| 80 | pars.add_argument('-p', '--preserve', action='store_true',\ |
| 81 | help='Preserve temporary output directory even if option -O is not ' |
| 82 | 'given') |
| 83 | |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 84 | if '-H' in argv: |
| 85 | argv.append('build') |
| 86 | |
| 87 | epilog = '''Binman creates and manipulate images for a board from a set of binaries. Binman is |
| 88 | controlled by a description in the board device tree.''' |
| 89 | |
| 90 | parser = ArgumentParser(epilog=epilog) |
| 91 | parser.add_argument('-B', '--build-dir', type=str, default='b', |
| 92 | help='Directory containing the build output') |
| 93 | parser.add_argument('-D', '--debug', action='store_true', |
| 94 | help='Enabling debugging (provides a full traceback on error)') |
| 95 | parser.add_argument('-H', '--full-help', action='store_true', |
| 96 | default=False, help='Display the README file') |
Simon Glass | 9a1c726 | 2023-02-22 12:14:49 -0700 | [diff] [blame] | 97 | parser.add_argument('--tooldir', type=str, |
Simon Glass | 25b39e8 | 2023-04-19 15:21:14 -0600 | [diff] [blame] | 98 | default=os.path.join(os.path.expanduser('~/.binman-tools')), |
Simon Glass | 9a1c726 | 2023-02-22 12:14:49 -0700 | [diff] [blame] | 99 | help='Set the directory to store tools') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 100 | parser.add_argument('--toolpath', type=str, action='append', |
Simon Glass | 9a1c726 | 2023-02-22 12:14:49 -0700 | [diff] [blame] | 101 | help='Add a path to the list of directories containing tools') |
Simon Glass | 76f496d | 2021-07-06 10:36:37 -0600 | [diff] [blame] | 102 | parser.add_argument('-T', '--threads', type=int, |
| 103 | default=None, help='Number of threads to use (0=single-thread)') |
| 104 | parser.add_argument('--test-section-timeout', action='store_true', |
| 105 | help='Use a zero timeout for section multi-threading (for testing)') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 106 | parser.add_argument('-v', '--verbosity', default=1, |
| 107 | type=int, help='Control verbosity: 0=silent, 1=warnings, 2=notices, ' |
| 108 | '3=info, 4=detail, 5=debug') |
Simon Glass | 88e04da | 2021-11-23 11:03:42 -0700 | [diff] [blame] | 109 | parser.add_argument('-V', '--version', nargs=0, action=BinmanVersion) |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 110 | |
| 111 | subparsers = parser.add_subparsers(dest='cmd') |
Simon Glass | 7668194 | 2020-10-26 17:40:02 -0600 | [diff] [blame] | 112 | subparsers.required = True |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 113 | |
| 114 | build_parser = subparsers.add_parser('build', help='Build firmware image') |
| 115 | build_parser.add_argument('-a', '--entry-arg', type=str, action='append', |
Simon Glass | 91710b3 | 2018-07-17 13:25:32 -0600 | [diff] [blame] | 116 | help='Set argument value arg=value') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 117 | build_parser.add_argument('-b', '--board', type=str, |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 118 | help='Board name to build') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 119 | build_parser.add_argument('-d', '--dt', type=str, |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 120 | help='Configuration file (.dtb) to use') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 121 | build_parser.add_argument('--fake-dtb', action='store_true', |
Simon Glass | 3140201 | 2018-09-14 04:57:23 -0600 | [diff] [blame] | 122 | help='Use fake device tree contents (for testing only)') |
Heiko Thiery | 6d45136 | 2022-01-06 11:49:41 +0100 | [diff] [blame] | 123 | build_parser.add_argument('--fake-ext-blobs', action='store_true', |
| 124 | help='Create fake ext blobs with dummy content (for testing only)') |
Simon Glass | 66152ce | 2022-01-09 20:14:09 -0700 | [diff] [blame] | 125 | build_parser.add_argument('--force-missing-bintools', type=str, |
| 126 | help='Comma-separated list of bintools to consider missing (for testing)') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 127 | build_parser.add_argument('-i', '--image', type=str, action='append', |
Simon Glass | 3b376c3 | 2018-09-14 04:57:12 -0600 | [diff] [blame] | 128 | help='Image filename to build (if not specified, build all)') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 129 | build_parser.add_argument('-I', '--indir', action='append', |
Simon Glass | 720d567 | 2019-07-08 13:18:31 -0600 | [diff] [blame] | 130 | help='Add a path to the list of directories to use for input files') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 131 | build_parser.add_argument('-m', '--map', action='store_true', |
Simon Glass | 3073266 | 2018-06-01 09:38:20 -0600 | [diff] [blame] | 132 | default=False, help='Output a map file for each image') |
Simon Glass | 5d94cc6 | 2020-07-09 18:39:38 -0600 | [diff] [blame] | 133 | build_parser.add_argument('-M', '--allow-missing', action='store_true', |
Simon Glass | 6bce5dc | 2022-11-09 19:14:42 -0700 | [diff] [blame] | 134 | default=False, help='Allow external blobs and bintools to be missing') |
Simon Glass | ed93067 | 2021-03-18 20:25:05 +1300 | [diff] [blame] | 135 | build_parser.add_argument('-n', '--no-expanded', action='store_true', |
| 136 | help="Don't use 'expanded' versions of entries where available; " |
| 137 | "normally 'u-boot' becomes 'u-boot-expanded', for example") |
Simon Glass | b9b9b27 | 2023-03-02 17:02:42 -0700 | [diff] [blame] | 138 | _AddPreserve(build_parser) |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 139 | build_parser.add_argument('-u', '--update-fdt', action='store_true', |
Simon Glass | e8561af | 2018-08-01 15:22:37 -0600 | [diff] [blame] | 140 | default=False, help='Update the binman node with offset/size info') |
Simon Glass | adfb849 | 2021-11-03 21:09:18 -0600 | [diff] [blame] | 141 | build_parser.add_argument('--update-fdt-in-elf', type=str, |
| 142 | help='Update an ELF file with the output dtb: infile,outfile,begin_sym,end_sym') |
Simon Glass | 6bce5dc | 2022-11-09 19:14:42 -0700 | [diff] [blame] | 143 | build_parser.add_argument( |
| 144 | '-W', '--ignore-missing', action='store_true', default=False, |
| 145 | help='Return success even if there are missing blobs/bintools (requires -M)') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 146 | |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 147 | subparsers.add_parser( |
Simon Glass | 620c446 | 2022-01-09 20:14:11 -0700 | [diff] [blame] | 148 | 'bintool-docs', help='Write out bintool documentation (see bintool.rst)') |
| 149 | |
| 150 | subparsers.add_parser( |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 151 | 'entry-docs', help='Write out entry documentation (see entries.rst)') |
Simon Glass | f46732a | 2019-07-08 14:25:29 -0600 | [diff] [blame] | 152 | |
Simon Glass | b2fd11d | 2019-07-08 14:25:48 -0600 | [diff] [blame] | 153 | list_parser = subparsers.add_parser('ls', help='List files in an image') |
| 154 | list_parser.add_argument('-i', '--image', type=str, required=True, |
| 155 | help='Image filename to list') |
| 156 | list_parser.add_argument('paths', type=str, nargs='*', |
| 157 | help='Paths within file to list (wildcard)') |
| 158 | |
Simon Glass | 33046a3 | 2021-11-23 11:03:41 -0700 | [diff] [blame] | 159 | make_extract_parser(subparsers) |
Simon Glass | 980a284 | 2019-07-08 14:25:52 -0600 | [diff] [blame] | 160 | |
Simon Glass | 30033c2 | 2019-07-20 12:24:15 -0600 | [diff] [blame] | 161 | replace_parser = subparsers.add_parser('replace', |
| 162 | help='Replace entries in an image') |
| 163 | replace_parser.add_argument('-C', '--compressed', action='store_true', |
| 164 | help='Input data is already compressed if needed for the entry') |
| 165 | replace_parser.add_argument('-i', '--image', type=str, required=True, |
Jan Kiszka | 8ea4443 | 2021-11-11 08:13:30 +0100 | [diff] [blame] | 166 | help='Image filename to update') |
Simon Glass | 30033c2 | 2019-07-20 12:24:15 -0600 | [diff] [blame] | 167 | replace_parser.add_argument('-f', '--filename', type=str, |
| 168 | help='Input filename to read from') |
| 169 | replace_parser.add_argument('-F', '--fix-size', action='store_true', |
| 170 | help="Don't allow entries to be resized") |
| 171 | replace_parser.add_argument('-I', '--indir', type=str, default='', |
| 172 | help='Path to directory to use for input files') |
| 173 | replace_parser.add_argument('-m', '--map', action='store_true', |
| 174 | default=False, help='Output a map file for the updated image') |
Simon Glass | b9b9b27 | 2023-03-02 17:02:42 -0700 | [diff] [blame] | 175 | _AddPreserve(replace_parser) |
Simon Glass | 30033c2 | 2019-07-20 12:24:15 -0600 | [diff] [blame] | 176 | replace_parser.add_argument('paths', type=str, nargs='*', |
Jan Kiszka | 8ea4443 | 2021-11-11 08:13:30 +0100 | [diff] [blame] | 177 | help='Paths within file to replace (wildcard)') |
Simon Glass | 30033c2 | 2019-07-20 12:24:15 -0600 | [diff] [blame] | 178 | |
Ivan Mikhaylov | 8a80386 | 2023-03-08 01:13:39 +0000 | [diff] [blame] | 179 | sign_parser = subparsers.add_parser('sign', |
| 180 | help='Sign entries in image') |
| 181 | sign_parser.add_argument('-a', '--algo', type=str, required=True, |
| 182 | help='Hash algorithm e.g. sha256,rsa4096') |
| 183 | sign_parser.add_argument('-f', '--file', type=str, required=False, |
| 184 | help='Input filename to sign') |
| 185 | sign_parser.add_argument('-i', '--image', type=str, required=True, |
| 186 | help='Image filename to update') |
| 187 | sign_parser.add_argument('-k', '--key', type=str, required=True, |
| 188 | help='Private key file for signing') |
| 189 | sign_parser.add_argument('paths', type=str, nargs='*', |
| 190 | help='Paths within file to sign (wildcard)') |
| 191 | |
Simon Glass | cd6d633 | 2023-02-23 18:18:19 -0700 | [diff] [blame] | 192 | if HAS_TESTS: |
| 193 | test_parser = subparsers.add_parser('test', help='Run tests') |
| 194 | test_parser.add_argument('-P', '--processes', type=int, |
| 195 | help='set number of processes to use for running tests') |
| 196 | test_parser.add_argument('-T', '--test-coverage', action='store_true', |
| 197 | default=False, help='run tests and check for 100%% coverage') |
| 198 | test_parser.add_argument( |
| 199 | '-X', '--test-preserve-dirs', action='store_true', |
| 200 | help='Preserve and display test-created input directories; also ' |
| 201 | 'preserve the output directory if a single test is run (pass ' |
| 202 | 'test name at the end of the command line') |
| 203 | test_parser.add_argument('tests', nargs='*', |
| 204 | help='Test names to run (omit for all)') |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 205 | |
Simon Glass | 4eae925 | 2022-01-09 20:13:50 -0700 | [diff] [blame] | 206 | tool_parser = subparsers.add_parser('tool', help='Check bintools') |
| 207 | tool_parser.add_argument('-l', '--list', action='store_true', |
| 208 | help='List all known bintools') |
Simon Glass | cd6d633 | 2023-02-23 18:18:19 -0700 | [diff] [blame] | 209 | tool_parser.add_argument( |
| 210 | '-f', '--fetch', action='store_true', |
| 211 | help='fetch a bintool from a known location (or: all/missing)') |
Simon Glass | 4eae925 | 2022-01-09 20:13:50 -0700 | [diff] [blame] | 212 | tool_parser.add_argument('bintools', type=str, nargs='*') |
| 213 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 214 | return parser.parse_args(argv) |