=== modified file 'linaro-android-media-create'
--- linaro-android-media-create	2012-07-26 08:48:15 +0000
+++ linaro-android-media-create	2012-12-28 13:09:56 +0000
@@ -26,7 +26,7 @@
 from linaro_image_tools import cmd_runner
 
 from linaro_image_tools.media_create.android_boards import (
-    android_board_configs,
+    get_board_config,
     )
 from linaro_image_tools.media_create.check_device import (
     confirm_device_selection_and_ensure_it_is_ready)
@@ -40,8 +40,11 @@
     unpack_android_binary_tarball
     )
 from linaro_image_tools.media_create import get_android_args_parser
-from linaro_image_tools.utils import ensure_command
-
+from linaro_image_tools.utils import (
+    additional_android_option_checks,
+    ensure_command,
+    get_logger
+    )
 
 
 # Just define the global variables
@@ -89,6 +92,10 @@
     parser = get_android_args_parser()
     args = parser.parse_args()
 
+    logger = get_logger(debug=args.debug)
+
+    additional_android_option_checks(args)
+
     # If --help was specified this won't execute.
     # Create temp dir and initialize rest of path vars.
     TMP_DIR = tempfile.mkdtemp()
@@ -102,13 +109,19 @@
     DATA_DISK = os.path.join(TMP_DIR, 'userdata-disc')
     SDCARD_DISK = os.path.join(TMP_DIR, 'sdcard-disc')
 
-    board_config = android_board_configs[args.dev]
+    board_config = get_board_config(args.dev)
+    if args.hwpack:
+        board_config.from_file(args.hwpack)
+    else:
+        logger.warning("No Android hwpack provided: default board values "
+                       "will be used.")
     board_config.add_boot_args(args.extra_boot_args)
     board_config.add_boot_args_from_file(args.extra_boot_args_file)
 
     if args.dev == 'iMX53':
         # XXX: remove this and the corresponding entry in android_board_configs
-        print "DEPRECATION WARNING: iMX53 is deprecated, please use mx53loco."
+        logger.warning("DEPRECATION WARNING: iMX53 is deprecated, please "
+                       "use mx53loco.")
 
     ensure_required_commands(args)
 
@@ -117,11 +130,8 @@
         if not confirm_device_selection_and_ensure_it_is_ready(args.device):
             sys.exit(1)
     elif not args.should_create_partitions:
-        print ("Do not use --no-part in conjunction with --image_file.")
+        logger.error("Do not use --no-part in conjunction with --image_file.")
         sys.exit(1)
-    else:
-        # All good, move on.
-        pass
 
     cmd_runner.run(['mkdir', '-p', BOOT_DIR]).wait()
     cmd_runner.run(['mkdir', '-p', SYSTEM_DIR]).wait()

=== modified file 'linaro-media-create'
--- linaro-media-create	2012-10-22 06:57:20 +0000
+++ linaro-media-create	2013-01-02 14:36:38 +0000
@@ -25,7 +25,7 @@
 
 from linaro_image_tools import cmd_runner
 
-from linaro_image_tools.media_create.boards import board_configs
+from linaro_image_tools.media_create.boards import get_board_config
 from linaro_image_tools.media_create.check_device import (
     confirm_device_selection_and_ensure_it_is_ready)
 from linaro_image_tools.media_create.chroot_utils import (
@@ -131,9 +131,8 @@
         logger.error(e.value)
         sys.exit(1)
 
-    board_config = board_configs[args.dev]
+    board_config = get_board_config(args.dev)
     board_config.set_metadata(args.hwpacks, args.bootloader, args.dev)
-    board_config.set_board(args.dev)
     board_config.add_boot_args(args.extra_boot_args)
     board_config.add_boot_args_from_file(args.extra_boot_args_file)
 
@@ -152,9 +151,6 @@
         logger.error("Do not use --no-boot or --no-part in conjunction with "
                      "--image_file.")
         sys.exit(1)
-    else:
-        # All good, move on.
-        pass
 
     # If --help was specified this won't execute.
     # Create temp dir and initialize rest of path vars.

=== modified file 'linaro_image_tools/hwpack/config.py'
--- linaro_image_tools/hwpack/config.py	2012-12-07 08:47:58 +0000
+++ linaro_image_tools/hwpack/config.py	2013-01-03 10:40:12 +0000
@@ -296,7 +296,7 @@
             self._validate_mmc_id()
             self._validate_extra_boot_options()
             self._validate_boot_script()
-            self._validate_extra_serial_opts()
+            self._validate_extra_serial_options()
             self._validate_snowball_startup_files_config()
             self._validate_samsung_bl1_start()
             self._validate_samsung_bl1_len()
@@ -620,7 +620,7 @@
                                            join_list_with=" ")
 
     @property
-    def extra_serial_opts(self):
+    def extra_serial_options(self):
         """Extra serial options.
 
         A str.
@@ -1021,7 +1021,7 @@
         # Optional and tricky to determine a valid pattern.
         pass
 
-    def _validate_extra_serial_opts(self):
+    def _validate_extra_serial_options(self):
         # Optional and tricky to determine a valid pattern.
         pass
 

=== modified file 'linaro_image_tools/hwpack/hardwarepack.py'
--- linaro_image_tools/hwpack/hardwarepack.py	2012-12-07 08:47:58 +0000
+++ linaro_image_tools/hwpack/hardwarepack.py	2013-01-03 10:40:12 +0000
@@ -128,7 +128,7 @@
                       env_dd=None, boot_script=None,
                       bootloader_file_in_boot_part=None,
                       uboot_dd=None, spl_in_boot_part=None, spl_dd=None,
-                      extra_serial_opts=None, loader_start=None,
+                      extra_serial_options=None, loader_start=None,
                       snowball_startup_files_config=None,
                       samsung_bl1_start=None, samsung_bl1_len=None,
                       samsung_env_start=None, samsung_env_len=None,
@@ -162,7 +162,7 @@
         self.spl_in_boot_part = spl_in_boot_part
         self.spl_dd = spl_dd
         self.env_dd = env_dd
-        self.extra_serial_opts = extra_serial_opts
+        self.extra_serial_options = extra_serial_options
         self.snowball_startup_files_config = snowball_startup_files_config
         self.samsung_bl1_start = samsung_bl1_start
         self.samsung_bl1_len = samsung_bl1_len
@@ -216,7 +216,7 @@
                 dtb_file=config.dtb_file,
                 env_dd=config.env_dd,
                 extra_boot_options=config.extra_boot_options,
-                extra_serial_opts=config.extra_serial_opts,
+                extra_serial_options=config.extra_serial_options,
                 initrd_addr=config.initrd_addr,
                 initrd=config.initrd,
                 kernel_addr=config.kernel_addr,
@@ -320,12 +320,12 @@
             metadata += dump({DTB_FILES_FIELD: self.dtb_files})
         if self.boot_script is not None:
             metadata += dump({BOOT_SCRIPT_FIELD: self.boot_script})
-        if self.extra_serial_opts is not None:
+        if self.extra_serial_options is not None:
             # XXX Check why and where once we get a list once a string.
-            if isinstance(self.extra_serial_opts, list):
-                extra_serial_options = " ".join(self.extra_serial_opts)
+            if isinstance(self.extra_serial_options, list):
+                extra_serial_options = " ".join(self.extra_serial_options)
             else:
-                extra_serial_options = self.extra_serial_opts
+                extra_serial_options = self.extra_serial_options
             metadata += dump({
                             EXTRA_SERIAL_OPTIONS_FIELD:
                             extra_serial_options})
@@ -417,8 +417,8 @@
             metadata += "SPL_DD=%s\n" % self.spl_dd
         if self.env_dd is not None:
             metadata += "ENV_DD=%s\n" % self.env_dd
-        if self.extra_serial_opts is not None:
-            metadata += "EXTRA_SERIAL_OPTIONS=%s\n" % self.extra_serial_opts
+        if self.extra_serial_options is not None:
+            metadata += "EXTRA_SERIAL_OPTIONS=%s\n" % self.extra_serial_options
         if self.snowball_startup_files_config is not None:
             metadata += "SNOWBALL_STARTUP_FILES_CONFIG=%s\n" % (
                 self.snowball_startup_files_config)

=== modified file 'linaro_image_tools/hwpack/tests/__init__.py'
--- linaro_image_tools/hwpack/tests/__init__.py	2012-07-25 09:00:58 +0000
+++ linaro_image_tools/hwpack/tests/__init__.py	2012-12-10 17:32:21 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2010, 2011 Linaro
+# Copyright (C) 2010, 2011, 2012 Linaro
 #
 # Author: James Westby <james.westby@linaro.org>
 #

=== modified file 'linaro_image_tools/hwpack/tests/test_config.py'
--- linaro_image_tools/hwpack/tests/test_config.py	2012-08-28 17:34:16 +0000
+++ linaro_image_tools/hwpack/tests/test_config.py	2013-01-03 10:40:12 +0000
@@ -503,11 +503,11 @@
             "omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000",
             config.extra_boot_options)
 
-    def test_extra_serial_opts(self):
+    def test_extra_serial_options(self):
         config = self.get_config(self.valid_complete_v2 + self.valid_end)
         config.validate()
         self.assertEqual("console=tty0 console=ttyO2,115200n8",
-                         config.extra_serial_opts)
+                         config.extra_serial_options)
 
     def test_boot_script(self):
         config = self.get_config(self.valid_complete_v2 + self.valid_end)

=== modified file 'linaro_image_tools/hwpack/tests/test_config_v3.py'
--- linaro_image_tools/hwpack/tests/test_config_v3.py	2012-12-27 10:29:42 +0000
+++ linaro_image_tools/hwpack/tests/test_config_v3.py	2013-01-03 10:40:12 +0000
@@ -518,11 +518,11 @@
             "omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000",
             config.extra_boot_options)
 
-    def test_extra_serial_opts(self):
+    def test_extra_serial_options(self):
         config = self.get_config(self.valid_complete_v3 + self.valid_end)
         config.validate()
         self.assertEqual('console=tty0 console=ttyO2,115200n8',
-                         config.extra_serial_opts)
+                         config.extra_serial_options)
 
     def test_boot_script(self):
         config = self.get_config(self.valid_complete_v3 + self.valid_end)

=== modified file 'linaro_image_tools/hwpack/tests/test_hardwarepack.py'
--- linaro_image_tools/hwpack/tests/test_hardwarepack.py	2012-07-23 14:44:37 +0000
+++ linaro_image_tools/hwpack/tests/test_hardwarepack.py	2013-01-03 10:40:12 +0000
@@ -257,7 +257,7 @@
         metadata = Metadata("ahwpack", "4", "armel",
                             format=HardwarePackFormatV2())
         metadata.add_v2_config(
-            extra_serial_opts='console=tty0 console=ttyO2,115200n8')
+            extra_serial_options='console=tty0 console=ttyO2,115200n8')
         expected_out = ("NAME=ahwpack\nVERSION=4\n"
                         "ARCHITECTURE=armel\nEXTRA_SERIAL_OPTIONS="
                         "console=tty0 console=ttyO2,115200n8\n")
@@ -335,7 +335,7 @@
                                     format=HardwarePackFormatV3())
         options = ['option1', 'option2,option3']
         # Need to call also this one!
-        metadata.add_v2_config(extra_serial_opts=options)
+        metadata.add_v2_config(extra_serial_options=options)
         metadata.add_v3_config(bootloaders=None)
         expected_out = ("format: '3.0'\nname: ahwpack\nversion: '4'\n"
                         "architecture: armel\nextra_serial_options: option1 "

=== modified file 'linaro_image_tools/media_create/__init__.py'
--- linaro_image_tools/media_create/__init__.py	2012-10-22 06:57:20 +0000
+++ linaro_image_tools/media_create/__init__.py	2012-12-05 14:54:29 +0000
@@ -78,6 +78,7 @@
     parser.add_argument(
         '--extra-boot-args-file', dest='extra_boot_args_file',
         required=False, help=('File containing extra boot arguments.'))
+    parser.add_argument("--debug", action="store_true")
 
 
 def get_args_parser():
@@ -173,7 +174,6 @@
         help="Select a bootloader from a hardware pack that contains more "
              "than one. If not specified, it will default to '%s'." %
              DEFAULT_BOOTLOADER)
-    parser.add_argument("--debug", action="store_true")
 
     add_common_options(parser)
     return parser
@@ -189,6 +189,9 @@
         '--image-file', '--image_file', dest='device',
         help='File where we should write the image file.')
     parser.add_argument(
+        '--hwpack', required=False,
+        help=('An Android hardware pack file with the board configuration.'))
+    parser.add_argument(
         '--image-size', '--image_size', default='2G',
         help=('The image size, specified in mega/giga bytes (e.g. 3000M or '
               '3G); use with --image_file only'))
@@ -202,7 +205,6 @@
         '--console', action='append', dest='consoles', default=[],
         help=('Add a console to kernel boot parameter; this parameter can be '
               'defined multiple times.'))
-
     parser.add_argument(
         '--system', default='system.tar.bz2', required=True,
         help=('The tarball containing the Android system paritition'))
@@ -212,7 +214,6 @@
     parser.add_argument(
         '--boot', default='boot.tar.bz2', required=True,
         help=('The tarball containing the Android root partition'))
-
     parser.add_argument(
         '--no-part', dest='should_create_partitions', action='store_false',
         help='Reuse existing partitions on the given media.')

=== modified file 'linaro_image_tools/media_create/android_boards.py'
--- linaro_image_tools/media_create/android_boards.py	2012-12-12 09:35:49 +0000
+++ linaro_image_tools/media_create/android_boards.py	2013-01-03 13:55:33 +0000
@@ -20,45 +20,157 @@
 """Configuration for boards supported by linaro-android-media-create.
 
 To add support for a new board, you need to create a subclass of
-AndroidBoardConfig, set appropriate values for its variables and add it to
-android_board_configs at the bottom of this file.
+AndroidBoardConfig, create an Android hwpack as explained here:
+
+https://wiki.linaro.org/AndroidHardwarePacksV3
+
+and add the board to 'android_board_configs' at the end of this file.
 """
 
+import os
+import yaml
+import logging
+
+from linaro_image_tools import cmd_runner
+from linaro_image_tools.hwpack.hwpack_fields import FORMAT_FIELD
 from linaro_image_tools.media_create.partitions import SECTOR_SIZE
-from linaro_image_tools.media_create.boards import PART_ALIGN_S
-from linaro_image_tools.media_create.boards import BeagleConfig
-from linaro_image_tools.media_create.boards import PandaConfig
-from linaro_image_tools.media_create.boards import Mx53LoCoConfig
-from linaro_image_tools.media_create.boards import SnowballSdConfig
-from linaro_image_tools.media_create.boards import SnowballEmmcConfig
-from linaro_image_tools.media_create.boards import SMDKV310Config
-from linaro_image_tools.media_create.boards import OrigenConfig
-from linaro_image_tools.media_create.boards import OrigenQuadConfig
-from linaro_image_tools.media_create.boards import VexpressConfig
 from linaro_image_tools.media_create.boards import (
+    BeagleConfig,
+    BoardConfig,
+    BoardConfigException,
+    Mx53LoCoConfig,
+    OrigenConfig,
+    OrigenQuadConfig,
+    PART_ALIGN_S,
+    PandaConfig,
+    SMDKV310Config,
+    SnowballEmmcConfig,
+    SnowballSdConfig,
+    VexpressConfig,
+    align_partition,
     align_up,
-    align_partition,
-    classproperty,
+    install_mx5_boot_loader,
     make_boot_script,
-    install_mx5_boot_loader,
     )
-
-from linaro_image_tools import cmd_runner
-import os
-
-
-class AndroidBoardConfig(object):
-    @classmethod
-    def _get_bootargs(cls, consoles):
+from linaro_image_tools.utils import DEFAULT_LOGGER_NAME
+
+logger = logging.getLogger(DEFAULT_LOGGER_NAME)
+
+BOOT_MIN_SIZE_S = align_up(128 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
+SYSTEM_MIN_SIZE_S = align_up(512 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
+CACHE_MIN_SIZE_S = align_up(256 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
+USERDATA_MIN_SIZE_S = align_up(512 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
+SDCARD_MIN_SIZE_S = align_up(512 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
+LOADER_MIN_SIZE_S = align_up(1 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
+
+
+class AndroidBoardConfig(BoardConfig):
+
+    def __init__(self):
+        super(AndroidBoardConfig, self).__init__()
+        self.dtb_name = None
+        self._extra_serial_options = []
+        self._android_specific_args = []
+        self._extra_boot_args_options = []
+        self._live_serial_options = []
+
+    def _get_android_specific_args(self):
+        android_args = self._android_specific_args
+        if isinstance(android_args, list):
+            android_args = ' '.join(self._android_specific_args)
+        return android_args
+
+    def _set_android_specific_args(self, value):
+        self._android_specific_args = value
+
+    android_specific_args = property(_get_android_specific_args,
+                                     _set_android_specific_args)
+
+    def _get_extra_boot_args_options(self):
+        extra_boot_args = self._extra_boot_args_options
+        if isinstance(extra_boot_args, list):
+            extra_boot_args = ' '.join(self._extra_boot_args_options)
+        return extra_boot_args
+
+    def _set_extra_boot_args_options(self, value):
+        self._extra_boot_args_options = value
+
+    extra_boot_args_options = property(_get_extra_boot_args_options,
+                                       _set_extra_boot_args_options)
+
+    def _get_extra_serial_options(self):
+        extra_serial = self._extra_serial_options
+        if isinstance(extra_serial, list):
+            extra_serial = ' '.join(self._extra_serial_options)
+        return extra_serial
+
+    def _set_extra_serial_options(self, value):
+        self._extra_serial_options = value
+
+    extra_serial_options = property(_get_extra_serial_options,
+                                 _set_extra_serial_options)
+
+    def _get_live_serial_options(self):
+        serial_options = self._live_serial_options
+        if serial_options:
+            if isinstance(serial_options, list):
+                serial_options = ' '.join(self._live_serial_options)
+            if self._check_placeholder_presence(serial_options, '%s'):
+                serial_options = serial_options % self.serial_tty
+        return serial_options
+
+    def _set_live_serial_options(self, value):
+        self._live_serial_options = value
+
+    live_serial_options = property(_get_live_serial_options,
+                                   _set_live_serial_options)
+
+    def from_file(self, hwpack):
+        """Loads the Android board configuration from an Android hardware pack
+        configuration file and sets the config attributes with their values.
+
+        :param hwpack: The Android hwpack configuration file.
+        :return The configuration read from the file as a dictionary.
+        """
+        try:
+            with open(hwpack, 'r') as hw:
+                config = yaml.safe_load(hw)
+            self._set_attributes(config)
+            return config
+        except yaml.YAMLError, ex:
+            logger.debug("Error loading YAML file %s" % hwpack, ex)
+            raise BoardConfigException("Error reading Android hwpack %s"
+                                       % hwpack)
+        except IOError, ex:
+            logger.debug("Error reading hwpack file %s" % hwpack, ex)
+            raise BoardConfigException("Android hwpack %s could not be found"
+                                       % hwpack)
+
+    def _set_attributes(self, config):
+        """Initialize the class attributes with the values read from the
+        Android hardware pack configuration file.
+
+        :param config: The config read from the Android hwpack.
+        """
+        for name, value in config.iteritems():
+            if name == FORMAT_FIELD:
+                setattr(self, 'hwpack_format', value)
+            elif hasattr(self, name):
+                setattr(self, name, value)
+            else:
+                logger.warning("Attribute '%s' does not belong to this "
+                               "instance of '%s'." % (name, self.__class__))
+
+    def _get_bootargs(self, consoles):
         """Get the bootargs for this board.
 
         In general subclasses should not have to override this.
         """
         boot_args_options = 'rootwait ro'
-        if cls.extra_boot_args_options is not None:
-            boot_args_options += ' %s' % cls.extra_boot_args_options
-        boot_args_options += ' %s' % cls.android_specific_args
-        serial_opts = cls._extra_serial_opts
+        if self.extra_boot_args_options:
+            boot_args_options += ' %s' % self.extra_boot_args_options
+        boot_args_options += ' %s' % self.android_specific_args
+        serial_opts = self.extra_serial_options
         for console in consoles:
             serial_opts += ' console=%s' % console
 
@@ -70,34 +182,32 @@
             "%(boot_args_options)s"
              % replacements)
 
-    @classmethod
-    def _get_boot_env(cls, consoles):
+    def _get_boot_env(self, consoles):
         """Get the boot environment for this board.
 
         In general subclasses should not have to override this.
         """
         boot_env = {}
-        boot_env["bootargs"] = cls._get_bootargs(consoles)
+        boot_env["bootargs"] = self._get_bootargs(consoles)
         initrd = False
-        if cls.initrd_addr:
+        if self.initrd_addr:
             initrd = True
         # On Android, the DTB file is always built as part of the kernel it
         # comes from - and lives in the same directory in the boot tarball, so
         # here we don't need to pass the whole path to it.
-        boot_env["bootcmd"] = cls._get_bootcmd(initrd, cls.dtb_name)
-        boot_env["initrd_high"] = cls.initrd_high
-        boot_env["fdt_high"] = cls.fdt_high
+        boot_env["bootcmd"] = self._get_bootcmd(initrd, self.dtb_name)
+        boot_env["initrd_high"] = self.initrd_high
+        boot_env["fdt_high"] = self.fdt_high
         return boot_env
 
-    @classmethod
-    def populate_boot_script(cls, boot_partition, boot_disk, consoles):
+    def populate_boot_script(self, boot_partition, boot_disk, consoles):
         cmd_runner.run(['mkdir', '-p', boot_disk]).wait()
         # TODO: Use partition_mounted() here to make sure the partition is
         # always umounted after we're done.
         cmd_runner.run(['mount', boot_partition, boot_disk],
             as_root=True).wait()
 
-        boot_env = cls._get_boot_env(consoles)
+        boot_env = self._get_boot_env(consoles)
         cmdline_filepath = os.path.join(boot_disk, "cmdline")
         cmdline_file = open(cmdline_filepath, 'r')
         android_kernel_cmdline = cmdline_file.read()
@@ -106,7 +216,7 @@
         cmdline_file.close()
 
         boot_dir = boot_disk
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
 
         cmd_runner.run(['sync']).wait()
@@ -115,25 +225,13 @@
         except cmd_runner.SubcommandNonZeroReturnValue:
             pass
 
-    @classmethod
-    def get_sfdisk_cmd(cls, should_align_boot_part=False,
+    def get_sfdisk_cmd(self, should_align_boot_part=False,
                        start_addr=0, extra_part=False):
-        if cls.fat_size == 32:
+        if self.fat_size == 32:
             partition_type = '0x0C'
         else:
             partition_type = '0x0E'
 
-        BOOT_MIN_SIZE_S = align_up(
-            128 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-        SYSTEM_MIN_SIZE_S = align_up(
-            512 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-        CACHE_MIN_SIZE_S = align_up(
-            256 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-        USERDATA_MIN_SIZE_S = align_up(
-            512 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-        SDCARD_MIN_SIZE_S = align_up(
-            512 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-
         # align on sector 63 for compatibility with broken versions of x-loader
         # unless align_boot_part is set
         boot_align = 63
@@ -175,86 +273,89 @@
             cache_start, _cache_len, userdata_start, userdata_start,
             _userdata_len, sdcard_start)
 
-    @classmethod
-    def populate_raw_partition(cls, media, boot_dir):
-        super(AndroidBoardConfig, cls).populate_raw_partition(media, boot_dir)
+    def populate_raw_partition(self, media, boot_dir):
+        super(AndroidBoardConfig, self).populate_raw_partition(media, boot_dir)
 
-    @classmethod
-    def install_boot_loader(cls, boot_partition, boot_device_or_file):
+    def install_boot_loader(self, boot_partition, boot_device_or_file):
         pass
 
 
 class AndroidOmapConfig(AndroidBoardConfig):
-    dtb_name = None
+    """Placeholder class for OMAP configuration inheritance."""
 
 
 class AndroidBeagleConfig(AndroidOmapConfig, BeagleConfig):
-    _extra_serial_opts = 'console=tty0 console=ttyO2,115200n8'
-    android_specific_args = 'init=/init androidboot.console=ttyO2'
-    dtb_name = None
-
-
-class AndroidPandaConfig(AndroidOmapConfig, PandaConfig):
-    bootloader_flavor = 'omap4_panda'
-    dtb_addr = '0x815f0000'
-    dtb_name = 'board.dtb'
-    _extra_serial_opts = 'console=ttyO2,115200n8'
-    extra_boot_args_options = (
-        'earlyprintk fixrtc nocompcache vram=48M '
-        'omapfb.vram=0:24M,1:24M mem=456M@0x80000000 mem=512M@0xA0000000')
-    android_specific_args = 'init=/init androidboot.console=ttyO2'
+    """Placeholder class for Beagle configuration inheritance."""
+    def __init__(self):
+        super(AndroidBeagleConfig, self).__init__()
+        self._android_specific_args = 'init=/init androidboot.console=ttyO2'
+        self._extra_serial_options = 'console=tty0 console=ttyO2,115200n8'
+
+
+class AndroidPandaConfig(AndroidBoardConfig, PandaConfig):
+    """Placeholder class for Panda configuration inheritance."""
+    def __init__(self):
+        super(AndroidPandaConfig, self).__init__()
+        self.dtb_name = 'board.dtb'
+        self._extra_serial_options = 'console=ttyO2,115200n8'
+        self._extra_boot_args_options = (
+            'earlyprintk fixrtc nocompcache vram=48M '
+            'omapfb.vram=0:24M,1:24M mem=456M@0x80000000 mem=512M@0xA0000000')
+        self._android_specific_args = 'init=/init androidboot.console=ttyO2'
+        self.dtb_addr = '0x815f0000'
+        self.bootloader_flavor = 'omap4_panda'
 
 
 class AndroidSnowballSdConfig(AndroidBoardConfig, SnowballSdConfig):
-    boot_script = 'boot.scr'
-    fdt_high = '0x05000000'
-    initrd_addr = '0x05000000'
-    initrd_high = '0x06000000'
-    extra_boot_args_options = (
-        'earlyprintk mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
-        'mem=22M@360M mem_issw=1M@383M mem=640M@384M vmalloc=500M')
-    _extra_serial_opts = 'console=ttyAMA2,115200n8'
-    android_specific_args = 'init=/init androidboot.console=ttyAMA2'
-    dtb_name = 'board.dtb'
-    dtb_addr = '0x8000000'
+    """Placeholder class for Snowball Sd configuration inheritance."""
+    def __init__(self):
+        super(AndroidSnowballSdConfig, self).__init__()
+        self.dtb_name = 'board.dtb'
+        self._android_specific_args = 'init=/init androidboot.console=ttyAMA2'
+        self._extra_boot_args_options = (
+            'earlyprintk mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
+            'mem=22M@360M mem_issw=1M@383M mem=640M@384M vmalloc=500M')
+        self._extra_serial_options = 'console=ttyAMA2,115200n8'
+        self.boot_script = 'boot.scr'
+        self.fdt_high = '0x05000000'
+        self.initrd_addr = '0x05000000'
+        self.initrd_high = '0x06000000'
+        self.dtb_addr = '0x8000000'
 
 
 class AndroidSnowballEmmcConfig(AndroidBoardConfig, SnowballEmmcConfig):
-    boot_script = 'boot.scr'
-    fdt_high = '0x05000000'
-    initrd_addr = '0x05000000'
-    initrd_high = '0x06000000'
-    extra_boot_args_options = (
-        'earlyprintk mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
-        'mem=22M@360M mem_issw=1M@383M mem=640M@384M vmalloc=500M')
-    _extra_serial_opts = 'console=ttyAMA2,115200n8'
-    android_specific_args = 'init=/init androidboot.console=ttyAMA2'
-    mmc_option = '0:2'
-    dtb_name = 'board.dtb'
-    dtb_addr = '0x8000000'
-
-    @classmethod
-    def get_sfdisk_cmd(cls, should_align_boot_part=False):
-
-        LOADER_MIN_SIZE_S = align_up(
-            1 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-
+    """Class for Snowball Emmc configuration inheritance."""
+    def __init__(self):
+        super(AndroidSnowballEmmcConfig, self).__init__()
+        self.dtb_name = 'board.dtb'
+        self._extra_boot_args_options = (
+            'earlyprintk mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
+            'mem=22M@360M mem_issw=1M@383M mem=640M@384M vmalloc=500M')
+        self._extra_serial_options = 'console=ttyAMA2,115200n8'
+        self._android_specific_args = 'init=/init androidboot.console=ttyAMA2'
+        self.boot_script = 'boot.scr'
+        self.fdt_high = '0x05000000'
+        self.initrd_addr = '0x05000000'
+        self.initrd_high = '0x06000000'
+        self.mmc_option = '0:2'
+        self.dtb_addr = '0x8000000'
+
+    def get_sfdisk_cmd(self, should_align_boot_part=False):
         loader_start, loader_end, loader_len = align_partition(
             SnowballEmmcConfig.SNOWBALL_LOADER_START_S,
             LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
 
-        command = super(AndroidSnowballEmmcConfig, cls).get_sfdisk_cmd(
+        command = super(AndroidSnowballEmmcConfig, self).get_sfdisk_cmd(
             should_align_boot_part=True, start_addr=loader_end,
             extra_part=True)
 
         return '%s,%s,0xDA\n%s' % (
             loader_start, loader_len, command)
 
-    @classmethod
-    def populate_raw_partition(cls, media, boot_dir):
+    def populate_raw_partition(self, media, boot_dir):
         # To avoid adding a Snowball specific command line option, we assume
         # that the user already has unpacked the startfiles to ./startupfiles
-        config_files_dir = cls.snowball_config(boot_dir)
+        config_files_dir = self.snowball_config(boot_dir)
         assert os.path.exists(config_files_dir), (
             "You need to unpack the Snowball startupfiles to the directory "
             "'startupfiles' in your current working directory. See "
@@ -265,72 +366,98 @@
         for boot_file in boot_files:
             cmd_runner.run(['cp', os.path.join(boot_dir, 'boot', boot_file),
                             config_files_dir], as_root=True).wait()
-        super(AndroidSnowballEmmcConfig, cls).populate_raw_partition(
+        super(AndroidSnowballEmmcConfig, self).populate_raw_partition(
             media, boot_dir)
 
-    @classmethod
-    def snowball_config(cls, chroot_dir):
+    def snowball_config(self, chroot_dir):
         # The user is expected to have unpacked the startupfiles to this subdir
         # of their working dir.
         return os.path.join('.', 'startupfiles')
 
-    @classproperty
-    def delete_startupfiles(cls):
+    @property
+    def delete_startupfiles(self):
         # The startupfiles will have been unpacked to the user's working dir
         # and should not be deleted after they have been installed.
         return False
 
 
 class AndroidMx53LoCoConfig(AndroidBoardConfig, Mx53LoCoConfig):
-    extra_boot_args_options = (
-        'earlyprintk rootdelay=1 fixrtc nocompcache di1_primary tve')
-    _extra_serial_opts = 'console=%s,115200n8' % (
-        Mx53LoCoConfig.serial_tty)
-    android_specific_args = 'init=/init androidboot.console=%s' % (
-        Mx53LoCoConfig.serial_tty)
-    dtb_name = None
-
-    @classmethod
-    def get_sfdisk_cmd(cls, should_align_boot_part=False):
+    """Class for Mx53LoCo configuration inheritance."""
+    def __init__(self):
+        super(AndroidMx53LoCoConfig, self).__init__()
+        self._extra_boot_args_options = (
+            'earlyprintk rootdelay=1 fixrtc nocompcache di1_primary tve')
+        self._extra_serial_options = 'console=%s,115200n8'
+        self._android_specific_args = 'init=/init androidboot.console=%s'
+
+    def _get_extra_serial_options(self):
+        serial_opts = self._extra_serial_options
+        if serial_opts:
+            if isinstance(serial_opts, list):
+                serial_opts = ' '.join(serial_opts)
+            if self._check_placeholder_presence(serial_opts, '%s'):
+                serial_opts = serial_opts % self.serial_tty
+        return serial_opts
+
+    def _set_extra_serial_options(self, value):
+        self._extra_serial_options = value
+
+    extra_serial_options = property(_get_extra_serial_options,
+                                 _set_extra_serial_options)
+
+    def _get_android_specific_args(self):
+        android_args = self._android_specific_args
+        if android_args:
+            if isinstance(android_args, list):
+                android_args = ' '.join(android_args)
+            if self._check_placeholder_presence(android_args, '%s'):
+                android_args = android_args % self.serial_tty
+        return android_args
+
+    def _set_android_specific_args(self, value):
+        self._android_specific_args = value
+
+    android_specific_args = property(_get_android_specific_args,
+                                     _set_android_specific_args)
+
+    def get_sfdisk_cmd(self, should_align_boot_part=False):
         loader_start, loader_end, loader_len = align_partition(
-            1, cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
+            1, self.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
 
-        command = super(AndroidMx53LoCoConfig, cls).get_sfdisk_cmd(
+        command = super(AndroidMx53LoCoConfig, self).get_sfdisk_cmd(
             should_align_boot_part=True, start_addr=loader_end,
             extra_part=True)
 
         return '%s,%s,0xDA\n%s' % (
             loader_start, loader_len, command)
 
-    @classmethod
-    def install_boot_loader(cls, boot_partition, boot_device_or_file):
+    def install_boot_loader(self, boot_partition, boot_device_or_file):
         install_mx5_boot_loader(
             os.path.join(boot_device_or_file, "u-boot.imx"),
-            boot_partition, cls.LOADER_MIN_SIZE_S)
+            boot_partition, self.LOADER_MIN_SIZE_S)
 
 
 class AndroidMx6QSabreliteConfig(AndroidMx53LoCoConfig):
-    bootloader_flavor = 'mx6qsabrelite'
-    kernel_addr = '0x10000000'
-    initrd_addr = '0x12000000'
-    load_addr = '0x10008000'
-    dtb_addr = '0x11ff0000'
-    dtb_name = 'board.dtb'
+    """Placeholder class for Mx6Q Sabrelite configuration inheritance."""
+    def __init__(self):
+        super(AndroidMx6QSabreliteConfig, self).__init__()
+        self.dtb_name = 'board.dtb'
+        self.bootloader_flavor = 'mx6qsabrelite'
+        self.kernel_addr = '0x10000000'
+        self.initrd_addr = '0x12000000'
+        self.load_addr = '0x10008000'
+        self.dtb_addr = '0x11ff0000'
 
 
 class AndroidSamsungConfig(AndroidBoardConfig):
-    dtb_name = None
-
-    @classmethod
-    def get_sfdisk_cmd(cls, should_align_boot_part=False):
-        loaders_min_len = (
-            cls.samsung_bl1_start + cls.samsung_bl1_len + cls.samsung_bl2_len +
-            cls.samsung_env_len)
+    def get_sfdisk_cmd(self, should_align_boot_part=False):
+        loaders_min_len = (self.samsung_bl1_start + self.samsung_bl1_len +
+            self.samsung_bl2_len + self.samsung_env_len)
 
         loader_start, loader_end, loader_len = align_partition(
             1, loaders_min_len, 1, PART_ALIGN_S)
 
-        command = super(AndroidSamsungConfig, cls).get_sfdisk_cmd(
+        command = super(AndroidSamsungConfig, self).get_sfdisk_cmd(
             should_align_boot_part=False, start_addr=loader_end,
             extra_part=True)
 
@@ -339,40 +466,67 @@
 
 
 class AndroidSMDKV310Config(AndroidSamsungConfig, SMDKV310Config):
-    _extra_serial_opts = 'console=tty0 console=ttySAC1,115200n8'
-    android_specific_args = 'init=/init androidboot.console=ttySAC1'
-    dtb_name = None
+    """Placeholder class for SMDKV310 configuration inheritance."""
+    def __init__(self):
+        super(AndroidSMDKV310Config, self).__init__()
+        self._extra_serial_options = 'console=tty0 console=ttySAC1,115200n8'
+        self._android_specific_args = 'init=/init androidboot.console=ttySAC1'
 
 
 class AndroidOrigenConfig(AndroidSamsungConfig, OrigenConfig):
-    _extra_serial_opts = 'console=tty0 console=ttySAC2,115200n8'
-    android_specific_args = 'init=/init androidboot.console=ttySAC2'
-    dtb_name = None
+    """Placeholder class for Origen configuration inheritance."""
+    def __init__(self):
+        super(AndroidOrigenConfig, self).__init__()
+        self._extra_serial_options = 'console=tty0 console=ttySAC2,115200n8'
+        self._android_specific_args = 'init=/init androidboot.console=ttySAC2'
 
 
 class AndroidOrigenQuadConfig(AndroidSamsungConfig, OrigenQuadConfig):
-    _extra_serial_opts = 'console=tty0 console=ttySAC2,115200n8'
-    android_specific_args = 'init=/init androidboot.console=ttySAC2'
-    dtb_name = None
+    def __init__(self):
+        super(AndroidOrigenQuadConfig, self).__init__()
+        self._extra_serial_options = 'console=tty0 console=ttySAC2,115200n8'
+        self._android_specific_args = 'init=/init androidboot.console=ttySAC2'
 
 
 class AndroidVexpressConfig(AndroidBoardConfig, VexpressConfig):
-    _extra_serial_opts = 'console=tty0 console=ttyAMA0,38400n8'
-    android_specific_args = 'init=/init androidboot.console=ttyAMA0'
-    dtb_name = None
-
-
+    """Placeholder class for Vexpress configuration inheritance."""
+    def __init__(self):
+        super(AndroidVexpressConfig, self).__init__()
+        self._extra_serial_options = 'console=tty0 console=ttyAMA0,38400n8'
+        self._android_specific_args = 'init=/init androidboot.console=ttyAMA0'
+
+
+# This dictionary is composed as follows:
+# <device_name>: <class>
+# The <device_name> is the command line argument passed to l-a-m-c, the
+# <class> is the corresponding config class in this file (not the instance).
+# If a new device does not have special needs, it is possible to use the
+# general AndroidBoardConfig class.
 android_board_configs = {
     'beagle': AndroidBeagleConfig,
-    'panda': AndroidPandaConfig,
-    'snowball_sd': AndroidSnowballSdConfig,
-    'snowball_emmc': AndroidSnowballEmmcConfig,
-    'smdkv310': AndroidSMDKV310Config,
+    'iMX53': AndroidMx53LoCoConfig,
     'mx53loco': AndroidMx53LoCoConfig,
-    'iMX53': AndroidMx53LoCoConfig,
     'mx6qsabrelite': AndroidMx6QSabreliteConfig,
     'origen': AndroidOrigenConfig,
     'origen_quad': AndroidOrigenQuadConfig,
+    'panda': AndroidPandaConfig,
+    'smdkv310': AndroidSMDKV310Config,
+    'snowball_emmc': AndroidSnowballEmmcConfig,
+    'snowball_sd': AndroidSnowballSdConfig,
     'vexpress': AndroidVexpressConfig,
     'vexpress-a9': AndroidVexpressConfig,
     }
+
+
+def get_board_config(board):
+    """Get the board configuration for the specified board.
+
+    :param board: The name of the board to get the configuration of.
+    :type board: str
+    """
+    clazz = android_board_configs.get(board, None)
+    if clazz:
+        return clazz()
+    else:
+        raise BoardConfigException("Board name '%s' has no configuration "
+                                   "available." % board)

=== modified file 'linaro_image_tools/media_create/boards.py'
--- linaro_image_tools/media_create/boards.py	2012-12-23 12:49:02 +0000
+++ linaro_image_tools/media_create/boards.py	2013-01-02 14:38:13 +0000
@@ -24,24 +24,59 @@
 board_configs at the bottom of this file.
 """
 
