aboutsummaryrefslogtreecommitdiff
path: root/linaro_image_tools/media_create/boards.py
diff options
context:
space:
mode:
authorJames Tunnicliffe <james.tunnicliffe@linaro.org>2012-09-10 10:40:55 +0100
committerJames Tunnicliffe <james.tunnicliffe@linaro.org>2012-09-10 10:40:55 +0100
commitfa763179709cfa0be81e611faff895bd0d3835ce (patch)
tree2a1a29cdfbbf7067e6d4eb0dbf29b0522885d56f /linaro_image_tools/media_create/boards.py
parent1c495bc7c0a02762aefe9b6357ce9b4488b35079 (diff)
Refactored copy_files support.
* Don't extract files into hwpack (leave in package) * Extract files to target path. TODO: * Rename file support.
Diffstat (limited to 'linaro_image_tools/media_create/boards.py')
-rw-r--r--linaro_image_tools/media_create/boards.py138
1 files changed, 129 insertions, 9 deletions
diff --git a/linaro_image_tools/media_create/boards.py b/linaro_image_tools/media_create/boards.py
index 1809e4a..d54f10e 100644
--- a/linaro_image_tools/media_create/boards.py
+++ b/linaro_image_tools/media_create/boards.py
@@ -37,6 +37,7 @@ import shutil
import string
import logging
from linaro_image_tools.hwpack.config import Config
+from linaro_image_tools.hwpack.builder import PackageUnpacker
from parted import Device
@@ -128,6 +129,7 @@ class HardwarepackHandler(object):
self.hwpack_tarfiles = []
self.bootloader = bootloader
self.board = board
+ self.tempdirs = {}
class FakeSecHead(object):
""" Add a fake section header to the metadata file.
@@ -162,6 +164,11 @@ class HardwarepackHandler(object):
if self.tempdir is not None and os.path.exists(self.tempdir):
shutil.rmtree(self.tempdir)
+ for name in self.tempdirs:
+ tempdir = self.tempdirs[name]
+ if tempdir is not None and os.path.exists(tempdir):
+ shutil.rmtree(tempdir)
+
def get_field(self, field):
data = None
hwpack_with_data = None
@@ -223,6 +230,97 @@ class HardwarepackHandler(object):
return out_files[0]
return out_files
+ def list_packages(self):
+ """Return list of (package names, TarFile object containing them)"""
+ packages = []
+ for tf in self.hwpack_tarfiles:
+ for name in tf.getnames():
+ if name.startswith("pkgs/") and name.endswith(".deb"):
+ packages.append((tf, name))
+ return packages
+
+ def find_package_for(self, name, version=None, revision=None,
+ architecture=None):
+ """Find a package that matches the name, version, rev and arch given.
+
+ Packages are named according to the debian specification:
+ http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html
+ <name>_<Version>-<DebianRevisionNumber>_<DebianArchitecture>.deb
+ DebianRevisionNumber seems to be optional.
+ Use this spec to return a package matching the requirements given.
+ """
+ for tar_file, package in self.list_packages():
+ file_name = os.path.basename(package)
+ dpkg_chunks = re.search("^(.+)_(.+)_(.+)\.deb$",
+ file_name)
+ assert dpkg_chunks, "Could not split package file name into"\
+ "<name>_<Version>_<DebianArchitecture>.deb"
+
+ pkg_name = dpkg_chunks.group(1)
+ pkg_version = dpkg_chunks.group(2)
+ pkg_architecture = dpkg_chunks.group(3)
+
+ ver_chunks = re.search("^(.+)-(.+)$", pkg_version)
+ if ver_chunks:
+ pkg_version = ver_chunks.group(1)
+ pkg_revision = ver_chunks.group(2)
+ else:
+ pkg_revision = None
+
+ if name != pkg_name:
+ continue
+ if version != None and str(version) != pkg_version:
+ continue
+ if revision != None and str(revision) != pkg_revision:
+ continue
+ if (architecture != None and
+ str(architecture) != pkg_architecture):
+ continue
+
+ # Got a matching package - return its path inside the tarball
+ return tar_file, package
+
+ # Failed to find a matching package - return None
+ return None
+
+ def get_file_from_package(self, file_path, package_name,
+ package_version=None, package_revision=None,
+ package_architecture=None):
+ """Extract named file from package specified by name, ver, rev, arch.
+
+ File is extracted from the package matching the given specification
+ to a temporary directory. The absolute path to the extracted file is
+ returned.
+ """
+
+ package_info = self.find_package_for(package_name,
+ package_version,
+ package_revision,
+ package_architecture)
+ if package_info is None:
+ return None
+ tar_file, package = package_info
+
+ # Avoid unpacking hardware pack more than once by assigning each one
+ # its own tempdir to unpack into.
+ # TODO: update logic that uses self.tempdir so we can get rid of this
+ # by sharing nicely.
+ if not package in self.tempdirs:
+ self.tempdirs[package] = tempfile.mkdtemp()
+ tempdir = self.tempdirs[package]
+
+ # We extract everything in the hardware pack so we don't have to worry
+ # about chasing links (extract a link, find where it points to, extract
+ # that...). This is slower, but more reliable.
+ tar_file.extractall(tempdir)
+ package_path = os.path.join(tempdir, package)
+
+ with PackageUnpacker() as self.package_unpacker:
+ extracted_file = self.package_unpacker.get_file(package_path,
+ file_path)
+
+ return extracted_file
+
class BoardConfig(object):
board = None
@@ -465,6 +563,9 @@ class BoardConfig(object):
cls.SAMSUNG_V310_BL2_START = (cls.SAMSUNG_V310_ENV_START +
cls.SAMSUNG_V310_ENV_LEN)
+ cls.bootloader_copy_files = cls.hardwarepack_handler.get_field(
+ "bootloader_copy_files")
+
@classmethod
def get_file(cls, file_alias, default=None):
# XXX remove the 'default' parameter when V1 support is removed!
@@ -793,7 +894,6 @@ class BoardConfig(object):
bootloader_parts_dir = os.path.join(chroot_dir, parts_dir)
cmd_runner.run(['mkdir', '-p', boot_disk]).wait()
with partition_mounted(boot_partition, boot_disk):
- boot_files = []
with cls.hardwarepack_handler:
if cls.bootloader_file_in_boot_part:
# <legacy v1 support>
@@ -813,22 +913,42 @@ class BoardConfig(object):
assert bootloader_bin is not None, (
"bootloader binary could not be found")
- boot_files.append(bootloader_bin)
-
- copy_files = cls.get_file('boot_copy_files')
- if copy_files:
- boot_files.extend(copy_files)
-
- for f in boot_files:
proc = cmd_runner.run(
- ['cp', '-v', f, boot_disk], as_root=True)
+ ['cp', '-v', bootloader_bin, boot_disk], as_root=True)
proc.wait()
+ # Handle copy_files field.
+ cls.copy_files(boot_disk)
+
cls.make_boot_files(
bootloader_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
rootfs_id, boot_disk, boot_device_or_file)
@classmethod
+ def copy_files(cls, boot_disk):
+ """Handle the copy_files metadata field."""
+
+ # Extract anything specified by copy_files sections
+ # self.bootloader_copy_files is always of the form:
+ # {'source_package':
+ # [
+ # {'source_path': 'dest_path'}
+ # ]
+ # }
+ if cls.bootloader_copy_files is None:
+ return
+
+ for source_package, file_list in cls.bootloader_copy_files.iteritems():
+ for file_info in file_list:
+ for source_path, dest_path in file_info.iteritems():
+ source = cls.hardwarepack_handler.get_file_from_package(
+ source_path, source_package)
+ proc = cmd_runner.run(
+ ['cp', '-v', source,
+ os.path.join(boot_disk, dest_path)], as_root=True)
+ proc.wait()
+
+ @classmethod
def _get_kflavor_files(cls, path):
"""Search for kernel, initrd and optional dtb in path."""
if cls.kernel_flavors is None: