Merge lp:~mabac/linaro-image-tools/hwpacks-v2-lmc into lp:linaro-image-tools/11.11

Proposed by Mattias Backman
Status: Merged
Merged at revision: 370
Proposed branch: lp:~mabac/linaro-image-tools/hwpacks-v2-lmc
Merge into: lp:linaro-image-tools/11.11
Diff against target: 802 lines (+555/-32)
6 files modified
linaro-hwpack-install (+1/-1)
linaro-media-create (+1/-0)
linaro_image_tools/hwpack/config.py (+10/-8)
linaro_image_tools/hwpack/tests/test_config.py (+9/-6)
linaro_image_tools/media_create/boards.py (+214/-17)
linaro_image_tools/media_create/tests/test_media_create.py (+320/-0)
To merge this branch: bzr merge lp:~mabac/linaro-image-tools/hwpacks-v2-lmc
Reviewer Review Type Date Requested Status
James Westby (community) Approve
Review via email: mp+65669@code.launchpad.net

Description of the change

Hi,

This is the second part of hwpacks v2 format support. It adds the new fields present in hwpack-create to linaro-media-create.

Reading the metadata file and other data from the hwpack tarball is handled by HardwarepackHandler which treats the metadata file as a ConfigParser file (by adding a bogus header to it). I'm thinking that when we do one hwpack per SoC we might use a [main] header and [boardX51] like headers to set board specific information.

The metadata fields are used in BoardConfig.set_metadata(hwpack_file) which sets most fields straight to BoardConfig class fields. Special cases are partition_layout and u-boot.

Partition_layout now decides whether to use fat32 or fat16, still the same partition layout but this will support adding a special partition for the Snowball later.

The u-boot file is unpacked from the tarball into a temp folder if the format is something else than V1 and is available for copying to the boot disc or dd:ing as some boards do. The concatenation of paths to find the file is there as a fallback for the V1 format.

Multiple hwpacks can be passed and l-m-c will bail if any field is set in more than one hwpack, with the exception for the standard ones such as name, architecture, supported etc.

It is tested on my Panda by creating a hwpack using lp:~mabac/+junk/hwpack.natty.linaro-panda and then writing that to the Panda with l-m-c. The board boots and looks happy. ;)

I have yet to find out where these fields goes, they are currently set but unused:
 - mmc_id
 - wired_interfaces
 - wireless_interfaces

Thanks,

Mattias

To post a comment you must log in.
Revision history for this message
Mattias Backman (mabac) wrote :

+ board_config.set_metadata(args.hwpacks[0])

This is a bit odd, yes. If we pass multiple hwpacks, I'm not sure which metadata should be used.

Revision history for this message
James Westby (james-w) wrote :

Hi,

This is pretty small, nice work.

I wonder if using ConfigParser to read the metadata file will do something
odd to the data in some circumstances? Perhaps we should turn off all its
magic?

As for multiple hwpacks, I think it should set with data from all of them
eventually, only using the data where defined, and erroring on overlaps. For
now I think just finding the hwpack with the metadata that we want is good
enough (only one will include a kernel.)

Thanks,

James

Revision history for this message
Mattias Backman (mabac) wrote :

> Hi,
>
> This is pretty small, nice work.
>
> I wonder if using ConfigParser to read the metadata file will do something
> odd to the data in some circumstances? Perhaps we should turn off all its
> magic?

I don't know what magic changes it might do to the data. Is there some type of common conversions that it does? If there's any risk of strange bugs in the future, it might be better to simply tokenize the metadata file at '=' or something.

>
> As for multiple hwpacks, I think it should set with data from all of them
> eventually, only using the data where defined, and erroring on overlaps. For
> now I think just finding the hwpack with the metadata that we want is good
> enough (only one will include a kernel.)

Then I'll go with setting the data from all hwpacks and fail if the same field is set more than once.

Revision history for this message
James Westby (james-w) wrote :

56 + "section. Valid partition layouts are bootfs16_rootfs, " \
57 + "bootfs_rootfs.", config)

Could we make that exception text use the defined_partition_layouts so that it
is never out of date?

160 + assert format == format_string, "Mixing hwpack formats is " \
161 + "not supported!"

Is there a particular reason for that?

This looks good to me though.

Thanks,

James

review: Approve
Revision history for this message
Mattias Backman (mabac) wrote :

On Tue, Jun 28, 2011 at 6:14 PM, James Westby <email address hidden> wrote:
> Review: Approve
> 56      +                "section. Valid partition layouts are bootfs16_rootfs, " \
> 57      +                "bootfs_rootfs.", config)
>
> Could we make that exception text use the defined_partition_layouts so that it
> is never out of date?

Sure, I'll see to that.

>
>
> 160     +                assert format == format_string, "Mixing hwpack formats is " \
> 161     +                    "not supported!"
>
>
> Is there a particular reason for that?

Actually no, and just removing the assertion would work fine, I think.
I was mostly fishing for any opinion on this.

>
> This looks good to me though.

Good. Adding the support for multiple hardwarepacks made the change
quite a lot bigger and a bit ugly. But I guess there will be some
opportunity to tweak that part a bit when I move along to the
remaining bits.

>
> Thanks,
>
> James
>
> --
> https://code.launchpad.net/~mabac/linaro-image-tools/hwpacks-v2-lmc/+merge/65669
> You are the owner of lp:~mabac/linaro-image-tools/hwpacks-v2-lmc.
>

Revision history for this message
James Westby (james-w) wrote :

On Tue, 28 Jun 2011 18:37:23 -0000, Mattias Backman <email address hidden> wrote:
> Actually no, and just removing the assertion would work fine, I think.
> I was mostly fishing for any opinion on this.

I can't see any reason to exclude a 1.0 hwpack being used with a 2.0
hwpack, provided the code doesn't complain about that due to the
defaults.

I've no idea about future formats, but we can exclude those combinations
when we add support for them.

Therefore I don't think there's any need for this assertion.

Thanks,

James

Revision history for this message
Mattias Backman (mabac) wrote :

> On Tue, 28 Jun 2011 18:37:23 -0000, Mattias Backman
> <email address hidden> wrote:
> > Actually no, and just removing the assertion would work fine, I think.
> > I was mostly fishing for any opinion on this.
>
> I can't see any reason to exclude a 1.0 hwpack being used with a 2.0
> hwpack, provided the code doesn't complain about that due to the
> defaults.
>
> I've no idea about future formats, but we can exclude those combinations
> when we add support for them.
>
> Therefore I don't think there's any need for this assertion.

Ok. With the current code, which assumes that the defaults are not to be used for 2.0 hwpacks, the 2.0 hwpack would simply take precedence. However if the 2.0 metadata is not there (perhaps allowed for a pure x11 hwpack?) there would be a problem since I just wipe the defaults if I see a 2.0 hwpack.

Do you think I should allow for the 1.0 defaults to trickle in when in mixed 1.0/2.0 mode, or just decide that in mixed mode, the 2.0 metadata has to be there?

376. By Mattias Backman

Change test to use variable for matching text.

377. By Mattias Backman

Allow mixing hwpack formats and consider metadata format to be the same as the highest format version encountered.

Revision history for this message
James Westby (james-w) wrote :

On Wed, 29 Jun 2011 07:35:50 -0000, Mattias Backman <email address hidden> wrote:
> Ok. With the current code, which assumes that the defaults are not to
> be used for 2.0 hwpacks, the 2.0 hwpack would simply take
> precedence. However if the 2.0 metadata is not there (perhaps allowed
> for a pure x11 hwpack?) there would be a problem since I just wipe the
> defaults if I see a 2.0 hwpack.

Hmm, that does make it trickier.

Could we have it only wipe the data if the 2.0 hwpack contains a single field?

> Do you think I should allow for the 1.0 defaults to trickle in when in
> mixed 1.0/2.0 mode, or just decide that in mixed mode, the 2.0
> metadata has to be there?

It seems overly restrictive to have that, but I don't think it's
important, so we shouldn't spend a lot of time on this.

2.0 is the future, so let's make that work well, and keep the code
maintainable.

If the easiest way to do that is to forbid a mix of 1.0/2.0 then let's
do that.

Thanks,

James

Revision history for this message
Mattias Backman (mabac) wrote :

> On Wed, 29 Jun 2011 07:35:50 -0000, Mattias Backman
> <email address hidden> wrote:
> > Ok. With the current code, which assumes that the defaults are not to
> > be used for 2.0 hwpacks, the 2.0 hwpack would simply take
> > precedence. However if the 2.0 metadata is not there (perhaps allowed
> > for a pure x11 hwpack?) there would be a problem since I just wipe the
> > defaults if I see a 2.0 hwpack.
>
> Hmm, that does make it trickier.
>
> Could we have it only wipe the data if the 2.0 hwpack contains a single field?
>
> > Do you think I should allow for the 1.0 defaults to trickle in when in
> > mixed 1.0/2.0 mode, or just decide that in mixed mode, the 2.0
> > metadata has to be there?
>
> It seems overly restrictive to have that, but I don't think it's
> important, so we shouldn't spend a lot of time on this.
>
> 2.0 is the future, so let's make that work well, and keep the code
> maintainable.
>
> If the easiest way to do that is to forbid a mix of 1.0/2.0 then let's
> do that.

I'll have to sleep on this. I think that we can keep the defaults if there is one or more 1.0 hwpacks supplied and wipe the defaults only there are no 1.0 hwpacks at all. That would mean that eventually when no-one uses 1.0 hwpacks at all anymore, the 2.0 hwpacks need to carry the data.

I think I may have left out making hwpack-create assert that the 2.0 fields should be mandatory in the validate methods.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'linaro-hwpack-install'
2--- linaro-hwpack-install 2011-01-29 16:35:06 +0000
3+++ linaro-hwpack-install 2011-06-29 14:00:56 +0000
4@@ -36,7 +36,7 @@
5 FORCE_YES="no"
6 SOURCES_LIST_FILE="${TEMP_DIR}/sources.list"
7 APT_GET_OPTIONS="Dir::Etc::SourceList=${SOURCES_LIST_FILE}"
8-SUPPORTED_FORMATS="1.0" # A space-separated list of hwpack formats.
9+SUPPORTED_FORMATS="1.0 2.0" # A space-separated list of hwpack formats.
10
11 sudo="sudo"
12 if [ $(id -u) -eq 0 ]; then
13
14=== modified file 'linaro-media-create'
15--- linaro-media-create 2011-06-21 09:16:28 +0000
16+++ linaro-media-create 2011-06-29 14:00:56 +0000
17@@ -104,6 +104,7 @@
18 ROOT_DISK = os.path.join(TMP_DIR, 'root-disc')
19
20 board_config = board_configs[args.board]
21+ board_config.set_metadata(args.hwpacks)
22
23 ensure_required_commands(args)
24
25
26=== modified file 'linaro_image_tools/hwpack/config.py'
27--- linaro_image_tools/hwpack/config.py 2011-06-20 13:46:16 +0000
28+++ linaro_image_tools/hwpack/config.py 2011-06-29 14:00:56 +0000
29@@ -42,7 +42,7 @@
30 SOURCES_ENTRY_KEY = "sources-entry"
31 PACKAGES_KEY = "packages"
32 PACKAGE_REGEX = NAME_REGEX
33- PATH_REGEX = r"[a-z0-9][a-z0-9+\-./]+$"
34+ PATH_REGEX = r"[a-z0-9][a-z0-9+\-./_]+$"
35 ORIGIN_KEY = "origin"
36 MAINTAINER_KEY = "maintainer"
37 ARCHITECTURES_KEY = "architectures"
38@@ -59,6 +59,13 @@
39 MMC_ID_KEY = "mmc_id"
40 FORMAT_KEY = "format"
41
42+ DEFINED_PARTITION_LAYOUTS = [
43+ 'bootfs16_rootfs',
44+ 'bootfs_rootfs',
45+ #'reserved_bootfs_rootfs',
46+ ]
47+
48+
49 def __init__(self, fp):
50 """Create a Config.
51
52@@ -375,17 +382,12 @@
53 pass
54
55 def _validate_partition_layout(self):
56- defined_partition_layouts = [
57- #'bootfs16_rootfs',
58- 'bootfs_rootfs',
59- #'reserved_bootfs_rootfs',
60- ]
61- if self.partition_layout not in defined_partition_layouts:
62+ if self.partition_layout not in self.DEFINED_PARTITION_LAYOUTS:
63 raise HwpackConfigError(
64 "Undefined partition layout %s in the [%s] section. "
65 "Valid partition layouts are %s."
66 % (self.partition_layout, self.MAIN_SECTION,
67- ", ".join(defined_partition_layouts)))
68+ ", ".join(self.DEFINED_PARTITION_LAYOUTS)))
69
70 def _validate_mmc_id(self):
71 mmc_id = self.mmc_id
72
73=== modified file 'linaro_image_tools/hwpack/tests/test_config.py'
74--- linaro_image_tools/hwpack/tests/test_config.py 2011-06-17 12:28:43 +0000
75+++ linaro_image_tools/hwpack/tests/test_config.py 2011-06-29 14:00:56 +0000
76@@ -216,13 +216,16 @@
77 self.assertValidationError("Invalid path: ~~", config)
78
79 def test_validate_partition_layout(self):
80- config = self.get_config(self.valid_start_v2 +
81- "u-boot-package = u-boot-linaro-s5pv310\n" \
82- "u-boot-file = u-boot.bin\n" \
83- "partition_layout = apafs_bananfs\n")
84+ partition_layout = 'apafs_bananfs'
85+ config = self.get_config(self.valid_start_v2 + "u-boot-package = " \
86+ "u-boot-linaro-s5pv310\nu-boot-file = " \
87+ "u-boot.bin\npartition_layout = %s\n" % \
88+ partition_layout)
89 self.assertValidationError(
90- "Undefined partition layout apafs_bananfs in the [hwpack] " \
91- "section. Valid partition layouts are bootfs_rootfs.", config)
92+ "Undefined partition layout %s in the [%s] section. "
93+ "Valid partition layouts are %s."
94+ % (partition_layout, 'hwpack',
95+ ", ".join(config.DEFINED_PARTITION_LAYOUTS)), config)
96
97 def test_validate_wired_interfaces(self):
98 self.assertTrue("XXX What is an invalid interface name?")
99
100=== modified file 'linaro_image_tools/media_create/boards.py'
101--- linaro_image_tools/media_create/boards.py 2011-06-23 15:12:13 +0000
102+++ linaro_image_tools/media_create/boards.py 2011-06-29 14:00:56 +0000
103@@ -31,11 +31,20 @@
104 import tempfile
105 import struct
106 from binascii import crc32
107+import tarfile
108+import ConfigParser
109+import shutil
110
111 from linaro_image_tools import cmd_runner
112
113 from linaro_image_tools.media_create.partitions import SECTOR_SIZE
114
115+from linaro_image_tools.hwpack.hardwarepack_format import (
116+ HardwarePackFormatV1,
117+ HardwarePackFormatV2,
118+)
119+
120+
121 KERNEL_GLOB = 'vmlinuz-*-%(kernel_flavor)s'
122 INITRD_GLOB = 'initrd.img-*-%(kernel_flavor)s'
123 DTB_GLOB = 'dt-*-%(kernel_flavor)s/%(dtb_name)s'
124@@ -129,6 +138,95 @@
125 return self.getter(cls)
126
127
128+class HardwarepackHandler(object):
129+ metadata_filename = 'metadata'
130+ format_filename = 'FORMAT'
131+ main_section = 'main'
132+ hwpack_tarfiles = []
133+ tempdir = None
134+
135+ def __init__(self, hwpacks):
136+ self.hwpacks = hwpacks
137+ self.hwpack_tarfiles = []
138+
139+ class FakeSecHead(object):
140+ """ Add a fake section header to the metadata file.
141+
142+ This is done so we can use ConfigParser to parse the file.
143+ """
144+ def __init__(self, fp):
145+ self.fp = fp
146+ self.sechead = '[%s]\n' % HardwarepackHandler.main_section
147+
148+ def readline(self):
149+ if self.sechead:
150+ try:
151+ return self.sechead
152+ finally:
153+ self.sechead = None
154+ else:
155+ return self.fp.readline()
156+
157+ def __enter__(self):
158+ self.tempdir = tempfile.mkdtemp()
159+ for hwpack in self.hwpacks:
160+ hwpack_tarfile = tarfile.open(hwpack, mode='r:gz')
161+ self.hwpack_tarfiles.append(hwpack_tarfile)
162+ return self
163+
164+ def __exit__(self, type, value, traceback):
165+ for hwpack_tarfile in self.hwpack_tarfiles:
166+ if hwpack_tarfile is not None:
167+ hwpack_tarfile.close()
168+ self.hwpack_tarfiles = []
169+ if self.tempdir is not None and os.path.exists(self.tempdir):
170+ shutil.rmtree(self.tempdir)
171+
172+ def get_field(self, section, field):
173+ data = None
174+ hwpack_with_data = None
175+ for hwpack_tarfile in self.hwpack_tarfiles:
176+ metadata = hwpack_tarfile.extractfile(self.metadata_filename)
177+ # Use RawConfigParser which does not support the magical interpolation
178+ # behavior of ConfigParser so we don't mess up metadata accidentally.
179+ parser = ConfigParser.RawConfigParser()
180+ parser.readfp(self.FakeSecHead(metadata))
181+ try:
182+ new_data = parser.get(section, field)
183+ if new_data is not None:
184+ assert data is None, "The metadata field '%s' is set to " \
185+ "'%s' and new value '%s' is found" % (field, data, new_data)
186+ data = new_data
187+ hwpack_with_data = hwpack_tarfile
188+ except ConfigParser.NoOptionError:
189+ continue
190+ return data, hwpack_with_data
191+
192+ def get_format(self):
193+ format = None
194+ for hwpack_tarfile in self.hwpack_tarfiles:
195+ format_file = hwpack_tarfile.extractfile(self.format_filename)
196+ format_string = format_file.read().strip()
197+ if format_string == '2.0':
198+ # Format is taken from the hwpack of highest format version.
199+ return HardwarePackFormatV2()
200+ else:
201+ format = format_string
202+ if format is None or format == '1.0':
203+ return HardwarePackFormatV1()
204+ else:
205+ raise AssertionError("Format version '%s' is not supported." % \
206+ format_string)
207+
208+ def get_file(self, file_alias):
209+ file_name, hwpack_tarfile = self.get_field(self.main_section,
210+ file_alias)
211+ if file_name is not None:
212+ hwpack_tarfile.extract(file_name, self.tempdir)
213+ file_name = os.path.join(self.tempdir, file_name)
214+ return file_name
215+
216+
217 class BoardConfig(object):
218 """The configuration used when building an image for a board."""
219 # These attributes may not need to be redefined on some subclasses.
220@@ -138,12 +236,14 @@
221 mmc_option = '0:1'
222 mmc_part_offset = 0
223 fat_size = 32
224- extra_serial_opts = ''
225- live_serial_opts = ''
226+ _extra_serial_opts = ''
227+ _live_serial_opts = ''
228 extra_boot_args_options = None
229 supports_writing_to_mmc = True
230
231- # These attributes must be defined on all subclasses.
232+ # These attributes must be defined on all subclasses for backwards
233+ # compatibility with hwpacks v1 format. Hwpacks v2 format allows these to
234+ # be specified in the hwpack metadata.
235 kernel_addr = None
236 initrd_addr = None
237 load_addr = None
238@@ -152,6 +252,71 @@
239 kernel_flavors = None
240 boot_script = None
241 serial_tty = None
242+ wired_interfaces = None
243+ wireless_interfaces = None
244+ mmc_id = None
245+
246+ hardwarepack_handler = None
247+
248+ @classmethod
249+ def get_metadata_field(cls, target, field_name):
250+ """ Return the metadata value for field_name if it can be found.
251+
252+ Also assert that target is None to make sure that no defaults have
253+ come this far by mistake.
254+ """
255+ data, _ = cls.hardwarepack_handler.get_field(
256+ cls.hardwarepack_handler.main_section, field_name)
257+ if data is not None:
258+ assert target is None, "Metadata field '%s' is already set to " \
259+ "'%s'." % (field_name, target)
260+ return data
261+
262+ @classmethod
263+ def set_metadata(cls, hwpacks):
264+ cls.hardwarepack_handler = HardwarepackHandler(hwpacks)
265+ with cls.hardwarepack_handler:
266+ if not cls.hardwarepack_handler.get_format().has_v2_fields:
267+ return
268+
269+ # Clear V1 defaults.
270+ cls.kernel_addr = None
271+ cls.initrd_addr = None
272+ cls.load_addr = None
273+ cls.serial_tty = None
274+ cls.fat_size = None
275+
276+ # Set new values from metadata.
277+ cls.kernel_addr = cls.get_metadata_field(
278+ cls.kernel_addr, 'kernel_addr')
279+ cls.initrd_addr = cls.get_metadata_field(
280+ cls.initrd_addr, 'initrd_addr')
281+ cls.load_addr = cls.get_metadata_field(
282+ cls.load_addr, 'load_addr')
283+ cls.serial_tty = cls.get_metadata_field(
284+ cls.serial_tty, 'serial_tty')
285+ cls.wired_interfaces = cls.get_metadata_field(
286+ cls.wired_interfaces, 'wired_interfaces')
287+ cls.wireless_interfaces = cls.get_metadata_field(
288+ cls.wireless_interfaces, 'wireless_interfaces')
289+ cls.mmc_id = cls.get_metadata_field(
290+ cls.mmc_id, 'mmc_id')
291+
292+ partition_layout = cls.get_metadata_field(cls.fat_size, 'partition_layout')
293+ if partition_layout == 'bootfs_rootfs' or partition_layout is None:
294+ cls.fat_size = 32
295+ elif partition_layout == 'bootfs16_rootfs':
296+ cls.fat_size = 16
297+ else:
298+ raise AssertionError("Unknown partition layout '%s'." % partition_layout)
299+
300+ @classmethod
301+ def get_file(cls, file_alias, default=None):
302+ file_in_hwpack = cls.hardwarepack_handler.get_file(file_alias)
303+ if file_in_hwpack is not None:
304+ return file_in_hwpack
305+ else:
306+ return default
307
308 @classmethod
309 def get_sfdisk_cmd(cls, should_align_boot_part=False):
310@@ -299,10 +464,12 @@
311 if cls.uboot_in_boot_part:
312 assert cls.uboot_flavor is not None, (
313 "uboot_in_boot_part is set but not uboot_flavor")
314- uboot_bin = os.path.join(chroot_dir, 'usr', 'lib', 'u-boot',
315- cls.uboot_flavor, 'u-boot.bin')
316- cmd_runner.run(
317- ['cp', '-v', uboot_bin, boot_disk], as_root=True).wait()
318+ with cls.hardwarepack_handler:
319+ uboot_bin = cls.get_file('u_boot', default=os.path.join(
320+ chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
321+ 'u-boot.bin'))
322+ cmd_runner.run(
323+ ['cp', '-v', uboot_bin, boot_disk], as_root=True).wait()
324
325 cls.make_boot_files(
326 uboot_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
327@@ -471,8 +638,8 @@
328
329 class Ux500Config(BoardConfig):
330 serial_tty = 'ttyAMA2'
331- extra_serial_opts = 'console=tty0 console=%s,115200n8' % serial_tty
332- live_serial_opts = 'serialtty=%s' % serial_tty
333+ _extra_serial_opts = 'console=tty0 console=%s,115200n8'
334+ _live_serial_opts = 'serialtty=%s'
335 kernel_addr = '0x00100000'
336 initrd_addr = '0x08000000'
337 load_addr = '0x00008000'
338@@ -485,6 +652,14 @@
339 'hwmem=48M@302M mem=152M@360M')
340 mmc_option = '1:1'
341
342+ @classproperty
343+ def live_serial_opts(cls):
344+ return cls._live_serial_opts % cls.serial_tty
345+
346+ @classproperty
347+ def extra_serial_opts(cls):
348+ return cls._extra_serial_opts % cls.serial_tty
349+
350 @classmethod
351 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
352 boot_device_or_file, k_img_data, i_img_data,
353@@ -642,12 +817,20 @@
354
355 class Mx5Config(BoardConfig):
356 serial_tty = 'ttymxc0'
357- extra_serial_opts = 'console=tty0 console=%s,115200n8' % serial_tty
358- live_serial_opts = 'serialtty=%s' % serial_tty
359+ _extra_serial_opts = 'console=tty0 console=%s,115200n8'
360+ _live_serial_opts = 'serialtty=%s'
361 boot_script = 'boot.scr'
362 mmc_part_offset = 1
363 mmc_option = '0:2'
364
365+ @classproperty
366+ def live_serial_opts(cls):
367+ return cls._live_serial_opts % cls.serial_tty
368+
369+ @classproperty
370+ def extra_serial_opts(cls):
371+ return cls._extra_serial_opts % cls.serial_tty
372+
373 @classmethod
374 def get_sfdisk_cmd(cls, should_align_boot_part=None):
375 """Return the sfdisk command to partition the media.
376@@ -680,9 +863,11 @@
377 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
378 boot_device_or_file, k_img_data, i_img_data,
379 d_img_data):
380- uboot_file = os.path.join(
381- chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor, 'u-boot.imx')
382- install_mx5_boot_loader(uboot_file, boot_device_or_file)
383+ with cls.hardwarepack_handler:
384+ uboot_file = cls.get_file('u_boot', default=os.path.join(
385+ chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
386+ 'u-boot.imx'))
387+ install_mx5_boot_loader(uboot_file, boot_device_or_file)
388 make_uImage(cls.load_addr, k_img_data, boot_dir)
389 make_uInitrd(i_img_data, boot_dir)
390 make_dtb(d_img_data, boot_dir)
391@@ -730,8 +915,8 @@
392 uboot_flavor = 'ca9x4_ct_vxp'
393 uboot_in_boot_part = True
394 serial_tty = 'ttyAMA0'
395- extra_serial_opts = 'console=tty0 console=%s,38400n8' % serial_tty
396- live_serial_opts = 'serialtty=%s' % serial_tty
397+ _extra_serial_opts = 'console=tty0 console=%s,38400n8'
398+ _live_serial_opts = 'serialtty=%s'
399 kernel_addr = '0x60008000'
400 initrd_addr = '0x81000000'
401 load_addr = kernel_addr
402@@ -741,6 +926,14 @@
403 # only allows for FAT16
404 fat_size = 16
405
406+ @classproperty
407+ def live_serial_opts(cls):
408+ return cls._live_serial_opts % cls.serial_tty
409+
410+ @classproperty
411+ def extra_serial_opts(cls):
412+ return cls._extra_serial_opts % cls.serial_tty
413+
414 @classmethod
415 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
416 boot_device_or_file, k_img_data, i_img_data,
417@@ -751,7 +944,7 @@
418 class SMDKV310Config(BoardConfig):
419 uboot_flavor = 'smdkv310'
420 serial_tty = 'ttySAC1'
421- extra_serial_opts = 'console=%s,115200n8' % serial_tty
422+ _extra_serial_opts = 'console=%s,115200n8'
423 kernel_addr = '0x40007000'
424 initrd_addr = '0x42000000'
425 load_addr = '0x40008000'
426@@ -760,6 +953,10 @@
427 mmc_part_offset = 1
428 mmc_option = '0:2'
429
430+ @classproperty
431+ def extra_serial_opts(cls):
432+ return cls._extra_serial_opts % cls.serial_tty
433+
434 @classmethod
435 def get_sfdisk_cmd(cls, should_align_boot_part=False):
436 # bootloaders partition needs to hold BL1, U-Boot environment, and BL2
437
438=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
439--- linaro_image_tools/media_create/tests/test_media_create.py 2011-06-23 15:12:13 +0000
440+++ linaro_image_tools/media_create/tests/test_media_create.py 2011-06-29 14:00:56 +0000
441@@ -28,7 +28,9 @@
442 import textwrap
443 import time
444 import types
445+import tarfile
446
447+from StringIO import StringIO
448 from testtools import TestCase
449
450 from linaro_image_tools import cmd_runner
451@@ -61,6 +63,8 @@
452 _get_smdk_spl,
453 _get_smdk_uboot,
454 _run_mkimage,
455+ HardwarepackHandler,
456+ BoardConfig,
457 )
458 from linaro_image_tools.media_create.android_boards import (
459 android_board_configs,
460@@ -115,12 +119,321 @@
461 MockSomethingFixture,
462 )
463 from linaro_image_tools.utils import find_command, preferred_tools_dir
464+from linaro_image_tools.hwpack.hardwarepack_format import (
465+ HardwarePackFormatV1,
466+ HardwarePackFormatV2,
467+)
468
469
470 chroot_args = " ".join(cmd_runner.CHROOT_ARGS)
471 sudo_args = " ".join(cmd_runner.SUDO_ARGS)
472
473
474+class TestHardwarepackHandler(TestCaseWithFixtures):
475+ def setUp(self):
476+ super(TestHardwarepackHandler, self).setUp()
477+ self.tar_dir_fixture = CreateTempDirFixture()
478+ self.useFixture(self.tar_dir_fixture)
479+
480+ self.tarball_fixture = CreateTarballFixture(
481+ self.tar_dir_fixture.get_temp_dir())
482+ self.useFixture(self.tarball_fixture)
483+
484+ self.metadata = (
485+ "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\nORIGIN=linaro\n")
486+
487+ def add_to_tarball(self, files, tarball=None):
488+ if tarball is None:
489+ tarball = self.tarball_fixture.get_tarball()
490+ tar_file = tarfile.open(tarball, mode='w:gz')
491+ for filename, data in files:
492+ tarinfo = tarfile.TarInfo(filename)
493+ tarinfo.size = len(data)
494+ tar_file.addfile(tarinfo, StringIO(data))
495+ tar_file.close()
496+ return tarball
497+
498+ def test_get_format_1(self):
499+ data = '1.0'
500+ format = "%s\n" % data
501+ tarball = self.add_to_tarball(
502+ [('FORMAT', format), ('metadata', self.metadata)])
503+ hp = HardwarepackHandler([tarball])
504+ with hp:
505+ self.assertIsInstance(hp.get_format(), HardwarePackFormatV1)
506+
507+ def test_get_format_2(self):
508+ data = '2.0'
509+ format = "%s\n" % data
510+ tarball = self.add_to_tarball(
511+ [('FORMAT', format), ('metadata', self.metadata)])
512+ hp = HardwarepackHandler([tarball])
513+ with hp:
514+ self.assertIsInstance(hp.get_format(), HardwarePackFormatV2)
515+
516+ def test_get_unknown_format_raises(self):
517+ data = '9.9'
518+ format = "%s\n" % data
519+ tarball = self.add_to_tarball(
520+ [('FORMAT', format), ('metadata', self.metadata)])
521+ hp = HardwarepackHandler([tarball])
522+ with hp:
523+ self.assertRaises(AssertionError, hp.get_format)
524+
525+ def test_higher_format_sticks(self):
526+ format1 = "%s\n" % '1.0'
527+ format2 = "%s\n" % '2.0'
528+ tarball1 = self.add_to_tarball(
529+ [('FORMAT', format1), ('metadata', self.metadata)],
530+ tarball=self.tarball_fixture.get_tarball())
531+ tarball_fixture2 = CreateTarballFixture(
532+ self.tar_dir_fixture.get_temp_dir(), reldir='tarfile2',
533+ filename='secondtarball.tar.gz')
534+ self.useFixture(tarball_fixture2)
535+ tarball2 = self.add_to_tarball(
536+ [('FORMAT', format2), ('metadata', self.metadata)],
537+ tarball=tarball_fixture2.get_tarball())
538+ hp = HardwarepackHandler([tarball2, tarball1])
539+ with hp:
540+ self.assertIsInstance(hp.get_format(), HardwarePackFormatV2)
541+
542+ def test_identical_formats_ok(self):
543+ format1 = "%s\n" % '2.0'
544+ format2 = "%s\n" % '2.0'
545+ tarball1 = self.add_to_tarball(
546+ [('FORMAT', format1), ('metadata', self.metadata)],
547+ tarball=self.tarball_fixture.get_tarball())
548+ tarball_fixture2 = CreateTarballFixture(
549+ self.tar_dir_fixture.get_temp_dir(), reldir='tarfile2',
550+ filename='secondtarball.tar.gz')
551+ self.useFixture(tarball_fixture2)
552+ tarball2 = self.add_to_tarball(
553+ [('FORMAT', format2), ('metadata', self.metadata)],
554+ tarball=tarball_fixture2.get_tarball())
555+ hp = HardwarepackHandler([tarball1, tarball2])
556+ with hp:
557+ self.assertIsInstance(hp.get_format(), HardwarePackFormatV2)
558+
559+ def test_get_metadata(self):
560+ data = 'data to test'
561+ metadata = self.metadata + "TEST=%s\n" % data
562+ tarball = self.add_to_tarball(
563+ [('metadata', metadata)])
564+ hp = HardwarepackHandler([tarball])
565+ with hp:
566+ test_data, _ = hp.get_field(hp.main_section, 'test')
567+ self.assertEqual(test_data, data)
568+
569+ def test_preserves_formatters(self):
570+ data = '%s%d'
571+ metadata = self.metadata + "TEST=%s\n" % data
572+ tarball = self.add_to_tarball(
573+ [('metadata', metadata)])
574+ hp = HardwarepackHandler([tarball])
575+ with hp:
576+ test_data, _ = hp.get_field(hp.main_section, 'test')
577+ self.assertEqual(test_data, data)
578+
579+ def test_creates_tempdir(self):
580+ tarball = self.add_to_tarball(
581+ [('metadata', self.metadata)])
582+ hp = HardwarepackHandler([tarball])
583+ with hp:
584+ self.assertTrue(os.path.exists(hp.tempdir))
585+
586+ def test_tempfiles_are_removed(self):
587+ tempdir = None
588+ tarball = self.add_to_tarball(
589+ [('metadata', self.metadata)])
590+ hp = HardwarepackHandler([tarball])
591+ with hp:
592+ tempdir = hp.tempdir
593+ self.assertFalse(os.path.exists(tempdir))
594+
595+ def test_get_file(self):
596+ data = 'test file contents\n'
597+ metadata_file = 'TESTFILE'
598+ file_in_archive = 'testfile'
599+ metadata = self.metadata + "%s=%s\n" % (metadata_file, file_in_archive)
600+ tarball = self.add_to_tarball(
601+ [('metadata', metadata),
602+ (file_in_archive, data)])
603+ hp = HardwarepackHandler([tarball])
604+ with hp:
605+ test_file = hp.get_file(metadata_file)
606+ self.assertEquals(data, open(test_file, 'r').read())
607+
608+
609+class TestSetMetadata(TestCaseWithFixtures):
610+
611+ class MockHardwarepackHandler(HardwarepackHandler):
612+ metadata_dict = {}
613+
614+ def __enter__(self):
615+ return self
616+
617+ def get_field(self, section, field):
618+ try:
619+ return self.metadata_dict[field], None
620+ except:
621+ return None, None
622+
623+ def get_format(self):
624+ return HardwarePackFormatV2()
625+
626+ def get_file(self, file_alias):
627+ return None
628+
629+ def test_does_not_set_if_old_format(self):
630+ self.useFixture(MockSomethingFixture(
631+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
632+ self.MockHardwarepackHandler))
633+
634+ class config(BoardConfig):
635+ pass
636+ config.set_metadata('ahwpack.tar.gz')
637+ self.assertEquals(None, config.kernel_addr)
638+
639+ def test_sets_kernel_addr(self):
640+ self.useFixture(MockSomethingFixture(
641+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
642+ self.MockHardwarepackHandler))
643+ field_to_test = 'kernel_addr'
644+ data_to_set = '0x8123ABCD'
645+ self.MockHardwarepackHandler.metadata_dict = {
646+ field_to_test: data_to_set,
647+ }
648+ class config(BoardConfig):
649+ pass
650+ config.set_metadata('ahwpack.tar.gz')
651+ self.assertEquals(data_to_set, config.kernel_addr)
652+
653+ def test_sets_initrd_addr(self):
654+ self.useFixture(MockSomethingFixture(
655+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
656+ self.MockHardwarepackHandler))
657+ field_to_test = 'initrd_addr'
658+ data_to_set = '0x8123ABCD'
659+ self.MockHardwarepackHandler.metadata_dict = {
660+ field_to_test: data_to_set,
661+ }
662+ class config(BoardConfig):
663+ pass
664+ config.set_metadata('ahwpack.tar.gz')
665+ self.assertEquals(data_to_set, config.initrd_addr)
666+
667+ def test_sets_load_addr(self):
668+ self.useFixture(MockSomethingFixture(
669+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
670+ self.MockHardwarepackHandler))
671+ field_to_test = 'load_addr'
672+ data_to_set = '0x8123ABCD'
673+ self.MockHardwarepackHandler.metadata_dict = {
674+ field_to_test: data_to_set,
675+ }
676+ class config(BoardConfig):
677+ pass
678+ config.set_metadata('ahwpack.tar.gz')
679+ self.assertEquals(data_to_set, config.load_addr)
680+
681+ def test_sets_serial_tty(self):
682+ self.useFixture(MockSomethingFixture(
683+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
684+ self.MockHardwarepackHandler))
685+ field_to_test = 'serial_tty'
686+ data_to_set = 'ttyAA'
687+ self.MockHardwarepackHandler.metadata_dict = {
688+ field_to_test: data_to_set,
689+ }
690+ class config(BoardConfig):
691+ pass
692+ config.set_metadata('ahwpack.tar.gz')
693+ self.assertEquals(data_to_set, config.serial_tty)
694+
695+ def test_sets_wired_interfaces(self):
696+ self.useFixture(MockSomethingFixture(
697+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
698+ self.MockHardwarepackHandler))
699+ field_to_test = 'wired_interfaces'
700+ data_to_set = 'eth0 eth1'
701+ self.MockHardwarepackHandler.metadata_dict = {
702+ field_to_test: data_to_set,
703+ }
704+ class config(BoardConfig):
705+ pass
706+ config.set_metadata('ahwpack.tar.gz')
707+ self.assertEquals(data_to_set, config.wired_interfaces)
708+
709+ def test_sets_wireless_interfaces(self):
710+ self.useFixture(MockSomethingFixture(
711+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
712+ self.MockHardwarepackHandler))
713+ field_to_test = 'wireless_interfaces'
714+ data_to_set = 'wlan0 wl1'
715+ self.MockHardwarepackHandler.metadata_dict = {
716+ field_to_test: data_to_set,
717+ }
718+ class config(BoardConfig):
719+ pass
720+ config.set_metadata('ahwpack.tar.gz')
721+ self.assertEquals(data_to_set, config.wireless_interfaces)
722+
723+ def test_sets_mmc_id(self):
724+ self.useFixture(MockSomethingFixture(
725+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
726+ self.MockHardwarepackHandler))
727+ field_to_test = 'mmc_id'
728+ data_to_set = '1'
729+ self.MockHardwarepackHandler.metadata_dict = {
730+ field_to_test: data_to_set,
731+ }
732+ class config(BoardConfig):
733+ pass
734+ config.set_metadata('ahwpack.tar.gz')
735+ self.assertEquals(data_to_set, config.mmc_id)
736+
737+ def test_sets_partition_layout_32(self):
738+ self.useFixture(MockSomethingFixture(
739+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
740+ self.MockHardwarepackHandler))
741+ field_to_test = 'partition_layout'
742+ data_to_set = 'bootfs_rootfs'
743+ self.MockHardwarepackHandler.metadata_dict = {
744+ field_to_test: data_to_set,
745+ }
746+ class config(BoardConfig):
747+ pass
748+ config.set_metadata('ahwpack.tar.gz')
749+ self.assertEquals(32, config.fat_size)
750+
751+ def test_sets_partition_layout_16(self):
752+ self.useFixture(MockSomethingFixture(
753+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
754+ self.MockHardwarepackHandler))
755+ field_to_test = 'partition_layout'
756+ data_to_set = 'bootfs16_rootfs'
757+ self.MockHardwarepackHandler.metadata_dict = {
758+ field_to_test: data_to_set,
759+ }
760+ class config(BoardConfig):
761+ pass
762+ config.set_metadata('ahwpack.tar.gz')
763+ self.assertEquals(16, config.fat_size)
764+
765+ def test_sets_partition_layout_raises(self):
766+ self.useFixture(MockSomethingFixture(
767+ linaro_image_tools.media_create.boards, 'HardwarepackHandler',
768+ self.MockHardwarepackHandler))
769+ field_to_test = 'partition_layout'
770+ data_to_set = 'bootfs_bogus_rootfs'
771+ self.MockHardwarepackHandler.metadata_dict = {
772+ field_to_test: data_to_set,
773+ }
774+ class config(BoardConfig):
775+ pass
776+ self.assertRaises(AssertionError, config.set_metadata, 'ahwpack.tar.gz')
777+
778+
779 class TestGetMLOFile(TestCaseWithFixtures):
780
781 def test_mlo_from_new_xloader(self):
782@@ -255,6 +568,10 @@
783 def test_mx5_steps(self):
784 class SomeMx5Config(boards.Mx5Config):
785 uboot_flavor = 'uboot_flavor'
786+ SomeMx5Config.hardwarepack_handler = (
787+ TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
788+ SomeMx5Config.hardwarepack_handler.get_format = (
789+ lambda: HardwarePackFormatV1())
790 self.make_boot_files(SomeMx5Config)
791 expected = [
792 'install_mx5_boot_loader', 'make_uImage', 'make_uInitrd',
793@@ -1252,6 +1569,9 @@
794
795 self.config = c
796 self.config.boot_script = 'boot_script'
797+ self.config.hardwarepack_handler = \
798+ TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz')
799+ self.config.hardwarepack_handler.get_format = lambda: HardwarePackFormatV1()
800 self.popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
801 self.useFixture(MockSomethingFixture(
802 self.config, 'make_boot_files', self.save_args))

Subscribers

People subscribed via source and target branches