diff mbox

[Branch,~linaro-image-tools/linaro-image-tools/trunk] Rev 370: Add support for first batch of hwpack 2.0 fields to linaro-media-create.

Message ID 20110706183919.10312.45195.launchpad@loganberry.canonical.com
State Accepted
Headers show

Commit Message

Mattias Backman July 6, 2011, 6:39 p.m. UTC
Merge authors:
  Mattias Backman (mabac)
Related merge proposals:
  https://code.launchpad.net/~mabac/linaro-image-tools/hwpacks-v2-lmc/+merge/65669
  proposed by: Mattias Backman (mabac)
  review: Approve - James Westby (james-w)
------------------------------------------------------------
revno: 370 [merge]
committer: Mattias Backman <mattias.backman@linaro.org>
branch nick: trunk
timestamp: Fri 2011-07-01 16:33:32 +0200
message:
  Add support for first batch of hwpack 2.0 fields to linaro-media-create.
  
  This adds support for kernel_addr, initrd_addr, load_addr, u-boot (path 
  to uboot binary in the hwpack), serial_tty and partition_layout. 
modified:
  linaro-hwpack-install
  linaro-media-create
  linaro_image_tools/hwpack/config.py
  linaro_image_tools/hwpack/tests/test_config.py
  linaro_image_tools/media_create/boards.py
  linaro_image_tools/media_create/tests/test_media_create.py


--
lp:linaro-image-tools
https://code.launchpad.net/~linaro-image-tools/linaro-image-tools/trunk

You are subscribed to branch lp:linaro-image-tools.
To unsubscribe from this branch go to https://code.launchpad.net/~linaro-image-tools/linaro-image-tools/trunk/+edit-subscription
diff mbox

Patch

=== modified file 'linaro-hwpack-install'
--- linaro-hwpack-install	2011-01-29 16:35:06 +0000
+++ linaro-hwpack-install	2011-06-23 12:52:43 +0000
@@ -36,7 +36,7 @@ 
 FORCE_YES="no"
 SOURCES_LIST_FILE="${TEMP_DIR}/sources.list"
 APT_GET_OPTIONS="Dir::Etc::SourceList=${SOURCES_LIST_FILE}"
-SUPPORTED_FORMATS="1.0"  # A space-separated list of hwpack formats.
+SUPPORTED_FORMATS="1.0 2.0"  # A space-separated list of hwpack formats.
 
 sudo="sudo"
 if [ $(id -u) -eq 0 ]; then

=== modified file 'linaro-media-create'
--- linaro-media-create	2011-06-21 09:16:28 +0000
+++ linaro-media-create	2011-06-28 13:35:12 +0000
@@ -104,6 +104,7 @@ 
     ROOT_DISK = os.path.join(TMP_DIR, 'root-disc')
 
     board_config = board_configs[args.board]
+    board_config.set_metadata(args.hwpacks)
 
     ensure_required_commands(args)
 

=== modified file 'linaro_image_tools/hwpack/config.py'
--- linaro_image_tools/hwpack/config.py	2011-06-28 15:16:43 +0000
+++ linaro_image_tools/hwpack/config.py	2011-07-01 14:33:32 +0000
@@ -42,7 +42,7 @@ 
     SOURCES_ENTRY_KEY = "sources-entry"
     PACKAGES_KEY = "packages"
     PACKAGE_REGEX = NAME_REGEX
-    PATH_REGEX = r"[a-z0-9][a-z0-9+\-./]+$"
+    PATH_REGEX = r"[a-z0-9][a-z0-9+\-./_]+$"
     ORIGIN_KEY = "origin"
     MAINTAINER_KEY = "maintainer"
     ARCHITECTURES_KEY = "architectures"
@@ -59,6 +59,13 @@ 
     MMC_ID_KEY = "mmc_id"
     FORMAT_KEY = "format"
 
