~ubuntu-branches/ubuntu/trusty/linaro-image-tools/trusty-proposed

« back to all changes in this revision

Viewing changes to linaro_image_tools/media_create/boards.py

  • Committer: Package Import Robot
  • Author(s): Fathi Boudra
  • Date: 2012-09-26 12:21:49 UTC
  • mfrom: (271.1.27)
  • Revision ID: package-import@ubuntu.com-20120926122149-rnhe2rio87b3mdyt
Tags: 2012.09.1-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
import string
38
38
import logging
39
39
from linaro_image_tools.hwpack.config import Config
 
40
from linaro_image_tools.hwpack.builder import PackageUnpacker
40
41
 
41
42
from parted import Device
42
43
 
128
129
        self.hwpack_tarfiles = []
129
130
        self.bootloader = bootloader
130
131
        self.board = board
 
132
        self.tempdirs = {}
131
133
 
132
134
    class FakeSecHead(object):
133
135
        """ Add a fake section header to the metadata file.
162
164
        if self.tempdir is not None and os.path.exists(self.tempdir):
163
165
            shutil.rmtree(self.tempdir)
164
166
 
165
 
    def get_field(self, field):
 
167
        for name in self.tempdirs:
 
168
            tempdir = self.tempdirs[name]
 
169
            if tempdir is not None and os.path.exists(tempdir):
 
170
                shutil.rmtree(tempdir)
 
171
 
 
172
    def get_field(self, field, return_keys=False):
166
173
        data = None
167
174
        hwpack_with_data = None
 
175
        keys = None
168
176
        for hwpack_tarfile in self.hwpack_tarfiles:
169
177
            metadata = hwpack_tarfile.extractfile(self.metadata_filename)
170
178
            lines = metadata.readlines()
181
189
                                                              new_data)
182
190
                    data = new_data
183
191
                    hwpack_with_data = hwpack_tarfile
 
192
                    if return_keys:
 
193
                        keys = parser.get_last_used_keys()
184
194
            except ConfigParser.NoOptionError:
185
195
                continue
186
196
 
 
197
        if return_keys:
 
198
            return data, hwpack_with_data, keys
187
199
        return data, hwpack_with_data
188
200
 
189
201
    def get_format(self):
202
214
        return format
203
215
 
204
216
    def get_file(self, file_alias):
205
 
        file_name, hwpack_tarfile = self.get_field(file_alias)
206
 
        if file_name is not None:
207
 
            hwpack_tarfile.extract(file_name, self.tempdir)
208
 
            file_name = os.path.join(self.tempdir, file_name)
209
 
        return file_name
 
217
        """Get file(s) from a hwpack.
 
218
        :param file_alias: Property name (not field name) which contains
 
219
                           file reference(s)
 
220
        :return: path to a file or list of paths to files
 
221
        """
 
222
        file_names, hwpack_tarfile, keys = self.get_field(file_alias,
 
223
                                                          return_keys=True)
 
224
        if not file_names:
 
225
            return file_names
 
226
        single = False
 
227
        if not isinstance(file_names, list):
 
228
            single = True
 
229
            file_names = [file_names]
 
230
        out_files = []
 
231
 
 
232
        # Depending on if board and/or bootloader were used to look up the
 
233
        # file we are getting, we need to prepend those names to the path
 
234
        # to get the correct extracted file from the hardware pack.
 
235
        config_names = [("board", "boards"), ("bootloader", "bootloaders")]
 
236
        base_path = ""
 
237
        if keys:
 
238
            # If keys is non-empty, we have a V3 config option that was
 
239
            # modified by the bootloader and/or boot option...
 
240
            for name, key in config_names:
 
241
                if self.get_field(name):
 
242
                    value = self.get_field(name)[0]
 
243
                    if keys[0] == key:
 
244
                        base_path = os.path.join(base_path, value)
 
245
                        keys = keys[1:]
 
246
 
 
247
        for f in file_names:
 
248
            # Check that the base path is needed. If the file doesn't exist,
 
249
            # try without it (this provides fallback to V2 style directory
 
250
            # layouts with a V3 config).
 
251
            path_inc_board_and_bootloader = os.path.join(base_path, f)
 
252
            if path_inc_board_and_bootloader in hwpack_tarfile.getnames():
 
253
                f = path_inc_board_and_bootloader
 
254
            hwpack_tarfile.extract(f, self.tempdir)
 
255
            f = os.path.join(self.tempdir, f)
 
256
            out_files.append(f)
 
257
        if single:
 
258
            return out_files[0]
 
259
        return out_files
 
260
 
 
261
    def list_packages(self):
 
262
        """Return list of (package names, TarFile object containing them)"""
 
263
        packages = []
 
264
        for tf in self.hwpack_tarfiles:
 
265
            for name in tf.getnames():
 
266
                if name.startswith("pkgs/") and name.endswith(".deb"):
 
267
                    packages.append((tf, name))
 
268
        return packages
 
269
 
 
270
    def find_package_for(self, name, version=None, revision=None,
 
271
                         architecture=None):
 
272
        """Find a package that matches the name, version, rev and arch given.
 
