blob: 6bf8c369875535d400ef3be9eec48901ad1b8a1d [file] [log] [blame]
Xiaochu Liudeed0232018-06-26 10:25:34 -07001# -*- coding: utf-8 -*-
2# Copyright 2018 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Script to generate a DLC (Downloadable Content) artifact."""
7
Mike Frysinger93e8ffa2019-07-03 20:24:18 -04008from __future__ import division
Xiaochu Liudeed0232018-06-26 10:25:34 -07009from __future__ import print_function
10
11import hashlib
12import json
13import math
14import os
Amin Hassani11a88cf2019-01-29 15:31:24 -080015import shutil
Xiaochu Liudeed0232018-06-26 10:25:34 -070016
17from chromite.lib import commandline
18from chromite.lib import cros_build_lib
Amin Hassanib97a5ee2019-01-23 14:44:43 -080019from chromite.lib import cros_logging as logging
Xiaochu Liudeed0232018-06-26 10:25:34 -070020from chromite.lib import osutils
21
Amin Hassani8f1cc0f2019-03-06 15:34:53 -080022from chromite.scripts import cros_set_lsb_release
Xiaochu Liudeed0232018-06-26 10:25:34 -070023
Amin Hassani2af75a92019-01-22 21:07:45 -080024DLC_META_DIR = 'opt/google/dlc/'
25DLC_IMAGE_DIR = 'build/rootfs/dlc/'
Amin Hassanid5742d32019-01-22 21:13:34 -080026LSB_RELEASE = 'etc/lsb-release'
27
Amin Hassani11a88cf2019-01-29 15:31:24 -080028# This file has major and minor version numbers that the update_engine client
29# supports. These values are needed for generating a delta/full payload.
30UPDATE_ENGINE_CONF = 'etc/update_engine.conf'
31
32_EXTRA_RESOURCES = (
33 UPDATE_ENGINE_CONF,
34)
35
Amin Hassanid5742d32019-01-22 21:13:34 -080036DLC_ID_KEY = 'DLC_ID'
Amin Hassanib5a48042019-03-18 14:30:51 -070037DLC_PACKAGE_KEY = 'DLC_PACKAGE'
Amin Hassanid5742d32019-01-22 21:13:34 -080038DLC_NAME_KEY = 'DLC_NAME'
Amin Hassani8f1cc0f2019-03-06 15:34:53 -080039DLC_APPID_KEY = 'DLC_RELEASE_APPID'
Amin Hassani2af75a92019-01-22 21:07:45 -080040
Amin Hassani22a25eb2019-01-11 14:25:02 -080041_SQUASHFS_TYPE = 'squashfs'
42_EXT4_TYPE = 'ext4'
43
Amin Hassanid5742d32019-01-22 21:13:34 -080044
Xiaochu Liudeed0232018-06-26 10:25:34 -070045def HashFile(file_path):
46 """Calculate the sha256 hash of a file.
47
48 Args:
49 file_path: (str) path to the file.
50
51 Returns:
52 [str]: The sha256 hash of the file.
53 """
54 sha256 = hashlib.sha256()
55 with open(file_path, 'rb') as f:
56 for b in iter(lambda: f.read(2048), b''):
57 sha256.update(b)
58 return sha256.hexdigest()
59
60
Amin Hassani174eb7e2019-01-18 11:11:24 -080061class DlcGenerator(object):
Xiaochu Liudeed0232018-06-26 10:25:34 -070062 """Object to generate DLC artifacts."""
63 # Block size for the DLC image.
64 # We use 4K for various reasons:
65 # 1. it's what imageloader (linux kernel) supports.
66 # 2. it's what verity supports.
67 _BLOCK_SIZE = 4096
68 # Blocks in the initial sparse image.
69 _BLOCKS = 500000
70 # Version of manifest file.
71 _MANIFEST_VERSION = 1
72
Amin Hassanicc7ffce2019-01-11 14:57:52 -080073 # The DLC root path inside the DLC module.
74 _DLC_ROOT_DIR = 'root'
75
Amin Hassanib97a5ee2019-01-23 14:44:43 -080076 def __init__(self, src_dir, sysroot, install_root_dir, fs_type,
Amin Hassanib5a48042019-03-18 14:30:51 -070077 pre_allocated_blocks, version, dlc_id, dlc_package, name):
Xiaochu Liudeed0232018-06-26 10:25:34 -070078 """Object initializer.
79
80 Args:
Xiaochu Liudeed0232018-06-26 10:25:34 -070081 src_dir: (str) path to the DLC source root directory.
Amin Hassanib97a5ee2019-01-23 14:44:43 -080082 sysroot: (str) The path to the build root directory.
Amin Hassani2af75a92019-01-22 21:07:45 -080083 install_root_dir: (str) The path to the root installation directory.
Xiaochu Liudeed0232018-06-26 10:25:34 -070084 fs_type: (str) file system type.
85 pre_allocated_blocks: (int) number of blocks pre-allocated on device.
86 version: (str) DLC version.
87 dlc_id: (str) DLC ID.
Amin Hassanib5a48042019-03-18 14:30:51 -070088 dlc_package: (str) DLC Package.
Xiaochu Liudeed0232018-06-26 10:25:34 -070089 name: (str) DLC name.
90 """
91 self.src_dir = src_dir
Amin Hassanib97a5ee2019-01-23 14:44:43 -080092 self.sysroot = sysroot
Amin Hassani2af75a92019-01-22 21:07:45 -080093 self.install_root_dir = install_root_dir
Xiaochu Liudeed0232018-06-26 10:25:34 -070094 self.fs_type = fs_type
95 self.pre_allocated_blocks = pre_allocated_blocks
96 self.version = version
97 self.dlc_id = dlc_id
Amin Hassanib5a48042019-03-18 14:30:51 -070098 self.dlc_package = dlc_package
Xiaochu Liudeed0232018-06-26 10:25:34 -070099 self.name = name
Amin Hassani2af75a92019-01-22 21:07:45 -0800100
101 self.meta_dir = os.path.join(self.install_root_dir, DLC_META_DIR,
Amin Hassanib5a48042019-03-18 14:30:51 -0700102 self.dlc_id, self.dlc_package)
Amin Hassani2af75a92019-01-22 21:07:45 -0800103 self.image_dir = os.path.join(self.install_root_dir, DLC_IMAGE_DIR,
Amin Hassanib5a48042019-03-18 14:30:51 -0700104 self.dlc_id, self.dlc_package)
Amin Hassani2af75a92019-01-22 21:07:45 -0800105 osutils.SafeMakedirs(self.meta_dir)
106 osutils.SafeMakedirs(self.image_dir)
107
Xiaochu Liudeed0232018-06-26 10:25:34 -0700108 # Create path for all final artifacts.
Amin Hassanib5a48042019-03-18 14:30:51 -0700109 self.dest_image = os.path.join(self.image_dir, 'dlc.img')
Amin Hassani2af75a92019-01-22 21:07:45 -0800110 self.dest_table = os.path.join(self.meta_dir, 'table')
111 self.dest_imageloader_json = os.path.join(self.meta_dir, 'imageloader.json')
Xiaochu Liudeed0232018-06-26 10:25:34 -0700112
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700113 # Log out the member variable values initially set.
114 logging.debug('Initial internal values of DlcGenerator: %s',
115 json.dumps(self.__dict__, sort_keys=True))
116
Xiaochu Liudeed0232018-06-26 10:25:34 -0700117 def SquashOwnerships(self, path):
118 """Squash the owernships & permissions for files.
119
120 Args:
121 path: (str) path that contains all files to be processed.
122 """
123 cros_build_lib.SudoRunCommand(['chown', '-R', '0:0', path])
124 cros_build_lib.SudoRunCommand(
125 ['find', path, '-exec', 'touch', '-h', '-t', '197001010000.00', '{}',
126 '+'])
127
128 def CreateExt4Image(self):
129 """Create an ext4 image."""
130 with osutils.TempDir(prefix='dlc_') as temp_dir:
131 mount_point = os.path.join(temp_dir, 'mount_point')
132 # Create a raw image file.
133 with open(self.dest_image, 'w') as f:
134 f.truncate(self._BLOCKS * self._BLOCK_SIZE)
135 # Create an ext4 file system on the raw image.
136 cros_build_lib.RunCommand(
137 ['/sbin/mkfs.ext4', '-b', str(self._BLOCK_SIZE), '-O',
138 '^has_journal', self.dest_image], capture_output=True)
139 # Create the mount_point directory.
140 osutils.SafeMakedirs(mount_point)
141 # Mount the ext4 image.
142 osutils.MountDir(self.dest_image, mount_point, mount_opts=('loop', 'rw'))
Amin Hassanicc7ffce2019-01-11 14:57:52 -0800143
Xiaochu Liudeed0232018-06-26 10:25:34 -0700144 try:
Amin Hassani11a88cf2019-01-29 15:31:24 -0800145 self.SetupDlcImageFiles(mount_point)
Xiaochu Liudeed0232018-06-26 10:25:34 -0700146 finally:
147 # Unmount the ext4 image.
148 osutils.UmountDir(mount_point)
149 # Shrink to minimum size.
150 cros_build_lib.RunCommand(
151 ['/sbin/e2fsck', '-y', '-f', self.dest_image], capture_output=True)
152 cros_build_lib.RunCommand(
153 ['/sbin/resize2fs', '-M', self.dest_image], capture_output=True)
154
155 def CreateSquashfsImage(self):
156 """Create a squashfs image."""
157 with osutils.TempDir(prefix='dlc_') as temp_dir:
Amin Hassani22a25eb2019-01-11 14:25:02 -0800158 squashfs_root = os.path.join(temp_dir, 'squashfs-root')
Amin Hassani11a88cf2019-01-29 15:31:24 -0800159 self.SetupDlcImageFiles(squashfs_root)
Amin Hassani22a25eb2019-01-11 14:25:02 -0800160
161 cros_build_lib.RunCommand(['mksquashfs', squashfs_root, self.dest_image,
162 '-4k-align', '-noappend'],
163 capture_output=True)
164
165 # We changed the ownership and permissions of the squashfs_root
166 # directory. Now we need to remove it manually.
167 osutils.RmDir(squashfs_root, sudo=True)
Xiaochu Liudeed0232018-06-26 10:25:34 -0700168
Amin Hassani11a88cf2019-01-29 15:31:24 -0800169 def SetupDlcImageFiles(self, dlc_dir):
170 """Prepares the directory dlc_dir with all the files a DLC needs.
171
172 Args:
173 dlc_dir: (str) The path to where to setup files inside the DLC.
174 """
175 dlc_root_dir = os.path.join(dlc_dir, self._DLC_ROOT_DIR)
176 osutils.SafeMakedirs(dlc_root_dir)
177 osutils.CopyDirContents(self.src_dir, dlc_root_dir)
178 self.PrepareLsbRelease(dlc_dir)
179 self.CollectExtraResources(dlc_dir)
180 self.SquashOwnerships(dlc_dir)
181
Amin Hassanid5742d32019-01-22 21:13:34 -0800182 def PrepareLsbRelease(self, dlc_dir):
183 """Prepare the file /etc/lsb-release in the DLC module.
184
185 This file is used dropping some identification parameters for the DLC.
186
187 Args:
188 dlc_dir: (str) The path to root directory of the DLC. e.g. mounted point
189 when we are creating the image.
190 """
Amin Hassani8f1cc0f2019-03-06 15:34:53 -0800191 # Reading the platform APPID and creating the DLC APPID.
192 platform_lsb_release = osutils.ReadFile(os.path.join(self.sysroot,
193 LSB_RELEASE))
194 app_id = None
195 for line in platform_lsb_release.split('\n'):
196 if line.startswith(cros_set_lsb_release.LSB_KEY_APPID_RELEASE):
197 app_id = line.split('=')[1]
198 if app_id is None:
199 raise Exception('%s does not have a valid key %s' %
200 (platform_lsb_release,
201 cros_set_lsb_release.LSB_KEY_APPID_RELEASE))
Amin Hassanid5742d32019-01-22 21:13:34 -0800202
203 fields = {
204 DLC_ID_KEY: self.dlc_id,
Amin Hassanib5a48042019-03-18 14:30:51 -0700205 DLC_PACKAGE_KEY: self.dlc_package,
Amin Hassanid5742d32019-01-22 21:13:34 -0800206 DLC_NAME_KEY: self.name,
Amin Hassani8f1cc0f2019-03-06 15:34:53 -0800207 # The DLC appid is generated by concatenating the platform appid with
208 # the DLC ID using an underscore. This pattern should never be changed
209 # once set otherwise it can break a lot of things!
210 DLC_APPID_KEY: '%s_%s' % (app_id, self.dlc_id),
Amin Hassanid5742d32019-01-22 21:13:34 -0800211 }
Amin Hassani8f1cc0f2019-03-06 15:34:53 -0800212
213 lsb_release = os.path.join(dlc_dir, LSB_RELEASE)
214 osutils.SafeMakedirs(os.path.dirname(lsb_release))
Amin Hassanid5742d32019-01-22 21:13:34 -0800215 content = ''.join(['%s=%s\n' % (k, v) for k, v in fields.items()])
216 osutils.WriteFile(lsb_release, content)
217
Amin Hassani11a88cf2019-01-29 15:31:24 -0800218 def CollectExtraResources(self, dlc_dir):
219 """Collect the extra resources needed by the DLC module.
220
221 Look at the documentation around _EXTRA_RESOURCES.
222
223 Args:
224 dlc_dir: (str) The path to root directory of the DLC. e.g. mounted point
225 when we are creating the image.
226 """
227 for r in _EXTRA_RESOURCES:
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800228 source_path = os.path.join(self.sysroot, r)
Amin Hassani11a88cf2019-01-29 15:31:24 -0800229 target_path = os.path.join(dlc_dir, r)
230 osutils.SafeMakedirs(os.path.dirname(target_path))
231 shutil.copyfile(source_path, target_path)
232
Xiaochu Liudeed0232018-06-26 10:25:34 -0700233 def CreateImage(self):
234 """Create the image and copy the DLC files to it."""
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700235 logging.info('Creating the DLC image.')
Amin Hassani22a25eb2019-01-11 14:25:02 -0800236 if self.fs_type == _EXT4_TYPE:
Xiaochu Liudeed0232018-06-26 10:25:34 -0700237 self.CreateExt4Image()
Amin Hassani22a25eb2019-01-11 14:25:02 -0800238 elif self.fs_type == _SQUASHFS_TYPE:
Xiaochu Liudeed0232018-06-26 10:25:34 -0700239 self.CreateSquashfsImage()
240 else:
241 raise ValueError('Wrong fs type: %s used:' % self.fs_type)
242
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700243 def VerifyImageSize(self):
Xiaochu Liu36b30592019-08-06 09:39:54 -0700244 """Verify the image can fit to the reserved file."""
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700245 logging.info('Verifying the DLC image size.')
246 image_bytes = os.path.getsize(self.dest_image)
Xiaochu Liu36b30592019-08-06 09:39:54 -0700247 preallocated_bytes = self.pre_allocated_blocks * self._BLOCK_SIZE
248 # Verifies the actual size of the DLC image is NOT smaller than the
249 # preallocated space.
250 if preallocated_bytes < image_bytes:
251 raise ValueError(
252 'The DLC_PREALLOC_BLOCKS (%s) value set in DLC ebuild resulted in a '
253 'max size of DLC_PREALLOC_BLOCKS * 4K (%s) bytes the DLC image is '
254 'allowed to occupy. The value is smaller than the actual image size '
255 '(%s) required. Increase DLC_PREALLOC_BLOCKS in your ebuild to at '
256 'least %d.' % (
257 self.pre_allocated_blocks, preallocated_bytes, image_bytes,
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700258 self.GetOptimalImageBlockSize(image_bytes)))
259
260 def GetOptimalImageBlockSize(self, image_bytes):
261 """Given the image bytes, get the least amount of blocks required."""
262 return int(math.ceil(image_bytes / self._BLOCK_SIZE))
Xiaochu Liu36b30592019-08-06 09:39:54 -0700263
Xiaochu Liudeed0232018-06-26 10:25:34 -0700264 def GetImageloaderJsonContent(self, image_hash, table_hash, blocks):
265 """Return the content of imageloader.json file.
266
267 Args:
268 image_hash: (str) sha256 hash of the DLC image.
269 table_hash: (str) sha256 hash of the DLC table file.
270 blocks: (int) number of blocks in the DLC image.
271
272 Returns:
273 [str]: content of imageloader.json file.
274 """
275 return {
276 'fs-type': self.fs_type,
277 'id': self.dlc_id,
Amin Hassanib5a48042019-03-18 14:30:51 -0700278 'package': self.dlc_package,
Xiaochu Liudeed0232018-06-26 10:25:34 -0700279 'image-sha256-hash': image_hash,
280 'image-type': 'dlc',
281 'is-removable': True,
282 'manifest-version': self._MANIFEST_VERSION,
283 'name': self.name,
284 'pre-allocated-size': self.pre_allocated_blocks * self._BLOCK_SIZE,
285 'size': blocks * self._BLOCK_SIZE,
286 'table-sha256-hash': table_hash,
287 'version': self.version,
288 }
289
290 def GenerateVerity(self):
291 """Generate verity parameters and hashes for the image."""
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700292 logging.info('Generating DLC image verity.')
Xiaochu Liudeed0232018-06-26 10:25:34 -0700293 with osutils.TempDir(prefix='dlc_') as temp_dir:
294 hash_tree = os.path.join(temp_dir, 'hash_tree')
295 # Get blocks in the image.
296 blocks = math.ceil(
297 os.path.getsize(self.dest_image) / self._BLOCK_SIZE)
298 result = cros_build_lib.RunCommand(
299 ['verity', 'mode=create', 'alg=sha256', 'payload=' + self.dest_image,
300 'payload_blocks=' + str(blocks), 'hashtree=' + hash_tree,
301 'salt=random'], capture_output=True)
302 table = result.output
303
304 # Append the merkle tree to the image.
305 osutils.WriteFile(self.dest_image, osutils.ReadFile(hash_tree), 'a+')
306
307 # Write verity parameter to table file.
308 osutils.WriteFile(self.dest_table, table)
309
310 # Compute image hash.
311 image_hash = HashFile(self.dest_image)
312 table_hash = HashFile(self.dest_table)
313 # Write image hash to imageloader.json file.
314 blocks = math.ceil(
315 os.path.getsize(self.dest_image) / self._BLOCK_SIZE)
316 imageloader_json_content = self.GetImageloaderJsonContent(
317 image_hash, table_hash, int(blocks))
318 with open(self.dest_imageloader_json, 'w') as f:
319 json.dump(imageloader_json_content, f)
320
321 def GenerateDLC(self):
322 """Generate a DLC artifact."""
323 # Create the image and copy the DLC files to it.
324 self.CreateImage()
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700325 # Verify the image created is within preallocated size.
326 self.VerifyImageSize()
Xiaochu Liudeed0232018-06-26 10:25:34 -0700327 # Generate hash tree and other metadata.
328 self.GenerateVerity()
329
330
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800331def CopyAllDlcs(sysroot, install_root_dir):
332 """Copies all DLC image files into the images directory.
333
334 Copies the DLC image files in the given build directory into the given DLC
335 image directory. If the DLC build directory does not exist, or there is no DLC
336 for that board, this function does nothing.
337
338 Args:
339 sysroot: Path to directory containing DLC images, e.g /build/<board>.
340 install_root_dir: Path to DLC output directory,
341 e.g. src/build/images/<board>/<version>.
342 """
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800343 build_dir = os.path.join(sysroot, DLC_IMAGE_DIR)
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700344 output_dir = os.path.join(install_root_dir, 'dlc')
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800345
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700346 if not os.path.exists(build_dir):
347 logging.info('DLC build directory (%s) does not exists, ignorning.',
348 build_dir)
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800349 return
350
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700351 if not os.listdir(build_dir):
352 logging.info('There are no DLC(s) to copy to output, ignoring.')
353 return
354
355 logging.info('Copying all DLC images from %s to %s.', build_dir, output_dir)
Amin Hassani6c0228b2019-03-04 13:42:33 -0800356 logging.info('Detected the following DLCs: %s',
357 ', '.join(os.listdir(build_dir)))
358
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800359 osutils.SafeMakedirs(output_dir)
360 osutils.CopyDirContents(build_dir, output_dir)
361
Amin Hassani6c0228b2019-03-04 13:42:33 -0800362 logging.info('Done copying the DLCs to their destination.')
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800363
Xiaochu Liudeed0232018-06-26 10:25:34 -0700364def GetParser():
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800365 """Creates an argument parser and returns it."""
Xiaochu Liudeed0232018-06-26 10:25:34 -0700366 parser = commandline.ArgumentParser(description=__doc__)
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800367 # This script is used both for building an individual DLC or copying all final
368 # DLCs images to their final destination nearby chromiumsos_test_image.bin,
369 # etc. These two arguments are required in both cases.
370 parser.add_argument('--sysroot', type='path', metavar='DIR', required=True,
371 help="The root path to the board's build root, e.g. "
Mike Frysinger80de5012019-08-01 14:10:53 -0400372 '/build/eve')
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800373 parser.add_argument('--install-root-dir', type='path', metavar='DIR',
374 required=True,
375 help='If building a specific DLC, it is the root path to'
376 ' install DLC images (%s) and metadata (%s). Otherwise it'
377 ' is the target directory where the Chrome OS images gets'
378 ' dropped in build_image, e.g. '
379 'src/build/images/<board>/latest.' % (DLC_IMAGE_DIR,
380 DLC_META_DIR))
Amin Hassani22a25eb2019-01-11 14:25:02 -0800381
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800382 one_dlc = parser.add_argument_group('Arguments required for building only '
383 'one DLC')
384 one_dlc.add_argument('--src-dir', type='path', metavar='SRC_DIR_PATH',
385 help='Root directory path that contains all DLC files '
386 'to be packed.')
387 one_dlc.add_argument('--pre-allocated-blocks', type=int,
388 metavar='PREALLOCATEDBLOCKS',
389 help='Number of blocks (block size is 4k) that need to'
390 'be pre-allocated on device.')
391 one_dlc.add_argument('--version', metavar='VERSION', help='DLC Version.')
392 one_dlc.add_argument('--id', metavar='ID', help='DLC ID (unique per DLC).')
Amin Hassanib5a48042019-03-18 14:30:51 -0700393 one_dlc.add_argument('--package', metavar='PACKAGE',
394 help='The package ID that is unique within a DLC, One'
395 ' DLC cannot have duplicate package IDs.')
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800396 one_dlc.add_argument('--name', metavar='NAME',
397 help='A human-readable name for the DLC.')
398 one_dlc.add_argument('--fs-type', metavar='FS_TYPE', default=_SQUASHFS_TYPE,
399 choices=(_SQUASHFS_TYPE, _EXT4_TYPE),
400 help='File system type of the image.')
Xiaochu Liudeed0232018-06-26 10:25:34 -0700401 return parser
402
403
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800404def ValidateArguments(opts):
405 """Validates the correctness of the passed arguments.
406
407 Args:
408 opts: Parsed arguments.
409 """
410 # Make sure if the intention is to build one DLC, all the required arguments
411 # are passed.
412 per_dlc_req_args = ('src_dir', 'pre_allocated_blocks', 'version', 'id',
Amin Hassanib5a48042019-03-18 14:30:51 -0700413 'package', 'name')
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800414 if (opts.id and
415 not all(vars(opts)[arg] is not None for arg in per_dlc_req_args)):
416 raise Exception('If the intention is to build only one DLC, all the flags'
417 '%s required for it should be passed .' % per_dlc_req_args)
418
419 if opts.fs_type == _EXT4_TYPE:
Jae Hoon Kime5b88622019-08-23 11:11:33 -0700420 raise Exception('ext4 unsupported for DLC, see https://crbug.com/890060')
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800421
422
Xiaochu Liudeed0232018-06-26 10:25:34 -0700423def main(argv):
424 opts = GetParser().parse_args(argv)
425 opts.Freeze()
426
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800427 ValidateArguments(opts)
Amin Hassani2af75a92019-01-22 21:07:45 -0800428
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800429 if opts.id:
430 logging.info('Building DLC %s', opts.id)
431 dlc_generator = DlcGenerator(src_dir=opts.src_dir,
432 sysroot=opts.sysroot,
433 install_root_dir=opts.install_root_dir,
434 fs_type=opts.fs_type,
435 pre_allocated_blocks=opts.pre_allocated_blocks,
436 version=opts.version,
437 dlc_id=opts.id,
Amin Hassanib5a48042019-03-18 14:30:51 -0700438 dlc_package=opts.package,
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800439 name=opts.name)
440 dlc_generator.GenerateDLC()
441 else:
Amin Hassanib97a5ee2019-01-23 14:44:43 -0800442 CopyAllDlcs(opts.sysroot, opts.install_root_dir)