blob: 8f50b826cee9dce74937af19e2deb012c1974a95 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2018 The ChromiumOS Authors
Xiaochu Liudeed0232018-06-26 10:25:34 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Xiaochu Liudeed0232018-06-26 10:25:34 -07004
Mike Frysinger88770ef2021-05-21 11:04:00 -04005"""Script to generate a DLC (Downloadable Content) artifact."""
Xiaochu Liudeed0232018-06-26 10:25:34 -07006
Chris McDonald59650c32021-07-20 15:29:28 -06007import logging
8
Xiaochu Liudeed0232018-06-26 10:25:34 -07009from chromite.lib import commandline
Chris McDonald59650c32021-07-20 15:29:28 -060010from chromite.lib import dlc_lib
Xiaochu Liudeed0232018-06-26 10:25:34 -070011
12
Xiaochu Liudeed0232018-06-26 10:25:34 -070013def GetParser():
Alex Klein1699fab2022-09-08 08:46:06 -060014 """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 Hassani22a25eb2019-01-11 14:25:02 -080044
Alex Klein1699fab2022-09-08 08:46:06 -060045 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 Kimc3cf2272022-10-28 23:59:10 +0000135 "--scaled",
136 default=False,
137 action="store_true",
138 help="DLC will be fed through scaling design.",
139 )
140 one_dlc.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600141 "--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 Liudeed0232018-06-26 10:25:34 -0700160
161
Andrew67b5fa72020-02-05 14:14:48 -0800162def ValidateArguments(parser, opts, req_flags, invalid_flags):
Alex Klein1699fab2022-09-08 08:46:06 -0600163 """Validates the correctness of the passed arguments.
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800164
Alex Klein1699fab2022-09-08 08:46:06 -0600165 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 )
Andrew67b5fa72020-02-05 14:14:48 -0800186
Alex Klein1699fab2022-09-08 08:46:06 -0600187 if opts.fs_type == dlc_lib.EXT4_TYPE:
188 parser.error("ext4 unsupported for DLC, see https://crbug.com/890060")
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800189
Alex Klein1699fab2022-09-08 08:46:06 -0600190 if opts.id:
191 dlc_lib.ValidateDlcIdentifier(opts.id)
192 if opts.package:
193 dlc_lib.ValidateDlcIdentifier(opts.package)
Amin Hassanibc1a4792019-10-24 14:39:57 -0700194
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800195
Xiaochu Liudeed0232018-06-26 10:25:34 -0700196def main(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600197 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 ]
Andrew67b5fa72020-02-05 14:14:48 -0800224
Alex Klein1699fab2022-09-08 08:46:06 -0600225 ValidateArguments(parser, opts, per_dlc_req_args, per_dlc_invalid_args)
Andrew67b5fa72020-02-05 14:14:48 -0800226
Alex Klein1699fab2022-09-08 08:46:06 -0600227 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 Kimc3cf2272022-10-28 23:59:10 +0000246 scaled=opts.scaled,
Alex Klein1699fab2022-09-08 08:46:06 -0600247 )
248 params.StoreDlcParameters(
249 install_root_dir=opts.install_root_dir, sudo=True
250 )
Andrew67b5fa72020-02-05 14:14:48 -0800251
Alex Klein1699fab2022-09-08 08:46:06 -0600252 else:
253 dlc_lib.InstallDlcImages(
254 sysroot=opts.sysroot,
255 dlc_id=opts.id,
256 install_root_dir=opts.install_root_dir,
257 preload=opts.preload,
258 factory_install=opts.factory_install,
259 src_dir=opts.src_dir,
260 rootfs=opts.rootfs,
261 stateful=opts.stateful,
262 board=opts.board,
263 )