Merge lp:~mabac/linaro-image-tools/hwpacks-v2-lmc into lp:linaro-image-tools/11.11
- hwpacks-v2-lmc
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby (community) | Approve | ||
Review via email: mp+65669@code.launchpad.net |
Commit message
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-
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.
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
Mattias Backman (mabac) wrote : | # |
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
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.
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_
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
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_
> 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:/
> You are the owner of lp:~mabac/linaro-image-tools/hwpacks-v2-lmc.
>
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
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.
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
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
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)) |
+ 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.