273
 
 
274
        Packages are named according to the debian specification:
 
275
        http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html
 
276
        <name>_<Version>-<DebianRevisionNumber>_<DebianArchitecture>.deb
 
277
        DebianRevisionNumber seems to be optional.
 
278
        Use this spec to return a package matching the requirements given.
 
279
        """
 
280
        for tar_file, package in self.list_packages():
 
281
            file_name = os.path.basename(package)
 
282
            dpkg_chunks = re.search("^(.+)_(.+)_(.+)\.deb$",
 
283
                                    file_name)
 
284
            assert dpkg_chunks, "Could not split package file name into"\
 
285
                "<name>_<Version>_<DebianArchitecture>.deb"
 
286
 
 
287
            pkg_name = dpkg_chunks.group(1)
 
288
            pkg_version = dpkg_chunks.group(2)
 
289
            pkg_architecture = dpkg_chunks.group(3)
 
290
 
 
291
            ver_chunks = re.search("^(.+)-(.+)$", pkg_version)
 
292
            if ver_chunks:
 
293
                pkg_version = ver_chunks.group(1)
 
294
                pkg_revision = ver_chunks.group(2)
 
295
            else:
 
296
                pkg_revision = None
 
297
 
 
298
            if name != pkg_name:
 
299
                continue
 
300
            if version != None and str(version) != pkg_version:
 
301
                continue
 
302
            if revision != None and str(revision) != pkg_revision:
 
303
                continue
 
304
            if (architecture != None and
 
305
                str(architecture) != pkg_architecture):
 
306
                continue
 
307
 
 
308
            # Got a matching package - return its path inside the tarball
 
309
            return tar_file, package
 
310
 
 
311
        # Failed to find a matching package - return None
 
312
        return None
 
313
 
 
314
    def get_file_from_package(self, file_path, package_name,
 
315
                              package_version=None, package_revision=None,
 
316
                              package_architecture=None):
 
317
        """Extract named file from package specified by name, ver, rev, arch.
 
318
 
 
319
        File is extracted from the package matching the given specification
 
320
        to a temporary directory. The absolute path to the extracted file is
 
321
        returned.
 
