Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame] | 1 | # Copyright 2018 The ChromiumOS Authors |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 4 | |
Mike Frysinger | 88770ef | 2021-05-21 11:04:00 -0400 | [diff] [blame] | 5 | """Script to generate a DLC (Downloadable Content) artifact.""" |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 6 | |
Chris McDonald | 59650c3 | 2021-07-20 15:29:28 -0600 | [diff] [blame] | 7 | import logging |
| 8 | |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 9 | from chromite.lib import commandline |
Chris McDonald | 59650c3 | 2021-07-20 15:29:28 -0600 | [diff] [blame] | 10 | from chromite.lib import dlc_lib |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 11 | |
| 12 | |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 13 | def GetParser(): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 14 | """Creates an argument parser and returns it.""" |
| 15 | parser = commandline.ArgumentParser(description=__doc__) |
| 16 | # This script is used both for building an individual DLC or copying all final |
| 17 | # DLCs images to their final destination nearby chromiumos_test_image.bin, |
| 18 | # etc. These two arguments are required in both cases. |
| 19 | parser.add_argument( |
| 20 | "--sysroot", |
| 21 | type="path", |
| 22 | metavar="DIR", |
| 23 | help="The root path to the board's build root, e.g. " "/build/eve", |
| 24 | ) |
| 25 | # TODO(andrewlassalle): Remove src-dir in the future(2021?) if nobody uses it. |
| 26 | parser.add_argument( |
| 27 | "--src-dir", |
| 28 | type="path", |
| 29 | metavar="SRC_DIR_PATH", |
| 30 | help="Override the default Root directory path that contains all DLC " |
| 31 | "files to be packed.", |
| 32 | ) |
| 33 | parser.add_argument( |
| 34 | "--install-root-dir", |
| 35 | type="path", |
| 36 | metavar="DIR", |
| 37 | help="If building a specific DLC, it is the root path to" |
| 38 | " install DLC images (%s) and metadata (%s). Otherwise it" |
| 39 | " is the target directory where the Chrome OS images gets" |
| 40 | " dropped in build_image, e.g. " |
| 41 | "src/build/images/<board>/latest." |
| 42 | % (dlc_lib.DLC_BUILD_DIR, dlc_lib.DLC_META_DIR), |
| 43 | ) |
Amin Hassani | 22a25eb | 2019-01-11 14:25:02 -0800 | [diff] [blame] | 44 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 45 | one_dlc = parser.add_argument_group( |
| 46 | "Arguments required for building only " "one DLC" |
| 47 | ) |
| 48 | one_dlc.add_argument( |
| 49 | "--rootfs", |
| 50 | type="path", |
| 51 | metavar="ROOT_FS_PATH", |
| 52 | help="Path to the platform rootfs.", |
| 53 | ) |
| 54 | one_dlc.add_argument( |
| 55 | "--stateful", |
| 56 | type="path", |
| 57 | metavar="STATEFUL_PATH", |
| 58 | help="Path to the platform stateful.", |
| 59 | ) |
| 60 | one_dlc.add_argument( |
| 61 | "--pre-allocated-blocks", |
| 62 | type=int, |
| 63 | metavar="PREALLOCATEDBLOCKS", |
| 64 | help="Number of blocks (block size is 4k) that need to" |
| 65 | "be pre-allocated on device.", |
| 66 | ) |
| 67 | one_dlc.add_argument("--version", metavar="VERSION", help="DLC Version.") |
| 68 | one_dlc.add_argument("--id", metavar="ID", help="DLC ID (unique per DLC).") |
| 69 | one_dlc.add_argument( |
| 70 | "--package", |
| 71 | metavar="PACKAGE", |
| 72 | help="The package ID that is unique within a DLC, One" |
| 73 | " DLC cannot have duplicate package IDs.", |
| 74 | ) |
| 75 | one_dlc.add_argument( |
| 76 | "--name", metavar="NAME", help="A human-readable name for the DLC." |
| 77 | ) |
| 78 | one_dlc.add_argument("--description", help="The description for the DLC.") |
| 79 | one_dlc.add_argument( |
| 80 | "--board", metavar="BOARD", help="The target board we are building for." |
| 81 | ) |
| 82 | one_dlc.add_argument( |
| 83 | "--fullnamerev", |
| 84 | metavar="FULL_NAME_REV", |
| 85 | help="The full ebuild package name.", |
| 86 | ) |
| 87 | one_dlc.add_argument( |
| 88 | "--fs-type", |
| 89 | metavar="FS_TYPE", |
| 90 | default=dlc_lib.SQUASHFS_TYPE, |
| 91 | choices=(dlc_lib.SQUASHFS_TYPE, dlc_lib.EXT4_TYPE), |
| 92 | help="File system type of the image.", |
| 93 | ) |
| 94 | one_dlc.add_argument( |
| 95 | "--preload", |
| 96 | default=False, |
| 97 | action="store_true", |
| 98 | help="Allow preloading of DLC.", |
| 99 | ) |
| 100 | one_dlc.add_argument( |
| 101 | "--factory-install", |
| 102 | default=False, |
| 103 | action="store_true", |
| 104 | help="Allow factory installing of DLC.", |
| 105 | ) |
| 106 | one_dlc.add_argument( |
| 107 | "--loadpin-verity-digest", |
| 108 | default=False, |
| 109 | action="store_true", |
| 110 | help="Allow DLC to be a trusted dm-verity digest.", |
| 111 | ) |
| 112 | one_dlc.add_argument( |
| 113 | "--used-by", |
| 114 | default=dlc_lib.USED_BY_SYSTEM, |
| 115 | choices=(dlc_lib.USED_BY_USER, dlc_lib.USED_BY_SYSTEM), |
| 116 | help="Defines how this DLC will be used so dlcservice can take proper " |
| 117 | 'actions based on the type of usage. For example, if "user" is passed, ' |
| 118 | "dlcservice does ref counting when DLC is installed/uninstalled. For " |
| 119 | '"system", there will be no such provisions.', |
| 120 | ) |
| 121 | one_dlc.add_argument( |
| 122 | "--days-to-purge", |
| 123 | type=int, |
| 124 | default=0, |
| 125 | help="Defines the number of days before purging a DLC after it has " |
| 126 | "been uninstalled.", |
| 127 | ) |
| 128 | one_dlc.add_argument( |
| 129 | "--mount-file-required", |
| 130 | default=False, |
| 131 | action="store_true", |
| 132 | help="Allow indirect mount file generation for DLC.", |
| 133 | ) |
| 134 | one_dlc.add_argument( |
Jae Hoon Kim | c3cf227 | 2022-10-28 23:59:10 +0000 | [diff] [blame] | 135 | "--scaled", |
| 136 | default=False, |
| 137 | action="store_true", |
| 138 | help="DLC will be fed through scaling design.", |
| 139 | ) |
| 140 | one_dlc.add_argument( |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 141 | "--reserved", |
| 142 | default=False, |
| 143 | action="store_true", |
| 144 | help="Always reserve space for this DLC.", |
| 145 | ) |
| 146 | one_dlc.add_argument( |
| 147 | "--critical-update", |
| 148 | default=False, |
| 149 | action="store_true", |
| 150 | help="Always update with the OS for this DLC.", |
| 151 | ) |
| 152 | one_dlc.add_argument( |
| 153 | "--build-package", |
| 154 | default=False, |
| 155 | action="store_true", |
| 156 | help="Flag to indicate if the script is executed during the " |
| 157 | "build_packages phase.", |
| 158 | ) |
| 159 | return parser |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 160 | |
| 161 | |
Andrew | 67b5fa7 | 2020-02-05 14:14:48 -0800 | [diff] [blame] | 162 | def ValidateArguments(parser, opts, req_flags, invalid_flags): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 163 | """Validates the correctness of the passed arguments. |
Amin Hassani | b97a5ee | 2019-01-23 14:44:43 -0800 | [diff] [blame] | 164 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 165 | Args: |
| 166 | parser: Arguments parser. |
| 167 | opts: Parsed arguments. |
| 168 | req_flags: all the required flags. |
| 169 | invalid_flags: all the flags that are not allowed. |
| 170 | """ |
| 171 | # Make sure if the intention is to build one DLC, all the required arguments |
| 172 | # are passed and none of the invalid ones are passed. This will ensure the |
| 173 | # script is called twice per DLC. |
| 174 | if opts.id: |
| 175 | if not all(vars(opts)[x] is not None for x in req_flags): |
| 176 | parser.error( |
| 177 | "If the intention is to build only one DLC, all the flags" |
| 178 | "%s required for it should be passed." % req_flags |
| 179 | ) |
| 180 | if any(vars(opts)[x] is not None for x in invalid_flags): |
| 181 | parser.error( |
| 182 | "If the intention is to build only one DLC, all the flags" |
| 183 | "%s should be passed in the build_packages phase, not in " |
| 184 | "the build_image phase." % invalid_flags |
| 185 | ) |
Andrew | 67b5fa7 | 2020-02-05 14:14:48 -0800 | [diff] [blame] | 186 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 187 | if opts.fs_type == dlc_lib.EXT4_TYPE: |
| 188 | parser.error("ext4 unsupported for DLC, see https://crbug.com/890060") |
Amin Hassani | b97a5ee | 2019-01-23 14:44:43 -0800 | [diff] [blame] | 189 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 190 | if opts.id: |
| 191 | dlc_lib.ValidateDlcIdentifier(opts.id) |
| 192 | if opts.package: |
| 193 | dlc_lib.ValidateDlcIdentifier(opts.package) |
Amin Hassani | bc1a479 | 2019-10-24 14:39:57 -0700 | [diff] [blame] | 194 | |
Amin Hassani | b97a5ee | 2019-01-23 14:44:43 -0800 | [diff] [blame] | 195 | |
Xiaochu Liu | deed023 | 2018-06-26 10:25:34 -0700 | [diff] [blame] | 196 | def main(argv): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 197 | parser = GetParser() |
| 198 | opts = parser.parse_args(argv) |
| 199 | opts.Freeze() |
| 200 | per_dlc_req_args = ["id"] |
| 201 | per_dlc_invalid_args = [] |
| 202 | if opts.build_package: |
| 203 | per_dlc_req_args += [ |
| 204 | "pre_allocated_blocks", |
| 205 | "version", |
| 206 | "name", |
| 207 | "description", |
| 208 | "package", |
| 209 | "install_root_dir", |
| 210 | "days_to_purge", |
| 211 | ] |
| 212 | per_dlc_invalid_args += ["src_dir", "sysroot", "stateful"] |
| 213 | else: |
| 214 | per_dlc_req_args += ["sysroot", "board"] |
| 215 | per_dlc_invalid_args += [ |
| 216 | "name", |
| 217 | "pre_allocated_blocks", |
| 218 | "version", |
| 219 | "package", |
| 220 | "days_to_purge", |
| 221 | "reserved", |
| 222 | "critical_update", |
| 223 | ] |
Andrew | 67b5fa7 | 2020-02-05 14:14:48 -0800 | [diff] [blame] | 224 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 225 | ValidateArguments(parser, opts, per_dlc_req_args, per_dlc_invalid_args) |
Andrew | 67b5fa7 | 2020-02-05 14:14:48 -0800 | [diff] [blame] | 226 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 227 | if opts.build_package: |
| 228 | logging.info("Building package: DLC %s", opts.id) |
| 229 | params = dlc_lib.EbuildParams( |
| 230 | dlc_id=opts.id, |
| 231 | dlc_package=opts.package, |
| 232 | fs_type=opts.fs_type, |
| 233 | name=opts.name, |
| 234 | description=opts.description, |
| 235 | pre_allocated_blocks=opts.pre_allocated_blocks, |
| 236 | version=opts.version, |
| 237 | preload=opts.preload, |
| 238 | factory_install=opts.factory_install, |
| 239 | loadpin_verity_digest=opts.loadpin_verity_digest, |
| 240 | mount_file_required=opts.mount_file_required, |
| 241 | reserved=opts.reserved, |
| 242 | critical_update=opts.critical_update, |
| 243 | used_by=opts.used_by, |
| 244 | days_to_purge=opts.days_to_purge, |
| 245 | fullnamerev=opts.fullnamerev, |
Jae Hoon Kim | c3cf227 | 2022-10-28 23:59:10 +0000 | [diff] [blame] | 246 | scaled=opts.scaled, |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 247 | ) |
Jae Hoon Kim | b0ca685 | 2023-03-21 05:50:41 +0000 | [diff] [blame] | 248 | params.VerifyDlcParameters() |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 249 | params.StoreDlcParameters( |
| 250 | install_root_dir=opts.install_root_dir, sudo=True |
| 251 | ) |
Andrew | 67b5fa7 | 2020-02-05 14:14:48 -0800 | [diff] [blame] | 252 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 253 | else: |
| 254 | dlc_lib.InstallDlcImages( |
| 255 | sysroot=opts.sysroot, |
| 256 | dlc_id=opts.id, |
| 257 | install_root_dir=opts.install_root_dir, |
| 258 | preload=opts.preload, |
| 259 | factory_install=opts.factory_install, |
| 260 | src_dir=opts.src_dir, |
| 261 | rootfs=opts.rootfs, |
| 262 | stateful=opts.stateful, |
| 263 | board=opts.board, |
| 264 | ) |