=== modified file 'linaro_image_tools/media_create/android_boards.py'
--- linaro_image_tools/media_create/android_boards.py	2012-02-21 07:57:57 +0000
+++ linaro_image_tools/media_create/android_boards.py	2012-02-21 08:01:08 +0000
@@ -37,6 +37,7 @@
 from linaro_image_tools.media_create.boards import (
     align_up,
     align_partition,
+    classproperty,
     make_boot_script,
     install_mx5_boot_loader,
     )
@@ -238,6 +239,36 @@
         return '%s,%s,0xDA\n%s' % (
             loader_start, loader_len, command)
 
+    @classmethod
+    def populate_raw_partition(cls, 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)
+        assert os.path.exists(config_files_dir), (
+            "You need to unpack the Snowball startupfiles to the directory "
+            "'startupfiles' in your current working directory. See "
+            "igloocommunity.org for more information.")
+        # We copy the u-boot files from the unpacked boot.tar.bz2
+        # and put it with the startfiles.
+        boot_files = ['u-boot.bin']
+        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(
+            media, boot_dir)
+
+    @classmethod
+    def snowball_config(cls, 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):
+        # 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 = (

=== modified file 'linaro_image_tools/media_create/boards.py'
--- linaro_image_tools/media_create/boards.py	2012-02-16 10:25:22 +0000
+++ linaro_image_tools/media_create/boards.py	2012-02-21 07:52:13 +0000
@@ -820,6 +820,13 @@
         # Override in subclass if needed
         pass
 
+    @classmethod
+    def snowball_config(cls, chroot_dir):
+        # Override in subclasses where applicable
+        raise NotImplementedError(
+            "snowball_config() must only be called on BoardConfigs that use the "
+            "Snowball startupfiles.")
+
 
 class OmapConfig(BoardConfig):
     kernel_flavors = ['linaro-omap4', 'linaro-lt-omap', 'linaro-omap', 'omap4']
@@ -1075,21 +1082,36 @@
     @classmethod
     def populate_raw_partition(cls, boot_device_or_file, chroot_dir):
         # Populate created raw partition with TOC and startup files.
-        config_files_path = os.path.join(chroot_dir, 'boot')
         _, toc_filename = tempfile.mkstemp()
-        new_files = cls.get_file_info(chroot_dir)
+        config_files_dir = cls.snowball_config(chroot_dir)
+        new_files = cls.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,
-                                     boot_device_or_file,
-                                     cls.SNOWBALL_LOADER_START_S)
+                                         boot_device_or_file,
+                                         cls.SNOWBALL_LOADER_START_S,
+                                         cls.delete_startupfiles)
         cls.delete_file(toc_filename)
-        cls.delete_file(os.path.join(config_files_path,
-                                     cls.snowball_startup_files_config))
+        if cls.delete_startupfiles:
+            cls.delete_file(os.path.join(config_files_dir,
+                                         cls.snowball_startup_files_config))
+
+    @classmethod
+    def snowball_config(cls, chroot_dir):        
+        # We will find the startupfiles in the target boot partition.
+        return os.path.join(chroot_dir, 'boot')
+
+    @classproperty
+    def delete_startupfiles(cls):
+        # 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,
-                                     boot_device_or_file, start_sector):
+                                     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. '''
@@ -1107,7 +1129,8 @@
             else:
                 seek_sectors = start_sector + file['offset'] / SECTOR_SIZE
                 _dd(filename, boot_device_or_file, seek=seek_sectors)
-            cls.delete_file(filename)
+            if delete_startupfiles:
+                cls.delete_file(filename)
 
     @classmethod
     def delete_file(cls, file_path):
@@ -1138,14 +1161,14 @@
             f.write(data)
 
     @classmethod
-    def get_file_info(cls, chroot_dir):
+    def get_file_info(cls, 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
         files = []
-        bin_dir = os.path.join(chroot_dir, 'boot')
-        with open(os.path.join(bin_dir, cls.snowball_startup_files_config),
+        with open(os.path.join(config_files_dir,
+                               cls.snowball_startup_files_config),
                   'r') as info_file:
             for line in info_file:
                 file_data = line.split()
@@ -1158,7 +1181,7 @@
                     filename = os.path.join(chroot_dir,
                                             file_data[1].lstrip('/'))
                 else:
-                    filename = os.path.join(bin_dir, file_data[1])
+                    filename = os.path.join(config_files_dir, file_data[1])
                 assert os.path.exists(filename), "File %s does not exist, " \
                     "please check the startfiles config file." % file_data[1]
                 address = long(file_data[3], 16)

=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
--- linaro_image_tools/media_create/tests/test_media_create.py	2012-02-20 18:32:21 +0000
+++ linaro_image_tools/media_create/tests/test_media_create.py	2012-02-21 08:01:08 +0000
@@ -65,6 +65,7 @@
     )
 from linaro_image_tools.media_create.android_boards import (
     android_board_configs,
+    AndroidSnowballEmmcConfig,
     )
 from linaro_image_tools.media_create.chroot_utils import (
     copy_file,
@@ -667,10 +668,19 @@
         super(TestSnowballBootFiles, self).setUp()
         self.tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
         self.temp_bootdir_path = os.path.join(self.tempdir, 'boot')
+        self.temp_configdir_path = os.path.join(self.tempdir, 'startfiles')
         if not os.path.exists(self.temp_bootdir_path):
             os.makedirs(self.temp_bootdir_path)
+        if not os.path.exists(self.temp_configdir_path):
+            os.makedirs(self.temp_configdir_path)
 
     def setupFiles(self):
+        return self.create_test_files(self.temp_bootdir_path)
+
+    def setupAndroidFiles(self):
+        return self.create_test_files(self.temp_configdir_path)
+
+    def create_test_files(self, path):
         ''' Adds some files in the temp dir that the tested function
             can use as input:
             * A config file, which the tested function reads to
@@ -687,8 +697,8 @@
                     ('NORMAL', 'u-boot.bin', 0, 0xBA0000, '9'),
                     ('UBOOT_ENV', 'u-boot-env.bin', 0, 0x00C1F000, '10')]
         # Create a config file
-        cfg_file = os.path.join(self.temp_bootdir_path,
-        boards.SnowballEmmcConfig.snowball_startup_files_config)
+        cfg_file = os.path.join(
+            path, boards.SnowballEmmcConfig.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
@@ -700,7 +710,7 @@
         # Define dummy binary files, containing nothing but their own
         # section names.
         for line in src_data:
-            with open(os.path.join(self.temp_bootdir_path, line[1]), 'w') as f:
+            with open(os.path.join(path, line[1]), 'w') as f:
                 f.write(line[0])
         #define the expected values read from the config file
         expected = []
@@ -711,7 +721,7 @@
                 len('PWR_MGT'), len('NORMAL'), len('UBOOT_ENV')]
         i = 0
         for line in src_data:
-            filename = os.path.join(self.temp_bootdir_path, line[1])
+            filename = os.path.join(path, line[1])
             expected.append({'section_name': line[0],
                              'filename': filename,
                              'align': int(line[2]),
@@ -731,7 +741,7 @@
                                                0xBA0000, '9'))
         with open(os.path.join(self.temp_bootdir_path, uboot_file), 'w') as f:
             file_info = boards.SnowballEmmcConfig.get_file_info(
-                self.tempdir)
+                self.tempdir, self.temp_bootdir_path)
         self.assertEquals(file_info[0]['filename'],
                           os.path.join(self.temp_bootdir_path, uboot_file))
 
@@ -747,7 +757,7 @@
                                                0xBA0000, '9'))
         with open(uboot_file, 'w') as f:
             file_info = boards.SnowballEmmcConfig.get_file_info(
-                self.tempdir)
+                self.tempdir, self.temp_bootdir_path)
         self.assertEquals(file_info[0]['filename'], uboot_file)
 
     def test_get_file_info_raises(self):
@@ -758,7 +768,7 @@
                 f.write('%s %s %i %#x %s\n' % ('NORMAL', 'u-boot.bin', 0,
                                                0xBA0000, '9'))
         self.assertRaises(AssertionError, boards.SnowballEmmcConfig.get_file_info,
-                          self.tempdir)
+                          self.tempdir, self.temp_bootdir_path)
 
     def test_file_name_size(self):
         ''' Test using a to large toc file '''
@@ -776,7 +786,7 @@
             toc_filename, files, "boot_device_or_file",
             boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S)
 
-    def test_install_snowball_boot_loader_toc(self):
+    def test_install_snowball_boot_loader_toc_dont_delete(self):
         fixture = self.useFixture(MockCmdRunnerPopenFixture())
         toc_filename = self.createTempFileAsFixture()
         files = self.setupFiles()
@@ -789,6 +799,33 @@
             boards.SnowballEmmcConfig.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' \
+            ' bs=1 conv=notrunc seek=131588'
+            % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/mem_init.bin of=boot_device_or_file bs=512' \
+            ' conv=notrunc seek=3072' % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/power_management.bin of=boot_device_or_file bs=512' \
+            ' conv=notrunc seek=3200' % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/u-boot.bin of=boot_device_or_file bs=512' \
+            ' conv=notrunc seek=24064' % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/u-boot-env.bin of=boot_device_or_file bs=512'
+            ' conv=notrunc seek=25080' % (sudo_args, self.temp_bootdir_path)]
+
+        self.assertEqual(expected, fixture.mock.commands_executed)
+
+    def test_install_snowball_boot_loader_toc_delete(self):
+        fixture = self.useFixture(MockCmdRunnerPopenFixture())
+        toc_filename = self.createTempFileAsFixture()
+        files = self.setupFiles()
+        boards.SnowballEmmcConfig.install_snowball_boot_loader(toc_filename,
+            files, "boot_device_or_file",
+            boards.SnowballEmmcConfig.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),
+            '%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,
             self.temp_bootdir_path),
             '%s dd if=%s/boot_image_x-loader.bin of=boot_device_or_file' \
@@ -812,6 +849,33 @@
 
         self.assertEqual(expected, fixture.mock.commands_executed)
 
+    def test_install_snowball_boot_loader_toc_android(self):
+        fixture = self.useFixture(MockCmdRunnerPopenFixture())
+        toc_filename = self.createTempFileAsFixture()
+        files = self.setupFiles()
+        AndroidSnowballEmmcConfig.install_snowball_boot_loader(
+            toc_filename, files, "boot_device_or_file",
+            AndroidSnowballEmmcConfig.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),
+            '%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' \
+            ' bs=1 conv=notrunc seek=131588'
+            % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/mem_init.bin of=boot_device_or_file bs=512' \
+            ' conv=notrunc seek=3072' % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/power_management.bin of=boot_device_or_file bs=512' \
+            ' conv=notrunc seek=3200' % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/u-boot.bin of=boot_device_or_file bs=512' \
+            ' conv=notrunc seek=24064' % (sudo_args, self.temp_bootdir_path),
+            '%s dd if=%s/u-boot-env.bin of=boot_device_or_file bs=512'
+            ' conv=notrunc seek=25080' % (sudo_args, self.temp_bootdir_path)]
+
+        self.assertEqual(expected, fixture.mock.commands_executed)
+
     def test_snowball_make_boot_files(self):
         fixture = self.useFixture(MockCmdRunnerPopenFixture())
         self.useFixture(MockSomethingFixture(tempfile, 'mkstemp',
@@ -868,12 +932,12 @@
         '''When the files cannot be read, an IOError should be raised'''
         self.assertRaises(IOError,
                           boards.SnowballEmmcConfig.get_file_info,
-                          self.tempdir)
+                          self.tempdir, self.temp_bootdir_path)
 
     def test_normal_case(self):
         expected = self.setupFiles()
         actual = boards.SnowballEmmcConfig.get_file_info(
-            self.tempdir)
+            self.tempdir, self.temp_bootdir_path)
         self.assertEquals(expected, actual)
 
 
@@ -1026,6 +1090,204 @@
             'make_dtb', 'make_boot_script', 'make_boot_ini']
         self.assertEqual(expected, self.funcs_calls)
 
+class TestPopulateRawPartition(TestCaseWithFixtures):
+
+    def setUp(self):
+        super(TestPopulateRawPartition, self).setUp()
+        self.funcs_calls = []
+        self.mock_all_boards_funcs()
+
+    def mock_all_boards_funcs(self):
+        """Mock functions of boards module with a call tracer."""
+
+        def mock_func_creator(name):
+            return lambda *args, **kwargs: self.funcs_calls.append(name)
+
+        for name in dir(boards):
+            attr = getattr(boards, name)
+            if type(attr) == types.FunctionType:
+                self.useFixture(MockSomethingFixture(
+                    linaro_image_tools.media_create.boards, name,
+                    mock_func_creator(name)))
+
+    def populate_raw_partition(self, config):
+        config.populate_raw_partition('', '')
+
+    def test_snowball_config_raises(self):
+        self.assertRaises(NotImplementedError,
+                          boards.SnowballSdConfig.snowball_config, '')
+
+    def test_beagle_raw(self):
+        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)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_snowball_sd_raw(self):
+        self.populate_raw_partition(boards.SnowballSdConfig)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_snowball_emmc_raw(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.SnowballEmmcConfig,
+                'get_file_info',
+                mock_func_creator('get_file_info')))
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards.SnowballEmmcConfig,
+                'create_toc',
+                mock_func_creator('create_toc')))
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards.SnowballEmmcConfig,
+                'install_snowball_boot_loader',
+                mock_func_creator('install_snowball_boot_loader')))
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards.SnowballEmmcConfig,
+                'delete_file',
+                mock_func_creator('delete_file')))
+        self.populate_raw_partition(boards.SnowballEmmcConfig)
+        expected = ['get_file_info', 'create_toc',
+                    'install_snowball_boot_loader', 'delete_file',
+                    'delete_file']
+        # Test that we run the Snowball populate_raw_partition() and
+        # delete both the toc and startfiles.
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_smdkv310_raw(self):
+        self.useFixture(MockSomethingFixture(os.path, 'getsize',
+                                             lambda file: 1))
+
+        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)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_origen_raw(self):
+        self.useFixture(MockSomethingFixture(os.path, 'getsize',
+                                             lambda file: 1))
+
+        self.populate_raw_partition(boards.OrigenConfig)
+        expected = ['_dd', '_dd', '_dd']
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_vexpress_a9_raw(self):
+        self.populate_raw_partition(boards.VexpressA9Config)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
+
+class TestPopulateRawPartitionAndroid(TestCaseWithFixtures):
+
+    def setUp(self):
+        super(TestPopulateRawPartitionAndroid, self).setUp()
+        self.funcs_calls = []
+
+    def populate_raw_partition(self, config):
+        config.populate_raw_partition('', '')
+
+    def test_beagle_raw(self):
+        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)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_snowball_sd_raw(self):
+        self.populate_raw_partition(android_boards.AndroidSnowballSdConfig)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_snowball_emmc_raw(self):
+        def mock_func_creator(name):
+            return classmethod(
+                lambda *args, **kwargs: self.funcs_calls.append(name))
+
+        fixture = MockCmdRunnerPopenFixture()
+        self.useFixture(fixture)
+        expected_commands = ['sudo -E cp boot/u-boot.bin ./startupfiles']
+
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.android_boards.AndroidSnowballEmmcConfig,
+                'get_file_info',
+                mock_func_creator('get_file_info')))
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.android_boards.AndroidSnowballEmmcConfig,
+                'create_toc',
+                mock_func_creator('create_toc')))
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.android_boards.AndroidSnowballEmmcConfig,
+                'install_snowball_boot_loader',
+                mock_func_creator('install_snowball_boot_loader')))
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.android_boards.AndroidSnowballEmmcConfig,
+                'delete_file',
+                mock_func_creator('delete_file')))
+        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.
+        self.assertEqual(expected_commands, fixture.mock.commands_executed)
+        # Test that we run the Snowball populate_raw_partition() and only
+        # delete the toc.
+        self.assertEqual(expected_calls, self.funcs_calls)
+
+    def test_smdkv310_raw(self):
+        fixture = MockCmdRunnerPopenFixture()
+        self.useFixture(fixture)
+        expected_commands = [
+            'sudo -E dd if=/dev/zero of= bs=512 conv=notrunc count=32 seek=33',
+            'sudo -E dd if=boot/u-boot-mmc-spl.bin of= bs=512 conv=notrunc seek=1',
+            'sudo -E dd if=boot/u-boot.bin of= bs=512 conv=notrunc seek=65']
+        self.useFixture(MockSomethingFixture(os.path, 'getsize',
+                                             lambda file: 1))
+
+        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)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_origen_raw(self):
+        fixture = MockCmdRunnerPopenFixture()
+        self.useFixture(fixture)
+        expected_commands = [
+            'sudo -E dd if=/dev/zero of= bs=512 conv=notrunc count=32 seek=33',
+            'sudo -E dd if=boot/u-boot-mmc-spl.bin of= bs=512 conv=notrunc seek=1',
+            'sudo -E dd if=boot/u-boot.bin of= bs=512 conv=notrunc seek=65']
+        self.useFixture(MockSomethingFixture(os.path, 'getsize',
+                                             lambda file: 1))
+
+        self.populate_raw_partition(android_boards.AndroidOrigenConfig)
+        expected = []
+        # Test that we dd the files
+        self.assertEqual(expected_commands, fixture.mock.commands_executed)
+        self.assertEqual(expected, self.funcs_calls)
+
+    def test_vexpress_a9_raw(self):
+        self.populate_raw_partition(android_boards.AndroidVexpressA9Config)
+        expected = []
+        self.assertEqual(expected, self.funcs_calls)
+
 
 class TestAlignPartition(TestCase):
 