322
        """
 
323
 
 
324
        package_info = self.find_package_for(package_name,
 
325
                                             package_version,
 
326
                                             package_revision,
 
327
                                             package_architecture)
 
328
        if package_info is None:
 
329
            return None
 
330
        tar_file, package = package_info
 
331
 
 
332
        # Avoid unpacking hardware pack more than once by assigning each one
 
333
        # its own tempdir to unpack into.
 
334
        # TODO: update logic that uses self.tempdir so we can get rid of this
 
335
        # by sharing nicely.
 
336
        if not package in self.tempdirs:
 
337
            self.tempdirs[package] = tempfile.mkdtemp()
 
338
        tempdir = self.tempdirs[package]
 
339
 
 
340
        # We extract everything in the hardware pack so we don't have to worry
 
341
        # about chasing links (extract a link, find where it points to, extract
 
342
        # that...). This is slower, but more reliable.
 
343
        tar_file.extractall(tempdir)
 
344
        package_path = os.path.join(tempdir, package)
 
345
 
 
346
        with PackageUnpacker() as self.package_unpacker:
 
347
            extracted_file = self.package_unpacker.get_file(package_path,
 
348
                                                            file_path)
 
349
            after_tmp = re.sub(self.package_unpacker.tempdir, "",
 
350
                               extracted_file).lstrip("/\\")
 
351
            extract_dir = os.path.join(tempdir, "extracted",
 
352
                                       os.path.dirname(after_tmp))
 
353
            os.makedirs(extract_dir)
 
354
            shutil.move(extracted_file, extract_dir)
 
355
            extracted_file = os.path.join(extract_dir,
 
356
                                          os.path.basename(extracted_file))
 
357
        return extracted_file
210
358
 
211
359
 
212
360
class BoardConfig(object):
450
598
                cls.SAMSUNG_V310_BL2_START = (cls.SAMSUNG_V310_ENV_START +
451
599
                                              cls.SAMSUNG_V310_ENV_LEN)
452
600
 
 
601
            cls.bootloader_copy_files = cls.hardwarepack_handler.get_field(
 
602
                "bootloader_copy_files")[0]
 
603
 
 
604
            cls.bootloader = cls.hardwarepack_handler.get_field(
 
605
                                "bootloader")
 
606
            cls.board = board
 
607
 
453
608
    @classmethod
454
609
    def get_file(cls, file_alias, default=None):
455
610
        # XXX remove the 'default' parameter when V1 support is removed!
778
933
        bootloader_parts_dir = os.path.join(chroot_dir, parts_dir)
779
934
        cmd_runner.run(['mkdir', '-p', boot_disk]).wait()
780
935
        with partition_mounted(boot_partition, boot_disk):
781
 
            if cls.bootloader_file_in_boot_part:
782
 
                with cls.hardwarepack_handler:
 
936
            with cls.hardwarepack_handler:
 
937
                if cls.bootloader_file_in_boot_part:
783
938
                    # <legacy v1 support>
784
939
                    if cls.bootloader_flavor is not None:
785
940
                        default = os.path.join(
801
956
                        ['cp', '-v', bootloader_bin, boot_disk], as_root=True)
802
957
                    proc.wait()
803
958
 
 
959
                # Handle copy_files field.
 
960
                cls.copy_files(boot_disk)
 
961
 
804
962
            cls.make_boot_files(
805
963
                bootloader_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
806
964
                rootfs_id, boot_disk, boot_device_or_file)
807
965
 
808
966
    @classmethod
 
967
    def copy_files(cls, boot_disk):
 
968
        """Handle the copy_files metadata field."""
 
969
 
 
970
        # Extract anything specified by copy_files sections
 
971
        # self.bootloader_copy_files is always of the form:
 
972
        # {'source_package':
 
973
        #  [
 
974
        #   {'source_path': 'dest_path'}
 
975
        #  ]
 
976
        # }
 
977
        if cls.bootloader_copy_files is None:
 
978
            return
 
979
 
 
980
        for source_package, file_list in cls.bootloader_copy_files.iteritems():
 
981
            for file_info in file_list:
 
982
                for source_path, dest_path in file_info.iteritems():
 
983
                    source = cls.hardwarepack_handler.get_file_from_package(
 
984
                        source_path, source_package)
 
985
                    dest_path = dest_path.lstrip("/\\")
 
986
                    dirname = os.path.dirname(dest_path)
 
987
                    dirname = os.path.join(boot_disk, dirname)
 
988
                    if not os.path.exists(dirname):
 
989
                        cmd_runner.run(["mkdir", "-p", dirname],
 
990
                                       as_root=True).wait()
 
991
                    proc = cmd_runner.run(
 
992
                        ['cp', '-v', source,
 
993
                         os.path.join(boot_disk, dest_path)], as_root=True)
 
994
                    proc.wait()
 
995
 
 
996
    @classmethod
809
997
    def _get_kflavor_files(cls, path):
810
998
        """Search for kernel, initrd and optional dtb in path."""
811
999
        if cls.kernel_flavors is None:
1385
1573
    supports_writing_to_mmc = False
1386
1574
 
1387
1575
    @classmethod
1388
 
    def _get_bootcmd(cls, d_img_data):
 
1576
    def _get_bootcmd(cls, i_img_data, d_img_data):
1389
1577
        """Get the bootcmd for FastModel.
1390
1578
 
1391
1579
        We override this as we don't do uboot.