+from binascii import crc32
+from parted import Device
 import atexit
 import glob
+import logging
 import os
 import re
+import string
+import struct
 import tempfile
-import struct
-from binascii import crc32
-import string
-import logging
-
-from parted import Device
 
 from linaro_image_tools import cmd_runner
 
+from linaro_image_tools.hwpack.handler import HardwarepackHandler
 from linaro_image_tools.media_create.partitions import (
-    partition_mounted, SECTOR_SIZE, register_loopback)
+    SECTOR_SIZE,
+    partition_mounted,
+    register_loopback,
+    )
 
-from linaro_image_tools.hwpack.handler import HardwarepackHandler
+from linaro_image_tools.hwpack.hwpack_fields import (
+    BOOTFS,
+    BOOTFS16,
+    BOOT_MIN_SIZE_FIELD,
+    BOOT_SCRIPT_FIELD,
+    DTB_ADDR_FIELD,
+    DTB_FILES_FIELD,
+    DTB_FILE_FIELD,
+    ENV_DD_FIELD,
+    EXTRA_BOOT_OPTIONS_FIELD,
+    EXTRA_SERIAL_OPTIONS_FIELD,
+    INITRD_ADDR_FIELD,
+    KERNEL_ADDR_FIELD,
+    LOADER_MIN_SIZE_FIELD,
+    LOADER_START_FIELD,
+    LOAD_ADDR_FIELD,
+    MMC_ID_FIELD,
+    PARTITION_LAYOUT_FIELD,
+    RESERVED_BOOTFS,
+    ROOT_MIN_SIZE_FIELD,
+    SAMSUNG_BL1_LEN_FIELD,
+    SAMSUNG_BL1_START_FIELD,
+    SAMSUNG_BL2_LEN_FIELD,
+    SAMSUNG_BL2_START_FIELD,
+    SAMSUNG_ENV_LEN_FIELD,
+    SAMSUNG_ENV_START_FIELD,
+    SERIAL_TTY_FIELD,
+    SNOWBALL_STARTUP_FILES_CONFIG_FIELD,
+    SPL_DD_FIELD,
+    SPL_IN_BOOT_PART_FIELD,
+    WIRED_INTERFACES_FIELD,
+    WIRELESS_INTERFACES_FIELD,
+    )
 
 logger = logging.getLogger(__name__)
 
@@ -102,310 +137,290 @@
     cmd_runner.run(cmd, as_root=True).wait()
 
 
-class classproperty(object):
-    """A descriptor that provides @property behavior on class methods."""
-    def __init__(self, getter):
-        self.getter = getter
-
-    def __get__(self, instance, cls):
-        return self.getter(cls)
-
-
 class BoardConfig(object):
-    board = None
     """The configuration used when building an image for a board."""
-    hwpack_format = None
-    # These attributes may not need to be redefined on some subclasses.
-    bootloader_flavor = None
-    # whether to copy u-boot to the boot partition
-    bootloader_file_in_boot_part = False
-    bootloader_dd = False
-    spl_in_boot_part = False
-    spl_dd = False
-    env_dd = False
-    fatload_command = 'fatload'
-    mmc_option = '0:1'
-    mmc_device_id = 0
-    mmc_part_offset = 0
-    uimage_path = ''
-    fat_size = 32
-    extra_serial_opts = ''
-    _extra_serial_opts = ''
-    _live_serial_opts = ''
-    extra_boot_args_options = None
-    supports_writing_to_mmc = True
+
     LOADER_MIN_SIZE_S = align_up(1 * 1024 ** 2, SECTOR_SIZE) / SECTOR_SIZE
     BOOT_MIN_SIZE_S = align_up(50 * 1024 ** 2, SECTOR_SIZE) / SECTOR_SIZE
     ROOT_MIN_SIZE_S = align_up(50 * 1024 ** 2, SECTOR_SIZE) / SECTOR_SIZE
 
-    # 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
-    initrd_high = '0xffffffff'
-    load_addr = None
-    dtb_addr = None
-    dtb_name = None
-    dtb_file = None
-    fdt_high = '0xffffffff'
-    kernel_flavors = None
-    boot_script = None
-    serial_tty = None
-    wired_interfaces = None
-    wireless_interfaces = None
-    mmc_id = None
-    vmlinuz = None
-    initrd = None
-    partition_layout = None
-    LOADER_START_S = 1
-
-    # Support for dtb_files as per hwpack v3 format.
-    dtb_files = None
-
-    # Samsung Boot-loader implementation notes and terminology
-    #
-    # * BL0, BL1 etc. are the various bootloaders in order of execution
-    # * BL0 is the first stage bootloader, located in ROM; it loads BL1/SPL
-    # from MMC offset +1s and runs it.
-    # * BL1 is the secondary program loader (SPL), a small version
-    #   of U-Boot with a checksum; it inits DRAM and loads a 1024s long BL2
-    #   from MMC and runs it.
-    # * BL2 is the U-Boot.
-    #
-    # samsung_bl1_{start,len}: Offset and maximum size for BL1
-    # samsung_bl2_{start,len}: Offset and maximum size for BL2
-    # samsung_env_{start,len}: Offset and maximum size for Environment settings
-    #
-    samsung_bl1_start = 1
-    samsung_bl1_len = 32
-    samsung_bl2_start = 65
-    samsung_bl2_len = 1024
-    samsung_env_start = 33
-    samsung_env_len = 32
-
-    hardwarepack_handler = None
-
-    @classmethod
-    def get_metadata_field(cls, field_name):
+    def __init__(self):
+        super(BoardConfig, self).__init__()
+        # XXX: when killing v1 hwpack, we might rename these two without the
+        # leading underscore. It is done in this way since sublcasses use
+        # placeholders in the string for dinamically change values. But this
+        # is done only for hwpack v1.
+        self._extra_serial_options = ''
+        self._live_serial_opts = ''
+        self.board = None
+        self.boot_script = None
+        self.bootloader_dd = False
+        self.bootloader_file_in_boot_part = False
+        self.bootloader_flavor = None
+        self.dtb_addr = None
+        self.dtb_file = None
+        self.dtb_files = None
+        self.dtb_name = None
+        self.env_dd = False
+        self.extra_boot_args_options = None
+        self.fat_size = 32
+        self.fatload_command = 'fatload'
+        self.fdt_high = '0xffffffff'
+        self.hardwarepack_handler = None
+        self.hwpack_format = None
+        self.initrd_addr = None
+        self.initrd_high = '0xffffffff'
+        self.kernel_addr = None
+        self.kernel_flavors = None
+        self.load_addr = None
+        self.loader_start_s = 1
+        self.mmc_device_id = 0
+        self.mmc_id = None
+        self.mmc_option = '0:1'
+        self.mmc_part_offset = 0
+        self.partition_layout = None
+        self.serial_tty = None
+        self.spl_dd = False
+        self.spl_in_boot_part = False
+        self.supports_writing_to_mmc = True
+        self.uimage_path = ''
+        self.wired_interfaces = None
+        self.wireless_interfaces = None
+        # Samsung Boot-loader implementation notes and terminology
+        #
+        # * BL0, BL1 etc. are the various bootloaders in order of execution
+        # * BL0 is the first stage bootloader, located in ROM; it loads BL1/SPL
+        # from MMC offset +1s and runs it.
+        # * BL1 is the secondary program loader (SPL), a small version
+        #   of U-Boot with a checksum; it inits DRAM and loads a 1024s long BL2
+        #   from MMC and runs it.
+        # * BL2 is the U-Boot.
+        #
+        # samsung_bl1_{start,len}: Offset and maximum size for BL1
+        # samsung_bl2_{start,len}: Offset and maximum size for BL2
+        # samsung_env_{start,len}: Offset and maximum size for settings
+        #
+        self.samsung_bl1_start = 1
+        self.samsung_bl1_len = 32
+        self.samsung_bl2_start = 65
+        self.samsung_bl2_len = 1024
+        self.samsung_env_start = 33
+        self.samsung_env_len = 32
+        # XXX: attributes that are not listed in hwpackV3, should be removed?
+        self.vmlinuz = None
+        self.initrd = None
+
+    # XXX: can be removed when killing v1 hwpack.
+    def _get_live_serial_opts(self):
+        return_value = self._live_serial_opts
+        if self._check_placeholder_presence(return_value, r'%s'):
+            return_value = self._live_serial_opts % self.serial_tty
+        return return_value
+
+    def _set_live_serial_opts(self, value):
+        self._live_serial_opts = value
+
+    live_serial_opts = property(_get_live_serial_opts, _set_live_serial_opts)
+
+    # XXX: can be removed when killing v1 hwpack.
+    def _get_extra_serial_options(self):
+        return_value = self._extra_serial_options
+        if self._check_placeholder_presence(return_value, r'%s'):
+            return_value = return_value % self.serial_tty
+        return return_value
+
+    def _set_extra_serial_options(self, value):
+        self._extra_serial_options = value
+
+    extra_serial_options = property(_get_extra_serial_options,
+                                 _set_extra_serial_options)
+
+    def get_metadata_field(self, field_name):
         """ Return the metadata value for field_name if it can be found.
         """
-        data, _ = cls.hardwarepack_handler.get_field(field_name)
+        data, _ = self.hardwarepack_handler.get_field(field_name)
         return data
 
-    @classmethod
-    def set_board(cls, board):
-        cls.board = board
-
-    @classmethod
-    def set_metadata(cls, hwpacks, bootloader=None, board=None):
-        cls.hardwarepack_handler = HardwarepackHandler(hwpacks, bootloader,
+    def set_metadata(self, hwpacks, bootloader=None, board=None):
+        self.hardwarepack_handler = HardwarepackHandler(hwpacks, bootloader,
                                                        board)
-        with cls.hardwarepack_handler:
-            cls.hwpack_format = cls.hardwarepack_handler.get_format()
-            if (cls.hwpack_format == cls.hardwarepack_handler.FORMAT_1):
+        with self.hardwarepack_handler:
+            self.hwpack_format = self.hardwarepack_handler.get_format()
+            if (self.hwpack_format == self.hardwarepack_handler.FORMAT_1):
                 return
 
-            if (cls.hwpack_format != cls.hardwarepack_handler.FORMAT_1):
+            if (self.hwpack_format != self.hardwarepack_handler.FORMAT_1):
                 # Clear V1 defaults.
-                cls.kernel_addr = None
-                cls.initrd_addr = None
-                cls.load_addr = None
-                cls.serial_tty = None
-                cls.fat_size = None
-                cls.dtb_name = None
-                cls.dtb_addr = None
-                cls.extra_boot_args_options = None
-                cls.boot_script = None
-                cls.kernel_flavors = None
-                cls.mmc_option = None
-                cls.mmc_part_offset = None
-                cls.samsung_bl1_start = None
-                cls.samsung_bl1_len = None
-                cls.samsung_env_len = None
-                cls.samsung_bl2_len = None
-                # cls.samsung_bl2_start and cls.samsung_env_start should
+                # TODO When removing v1 support, remove also default values
+                # in the constructor and avoid all this.
+                self.kernel_addr = None
+                self.initrd_addr = None
+                self.load_addr = None
+                self.serial_tty = None
+                self.fat_size = None
+                self.dtb_name = None
+                self.dtb_addr = None
+                self.extra_boot_args_options = None
+                self.boot_script = None
+                self.kernel_flavors = None
+                self.mmc_option = None
+                self.mmc_part_offset = None
+                self.samsung_bl1_start = None
+                self.samsung_bl1_len = None
+                self.samsung_env_len = None
+                self.samsung_bl2_len = None
+                # self.samsung_bl2_start and self.samsung_env_start should
                 # be initialized to default value for backward compatibility.
 
+            self.board = board
             # Set new values from metadata.
-            cls.kernel_addr = cls.get_metadata_field('kernel_addr')
-            cls.initrd_addr = cls.get_metadata_field('initrd_addr')
-            cls.load_addr = cls.get_metadata_field('load_addr')
-            cls.dtb_addr = cls.get_metadata_field('dtb_addr')
-            cls.serial_tty = cls.get_metadata_field('serial_tty')
-            wired_interfaces = cls.get_metadata_field('wired_interfaces')
-            if wired_interfaces is not None:
-                cls.wired_interfaces = wired_interfaces
-            wireless_interfaces = cls.get_metadata_field(
-                'wireless_interfaces')
-            if wireless_interfaces is not None:
-                cls.wireless_interfaces = wireless_interfaces
-            cls.vmlinuz = cls.get_metadata_field('vmlinuz')
-            cls.initrd = cls.get_metadata_field('initrd')
-            cls.dtb_file = cls.get_metadata_field('dtb_file')
-            cls.dtb_files = cls.get_metadata_field('dtb_files')
-            cls.extra_boot_args_options = cls.get_metadata_field(
-                'extra_boot_options')
-            cls.boot_script = cls.get_metadata_field('boot_script')
-            cls.extra_serial_opts = cls.get_metadata_field(
-                'extra_serial_opts')
-            cls.snowball_startup_files_config = cls.get_metadata_field(
-                'snowball_startup_files_config')
-
-            cls.partition_layout = cls.get_metadata_field('partition_layout')
-            if cls.partition_layout in [
-                'bootfs_rootfs', 'reserved_bootfs_rootfs', None]:
-                cls.fat_size = 32
-            elif cls.partition_layout == 'bootfs16_rootfs':
-                cls.fat_size = 16
+            self.kernel_addr = self.get_metadata_field(KERNEL_ADDR_FIELD)
+            self.initrd_addr = self.get_metadata_field(INITRD_ADDR_FIELD)
+            self.load_addr = self.get_metadata_field(LOAD_ADDR_FIELD)
+            self.dtb_addr = self.get_metadata_field(DTB_ADDR_FIELD)
+            self.serial_tty = self.get_metadata_field(SERIAL_TTY_FIELD)
+            wired_interfaces = self.get_metadata_field(WIRED_INTERFACES_FIELD)
+            if wired_interfaces:
+                self.wired_interfaces = wired_interfaces
+            wireless_interfaces = self.get_metadata_field(
+                WIRELESS_INTERFACES_FIELD)
+            if wireless_interfaces:
+                self.wireless_interfaces = wireless_interfaces
+            self.dtb_file = self.get_metadata_field(DTB_FILE_FIELD)
+            # XXX: need to deprecate dtb_file field and use only dtb_files
+            # for multiple entries.
+            if self.dtb_file:
+                logger.warn("Deprecation warning: use the 'dtb_files' field "
+                            "instead of 'dtb_file'.")
+            self.dtb_files = self.get_metadata_field(DTB_FILES_FIELD)
+            self.extra_boot_args_options = self.get_metadata_field(
+                EXTRA_BOOT_OPTIONS_FIELD)
+            self.boot_script = self.get_metadata_field(BOOT_SCRIPT_FIELD)
+            self.extra_serial_options = self.get_metadata_field(
+                EXTRA_SERIAL_OPTIONS_FIELD)
+            self.snowball_startup_files_config = self.get_metadata_field(
+                SNOWBALL_STARTUP_FILES_CONFIG_FIELD)
+            self.partition_layout = self.get_metadata_field(
+                PARTITION_LAYOUT_FIELD)
+            if self.partition_layout in [BOOTFS, RESERVED_BOOTFS, None]:
+                self.fat_size = 32
+            elif self.partition_layout == BOOTFS16:
+                self.fat_size = 16
             else:
                 raise AssertionError("Unknown partition layout '%s'." % \
-                                         cls.partition_layout)
-
-            cls.mmc_option = cls.get_metadata_field('mmc_id')
-            if cls.mmc_option is not None:
-                cls.mmc_device_id = int(cls.mmc_option.split(':')[0])
-                cls.mmc_part_offset = int(cls.mmc_option.split(':')[1]) - 1
-
-            boot_min_size = cls.get_metadata_field('boot_min_size')
-            if boot_min_size is not None:
-                cls.BOOT_MIN_SIZE_S = align_up(int(boot_min_size) * 1024 ** 2,
-                                               SECTOR_SIZE) / SECTOR_SIZE
-            root_min_size = cls.get_metadata_field('root_min_size')
-            if root_min_size is not None:
-                cls.ROOT_MIN_SIZE_S = align_up(int(root_min_size) * 1024 ** 2,
-                                               SECTOR_SIZE) / SECTOR_SIZE
-            loader_min_size = cls.get_metadata_field('loader_min_size')
-            if loader_min_size is not None:
-                cls.LOADER_MIN_SIZE_S = (
+                                         self.partition_layout)
+
+            self.mmc_option = self.get_metadata_field(MMC_ID_FIELD)
+            if self.mmc_option:
+                self.mmc_device_id = int(self.mmc_option.split(':')[0])
+                self.mmc_part_offset = int(self.mmc_option.split(':')[1]) - 1
+
+            # XXX: need to fix these values.
+            boot_min_size = self.get_metadata_field(BOOT_MIN_SIZE_FIELD)
+            if boot_min_size:
+                self.BOOT_MIN_SIZE_S = align_up(int(boot_min_size) * 1024 ** 2,
+                                               SECTOR_SIZE) / SECTOR_SIZE
+            root_min_size = self.get_metadata_field(ROOT_MIN_SIZE_FIELD)
+            if root_min_size:
+                self.ROOT_MIN_SIZE_S = align_up(int(root_min_size) * 1024 ** 2,
+                                               SECTOR_SIZE) / SECTOR_SIZE
+            loader_min_size = self.get_metadata_field(LOADER_MIN_SIZE_FIELD)
+            if loader_min_size:
+                self.LOADER_MIN_SIZE_S = (
                     align_up(int(loader_min_size) * 1024 ** 2,
                              SECTOR_SIZE) / SECTOR_SIZE)
 
-            bootloader_file_in_boot_part = cls.get_metadata_field(
-                'bootloader_file_in_boot_part')
-            if bootloader_file_in_boot_part is None:
-                cls.bootloader_file_in_boot_part = False
-            elif string.lower(bootloader_file_in_boot_part) == 'yes':
-                cls.bootloader_file_in_boot_part = True
-            elif string.lower(bootloader_file_in_boot_part) == 'no':
-                cls.bootloader_file_in_boot_part = False
-            spl_in_boot_part = cls.get_metadata_field('spl_in_boot_part')
+            spl_in_boot_part = self.get_metadata_field(SPL_IN_BOOT_PART_FIELD)
             if spl_in_boot_part is None:
-                cls.spl_in_boot_part = False
+                self.spl_in_boot_part = False
             elif string.lower(spl_in_boot_part) == 'yes':
-                cls.spl_in_boot_part = True
+                self.spl_in_boot_part = True
             elif string.lower(spl_in_boot_part) == 'no':
-                cls.spl_in_boot_part = False
-            env_dd = cls.get_metadata_field('env_dd')
+                self.spl_in_boot_part = False
+
+            env_dd = self.get_metadata_field(ENV_DD_FIELD)
             if env_dd is None:
-                cls.env_dd = False
+                self.env_dd = False
             elif string.lower(env_dd) == 'yes':
-                cls.env_dd = True
+                self.env_dd = True
             elif string.lower(env_dd) == 'no':
-                cls.env_dd = False
+                self.env_dd = False
 
-            bootloader_dd = cls.get_metadata_field('bootloader_dd')
+            # XXX: in hwpack v3 this field is just called 'dd'.
+            # Need to check its use.
+            bootloader_dd = self.get_metadata_field('bootloader_dd')
             # Either bootloader_dd is not specified, or it contains the dd
             # offset.
             if bootloader_dd is None:
-                cls.bootloader_dd = False
+                self.bootloader_dd = False
             else:
-                cls.bootloader_dd = int(bootloader_dd)
-            spl_dd = cls.get_metadata_field('spl_dd')
+                self.bootloader_dd = int(bootloader_dd)
+            spl_dd = self.get_metadata_field(SPL_DD_FIELD)
             # Either spl_dd is not specified, or it contains the dd offset.
             if spl_dd is None:
-                cls.spl_dd = False
+                self.spl_dd = False
             else:
-                cls.spl_dd = int(spl_dd)
-
-            loader_start = cls.get_metadata_field('loader_start')
-            if loader_start is not None:
-                cls.LOADER_START_S = int(loader_start)
-
-            samsung_bl1_start = cls.get_metadata_field('samsung_bl1_start')
-            if samsung_bl1_start is not None:
-                cls.samsung_bl1_start = int(samsung_bl1_start)
-
-            samsung_bl1_len = cls.get_metadata_field('samsung_bl1_len')
-            if samsung_bl1_len is not None:
-                cls.samsung_bl1_len = int(samsung_bl1_len)
-
-            samsung_bl2_len = cls.get_metadata_field('samsung_bl2_len')
-            if samsung_bl2_len is not None:
-                cls.samsung_bl2_len = int(samsung_bl2_len)
-
-            samsung_bl2_start = cls.get_metadata_field('samsung_bl2_start')
-            if samsung_bl2_start is not None:
-                cls.samsung_bl2_start = int(samsung_bl2_start)
-
-            samsung_env_len = cls.get_metadata_field('samsung_env_len')
-            if samsung_env_len is not None:
-                cls.samsung_env_len = int(samsung_env_len)
-
-            samsung_env_start = cls.get_metadata_field('samsung_env_start')
+                self.spl_dd = int(spl_dd)
+
+            loader_start = self.get_metadata_field(LOADER_START_FIELD)
+            if loader_start:
+                self.loader_start_s = int(loader_start)
+
+            samsung_bl1_start = self.get_metadata_field(
+                SAMSUNG_BL1_START_FIELD)
+            if samsung_bl1_start:
+                self.samsung_v310_bl1_start = int(samsung_bl1_start)
+            samsung_bl1_len = self.get_metadata_field(SAMSUNG_BL1_LEN_FIELD)
+            if samsung_bl1_len:
+                self.samsung_v310_bl1_len = int(samsung_bl1_len)
+            samsung_env_len = self.get_metadata_field(SAMSUNG_ENV_LEN_FIELD)
+            if samsung_env_len:
+                self.samsung_v310_env_len = int(samsung_env_len)
+            samsung_bl2_start = \
+                self.get_metadata_field(SAMSUNG_BL2_START_FIELD)
+            if samsung_bl2_start:
+                self.samsung_bl2_start = int(samsung_bl2_start)
+            samsung_bl2_len = self.get_metadata_field(SAMSUNG_BL2_LEN_FIELD)
+            if samsung_bl2_len:
+                self.samsung_v310_bl2_len = int(samsung_bl2_len)
+            samsung_env_start = \
+                self.get_metadata_field(SAMSUNG_ENV_START_FIELD)
             if samsung_env_start is not None:
-                cls.samsung_env_start = int(samsung_env_start)
+                self.samsung_env_start = int(samsung_env_start)
 
-            cls.bootloader_copy_files = cls.hardwarepack_handler.get_field(
+            self.bootloader_copy_files = self.hardwarepack_handler.get_field(
                 "bootloader_copy_files")[0]
 
-            cls.bootloader = cls.hardwarepack_handler.get_field(
-                                "bootloader")
-            cls.board = board
+            # XXX: no reference in hwpackV3 format of these fields, double
+            # check if they can be dropped when killing v1.
+            self.bootloader = self.hardwarepack_handler.get_field(
+                "bootloader")
+            self.vmlinuz = self.get_metadata_field('vmlinuz')
+            self.initrd = self.get_metadata_field('initrd')
+            bootloader_file_in_boot_part = self.get_metadata_field(
+                'bootloader_file_in_boot_part')
+            if bootloader_file_in_boot_part is None:
+                self.bootloader_file_in_boot_part = False
+            elif string.lower(bootloader_file_in_boot_part) == 'yes':
+                self.bootloader_file_in_boot_part = True
+            elif string.lower(bootloader_file_in_boot_part) == 'no':
+                self.bootloader_file_in_boot_part = False
 
-    @classmethod
-    def get_file(cls, file_alias, default=None):
+    def get_file(self, file_alias, default=None):
         # XXX remove the 'default' parameter when V1 support is removed!
-        file_in_hwpack = cls.hardwarepack_handler.get_file(file_alias)
+        file_in_hwpack = self.hardwarepack_handler.get_file(file_alias)
         if file_in_hwpack is not None:
             return file_in_hwpack
         else:
             return default
 
-    @classmethod
-    def get_v1_sfdisk_cmd(cls, should_align_boot_part=False):
-        """Return the sfdisk command to partition the media.
-
-        :param should_align_boot_part: Whether to align the boot partition too.
-
-        This default implementation returns a boot vfat partition of type
-        FAT16 or FAT32, followed by a root partition.
-
-        XXX: This default implementation and all overrides are left for V1
-        compatibility only. They should be removed as part of the work to
-        kill off hwpacks V1.
-        """
-        if cls.fat_size == 32:
-            partition_type = '0x0C'
-        else:
-            partition_type = '0x0E'
-
-        # align on sector 63 for compatibility with broken versions of x-loader
-        # unless align_boot_part is set
-        boot_align = 63
-        if should_align_boot_part:
-            boot_align = PART_ALIGN_S
-
-        # can only start on sector 1 (sector 0 is MBR / partition table)
-        boot_start, boot_end, boot_len = align_partition(
-            1, cls.BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)
-        # apparently OMAP3 ROMs require the vfat length to be an even number
-        # of sectors (multiple of 1 KiB); decrease the length if it's odd,
-        # there should still be enough room
-        boot_len = boot_len - boot_len % 2
-        boot_end = boot_start + boot_len - 1
-
-        # we ignore _root_end / _root_len and return a sfdisk command to
-        # instruct the use of all remaining space; XXX if we had some root size
-        # config, we could do something more sensible
-        root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
-
-        return '%s,%s,%s,*\n%s,,,-' % (
-            boot_start, boot_len, partition_type, root_start)
-
-    @classmethod
-    def get_normal_sfdisk_cmd(cls, should_align_boot_part=False):
+    def get_v1_sfdisk_cmd(self, should_align_boot_part=False):
+        # XXX: This default implementation and all overrides are left for V1
+        # compatibility only. They should be removed as part of the work to
+        # kill off hwpacks V1.
+        return self.get_normal_sfdisk_cmd(should_align_boot_part)
+
+    def get_normal_sfdisk_cmd(self, should_align_boot_part=False):
         """Return the sfdisk command to partition the media.
 
         :param should_align_boot_part: Whether to align the boot partition too.
@@ -413,7 +428,7 @@
         This returns a boot vfat partition of type FAT16
         or FAT32, followed by a root partition.
         """
-        if cls.fat_size == 32:
+        if self.fat_size == 32:
             partition_type = '0x0C'
         else:
             partition_type = '0x0E'
@@ -427,7 +442,7 @@
 
         # can only start on sector 1 (sector 0 is MBR / partition table)
         boot_start, boot_end, boot_len = align_partition(
-            1, cls.BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)
+            1, self.BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)
         # apparently OMAP3 ROMs require the vfat length to be an even number
         # of sectors (multiple of 1 KiB); decrease the length if it's odd,
         # there should still be enough room
@@ -439,13 +454,12 @@
         # instruct the use of all remaining space; XXX we now have root size
         # config, so we can do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,%s,*\n%s,,,-' % (
             boot_start, boot_len, partition_type, root_start)
 