+    DEFINED_PARTITION_LAYOUTS = [
+        'bootfs16_rootfs',
+        'bootfs_rootfs',
+        #'reserved_bootfs_rootfs',
+        ]
+
+
     def __init__(self, fp):
         """Create a Config.
 
@@ -375,17 +382,12 @@ 
         pass
 
     def _validate_partition_layout(self):
-        defined_partition_layouts = [
-            #'bootfs16_rootfs',
-            'bootfs_rootfs',
-            #'reserved_bootfs_rootfs',
-            ]
-        if self.partition_layout not in defined_partition_layouts:
+        if self.partition_layout not in self.DEFINED_PARTITION_LAYOUTS:
             raise HwpackConfigError(
                 "Undefined partition layout %s in the [%s] section. "
                 "Valid partition layouts are %s."
                 % (self.partition_layout, self.MAIN_SECTION,
-                   ", ".join(defined_partition_layouts)))
+                   ", ".join(self.DEFINED_PARTITION_LAYOUTS)))
 
     def _validate_mmc_id(self):
         mmc_id = self.mmc_id

=== modified file 'linaro_image_tools/hwpack/tests/test_config.py'
--- linaro_image_tools/hwpack/tests/test_config.py	2011-06-17 12:28:43 +0000
+++ linaro_image_tools/hwpack/tests/test_config.py	2011-06-29 07:18:40 +0000
@@ -216,13 +216,16 @@ 
         self.assertValidationError("Invalid path: ~~", config)
 
     def test_validate_partition_layout(self):
-        config = self.get_config(self.valid_start_v2 + 
-                                 "u-boot-package = u-boot-linaro-s5pv310\n" \
-                                     "u-boot-file = u-boot.bin\n" \
-                                     "partition_layout = apafs_bananfs\n")
+        partition_layout = 'apafs_bananfs'
+        config = self.get_config(self.valid_start_v2 + "u-boot-package = " \
+                                     "u-boot-linaro-s5pv310\nu-boot-file = " \
+                                     "u-boot.bin\npartition_layout = %s\n" % \
+                                     partition_layout)
         self.assertValidationError(
-            "Undefined partition layout apafs_bananfs in the [hwpack] " \
-                "section. Valid partition layouts are bootfs_rootfs.", config)
+            "Undefined partition layout %s in the [%s] section. "
+            "Valid partition layouts are %s."
+            % (partition_layout, 'hwpack',
+               ", ".join(config.DEFINED_PARTITION_LAYOUTS)), config)
 
     def test_validate_wired_interfaces(self):
         self.assertTrue("XXX What is an invalid interface name?")

=== modified file 'linaro_image_tools/media_create/boards.py'
--- linaro_image_tools/media_create/boards.py	2011-07-01 09:18:48 +0000
+++ linaro_image_tools/media_create/boards.py	2011-07-01 14:33:32 +0000
@@ -31,11 +31,15 @@ 
 import tempfile
 import struct
 from binascii import crc32
+import tarfile
+import ConfigParser
+import shutil
 
 from linaro_image_tools import cmd_runner
 
 from linaro_image_tools.media_create.partitions import SECTOR_SIZE
 
+
 KERNEL_GLOB = 'vmlinuz-*-%(kernel_flavor)s'
 INITRD_GLOB = 'initrd.img-*-%(kernel_flavor)s'
 DTB_GLOB = 'dt-*-%(kernel_flavor)s/%(dtb_name)s'
@@ -132,6 +136,98 @@ 
         return self.getter(cls)
 
 
+class HardwarepackHandler(object):
+    FORMAT_1 = '1.0'
+    FORMAT_2 = '2.0'
+    FORMAT_MIXED = '1.0and2.0'
+    metadata_filename = 'metadata'
+    format_filename = 'FORMAT'
+    main_section = 'main'
+    hwpack_tarfiles = []
+    tempdir = None
+
+    def __init__(self, hwpacks):
+        self.hwpacks = hwpacks
+        self.hwpack_tarfiles = []
+    
+    class FakeSecHead(object):
+        """ Add a fake section header to the metadata file.
+
+        This is done so we can use ConfigParser to parse the file.
+        """
+        def __init__(self, fp):
+            self.fp = fp
+            self.sechead = '[%s]\n' % HardwarepackHandler.main_section
+
+        def readline(self):
+            if self.sechead:
+                try:
+                    return self.sechead
+                finally:
+                    self.sechead = None
+            else:
+                return self.fp.readline()
+
+    def __enter__(self):
+        self.tempdir = tempfile.mkdtemp()
+        for hwpack in self.hwpacks:
+            hwpack_tarfile = tarfile.open(hwpack, mode='r:gz')
+            self.hwpack_tarfiles.append(hwpack_tarfile)
+        return self
+
+    def __exit__(self, type, value, traceback):
+        for hwpack_tarfile in self.hwpack_tarfiles:
+            if hwpack_tarfile is not None:
+                hwpack_tarfile.close()
+        self.hwpack_tarfiles = []
+        if self.tempdir is not None and os.path.exists(self.tempdir):
+            shutil.rmtree(self.tempdir)
+
+    def get_field(self, section, field):
+        data = None
+        hwpack_with_data = None
+        for hwpack_tarfile in self.hwpack_tarfiles:
+            metadata = hwpack_tarfile.extractfile(self.metadata_filename)
+            # Use RawConfigParser which does not support the magical interpolation
+            # behavior of ConfigParser so we don't mess up metadata accidentally.
+            parser = ConfigParser.RawConfigParser()
+            parser.readfp(self.FakeSecHead(metadata))
+            try:
+                new_data = parser.get(section, field)
+                if new_data is not None:
+                    assert data is None, "The metadata field '%s' is set to " \
+                        "'%s' and new value '%s' is found" % (field, data, new_data)
+                    data = new_data
+                    hwpack_with_data = hwpack_tarfile
+            except ConfigParser.NoOptionError:
+                continue
+        return data, hwpack_with_data
+
+    def get_format(self):
+        format = None
+        supported_formats = [self.FORMAT_1, self.FORMAT_2]
+        for hwpack_tarfile in self.hwpack_tarfiles:
+            format_file = hwpack_tarfile.extractfile(self.format_filename)
+            format_string = format_file.read().strip()
+            if not format_string in supported_formats:
+                raise AssertionError(
+                    "Format version '%s' is not supported." % \
+                        format_string)
+            if format is None:
+                format = format_string
+            elif format != format_string:
+                return self.FORMAT_MIXED
+        return format
+
+    def get_file(self, file_alias):
+        file_name, hwpack_tarfile = self.get_field(self.main_section,
+                                                   file_alias)
+        if file_name is not None:
+            hwpack_tarfile.extract(file_name, self.tempdir)
+            file_name = os.path.join(self.tempdir, file_name)
+        return file_name
+
+
 class BoardConfig(object):
     """The configuration used when building an image for a board."""
     # These attributes may not need to be redefined on some subclasses.
@@ -141,12 +237,14 @@ 
     mmc_option = '0:1'
     mmc_part_offset = 0
     fat_size = 32
-    extra_serial_opts = ''
-    live_serial_opts = ''
+    _extra_serial_opts = ''
+    _live_serial_opts = ''
     extra_boot_args_options = None
     supports_writing_to_mmc = True
 
-    # These attributes must be defined on all subclasses.
+    # These attributes must be defined on all subclasses for backwards
+    # compatibility with hwpacks v1 format. Hwpacks v2 format allows these to
+    # be specified in the hwpack metadata.
     kernel_addr = None
     initrd_addr = None
     load_addr = None
@@ -155,6 +253,68 @@ 
     kernel_flavors = None
     boot_script = None
     serial_tty = None
+    wired_interfaces = None
+    wireless_interfaces = None
+    mmc_id = None
+
+    hardwarepack_handler = None
+
+    @classmethod
+    def get_metadata_field(cls, target, field_name):
+        """ Return the metadata value for field_name if it can be found.
+        """
+        data, _ = cls.hardwarepack_handler.get_field(
+            cls.hardwarepack_handler.main_section, field_name)
+        return data
+
+    @classmethod
+    def set_metadata(cls, hwpacks):
+        cls.hardwarepack_handler = HardwarepackHandler(hwpacks)
+        with cls.hardwarepack_handler:
+            if (cls.hardwarepack_handler.get_format() ==
+                cls.hardwarepack_handler.FORMAT_1):
+                return
+
+            if (cls.hardwarepack_handler.get_format() ==
+                cls.hardwarepack_handler.FORMAT_2):
+                # Clear V1 defaults.
+                cls.kernel_addr = None
+                cls.initrd_addr = None
+                cls.load_addr = None
+                cls.serial_tty = None
+                cls.fat_size = None
+
+            # Set new values from metadata.
+            cls.kernel_addr = cls.get_metadata_field(
+                cls.kernel_addr, 'kernel_addr')
+            cls.initrd_addr = cls.get_metadata_field(
+                cls.initrd_addr, 'initrd_addr')
+            cls.load_addr = cls.get_metadata_field(
+                cls.load_addr, 'load_addr')
+            cls.serial_tty = cls.get_metadata_field(
+                cls.serial_tty, 'serial_tty')
+            cls.wired_interfaces = cls.get_metadata_field(
+                cls.wired_interfaces, 'wired_interfaces')
+            cls.wireless_interfaces = cls.get_metadata_field(
+                cls.wireless_interfaces, 'wireless_interfaces')
+            cls.mmc_id = cls.get_metadata_field(
+                cls.mmc_id, 'mmc_id')
+
+            partition_layout = cls.get_metadata_field(cls.fat_size, 'partition_layout')
+            if partition_layout == 'bootfs_rootfs' or partition_layout is None:
+                cls.fat_size = 32
+            elif partition_layout == 'bootfs16_rootfs':
+                cls.fat_size = 16
+            else:
+                raise AssertionError("Unknown partition layout '%s'." % partition_layout)
+
+    @classmethod
+    def get_file(cls, file_alias, default=None):
+        file_in_hwpack = cls.hardwarepack_handler.get_file(file_alias)
+        if file_in_hwpack is not None:
+            return file_in_hwpack
+        else:
+            return default
 
     @classmethod
     def get_sfdisk_cmd(cls, should_align_boot_part=False):
@@ -302,10 +462,12 @@ 
         if cls.uboot_in_boot_part:
             assert cls.uboot_flavor is not None, (
                 "uboot_in_boot_part is set but not uboot_flavor")
-            uboot_bin = os.path.join(chroot_dir, 'usr', 'lib', 'u-boot',
-                cls.uboot_flavor, 'u-boot.bin')
-            cmd_runner.run(
-                ['cp', '-v', uboot_bin, boot_disk], as_root=True).wait()
+            with cls.hardwarepack_handler:
+                uboot_bin = cls.get_file('u_boot', default=os.path.join(
+                        chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
+                        'u-boot.bin'))
+                cmd_runner.run(
+                    ['cp', '-v', uboot_bin, boot_disk], as_root=True).wait()
 
         cls.make_boot_files(
             uboot_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
@@ -479,8 +641,8 @@ 
 
 class Ux500Config(BoardConfig):
     serial_tty = 'ttyAMA2'
-    extra_serial_opts = 'console=tty0 console=%s,115200n8' % serial_tty
-    live_serial_opts = 'serialtty=%s' % serial_tty
+    _extra_serial_opts = 'console=tty0 console=%s,115200n8'
+    _live_serial_opts = 'serialtty=%s'
     kernel_addr = '0x00100000'
     initrd_addr = '0x08000000'
     load_addr = '0x00008000'
@@ -493,6 +655,14 @@ 
         'hwmem=48M@302M mem=152M@360M')
     mmc_option = '1:1'
 
+    @classproperty
+    def live_serial_opts(cls):
+        return cls._live_serial_opts % cls.serial_tty
+
+    @classproperty
+    def extra_serial_opts(cls):
+        return cls._extra_serial_opts % cls.serial_tty
+
     @classmethod
     def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
@@ -667,12 +837,20 @@ 
 
 class Mx5Config(BoardConfig):
     serial_tty = 'ttymxc0'
-    extra_serial_opts = 'console=tty0 console=%s,115200n8' % serial_tty
-    live_serial_opts = 'serialtty=%s' % serial_tty
+    _extra_serial_opts = 'console=tty0 console=%s,115200n8'
+    _live_serial_opts = 'serialtty=%s'
     boot_script = 'boot.scr'
     mmc_part_offset = 1
     mmc_option = '0:2'
 
+    @classproperty
+    def live_serial_opts(cls):
+        return cls._live_serial_opts % cls.serial_tty
+
+    @classproperty
+    def extra_serial_opts(cls):
+        return cls._extra_serial_opts % cls.serial_tty
+
     @classmethod
     def get_sfdisk_cmd(cls, should_align_boot_part=None):
         """Return the sfdisk command to partition the media.
@@ -705,9 +883,11 @@ 
     def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
-        uboot_file = os.path.join(
-            chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor, 'u-boot.imx')
-        install_mx5_boot_loader(uboot_file, boot_device_or_file)
+        with cls.hardwarepack_handler:
+            uboot_file = cls.get_file('u_boot', default=os.path.join(
+                    chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
+                    'u-boot.imx'))
+            install_mx5_boot_loader(uboot_file, boot_device_or_file)
         make_uImage(cls.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
         make_dtb(d_img_data, boot_dir)
@@ -755,8 +935,8 @@ 
     uboot_flavor = 'ca9x4_ct_vxp'
     uboot_in_boot_part = True
     serial_tty = 'ttyAMA0'
-    extra_serial_opts = 'console=tty0 console=%s,38400n8' % serial_tty
-    live_serial_opts = 'serialtty=%s' % serial_tty
+    _extra_serial_opts = 'console=tty0 console=%s,38400n8'
+    _live_serial_opts = 'serialtty=%s'
     kernel_addr = '0x60008000'
     initrd_addr = '0x81000000'
     load_addr = kernel_addr
@@ -766,6 +946,14 @@ 
     # only allows for FAT16
     fat_size = 16
 
+    @classproperty
+    def live_serial_opts(cls):
+        return cls._live_serial_opts % cls.serial_tty
+
+    @classproperty
+    def extra_serial_opts(cls):
+        return cls._extra_serial_opts % cls.serial_tty
+
     @classmethod
     def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
@@ -777,7 +965,7 @@ 
 class SMDKV310Config(BoardConfig):
     uboot_flavor = 'smdkv310'
     serial_tty = 'ttySAC1'
-    extra_serial_opts = 'console=%s,115200n8' % serial_tty
+    _extra_serial_opts = 'console=%s,115200n8'
     kernel_addr = '0x40007000'
     initrd_addr = '0x42000000'
     load_addr = '0x40008000'
@@ -786,6 +974,10 @@ 
     mmc_part_offset = 1
     mmc_option = '0:2'
 
+    @classproperty
+    def extra_serial_opts(cls):
+        return cls._extra_serial_opts % cls.serial_tty
+
     @classmethod
     def get_sfdisk_cmd(cls, should_align_boot_part=False):
         # bootloaders partition needs to hold BL1, U-Boot environment, and BL2

=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
--- linaro_image_tools/media_create/tests/test_media_create.py	2011-07-01 09:16:24 +0000
+++ linaro_image_tools/media_create/tests/test_media_create.py	2011-07-01 14:33:32 +0000
@@ -29,7 +29,9 @@ 
 import time
 import types
 import struct
+import tarfile
 
+from StringIO import StringIO
 from testtools import TestCase
 
 from linaro_image_tools import cmd_runner
@@ -63,6 +65,8 @@ 
     _get_smdk_spl,
     _get_smdk_uboot,
     _run_mkimage,
+    HardwarepackHandler,
+    BoardConfig,
     )
 from linaro_image_tools.media_create.android_boards import (
     android_board_configs,
@@ -123,6 +127,311 @@ 
 sudo_args = " ".join(cmd_runner.SUDO_ARGS)
 
 
+class TestHardwarepackHandler(TestCaseWithFixtures):
+    def setUp(self):
+        super(TestHardwarepackHandler, self).setUp()
+        self.tar_dir_fixture = CreateTempDirFixture()
+        self.useFixture(self.tar_dir_fixture)
+
+        self.tarball_fixture = CreateTarballFixture(
+            self.tar_dir_fixture.get_temp_dir())
+        self.useFixture(self.tarball_fixture)
+
+        self.metadata = (
+            "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\nORIGIN=linaro\n")
+
+    def add_to_tarball(self, files, tarball=None):
+        if tarball is None:
+            tarball = self.tarball_fixture.get_tarball()
+        tar_file = tarfile.open(tarball, mode='w:gz')
+        for filename, data in files:
+            tarinfo = tarfile.TarInfo(filename)
+            tarinfo.size = len(data)
+            tar_file.addfile(tarinfo, StringIO(data))
+        tar_file.close()
+        return tarball
+
+    def test_get_format_1(self):
+        data = '1.0'
+        format = "%s\n" % data
+        tarball = self.add_to_tarball(
+            [('FORMAT', format), ('metadata', self.metadata)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            self.assertEquals(hp.get_format(), data)
+
+    def test_get_format_2(self):
+        data = '2.0'
+        format = "%s\n" % data
+        tarball = self.add_to_tarball(
+            [('FORMAT', format), ('metadata', self.metadata)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            self.assertEquals(hp.get_format(), data)
+
+    def test_get_unknown_format_raises(self):
+        data = '9.9'
+        format = "%s\n" % data
+        tarball = self.add_to_tarball(
+            [('FORMAT', format), ('metadata', self.metadata)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            self.assertRaises(AssertionError, hp.get_format)
+
+    def test_mixed_formats(self):
+        format1 = "%s\n" % '1.0'
+        format2 = "%s\n" % '2.0'
+        tarball1 = self.add_to_tarball(
+            [('FORMAT', format1), ('metadata', self.metadata)],
+            tarball=self.tarball_fixture.get_tarball())
+        tarball_fixture2 = CreateTarballFixture(
+            self.tar_dir_fixture.get_temp_dir(), reldir='tarfile2',
+            filename='secondtarball.tar.gz')
+        self.useFixture(tarball_fixture2)
+        tarball2 = self.add_to_tarball(
+            [('FORMAT', format2), ('metadata', self.metadata)],
+            tarball=tarball_fixture2.get_tarball())
+        hp = HardwarepackHandler([tarball2, tarball1])
+        with hp:
+            self.assertEquals(hp.get_format(), '1.0and2.0')
+
+    def test_identical_formats_ok(self):
+        format1 = "%s\n" % '2.0'
+        format2 = "%s\n" % '2.0'
+        tarball1 = self.add_to_tarball(
+            [('FORMAT', format1), ('metadata', self.metadata)],
+            tarball=self.tarball_fixture.get_tarball())
+        tarball_fixture2 = CreateTarballFixture(
+            self.tar_dir_fixture.get_temp_dir(), reldir='tarfile2',
+            filename='secondtarball.tar.gz')
+        self.useFixture(tarball_fixture2)
+        tarball2 = self.add_to_tarball(
+            [('FORMAT', format2), ('metadata', self.metadata)],
+            tarball=tarball_fixture2.get_tarball())
+        hp = HardwarepackHandler([tarball1, tarball2])
+        with hp:
+            self.assertEquals(hp.get_format(), '2.0')
+
+    def test_get_metadata(self):
+        data = 'data to test'
+        metadata = self.metadata + "TEST=%s\n" % data
+        tarball = self.add_to_tarball(
+            [('metadata', metadata)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            test_data, _ = hp.get_field(hp.main_section, 'test')
+            self.assertEqual(test_data, data)
+
+    def test_preserves_formatters(self):
+        data = '%s%d'
+        metadata = self.metadata + "TEST=%s\n" % data
+        tarball = self.add_to_tarball(
+            [('metadata', metadata)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            test_data, _ = hp.get_field(hp.main_section, 'test')
+            self.assertEqual(test_data, data)
+
+    def test_creates_tempdir(self):
+        tarball = self.add_to_tarball(
+            [('metadata', self.metadata)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            self.assertTrue(os.path.exists(hp.tempdir))
+
+    def test_tempfiles_are_removed(self):
+        tempdir = None
+        tarball = self.add_to_tarball(
+            [('metadata', self.metadata)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            tempdir = hp.tempdir
+        self.assertFalse(os.path.exists(tempdir))
+
+    def test_get_file(self):
+        data = 'test file contents\n'
+        metadata_file = 'TESTFILE'
+        file_in_archive = 'testfile'
+        metadata = self.metadata + "%s=%s\n" % (metadata_file, file_in_archive)
+        tarball = self.add_to_tarball(
+            [('metadata', metadata),
+             (file_in_archive, data)])
+        hp = HardwarepackHandler([tarball])
+        with hp:
+            test_file = hp.get_file(metadata_file)
+            self.assertEquals(data, open(test_file, 'r').read())
+        
+
+class TestSetMetadata(TestCaseWithFixtures):
+
+    class MockHardwarepackHandler(HardwarepackHandler):
+        metadata_dict = {}
+
+        def __enter__(self):
+            return self
+
+        def get_field(self, section, field):
+            try:
+                return self.metadata_dict[field], None
+            except:
+                return None, None
+
+        def get_format(self):
+            return '2.0'
+
+        def get_file(self, file_alias):
+            return None
+
+    def test_does_not_set_if_old_format(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(None, config.kernel_addr)
+
+    def test_sets_kernel_addr(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'kernel_addr'
+        data_to_set = '0x8123ABCD'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, config.kernel_addr)
+
+    def test_sets_initrd_addr(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'initrd_addr'
+        data_to_set = '0x8123ABCD'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, config.initrd_addr)
+
+    def test_sets_load_addr(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'load_addr'
+        data_to_set = '0x8123ABCD'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, config.load_addr)
+
+    def test_sets_serial_tty(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'serial_tty'
+        data_to_set = 'ttyAA'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, config.serial_tty)
+
+    def test_sets_wired_interfaces(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'wired_interfaces'
+        data_to_set = 'eth0 eth1'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, config.wired_interfaces)
+
+    def test_sets_wireless_interfaces(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'wireless_interfaces'
+        data_to_set = 'wlan0 wl1'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, config.wireless_interfaces)
+
+    def test_sets_mmc_id(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'mmc_id'
+        data_to_set = '1'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, config.mmc_id)
+
+    def test_sets_partition_layout_32(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'partition_layout'
+        data_to_set = 'bootfs_rootfs'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(32, config.fat_size)
+
+    def test_sets_partition_layout_16(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'partition_layout'
+        data_to_set = 'bootfs16_rootfs'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(16, config.fat_size)
+
+    def test_sets_partition_layout_raises(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'partition_layout'
+        data_to_set = 'bootfs_bogus_rootfs'
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        self.assertRaises(AssertionError, config.set_metadata, 'ahwpack.tar.gz')
+
+
 class TestGetMLOFile(TestCaseWithFixtures):
 
     def test_mlo_from_new_xloader(self):
@@ -507,6 +816,10 @@ 
     def test_mx5_steps(self):
         class SomeMx5Config(boards.Mx5Config):
             uboot_flavor = 'uboot_flavor'
+        SomeMx5Config.hardwarepack_handler = (
+            TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
+        SomeMx5Config.hardwarepack_handler.get_format = (
+            lambda: '1.0')
         self.make_boot_files(SomeMx5Config)
         expected = [
             'install_mx5_boot_loader', 'make_uImage', 'make_uInitrd',
@@ -1554,6 +1867,9 @@ 
 
         self.config = c
         self.config.boot_script = 'boot_script'
+        self.config.hardwarepack_handler = \
+            TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz')
+        self.config.hardwarepack_handler.get_format = lambda: '1.0'
         self.popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         self.useFixture(MockSomethingFixture(
             self.config, 'make_boot_files', self.save_args))