-    @classmethod
-    def get_reserved_sfdisk_cmd(cls, should_align_boot_part=None):
+    def get_reserved_sfdisk_cmd(self, should_align_boot_part=None):
         """Return the sfdisk command to partition the media.
 
         :param should_align_boot_part: Ignored.
@@ -454,40 +468,38 @@
         FAT16 or FAT32, followed by a root partition.
         """
         loader_start, loader_end, loader_len = align_partition(
-            cls.LOADER_START_S, cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
+            self.loader_start_s, self.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
 
         boot_start, boot_end, boot_len = align_partition(
-            loader_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            loader_end + 1, self.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
         loader_start, loader_len, boot_start, boot_len, root_start)
 
-    @classmethod
-    def get_sfdisk_cmd(cls, should_align_boot_part=False):
-        if (cls.partition_layout in ['bootfs_rootfs', 'bootfs16_rootfs'] or
-            cls.board == 'snowball_sd'):
-            return cls.get_normal_sfdisk_cmd(should_align_boot_part)
-        elif cls.partition_layout in ['reserved_bootfs_rootfs']:
-            return cls.get_reserved_sfdisk_cmd(should_align_boot_part)
+    def get_sfdisk_cmd(self, should_align_boot_part=False):
+        if (self.partition_layout in ['bootfs_rootfs', 'bootfs16_rootfs'] or
+            self.board == 'snowball_sd'):
+            return self.get_normal_sfdisk_cmd(should_align_boot_part)
+        elif self.partition_layout in ['reserved_bootfs_rootfs']:
+            return self.get_reserved_sfdisk_cmd(should_align_boot_part)
         else:
-            assert (cls.hwpack_format == HardwarepackHandler.FORMAT_1), (
+            assert (self.hwpack_format == HardwarepackHandler.FORMAT_1), (
                 "Hwpack format is not 1.0 but "
                 "partition_layout is unspecified.")
-            return cls.get_v1_sfdisk_cmd(should_align_boot_part)
+            return self.get_v1_sfdisk_cmd(should_align_boot_part)
 
-    @classmethod
-    def _get_bootcmd(cls, i_img_data, d_img_data):
+    def _get_bootcmd(self, i_img_data, d_img_data):
         """Get the bootcmd for this board.
 
         In general subclasses should not have to override this.
         """
         replacements = dict(
-            fatload_command=cls.fatload_command, uimage_path=cls.uimage_path,
-            mmc_option=cls.mmc_option, kernel_addr=cls.kernel_addr,
-            initrd_addr=cls.initrd_addr, dtb_addr=cls.dtb_addr)
+            fatload_command=self.fatload_command, uimage_path=self.uimage_path,
+            mmc_option=self.mmc_option, kernel_addr=self.kernel_addr,
+            initrd_addr=self.initrd_addr, dtb_addr=self.dtb_addr)
         boot_script = (
             ("%(fatload_command)s mmc %(mmc_option)s %(kernel_addr)s " +
              "%(uimage_path)suImage; ")) % replacements
@@ -496,7 +508,7 @@
             ("%(fatload_command)s mmc %(mmc_option)s %(initrd_addr)s " +
              "%(uimage_path)suInitrd; ")) % replacements
             if d_img_data is not None:
-                assert cls.dtb_addr is not None, (
+                assert self.dtb_addr is not None, (
                     "Need a dtb_addr when passing d_img_data")
                 boot_script += (
                     ("%(fatload_command)s mmc %(mmc_option)s %(dtb_addr)s " +
@@ -508,37 +520,34 @@
                 boot_script += ((" %(dtb_addr)s")) % replacements
         return boot_script
 
-    @classmethod
-    def add_boot_args(cls, extra_args):
+    def add_boot_args(self, extra_args):
         if extra_args is not None:
-            if cls.extra_boot_args_options is None:
-                cls.extra_boot_args_options = extra_args
+            if self.extra_boot_args_options is None:
+                self.extra_boot_args_options = extra_args
             else:
-                cls.extra_boot_args_options += ' %s' % extra_args
+                self.extra_boot_args_options += ' %s' % extra_args
 
-    @classmethod
-    def add_boot_args_from_file(cls, path):
+    def add_boot_args_from_file(self, path):
         if path is not None:
             with open(path, 'r') as boot_args_file:
-                cls.add_boot_args(boot_args_file.read().strip())
+                self.add_boot_args(boot_args_file.read().strip())
 
-    @classmethod
-    def _get_bootargs(cls, is_live, is_lowmem, consoles, rootfs_id):
+    def _get_bootargs(self, is_live, is_lowmem, consoles, rootfs_id):
         """Get the bootargs for this board.
 
         In general subclasses should not have to override this.
         """
         boot_args_options = 'rootwait ro'
-        if cls.extra_boot_args_options is not None:
-            boot_args_options += ' %s' % cls.extra_boot_args_options
-        serial_opts = cls.extra_serial_opts
+        if self.extra_boot_args_options:
+            boot_args_options += ' %s' % self.extra_boot_args_options
+        serial_opts = self.extra_serial_options
         for console in consoles:
             serial_opts += ' console=%s' % console
 
         lowmem_opt = ''
         boot_snippet = 'root=%s' % rootfs_id
         if is_live:
-            serial_opts += ' %s' % cls.live_serial_opts
+            serial_opts += ' %s' % self.live_serial_opts
             boot_snippet = 'boot=casper'
             if is_lowmem:
                 lowmem_opt = 'only-ubiquity'
@@ -552,45 +561,42 @@
                 "%(boot_snippet)s %(boot_args_options)s"
              % replacements)
 
-    @classmethod
-    def _get_boot_env(cls, is_live, is_lowmem, consoles, rootfs_id,
+    def _get_boot_env(self, is_live, is_lowmem, consoles, rootfs_id,
                       i_img_data, d_img_data):
         """Get the boot environment for this board.
 
         In general subclasses should not have to override this.
         """
         boot_env = {}
-        boot_env["bootargs"] = cls._get_bootargs(
+        boot_env["bootargs"] = self._get_bootargs(
             is_live, is_lowmem, consoles, rootfs_id)
-        boot_env["bootcmd"] = cls._get_bootcmd(i_img_data, d_img_data)
-        boot_env["initrd_high"] = cls.initrd_high
-        boot_env["fdt_high"] = cls.fdt_high
+        boot_env["bootcmd"] = self._get_bootcmd(i_img_data, d_img_data)
+        boot_env["initrd_high"] = self.initrd_high
+        boot_env["fdt_high"] = self.fdt_high
         return boot_env
 
-    @classmethod
-    def make_boot_files(cls, bootloader_parts_dir, is_live, is_lowmem,
+    def make_boot_files(self, bootloader_parts_dir, is_live, is_lowmem,
                         consoles, chroot_dir, rootfs_id, boot_dir,
                         boot_device_or_file):
-        if cls.hwpack_format == HardwarepackHandler.FORMAT_1:
+        if self.hwpack_format == HardwarepackHandler.FORMAT_1:
             parts_dir = bootloader_parts_dir
         else:
             parts_dir = chroot_dir
-        (k_img_data, i_img_data, d_img_data) = cls._get_kflavor_files(
+        (k_img_data, i_img_data, d_img_data) = self._get_kflavor_files(
             parts_dir)
-        boot_env = cls._get_boot_env(is_live, is_lowmem, consoles, rootfs_id,
+        boot_env = self._get_boot_env(is_live, is_lowmem, consoles, rootfs_id,
                                      i_img_data, d_img_data)
 
-        if cls.hwpack_format == HardwarepackHandler.FORMAT_1:
-            cls._make_boot_files(
+        if self.hwpack_format == HardwarepackHandler.FORMAT_1:
+            self._make_boot_files(
                 boot_env, chroot_dir, boot_dir,
                 boot_device_or_file, k_img_data, i_img_data, d_img_data)
         else:
-            cls._make_boot_files_v2(
+            self._make_boot_files_v2(
                 boot_env, chroot_dir, boot_dir,
                 boot_device_or_file, k_img_data, i_img_data, d_img_data)
 
-    @classmethod
-    def _copy_dtb_files(cls, dtb_files, dest_dir, search_dir):
+    def _copy_dtb_files(self, dtb_files, dest_dir, search_dir):
         """Copy the files defined in dtb_files into the boot directory.
 
         :param dtb_files: The list of dtb files
@@ -630,13 +636,12 @@
                 else:
                     # Hopefully we should never get here.
                     # This should only happen if the hwpack config YAML file is
-                    # wrong
+                    # wrong.
                     logger.warn('WARNING: Wrong syntax in metadata file. '
                                 'Check the hwpack configuration file used to '
                                 'generate the hwpack archive.')
 
-    @classmethod
-    def _dd_file(cls, from_file, to_file, seek, max_size=None):
+    def _dd_file(self, from_file, to_file, seek, max_size=None):
         assert from_file is not None, "No source file name given."
         if max_size is not None:
             assert os.path.getsize(from_file) <= max_size, (
@@ -644,23 +649,21 @@
         logger.info("Writing '%s' to '%s' at %s." % (from_file, to_file, seek))
         _dd(from_file, to_file, seek=seek)
 
-    @classmethod
-    def install_samsung_boot_loader(cls, samsung_spl_file, bootloader_file,
+    def install_samsung_boot_loader(self, samsung_spl_file, bootloader_file,
                                     boot_device_or_file):
-                cls._dd_file(samsung_spl_file, boot_device_or_file,
-                             cls.samsung_bl1_start,
-                             cls.samsung_bl1_len * SECTOR_SIZE)
-                cls._dd_file(bootloader_file, boot_device_or_file,
-                             cls.samsung_bl2_start,
-                             cls.samsung_bl2_len * SECTOR_SIZE)
+                self._dd_file(samsung_spl_file, boot_device_or_file,
+                             self.samsung_bl1_start,
+                             self.samsung_bl1_len * SECTOR_SIZE)
+                self._dd_file(bootloader_file, boot_device_or_file,
+                             self.samsung_bl2_start,
+                             self.samsung_bl2_len * SECTOR_SIZE)
 
-    @classmethod
-    def _make_boot_files_v2(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files_v2(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
-        with cls.hardwarepack_handler:
-            spl_file = cls.get_file('spl_file')
-            if cls.spl_in_boot_part:
+        with self.hardwarepack_handler:
+            spl_file = self.get_file('spl_file')
+            if self.spl_in_boot_part:
                 assert spl_file is not None, (
                     "SPL binary could not be found")
                 logger.info(
@@ -670,15 +673,15 @@
                 # XXX: Is this really needed?
                 cmd_runner.run(["sync"]).wait()
 
-            if cls.spl_dd:
-                cls._dd_file(spl_file, boot_device_or_file, cls.spl_dd)
-
-            bootloader_file = cls.get_file('bootloader_file')
-            if cls.bootloader_dd:
-                cls._dd_file(bootloader_file, boot_device_or_file,
-                             cls.bootloader_dd)
-
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
+            if self.spl_dd:
+                self._dd_file(spl_file, boot_device_or_file, self.spl_dd)
+
+            bootloader_file = self.get_file('bootloader_file')
+            if self.bootloader_dd:
+                self._dd_file(bootloader_file, boot_device_or_file,
+                             self.bootloader_dd)
+
+        make_uImage(self.load_addr, k_img_data, boot_dir)
 
         if i_img_data is not None:
             make_uInitrd(i_img_data, boot_dir)
@@ -686,29 +689,28 @@
         if d_img_data is not None:
             make_dtb(d_img_data, boot_dir)
 
-        if cls.boot_script is not None:
-            boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        if self.boot_script is not None:
+            boot_script_path = os.path.join(boot_dir, self.boot_script)
             make_boot_script(boot_env, boot_script_path)
 
             # Only used for Omap, will this be bad for the other boards?
             make_boot_ini(boot_script_path, boot_dir)
 
-        if (cls.snowball_startup_files_config is not None and
-            cls.board != 'snowball_sd'):
-            cls.populate_raw_partition(boot_device_or_file, chroot_dir)
+        if (self.snowball_startup_files_config is not None and
+            self.board != 'snowball_sd'):
+            self.populate_raw_partition(boot_device_or_file, chroot_dir)
 
-        if cls.env_dd:
+        if self.env_dd:
             # Do we need to zero out the env before flashing it?
             _dd("/dev/zero", boot_device_or_file,
-                count=cls.samsung_env_len,
-                seek=cls.samsung_env_start)
-            env_size = cls.samsung_env_len * SECTOR_SIZE
+                count=self.samsung_env_len,
+                seek=self.samsung_env_start)
+            env_size = self.samsung_env_len * SECTOR_SIZE
             env_file = make_flashable_env(boot_env, env_size)
-            cls._dd_file(env_file, boot_device_or_file,
-                         cls.samsung_env_start)
+            self._dd_file(env_file, boot_device_or_file,
+                         self.samsung_env_start)
 
-    @classmethod
-    def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         """Make the necessary boot files for this board.
@@ -718,8 +720,7 @@
         """
         raise NotImplementedError()
 
-    @classmethod
-    def populate_boot(cls, chroot_dir, rootfs_id, boot_partition, boot_disk,
+    def populate_boot(self, chroot_dir, rootfs_id, boot_partition, boot_disk,
                       boot_device_or_file, is_live, is_lowmem, consoles):
         parts_dir = 'boot'
         if is_live:
@@ -727,21 +728,21 @@
         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):
-            with cls.hardwarepack_handler:
-                if cls.bootloader_file_in_boot_part:
+            with self.hardwarepack_handler:
+                if self.bootloader_file_in_boot_part:
                     # <legacy v1 support>
-                    if cls.bootloader_flavor is not None:
+                    if self.bootloader_flavor is not None:
                         default = os.path.join(
                             chroot_dir, 'usr', 'lib', 'u-boot',
-                            cls.bootloader_flavor, 'u-boot.img')
+                            self.bootloader_flavor, 'u-boot.img')
                         if not os.path.exists(default):
                             default = os.path.join(
                                 chroot_dir, 'usr', 'lib', 'u-boot',
-                                cls.bootloader_flavor, 'u-boot.bin')
+                                self.bootloader_flavor, 'u-boot.bin')
                     else:
                         default = None
                     # </legacy v1 support>
-                    bootloader_bin = cls.get_file('bootloader_file',
+                    bootloader_bin = self.get_file('bootloader_file',
                                                    default=default)
                     assert bootloader_bin is not None, (
                         "bootloader binary could not be found")
@@ -751,18 +752,17 @@
                     proc.wait()
 
                 # Handle copy_files field.
-                cls.copy_files(boot_disk)
+                self.copy_files(boot_disk)
 
             # Handle dtb_files field.
-            if cls.dtb_files:
-                cls._copy_dtb_files(cls.dtb_files, boot_disk, chroot_dir)
+            if self.dtb_files:
+                self._copy_dtb_files(self.dtb_files, boot_disk, chroot_dir)
 
-            cls.make_boot_files(
+            self.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):
+    def copy_files(self, boot_disk):
         """Handle the copy_files metadata field."""
 
         # Extract anything specified by copy_files sections
@@ -772,13 +772,14 @@
         #   {'source_path': 'dest_path'}
         #  ]
         # }
-        if cls.bootloader_copy_files is None:
+        if self.bootloader_copy_files is None:
             return
 
-        for source_package, file_list in cls.bootloader_copy_files.iteritems():
+        for source_package, file_list in \
+                self.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 = self.hardwarepack_handler.get_file_from_package(
                         source_path, source_package)
                     dest_path = dest_path.lstrip("/\\")
                     dirname = os.path.dirname(dest_path)
@@ -791,25 +792,24 @@
                          os.path.join(boot_disk, dest_path)], as_root=True)
                     proc.wait()
 
-    @classmethod
-    def _get_kflavor_files(cls, path):
+    def _get_kflavor_files(self, path):
         """Search for kernel, initrd and optional dtb in path."""
-        if cls.kernel_flavors is None:
+        if self.kernel_flavors is None:
             # V2 metadata specifies each glob, not flavors.
             # XXX This duplication is temporary until V1 dies.
-            return cls._get_kflavor_files_v2(path)
+            return self._get_kflavor_files_v2(path)
 
-        for flavor in cls.kernel_flavors:
+        for flavor in self.kernel_flavors:
             kregex = KERNEL_GLOB % {'kernel_flavor': flavor}
             iregex = INITRD_GLOB % {'kernel_flavor': flavor}
             dregex = DTB_GLOB % {'kernel_flavor': flavor,
-                                 'dtb_name': cls.dtb_name}
+                                 'dtb_name': self.dtb_name}
             kernel = _get_file_matching(os.path.join(path, kregex))
             if kernel is not None:
                 initrd = _get_file_matching(os.path.join(path, iregex))
                 if initrd is not None:
                     dtb = None
-                    if cls.dtb_name is not None:
+                    if self.dtb_name is not None:
                         dtb = _get_file_matching(os.path.join(path, dregex))
                     return (kernel, initrd, dtb)
                 raise ValueError(
@@ -817,83 +817,83 @@
                         flavor, iregex))
         raise ValueError(
             "No kernel found matching %s for flavors %s" % (
-                KERNEL_GLOB, " ".join(cls.kernel_flavors)))
+                KERNEL_GLOB, " ".join(self.kernel_flavors)))
 
-    @classmethod
-    def _get_kflavor_files_v2(cls, path):
+    def _get_kflavor_files_v2(self, path):
         kernel = initrd = dtb = None
 
-        if cls.vmlinuz:
-            kernel = _get_file_matching(os.path.join(path, cls.vmlinuz))
-        if not cls.vmlinuz or not kernel:
+        if self.vmlinuz:
+            kernel = _get_file_matching(os.path.join(path, self.vmlinuz))
+        if not self.vmlinuz or not kernel:
             raise ValueError("Unable to find a valid kernel image.")
 
-        if cls.initrd:
-            initrd = _get_file_matching(os.path.join(path, cls.initrd))
-        if not cls.initrd or not initrd:
+        if self.initrd:
+            initrd = _get_file_matching(os.path.join(path, self.initrd))
+        if not self.initrd or not initrd:
             logger.warn("Could not find a valid initrd, skipping uInitd.")
 
-        if cls.dtb_file:
-            dtb = _get_file_matching(os.path.join(path, cls.dtb_file))
-        if not cls.dtb_file or not dtb:
+        if self.dtb_file:
+            dtb = _get_file_matching(os.path.join(path, self.dtb_file))
+        if not self.dtb_file or not dtb:
             logger.warn("Could not find a valid dtb file, skipping it.")
 
         logger.info("Will use kernel=%s, initrd=%s, dtb=%s." % \
                              (kernel, initrd, dtb))
         return (kernel, initrd, dtb)
 
-    @classmethod
-    def populate_raw_partition(cls, media, boot_dir):
+    def populate_raw_partition(self, media, boot_dir):
         # Override in subclass if needed
         pass
 
-    @classmethod
-    def snowball_config(cls, chroot_dir):
+    def snowball_config(self, chroot_dir):
         # Override in subclasses where applicable
         raise NotImplementedError(
             "snowball_config() must only be called on BoardConfigs that "
             "use the Snowball startupfiles.")
 
+    # XXX: can be removed when killing v1 hwpack and updating the attributes
+    # that use it.
+    @staticmethod
+    def _check_placeholder_presence(string, placeholder):
+        """Checks if the passed string contains the particular placeholder."""
+        # Very simple way of achieving that.
+        presence = False
+        if placeholder in string:
+            presence = True
+        return presence
+
 
 class OmapConfig(BoardConfig):
-    kernel_flavors = ['linaro-omap4', 'linaro-lt-omap', 'linaro-omap', 'omap4']
-    bootloader_file_in_boot_part = True
-
-    # XXX: Here we define these things as dynamic properties because our
-    # temporary hack to fix bug 697824 relies on changing the board's
-    # serial_tty at run time.
-    _extra_serial_opts = None
-    _live_serial_opts = None
-    _serial_tty = None
-
-    @classproperty
-    def serial_tty(cls):
-        # This is just to make sure no callsites use .serial_tty before
-        # calling set_appropriate_serial_tty(). If we had this in the first
-        # place we'd have uncovered bug 710971 before releasing.
-        raise AttributeError(
-            "You must not use this attribute before calling "
-            "set_appropriate_serial_tty")
-
-    @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 set_appropriate_serial_tty(cls, chroot_dir):
+
+    def __init__(self):
+        super(OmapConfig, self).__init__()
+        self.kernel_flavors = ['linaro-omap4', 'linaro-lt-omap',
+                               'linaro-omap', 'omap4']
+        self.bootloader_file_in_boot_part = True
+        # XXX: Here we define these things as dynamic properties because our
+        # temporary hack to fix bug 697824 relies on changing the board's
+        # serial_tty at run time.
+        self._serial_tty = None
+
+    # XXX: when killing v1 hwpack this should be safely removed.
+    def _get_serial_tty(self):
+        return self._serial_tty
+
+    def _set_serial_tty(self, value):
+        self._serial_tty = value
+
+    serial_tty = property(_get_serial_tty, _set_serial_tty)
+
+    def set_appropriate_serial_tty(self, chroot_dir):
         """Set the appropriate serial_tty depending on the kernel used.
 
         If the kernel found in the chroot dir is << 2.6.36 we use tyyS2, else
         we use the default value (_serial_tty).
         """
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
         # XXX: This is also part of our temporary hack to fix bug 697824.
-        cls.serial_tty = classproperty(lambda cls: cls._serial_tty)
+        # cls.serial_tty = classproperty(lambda cls: cls._serial_tty)
         vmlinuz = _get_file_matching(
             os.path.join(chroot_dir, 'boot', 'vmlinuz*'))
         basename = os.path.basename(vmlinuz)
@@ -902,135 +902,134 @@
         if match is not None:
             minor_version = match.group(1)
             if int(minor_version) < 36:
-                cls.serial_tty = classproperty(lambda cls: 'ttyS2')
+                self.serial_tty = 'ttyS2'
 
-    @classmethod
-    def make_boot_files(cls, bootloader_parts_dir, is_live, is_lowmem,
+    def make_boot_files(self, bootloader_parts_dir, is_live, is_lowmem,
                         consoles, chroot_dir, rootfs_id, boot_dir,
                         boot_device_or_file):
         # XXX: This is also part of our temporary hack to fix bug 697824; we
         # need to call set_appropriate_serial_tty() before doing anything that
-        # may use cls.serial_tty.
-        if cls.hwpack_format == HardwarepackHandler.FORMAT_1:
-            cls.set_appropriate_serial_tty(chroot_dir)
-        super(OmapConfig, cls).make_boot_files(
+        # may use self.serial_tty.
+        if self.hwpack_format == HardwarepackHandler.FORMAT_1:
+            self.set_appropriate_serial_tty(chroot_dir)
+        super(OmapConfig, self).make_boot_files(
             bootloader_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
             rootfs_id, boot_dir, boot_device_or_file)
 
-    @classmethod
-    def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
-        install_omap_boot_loader(chroot_dir, boot_dir, cls)
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
+        install_omap_boot_loader(chroot_dir, boot_dir, self)
+        make_uImage(self.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
         make_dtb(d_img_data, boot_dir)
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
         make_boot_ini(boot_script_path, boot_dir)
 
 
 class BeagleConfig(OmapConfig):
-    bootloader_flavor = 'omap3_beagle'
-    dtb_name = 'omap3-beagle.dtb'
-    _serial_tty = 'ttyO2'
-    _extra_serial_opts = 'console=tty0 console=%s,115200n8'
-    _live_serial_opts = 'serialtty=%s'
-    kernel_addr = '0x80000000'
-    dtb_addr = '0x815f0000'
-    initrd_addr = '0x81600000'
-    load_addr = '0x80008000'
-    boot_script = 'boot.scr'
-    extra_boot_args_options = (
-        'earlyprintk fixrtc nocompcache vram=12M '
-        'omapfb.mode=dvi:1280x720MR-16@60 mpurate=${mpurate}')
+
+    def __init__(self):
+        super(BeagleConfig, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.bootloader_flavor = 'omap3_beagle'
+        self.dtb_addr = '0x815f0000'
+        self.dtb_name = 'omap3-beagle.dtb'
+        self.extra_boot_args_options = (
+            'earlyprintk fixrtc nocompcache vram=12M '
+            'omapfb.mode=dvi:1280x720MR-16@60 mpurate=${mpurate}')
+        self.initrd_addr = '0x81600000'
+        self.kernel_addr = '0x80000000'
+        self.load_addr = '0x80008000'
+        self._serial_tty = 'ttyO2'
+        self._extra_serial_options = 'console=tty0 console=%s,115200n8'
+        self._live_serial_opts = 'serialtty=%s'
 
 
 class OveroConfig(OmapConfig):
-    bootloader_flavor = 'omap3_overo'
-    dtb_name = 'omap3-overo.dtb'
-    _serial_tty = 'ttyO2'
-    _extra_serial_opts = 'console=tty0 console=%s,115200n8'
-    kernel_addr = '0x80000000'
-    dtb_addr = '0x815f0000'
-    initrd_addr = '0x81600000'
-    load_addr = '0x80008000'
-    boot_script = 'boot.scr'
-    extra_boot_args_options = (
-        'earlyprintk mpurate=${mpurate} vram=12M '
-        'omapdss.def_disp=${defaultdisplay} omapfb.mode=dvi:${dvimode}')
+    def __init__(self):
+        super(OveroConfig, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.bootloader_flavor = 'omap3_overo'
+        self.dtb_addr = '0x815f0000'
+        self.dtb_name = 'omap3-overo.dtb'
+        self.extra_boot_args_options = (
+            'earlyprintk mpurate=${mpurate} vram=12M '
+            'omapdss.def_disp=${defaultdisplay} omapfb.mode=dvi:${dvimode}')
+        self.initrd_addr = '0x81600000'
+        self.kernel_addr = '0x80000000'
+        self.load_addr = '0x80008000'
+        self._extra_serial_options = 'console=tty0 console=%s,115200n8'
+        self._serial_tty = 'ttyO2'
 
 
 class PandaConfig(OmapConfig):
-    bootloader_flavor = 'omap4_panda'
-    dtb_name = 'omap4-panda.dtb'
-    _serial_tty = 'ttyO2'
-    _extra_serial_opts = 'console=tty0 console=%s,115200n8'
-    _live_serial_opts = 'serialtty=%s'
-    kernel_addr = '0x80200000'
-    dtb_addr = '0x815f0000'
-    initrd_addr = '0x81600000'
-    load_addr = '0x80008000'
-    boot_script = 'boot.scr'
-    extra_boot_args_options = (
-        'earlyprintk fixrtc nocompcache vram=48M '
-        'omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000')
+    def __init__(self):
+        super(PandaConfig, self).__init__()
+        self._serial_tty = 'ttyO2'
+        self.boot_script = 'boot.scr'
+        self.bootloader_flavor = 'omap4_panda'
+        self.dtb_addr = '0x815f0000'
+        self.dtb_name = 'omap4-panda.dtb'
+        self.extra_boot_args_options = (
+            'earlyprintk fixrtc nocompcache vram=48M '
+            'omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000')
+        self.initrd_addr = '0x81600000'
+        self.kernel_addr = '0x80200000'
+        self.load_addr = '0x80008000'
+        self._extra_serial_options = 'console=tty0 console=%s,115200n8'
+        self._live_serial_opts = 'serialtty=%s'
 
 
 class IgepConfig(BeagleConfig):
-    bootloader_file_in_boot_part = False
-    bootloader_flavor = None
-    dtb_name = 'isee-igep-v2.dtb'
+    def __init__(self):
+        super(IgepConfig, self).__init__()
+        self.bootloader_file_in_boot_part = False
+        self.bootloader_flavor = None
+        self.dtb_name = 'isee-igep-v2.dtb'
 
-    @classmethod
-    def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
+        make_uImage(self.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
         make_dtb(d_img_data, boot_dir)
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
         make_boot_ini(boot_script_path, boot_dir)
 
 
 class Ux500Config(BoardConfig):
-    serial_tty = 'ttyAMA2'
-    _extra_serial_opts = 'console=tty0 console=%s,115200n8'
-    _live_serial_opts = 'serialtty=%s'
-    kernel_addr = '0x00100000'
-    initrd_addr = '0x08000000'
-    load_addr = '0x00008000'
-    kernel_flavors = ['u8500', 'ux500']
-    boot_script = 'flash.scr'
-    extra_boot_args_options = (
-        'earlyprintk rootdelay=1 fixrtc nocompcache '
-        'mem=96M@0 mem_modem=32M@96M mem=44M@128M pmem=22M@172M '
-        'mem=30M@194M mem_mali=32M@224M pmem_hwb=54M@256M '
-        '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,
+    def __init__(self):
+        super(Ux500Config, self).__init__()
+        self.boot_script = 'flash.scr'
+        self.extra_boot_args_options = (
+            'earlyprintk rootdelay=1 fixrtc nocompcache '
+            'mem=96M@0 mem_modem=32M@96M mem=44M@128M pmem=22M@172M '
+            'mem=30M@194M mem_mali=32M@224M pmem_hwb=54M@256M '
+            'hwmem=48M@302M mem=152M@360M')
+        self.initrd_addr = '0x08000000'
+        self.kernel_addr = '0x00100000'
+        self.kernel_flavors = ['u8500', 'ux500']
+        self.load_addr = '0x00008000'
+        self.mmc_option = '1:1'
+        self.serial_tty = 'ttyAMA2'
+        self._extra_serial_options = 'console=tty0 console=%s,115200n8'
+        self._live_serial_opts = 'serialtty=%s'
+
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
+        make_uImage(self.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
 
 
@@ -1040,15 +1039,16 @@
        Note that the Snowball board needs a loader partition on the
        internal eMMC flash to boot. That partition is created with
        the SnowballConfigImage configuration.'''
+    def __init__(self):
+        super(SnowballSdConfig, self).__init__()
 
-    @classmethod
-    def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
+        make_uImage(self.load_addr, k_img_data, boot_dir)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
 
 
@@ -1056,16 +1056,18 @@
     '''Use only with --image option. Creates a raw image which contains an
        additional (raw) loader partition, containing some boot stages
        and u-boot.'''
-    # Boot ROM looks for a boot table of contents (TOC) at 0x20000
-    # Actually, it first looks at address 0, but that's where l-m-c
-    # puts the MBR, so the boot loader skips that address.
-    supports_writing_to_mmc = False
     SNOWBALL_LOADER_START_S = (128 * 1024) / SECTOR_SIZE
-    snowball_startup_files_config = 'startfiles.cfg'
     TOC_SIZE = 512
 
-    @classmethod
-    def get_v1_sfdisk_cmd(cls, should_align_boot_part=None):
+    def __init__(self):
+        super(SnowballEmmcConfig, self).__init__()
+        # Boot ROM looks for a boot table of contents (TOC) at 0x20000
+        # Actually, it first looks at address 0, but that's where l-m-c
+        # puts the MBR, so the boot loader skips that address.
+        self.supports_writing_to_mmc = False
+        self.snowball_startup_files_config = 'startfiles.cfg'
+
+    def get_v1_sfdisk_cmd(self, should_align_boot_part=None):
         """Return the sfdisk command to partition the media.
 
         :param should_align_boot_part: Ignored.
@@ -1083,68 +1085,64 @@
         # with the usual SECTOR_SIZE of 0x200.
         # (sector 0 is MBR / partition table)
         loader_start, loader_end, loader_len = align_partition(
-            SnowballEmmcConfig.SNOWBALL_LOADER_START_S,
-            cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
+            self.SNOWBALL_LOADER_START_S,
+            self.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
 
         boot_start, boot_end, boot_len = align_partition(
-            loader_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            loader_end + 1, self.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
         # we ignore _root_end / _root_len and return an sfdisk command to
         # instruct the use of all remaining space; XXX if we had some root size
         # config, we could do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
         loader_start, loader_len, boot_start, boot_len, root_start)
 
-    @classmethod
-    def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
+        make_uImage(self.load_addr, k_img_data, boot_dir)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
-        cls.populate_raw_partition(boot_device_or_file, chroot_dir)
+        self.populate_raw_partition(boot_device_or_file, chroot_dir)
 
-    @classmethod
-    def populate_raw_partition(cls, boot_device_or_file, chroot_dir):
+    def populate_raw_partition(self, boot_device_or_file, chroot_dir):
         # Populate created raw partition with TOC and startup files.
         _, toc_filename = tempfile.mkstemp()
-        config_files_dir = cls.snowball_config(chroot_dir)
-        new_files = cls.get_file_info(chroot_dir, config_files_dir)
+        config_files_dir = self.snowball_config(chroot_dir)
+        new_files = self.get_file_info(chroot_dir, config_files_dir)
         with open(toc_filename, 'wb') as toc:
-            cls.create_toc(toc, new_files)
-        cls.install_snowball_boot_loader(toc_filename, new_files,
+            self.create_toc(toc, new_files)
+        self.install_snowball_boot_loader(toc_filename, new_files,
                                          boot_device_or_file,
-                                         cls.SNOWBALL_LOADER_START_S,
-                                         cls.delete_startupfiles)
-        cls.delete_file(toc_filename)
-        if cls.delete_startupfiles:
-            cls.delete_file(os.path.join(config_files_dir,
-                                         cls.snowball_startup_files_config))
+                                         self.SNOWBALL_LOADER_START_S,
+                                         self.delete_startupfiles)
+        self.delete_file(toc_filename)
+        if self.delete_startupfiles:
+            self.delete_file(os.path.join(config_files_dir,
+                                         self.snowball_startup_files_config))
 
-    @classmethod
-    def snowball_config(cls, chroot_dir):
+    def snowball_config(self, chroot_dir):
         # We will find the startupfiles in the target boot partition.
         return os.path.join(chroot_dir, 'boot')
 
-    @classproperty
-    def delete_startupfiles(cls):
+    @property
+    def delete_startupfiles(self):
         # The startupfiles will have been installed to the target boot
         # partition by the hwpack, and should be deleted so we don't leave
         # them on the target system.
         return True
 
-    @classmethod
-    def install_snowball_boot_loader(cls, toc_file_name, files,
+    def install_snowball_boot_loader(self, toc_file_name, files,
                                      boot_device_or_file, start_sector,
                                      delete_startupfiles=False):
         ''' Copies TOC and boot files into the boot partition.
         A sector size of 1 is used for some files, as they do not
         necessarily start on an even address. '''
-        assert os.path.getsize(toc_file_name) <= cls.TOC_SIZE
+        assert os.path.getsize(toc_file_name) <= self.TOC_SIZE
         _dd(toc_file_name, boot_device_or_file, seek=start_sector)
 
         for file in files:
@@ -1159,16 +1157,14 @@
                 seek_sectors = start_sector + file['offset'] / SECTOR_SIZE
                 _dd(filename, boot_device_or_file, seek=seek_sectors)
             if delete_startupfiles:
-                cls.delete_file(filename)
+                self.delete_file(filename)
 
-    @classmethod
-    def delete_file(cls, file_path):
+    def delete_file(self, file_path):
             cmd = ["rm", "%s" % file_path]
             proc = cmd_runner.run(cmd, as_root=True)
             proc.wait()
 
-    @classmethod
-    def create_toc(cls, f, files):
+    def create_toc(self, f, files):
         ''' Writes a table of contents of the boot binaries.
         Boot rom searches this table to find the binaries.'''
         # Format string means: < little endian,
@@ -1190,15 +1186,14 @@
                                file['section_name'])
             f.write(data)
 
-    @classmethod
-    def get_file_info(cls, chroot_dir, config_files_dir):
+    def get_file_info(self, chroot_dir, config_files_dir):
         ''' Fills in the offsets of files that are located in
         non-absolute memory locations depending on their sizes.'
         Also fills in file sizes'''
-        ofs = cls.TOC_SIZE
+        ofs = self.TOC_SIZE
         files = []
         with open(os.path.join(config_files_dir,
-                               cls.snowball_startup_files_config),
+                               self.snowball_startup_files_config),
                   'r') as info_file:
             for line in info_file:
                 file_data = line.split()
@@ -1229,23 +1224,16 @@
 
 
 class Mx5Config(BoardConfig):
-    serial_tty = 'ttymxc0'
-    _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_v1_sfdisk_cmd(cls, should_align_boot_part=None):
+    def __init__(self):
+        super(Mx5Config, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.mmc_option = '0:2'
+        self.mmc_part_offset = 1
+        self.serial_tty = 'ttymxc0'
+        self._extra_serial_options = 'console=tty0 console=%s,115200n8'
+        self._live_serial_opts = 'serialtty=%s'
+
+    def get_v1_sfdisk_cmd(self, should_align_boot_part=None):
         """Return the sfdisk command to partition the media.
 
         :param should_align_boot_part: Ignored.
@@ -1259,103 +1247,107 @@
         # onwards, so it's safer to just start at the first sector, sector 1
         # (sector 0 is MBR / partition table)
         loader_start, loader_end, loader_len = align_partition(
-            1, cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
+            1, self.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
 
         boot_start, boot_end, boot_len = align_partition(
-            loader_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            loader_end + 1, self.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
         # we ignore _root_end / _root_len and return a sfdisk command to
         # instruct the use of all remaining space; XXX if we had some root size
         # config, we could do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
             loader_start, loader_len, boot_start, boot_len, root_start)
 
-    @classmethod
-    def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
-        with cls.hardwarepack_handler:
-            bootloader_file = cls.get_file('bootloader_file',
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
+        with self.hardwarepack_handler:
+            bootloader_file = self.get_file('bootloader_file',
                 default=os.path.join(
-                    chroot_dir, 'usr', 'lib', 'u-boot', cls.bootloader_flavor,
+                    chroot_dir, 'usr', 'lib', 'u-boot', self.bootloader_flavor,
                     'u-boot.imx'))
             install_mx5_boot_loader(bootloader_file, boot_device_or_file,
-                                    cls.LOADER_MIN_SIZE_S)
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
+                                    self.LOADER_MIN_SIZE_S)
+        make_uImage(self.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
         make_dtb(d_img_data, boot_dir)
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
 
 
 class Mx51Config(Mx5Config):
-    kernel_addr = '0x90000000'
-    dtb_addr = '0x91ff0000'
-    initrd_addr = '0x92000000'
-    load_addr = '0x90008000'
-    kernel_flavors = ['linaro-mx51', 'linaro-lt-mx5']
+    def __init__(self):
+        super(Mx51Config, self).__init__()
+        self.dtb_addr = '0x91ff0000'
+        self.initrd_addr = '0x92000000'
+        self.kernel_addr = '0x90000000'
+        self.kernel_flavors = ['linaro-mx51', 'linaro-lt-mx5']
+        self.load_addr = '0x90008000'
 
 
 class Mx53Config(Mx5Config):
-    kernel_addr = '0x70000000'
-    dtb_addr = '0x71ff0000'
-    initrd_addr = '0x72000000'
-    load_addr = '0x70008000'
-    kernel_flavors = ['linaro-lt-mx53', 'linaro-lt-mx5']
+    def __init__(self):
+        super(Mx53Config, self).__init__()
+        self.dtb_addr = '0x71ff0000'
+        self.initrd_addr = '0x72000000'
+        self.kernel_addr = '0x70000000'
+        self.kernel_flavors = ['linaro-lt-mx53', 'linaro-lt-mx5']
+        self.load_addr = '0x70008000'
 
 
 class EfikamxConfig(Mx51Config):
-    bootloader_flavor = 'efikamx'
-    dtb_name = 'genesi-efikamx.dtb'
+    def __init__(self):
+        super(EfikamxConfig, self).__init__()
+        self.bootloader_flavor = 'efikamx'
+        self.dtb_name = 'genesi-efikamx.dtb'
 
 
 class EfikasbConfig(Mx51Config):
-    bootloader_flavor = 'efikasb'
-    dtb_name = 'genesi-efikasb.dtb'
+    def __init__(self):
+        super(EfikasbConfig, self).__init__()
+        self.bootloader_flavor = 'efikasb'
+        self.dtb_name = 'genesi-efikasb.dtb'
 
 
 class Mx51evkConfig(Mx51Config):
-    bootloader_flavor = 'mx51evk'
-    dtb_name = 'mx51-babbage.dtb'
+    def __init__(self):
+        super(Mx51evkConfig, self).__init__()
+        self.bootloader_flavor = 'mx51evk'
+        self.dtb_name = 'mx51-babbage.dtb'
 
 
 class Mx53LoCoConfig(Mx53Config):
-    bootloader_flavor = 'mx53loco'
-    dtb_name = 'mx53-loco.dtb'
+    def __init__(self):
+        super(Mx53LoCoConfig, self).__init__()
+        self.bootloader_flavor = 'mx53loco'
+        self.dtb_name = 'mx53-loco.dtb'
 
 
 class VexpressConfig(BoardConfig):
-    bootloader_flavor = 'ca9x4_ct_vxp'
-    bootloader_file_in_boot_part = True
-    serial_tty = 'ttyAMA0'
-    _extra_serial_opts = 'console=tty0 console=%s,38400n8'
-    _live_serial_opts = 'serialtty=%s'
-    kernel_addr = '0x60000000'
-    initrd_addr = '0x62000000'
-    load_addr = '0x60008000'
-    kernel_flavors = ['linaro-vexpress']
-    boot_script = 'boot.scr'
-    # ARM Boot Monitor is used to load u-boot, uImage etc. into flash and
-    # 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,
+    def __init__(self):
+        super(VexpressConfig, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.bootloader_file_in_boot_part = True
+        self.bootloader_flavor = 'ca9x4_ct_vxp'
+        # ARM Boot Monitor is used to load u-boot, uImage etc. into flash and
+        # only allows for FAT16
+        self.fat_size = 16
+        self.initrd_addr = '0x62000000'
+        self.kernel_addr = '0x60000000'
+        self.kernel_flavors = ['linaro-vexpress']
+        self.load_addr = '0x60008000'
+        self.serial_tty = 'ttyAMA0'
+        self._extra_serial_options = 'console=tty0 console=%s,38400n8'
+        self._live_serial_opts = 'serialtty=%s'
+
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
+        make_uImage(self.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
 
 
@@ -1363,22 +1355,23 @@
     # For now, this is a duplicate of VexpressConfig.
     # In future, there will also be A5 and A15 variants.
     # For all of these, there should never be any V1 hardware packs.
-    pass
+    def __init__(self):
+        super(VexpressA9Config, self).__init__()
 
 
 class FastModelConfig(BoardConfig):
-    supports_writing_to_mmc = False
+    def __init__(self):
+        super(FastModelConfig, self).__init__()
+        self.supports_writing_to_mmc = False
 
-    @classmethod
-    def _get_bootcmd(cls, i_img_data, d_img_data):
+    def _get_bootcmd(self, i_img_data, d_img_data):
         """Get the bootcmd for FastModel.
 
         We override this as we don't do uboot.
         """
         return ""
 
-    @classmethod
-    def _make_boot_files_v2(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files_v2(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         output_dir = os.path.dirname(boot_device_or_file)
@@ -1395,16 +1388,14 @@
 
 
 class SamsungConfig(BoardConfig):
-    @classproperty
-    def extra_serial_opts(cls):
-        return cls._extra_serial_opts % cls.serial_tty
+    def __init__(self):
+        super(SamsungConfig, self).__init__()
+        self._extra_serial_options = None
 
-    @classmethod
-    def get_v1_sfdisk_cmd(cls, should_align_boot_part=False):
+    def get_v1_sfdisk_cmd(self, should_align_boot_part=False):
         # bootloaders partition needs to hold BL1, U-Boot environment, and BL2
-        loaders_min_len = (
-            cls.samsung_bl1_start + cls.samsung_bl1_len + cls.samsung_bl2_len +
-            cls.samsung_env_len)
+        loaders_min_len = (self.samsung_bl1_start + self.samsung_bl1_len +
+            self.samsung_bl2_len + self.samsung_env_len)
 
         # bootloaders partition
         loaders_start, loaders_end, loaders_len = align_partition(
@@ -1412,44 +1403,42 @@
 
         # FAT boot partition
         boot_start, boot_end, boot_len = align_partition(
-            loaders_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            loaders_end + 1, self.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         # root partition
         # we ignore _root_end / _root_len and return a sfdisk command to
         # instruct the use of all remaining space; XXX if we had some root size
         # config, we could do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
             loaders_start, loaders_len, boot_start, boot_len, root_start)
 
-    @classmethod
-    def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
-        cls.install_samsung_boot_loader(cls._get_samsung_spl(chroot_dir),
-            cls._get_samsung_bootloader(chroot_dir), boot_device_or_file)
-        env_size = cls.samsung_env_len * SECTOR_SIZE
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
+        self.install_samsung_boot_loader(self._get_samsung_spl(chroot_dir),
+            self._get_samsung_bootloader(chroot_dir), boot_device_or_file)
+        env_size = self.samsung_env_len * SECTOR_SIZE
         env_file = make_flashable_env(boot_env, env_size)
-        _dd(env_file, boot_device_or_file, seek=cls.samsung_env_start)
+        _dd(env_file, boot_device_or_file, seek=self.samsung_env_start)
 
-        make_uImage(cls.load_addr, k_img_data, boot_dir)
+        make_uImage(self.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
 
         # unused at the moment once FAT support enabled for the
         # Samsung u-boot this can be used bug 727978
-        boot_script_path = os.path.join(boot_dir, cls.boot_script)
+        boot_script_path = os.path.join(boot_dir, self.boot_script)
         make_boot_script(boot_env, boot_script_path)
 
-    @classmethod
-    def _get_samsung_spl(cls, chroot_dir):
+    def _get_samsung_spl(self, chroot_dir):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
         spl_dir = os.path.join(
-            chroot_dir, 'usr', 'lib', 'u-boot', cls.bootloader_flavor)
+            chroot_dir, 'usr', 'lib', 'u-boot', self.bootloader_flavor)
         old_spl_path = os.path.join(spl_dir, 'v310_mmc_spl.bin')
         new_spl_path = os.path.join(spl_dir, 'u-boot-mmc-spl.bin')
         spl_path_origen2 = os.path.join(spl_dir, 'origen-spl.bin')
@@ -1479,49 +1468,48 @@
                                  % (old_spl_path, new_spl_path))
         return spl_file
 
-    @classmethod
-    def _get_samsung_bootloader(cls, chroot_dir):
+    def _get_samsung_bootloader(self, chroot_dir):
         # XXX: delete this method when hwpacks V1 can die
-        assert cls.hwpack_format == HardwarepackHandler.FORMAT_1
+        assert self.hwpack_format == HardwarepackHandler.FORMAT_1
         bootloader_file = os.path.join(
-            chroot_dir, 'usr', 'lib', 'u-boot', cls.bootloader_flavor,
+            chroot_dir, 'usr', 'lib', 'u-boot', self.bootloader_flavor,
             'u-boot.bin')
         return bootloader_file
 
-    @classmethod
-    def populate_raw_partition(cls, boot_device_or_file, chroot_dir):
+    def populate_raw_partition(self, boot_device_or_file, chroot_dir):
         # Zero the env so that the boot_script will get loaded
-        _dd("/dev/zero", boot_device_or_file, count=cls.samsung_env_len,
-            seek=cls.samsung_env_start)
+        _dd("/dev/zero", boot_device_or_file, count=self.samsung_env_len,
+            seek=self.samsung_env_start)
         # Populate created raw partition with BL1 and u-boot
         spl_file = os.path.join(chroot_dir, 'boot', 'u-boot-mmc-spl.bin')
         assert os.path.getsize(spl_file) <= (
-            cls.samsung_bl1_len * SECTOR_SIZE), (
+            self.samsung_bl1_len * SECTOR_SIZE), (
             "%s is larger than Samsung BL1 size" % spl_file)
-        _dd(spl_file, boot_device_or_file, seek=cls.samsung_bl1_start)
+        _dd(spl_file, boot_device_or_file, seek=self.samsung_bl1_start)
         uboot_file = os.path.join(chroot_dir, 'boot', 'u-boot.bin')
         assert os.path.getsize(uboot_file) <= (
-            cls.samsung_bl2_len * SECTOR_SIZE), (
+            self.samsung_bl2_len * SECTOR_SIZE), (
             "%s is larger than Samsung BL2 size" % uboot_file)
-        _dd(uboot_file, boot_device_or_file, seek=cls.samsung_bl2_start)
+        _dd(uboot_file, boot_device_or_file, seek=self.samsung_bl2_start)
 
 
 class SMDKV310Config(SamsungConfig):
-    bootloader_flavor = 'smdkv310'
-    serial_tty = 'ttySAC1'
-    _extra_serial_opts = 'console=%s,115200n8'
-    kernel_addr = '0x40007000'
-    initrd_addr = '0x42000000'
-    load_addr = '0x40008000'
-    kernel_flavors = ['s5pv310']
-    boot_script = 'boot.scr'
-    mmc_part_offset = 1
-    mmc_option = '0:2'
+    def __init__(self):
+        super(SMDKV310Config, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.bootloader_flavor = 'smdkv310'
+        self.initrd_addr = '0x42000000'
+        self.kernel_addr = '0x40007000'
+        self.kernel_flavors = ['s5pv310']
+        self.load_addr = '0x40008000'
+        self.mmc_option = '0:2'
+        self.mmc_part_offset = 1
+        self.serial_tty = 'ttySAC1'
+        self._extra_serial_options = 'console=%s,115200n8'
 
-    @classmethod
-    def _get_boot_env(cls, is_live, is_lowmem, consoles, rootfs_id,
+    def _get_boot_env(self, is_live, is_lowmem, consoles, rootfs_id,
                       i_img_data, d_img_data):
-        boot_env = super(SamsungConfig, cls)._get_boot_env(
+        boot_env = super(SamsungConfig, self)._get_boot_env(
             is_live, is_lowmem, consoles, rootfs_id, i_img_data, d_img_data)
 
         boot_env["ethact"] = "smc911x-0"
@@ -1531,60 +1519,59 @@
 
 
 class OrigenConfig(SamsungConfig):
-    bootloader_flavor = 'origen'
-    serial_tty = 'ttySAC2'
-    _extra_serial_opts = 'console=%s,115200n8'
-    kernel_addr = '0x40007000'
-    initrd_addr = '0x42000000'
-    load_addr = '0x40008000'
-    kernel_flavors = ['origen']
-    boot_script = 'boot.scr'
-    mmc_part_offset = 1
-    mmc_option = '0:2'
+    # TODO test
+    def __init__(self):
+        super(OrigenConfig, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.bootloader_flavor = 'origen'
+        self.initrd_addr = '0x42000000'
+        self.kernel_addr = '0x40007000'
+        self.kernel_flavors = ['origen']
+        self.load_addr = '0x40008000'
+        self.mmc_option = '0:2'
+        self.mmc_part_offset = 1
+        self.serial_tty = 'ttySAC2'
+        self._extra_serial_options = 'console=%s,115200n8'
 
 
 class OrigenQuadConfig(SamsungConfig):
-    bootloader_flavor = 'origen_quad'
-    serial_tty = 'ttySAC2'
-    _extra_serial_opts = 'console=%s,115200n8'
-    kernel_addr = '0x40007000'
-    initrd_addr = '0x42000000'
-    load_addr = '0x40008000'
-    kernel_flavors = ['origen_quad']
-    boot_script = 'boot.scr'
-    mmc_part_offset = 1
-    mmc_option = '0:2'
-    samsung_bl1_len = 48
-    samsung_bl2_start = 49
-    samsung_env_start = 1073
+    def __init__(self):
+        super(OrigenQuadConfig, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.bootloader_flavor = 'origen_quad'
+        self.initrd_addr = '0x42000000'
+        self.kernel_addr = '0x40007000'
+        self.kernel_flavors = ['origen_quad']
+        self.load_addr = '0x40008000'
+        self.mmc_option = '0:2'
+        self.mmc_part_offset = 1
+        self.samsung_bl1_len = 48
+        self.samsung_bl2_start = 49
+        self.samsung_env_start = 1073
+        self.serial_tty = 'ttySAC2'
+        self._extra_serial_options = 'console=%s,115200n8'
 
 
 class ArndaleConfig(SamsungConfig):
-    bootloader_flavor = 'arndale'
-    serial_tty = 'ttySAC2'
-    _extra_serial_opts = 'console=%s,115200n8'
-    kernel_addr = '0x40007000'
-    initrd_addr = '0x42000000'
-    dtb_addr = '0x41f00000'
-    load_addr = '0x40008000'
-    kernel_flavors = ['arndale']
-    boot_script = 'boot.scr'
-    mmc_part_offset = 1
-    mmc_option = '0:2'
-    samsung_bl1_start = 17
-    samsung_bl2_start = 49
-    samsung_env_start = 1073
+    def __init__(self):
+        super(ArndaleConfig, self).__init__()
+        self.boot_script = 'boot.scr'
+        self.bootloader_flavor = 'arndale'
+        self.dtb_addr = '0x41f00000'
+        self.initrd_addr = '0x42000000'
+        self.kernel_addr = '0x40007000'
+        self.kernel_flavors = ['arndale']
+        self.load_addr = '0x40008000'
+        self.mmc_option = '0:2'
+        self.mmc_part_offset = 1
+        self.samsung_bl1_start = 17
+        self.samsung_bl2_start = 49
+        self.samsung_env_start = 1073
+        self.serial_tty = 'ttySAC2'
+        self._extra_serial_options = 'console=%s,115200n8'
 
 
 class I386Config(BoardConfig):
-    # define serial
-    serial_tty = 'ttyS0'
-    _extra_serial_opts = 'console=tty0 console=%s,115200n8'
-    _live_serial_opts = 'serialtty=%s'
-
-    # define kernel image
-    kernel_flavors = ['generic', 'pae']
-
     # define bootloader
     BOOTLOADER_CMD = 'grub-install'
     BOOTLOADER_CFG_FILE = 'grub/grub.cfg'
@@ -1596,16 +1583,14 @@
             initrd /%s
     }"""
 
-    @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,
+    def __init__(self):
+        super(I386Config, self).__init__()
+        self.kernel_flavors = ['generic', 'pae']
+        self.serial_tty = 'ttyS0'
+        self._extra_serial_options = 'console=tty0 console=%s,115200n8'
+        self._live_serial_opts = 'serialtty=%s'
+
+    def _make_boot_files(self, boot_env, chroot_dir, boot_dir,
                          boot_device_or_file, k_img_data, i_img_data,
                          d_img_data):
         # copy image and init into boot partition
@@ -1618,13 +1603,13 @@
         img_loop = register_loopback(boot_device_or_file, 0, img_size)
 
         # install bootloader
-        cmd_runner.run([cls.BOOTLOADER_CMD, '--boot-directory=%s' % boot_dir,
+        cmd_runner.run([self.BOOTLOADER_CMD, '--boot-directory=%s' % boot_dir,
             '--modules', 'part_msdos', img_loop],
             as_root=True).wait()
 
         # generate loader config file
-        loader_config = cls.BOOTLOADER_CFG % (os.path.basename(k_img_data),
-            cls.extra_serial_opts, os.path.basename(i_img_data))
+        loader_config = self.BOOTLOADER_CFG % (os.path.basename(k_img_data),
+            self.extra_serial_options, os.path.basename(i_img_data))
 
         _, tmpfile = tempfile.mkstemp()
         atexit.register(os.unlink, tmpfile)
@@ -1632,42 +1617,59 @@
             fd.write(loader_config)
 
         cmd_runner.run(['cp', tmpfile, os.path.join(boot_dir,
-            cls.BOOTLOADER_CFG_FILE)], as_root=True).wait()
+            self.BOOTLOADER_CFG_FILE)], as_root=True).wait()
 
-    @classmethod
-    def _make_boot_files_v2(cls, boot_env, chroot_dir, boot_dir,
+    def _make_boot_files_v2(self, boot_env, chroot_dir, boot_dir,
                             boot_device_or_file, k_img_data, i_img_data,
                             d_img_data):
         # reuse hwpack v1 function
-        cls._make_boot_files(boot_env, chroot_dir, boot_dir,
-                             boot_device_or_file, k_img_data, i_img_data,
-                             d_img_data)
+        self._make_boot_files(boot_env, chroot_dir, boot_dir,
+                              boot_device_or_file, k_img_data, i_img_data,
+                              d_img_data)
+
+
+class BoardConfigException(Exception):
+    """General board config exception."""
 
 
 board_configs = {
     'arndale': ArndaleConfig,
     'beagle': BeagleConfig,
-    'igep': IgepConfig,
-    'panda': PandaConfig,
-    'vexpress': VexpressConfig,
-    'vexpress-a9': VexpressA9Config,
-    'fastmodel': FastModelConfig,
-    'ux500': Ux500Config,
-    'snowball_sd': SnowballSdConfig,
-    'snowball_emmc': SnowballEmmcConfig,
     'efikamx': EfikamxConfig,
     'efikasb': EfikasbConfig,
+    'fastmodel': FastModelConfig,
+    'i386': I386Config,
+    'igep': IgepConfig,
     'mx51evk': Mx51evkConfig,
     'mx53loco': Mx53LoCoConfig,
+    'mx6qsabrelite': BoardConfig,
+    'origen': OrigenConfig,
+    'origen_quad': OrigenQuadConfig,
     'overo': OveroConfig,
+    'panda': PandaConfig,
     'smdkv310': SMDKV310Config,
-    'origen': OrigenConfig,
-    'origen_quad': OrigenQuadConfig,
-    'mx6qsabrelite': BoardConfig,
-    'i386': I386Config,
+    'snowball_emmc': SnowballEmmcConfig,
+    'snowball_sd': SnowballSdConfig,
+    'ux500': Ux500Config,
+    'vexpress': VexpressConfig,
+    'vexpress-a9': VexpressA9Config,
     }
 
 
+def get_board_config(board):
+    """Get the board configuration for the specified board.
+
+    :param board: The name of the board to get the configuration of.
+    :type board: str
+    """
+    clazz = board_configs.get(board, None)
+    if clazz:
+        return clazz()
+    else:
+        raise BoardConfigException("Board name '%s' has no configuration "
+                                   "available." % board)
+
+
 def _dd(input_file, output_file, block_size=SECTOR_SIZE, count=None, seek=None,
         skip=None):
     """Wrapper around the dd command"""

=== modified file 'linaro_image_tools/media_create/tests/__init__.py'
--- linaro_image_tools/media_create/tests/__init__.py	2012-06-07 13:12:42 +0000
+++ linaro_image_tools/media_create/tests/__init__.py	2012-12-10 17:32:21 +0000
@@ -1,9 +1,28 @@
+# Copyright (C) 2010, 2011, 2012 Linaro
+#
+# This file is part of Linaro Image Tools.
+#
+# Linaro Image Tools is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Linaro Image Tools is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
 import unittest
 
 
 def test_suite():
-    module_names = ['linaro_image_tools.media_create.tests.test_media_create',
-                   ]
+    module_names = [
+        'linaro_image_tools.media_create.tests.test_media_create',
+        'linaro_image_tools.media_create.tests.test_android_boards',
+        ]
     loader = unittest.TestLoader()
     suite = loader.loadTestsFromNames(module_names)
     return suite

=== added file 'linaro_image_tools/media_create/tests/test_android_boards.py'
--- linaro_image_tools/media_create/tests/test_android_boards.py	1970-01-01 00:00:00 +0000
+++ linaro_image_tools/media_create/tests/test_android_boards.py	2013-01-03 13:55:33 +0000
@@ -0,0 +1,480 @@
+# Copyright (C) 2010, 2011 Linaro
+#
+# Author: Milo Casagrande <milo.casagrande@linaro.org>
+#
+# This file is part of Linaro Image Tools.
+#
+# Linaro Image Tools is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Linaro Image Tools is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from testtools import TestCase
+
+from linaro_image_tools.media_create.boards import (
+    BoardConfigException,
+    )
+
+from linaro_image_tools.media_create.android_boards import (
+    AndroidBeagleConfig,
+    get_board_config,
+    )
+
+from linaro_image_tools.testing import TestCaseWithFixtures
+from linaro_image_tools.tests.fixtures import CreateTempFileFixture
+
+
+class TestAndroidBoards(TestCase):
+    """Class to test small things in android_boards."""
+
+    def test_get_board_config(self):
+        instance = get_board_config('beagle')
+        self.assertIsInstance(instance, AndroidBeagleConfig)
+
+    def test_get_board_config_wrong(self):
+        self.assertRaises(BoardConfigException, get_board_config, 'notadevice')
+
+    def test_hwpack_not_exists(self):
+        instance = get_board_config('beagle')
+        self.assertRaises(BoardConfigException, instance.from_file, 'a_file')
+
+
+class TestAndroidBoardsHwpack(TestCaseWithFixtures):
+    """Class to test the new Android hwpack configuration file."""
+
+    # All the necessary Android hwpack fields for the tests.
+    hwpack_format = 'format: 3.0\n'
+    hwpack_dtb_name = 'dtb_name: %(dtb_name)s\n'
+    hwpack_fdt_high = "fdt_high: '%(fdt_high)s'\n"
+    hwpack_fat_size = 'fat_size: 16\n'
+    hwpack_android_args = 'android_specific_args: %(android_specific_args)s\n'
+    hwpack_extra_serial = 'extra_serial_options: %(extra_serial_options)s\n'
+    hwpack_extra_boot = ('extra_boot_args_options: '
+                         '%(extra_boot_args_options)s\n')
+    hwpack_bootloader_flavor = 'bootloader_flavor: %(bootloader_flavor)s\n'
+    hwpack_initrd_addr = 'initrd_addr: \'%(initrd_addr)s\'\n'
+    hwpack_initrd_high = 'initrd_high: \'%(initrd_high)s\'\n'
+    hwpack_kernel_addr = 'kernel_addr: \'%(kernel_addr)s\'\n'
+    hwpack_load_addr = 'load_addr: \'%(load_addr)s\'\n'
+    hwpack_dtb_addr = 'dtb_addr: \'%(dtb_addr)s\'\n'
+    hwpack_boot_script = 'boot_script: %(boot_script)s\n'
+    hwpack_mmc_option = 'mmc_option: \'%(mmc_option)s\'\n'
+
+    # Some defaults YAML-like strings to use for the tests.
+    android_hwpack_base = (hwpack_format + hwpack_dtb_name)
+    android_hwpack_simple = (android_hwpack_base + hwpack_fdt_high +
+                             hwpack_fat_size)
+    android_hwpack_android_args = (android_hwpack_base + hwpack_android_args)
+    android_hwpack_extra_serial = (android_hwpack_base + hwpack_extra_serial)
+    android_hwpack_extra_boot = (android_hwpack_base + hwpack_extra_boot)
+
+    android_hwpack_panda = (
+        hwpack_format + hwpack_android_args + hwpack_bootloader_flavor +
+        hwpack_dtb_addr + hwpack_dtb_name + hwpack_extra_boot +
+        hwpack_extra_serial
+        )
+
+    android_hwpack_mx6 = (
+        android_hwpack_panda + hwpack_initrd_addr + hwpack_kernel_addr +
+        hwpack_load_addr
+        )
+
+    android_hwpack_snowball_sd = (
+        hwpack_android_args + hwpack_boot_script + hwpack_dtb_addr +
+        hwpack_dtb_name + hwpack_extra_boot + hwpack_extra_serial +
+        hwpack_fdt_high + hwpack_format + hwpack_initrd_addr
+        )
+
+    android_hwpack_snowball_emmc = (
+        android_hwpack_snowball_sd + hwpack_initrd_high + hwpack_mmc_option)
+
+    def setUp(self):
+        super(TestAndroidBoardsHwpack, self).setUp()
+        # Pick a default board.
+        self.config = get_board_config('beagle')
+
+    def _get_tmp_file_name(self, content=None):
+        name = self.useFixture(CreateTempFileFixture(content)).get_file_name()
+        return name
+
+    def assertBootEnv(self, expected, config=None, board='beagle'):
+        """Helper function the boot env parameters.
+
+        :param config: The string containing the YAML configuration.
+        :type str
+        :param expected: The expected configuration.
+        :type dict
+        :param board: The name of the board to test. Defaults to beagle.
+        :type str
+        """
+        board_conf = get_board_config(board)
+        if config:
+            name = self.useFixture(CreateTempFileFixture(config)).\
+                get_file_name()
+            board_conf.from_file(name)
+        self.assertEqual(expected, board_conf._get_boot_env(consoles=[]))
+
+    def test_read_from_file(self):
+        values = {'fdt_high': '0xFFFFFFFF', 'dtb_name': 'a_name'}
+        expected = {'format': 3.0, 'dtb_name': 'a_name',
+                    'fdt_high': '0xFFFFFFFF', 'fat_size': 16}
+        yaml_conf = self.android_hwpack_simple % values
+        name = self._get_tmp_file_name(yaml_conf)
+        conf = self.config.from_file(name)
+        self.assertEqual(expected, conf)
+
+    def test_android_specific_args(self):
+        """The field android_specific_args should be a concatenated string."""
+        values = {'android_specific_args': ['init=/init',
+                                            'androidboot.console=ttyO2'],
+                  'dtb_name': 'a_name'}
+        yaml_conf = self.android_hwpack_android_args % values
+        name = self._get_tmp_file_name(yaml_conf)
+        self.config.from_file(name)
+        expected = 'init=/init androidboot.console=ttyO2'
+        self.assertEqual(expected, self.config.android_specific_args)
+
+    def test_extra_serial_options(self):
+        """The field extra_serial_options should be a concatenated string."""
+        values = {'dtb_name': 'a_name',
+                  'extra_serial_options': ['console=tty0',
+                                           'console=ttyO2,115200n8']}
+        yaml_conf = self.android_hwpack_extra_serial % values
+        name = self._get_tmp_file_name(yaml_conf)
+        self.config.from_file(name)
+        expected = 'console=tty0 console=ttyO2,115200n8'
+        self.assertEqual(expected, self.config.extra_serial_options)
+
+    def test_extra_boot_args_options(self):
+        """The field extra_boot_args_options should be a concatenated string.
+        Testing presence of a field defined in the parent class."""
+        values = {'dtb_name': 'a_name',
+                  'extra_boot_args_options': ['earlyprintk', 'mem=128M@0',
+                                              'mali.mali_mem=64M@128M']
+            }
+        yaml_conf = self.android_hwpack_extra_boot % values
+        name = self._get_tmp_file_name(yaml_conf)
+        self.config.from_file(name)
+        expected = 'earlyprintk mem=128M@0 mali.mali_mem=64M@128M'
+        self.assertEqual(expected, self.config.extra_boot_args_options)
+
+    def test_android_mx6(self):
+        values = {
+            "android_specific_args": ["init=/init", "androidboot.console=%s"],
+            "bootloader_flavor": "mx6qsabrelite",
+            "dtb_addr": '0x11ff0000',
+            "dtb_name": "board.dtb",
+            "extra_boot_args_options": ["earlyprintk", "rootdelay=1",
+                                        "fixrtc", "nocompcache",
+                                        "di1_primary", "tve"],
+            "extra_serial_options": ["console=%s,115200n8"],
+            "initrd_addr": '0x12000000',
+            "kernel_addr": '0x10000000',
+            "load_addr": '0x10008000',
+            }
+        expected = {
+            'bootargs': 'console=ttymxc0,115200n8 '
+                        'rootwait ro earlyprintk rootdelay=1 fixrtc '
+                        'nocompcache di1_primary tve init=/init '
+                        'androidboot.console=ttymxc0',
+            'bootcmd': 'fatload mmc 0:2 0x10000000 uImage; '
+                       'fatload mmc 0:2 0x12000000 uInitrd; '
+                       'fatload mmc 0:2 0x11ff0000 board.dtb; '
+                       'bootm 0x10000000 0x12000000 0x11ff0000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        config = self.android_hwpack_mx6 % values
+        self.assertBootEnv(expected, config=config, board='mx6qsabrelite')
+
+    def test_android_mx6_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=ttymxc0,115200n8 '
+                        'rootwait ro earlyprintk rootdelay=1 fixrtc '
+                        'nocompcache di1_primary tve init=/init '
+                        'androidboot.console=ttymxc0',
+            'bootcmd': 'fatload mmc 0:2 0x10000000 uImage; '
+                       'fatload mmc 0:2 0x12000000 uInitrd; '
+                       'fatload mmc 0:2 0x11ff0000 board.dtb; '
+                       'bootm 0x10000000 0x12000000 0x11ff0000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        self.assertBootEnv(expected, board='mx6qsabrelite')
+
+    def test_panda(self):
+        values = {
+            "android_specific_args": ["init=/init",
+                                      "androidboot.console=ttyO2"],
+            "bootloader_flavor": "omap4_panda",
+            "dtb_addr": '0x815f0000',
+            "dtb_name": "board.dtb",
+            "extra_boot_args_options": ["earlyprintk", "fixrtc",
+                                        "nocompcache", "vram=48M",
+                                        "omapfb.vram=0:24M,1:24M",
+                                        "mem=456M@0x80000000",
+                                        "mem=512M@0xA0000000"],
+            "extra_serial_options": ["console=ttyO2,115200n8"],
+            }
+        expected = {
+            'bootargs': 'console=ttyO2,115200n8 '
+                        'rootwait ro earlyprintk fixrtc '
+                        'nocompcache vram=48M omapfb.vram=0:24M,1:24M '
+                        'mem=456M@0x80000000 mem=512M@0xA0000000 '
+                        'init=/init androidboot.console=ttyO2',
+            'bootcmd': 'fatload mmc 0:1 0x80200000 uImage; '
+                       'fatload mmc 0:1 0x81600000 uInitrd; '
+                       'fatload mmc 0:1 0x815f0000 board.dtb; '
+                       'bootm 0x80200000 0x81600000 0x815f0000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        config = self.android_hwpack_panda % values
+        self.assertBootEnv(expected, config=config, board='panda')
+
+    def test_panda_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=ttyO2,115200n8 '
+                        'rootwait ro earlyprintk fixrtc '
+                        'nocompcache vram=48M omapfb.vram=0:24M,1:24M '
+                        'mem=456M@0x80000000 mem=512M@0xA0000000 '
+                        'init=/init androidboot.console=ttyO2',
+            'bootcmd': 'fatload mmc 0:1 0x80200000 uImage; '
+                       'fatload mmc 0:1 0x81600000 uInitrd; '
+                       'fatload mmc 0:1 0x815f0000 board.dtb; '
+                       'bootm 0x80200000 0x81600000 0x815f0000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        self.assertBootEnv(expected, board='panda')
+
+    def test_android_snowball_sd(self):
+        values = {
+            "android_specific_args": ["init=/init",
+                                      "androidboot.console=ttyAMA2"],
+            "boot_script": "boot.scr",
+            "dtb_addr": '0x8000000',
+            "dtb_name": "board.dtb",
+            "extra_boot_args_options": ["earlyprintk", "mem=128M@0",
+                                        "mali.mali_mem=64M@128M",
+                                        "hwmem=168M@192M", "mem=22M@360M",
+                                        "mem_issw=1M@383M", "mem=640M@384M",
+                                        "vmalloc=500M"],
+            "extra_serial_options": ["console=ttyAMA2,115200n8"],
+            "fdt_high": '0x05000000',
+            "initrd_addr": '0x05000000',
+            "initrd_high": '0x06000000',
+            }
+        expected = {
+            'bootargs': 'console=ttyAMA2,115200n8 '
+                        'rootwait ro earlyprintk '
+                        'mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
+                        'mem=22M@360M mem_issw=1M@383M mem=640M@384M '
+                        'vmalloc=500M init=/init androidboot.console=ttyAMA2',
+            'bootcmd': 'fatload mmc 1:1 0x00100000 uImage; '
+                       'fatload mmc 1:1 0x05000000 uInitrd; '
+                       'fatload mmc 1:1 0x8000000 board.dtb; '
+                       'bootm 0x00100000 0x05000000 0x8000000',
+            'fdt_high': '0x05000000',
+            'initrd_high': '0x06000000'}
+        config = self.android_hwpack_snowball_sd % values
+        self.assertBootEnv(expected, config=config, board='snowball_sd')
+
+    def test_android_snowball_sd_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=ttyAMA2,115200n8 '
+                        'rootwait ro earlyprintk '
+                        'mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
+                        'mem=22M@360M mem_issw=1M@383M mem=640M@384M '
+                        'vmalloc=500M init=/init androidboot.console=ttyAMA2',
+            'bootcmd': 'fatload mmc 1:1 0x00100000 uImage; '
+                       'fatload mmc 1:1 0x05000000 uInitrd; '
+                       'fatload mmc 1:1 0x8000000 board.dtb; '
+                       'bootm 0x00100000 0x05000000 0x8000000',
+            'fdt_high': '0x05000000',
+            'initrd_high': '0x06000000'}
+        self.assertBootEnv(expected, board='snowball_sd')
+
+    def test_android_snowball_emmc(self):
+        values = {
+            "android_specific_args": ["init=/init",
+                                      "androidboot.console=ttyAMA2"],
+            "boot_script": "boot.scr",
+            "dtb_addr": '0x8000000',
+            "dtb_name": "board.dtb",
+            "extra_boot_args_options": ["earlyprintk", "mem=128M@0",
+                                        "mali.mali_mem=64M@128M",
+                                        "hwmem=168M@192M", "mem=22M@360M",
+                                        "mem_issw=1M@383M", "mem=640M@384M",
+                                        "vmalloc=500M"],
+            "extra_serial_options": ["console=ttyAMA2,115200n8"],
+            "fdt_high": '0x05000000',
+            "initrd_addr": '0x05000000',
+            "initrd_high": '0x06000000',
+            "mmc_option": '0:2'
+            }
+        expected = {
+            'bootargs': 'console=ttyAMA2,115200n8 '
+                        'rootwait ro earlyprintk '
+                        'mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
+                        'mem=22M@360M mem_issw=1M@383M mem=640M@384M '
+                        'vmalloc=500M init=/init androidboot.console=ttyAMA2',
+            'bootcmd': 'fatload mmc 0:2 0x00100000 uImage; '
+                       'fatload mmc 0:2 0x05000000 uInitrd; '
+                       'fatload mmc 0:2 0x8000000 board.dtb; '
+                       'bootm 0x00100000 0x05000000 0x8000000',
+            'fdt_high': '0x05000000',
+            'initrd_high': '0x06000000'}
+        config = self.android_hwpack_snowball_emmc % values
+        self.assertBootEnv(expected, config, board='snowball_emmc')
+
+    def test_android_snowball_emmc_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=ttyAMA2,115200n8 '
+                        'rootwait ro earlyprintk '
+                        'mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
+                        'mem=22M@360M mem_issw=1M@383M mem=640M@384M '
+                        'vmalloc=500M init=/init androidboot.console=ttyAMA2',
+            'bootcmd': 'fatload mmc 0:2 0x00100000 uImage; '
+                       'fatload mmc 0:2 0x05000000 uInitrd; '
+                       'fatload mmc 0:2 0x8000000 board.dtb; '
+                       'bootm 0x00100000 0x05000000 0x8000000',
+            'fdt_high': '0x05000000',
+            'initrd_high': '0x06000000'}
+        self.assertBootEnv(expected, board='snowball_emmc')
+
+    def test_android_origen(self):
+        values = {
+        "extra_serial_options": ["console=tty0", "console=ttySAC2,115200n8"],
+        "android_specific_args": ["init=/init", "androidboot.console=ttySAC2"]
+        }
+        expected = {
+            'bootargs': 'console=tty0 console=ttySAC2,115200n8 '
+                        'rootwait ro init=/init androidboot.console=ttySAC2',
+            'bootcmd': 'fatload mmc 0:2 0x40007000 uImage; '
+                       'fatload mmc 0:2 0x42000000 uInitrd; '
+                       'bootm 0x40007000 0x42000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        config = ((self.hwpack_format + self.hwpack_extra_serial +
+                   self.hwpack_android_args) % values)
+        self.assertBootEnv(expected, config=config, board='origen')
+
+    def test_android_origen_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=tty0 console=ttySAC2,115200n8 '
+                        'rootwait ro init=/init androidboot.console=ttySAC2',
+            'bootcmd': 'fatload mmc 0:2 0x40007000 uImage; '
+                       'fatload mmc 0:2 0x42000000 uInitrd; '
+                       'bootm 0x40007000 0x42000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        self.assertBootEnv(expected, board='origen')
+
+    def test_android_origen_quad(self):
+        values = {
+            "extra_serial_options": ["console=tty0",
+                                     "console=ttySAC2,115200n8"],
+            "android_specific_args": ["init=/init",
+                                      "androidboot.console=ttySAC2"]
+        }
+        expected = {
+            'bootargs': 'console=tty0 console=ttySAC2,115200n8 '
+                        'rootwait ro init=/init androidboot.console=ttySAC2',
+            'bootcmd': 'fatload mmc 0:2 0x40007000 uImage; '
+                       'fatload mmc 0:2 0x42000000 uInitrd; '
+                       'bootm 0x40007000 0x42000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        config = ((self.hwpack_format + self.hwpack_extra_serial +
+                   self.hwpack_android_args) % values)
+        self.assertBootEnv(expected, config=config, board='origen_quad')
+
+    def test_android_origen_quad_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=tty0 console=ttySAC2,115200n8 '
+                        'rootwait ro init=/init androidboot.console=ttySAC2',
+            'bootcmd': 'fatload mmc 0:2 0x40007000 uImage; '
+                       'fatload mmc 0:2 0x42000000 uInitrd; '
+                       'bootm 0x40007000 0x42000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        self.assertBootEnv(expected, board='origen_quad')
+
+    def test_android_vexpress(self):
+        values = {
+            "extra_serial_options": ["console=tty0",
+                                     "console=ttyAMA0,38400n8"],
+            "android_specific_args": ["init=/init",
+                                      "androidboot.console=ttyAMA0"]
+        }
+        expected = {
+            'bootargs': 'console=tty0 console=ttyAMA0,38400n8 '
+                        'rootwait ro init=/init androidboot.console=ttyAMA0',
+            'bootcmd': 'fatload mmc 0:1 0x60000000 uImage; '
+                       'fatload mmc 0:1 0x62000000 uInitrd; '
+                       'bootm 0x60000000 0x62000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        config = ((self.hwpack_format + self.hwpack_extra_serial +
+                   self.hwpack_android_args) % values)
+        self.assertBootEnv(expected, config=config, board='vexpress')
+
+    def test_android_vexpress_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=tty0 console=ttyAMA0,38400n8 '
+                        'rootwait ro init=/init androidboot.console=ttyAMA0',
+            'bootcmd': 'fatload mmc 0:1 0x60000000 uImage; '
+                       'fatload mmc 0:1 0x62000000 uInitrd; '
+                       'bootm 0x60000000 0x62000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        self.assertBootEnv(expected, board='vexpress')
+
+    def test_android_mx5(self):
+        values = {
+            "extra_boot_args_options": ["earlyprintk", "rootdelay=1",
+                                        "fixrtc", "nocompcache",
+                                        "di1_primary", "tve"],
+            "extra_serial_options": ["console=%s,115200n8"],
+            "android_specific_args": ["init=/init", "androidboot.console=%s"]
+        }
+        expected = {
+            'bootargs': 'console=ttymxc0,115200n8 '
+                        'rootwait ro earlyprintk rootdelay=1 fixrtc '
+                        'nocompcache di1_primary tve init=/init '
+                        'androidboot.console=ttymxc0',
+            'bootcmd': 'fatload mmc 0:2 0x70000000 uImage; '
+                       'fatload mmc 0:2 0x72000000 uInitrd; '
+                       'bootm 0x70000000 0x72000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        config = ((self.hwpack_format + self.hwpack_extra_boot +
+                   self.hwpack_extra_serial + self.hwpack_android_args) %
+                   values)
+        self.assertBootEnv(expected, config=config, board='mx53loco')
+
+    def test_android_mx5_old(self):
+        # Old test: use the values from the class, instead of passing them.
+        expected = {
+            'bootargs': 'console=ttymxc0,115200n8 '
+                        'rootwait ro earlyprintk rootdelay=1 fixrtc '
+                        'nocompcache di1_primary tve init=/init '
+                        'androidboot.console=ttymxc0',
+            'bootcmd': 'fatload mmc 0:2 0x70000000 uImage; '
+                       'fatload mmc 0:2 0x72000000 uInitrd; '
+                       'bootm 0x70000000 0x72000000',
+            'fdt_high': '0xffffffff',
+            'initrd_high': '0xffffffff'}
+        self.assertBootEnv(expected, board='mx53loco')

=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
--- linaro_image_tools/media_create/tests/test_media_create.py	2012-12-23 12:49:02 +0000
+++ linaro_image_tools/media_create/tests/test_media_create.py	2012-12-27 14:58:24 +0000
@@ -32,6 +32,7 @@
 import tarfile
 import dbus
 
+from mock import MagicMock
 from StringIO import StringIO
 from testtools import TestCase
 
@@ -50,7 +51,6 @@
     SECTOR_SIZE,
     align_up,
     align_partition,
-    board_configs,
     get_plain_boot_script_contents,
     make_flashable_env,
     install_mx5_boot_loader,
@@ -63,10 +63,10 @@
     _get_mlo_file,
     _run_mkimage,
     BoardConfig,
+    get_board_config,
     )
 from linaro_image_tools.media_create.android_boards import (
     AndroidSnowballEmmcConfig,
-    android_board_configs,
     )
 from linaro_image_tools.media_create.chroot_utils import (
     copy_file,
@@ -203,7 +203,7 @@
         return tarball
 
     def test_get_format_1(self):
-        data = '1.0'
+        data = HardwarepackHandler.FORMAT_1
         format = "%s\n" % data
         tarball = self.add_to_tarball(
             [('FORMAT', format), ('metadata', self.metadata)])
@@ -230,8 +230,8 @@
             self.assertRaises(AssertionError, hp.get_format)
 
     def test_mixed_formats(self):
-        format1 = "%s\n" % '1.0'
-        format2 = "%s\n" % '2.0'
+        format1 = "%s\n" % HardwarepackHandler.FORMAT_1
+        format2 = "%s\n" % HardwarepackHandler.FORMAT_2
         tarball1 = self.add_to_tarball(
             [('FORMAT', format1), ('metadata', self.metadata)],
             tarball=self.tarball_fixture.get_tarball())
@@ -247,8 +247,8 @@
             self.assertEquals(hp.get_format(), '1.0and2.0')
 
     def test_identical_formats_ok(self):
-        format1 = "%s\n" % '2.0'
-        format2 = "%s\n" % '2.0'
+        format1 = "%s\n" % HardwarepackHandler.FORMAT_2
+        format2 = "%s\n" % HardwarepackHandler.FORMAT_2
         tarball1 = self.add_to_tarball(
             [('FORMAT', format1), ('metadata', self.metadata)],
             tarball=self.tarball_fixture.get_tarball())
@@ -427,10 +427,9 @@
                 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)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(None, board_conf.kernel_addr)
 
     def test_sets_kernel_addr(self):
         self.useFixture(MockSomethingFixture(
@@ -442,10 +441,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.kernel_addr)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.kernel_addr)
 
     def test_sets_initrd_addr(self):
         self.useFixture(MockSomethingFixture(
@@ -457,10 +455,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.initrd_addr)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.initrd_addr)
 
     def test_sets_load_addr(self):
         self.useFixture(MockSomethingFixture(
@@ -472,10 +469,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.load_addr)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.load_addr)
 
     def test_sets_serial_tty(self):
         self.useFixture(MockSomethingFixture(
@@ -487,10 +483,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.serial_tty)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.serial_tty)
 
     def test_sets_wired_interfaces(self):
         self.useFixture(MockSomethingFixture(
@@ -502,10 +497,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.wired_interfaces)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.wired_interfaces)
 
     def test_sets_wireless_interfaces(self):
         self.useFixture(MockSomethingFixture(
@@ -517,10 +511,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.wireless_interfaces)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.wireless_interfaces)
 
     def test_sets_mmc_id(self):
         self.useFixture(MockSomethingFixture(
@@ -532,12 +525,11 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.mmc_option)
-        self.assertEquals(0, config.mmc_device_id)
-        self.assertEquals(0, config.mmc_part_offset)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.mmc_option)
+        self.assertEquals(0, board_conf.mmc_device_id)
+        self.assertEquals(0, board_conf.mmc_part_offset)
 
     def test_sets_boot_min_size(self):
         self.useFixture(MockSomethingFixture(
@@ -551,10 +543,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(expected, config.BOOT_MIN_SIZE_S)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(expected, board_conf.BOOT_MIN_SIZE_S)
 
     def test_sets_root_min_size(self):
         self.useFixture(MockSomethingFixture(
@@ -568,10 +559,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(expected, config.ROOT_MIN_SIZE_S)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(expected, board_conf.ROOT_MIN_SIZE_S)
 
     def test_sets_loader_min_size(self):
         self.useFixture(MockSomethingFixture(
@@ -585,10 +575,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(expected, config.LOADER_MIN_SIZE_S)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(expected, board_conf.LOADER_MIN_SIZE_S)
 
     def test_sets_partition_layout_32(self):
         self.useFixture(MockSomethingFixture(
@@ -600,10 +589,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(32, config.fat_size)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(32, board_conf.fat_size)
 
     def test_sets_partition_layout_16(self):
         self.useFixture(MockSomethingFixture(
@@ -615,10 +603,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(16, config.fat_size)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(16, board_conf.fat_size)
 
     def test_sets_partition_layout_raises(self):
         self.useFixture(MockSomethingFixture(
@@ -630,10 +617,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
+        board_conf = BoardConfig()
         self.assertRaises(
-            AssertionError, config.set_metadata, 'ahwpack.tar.gz')
+            AssertionError, board_conf.set_metadata, 'ahwpack.tar.gz')
 
     def test_sets_copy_files(self):
         self.useFixture(MockSomethingFixture(
@@ -647,10 +633,9 @@
             field_to_test: data_to_set,
             }
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata('ahwpack.tar.gz')
-        self.assertEquals(data_to_set, config.bootloader_copy_files)
+        board_conf = BoardConfig()
+        board_conf.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(data_to_set, board_conf.bootloader_copy_files)
 
 
 class TestGetMLOFile(TestCaseWithFixtures):
@@ -697,7 +682,10 @@
 
 
 class TestGetSMDKSPL(TestCaseWithFixtures):
-    config = boards.SMDKV310Config
+    def setUp(self):
+            super(TestGetSMDKSPL, self).setUp()
+            self.config = boards.SMDKV310Config()
+            self.config.hwpack_format = HardwarepackHandler.FORMAT_1
 
     def test_no_file_present(self):
         tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
@@ -729,7 +717,10 @@
 
 
 class TestGetSMDKUboot(TestCaseWithFixtures):
-    config = boards.SMDKV310Config
+    def setUp(self):
+        super(TestGetSMDKUboot, self).setUp()
+        self.config = boards.SMDKV310Config()
+        self.config.hwpack_format = HardwarepackHandler.FORMAT_1
 
     def test_uses_uboot_flavour(self):
         chroot_dir = "chroot"
@@ -740,7 +731,10 @@
 
 
 class TestGetOrigenSPL(TestCaseWithFixtures):
-    config = boards.OrigenConfig
+    def setUp(self):
+        super(TestGetOrigenSPL, self).setUp()
+        self.config = boards.OrigenConfig()
+        self.config.hwpack_format = HardwarepackHandler.FORMAT_1
 
     def test_no_file_present(self):
         tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
@@ -756,11 +750,17 @@
 
 
 class TestGetOrigenUboot(TestGetSMDKUboot):
-    config = boards.OrigenConfig
+    def setUp(self):
+        super(TestGetOrigenUboot, self).setUp()
+        self.config = boards.OrigenConfig()
+        self.config.hwpack_format = HardwarepackHandler.FORMAT_1
 
 
 class TestGetOrigenQuadSPL(TestCaseWithFixtures):
-    config = boards.OrigenQuadConfig
+    def setUp(self):
+        super(TestGetOrigenQuadSPL, self).setUp()
+        self.config = boards.OrigenQuadConfig()
+        self.config.hwpack_format = HardwarepackHandler.FORMAT_1
 
     def test_no_file_present(self):
         tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
@@ -776,11 +776,17 @@
 
 
 class TestGetOrigenQuadUboot(TestGetSMDKUboot):
-    config = boards.OrigenQuadConfig
+    def setUp(self):
+        super(TestGetOrigenQuadUboot, self).setUp()
+        self.config = boards.OrigenQuadConfig()
+        self.config.hwpack_format = HardwarepackHandler.FORMAT_1
 
 
 class TestGetArndaleSPL(TestCaseWithFixtures):
-    config = boards.ArndaleConfig
+    def setUp(self):
+        super(TestGetArndaleSPL, self).setUp()
+        self.config = boards.ArndaleConfig()
+        self.config.hwpack_format = HardwarepackHandler.FORMAT_1
 
     def test_no_file_present(self):
         tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
@@ -818,6 +824,7 @@
                  '\x05\x00\x00\x00' '\x05\x00\x00\x00' \
                  'hello' + zero + '\x00\x00\x00'
         self.expected = line1 + line2 + line3
+        self.board_conf = boards.SnowballEmmcConfig()
 
     def create_files_structure(self, src_data):
         ''' Creates the data structure that the tested function
@@ -841,7 +848,7 @@
         files = self.create_files_structure(correct_data)
         filename = os.path.join(self.tempdir, 'toc')
         with open(filename, 'w') as f:
-            boards.SnowballEmmcConfig.create_toc(f, files)
+            self.board_conf.create_toc(f, files)
         with open(filename, 'r') as f:
             actual = f.read()
         self.assertEquals(96, len(actual))
@@ -856,7 +863,7 @@
         files = self.create_files_structure(illegal_name_data)
         with open(os.path.join(self.tempdir, 'toc'), 'w') as f:
             self.assertRaises(AssertionError,
-                              boards.SnowballEmmcConfig.create_toc,
+                              self.board_conf.create_toc,
                               f, files)
 
     def test_create_toc_error_negative_unsigned(self):
@@ -866,7 +873,7 @@
         files = self.create_files_structure(illegal_unsigned_data)
         with open(os.path.join(self.tempdir, 'toc'), 'w') as f:
             self.assertRaises(struct.error,
-                              boards.SnowballEmmcConfig.create_toc,
+                              self.board_conf.create_toc,
                               f, files)
 
 
@@ -885,6 +892,8 @@
             os.makedirs(self.temp_bootdir_path)
         if not os.path.exists(self.temp_configdir_path):
             os.makedirs(self.temp_configdir_path)
+        self.snowball_config = get_board_config('snowball_emmc')
+        self.snowball_config.hwpack_format = HardwarepackHandler.FORMAT_1
 
     def setupFiles(self):
         return self.create_test_files(self.temp_bootdir_path)
@@ -910,7 +919,7 @@
                     ('UBOOT_ENV', 'u-boot-env.bin', 0, 0x00C1F000, '10')]
         # Create a config file
         cfg_file = os.path.join(
-            path, boards.SnowballEmmcConfig.snowball_startup_files_config)
+            path, self.snowball_config.snowball_startup_files_config)
         with open(cfg_file, 'w') as f:
             for line in src_data:
                 # Write comments, so we test that the parser can read them
@@ -926,8 +935,8 @@
                 f.write(line[0])
         #define the expected values read from the config file
         expected = []
-        ofs = [boards.SnowballEmmcConfig.TOC_SIZE,
-               boards.SnowballEmmcConfig.TOC_SIZE + len('ISSW'), 0x160000,
+        ofs = [self.snowball_config.TOC_SIZE,
+               self.snowball_config.TOC_SIZE + len('ISSW'), 0x160000,
                0x170000, 0xBA0000, 0xC1F000]
         size = [len('ISSW'), len('X-LOADER'), len('MEM_INIT'), \
                 len('PWR_MGT'), len('NORMAL'), len('UBOOT_ENV')]
@@ -946,13 +955,13 @@
     def test_get_file_info_relative_path(self):
         # Create a config file
         cfg_file = os.path.join(self.temp_bootdir_path,
-                      boards.SnowballEmmcConfig.snowball_startup_files_config)
+                      self.snowball_config.snowball_startup_files_config)
         uboot_file = 'u-boot.bin'
         with open(cfg_file, 'w') as f:
                 f.write('%s %s %i %#x %s\n' % ('NORMAL', uboot_file, 0,
                                                0xBA0000, '9'))
         with open(os.path.join(self.temp_bootdir_path, uboot_file), 'w') as f:
-            file_info = boards.SnowballEmmcConfig.get_file_info(
+            file_info = self.snowball_config.get_file_info(
                 self.tempdir, self.temp_bootdir_path)
         self.assertEquals(file_info[0]['filename'],
                           os.path.join(self.temp_bootdir_path, uboot_file))
@@ -960,7 +969,7 @@
     def test_get_file_info_abs_path(self):
         # Create a config file
         cfg_file = os.path.join(self.temp_bootdir_path,
-                      boards.SnowballEmmcConfig.snowball_startup_files_config)
+                      self.snowball_config.snowball_startup_files_config)
         uboot_dir = tempfile.mkdtemp(dir=self.tempdir)
         uboot_file = os.path.join(uboot_dir, 'u-boot.bin')
         uboot_relative_file = uboot_file.replace(self.tempdir, '')
@@ -968,19 +977,19 @@
                 f.write('%s %s %i %#x %s\n' % (
                         'NORMAL', uboot_relative_file, 0, 0xBA0000, '9'))
         with open(uboot_file, 'w') as f:
-            file_info = boards.SnowballEmmcConfig.get_file_info(
+            file_info = self.snowball_config.get_file_info(
                 self.tempdir, self.temp_bootdir_path)
         self.assertEquals(file_info[0]['filename'], uboot_file)
 
     def test_get_file_info_raises(self):
         # Create a config file
         cfg_file = os.path.join(self.temp_bootdir_path,
-                      boards.SnowballEmmcConfig.snowball_startup_files_config)
+                      self.snowball_config.snowball_startup_files_config)
         with open(cfg_file, 'w') as f:
                 f.write('%s %s %i %#x %s\n' % ('NORMAL', 'u-boot.bin', 0,
                                                0xBA0000, '9'))
         self.assertRaises(
-            AssertionError, boards.SnowballEmmcConfig.get_file_info,
+            AssertionError, self.snowball_config.get_file_info,
             self.tempdir, self.temp_bootdir_path)
 
     def test_file_name_size(self):
@@ -988,28 +997,28 @@
         _, toc_filename = tempfile.mkstemp()
         atexit.register(os.unlink, toc_filename)
         filedata = 'X'
-        bytes = boards.SnowballEmmcConfig.TOC_SIZE + 1
+        bytes = self.snowball_config.TOC_SIZE + 1
         tmpfile = open(toc_filename, 'wb')
         for n in xrange(bytes):
             tmpfile.write(filedata)
         tmpfile.close()
         files = self.setupFiles()
         self.assertRaises(AssertionError,
-            boards.SnowballEmmcConfig.install_snowball_boot_loader,
+            self.snowball_config.install_snowball_boot_loader,
             toc_filename, files, "boot_device_or_file",
-            boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S)
+            self.snowball_config.SNOWBALL_LOADER_START_S)
 
     def test_install_snowball_boot_loader_toc_dont_delete(self):
         fixture = self.useFixture(MockCmdRunnerPopenFixture())
         toc_filename = self.createTempFileAsFixture()
         files = self.setupFiles()
-        boards.SnowballEmmcConfig.install_snowball_boot_loader(toc_filename,
+        self.snowball_config.install_snowball_boot_loader(toc_filename,
             files, "boot_device_or_file",
-            boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S)
+            self.snowball_config.SNOWBALL_LOADER_START_S)
         expected = [
             '%s dd if=%s of=boot_device_or_file bs=512 conv=notrunc' \
             ' seek=%s' % (sudo_args, toc_filename,
-            boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S),
+            self.snowball_config.SNOWBALL_LOADER_START_S),
             '%s dd if=%s/boot_image_issw.bin of=boot_device_or_file bs=512' \
             ' conv=notrunc seek=257' % (sudo_args, self.temp_bootdir_path),
             '%s dd if=%s/boot_image_x-loader.bin of=boot_device_or_file' \
@@ -1030,13 +1039,13 @@
         fixture = self.useFixture(MockCmdRunnerPopenFixture())
         toc_filename = self.createTempFileAsFixture()
         files = self.setupFiles()
-        boards.SnowballEmmcConfig.install_snowball_boot_loader(toc_filename,
+        self.snowball_config.install_snowball_boot_loader(toc_filename,
             files, "boot_device_or_file",
-            boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S, True)
+            self.snowball_config.SNOWBALL_LOADER_START_S, True)
         expected = [
             '%s dd if=%s of=boot_device_or_file bs=512 conv=notrunc' \
             ' seek=%s' % (sudo_args, toc_filename,
-            boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S),
+            self.snowball_config.SNOWBALL_LOADER_START_S),
             '%s dd if=%s/boot_image_issw.bin of=boot_device_or_file bs=512' \
             ' conv=notrunc seek=257' % (sudo_args, self.temp_bootdir_path),
             '%s rm %s/boot_image_issw.bin' % (sudo_args,
@@ -1066,13 +1075,14 @@
         fixture = self.useFixture(MockCmdRunnerPopenFixture())
         toc_filename = self.createTempFileAsFixture()
         files = self.setupFiles()
-        AndroidSnowballEmmcConfig.install_snowball_boot_loader(
+        board_conf = AndroidSnowballEmmcConfig()
+        board_conf.install_snowball_boot_loader(
             toc_filename, files, "boot_device_or_file",
-            AndroidSnowballEmmcConfig.SNOWBALL_LOADER_START_S)
+            board_conf.SNOWBALL_LOADER_START_S)
         expected = [
             '%s dd if=%s of=boot_device_or_file bs=512 conv=notrunc' \
             ' seek=%s' % (sudo_args, toc_filename,
-            AndroidSnowballEmmcConfig.SNOWBALL_LOADER_START_S),
+            board_conf.SNOWBALL_LOADER_START_S),
             '%s dd if=%s/boot_image_issw.bin of=boot_device_or_file bs=512' \
             ' conv=notrunc seek=257' % (sudo_args, self.temp_bootdir_path),
             '%s dd if=%s/boot_image_x-loader.bin of=boot_device_or_file' \
@@ -1097,11 +1107,11 @@
         k_img_file = os.path.join(self.tempdir, 'vmlinuz-1-ux500')
         i_img_file = os.path.join(self.tempdir, 'initrd.img-1-ux500')
 
-        boot_env = board_configs['snowball_emmc']._get_boot_env(
+        boot_env = self.snowball_config._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
             rootfs_id="UUID=test_boot_env_uuid",
             i_img_data=None, d_img_data=None)
-        boards.SnowballEmmcConfig._make_boot_files(boot_env, self.tempdir,
+        self.snowball_config._make_boot_files(boot_env, self.tempdir,
             self.temp_bootdir_path, 'boot_device_or_file', k_img_file,
             i_img_file, None)
         expected = [
@@ -1145,12 +1155,12 @@
     def test_missing_files(self):
         '''When the files cannot be read, an IOError should be raised'''
         self.assertRaises(IOError,
-                          boards.SnowballEmmcConfig.get_file_info,
+                          self.snowball_config.get_file_info,
                           self.tempdir, self.temp_bootdir_path)
 
     def test_normal_case(self):
         expected = self.setupFiles()
-        actual = boards.SnowballEmmcConfig.get_file_info(
+        actual = self.snowball_config.get_file_info(
             self.tempdir, self.temp_bootdir_path)
         self.assertEquals(expected, actual)
 
@@ -1161,8 +1171,6 @@
         super(TestBootSteps, self).setUp()
         self.funcs_calls = []
         self.mock_all_boards_funcs()
-        boards = linaro_image_tools.media_create.boards
-        boards.BoardConfig.hwpack_format = '1.0'
 
     def mock_all_boards_funcs(self):
         """Mock functions of boards module with a call tracer."""
@@ -1179,169 +1187,174 @@
 
     def mock_set_appropriate_serial_tty(self, config):
 
-        def set_appropriate_serial_tty_mock(cls, chroot_dir):
-            cls.serial_tty = cls._serial_tty
+        def set_appropriate_serial_tty_mock(chroot_dir):
+            config.serial_tty = config._serial_tty
 
-        self.useFixture(MockSomethingFixture(
-            config, 'set_appropriate_serial_tty',
-            classmethod(set_appropriate_serial_tty_mock)))
+        config.set_appropriate_serial_tty = MagicMock(
+            side_effect=set_appropriate_serial_tty_mock)
 
     def make_boot_files(self, config):
-        def _get_kflavor_files_mock(cls, path):
-            if cls.dtb_name is None:
+        def _get_kflavor_files_mock(path):
+            if config.dtb_name is None:
                 return (path, path, None)
             return (path, path, path)
 
-        self.useFixture(MockSomethingFixture(
-            config, '_get_kflavor_files',
-            classmethod(_get_kflavor_files_mock)))
+        config._get_kflavor_files = MagicMock(
+            side_effect=_get_kflavor_files_mock)
 
         config.make_boot_files('', False, False, [], '', '', '', '')
 
     def test_vexpress_steps(self):
-        self.make_boot_files(boards.VexpressConfig)
+        board_conf = boards.VexpressConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.make_boot_files(board_conf)
         expected = ['make_uImage', 'make_uInitrd']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_vexpress_a9_steps(self):
-        self.make_boot_files(boards.VexpressA9Config)
+        board_conf = boards.VexpressA9Config()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.make_boot_files(board_conf)
         expected = ['make_uImage', 'make_uInitrd']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_mx5_steps(self):
-        class SomeMx5Config(boards.Mx5Config):
-            bootloader_flavor = 'bootloader_flavor'
-        SomeMx5Config.hardwarepack_handler = (
+        board_conf = boards.Mx5Config()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.bootloader_flavor = 'bootloader_flavor'
+        board_conf.hardwarepack_handler = (
             TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        SomeMx5Config.hardwarepack_handler.get_format = (
-            lambda: '1.0')
-        self.make_boot_files(SomeMx5Config)
+        board_conf.hardwarepack_handler.get_format = (
+            lambda: HardwarepackHandler.FORMAT_1)
+        self.make_boot_files(board_conf)
         expected = [
             'install_mx5_boot_loader', 'make_uImage', 'make_uInitrd',
             'make_dtb', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_smdkv310_steps(self):
-        def mock_func_creator(name):
-            return classmethod(
-                lambda *args, **kwargs: self.funcs_calls.append(name))
-
-        self.useFixture(MockSomethingFixture(
-                linaro_image_tools.media_create.boards.SMDKV310Config,
-                'install_samsung_boot_loader',
-                mock_func_creator('install_samsung_boot_loader')))
+        board_conf = boards.SMDKV310Config()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.install_samsung_boot_loader = MagicMock()
+        board_conf.install_samsung_boot_loader.return_value = \
+            self.funcs_calls.append('install_samsung_boot_loader')
         self.useFixture(MockSomethingFixture(os.path, 'exists',
                                              lambda file: True))
-        boards.SMDKV310Config.hardwarepack_handler = (
+        board_conf.hardwarepack_handler = (
             TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        boards.SMDKV310Config.hardwarepack_handler.get_format = (
-            lambda: '1.0')
-        self.make_boot_files(boards.SMDKV310Config)
+        board_conf.hardwarepack_handler.get_format = (
+            lambda: HardwarepackHandler.FORMAT_1)
+        self.make_boot_files(board_conf)
         expected = [
             'install_samsung_boot_loader', 'make_flashable_env', '_dd',
             'make_uImage', 'make_uInitrd', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_origen_steps(self):
-        def mock_func_creator(name):
-            return classmethod(
-                lambda *args, **kwargs: self.funcs_calls.append(name))
-
-        self.useFixture(MockSomethingFixture(
-                linaro_image_tools.media_create.boards.OrigenConfig,
-                'install_samsung_boot_loader',
-                mock_func_creator('install_samsung_boot_loader')))
+        board_conf = boards.OrigenConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.install_samsung_boot_loader = MagicMock()
+        board_conf.install_samsung_boot_loader.return_value = \
+            self.funcs_calls.append('install_samsung_boot_loader')
         self.useFixture(MockSomethingFixture(os.path, 'exists',
                                              lambda file: True))
-        boards.OrigenConfig.hardwarepack_handler = (
+        board_conf.hardwarepack_handler = (
             TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        boards.OrigenConfig.hardwarepack_handler.get_format = (
-            lambda: '1.0')
-        self.make_boot_files(boards.OrigenConfig)
+        board_conf.hardwarepack_handler.get_format = (
+            lambda: HardwarepackHandler.FORMAT_1)
+        self.make_boot_files(board_conf)
         expected = [
             'install_samsung_boot_loader', 'make_flashable_env', '_dd',
             'make_uImage', 'make_uInitrd', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_origen_quad_steps(self):
-        def mock_func_creator(name):
-            return classmethod(
-                lambda *args, **kwargs: self.funcs_calls.append(name))
+        board_conf = boards.OrigenQuadConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.install_samsung_boot_loader = MagicMock()
+        board_conf.install_samsung_boot_loader.return_value = \
+            self.funcs_calls.append('install_samsung_boot_loader')
 
-        self.useFixture(MockSomethingFixture(
-                linaro_image_tools.media_create.boards.OrigenQuadConfig,
-                'install_samsung_boot_loader',
-                mock_func_creator('install_samsung_boot_loader')))
         self.useFixture(MockSomethingFixture(os.path, 'exists',
                                              lambda file: True))
-        boards.OrigenQuadConfig.hardwarepack_handler = (
+        board_conf.hardwarepack_handler = (
             TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        boards.OrigenQuadConfig.hardwarepack_handler.get_format = (
-            lambda: '1.0')
-        self.make_boot_files(boards.OrigenQuadConfig)
+        board_conf.hardwarepack_handler.get_format = (
+            lambda: HardwarepackHandler.FORMAT_1)
+        self.make_boot_files(board_conf)
         expected = [
             'install_samsung_boot_loader', 'make_flashable_env', '_dd',
             'make_uImage', 'make_uInitrd', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_arndale_steps(self):
-        def mock_func_creator(name):
-            return classmethod(
-                lambda *args, **kwargs: self.funcs_calls.append(name))
+        board_conf = boards.ArndaleConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.install_samsung_boot_loader = MagicMock()
+        board_conf.install_samsung_boot_loader.return_value = \
+            self.funcs_calls.append('install_samsung_boot_loader')
 
-        self.useFixture(MockSomethingFixture(
-            linaro_image_tools.media_create.boards.ArndaleConfig,
-            'install_samsung_boot_loader',
-            mock_func_creator('install_samsung_boot_loader')))
         self.useFixture(MockSomethingFixture(os.path, 'exists',
             lambda file: True))
-        boards.ArndaleConfig.hardwarepack_handler = (
+        board_conf.hardwarepack_handler = (
             TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        boards.ArndaleConfig.hardwarepack_handler.get_format = (
+        board_conf.hardwarepack_handler.get_format = (
             lambda: '1.0')
-        self.make_boot_files(boards.ArndaleConfig)
+        self.make_boot_files(board_conf)
         expected = [
             'install_samsung_boot_loader', 'make_flashable_env', '_dd',
             'make_uImage', 'make_uInitrd', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_ux500_steps(self):
-        self.make_boot_files(boards.Ux500Config)
+        board_conf = boards.Ux500Config()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.make_boot_files(board_conf)
         expected = ['make_uImage', 'make_uInitrd', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_snowball_sd_steps(self):
-        self.make_boot_files(boards.SnowballSdConfig)
+        board_conf = boards.SnowballSdConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.make_boot_files(board_conf)
         expected = ['make_uImage', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_panda_steps(self):
-        self.mock_set_appropriate_serial_tty(boards.PandaConfig)
-        self.make_boot_files(boards.PandaConfig)
+        board_conf = boards.PandaConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.mock_set_appropriate_serial_tty(board_conf)
+        self.make_boot_files(board_conf)
         expected = [
             'install_omap_boot_loader', 'make_uImage', 'make_uInitrd',
             'make_dtb', 'make_boot_script', 'make_boot_ini']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_beagle_steps(self):
-        self.mock_set_appropriate_serial_tty(boards.BeagleConfig)
-        self.make_boot_files(boards.BeagleConfig)
+        board_conf = boards.BeagleConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.mock_set_appropriate_serial_tty(board_conf)
+        self.make_boot_files(board_conf)
         expected = [
             'install_omap_boot_loader', 'make_uImage', 'make_uInitrd',
             'make_dtb', 'make_boot_script', 'make_boot_ini']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_igep_steps(self):
-        self.mock_set_appropriate_serial_tty(boards.IgepConfig)
-        self.make_boot_files(boards.IgepConfig)
+        board_conf = boards.IgepConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.mock_set_appropriate_serial_tty(board_conf)
+        self.make_boot_files(board_conf)
         expected = [
             'make_uImage', 'make_uInitrd', 'make_dtb', 'make_boot_script',
             'make_boot_ini']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_overo_steps(self):
-        self.mock_set_appropriate_serial_tty(boards.OveroConfig)
-        self.make_boot_files(boards.OveroConfig)
+        board_conf = boards.OveroConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.mock_set_appropriate_serial_tty(board_conf)
+        self.make_boot_files(board_conf)
         expected = [
             'install_omap_boot_loader', 'make_uImage', 'make_uInitrd',
             'make_dtb', 'make_boot_script', 'make_boot_ini']
@@ -1373,20 +1386,20 @@
 
     def test_snowball_config_raises(self):
         self.assertRaises(NotImplementedError,
-                          boards.SnowballSdConfig.snowball_config, '')
+                          boards.SnowballSdConfig().snowball_config, '')
 
     def test_beagle_raw(self):
-        self.populate_raw_partition(android_boards.AndroidBeagleConfig)
+        self.populate_raw_partition(android_boards.AndroidBeagleConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
     def test_panda_raw(self):
-        self.populate_raw_partition(android_boards.AndroidPandaConfig)
+        self.populate_raw_partition(android_boards.AndroidPandaConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
     def test_snowball_sd_raw(self):
-        self.populate_raw_partition(boards.SnowballSdConfig)
+        self.populate_raw_partition(boards.SnowballSdConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1411,7 +1424,7 @@
                 linaro_image_tools.media_create.boards.SnowballEmmcConfig,
                 'delete_file',
                 mock_func_creator('delete_file')))
-        self.populate_raw_partition(boards.SnowballEmmcConfig)
+        self.populate_raw_partition(boards.SnowballEmmcConfig())
         expected = ['get_file_info', 'create_toc',
                     'install_snowball_boot_loader', 'delete_file',
                     'delete_file']
@@ -1423,12 +1436,12 @@
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
 
-        self.populate_raw_partition(boards.SMDKV310Config)
+        self.populate_raw_partition(boards.SMDKV310Config())
         expected = ['_dd', '_dd', '_dd']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_mx53loco_raw(self):
-        self.populate_raw_partition(boards.Mx53LoCoConfig)
+        self.populate_raw_partition(boards.Mx53LoCoConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1436,7 +1449,7 @@
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
 
-        self.populate_raw_partition(boards.OrigenConfig)
+        self.populate_raw_partition(boards.OrigenConfig())
         expected = ['_dd', '_dd', '_dd']
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1444,7 +1457,7 @@
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
 
-        self.populate_raw_partition(boards.OrigenQuadConfig)
+        self.populate_raw_partition(boards.OrigenQuadConfig())
         expected = ['_dd', '_dd', '_dd']
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1452,12 +1465,12 @@
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
             lambda file: 1))
 
-        self.populate_raw_partition(boards.ArndaleConfig)
+        self.populate_raw_partition(boards.ArndaleConfig())
         expected = ['_dd', '_dd', '_dd']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_vexpress_a9_raw(self):
-        self.populate_raw_partition(boards.VexpressA9Config)
+        self.populate_raw_partition(boards.VexpressA9Config())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1472,17 +1485,17 @@
         config.populate_raw_partition('', '')
 
     def test_beagle_raw(self):
-        self.populate_raw_partition(android_boards.AndroidBeagleConfig)
+        self.populate_raw_partition(android_boards.AndroidBeagleConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
     def test_panda_raw(self):
-        self.populate_raw_partition(android_boards.AndroidPandaConfig)
+        self.populate_raw_partition(android_boards.AndroidPandaConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
     def test_snowball_sd_raw(self):
-        self.populate_raw_partition(android_boards.AndroidSnowballSdConfig)
+        self.populate_raw_partition(android_boards.AndroidSnowballSdConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1513,7 +1526,7 @@
                 android_boards.AndroidSnowballEmmcConfig,
                 'delete_file',
                 mock_func_creator('delete_file')))
-        self.populate_raw_partition(android_boards.AndroidSnowballEmmcConfig)
+        self.populate_raw_partition(android_boards.AndroidSnowballEmmcConfig())
         expected_calls = ['get_file_info', 'create_toc',
                     'install_snowball_boot_loader', 'delete_file']
         # Test that we copy the u-boot files to the local startupfiles dir.
@@ -1533,14 +1546,14 @@
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
 
-        self.populate_raw_partition(android_boards.AndroidSMDKV310Config)
+        self.populate_raw_partition(android_boards.AndroidSMDKV310Config())
         expected_calls = []
         # Test that we dd the files
         self.assertEqual(expected_commands, fixture.mock.commands_executed)
         self.assertEqual(expected_calls, self.funcs_calls)
 
     def test_mx53loco_raw(self):
-        self.populate_raw_partition(android_boards.AndroidMx53LoCoConfig)
+        self.populate_raw_partition(android_boards.AndroidMx53LoCoConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1555,7 +1568,7 @@
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
 
-        self.populate_raw_partition(android_boards.AndroidOrigenConfig)
+        self.populate_raw_partition(android_boards.AndroidOrigenConfig())
         expected = []
         # Test that we dd the files
         self.assertEqual(expected_commands, fixture.mock.commands_executed)
@@ -1573,14 +1586,14 @@
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
 
-        self.populate_raw_partition(android_boards.AndroidOrigenQuadConfig)
+        self.populate_raw_partition(android_boards.AndroidOrigenQuadConfig())
         expected = []
         # Test that we dd the files
         self.assertEqual(expected_commands, fixture.mock.commands_executed)
         self.assertEqual(expected, self.funcs_calls)
 
     def test_vexpress_raw(self):
-        self.populate_raw_partition(android_boards.AndroidVexpressConfig)
+        self.populate_raw_partition(android_boards.AndroidVexpressConfig())
         expected = []
         self.assertEqual(expected, self.funcs_calls)
 
@@ -1611,25 +1624,29 @@
 
     def mock_set_appropriate_serial_tty(self, config):
 
-        def set_appropriate_serial_tty_mock(cls, chroot_dir):
+        def set_appropriate_serial_tty_mock(arg):
             self.set_appropriate_serial_tty_called = True
-            cls.serial_tty = cls._serial_tty
 
-        self.useFixture(MockSomethingFixture(
-            config, 'set_appropriate_serial_tty',
-            classmethod(set_appropriate_serial_tty_mock)))
+        # Need to mock all the calls done from make_boot_files in order
+        # to be able to correctly call it.
+        config._get_kflavor_files = MagicMock(return_value=('', '', ''))
+        config._get_boot_env = MagicMock(return_value=None)
+        config._make_boot_files = MagicMock()
+        config._make_boot_files_v2 = MagicMock()
+        config.set_appropriate_serial_tty = MagicMock(
+             side_effect=set_appropriate_serial_tty_mock)
 
     def test_omap_make_boot_files(self):
         self.set_appropriate_serial_tty_called = False
-        self.mock_set_appropriate_serial_tty(board_configs['beagle'])
-        self.useFixture(MockSomethingFixture(
-            boards.BoardConfig, 'make_boot_files',
-            classmethod(lambda *args: None)))
+
+        board_conf = boards.BeagleConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        self.mock_set_appropriate_serial_tty(board_conf)
         # We don't need to worry about what's passed to make_boot_files()
         # because we mock the method which does the real work above and here
         # we're only interested in ensuring that OmapConfig.make_boot_files()
         # calls set_appropriate_serial_tty().
-        board_configs['beagle'].make_boot_files(
+        board_conf.make_boot_files(
             None, None, None, None, None, None, None, None)
         self.assertTrue(
             self.set_appropriate_serial_tty_called,
@@ -1638,17 +1655,14 @@
     def test_omap_make_boot_files_v2(self):
         self.set_appropriate_serial_tty_called = False
 
-        class config(boards.BeagleConfig):
-            hwpack_format = HardwarepackHandler.FORMAT_2
-        self.mock_set_appropriate_serial_tty(config)
-        self.useFixture(MockSomethingFixture(
-            boards.BoardConfig, 'make_boot_files',
-            classmethod(lambda *args: None)))
+        board_conf = boards.BeagleConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_2
+        self.mock_set_appropriate_serial_tty(board_conf)
         # We don't need to worry about what's passed to make_boot_files()
         # because we mock the method which does the real work above and here
         # we're only interested in ensuring that OmapConfig.make_boot_files()
         # does not call set_appropriate_serial_tty().
-        config.make_boot_files(
+        board_conf.make_boot_files(
             None, None, None, None, None, None, None, None)
         self.assertFalse(
             self.set_appropriate_serial_tty_called,
@@ -1659,189 +1673,219 @@
         boot_dir = os.path.join(tempdir, 'boot')
         os.makedirs(boot_dir)
         open(os.path.join(boot_dir, 'vmlinuz-2.6.35-23-foo'), 'w').close()
-        boards.BeagleConfig.set_appropriate_serial_tty(tempdir)
-        self.assertEquals('ttyS2', boards.BeagleConfig.serial_tty)
+        board_conf = boards.BeagleConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.set_appropriate_serial_tty(tempdir)
+        self.assertEquals('ttyS2', board_conf.serial_tty)
 
     def test_set_appropriate_serial_tty_new_kernel(self):
         tempdir = self.useFixture(CreateTempDirFixture()).tempdir
         boot_dir = os.path.join(tempdir, 'boot')
         os.makedirs(boot_dir)
         open(os.path.join(boot_dir, 'vmlinuz-2.6.36-13-foo'), 'w').close()
-        boards.BeagleConfig.set_appropriate_serial_tty(tempdir)
-        self.assertEquals('ttyO2', boards.BeagleConfig.serial_tty)
+        board_conf = boards.BeagleConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.set_appropriate_serial_tty(tempdir)
+        self.assertEquals('ttyO2', board_conf.serial_tty)
 
     def test_set_appropriate_serial_tty_three_dot_oh_kernel(self):
         tempdir = self.useFixture(CreateTempDirFixture()).tempdir
         boot_dir = os.path.join(tempdir, 'boot')
         os.makedirs(boot_dir)
         open(os.path.join(boot_dir, 'vmlinuz-3.0-13-foo'), 'w').close()
-        boards.BeagleConfig.set_appropriate_serial_tty(tempdir)
-        self.assertEquals('ttyO2', boards.BeagleConfig.serial_tty)
+        board_conf = boards.BeagleConfig()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        board_conf.set_appropriate_serial_tty(tempdir)
+        self.assertEquals('ttyO2', board_conf.serial_tty)
 
 
 class TestGetSfdiskCmd(TestCase):
 
+    def set_up_config(self, config):
+        config.hwpack_format = HardwarepackHandler.FORMAT_1
+
     def test_default(self):
+        board_conf = BoardConfig()
+        self.set_up_config(board_conf)
         self.assertEqual(
-            '63,106432,0x0C,*\n106496,,,-',
-            boards.BoardConfig.get_sfdisk_cmd())
+            '63,106432,0x0C,*\n106496,,,-', board_conf.get_sfdisk_cmd())
 
     def test_default_aligned(self):
+        board_conf = BoardConfig()
+        self.set_up_config(board_conf)
         self.assertEqual(
             '8192,106496,0x0C,*\n114688,,,-',
-            boards.BoardConfig.get_sfdisk_cmd(should_align_boot_part=True))
+            board_conf.get_sfdisk_cmd(should_align_boot_part=True))
 
     def test_mx5(self):
+        board_conf = boards.Mx5Config()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
         self.assertEqual(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            boards.Mx5Config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_snowball_sd(self):
+        board_conf = boards.SnowballSdConfig()
+        self.set_up_config(board_conf)
         self.assertEqual(
-            '63,106432,0x0C,*\n106496,,,-',
-            boards.SnowballSdConfig.get_sfdisk_cmd())
+            '63,106432,0x0C,*\n106496,,,-', board_conf.get_sfdisk_cmd())
 
     def test_snowball_emmc(self):
+        board_conf = boards.SnowballEmmcConfig()
+        self.set_up_config(board_conf)
         self.assertEqual(
             '256,7936,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            boards.SnowballEmmcConfig.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_smdkv310(self):
+        board_conf = get_board_config('smdkv310')
+        self.set_up_config(board_conf)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            board_configs['smdkv310'].get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_origen(self):
+        board_conf = get_board_config('origen')
+        self.set_up_config(board_conf)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            board_configs['origen'].get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_origen_quad(self):
+        board_conf = get_board_config('origen_quad')
+        self.set_up_config(board_conf)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            board_configs['origen_quad'].get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_arndale(self):
+        board_conf = get_board_config('arndale')
+        self.set_up_config(board_conf)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            board_configs['arndale'].get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_panda_android(self):
         self.assertEqual(
             '63,270272,0x0C,*\n270336,1048576,L\n1318912,524288,L\n'
             '1843200,-,E\n1843200,1048576,L\n2891776,,,-',
-            android_boards.AndroidPandaConfig.get_sfdisk_cmd())
+            android_boards.AndroidPandaConfig().get_sfdisk_cmd())
 
     def test_origen_android(self):
         self.assertEqual(
             '1,8191,0xDA\n8253,270274,0x0C,*\n278528,1048576,L\n'
             '1327104,-,E\n1327104,524288,L\n1851392,1048576,L\n2899968,,,-',
-            android_boards.AndroidOrigenConfig.get_sfdisk_cmd())
+            android_boards.AndroidOrigenConfig().get_sfdisk_cmd())
 
     def test_origen_quad_android(self):
         self.assertEqual(
             '1,8191,0xDA\n8253,270274,0x0C,*\n278528,1048576,L\n'
             '1327104,-,E\n1327104,524288,L\n1851392,1048576,L\n2899968,,,-',
-            android_boards.AndroidOrigenQuadConfig.get_sfdisk_cmd())
+            android_boards.AndroidOrigenQuadConfig().get_sfdisk_cmd())
 
     def test_snowball_emmc_android(self):
         self.assertEqual(
             '256,7936,0xDA\n8192,262144,0x0C,*\n270336,1048576,L\n'
             '1318912,-,E\n1318912,524288,L\n1843200,1048576,L\n2891776,,,-',
-            android_boards.AndroidSnowballEmmcConfig.get_sfdisk_cmd())
+            android_boards.AndroidSnowballEmmcConfig().get_sfdisk_cmd())
 
     def test_vexpress_android(self):
         self.assertEqual(
             '63,270272,0x0E,*\n270336,1048576,L\n1318912,524288,L\n'
             '1843200,-,E\n1843200,1048576,L\n2891776,,,-',
-            android_boards.AndroidVexpressConfig.get_sfdisk_cmd())
+            android_boards.AndroidVexpressConfig().get_sfdisk_cmd())
 
     def test_mx5_android(self):
         self.assertEqual(
             '1,8191,0xDA\n8192,262144,0x0C,*\n270336,1048576,L\n'
             '1318912,-,E\n1318912,524288,L\n1843200,1048576,L\n2891776,,,-',
-            android_boards.AndroidMx53LoCoConfig.get_sfdisk_cmd())
+            android_boards.AndroidMx53LoCoConfig().get_sfdisk_cmd())
 
     def test_mx6_android(self):
         self.assertEqual(
             '1,8191,0xDA\n8192,262144,0x0C,*\n270336,1048576,L\n'
             '1318912,-,E\n1318912,524288,L\n1843200,1048576,L\n2891776,,,-',
-            android_boards.AndroidMx6QSabreliteConfig.get_sfdisk_cmd())
+            android_boards.AndroidMx6QSabreliteConfig().get_sfdisk_cmd())
 
 
 class TestGetSfdiskCmdV2(TestCase):
 
     def test_mx5(self):
-        class config(boards.Mx5Config):
-            partition_layout = 'reserved_bootfs_rootfs'
+        board_conf = boards.Mx5Config()
+        board_conf.partition_layout = 'reserved_bootfs_rootfs'
         self.assertEqual(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_snowball_sd(self):
-        class config(boards.SnowballSdConfig):
-            partition_layout = 'bootfs_rootfs'
+        board_conf = boards.SnowballSdConfig()
+        board_conf.partition_layout = 'bootfs_rootfs'
         self.assertEqual(
             '63,106432,0x0C,*\n106496,,,-',
-            config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_snowball_emmc(self):
-        class config(boards.SnowballEmmcConfig):
-            partition_layout = 'reserved_bootfs_rootfs'
-            LOADER_START_S = (128 * 1024) / SECTOR_SIZE
+        board_conf = boards.SnowballEmmcConfig()
+        board_conf.partition_layout = 'reserved_bootfs_rootfs'
+        board_conf.loader_start_s = (128 * 1024) / SECTOR_SIZE
         self.assertEqual(
             '256,7936,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_smdkv310(self):
-        class config(board_configs['smdkv310']):
-            partition_layout = 'reserved_bootfs_rootfs'
-            LOADER_MIN_SIZE_S = (boards.BoardConfig.samsung_bl1_start +
-                                 boards.BoardConfig.samsung_bl1_len +
-                                 boards.BoardConfig.samsung_bl2_len +
-                                 boards.BoardConfig.samsung_env_len)
+        board_conf = get_board_config('smdkv310')
+        board_conf.partition_layout = 'reserved_bootfs_rootfs'
+        board_conf.LOADER_MIN_SIZE_S = (
+            board_conf.samsung_bl1_start +
+            board_conf.samsung_bl1_len +
+            board_conf.samsung_bl2_len +
+            board_conf.samsung_env_len)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_origen(self):
-        class config(board_configs['origen']):
-            partition_layout = 'reserved_bootfs_rootfs'
-            LOADER_MIN_SIZE_S = (boards.BoardConfig.samsung_bl1_start +
-                                 boards.BoardConfig.samsung_bl1_len +
-                                 boards.BoardConfig.samsung_bl2_len +
-                                 boards.BoardConfig.samsung_env_len)
+        board_conf = get_board_config('origen')
+        board_conf.partition_layout = 'reserved_bootfs_rootfs'
+        board_conf.LOADER_MIN_SIZE_S = (
+                                 board_conf.samsung_bl1_start +
+                                 board_conf.samsung_bl1_len +
+                                 board_conf.samsung_bl2_len +
+                                 board_conf.samsung_env_len)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_origen_quad(self):
-        class config(board_configs['origen_quad']):
-            partition_layout = 'reserved_bootfs_rootfs'
-            LOADER_MIN_SIZE_S = (boards.BoardConfig.samsung_bl1_start +
-                                 boards.BoardConfig.samsung_bl1_len +
-                                 boards.BoardConfig.samsung_bl2_len +
-                                 boards.BoardConfig.samsung_env_len)
+        board_conf = get_board_config('origen_quad')
+        board_conf.partition_layout = 'reserved_bootfs_rootfs'
+        board_conf.LOADER_MIN_SIZE_S = (
+                                board_conf.samsung_bl1_start +
+                                board_conf.samsung_bl1_len +
+                                board_conf.samsung_bl2_len +
+                                board_conf.samsung_env_len)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
     def test_arndale(self):
-        class config(board_configs['arndale']):
-            partition_layout = 'reserved_bootfs_rootfs'
-            LOADER_MIN_SIZE_S = (boards.BoardConfig.samsung_bl1_start +
-                                 boards.BoardConfig.samsung_bl1_len +
-                                 boards.BoardConfig.samsung_bl2_len +
-                                 boards.BoardConfig.samsung_env_len)
+        board_conf = get_board_config('arndale')
+        board_conf.partition_layout = 'reserved_bootfs_rootfs'
+        board_conf.LOADER_MIN_SIZE_S = (
+            board_conf.samsung_bl1_start +
+            board_conf.samsung_bl1_len +
+            board_conf.samsung_bl2_len +
+            board_conf.samsung_env_len)
         self.assertEquals(
             '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
-            config.get_sfdisk_cmd())
+            board_conf.get_sfdisk_cmd())
 
 
 class TestGetBootCmd(TestCase):
 
     def test_vexpress(self):
-        boot_commands = board_configs['vexpress']._get_boot_env(
+        board_conf = get_board_config('vexpress')
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=['ttyXXX'],
             rootfs_id="UUID=deadbeef", i_img_data="initrd", d_img_data=None)
         expected = {
@@ -1855,7 +1899,8 @@
         self.assertEqual(expected, boot_commands)
 
     def test_vexpress_a9(self):
-        boot_commands = board_configs['vexpress-a9']._get_boot_env(
+        board_conf = get_board_config('vexpress-a9')
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=['ttyXXX'],
             rootfs_id="UUID=deadbeef", i_img_data="initrd", d_img_data=None)
         expected = {
@@ -1869,7 +1914,8 @@
         self.assertEqual(expected, boot_commands)
 
     def test_mx51(self):
-        boot_commands = boards.Mx51Config._get_boot_env(
+        board_conf = boards.Mx51Config()
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
             rootfs_id="UUID=deadbeef", i_img_data="initrd",
             d_img_data="mx51.dtb")
@@ -1885,7 +1931,8 @@
         self.assertEqual(expected, boot_commands)
 
     def test_smdkv310(self):
-        boot_commands = board_configs['smdkv310']._get_boot_env(
+        board_conf = get_board_config('smdkv310')
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
             rootfs_id="UUID=deadbeef", i_img_data="initrd", d_img_data=None)
         expected = {
@@ -1901,7 +1948,8 @@
         self.assertEqual(expected, boot_commands)
 
     def test_origen(self):
-        boot_commands = board_configs['origen']._get_boot_env(
+        board_conf = get_board_config('origen')
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
             rootfs_id="UUID=deadbeef", i_img_data="initrd", d_img_data=None)
         expected = {
@@ -1915,7 +1963,8 @@
         self.assertEqual(expected, boot_commands)
 
     def test_origen_quad(self):
-        boot_commands = board_configs['origen_quad']._get_boot_env(
+        board_conf = get_board_config('origen_quad')
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
             rootfs_id="UUID=deadbeef", i_img_data="initrd", d_img_data=None)
         expected = {
@@ -1929,7 +1978,8 @@
         self.assertEqual(expected, boot_commands)
 
     def test_ux500(self):
-        boot_commands = board_configs['ux500']._get_boot_env(
+        board_conf = get_board_config('ux500')
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
             rootfs_id="UUID=deadbeef", i_img_data="initrd", d_img_data=None)
         expected = {
@@ -1947,7 +1997,8 @@
         self.assertEqual(expected, boot_commands)
 
     def test_snowball_emmc(self):
-        boot_commands = board_configs['snowball_emmc']._get_boot_env(
+        board_conf = get_board_config('snowball_emmc')
+        boot_commands = board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
             rootfs_id="UUID=deadbeef", i_img_data="initrd", d_img_data=None)
         expected = {
@@ -1968,7 +2019,7 @@
         # XXX: To fix bug 697824 we have to change class attributes of our
         # OMAP board configs, and some tests do that so to make sure they
         # don't interfere with us we'll reset that before doing anything.
-        config = board_configs['panda']
+        config = get_board_config('panda')
         config.serial_tty = config._serial_tty
         boot_commands = config._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
@@ -1991,7 +2042,7 @@
         # XXX: To fix bug 697824 we have to change class attributes of our
         # OMAP board configs, and some tests do that so to make sure they
         # don't interfere with us we'll reset that before doing anything.
-        config = board_configs['beagle']
+        config = get_board_config('beagle')
         config.serial_tty = config._serial_tty
         boot_commands = config._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
@@ -2014,7 +2065,7 @@
         # XXX: To fix bug 697824 we have to change class attributes of our
         # OMAP board configs, and some tests do that so to make sure they
         # don't interfere with us we'll reset that before doing anything.
-        config = boards.IgepConfig
+        config = boards.IgepConfig()
         config.serial_tty = config._serial_tty
         boot_cmd = config._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
@@ -2037,7 +2088,7 @@
         # XXX: To fix bug 697824 we have to change class attributes of our
         # OMAP board configs, and some tests do that so to make sure they
         # don't interfere with us we'll reset that before doing anything.
-        config = board_configs['overo']
+        config = get_board_config('overo')
         config.serial_tty = config._serial_tty
         boot_commands = config._get_boot_env(
             is_live=False, is_lowmem=False, consoles=[],
@@ -2060,12 +2111,15 @@
 
 class TestExtraBootCmd(TestCaseWithFixtures):
 
+    def setUp(self):
+        super(TestExtraBootCmd, self).setUp()
+        self.board_conf = BoardConfig()
+
     def test_extra_boot_args_options_is_picked_by_get_boot_env(self):
         boot_args = 'whatever'
 
-        class config(BoardConfig):
-            extra_boot_args_options = boot_args
-        boot_commands = config._get_boot_env(
+        self.board_conf.extra_boot_args_options = boot_args
+        boot_commands = self.board_conf._get_boot_env(
             is_live=False, is_lowmem=False, consoles=['ttyXXX'],
             rootfs_id="UUID=deadbeef", i_img_data=None, d_img_data=None)
         expected = (
@@ -2075,28 +2129,25 @@
     def test_passing_None_to_add_boot_args(self):
         boot_args = 'extra-args'
 
-        class config(BoardConfig):
-            extra_boot_args_options = boot_args
-        config.add_boot_args(None)
-        self.assertEqual(boot_args, config.extra_boot_args_options)
+        self.board_conf.extra_boot_args_options = boot_args
+        self.board_conf.add_boot_args(None)
+        self.assertEqual(boot_args, self.board_conf.extra_boot_args_options)
 
     def test_passing_string_to_add_boot_args(self):
         boot_args = 'extra-args'
         extra_args = 'user-args'
 
-        class config(BoardConfig):
-            extra_boot_args_options = boot_args
-        config.add_boot_args(extra_args)
+        self.board_conf.extra_boot_args_options = boot_args
+        self.board_conf.add_boot_args(extra_args)
         self.assertEqual(
-            "%s %s" % (boot_args, extra_args), config.extra_boot_args_options)
+            "%s %s" % (boot_args, extra_args),
+            self.board_conf.extra_boot_args_options)
 
     def test_passing_string_to_add_boot_args_with_no_default_extra_args(self):
         extra_args = 'user-args'
 
-        class config(BoardConfig):
-            extra_boot_args_options = None
-        config.add_boot_args(extra_args)
-        self.assertEqual(extra_args, config.extra_boot_args_options)
+        self.board_conf.add_boot_args(extra_args)
+        self.assertEqual(extra_args, self.board_conf.extra_boot_args_options)
 
     def test_add_boot_args_from_file(self):
         boot_args = 'extra-args'
@@ -2105,19 +2156,18 @@
         with open(boot_arg_path, 'w') as boot_arg_file:
             boot_arg_file.write(extra_args)
 
-        class config(BoardConfig):
-            extra_boot_args_options = boot_args
-        config.add_boot_args_from_file(boot_arg_path)
+        self.board_conf.extra_boot_args_options = boot_args
+        self.board_conf.add_boot_args_from_file(boot_arg_path)
         self.assertEqual(
-            "%s %s" % (boot_args, extra_args), config.extra_boot_args_options)
+            "%s %s" % (boot_args, extra_args),
+            self.board_conf.extra_boot_args_options)
 
     def test_passing_None_to_add_boot_args_from_file(self):
         boot_args = 'extra-args'
 
-        class config(BoardConfig):
-            extra_boot_args_options = boot_args
-        config.add_boot_args_from_file(None)
-        self.assertEqual(boot_args, config.extra_boot_args_options)
+        self.board_conf.extra_boot_args_options = boot_args
+        self.board_conf.add_boot_args_from_file(None)
+        self.assertEqual(boot_args, self.board_conf.extra_boot_args_options)
 
     def test_add_boot_args_from_file_strips_whitespace_from_file(self):
         boot_args = 'extra-args'
@@ -2126,134 +2176,11 @@
         with open(boot_arg_path, 'w') as boot_arg_file:
             boot_arg_file.write('\n\n \t ' + extra_args + '  \n\n')
 
-        class config(BoardConfig):
-            extra_boot_args_options = boot_args
-        config.add_boot_args_from_file(boot_arg_path)
+        self.board_conf.extra_boot_args_options = boot_args
+        self.board_conf.add_boot_args_from_file(boot_arg_path)
         self.assertEqual(
-            "%s %s" % (boot_args, extra_args), config.extra_boot_args_options)
-
-
-class TestGetBootCmdAndroid(TestCase):
-
-    def test_panda(self):
-        # XXX: To fix bug 697824 we have to change class attributes of our
-        # OMAP board configs, and some tests do that so to make sure they
-        # don't interfere with us we'll reset that before doing anything.
-        config = android_board_configs['panda']
-        config.serial_tty = config._serial_tty
-        expected = {
-            'bootargs': 'console=ttyO2,115200n8 '
-                        'rootwait ro earlyprintk fixrtc '
-                        'nocompcache vram=48M omapfb.vram=0:24M,1:24M '
-                        'mem=456M@0x80000000 mem=512M@0xA0000000 '
-                        'init=/init androidboot.console=ttyO2',
-            'bootcmd': 'fatload mmc 0:1 0x80200000 uImage; '
-                       'fatload mmc 0:1 0x81600000 uInitrd; '
-                       'fatload mmc 0:1 0x815f0000 board.dtb; '
-                       'bootm 0x80200000 0x81600000 0x815f0000',
-            'fdt_high': '0xffffffff',
-            'initrd_high': '0xffffffff'}
-        self.assertBootEnv(config, expected)
-
-    def test_android_snowball_sd(self):
-        expected = {
-            'bootargs': 'console=ttyAMA2,115200n8 '
-                        'rootwait ro earlyprintk '
-                        'mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
-                        'mem=22M@360M mem_issw=1M@383M mem=640M@384M '
-                        'vmalloc=500M init=/init androidboot.console=ttyAMA2',
-            'bootcmd': 'fatload mmc 1:1 0x00100000 uImage; '
-                       'fatload mmc 1:1 0x05000000 uInitrd; '
-                       'fatload mmc 1:1 0x8000000 board.dtb; '
-                       'bootm 0x00100000 0x05000000 0x8000000',
-            'fdt_high': '0x05000000',
-            'initrd_high': '0x06000000'}
-        self.assertBootEnv(
-            android_boards.AndroidSnowballSdConfig, expected)
-
-    def test_android_snowball_emmc(self):
-        expected = {
-            'bootargs': 'console=ttyAMA2,115200n8 '
-                        'rootwait ro earlyprintk '
-                        'mem=128M@0 mali.mali_mem=64M@128M hwmem=168M@192M '
-                        'mem=22M@360M mem_issw=1M@383M mem=640M@384M '
-                        'vmalloc=500M init=/init androidboot.console=ttyAMA2',
-            'bootcmd': 'fatload mmc 0:2 0x00100000 uImage; '
-                       'fatload mmc 0:2 0x05000000 uInitrd; '
-                       'fatload mmc 0:2 0x8000000 board.dtb; '
-                       'bootm 0x00100000 0x05000000 0x8000000',
-            'fdt_high': '0x05000000',
-            'initrd_high': '0x06000000'}
-        self.assertBootEnv(
-            android_boards.AndroidSnowballEmmcConfig, expected)
-
-    def test_android_origen(self):
-        expected = {
-            'bootargs': 'console=tty0 console=ttySAC2,115200n8 '
-                        'rootwait ro init=/init androidboot.console=ttySAC2',
-            'bootcmd': 'fatload mmc 0:2 0x40007000 uImage; '
-                       'fatload mmc 0:2 0x42000000 uInitrd; '
-                       'bootm 0x40007000 0x42000000',
-            'fdt_high': '0xffffffff',
-            'initrd_high': '0xffffffff'}
-        self.assertBootEnv(
-            android_boards.AndroidOrigenConfig, expected)
-
-    def test_android_origen_quad(self):
-        expected = {
-            'bootargs': 'console=tty0 console=ttySAC2,115200n8 '
-                        'rootwait ro init=/init androidboot.console=ttySAC2',
-            'bootcmd': 'fatload mmc 0:2 0x40007000 uImage; '
-                       'fatload mmc 0:2 0x42000000 uInitrd; '
-                       'bootm 0x40007000 0x42000000',
-            'fdt_high': '0xffffffff',
-            'initrd_high': '0xffffffff'}
-        self.assertBootEnv(
-            android_boards.AndroidOrigenQuadConfig, expected)
-
-    def test_android_vexpress(self):
-        expected = {
-            'bootargs': 'console=tty0 console=ttyAMA0,38400n8 '
-                        'rootwait ro init=/init androidboot.console=ttyAMA0',
-            'bootcmd': 'fatload mmc 0:1 0x60000000 uImage; '
-                       'fatload mmc 0:1 0x62000000 uInitrd; '
-                       'bootm 0x60000000 0x62000000',
-            'fdt_high': '0xffffffff',
-            'initrd_high': '0xffffffff'}
-        self.assertBootEnv(
-            android_boards.AndroidVexpressConfig, expected)
-
-    def test_android_mx5(self):
-        expected = {
-            'bootargs': 'console=ttymxc0,115200n8 '
-                        'rootwait ro earlyprintk rootdelay=1 fixrtc '
-                        'nocompcache di1_primary tve init=/init '
-                        'androidboot.console=ttymxc0',
-            'bootcmd': 'fatload mmc 0:2 0x70000000 uImage; '
-                       'fatload mmc 0:2 0x72000000 uInitrd; '
-                       'bootm 0x70000000 0x72000000',
-            'fdt_high': '0xffffffff',
-            'initrd_high': '0xffffffff'}
-        self.assertBootEnv(
-            android_boards.AndroidMx53LoCoConfig, expected)
-
-    def test_android_mx6(self):
-        expected = {
-            'bootargs': 'console=ttymxc0,115200n8 '
-                        'rootwait ro earlyprintk rootdelay=1 fixrtc '
-                        'nocompcache di1_primary tve init=/init '
-                        'androidboot.console=ttymxc0',
-            'bootcmd': 'fatload mmc 0:2 0x10000000 uImage; '
-                       'fatload mmc 0:2 0x12000000 uInitrd; '
-                       'fatload mmc 0:2 0x11ff0000 board.dtb; '
-                       'bootm 0x10000000 0x12000000 0x11ff0000',
-            'fdt_high': '0xffffffff',
-            'initrd_high': '0xffffffff'}
-        self.assertBootEnv(
-            android_boards.AndroidMx6QSabreliteConfig, expected)
-
-    def assertBootEnv(self, config, expected):
-        self.assertEqual(expected, config._get_boot_env(consoles=[]))
+            "%s %s" % (boot_args, extra_args),
+            self.board_conf.extra_boot_args_options)
 
 
 class TestUnpackBinaryTarball(TestCaseWithFixtures):
@@ -2375,119 +2302,110 @@
             boards, '_get_mlo_file',
             lambda chroot_dir: "%s/MLO" % chroot_dir))
 
-        class config(BoardConfig):
-            pass
-        config.set_metadata([])
-        install_omap_boot_loader("chroot_dir", "boot_disk", config)
+        board_conf = BoardConfig()
+        board_conf.set_metadata([])
+        install_omap_boot_loader("chroot_dir", "boot_disk", board_conf)
         expected = [
             '%s cp -v chroot_dir/MLO boot_disk' % sudo_args, 'sync']
         self.assertEqual(expected, fixture.mock.commands_executed)
 
     def test_install_smdk_u_boot(self):
         fixture = self._mock_Popen()
-        bootloader_flavor = boards.SMDKV310Config.bootloader_flavor
+        board_conf = boards.SMDKV310Config()
+        bootloader_flavor = board_conf.bootloader_flavor
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
-        boards.SMDKV310Config.install_samsung_boot_loader(
+        board_conf.install_samsung_boot_loader(
             "%s/%s/SPL" % ("chroot_dir", bootloader_flavor),
             "%s/%s/uboot" % ("chroot_dir", bootloader_flavor), "boot_disk")
         expected = [
             '%s dd if=chroot_dir/%s/SPL of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.SMDKV310Config.samsung_bl1_start),
+                         board_conf.samsung_bl1_start),
             '%s dd if=chroot_dir/%s/uboot of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.SMDKV310Config.samsung_bl2_start)]
+                         board_conf.samsung_bl2_start)]
         self.assertEqual(expected, fixture.mock.commands_executed)
 
+    def _set_up_board_config(self, board_name):
+        """Internal method to set-up correctly board config, with the
+        appropriate mock objects.
+
+        :param board_name: The name of the board to set-up.
+        :return A 3-tuple: the config, the name of the bootloader, and the
+        value of chroot_dir.
+        """
+        board_conf = get_board_config(board_name)
+        bootloader_flavor = board_conf.bootloader_flavor
+        # Made-up value to be used as the chroot directory.
+        chroot_dir_value = 'chroot_dir'
+        board_conf._get_samsung_spl = MagicMock()
+        board_conf._get_samsung_spl.return_value = ("%s/%s/SPL" %
+            (chroot_dir_value, bootloader_flavor))
+        board_conf._get_samsung_bootloader = MagicMock()
+        board_conf._get_samsung_bootloader.return_value = ("%s/%s/uboot" %
+            (chroot_dir_value, bootloader_flavor))
+        board_conf.hardwarepack_handler = (
+            TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
+        board_conf.hardwarepack_handler.get_format = (
+            lambda: HardwarepackHandler.FORMAT_1)
+        return board_conf, bootloader_flavor, chroot_dir_value
+
     def test_install_origen_u_boot(self):
         fixture = self._mock_Popen()
-        bootloader_flavor = boards.OrigenConfig.bootloader_flavor
-        self.useFixture(MockSomethingFixture(
-            boards.OrigenConfig, '_get_samsung_spl',
-            classmethod(lambda cls, chroot_dir: "%s/%s/SPL" % (
-                chroot_dir, bootloader_flavor))))
-        self.useFixture(MockSomethingFixture(
-            boards.OrigenConfig, '_get_samsung_bootloader',
-            classmethod(lambda cls, chroot_dir: "%s/%s/uboot" % (
-                chroot_dir, bootloader_flavor))))
-        boards.OrigenConfig.hardwarepack_handler = (
-            TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        boards.OrigenConfig.hardwarepack_handler.get_format = (
-            lambda: '1.0')
+        board_conf, bootloader_flavor, chroot_dir_value = \
+            self._set_up_board_config('origen')
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
-        boards.OrigenConfig.install_samsung_boot_loader(
-            boards.OrigenConfig._get_samsung_spl("chroot_dir"),
-            boards.OrigenConfig._get_samsung_bootloader("chroot_dir"),
+        board_conf.install_samsung_boot_loader(
+            board_conf._get_samsung_spl(chroot_dir_value),
+            board_conf._get_samsung_bootloader(chroot_dir_value),
             "boot_disk")
         expected = [
             '%s dd if=chroot_dir/%s/SPL of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.OrigenConfig.samsung_bl1_start),
+                         board_conf.samsung_bl1_start),
             '%s dd if=chroot_dir/%s/uboot of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.OrigenConfig.samsung_bl2_start)]
+                         board_conf.samsung_bl2_start)]
         self.assertEqual(expected, fixture.mock.commands_executed)
 
     def test_install_origen_quad_u_boot(self):
         fixture = self._mock_Popen()
-        bootloader_flavor = boards.OrigenQuadConfig.bootloader_flavor
-        self.useFixture(MockSomethingFixture(
-            boards.OrigenQuadConfig, '_get_samsung_spl',
-            classmethod(lambda cls, chroot_dir: "%s/%s/SPL" % (
-                chroot_dir, bootloader_flavor))))
-        self.useFixture(MockSomethingFixture(
-            boards.OrigenQuadConfig, '_get_samsung_bootloader',
-            classmethod(lambda cls, chroot_dir: "%s/%s/uboot" % (
-                chroot_dir, bootloader_flavor))))
-        boards.OrigenQuadConfig.hardwarepack_handler = (
-            TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        boards.OrigenQuadConfig.hardwarepack_handler.get_format = (
-            lambda: '1.0')
+        board_conf, bootloader_flavor, chroot_dir_value = \
+            self._set_up_board_config('origen_quad')
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
                                              lambda file: 1))
-        boards.OrigenQuadConfig.install_samsung_boot_loader(
-            boards.OrigenQuadConfig._get_samsung_spl("chroot_dir"),
-            boards.OrigenQuadConfig._get_samsung_bootloader("chroot_dir"),
+        board_conf.install_samsung_boot_loader(
+            board_conf._get_samsung_spl(chroot_dir_value),
+            board_conf._get_samsung_bootloader(chroot_dir_value),
             "boot_disk")
         expected = [
             '%s dd if=chroot_dir/%s/SPL of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.OrigenQuadConfig.samsung_bl1_start),
+                         board_conf.samsung_bl1_start),
             '%s dd if=chroot_dir/%s/uboot of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.OrigenQuadConfig.samsung_bl2_start)]
+                         board_conf.samsung_bl2_start)]
         self.assertEqual(expected, fixture.mock.commands_executed)
 
     def test_install_arndale_u_boot(self):
         fixture = self._mock_Popen()
-        bootloader_flavor = boards.ArndaleConfig.bootloader_flavor
-        self.useFixture(MockSomethingFixture(
-            boards.ArndaleConfig, '_get_samsung_spl',
-            classmethod(lambda cls, chroot_dir: "%s/%s/SPL" % (
-                chroot_dir, bootloader_flavor))))
-        self.useFixture(MockSomethingFixture(
-            boards.ArndaleConfig, '_get_samsung_bootloader',
-            classmethod(lambda cls, chroot_dir: "%s/%s/uboot" % (
-                chroot_dir, bootloader_flavor))))
-        boards.ArndaleConfig.hardwarepack_handler = (
-            TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
-        boards.ArndaleConfig.hardwarepack_handler.get_format = (
-            lambda: '1.0')
+        board_conf, bootloader_flavor, chroot_dir_value = \
+            self._set_up_board_config('arndale')
         self.useFixture(MockSomethingFixture(os.path, 'getsize',
             lambda file: 1))
-        boards.ArndaleConfig.install_samsung_boot_loader(
-            boards.ArndaleConfig._get_samsung_spl("chroot_dir"),
-            boards.ArndaleConfig._get_samsung_bootloader("chroot_dir"),
+        board_conf.install_samsung_boot_loader(
+            board_conf._get_samsung_spl(chroot_dir_value),
+            board_conf._get_samsung_bootloader(chroot_dir_value),
             "boot_disk")
         expected = [
             '%s dd if=chroot_dir/%s/SPL of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.ArndaleConfig.samsung_bl1_start),
+                         board_conf.samsung_bl1_start),
             '%s dd if=chroot_dir/%s/uboot of=boot_disk bs=512 conv=notrunc '
             'seek=%d' % (sudo_args, bootloader_flavor,
-                         boards.ArndaleConfig.samsung_bl2_start)]
+                         board_conf.samsung_bl2_start)]
         self.assertEqual(expected, fixture.mock.commands_executed)
 
     def test_get_plain_boot_script_contents(self):
@@ -2544,77 +2462,77 @@
         flavorx = 'flavorX'
         flavorxy = 'flavorXY'
 
-        class config(boards.BoardConfig):
-            kernel_flavors = [flavorx, flavorxy]
-        for f in reversed(config.kernel_flavors):
+        board_conf = BoardConfig()
+        board_conf.kernel_flavors = [flavorx, flavorxy]
+        for f in reversed(board_conf.kernel_flavors):
             kfile = os.path.join(tempdir, 'vmlinuz-1-%s' % f)
             ifile = os.path.join(tempdir, 'initrd.img-1-%s' % f)
             open(kfile, "w").close()
             open(ifile, "w").close()
         self.assertEqual(
-            (kfile, ifile, None), config._get_kflavor_files(tempdir))
+            (kfile, ifile, None), board_conf._get_kflavor_files(tempdir))
 
     def test_get_dt_kflavor_files_more_specific(self):
         tempdir = self.useFixture(CreateTempDirFixture()).tempdir
         flavorx = 'flavorX'
         flavorxy = 'flavorXY'
 
-        class config(boards.BoardConfig):
-            kernel_flavors = [flavorx, flavorxy]
-            dtb_name = 'board_name.dtb'
-        for f in reversed(config.kernel_flavors):
+        board_conf = BoardConfig()
+        board_conf.kernel_flavors = [flavorx, flavorxy]
+        board_conf.dtb_name = 'board_name.dtb'
+        for f in reversed(board_conf.kernel_flavors):
             kfile = os.path.join(tempdir, 'vmlinuz-1-%s' % f)
             ifile = os.path.join(tempdir, 'initrd.img-1-%s' % f)
             dt = os.path.join(tempdir, 'dt-1-%s' % f)
             os.mkdir(dt)
-            dfile = os.path.join(dt, config.dtb_name)
+            dfile = os.path.join(dt, board_conf.dtb_name)
             open(kfile, "w").close()
             open(ifile, "w").close()
             open(dfile, "w").close()
         self.assertEqual(
-            (kfile, ifile, dfile), config._get_kflavor_files(tempdir))
+            (kfile, ifile, dfile), board_conf._get_kflavor_files(tempdir))
 
     def test_get_kflavor_files_later_in_flavors(self):
         tempdir = self.useFixture(CreateTempDirFixture()).tempdir
         flavor1 = 'flavorXY'
         flavor2 = 'flavorAA'
 
-        class config(boards.BoardConfig):
-            kernel_flavors = [flavor1, flavor2]
+        board_conf = BoardConfig()
+        board_conf.kernel_flavors = [flavor1, flavor2]
         kfile = os.path.join(tempdir, 'vmlinuz-1-%s' % flavor1)
         ifile = os.path.join(tempdir, 'initrd.img-1-%s' % flavor1)
         open(kfile, "w").close()
         open(ifile, "w").close()
         self.assertEqual(
-            (kfile, ifile, None), config._get_kflavor_files(tempdir))
+            (kfile, ifile, None), board_conf._get_kflavor_files(tempdir))
 
     def test_get_dt_kflavor_files_later_in_flavors(self):
         tempdir = self.useFixture(CreateTempDirFixture()).tempdir
         flavor1 = 'flavorXY'
         flavor2 = 'flavorAA'
 
-        class config(boards.BoardConfig):
-            kernel_flavors = [flavor1, flavor2]
-            dtb_name = 'board_name.dtb'
+        board_conf = BoardConfig()
+        board_conf.kernel_flavors = [flavor1, flavor2]
+        board_conf.dtb_name = 'board_name.dtb'
         kfile = os.path.join(tempdir, 'vmlinuz-1-%s' % flavor1)
         ifile = os.path.join(tempdir, 'initrd.img-1-%s' % flavor1)
         dt = os.path.join(tempdir, 'dt-1-%s' % flavor1)
         os.mkdir(dt)
-        dfile = os.path.join(dt, config.dtb_name)
+        dfile = os.path.join(dt, board_conf.dtb_name)
         open(kfile, "w").close()
         open(ifile, "w").close()
         open(dfile, "w").close()
         self.assertEqual(
-            (kfile, ifile, dfile), config._get_kflavor_files(tempdir))
+            (kfile, ifile, dfile), board_conf._get_kflavor_files(tempdir))
 
     def test_get_kflavor_files_raises_when_no_match(self):
         tempdir = self.useFixture(CreateTempDirFixture()).tempdir
         flavor1 = 'flavorXY'
         flavor2 = 'flavorAA'
 
-        class config(boards.BoardConfig):
-            kernel_flavors = [flavor1, flavor2]
-        self.assertRaises(ValueError, config._get_kflavor_files, tempdir)
+        board_conf = BoardConfig()
+        board_conf.kernel_flavors = [flavor1, flavor2]
+        self.assertRaises(ValueError, board_conf._get_kflavor_files, tempdir)
 
     def test_get_file_matching_no_files_found(self):
         self.assertEqual(
@@ -2647,8 +2565,6 @@
         # Stub time.sleep() as create_partitions() use that.
         self.orig_sleep = time.sleep
         time.sleep = lambda s: None
-        boards = linaro_image_tools.media_create.boards
-        boards.BoardConfig.hwpack_format = '1.0'
 
     def tearDown(self):
         super(TestCreatePartitions, self).tearDown()
@@ -2659,7 +2575,9 @@
         popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
 
-        create_partitions(boards.Mx5Config, self.media, HEADS, SECTORS, '')
+        board_conf = boards.Mx5Config()
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        create_partitions(board_conf, self.media, HEADS, SECTORS, '')
 
         self.assertEqual(
             ['%s parted -s %s mklabel msdos' % (sudo_args, self.media.path),
@@ -2680,8 +2598,9 @@
         popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
 
-        create_partitions(
-            board_configs['smdkv310'], self.media, HEADS, SECTORS, '')
+        board_conf = get_board_config('smdkv310')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        create_partitions(board_conf, self.media, HEADS, SECTORS, '')
 
         self.assertEqual(
             ['%s parted -s %s mklabel msdos' % (sudo_args, self.media.path),
@@ -2701,8 +2620,9 @@
         popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
 
-        create_partitions(
-            board_configs['origen'], self.media, HEADS, SECTORS, '')
+        board_conf = get_board_config('origen')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        create_partitions(board_conf, self.media, HEADS, SECTORS, '')
 
         self.assertEqual(
             ['%s parted -s %s mklabel msdos' % (sudo_args, self.media.path),
@@ -2722,8 +2642,10 @@
         popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
 
+        board_conf = get_board_config('origen_quad')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
         create_partitions(
-            board_configs['origen_quad'], self.media, HEADS, SECTORS, '')
+            board_conf, self.media, HEADS, SECTORS, '')
 
         self.assertEqual(
             ['%s parted -s %s mklabel msdos' % (sudo_args, self.media.path),
@@ -2743,8 +2665,10 @@
         popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
 
+        board_conf = get_board_config('arndale')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
         create_partitions(
-            board_configs['arndale'], self.media, HEADS, SECTORS, '')
+            board_conf, self.media, HEADS, SECTORS, '')
 
         self.assertEqual(
             ['%s parted -s %s mklabel msdos' % (sudo_args, self.media.path),
@@ -2763,8 +2687,9 @@
         popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
 
-        create_partitions(
-            board_configs['beagle'], self.media, HEADS, SECTORS, '')
+        board_conf = get_board_config('beagle')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        create_partitions(board_conf, self.media, HEADS, SECTORS, '')
 
         self.assertEqual(
             ['%s parted -s %s mklabel msdos' % (sudo_args, self.media.path),
@@ -2782,8 +2707,9 @@
         sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
 
         tmpfile = self.createTempFileAsFixture()
-        create_partitions(
-            board_configs['beagle'], Media(tmpfile), HEADS, SECTORS, '')
+        board_conf = get_board_config('beagle')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+        create_partitions(board_conf, Media(tmpfile), HEADS, SECTORS, '')
 
         # Unlike the test for partitioning of a regular block device, in this
         # case parted was not called as there's no existing partition table
@@ -3017,7 +2943,7 @@
         self.assertEqual(
             ("%s%d" % (tmpfile, 1), "%s%d" % (tmpfile, 2)),
             get_boot_and_root_partitions_for_media(
-                media, board_configs['beagle']))
+                media, get_board_config('beagle')))
 
     def test_get_boot_and_root_partitions_for_media_mx5(self):
         self.useFixture(MockSomethingFixture(
@@ -3028,7 +2954,7 @@
         media.is_block_device = True
         self.assertEqual(
             ("%s%d" % (tmpfile, 2), "%s%d" % (tmpfile, 3)),
-            get_boot_and_root_partitions_for_media(media, boards.Mx5Config))
+            get_boot_and_root_partitions_for_media(media, boards.Mx5Config()))
 
     def _create_qemu_img_with_partitions(self, sfdisk_commands, tempfile_size):
         tmpfile = self.createTempFileAsFixture()
@@ -3142,8 +3068,12 @@
         self.useFixture(MockSomethingFixture(
             partitions, 'get_boot_and_root_loopback_devices',
             lambda image: ('/dev/loop99', '/dev/loop98')))
+
+        board_conf = get_board_config('beagle')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+
         bootfs_dev, rootfs_dev = setup_partitions(
-            board_configs['beagle'], Media(tmpfile), '2G', 'boot',
+            board_conf, Media(tmpfile), '2G', 'boot',
             'root', 'ext3', True, True, True)
         self.assertEqual(
              # This is the call that would create a 2 GiB image file.
@@ -3173,8 +3103,12 @@
         # Pretend our tmpfile is a block device.
         media.is_block_device = True
         popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
+
+        board_conf = get_board_config('beagle')
+        board_conf.hwpack_format = HardwarepackHandler.FORMAT_1
+
         bootfs_dev, rootfs_dev = setup_partitions(
-            board_configs['beagle'], media, '2G', 'boot', 'root', 'ext3',
+            board_conf, media, '2G', 'boot', 'root', 'ext3',
             True, True, True)
         self.assertEqual(
             ['%s parted -s %s mklabel msdos' % (sudo_args, tmpfile),
@@ -3200,7 +3134,7 @@
             mock_get_udisks_device_path))
 
         tmpfile = self.createTempFileAsFixture()
-        partition = board_configs['beagle'].mmc_part_offset
+        partition = get_board_config('beagle').mmc_part_offset
 
         self.useFixture(MockSomethingFixture(
             glob, 'glob',
@@ -3243,7 +3177,7 @@
             mock_get_udisks_device_file))
 
         tmpfile = self.createTempFileAsFixture()
-        partition = board_configs['beagle'].mmc_part_offset
+        partition = get_board_config('beagle').mmc_part_offset
 
         self.useFixture(MockSomethingFixture(
             glob, 'glob',
@@ -3328,14 +3262,12 @@
         self.saved_args = args
 
     def prepare_config(self, config):
-        class c(config):
-            pass
-
-        self.config = c
+        self.config = config
         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.config.hardwarepack_handler.get_format = \
+            lambda: HardwarepackHandler.FORMAT_1
         self.popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
         self.useFixture(MockSomethingFixture(
             self.config, 'make_boot_files', self.save_args))
@@ -3351,10 +3283,7 @@
         return None
 
     def prepare_config_v3(self, config):
-        class c(config):
-            pass
-
-        self.config = c
+        self.config = config
         self.config.boot_script = 'boot_script'
         self.config.hardwarepack_handler = \
             TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz')
@@ -3378,21 +3307,21 @@
             'boot_device_or_file', is_live, False, [])
 
     def test_populate_boot_live(self):
-        self.prepare_config(boards.BoardConfig)
+        self.prepare_config(BoardConfig())
         self.call_populate_boot(self.config, is_live=True)
         self.assertEquals(
             self.expected_calls, self.popen_fixture.mock.commands_executed)
         self.assertEquals(self.expected_args_live, self.saved_args)
 
     def test_populate_boot_regular(self):
-        self.prepare_config(boards.BoardConfig)
+        self.prepare_config(BoardConfig())
         self.call_populate_boot(self.config)
         self.assertEquals(
             self.expected_calls, self.popen_fixture.mock.commands_executed)
         self.assertEquals(self.expected_args, self.saved_args)
 
     def test_populate_boot_bootloader_flavor(self):
-        self.prepare_config(boards.BoardConfig)
+        self.prepare_config(BoardConfig())
         self.config.bootloader_flavor = "bootloader_flavor"
         self.call_populate_boot(self.config)
         self.assertEquals(
@@ -3400,7 +3329,7 @@
         self.assertEquals(self.expected_args, self.saved_args)
 
     def test_populate_boot_bootloader_file_in_boot_part(self):
-        self.prepare_config(boards.BoardConfig)
+        self.prepare_config(BoardConfig())
         self.config.bootloader_flavor = "bootloader_flavor"
         self.config.bootloader_file_in_boot_part = True
         self.config.bootloader = "u_boot"
@@ -3414,7 +3343,7 @@
         self.assertEquals(self.expected_args, self.saved_args)
 
     def test_populate_boot_bootloader_file_in_boot_part_false(self):
-        self.prepare_config(boards.BoardConfig)
+        self.prepare_config(BoardConfig())
         self.config.bootloader_flavor = "bootloader_flavor"
         self.config.bootloader_file_in_boot_part = False
         self.call_populate_boot(self.config)
@@ -3424,7 +3353,7 @@
         self.assertEquals(self.expected_args, self.saved_args)
 
     def test_populate_bootloader_copy_files(self):
-        self.prepare_config_v3(boards.BoardConfig)
+        self.prepare_config_v3(BoardConfig())
         self.config.bootloader_flavor = "bootloader_flavor"
         # Test that copy_files works per spec (puts stuff in boot partition)
         # even if bootloader not in_boot_part.
@@ -3444,7 +3373,7 @@
         self.assertEquals(self.expected_args, self.saved_args)
 
     def test_populate_bootloader_copy_files_bootloader_set(self):
-        self.prepare_config_v3(boards.BoardConfig)
+        self.prepare_config_v3(BoardConfig())
         self.config.bootloader_flavor = "bootloader_flavor"
         # Test that copy_files works per spec (puts stuff in boot partition)
         # even if bootloader not in_boot_part.
@@ -3465,7 +3394,7 @@
         self.assertEquals(self.expected_args, self.saved_args)
 
     def test_populate_boot_no_bootloader_flavor(self):
-        self.prepare_config(boards.BoardConfig)
+        self.prepare_config(BoardConfig())
         self.config.bootloader_file_in_boot_part = True
         self.assertRaises(
             AssertionError, self.call_populate_boot, self.config)
@@ -3612,10 +3541,7 @@
         os.makedirs(os.path.join(tempdir, 'etc', 'network'))
         if_path = os.path.join(tempdir, 'etc', 'network', 'interfaces')
 
-        class board_config(boards.BoardConfig):
-            pass
-
-        update_network_interfaces(tempdir, board_config)
+        update_network_interfaces(tempdir, BoardConfig())
         self.assertFalse(os.path.exists(if_path))
 
     def test_update_interfaces_creates_entry(self):
@@ -3626,12 +3552,12 @@
         os.makedirs(os.path.join(tempdir, 'etc', 'network'))
         if_path = os.path.join(tempdir, 'etc', 'network', 'interfaces')
 
-        class board_config(boards.BoardConfig):
-            wired_interfaces = ['eth0']
+        board_conf = BoardConfig()
+        board_conf.wired_interfaces = ['eth0']
 
         expected = 'auto eth0\n' \
             'iface eth0 inet dhcp\n'
-        update_network_interfaces(tempdir, board_config)
+        update_network_interfaces(tempdir, board_conf)
         self.assertEqual(expected, open(if_path).read())
 
     def test_update_interfaces_creates_entries(self):
@@ -3642,14 +3568,14 @@
         os.makedirs(os.path.join(tempdir, 'etc', 'network'))
         if_path = os.path.join(tempdir, 'etc', 'network', 'interfaces')
 
-        class board_config(boards.BoardConfig):
-            wired_interfaces = ['eth0', 'eth1']
-            wireless_interfaces = ['wlan0']
+        board_conf = BoardConfig()
+        board_conf.wired_interfaces = ['eth0', 'eth1']
+        board_conf.wireless_interfaces = ['wlan0']
 
         expected = 'auto %(if)s\n' \
             'iface %(if)s inet dhcp\n'
 
-        update_network_interfaces(tempdir, board_config)
+        update_network_interfaces(tempdir, board_conf)
         self.assertIn(expected % {'if': 'eth1'}, open(if_path).read())
         self.assertIn(expected % {'if': 'eth0'}, open(if_path).read())
         self.assertIn(expected % {'if': 'wlan0'}, open(if_path).read())
@@ -3664,13 +3590,13 @@
         with open(if_path, 'w') as interfaces:
             interfaces.write('Original contents of file.\n')
 
-        class board_config(boards.BoardConfig):
-            wired_interfaces = ['eth0']
+        board_conf = BoardConfig()
+        board_conf.wired_interfaces = ['eth0']
 
         expected = 'Original contents of file.\n' \
             'auto eth0\n' \
             'iface eth0 inet dhcp\n'
-        update_network_interfaces(tempdir, board_config)
+        update_network_interfaces(tempdir, board_conf)
         self.assertEqual(expected, open(if_path).read())
 
     def test_write_data_to_protected_file(self):

=== modified file 'linaro_image_tools/tests/__init__.py'
--- linaro_image_tools/tests/__init__.py	2012-06-07 13:22:47 +0000
+++ linaro_image_tools/tests/__init__.py	2012-12-10 17:32:21 +0000
@@ -1,3 +1,20 @@
+# Copyright (C) 2010, 2011, 2012 Linaro
+#
+# This file is part of Linaro Image Tools.
+#
+# Linaro Image Tools is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Linaro Image Tools is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
 import os
 import unittest
 

=== modified file 'linaro_image_tools/utils.py'
--- linaro_image_tools/utils.py	2012-10-22 06:57:20 +0000
+++ linaro_image_tools/utils.py	2012-12-05 14:54:29 +0000
@@ -346,6 +346,14 @@
                 "--hwpack argument (%s) is not a regular file" % hwpack)
 
 
+def additional_android_option_checks(args):
+    """Checks that some of the args passed to l-a-m-c are valid."""
+    if args.hwpack:
+        if not os.path.isfile(args.hwpack):
+            raise InvalidHwpackFile(
+                "--hwpack argument (%s) is not a regular file" % args.hwpack)
+
+
 def check_required_args(args):
     """Check that the required args are passed."""
     if args.dev is None:

