Merge lp:~salgado/linaro-image-tools/bug-789093 into lp:~salgado/linaro-image-tools/trunk

Proposed by Guilherme Salgado
Status: Superseded
Proposed branch: lp:~salgado/linaro-image-tools/bug-789093
Merge into: lp:~salgado/linaro-image-tools/trunk
Diff against target: 4734 lines (+3510/-287)
18 files modified
fetch_image.py (+79/-0)
fetch_image_ui.py (+1714/-0)
linaro-android-media-create (+2/-1)
linaro-hwpack-install (+1/-1)
linaro-image-indexer (+2/-4)
linaro-media-create (+1/-0)
linaro_image_tools/FetchImage.py (+174/-152)
linaro_image_tools/fetch_image_settings.yaml (+4/-0)
linaro_image_tools/hwpack/config.py (+71/-9)
linaro_image_tools/hwpack/hardwarepack.py (+16/-2)
linaro_image_tools/hwpack/tests/test_config.py (+45/-6)
linaro_image_tools/hwpack/tests/test_hardwarepack.py (+27/-0)
linaro_image_tools/media_create/android_boards.py (+64/-4)
linaro_image_tools/media_create/boards.py (+359/-88)
linaro_image_tools/media_create/partitions.py (+21/-9)
linaro_image_tools/media_create/rootfs.py (+15/-1)
linaro_image_tools/media_create/tests/test_media_create.py (+914/-9)
setup.py (+1/-1)
To merge this branch: bzr merge lp:~salgado/linaro-image-tools/bug-789093
Reviewer Review Type Date Requested Status
Linaro Maintainers Pending
Review via email: mp+68248@code.launchpad.net

Description of the change

Make sure rootfs.move_contents() doesn't skip files that are not
world-readable

To post a comment you must log in.
377. By Guilherme Salgado

Make sure rootfs.move_contents() doesn't skip files that are not world-readable

Unmerged revisions

377. By Guilherme Salgado

Make sure rootfs.move_contents() doesn't skip files that are not world-readable

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'fetch_image.py'
--- fetch_image.py 1970-01-01 00:00:00 +0000
+++ fetch_image.py 2011-07-18 14:39:34 +0000
@@ -0,0 +1,79 @@
1#!/usr/bin/env python
2# Copyright (C) 2010, 2011 Linaro
3#
4# Author: James Tunnicliffe <james.tunnicliffe@linaro.org>
5#
6# This file is part of Linaro Image Tools.
7#
8# Linaro Image Tools is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License
10# as published by the Free Software Foundation; either version 2
11# of the License, or (at your option) any later version.
12#
13# Linaro Image Tools is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with Linaro Image Tools; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21# USA.
22
23import sys
24import os
25import linaro_image_tools.FetchImage as FetchImage
26import logging
27
28
29def main():
30 file_handler = FetchImage.FileHandler()
31 config = FetchImage.FetchImageConfig()
32
33 # Unfortunately we need to do a bit of a hack here and look for some
34 # options before performing a full options parse.
35 clean_cache = ("--clean-cache" in sys.argv[1:]
36 or "-x" in sys.argv[1:])
37
38 force_download = ("--force-download" in sys.argv[1:]
39 or "-d" in sys.argv[1:])
40
41 if clean_cache:
42 file_handler.clean_cache()
43
44 # If the settings file and server index need updating, grab them
45 file_handler.update_files_from_server(force_download)
46
47 # Load settings YAML, which defines the parameters we ask for and
48 # acceptable responses from the user
49 config.read_config(file_handler.settings_file)
50
51 # Using the settings that the YAML defines as what we need for a build,
52 # generate a command line parser and parse the command line
53 config.parse_args(sys.argv[1:])
54
55 if config.args['platform'] == "snapshot":
56 config.args['release_or_snapshot'] = "snapshot"
57 else:
58 config.args['release_or_snapshot'] = "release"
59
60 # Using the config we have, look up URLs to download data from in the
61 # server index
62 db = FetchImage.DB(file_handler.index_file)
63
64 image_url, hwpack_url = db.get_image_and_hwpack_urls(config.args)
65
66 if(image_url and hwpack_url):
67
68 tools_dir = os.path.dirname(__file__)
69 if tools_dir == '':
70 tools_dir = None
71
72 file_handler.create_media(image_url, hwpack_url,
73 config.args, tools_dir)
74 else:
75 logging.error(
76 "Unable to find files that match the parameters specified")
77
78if __name__ == '__main__':
79 main()
080
=== added file 'fetch_image_ui.py'
--- fetch_image_ui.py 1970-01-01 00:00:00 +0000
+++ fetch_image_ui.py 2011-07-18 14:39:34 +0000
@@ -0,0 +1,1714 @@
1#!/usr/bin/env python
2# Copyright (C) 2010, 2011 Linaro
3#
4# Author: James Tunnicliffe <james.tunnicliffe@linaro.org>
5#
6# This file is part of Linaro Image Tools.
7#
8# Linaro Image Tools is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License
10# as published by the Free Software Foundation; either version 2
11# of the License, or (at your option) any later version.
12#
13# Linaro Image Tools is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with Linaro Image Tools; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21# USA.
22
23import wx
24import wx.wizard
25import wx.wizard as wiz
26import sys
27import re
28import os
29import linaro_image_tools.FetchImage as FetchImage
30import string
31import unittest
32import operator
33import Queue
34import time
35import datetime
36
37
38def add_button(bind_to,
39 sizer,
40 label,
41 style,
42 select_event,
43 hover_event,
44 unhover_event):
45
46 """Create a radio button with event bindings."""
47 if(style != None):
48 radio_button = wx.RadioButton(bind_to, label=label, style=style)
49 else:
50 radio_button = wx.RadioButton(bind_to, label=label)
51
52 sizer.Add(radio_button, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
53 bind_to.Bind(wx.EVT_RADIOBUTTON, select_event, radio_button)
54 wx.EVT_ENTER_WINDOW(radio_button, hover_event)
55 wx.EVT_LEAVE_WINDOW(radio_button, unhover_event)
56
57 return radio_button
58
59
60class ReleaseOrSnapshotPage(wiz.PyWizardPage):
61 """Ask the user if they want to use a release or a snapshot"""
62
63 def __init__(self, parent, config):
64 wiz.PyWizardPage.__init__(self, parent)
65 self.config = config
66 self.settings = self.config.settings
67 self.sizer = wx.BoxSizer(wx.VERTICAL)
68 self.next = None
69 self.prev = None
70
71 self.sizer.Add(wx.StaticText(self, -1,
72"""This Wizard will write an operating system of your choosing to
73either a disk image or to an MMC card. First we need to know if
74your priority is stability or the latest and greatest features."""))
75
76 self.box1 = wx.BoxSizer(wx.VERTICAL)
77
78 self.button_text = {'release': "I would like to run stable, "
79 "tested software.",
80 'snapshot': "I would like to run untested, but "
81 "more up-to-date software."}
82
83 add_button(self, self.box1, self.button_text['release'],
84 wx.RB_GROUP, self.event_radio_button_select, None, None)
85
86 # Save the setting for the default selected value
87 self.settings['release_or_snapshot'] = "release"
88
89 add_button(self, self.box1, self.button_text['snapshot'], None,
90 self.event_radio_button_select, None, None)
91
92 self.sizer.Add(self.box1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
93
94 self.SetSizerAndFit(self.sizer)
95 self.sizer.Fit(self)
96 self.Move((50, 50))
97
98 def event_radio_button_select(self, event):
99 self.radio_selected = event.GetEventObject().GetLabel()
100 # The radio button can be release, snapshot or "latest snapshot"
101 if(self.radio_selected == self.button_text['release']):
102 self.settings['release_or_snapshot'] = "release"
103 else:
104 self.settings['release_or_snapshot'] = "snapshot"
105
106 def SetNext(self, next):
107 self.next = next
108
109 def GetNext(self):
110 return self.next
111
112
113class AboutMyHardwarePage(wiz.WizardPageSimple):
114 """Ask the user about their hardware. This only asks about the board, not
115 any specific hardware packs because there can be multiple names for the
116 same hardware pack or sometimes a hardware pack is only available in the
117 releases or snapshots repository. We whittle down the choice as we go
118 and the user can chose a hardare pack (if they don't like the default)
119 under advanced options in the Linaro Media Create options
120 page"""
121
122 def __init__(self, parent, config, db, width):
123 wiz.WizardPageSimple.__init__(self, parent)
124 self.settings = config.settings
125 self.db = db
126 self.sizer = wx.BoxSizer(wx.VERTICAL)
127 self.box1 = wx.BoxSizer(wx.VERTICAL)
128 self.box2 = wx.BoxSizer(wx.VERTICAL)
129
130 header = wx.StaticText(self,
131 label="Please select the hardware that you "
132 "would like to build an image for from "
133 "the following list")
134
135 header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
136
137 #--- Hardware Combo Box ---
138 # Make sure that the displayed release is the one set in settings if
139 # no selection is made
140 if "panda" in self.settings['choice']['hardware'].keys():
141 default_hardware = "panda"
142 else:
143 default_hardware = self.settings['choice']['hardware'].keys()[-1]
144
145 self.settings['hardware'] = default_hardware
146 self.settings['compatable_hwpacks'] = (
147 self.settings['choice']['hwpack'][self.settings['hardware']])
148
149 self.cb_hardware = wx.ComboBox(self,
150 value=self.settings['choice']
151 ['hardware']
152 [default_hardware],
153 style=wx.CB_DROPDOWN | wx.CB_READONLY)
154
155 self.Bind(wx.EVT_COMBOBOX,
156 self.event_combo_box_hardware,
157 self.cb_hardware)
158 self.box1.Add(self.cb_hardware, 0,
159 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
160
161 self.sizer.Add(header)
162 self.sizer.Add(self.box1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
163 self.sizer.Add(self.box2, 0, wx.ALIGN_LEFT | wx.ALL, 5)
164 self.SetSizerAndFit(self.sizer)
165 self.sizer.Fit(self)
166 self.Move((50, 50))
167
168 def on_page_changing(self):
169 self.update_hardware_box()
170
171 def update_hardware_box(self):
172 self.cb_hardware.Clear()
173
174 sorted_hardware_names = sorted(self.settings['choice']['hardware']
175 .iteritems(),
176 key=operator.itemgetter(1))
177
178 table = self.settings['release_or_snapshot'] + "_hwpacks"
179
180 for device_name, human_readable_name in sorted_hardware_names:
181 for hwpack in self.settings['choice']['hwpack'][device_name]:
182 if self.db.hardware_is_available_in_table(table, hwpack):
183 self.cb_hardware.Append(human_readable_name, device_name)
184 break
185
186 #--- Event(s) ---
187 def event_combo_box_hardware(self, event):
188 self.settings['hardware'] = (event
189 .GetEventObject()
190 .GetClientData(event.GetSelection())
191 .encode('ascii'))
192
193 self.settings['compatable_hwpacks'] = (
194 self.settings['choice']['hwpack'][self.settings['hardware']])
195 #--- END event(s) ---
196
197
198class SelectStableRelease(wiz.WizardPageSimple):
199 """Ask the user which Linaro release they would like to run."""
200 def __init__(self, parent, config, db, width):
201 wiz.WizardPageSimple.__init__(self, parent)
202 self.settings = config.settings
203 self.db = db
204 self.sizer = wx.BoxSizer(wx.VERTICAL)
205 self.wizard = parent
206
207 header = wx.StaticText(self, label="Please select the stable Linaro "
208 "release you would like to use")
209
210 header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
211
212 self.sizer.Add(header)
213 self.box1 = wx.BoxSizer(wx.VERTICAL)
214
215 platforms = []
216 for key, value in self.settings['choice']['platform'].items():
217 platforms.append(key)
218
219 default_release = self.settings['UI']['translate'][platforms[-1]]
220 self.cb_release = wx.ComboBox(self,
221 value=default_release,
222 style=wx.CB_DROPDOWN | wx.CB_READONLY)
223 self.Bind(wx.EVT_COMBOBOX,
224 self.event_combo_box_release,
225 self.cb_release)
226
227 if(default_release in self.settings['UI']['translate']):
228 default_release = self.settings['UI']['translate'][default_release]
229 self.settings['platform'] = (
230 self.settings['UI']['reverse-translate'][default_release])
231
232 for item in platforms:
233 if(item in self.settings['UI']['translate']):
234 new_item = self.settings['UI']['translate'][item]
235 item = new_item
236
237 self.cb_release.Append(item, item.upper())
238
239 self.cb_build = wx.ComboBox(self,
240 style=wx.CB_DROPDOWN | wx.CB_READONLY)
241 self.Bind(wx.EVT_COMBOBOX, self.event_combo_box_build, self.cb_build)
242
243 self.box1.Add(self.cb_release, 0,
244 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
245 self.box1.Add(self.cb_build, 0,
246 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
247 self.sizer.Add(self.box1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
248 self.SetSizerAndFit(self.sizer)
249 self.sizer.Fit(self)
250 self.Move((50, 50))
251
252 def update_build_box(self):
253 """Depending on what hardware has been chosen, the OS list may be
254 restricted. Filter out anything that is unavailable."""
255 self.cb_build.Clear()
256
257 builds = self.db.get_builds(self.settings['platform'])
258 self.cb_build.SetValue("No build available")
259
260 for build in builds:
261 if(self.db.hardware_is_available_for_platform_build(
262 self.settings['compatable_hwpacks'],
263 self.settings['platform'],
264 build)
265 and self.db.build_is_available_for_platform_image(
266 "release_binaries",
267 self.settings['platform'],
268 self.settings['image'],
269 build)):
270
271 self.cb_build.Append(build)
272 self.cb_build.SetValue(build)
273 self.settings['release_build'] = build
274
275 available_hwpacks = (
276 self.db.get_available_hwpacks_for_hardware_build_plaform(
277 self.settings['compatable_hwpacks'],
278 self.settings['platform'],
279 self.settings['release_build']))
280
281 if len(available_hwpacks):
282 self.settings['hwpack'] = available_hwpacks[0]
283 self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
284 else:
285 self.wizard.FindWindowById(wx.ID_FORWARD).Disable()
286
287 def update_release_and_build_boxes(self):
288 """Depending on what hardware has been chosen, some builds may be
289 unavailable..."""
290 self.cb_release.Clear()
291
292 default_release = None
293 for platform, value in self.settings['choice']['platform'].items():
294 if(self.db.hardware_is_available_for_platform(
295 self.settings['compatable_hwpacks'],
296 platform)
297 and len(self.db.execute_return_list(
298 'select * from release_binaries '
299 'where platform == ? and image == ?',
300 (platform, self.settings['image'])))):
301
302 if(platform in self.settings['UI']['translate']):
303 platform = self.settings['UI']['translate'][platform]
304
305 self.cb_release.Append(platform, platform.upper())
306 if not default_release or default_release < platform:
307 default_release = platform
308
309 self.settings['platform'] = (
310 self.settings['UI']['reverse-translate'][default_release])
311 self.cb_release.SetValue(default_release)
312 self.update_build_box()
313
314 #--- Event(s) ---
315 def event_combo_box_release(self, evt):
316 str = evt.GetString().encode('ascii').lower()
317 if(str in self.settings['UI']['reverse-translate']):
318 str = self.settings['UI']['reverse-translate'][str]
319 self.settings['platform'] = str
320
321 self.update_build_box()
322
323 def event_combo_box_build(self, evt):
324 self.settings['release_build'] = evt.GetString().encode('ascii')
325 #--- END event(s) ---
326
327
328class SelectSnapshot(wiz.WizardPageSimple):
329 """Present the user with a calendar widget and a list of builds available
330 on the selected date so they can chose a snapshot. Filter out days when
331 their chosen hardware does not have an available build."""
332
333 def __init__(self, parent, config, db, width):
334 wiz.WizardPageSimple.__init__(self, parent)
335 self.settings = config.settings
336 self.db = db
337 self.wizard = parent
338 self.width = width
339 self.sizer = wx.BoxSizer(wx.VERTICAL)
340
341 header = wx.StaticText(self,
342 label="Builds are created most days. First "
343 "please select the day on which the "
344 "build you would like to use was built,"
345 " then, if there was more than one "
346 "build that day you will be able to "
347 "select the build number.")
348 header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
349
350 box1 = wx.BoxSizer(wx.VERTICAL)
351 self.sizer.Add(header)
352
353 # Set today as the default build date in settings
354 # (matches the date picker)
355 self.today = wx.DateTime()
356 self.today.SetToCurrent()
357 self.settings['build_date'] = self.today.FormatISODate().encode('ascii')
358
359 dpc = wx.DatePickerCtrl(self, size=(120, -1),
360 style=wx.DP_DEFAULT)
361 self.Bind(wx.EVT_DATE_CHANGED, self.on_date_changed, dpc)
362
363 #--- Build number Combo Box ---
364 # Make sure that the displayed build is the one set in settings if no
365 # selection is made
366 self.settings['build_number'] = 0
367 self.update_build()
368 self.cb_build = wx.ComboBox(self,
369 style=wx.CB_DROPDOWN | wx.CB_READONLY)
370 self.Bind(wx.EVT_COMBOBOX, self.event_combo_box_build, self.cb_build)
371
372 #--- Layout ---
373 # -- Combo boxes for hardware and image selection --
374
375 grid2 = wx.FlexGridSizer(0, 2, 0, 0)
376 grid2.Add(dpc, 0, wx.ALIGN_LEFT | wx.ALL, 5)
377 grid2.Add(self.cb_build, 0, wx.ALIGN_LEFT | wx.ALL, 5)
378
379 box1.Add(grid2, 0, wx.ALIGN_LEFT | wx.ALL, 5)
380
381 self.sizer.Add(box1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
382
383 self.help_text = wx.StaticText(self)
384 self.sizer.Add(self.help_text, 1, wx.EXPAND, 5)
385
386 self.SetSizer(self.sizer)
387 self.sizer.Fit(self)
388 self.Move((50, 50))
389
390 def update_platform(self):
391 build_and_date = self.settings['snapshot_build'].split(":")
392
393 if len(build_and_date) == 2:
394 self.settings['platform'] = (
395 self.db.execute_return_list(
396 "select platform from snapshot_binaries "
397 "where date == ? and build == ?",
398 (build_and_date[0], build_and_date[1])))
399
400 if len(self.settings['platform']) > 0:
401 self.settings['platform'] = self.settings['platform'][0][0]
402
403 def update_build(self):
404 small_date = re.sub('-', '', self.settings['build_date'])
405 self.settings['snapshot_build'] = (small_date
406 + ":"
407 + str(self.settings['build_number']))
408
409 def fill_build_combo_box_for_date(self, date):
410 """Every time a date is chosen, this function should be called. It will
411 check to see if a compatible build is available. If there isn't, it
412 will search for one and provide some help text to tell the user when
413 compatable builds were built."""
414 # Re-populate the build combo box
415
416 self.cb_build.Clear()
417
418 builds = self.db.get_binary_builds_on_day_from_db(
419 self.settings['image'],
420 date,
421 self.settings['compatable_hwpacks'])
422
423 if len(builds):
424 max = 0
425 for item in builds:
426 #Always get a tuple, only interested in the first entry
427 item = item[0]
428 self.cb_build.Append(item, item.upper())
429
430 if item > max:
431 max = item
432
433 self.cb_build.SetValue(max)
434 self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
435 self.help_text.SetLabel("")
436
437 else:
438 self.cb_build.SetValue("No builds available")
439 future_date, past_date = self.db.get_next_prev_day_with_builds(
440 self.settings['image'],
441 date,
442 self.settings['compatable_hwpacks'])
443
444 help_text = None
445
446 if future_date and past_date:
447 help_text = ("There are no builds that match your "
448 "specifications available on the selected date. "
449 "The previous build was on " + past_date +
450 " and the next build was on " + future_date + ".")
451 elif future_date:
452 help_text = ("There are no builds that match your "
453 "specifications available on the selected date. "
454 "The next build was on " + future_date +
455 " and I couldn't find a past build (looked one "
456 "year back from the selected date).")
457 elif past_date:
458 help_text = ("There are no builds that match your "
459 "specifications available on the selected date. "
460 "The previous build was on " + past_date)
461 if date != self.today.FormatISODate().encode('ascii'):
462 help_text += (" and I couldn't find a future build (I "
463 "looked up to one year forward from the "
464 "selected date).")
465 else:
466 help_text = ("I could not find any builds that match your "
467 "specifications close to the selected date (I "
468 "looked forward and back one year from the "
469 "selected date).")
470
471 self.help_text.SetLabel(help_text)
472 self.help_text.Wrap(self.width - 10)
473 self.wizard.FindWindowById(wx.ID_FORWARD).Disable()
474
475 #--- Event(s) ---
476 def on_date_changed(self, evt):
477 self.settings['build_date'] = evt.GetDate().FormatISODate().encode('ascii')
478 self.fill_build_combo_box_for_date(self.settings['build_date'])
479 self.update_build()
480
481 def event_combo_box_build(self, evt):
482 self.settings['build_number'] = evt.GetString().encode('ascii').lower()
483 self.update_build()
484 #--- END event(s) ---
485
486
487class SelectOS(wiz.WizardPageSimple):
488 """Ask the user which OS they would like to run. Filter out any choices
489 that are unavailable due to previous choices."""
490 def __init__(self, parent, config, db, width):
491 wiz.WizardPageSimple.__init__(self, parent)
492 self.settings = config.settings
493 self.wizard = parent
494 self.db = db
495 self.width = width
496 self.sizer = wx.BoxSizer(wx.VERTICAL)
497 self.settings['image'] = None
498
499 header = wx.StaticText(self, label="Please select the operating "
500 "system you would like to run on "
501 "your hardware.")
502 header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
503
504 self.box1 = wx.BoxSizer(wx.VERTICAL)
505 self.sizer.Add(header)
506
507 self.cb_image = wx.ComboBox(self,
508 style=wx.CB_DROPDOWN | wx.CB_READONLY)
509 self.Bind(wx.EVT_COMBOBOX, self.event_combo_box_os, self.cb_image)
510
511 #--- Layout ---
512 # -- Combo boxes for hardware and image selection --
513 self.box1.Add(self.cb_image, 0, wx.ALIGN_LEFT | wx.ALL, 5)
514
515 self.sizer.Add(self.box1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
516
517 self.help_text = wx.StaticText(self)
518 self.sizer.Add(self.help_text, 1, wx.EXPAND, 5)
519
520 self.SetSizer(self.sizer)
521 self.sizer.Fit(self)
522 self.Move((50, 50))
523
524 def get_human_os_name(self, item):
525 """Given an OS name from the database, return a human name (either
526 translated from the YAML settings, or just prettified) and if it is a
527 LEB OS or not"""
528
529 item = re.sub("linaro-", "", item) # Remove any linaro- decoration
530
531 human_name = item
532
533 if item in self.settings['UI']['descriptions']:
534 human_name = self.settings['UI']['descriptions'][item]
535 else:
536 # Make human_name look nicer...
537 human_name = string.capwords(item)
538
539 leb_search = re.search("^LEB:\s*(.*)$", human_name)
540
541 if leb_search:
542 return leb_search.group(1), True
543
544 return human_name, False
545
546 def fill_os_list(self):
547 """Filter the list of OS's from the config file based on the users
548 preferences so all choices in the list are valid (i.e. their hardware
549 is supported for the build they have chosen)."""
550
551 # select unique image from snapshot_binaries/release_binaries to
552 # generate list
553 os_list = None
554 if self.settings['release_or_snapshot'] == "release":
555 os_list = self.db.get_os_list_from('release_binaries')
556 else:
557 os_list = self.db.get_os_list_from('snapshot_binaries')
558
559 self.cb_image.Clear()
560
561 printed_tag = None
562 last_name = None
563 current_image_setting_valid = False
564
565 for state in ["LEB", "other"]:
566 for item in os_list:
567 if item == "old":
568 # Old is a directory that sometimes hangs around,
569 # but isn't one we want to display
570 continue
571
572 # Save the original, untouched image name for use later.
573 # We give it a more human name for display
574 original = item
575 item = re.sub("linaro-", "", item)
576
577 os_hardware_combo_available = (
578 self.db.image_hardware_combo_available(
579 self.settings['release_or_snapshot'],
580 original,
581 self.settings['compatable_hwpacks']))
582
583 if os_hardware_combo_available:
584 human_name, is_LEB = self.get_human_os_name(item)
585
586 if item == self.settings['image']:
587 current_image_setting_valid = True
588
589 if state == "LEB" and is_LEB:
590
591 if printed_tag != state:
592 self.cb_image.Append(
593 "- Linaro Supported Releases -")
594 printed_tag = state
595
596 self.cb_image.Append(human_name, original)
597
598 if self.settings['image'] == None:
599 self.settings['image'] = original
600
601 elif state != "LEB" and not is_LEB:
602 if printed_tag != state:
603 self.cb_image.Append(
604 "- Community Supported Releases -")
605 printed_tag = state
606
607 self.cb_image.Append(human_name, original)
608
609 last_name = original
610
611 if( self.settings['image'] != None
612 and current_image_setting_valid == False):
613 # If we have an image setting, but it doesn't match the OS list, we
614 # have switched OS list. It may be that adding/removing "linaro-"
615 # from the name will get a match.
616
617 if re.search("linaro-", self.settings['image']):
618 test_name = re.sub("linaro-", "", self.settings['image'])
619 else:
620 test_name = "linaro-" + self.settings['image']
621
622 if test_name in os_list:
623 # Success! We have translated the name and can retain the
624 # "old setting"
625 self.settings['image'] = test_name
626 current_image_setting_valid = True
627
628 if( self.settings['image'] == None
629 or current_image_setting_valid == False):
630 # This should only get hit if there are no LEBs available
631 self.settings['image'] = last_name
632
633 assert self.settings['image']
634
635 # Make sure the visible selected value matches the saved setting
636 self.cb_image.SetValue(
637 self.get_human_os_name(self.settings['image'])[0])
638
639 #--- Event(s) ---
640 def event_combo_box_os(self, evt):
641 self.settings['image'] = self.cb_image.GetClientData(
642 evt.GetSelection())
643
644 if self.settings['image']: # Is None for items that aren't an OS
645 self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
646 image = re.sub("linaro-", "", self.settings['image'])
647
648 if image + "::long" in self.settings['UI']['descriptions']:
649 self.help_text.SetLabel(self.settings['UI']
650 ['descriptions']
651 [image + "::long"])
652 else:
653 self.help_text.SetLabel("")
654
655 else: # Have selected help text
656 self.wizard.FindWindowById(wx.ID_FORWARD).Disable()
657 self.help_text.SetLabel("Please select an operating system to run "
658 "on your chosen hardware.")
659
660 self.help_text.Wrap(self.width - 10)
661 #--- END event(s) ---
662
663
664class LMC_settings(wiz.WizardPageSimple):
665 """Present the user with, intially, the choice of writing the file system
666 they are going to have created to a file, or directly to a device. Ask
667 which file/device to write to.
668
669 If writing to a device, the user is asked to tick a box saying that they
670 understand that the device they have chosen will be erased.
671
672 If the user ticks the advanced box, more options are shown."""
673
674 def __init__(self, parent, config, db, width):
675 wiz.WizardPageSimple.__init__(self, parent)
676 self.settings = config.settings
677 self.wizard = parent
678 self.sizer = wx.BoxSizer(wx.VERTICAL)
679 self.yes_use_mmc = False
680 self.db = db
681
682 self.settings['path_selected'] = ""
683
684 header = wx.StaticText(self,
685 label="Media Creation Settings\n\n"
686 "Please select if you would like to write the "
687 "file system I am about to create to a memory "
688 "card, or to a file on the local file system.")
689 header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
690
691 #--- Build some widgets ---
692 #-- Target file system --
693 file_systems = ["ext3", "ext4", "btrfs", "ext2"]
694 default_target = file_systems[0]
695 self.settings['rootfs'] = default_target
696 cb_rootfs = wx.ComboBox(self,
697 value=default_target,
698 style=wx.CB_DROPDOWN | wx.CB_READONLY)
699
700 for item in file_systems:
701 cb_rootfs.Append(item, item.upper())
702
703 self.Bind(wx.EVT_COMBOBOX, self.event_combo_box_rootfs, cb_rootfs)
704
705 #-- Image size spinner
706 self.image_size_spinner = wx.SpinCtrl(self, -1, "")
707 self.Bind(wx.EVT_SPINCTRL,
708 self.event_image_size,
709 self.image_size_spinner)
710
711 #-- Swap size spinner
712 self.swap_size_spinner = wx.SpinCtrl(self, -1, "")
713 self.Bind(wx.EVT_SPINCTRL,
714 self.event_swap_size,
715 self.swap_size_spinner)
716
717 #--- Layout ---
718 self.sizer.Add(header, 0, wx.ALIGN_LEFT | wx.ALL, 5)
719 box1 = wx.BoxSizer(wx.VERTICAL)
720 file_dev_grid = wx.FlexGridSizer(0, 2, 0, 0)
721 box1.Add(file_dev_grid, 0, wx.EXPAND)
722 grid1 = wx.FlexGridSizer(0, 2, 0, 0)
723
724 # self.settings['write_to_file_or_device'] should match the first
725 # button below...
726 self.settings['write_to_file_or_device'] = "file"
727 add_button(self,
728 file_dev_grid,
729 "Write to file",
730 wx.RB_GROUP,
731 self.event_radio_button_select,
732 None, None)
733
734 add_button(self,
735 file_dev_grid,
736 "Write to device",
737 None,
738 self.event_radio_button_select,
739 None, None)
740
741 self.help_text_values = {"device": "Please select a device to write "
742 "the file system to:",
743
744 "file": "Please select a file to write the "
745 "file system to:"}
746
747 self.help_text = wx.StaticText(
748 self,
749 label=self.help_text_values[
750 self.settings['write_to_file_or_device']])
751 self.help_text.Wrap(width - 10)
752
753 #-- File/dev picker --
754 file_browse_button = wx.Button(self, -1, "Browse")
755 file_browse_grid = wx.FlexGridSizer(0, 2, 0, 0)
756 self.file_path_and_name = wx.TextCtrl(self, -1, "", size=(300, -1))
757
758 file_browse_grid.Add(self.file_path_and_name, 0, wx.EXPAND)
759 file_browse_grid.Add(file_browse_button, 0, wx.EXPAND)
760
761 self.Bind(wx.EVT_BUTTON,
762 self.event_open_file_control,
763 file_browse_button)
764
765 self.Bind(wx.EVT_TEXT,
766 self.event_file_path_and_name,
767 self.file_path_and_name)
768
769 box1.Add(self.help_text, 0, wx.ALIGN_LEFT | wx.ALL, 5)
770
771 box1.Add(file_browse_grid, 0, wx.EXPAND)
772
773 cb1 = wx.CheckBox(self, -1, "Show advanced options")
774 self.Bind(wx.EVT_CHECKBOX, self.event_show_advanced_options, cb1)
775 box1.Add(cb1)
776
777 #-- Combo boxes for hardware and image selection --
778 optional_settings_box_title = wx.StaticBox(
779 self,
780 label=" Optional Settings ")
781
782 self.optional_settings_box = wx.StaticBoxSizer(
783 optional_settings_box_title,
784 wx.VERTICAL)
785
786 self.box2 = wx.BoxSizer(wx.VERTICAL)
787
788 self.box2.AddWindow(self.optional_settings_box,
789 0,
790 border=2,
791 flag=wx.ALL | wx.EXPAND)
792
793 grid1.Add(cb_rootfs, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, 5)
794
795 grid1.Add(wx.StaticText(self,
796 label="The root file system of the image"),
797 0,
798 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
799 5)
800
801 # We want to sub-devide the cell, to add another grid sizer...
802 file_size_grid = wx.FlexGridSizer(0, 2, 0, 0)
803
804 grid1.Add(file_size_grid,
805 0,
806 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP)
807
808 # Add a spinner that allows us to type/click a numerical value (defined above)
809 file_size_grid.Add(self.image_size_spinner,
810 0,
811 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
812 5)
813
814 # Add a choice of MB or GB for size input
815 units = ["GB", "MB"]
816 self.size_unit = units[0] # Set the default unit
817 unit_choice = wx.Choice(self, -1, (100, 50), choices=units)
818 self.Bind(wx.EVT_CHOICE, self.event_chose_unit, unit_choice)
819 file_size_grid.Add(unit_choice, 0, wx.ALIGN_RIGHT | wx.TOP, 5)
820
821 # Back out of the extra grid, add some help text
822 grid1.Add(wx.StaticText(
823 self,
824 label="Writing to file only: Image file size"),
825 0,
826 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
827 5)
828
829 # The swap size (MB only)
830 grid1.Add(self.swap_size_spinner,
831 0,
832 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
833 5)
834
835 grid1.Add(wx.StaticText(self, label="Swap file size in MB"),
836 0,
837 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
838 5)
839
840 self.cb_hwpacks = wx.ComboBox(
841 self,
842 value=self.settings['compatable_hwpacks'][0],
843 style=wx.CB_DROPDOWN | wx.CB_READONLY)
844
845 self.Bind(wx.EVT_COMBOBOX,
846 self.event_combo_box_hwpack,
847 self.cb_hwpacks)
848
849 grid1.Add(self.cb_hwpacks,
850 0,
851 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
852 5)
853
854 grid1.Add(wx.StaticText(self, label="Compatible hardware packs"),
855 0,
856 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
857 5)
858
859 self.optional_settings_box.Add(grid1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
860
861 confirm_mmc_usage_title = wx.StaticBox(self, label=" Are you sure? ")
862
863 self.confirm_mmc_usage_box = wx.StaticBoxSizer(confirm_mmc_usage_title,
864 wx.VERTICAL)
865 cb2 = wx.CheckBox(
866 self,
867 -1,
868 "Yes, erase and use the device I have selected above.")
869
870 self.Bind(wx.EVT_CHECKBOX, self.event_use_mmc_tickbox, cb2)
871 self.confirm_mmc_usage_box.Add(cb2)
872
873 self.box3 = wx.BoxSizer(wx.VERTICAL)
874 self.box3.AddWindow(self.confirm_mmc_usage_box,
875 0,
876 border=2,
877 flag=wx.ALL | wx.EXPAND)
878
879 self.sizer.Add(box1, 0, wx.ALIGN_LEFT | wx.ALL, 0)
880 self.sizer.Add(self.box2, 0, wx.ALIGN_LEFT | wx.ALL, 0)
881 self.sizer.Add(self.box3, 0, wx.ALIGN_LEFT | wx.ALL, 0)
882 self.SetSizer(self.sizer)
883 self.sizer.Fit(self)
884 self.Move((50, 50))
885
886 def on_activate(self):
887 self.update_forward_active_and_mmc_confirm_box_visible()
888 self.set_hwpacks_for_hardware()
889
890 def set_hwpacks_for_hardware(self):
891 self.cb_hwpacks.Clear()
892
893 if self.settings['release_or_snapshot'] == "snapshot":
894 self.settings['build'] = self.settings['snapshot_build']
895
896 date_and_build = self.settings['build'].split(":")
897
898 compatable_hwpacks = (
899 self.db.get_available_hwpacks_for_hardware_snapshot_build(
900 self.settings['compatable_hwpacks'],
901 self.settings['platform'],
902 date_and_build[0],
903 date_and_build[1]))
904 else:
905 self.settings['build'] = self.settings['release_build']
906 compatable_hwpacks = (
907 self.db.get_available_hwpacks_for_hardware_build_plaform(
908 self.settings['compatable_hwpacks'],
909 self.settings['platform'],
910 self.settings['build']))
911
912 for hwpack in compatable_hwpacks:
913 self.cb_hwpacks.Append(hwpack)
914
915 self.cb_hwpacks.SetStringSelection(compatable_hwpacks[0])
916 self.settings['hwpack'] = compatable_hwpacks[0]
917
918 def update_forward_active_and_mmc_confirm_box_visible(self):
919 if( self.settings['path_selected']
920 and self.settings['path_selected'] != ""):
921
922 if ( self.settings['write_to_file_or_device'] == "file"
923 or self.settings['write_to_file_or_device'] == "device"
924 and self.yes_use_mmc):
925 self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
926 else:
927 self.wizard.FindWindowById(wx.ID_FORWARD).Disable()
928 else:
929 self.wizard.FindWindowById(wx.ID_FORWARD).Disable()
930
931 if self.settings['write_to_file_or_device'] == "device":
932 self.box3.Show(self.confirm_mmc_usage_box, True)
933 else:
934 self.box3.Hide(self.confirm_mmc_usage_box, True)
935
936 # --- Event Handlers ---
937 def event_open_file_control(self, event):
938 if self.settings['write_to_file_or_device'] == "file":
939
940 dlg = wx.FileDialog(self,
941 message="Save file as ...",
942 defaultDir=os.getcwd(),
943 defaultFile="",
944 style=wx.SAVE)
945
946 elif self.settings['write_to_file_or_device'] == "device":
947 dlg = wx.FileDialog(self,
948 message="Choose a device",
949 defaultDir=os.getcwd(),
950 defaultFile="",
951 style=wx.OPEN | wx.CHANGE_DIR)
952
953 if dlg.ShowModal() == wx.ID_OK:
954 self.settings['path_selected'] = dlg.GetPaths()[0]
955 self.file_path_and_name.SetValue(self.settings['path_selected'])
956
957 dlg.Destroy()
958 self.update_forward_active_and_mmc_confirm_box_visible()
959
960 def event_file_path_and_name(self, event):
961 self.settings['path_selected'] = event.GetString()
962 self.update_forward_active_and_mmc_confirm_box_visible()
963
964 def event_combo_box_hwpack(self, event):
965 self.settings['hwpack'] = event.GetString().encode('ascii')
966
967 def event_combo_box_rootfs(self, evt):
968 self.settings['rootfs'] = evt.GetString().encode('ascii').lower()
969
970 def event_radio_button_select(self, event):
971 """Search the label of the button that has been selected to work out
972 what we are writing to."""
973 setting_search = re.search(
974 "write to (\w+)",
975 event
976 .GetEventObject()
977 .GetLabel()
978 .encode('ascii')
979 .lower())
980
981 assert setting_search
982
983 self.settings['write_to_file_or_device'] = setting_search.group(1)
984
985 self.help_text.SetLabel(
986 self.help_text_values[self.settings['write_to_file_or_device']])
987
988 self.update_forward_active_and_mmc_confirm_box_visible()
989
990 def event_show_advanced_options(self, event):
991 if event.IsChecked():
992 self.box2.Show(self.optional_settings_box, True)
993 else:
994 self.box2.Hide(self.optional_settings_box, True)
995
996 def event_pick_file_path(self, evt):
997 self.settings['path_selected'] = os.path.abspath(evt.GetPath())
998 self.update_forward_active_and_mmc_confirm_box_visible()
999
1000 def update_image_size_setting(self):
1001 if(self.image_size_spinner.GetValue() > 0):
1002 self.settings['image_size'] = (str(self.image_size_spinner
1003 .GetValue())
1004 + self.size_unit[0])
1005 else:
1006 self.settings['image_size'] = None
1007
1008 def event_image_size(self, event):
1009 self.update_image_size_setting()
1010
1011 def event_chose_unit(self, event):
1012 self.size_unit = event.GetString()
1013 self.update_image_size_setting()
1014
1015 def event_swap_size(self, event):
1016 self.settings['swap_file'] = str(self.image_size_spinner.GetValue())
1017
1018 def event_use_mmc_tickbox(self, event):
1019 self.yes_use_mmc = event.IsChecked()
1020 self.update_forward_active_and_mmc_confirm_box_visible()
1021
1022
1023class RunLMC(wiz.WizardPageSimple):
1024 """Present the user with some information about their choices and a button
1025 to start linaro-media-create. The linaro-media-create process is started in
1026 a new thread and important events are communicated back to the UI through a
1027 queue."""
1028
1029 def __init__(self, parent, config, db, width):
1030 wiz.WizardPageSimple.__init__(self, parent)
1031 self.settings = config.settings
1032 self.sizer = wx.BoxSizer(wx.VERTICAL)
1033 self.db = db
1034 self.width = width
1035 self.wizard = parent
1036
1037 header = wx.StaticText(self, label="""Installing...""")
1038 header.Wrap(width - 10) # -10 because boarder below is 5 pixels wide
1039
1040 self.sizer.Add(header)
1041 self.box1 = wx.BoxSizer(wx.VERTICAL)
1042
1043 # We expect to print 4 lines of information, reserve space using blank
1044 # lines.
1045 self.settings_summary_text = wx.StaticText(self, label="\n\n\n\n")
1046 self.settings_summary_text.Wrap(width - 10)
1047
1048 self.box1.Add(self.settings_summary_text, 0, wx.ALIGN_LEFT | wx.ALL, 5)
1049
1050 self.start_button = wx.Button(self, 10, "Start", (20, 20))
1051 self.Bind(wx.EVT_BUTTON, self.start_lmc, self.start_button)
1052
1053 self.start_button.SetToolTipString("Start creating an image, using the"
1054 "above settings.")
1055
1056 self.start_button.SetSize(self.start_button.GetBestSize())
1057 self.box1.Add(self.start_button, 0, wx.ALIGN_LEFT | wx.ALL, 5)
1058
1059 self.download_guage = wx.Gauge(self,
1060 -1,
1061 1000,
1062 size=(self.width * 2 / 3, 25))
1063
1064 self.status_grid = wx.FlexGridSizer(0, 2)
1065
1066 self.status_grid.Add(wx.StaticText(self, label="Downloading files"),
1067 0,
1068 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1069 5)
1070
1071 self.downloading_files_status = wx.StaticText(self, label="")
1072
1073 self.status_grid.Add(self.downloading_files_status,
1074 0,
1075 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1076 5)
1077
1078 self.status_grid.Add(self.download_guage,
1079 0,
1080 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1081 5)
1082
1083 self.downloading_files_info = wx.StaticText(self, label="")
1084
1085 self.status_grid.Add(self.downloading_files_info,
1086 0,
1087 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1088 5)
1089
1090 self.status_grid.Add(wx.StaticText(self, label="Unpacking downloads"),
1091 0,
1092 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1093 5)
1094
1095 self.unpacking_files_status = wx.StaticText(self, label="")
1096
1097 self.status_grid.Add(self.unpacking_files_status,
1098 0,
1099 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1100 5)
1101
1102 self.status_grid.Add(wx.StaticText(self, label="Installing packages"),
1103 0,
1104 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1105 5)
1106
1107 self.installing_packages_status = wx.StaticText(self, label="")
1108
1109 self.status_grid.Add(self.installing_packages_status,
1110 0,
1111 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1112 5)
1113
1114 self.status_grid.Add(wx.StaticText(self, label="Create file system"),
1115 0,
1116 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1117 5)
1118
1119 self.create_file_system_status = wx.StaticText(self, label="")
1120
1121 self.status_grid.Add(self.create_file_system_status,
1122 0,
1123 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1124 5)
1125
1126 self.status_grid.Add(wx.StaticText(self, label="Populate file system"),
1127 0,
1128 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1129 5)
1130
1131 self.populate_file_system_status = wx.StaticText(self, label="")
1132
1133 self.status_grid.Add(self.populate_file_system_status,
1134 0,
1135 wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP,
1136 5)
1137
1138 self.sizer.Add(self.box1, 0, wx.ALIGN_LEFT | wx.ALL, 5)
1139 self.sizer.Add(self.status_grid, 0, wx.ALIGN_LEFT | wx.ALL, 5)
1140 self.SetSizerAndFit(self.sizer)
1141 self.sizer.Fit(self)
1142 self.Move((50, 50))
1143
1144 def on_activate(self):
1145 """Called just before the page is displayed to update the text based on
1146 the users preferences."""
1147
1148 # The build is stored in different forms depending on if we are using a
1149 # release or snapshot but from here on in it is a common value
1150 if self.settings['release_or_snapshot'] == "snapshot":
1151 self.settings['build'] = self.settings['snapshot_build']
1152 else:
1153 self.settings['build'] = self.settings['release_build']
1154
1155 settings_summary = ("Press start to create an image with the "
1156 "following settings:\n")
1157 settings_summary += "Operating System: " + self.settings['image'] + "\n"
1158 settings_summary += "Hardware: " + self.settings['hardware'] + "\n"
1159
1160 # Assumption is that a file may be in a long path, we don't know how
1161 # big the font is and we don't want to allow the path to run off the
1162 # end of the line, so if a file is chosen, just show the file name.
1163 # Devices are (probably) /dev/some_short_name and the user really needs
1164 # to check them, so we show the whole thing.
1165 path = self.settings['path_selected']
1166 if self.settings['write_to_file_or_device'] == "file":
1167 path = self.settings['path_selected'].split(os.sep)[-1]
1168
1169 settings_summary += ( "Writing image to "
1170 + self.settings['write_to_file_or_device']
1171 + " "
1172 + path)
1173
1174 self.settings_summary_text.SetLabel(settings_summary)
1175 self.settings_summary_text.Wrap(self.width - 10)
1176
1177 def start_lmc(self, event):
1178 """Start a thread that runs linaro-media-create and a timer, which
1179 checks for UI updates every 100ms"""
1180
1181 if self.settings['write_to_file_or_device'] == "file":
1182 self.settings['image_file'] = self.settings['path_selected']
1183 elif self.settings['write_to_file_or_device'] == "device":
1184 self.settings['mmc'] = self.settings['path_selected']
1185 else:
1186 assert False, ("self.config.settings['write_to_file_or_device'] "
1187 "was an unexpected value"
1188 + self.settings['write_to_file_or_device'])
1189
1190 image_url, hwpack_url = self.db.get_image_and_hwpack_urls(self.settings)
1191
1192 # Currently the UI is blocked when LMC is running, so grey out the
1193 # buttons to indicate to the user that they won't work!
1194 self.wizard.FindWindowById(wx.ID_BACKWARD).Disable()
1195 self.wizard.FindWindowById(wx.ID_CANCEL).Disable()
1196
1197 if(image_url and hwpack_url):
1198
1199 self.file_handler = FetchImage.FileHandler()
1200
1201 self.timer = wx.Timer(self)
1202 self.Bind(wx.EVT_TIMER, self.timer_ping, self.timer)
1203 self.timer.Start(milliseconds=100, oneShot=True)
1204
1205 tools_dir = os.path.dirname(__file__)
1206 if tools_dir == '':
1207 tools_dir = None
1208
1209 self.start_button.Disable()
1210 self.event_queue = Queue.Queue()
1211 self.lmc_thread = self.file_handler.LinaroMediaCreate(
1212 image_url,
1213 hwpack_url,
1214 self.file_handler,
1215 self.event_queue,
1216 self.settings,
1217 tools_dir)
1218 self.lmc_thread.start()
1219 else:
1220 print >> sys.stderr, ("Unable to find files that match the"
1221 "parameters specified")
1222
1223 def timer_ping(self, event):
1224 """During start_lmc a timer is started to poll for events from
1225 linaro-media-create every 100ms. This is the function which is called
1226 to do that polling."""
1227
1228 while not self.event_queue.empty():
1229 event = self.event_queue.get()
1230
1231 if event[0] == "start":
1232 self.event_start(event[1])
1233
1234 elif event[0] == "end":
1235 self.event_end(event[1])
1236
1237 elif event == "terminate":
1238 # Process complete. Enable next button.
1239 self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
1240 self.populate_file_system_status.SetLabel("Done")
1241 return # Even if queue isn't empty, stop processing it
1242
1243 elif event[0] == "update":
1244 self.event_update(event[1], event[2], event[3])
1245
1246 else:
1247 print >> sys.stderr, "timer_ping: Unhandled event", event
1248
1249 self.timer.Start(milliseconds=50, oneShot=True)
1250
1251 def unsigned_packages_query(self, package_list):
1252 message = ('In order to continue, I need to install some unsigned'
1253 'packages into the image. Is this OK? The packages are:'
1254 '\n\n' + package_list)
1255
1256 dlg = wx.MessageDialog(self,
1257 message,
1258 'Install Unsigned Packages Into Image?',
1259 wx.YES_NO | wx.NO_DEFAULT)
1260
1261 choice = dlg.ShowModal()
1262 dlg.Destroy()
1263
1264 return choice == wx.ID_YES
1265
1266 #--- Event(s) ---
1267 def event_start(self, event):
1268 if event == "download OS":
1269 self.downloading_files_status.SetLabel("Downloading OS")
1270 elif event == "download hwpack":
1271 self.downloading_files_status.SetLabel("Downloading Hardware Pack")
1272 elif event == "unpack":
1273 self.unpacking_files_status.SetLabel("Running")
1274 elif event == "installing packages":
1275 self.installing_packages_status.SetLabel("Running")
1276
1277 elif re.search('^unverified_packages:', event):
1278 # Get rid of event ID and whitespace invariance
1279 packages = " ".join(event.split()[1:])
1280 install_unsigned_packages = self.unsigned_packages_query(packages)
1281
1282 if install_unsigned_packages == False:
1283 self.file_handler.kill_create_media()
1284 sys.exit(1)
1285 else:
1286 self.lmc_thread.send_to_create_process("y")
1287
1288 elif event == "create file system":
1289 self.create_file_system_status.SetLabel("Running")
1290 elif event == "populate file system":
1291 self.populate_file_system_status.SetLabel("Running")
1292 else:
1293 print "Unhandled start event:", event
1294
1295 def event_end(self, event):
1296 if event == "download OS":
1297 self.downloading_files_status.SetLabel("Done (1/2)")
1298 elif event == "download hwpack":
1299 self.downloading_files_status.SetLabel("Done")
1300 elif event == "unpack":
1301 self.unpacking_files_status.SetLabel("Done")
1302 elif event == "installing packages":
1303 self.installing_packages_status.SetLabel("Done")
1304 elif event == "create file system":
1305 self.create_file_system_status.SetLabel("Done")
1306 elif event == "populate file system":
1307 self.populate_file_system_status.SetLabel("Done")
1308 else:
1309 print "Unhhandled end event:", event
1310
1311 def event_update(self, task, update_type, value):
1312 if task == "download":
1313 if update_type == "name":
1314 self.downloading_files_status.SetLabel("Downloading")
1315 self.old_time = time.time()
1316 self.old_bytes_downloaded = 0
1317
1318 elif update_type == "progress":
1319 self.total_bytes_downloaded += value
1320
1321 time_difference = time.time() - self.old_time
1322
1323 if time_difference > 1.0:
1324 self.old_time = time.time()
1325
1326 # More than a second has passed since we calculated data
1327 # rate
1328 speed = ( float( self.total_bytes_downloaded
1329 - self.old_bytes_downloaded)
1330 / time_difference)
1331
1332 self.old_bytes_downloaded = self.total_bytes_downloaded
1333
1334 self.speeds.append(speed)
1335
1336 average_speed = 0
1337 speeds_accumulated = 0
1338 for speed in reversed(self.speeds):
1339 average_speed += speed
1340 speeds_accumulated += 1
1341
1342 if speeds_accumulated == 6:
1343 break # do rolling average of 6 seconds
1344
1345 average_speed /= speeds_accumulated
1346
1347 time_remaining = ( ( self.total_bytes_to_download
1348 - self.total_bytes_downloaded)
1349 / speed)
1350
1351 pretty_time = str(datetime.timedelta(seconds=int(
1352 time_remaining)))
1353
1354 # Following table assumes we don't get past TBps internet
1355 # connections soon :-)
1356 units = ["Bps", "kBps", "MBps", "GBps", "TBps"]
1357 units_index = 0
1358 while speed > 1024:
1359 speed /= 1024
1360 units_index += 1
1361
1362 info = "Downloading at {0:.1f} {1}".format(
1363 speed,
1364 units[units_index])
1365
1366 self.downloading_files_status.SetLabel(info)
1367
1368 info = "{0} remaining".format(
1369 pretty_time)
1370
1371 self.downloading_files_info.SetLabel(info)
1372
1373 self.download_guage.SetValue( 1000
1374 * self.total_bytes_downloaded
1375 / self.total_bytes_to_download)
1376
1377 elif update_type == "total bytes":
1378 self.total_bytes_to_download = value
1379 self.total_bytes_downloaded = 0
1380 self.speeds = [] # keep an array of speeds used to calculate
1381 # the estimated time remaining - by not just using the
1382 # current speed we can stop the ETA bouncing around too much.
1383
1384 def event_combo_box_release(self, evt):
1385 pass
1386
1387 def event_combo_box_build(self, evt):
1388 pass
1389 #--- END event(s) ---
1390
1391
1392class TestDriveWizard(wx.wizard.Wizard):
1393 def __init__(self, title):
1394 wx.wizard.Wizard.__init__(self, None, -1, title, wx.NullBitmap)
1395 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.on_page_changing)
1396 self.done_startup = False
1397
1398 def on_page_changing(self, evt):
1399 'Executed before the page changes.'
1400
1401 if self.done_startup == False:
1402 self.pages['lmc_settings'].box2.Hide(
1403 self.pages['lmc_settings'].optional_settings_box,
1404 True)
1405
1406 self.pages['lmc_settings'].box3.Hide(
1407 self.pages['lmc_settings'].confirm_mmc_usage_box,
1408 True)
1409
1410 self.done_startup = True
1411
1412 page = evt.GetPage()
1413
1414 if evt.GetDirection(): # If going forwards...
1415 # Always enable back button if going forwards
1416 self.wizard.FindWindowById(wx.ID_BACKWARD).Enable()
1417
1418 # If going from a select snapshot or select release page, record
1419 # which we were on so the back button of the next page works
1420 if(self.config.settings['release_or_snapshot'] == "release"):
1421 self.pages['select_os'].SetNext(self.pages['select_release'])
1422 self.pages['select_release'].SetPrev(self.pages['select_os'])
1423
1424 self.pages['select_release'].SetNext(self.pages['lmc_settings'])
1425 self.pages['lmc_settings'].SetPrev(self.pages['select_release'])
1426 else:
1427 self.pages['select_os'].SetNext(self.pages['select_snapshot'])
1428 self.pages['select_snapshot'].SetPrev(self.pages['select_os'])
1429
1430 if(page == self.pages['select_os']):
1431 self.pages['select_snapshot'].fill_build_combo_box_for_date(
1432 self.config.settings['build_date'])
1433
1434 self.pages['select_snapshot'].SetNext(self.pages['lmc_settings'])
1435 self.pages['lmc_settings'].SetPrev(self.pages['select_snapshot'])
1436
1437 if page == self.pages['hardware_details']:
1438 self.pages['select_os'].fill_os_list()
1439
1440 if page == self.pages['release_or_snapshot']:
1441 self.pages['hardware_details'].on_page_changing()
1442
1443 # If about to move into the release selection, make sure the list
1444 # is populated only with releases that are valid with our current
1445 # selection
1446 if( page == self.pages['select_os']
1447 and self.config.settings['release_or_snapshot'] == "release"):
1448 self.pages['select_release'].update_release_and_build_boxes()
1449
1450 if page == self.pages['select_snapshot']:
1451 # Execute when exiting page
1452 self.pages['select_snapshot'].update_platform()
1453
1454 if( page == self.pages['select_snapshot']
1455 or page == self.pages['select_release']):
1456 self.pages['lmc_settings'].on_activate()
1457
1458 if page == self.pages['lmc_settings']:
1459 # Forward stays disabled until LMC has finished running
1460 self.wizard.FindWindowById(wx.ID_FORWARD).Disable()
1461 self.pages['run_lmc'].on_activate()
1462
1463 else: # Always enable the forward button if reversing into a page
1464 self.wizard.FindWindowById(wx.ID_FORWARD).Enable()
1465
1466 def go(self):
1467 file_handler = FetchImage.FileHandler()
1468 self.config = FetchImage.FetchImageConfig()
1469 self.config.settings["force_download"] = False
1470 self.config.settings['compatable_hwpacks'] = ['foo']
1471
1472 # If the settings file and server index need updating, grab them
1473 file_handler.update_files_from_server()
1474
1475 # Load settings YAML, which defines the parameters we ask for and
1476 # acceptable responses from the user
1477 self.config.read_config(file_handler.settings_file)
1478
1479 # Using the config we have, look up URLs to download data from in
1480 # the server index
1481 db = FetchImage.DB(file_handler.index_file)
1482
1483 # Create the wizard and the pages
1484 self.wizard = wiz.Wizard(self, -1, "Linaro Media Builder")
1485
1486 self.pages = {}
1487 self.pages['release_or_snapshot'] = ReleaseOrSnapshotPage(self.wizard,
1488 self.config)
1489 self.wizard.FitToPage(self.pages['release_or_snapshot'])
1490 (width, height) = self.wizard.GetSize()
1491
1492 self.pages['hardware_details'] = AboutMyHardwarePage(self.wizard,
1493 self.config,
1494 db,
1495 width)
1496
1497 self.pages['select_release'] = SelectStableRelease(self.wizard,
1498 self.config,
1499 db,
1500 width)
1501
1502 self.pages['select_snapshot'] = SelectSnapshot(self.wizard,
1503 self.config,
1504 db,
1505 width)
1506
1507 self.pages['select_os'] = SelectOS(self.wizard,
1508 self.config,
1509 db,
1510 width)
1511
1512 self.pages['lmc_settings'] = LMC_settings(self.wizard,
1513 self.config,
1514 db,
1515 width)
1516
1517 self.pages['run_lmc'] = RunLMC(self.wizard,
1518 self.config,
1519 db,
1520 width)
1521
1522 self.pages['release_or_snapshot'].SetNext(
1523 self.pages['hardware_details'])
1524
1525 self.pages['hardware_details'].SetPrev(
1526 self.pages['release_or_snapshot'])
1527
1528 self.pages['hardware_details'].SetNext(self.pages['select_os'])
1529 self.pages['select_os'].SetPrev(self.pages['hardware_details'])
1530 # Select OS goes to select build, which is customised for
1531 # releases or snapshots
1532 self.pages['lmc_settings'].SetNext(self.pages['run_lmc'])
1533 self.pages['run_lmc'].SetPrev(self.pages['lmc_settings'])
1534
1535 for (name, page) in self.pages.items():
1536 self.wizard.GetPageAreaSizer().Add(page)
1537
1538 self.wizard.RunWizard(self.pages['release_or_snapshot'])
1539
1540
1541def run():
1542 """Wrapper around the full wizard. Is encapsulated in its own function to
1543 allow a restart to be performed, as described in __main___, easily"""
1544 app = wx.PySimpleApp() # Start the application
1545 if app:
1546 pass # We don't use this directly. Stop pyflakes complaining!
1547
1548 w = TestDriveWizard('Simple Wizard')
1549 return w.go()
1550
1551
1552class TestURLLookupFunctions(unittest.TestCase):
1553
1554 def setUp(self):
1555 self.file_handler = FetchImage.FileHandler()
1556 self.file_handler.update_files_from_server()
1557 self.config = FetchImage.FetchImageConfig()
1558 self.config.settings["force_download"] = False
1559
1560 # Load settings YAML, which defines the parameters we ask for and
1561 # acceptable responses from the user
1562 self.config.read_config(self.file_handler.settings_file)
1563
1564 # Using the config we have, look up URLs to download data from in the
1565 # server index
1566 self.db = FetchImage.DB(self.file_handler.index_file)
1567
1568 def test_url_lookup(self):
1569 self.settings = self.config.settings
1570 self.settings['release_or_snapshot'] = "snapshot"
1571
1572 #--- Test first with a snapshot build lookup ---
1573 # -- Fix a build date --
1574 # We only need to look up a single snapshot date. Start with today and
1575 # go with the day in the DB, build 0
1576 today = wx.DateTime()
1577 today.SetToCurrent()
1578
1579 # -- Don't iterate through platforms for snapshot --
1580
1581 # -- Select hardware --
1582 for self.settings['hardware'] in (
1583 self.settings['choice']['hardware'].keys()):
1584
1585 compatable_hwpacks = self.settings['choice']['hwpack'][
1586 self.settings['hardware']]
1587
1588 future_date, past_date = self.db.get_next_prev_day_with_builds(
1589 "linaro-alip",
1590 today.FormatISODate().encode('ascii'),
1591 compatable_hwpacks)
1592
1593 if past_date == None:
1594 # Some hardware packs are not available in the snapshot repo,
1595 # so just skip if they aren't
1596 continue
1597
1598 builds = self.db.get_binary_builds_on_day_from_db(
1599 "linaro-alip",
1600 past_date,
1601 compatable_hwpacks)
1602
1603 self.assertTrue(len(builds))
1604 # If the above assert fails, either the DB is empty, or
1605 # db.get_binary_builds_on_day_from_db failed
1606
1607 small_date = re.sub('-', '', past_date)
1608 self.settings['build'] = small_date + ":" + "0"
1609
1610 # -- Iterate through hardware packs --
1611 for self.settings['hwpack'] in compatable_hwpacks:
1612
1613 # If hardware pack is available...
1614 if(self.settings['hwpack']
1615 in self.db.get_hwpacks('snapshot_hwpacks')):
1616
1617 # -- Iterate through images
1618 os_list = self.db.get_os_list_from('snapshot_binaries')
1619
1620 for self.settings['image'] in os_list:
1621 if re.search('old', self.settings['image']):
1622 # Directories with old in the name are of no
1623 # interest to us
1624 continue
1625
1626 # -- Check build which matches these parameters
1627 # (builds that don't match are excluded in UI) --
1628 if( len(self.db.execute_return_list(
1629 'select * from snapshot_hwpacks '
1630 'where hardware == ? '
1631 'and date == ? '
1632 'and build == ?',
1633 (self.settings['hwpack'],
1634 small_date,
1635 "0")))
1636 and len(self.db.execute_return_list(
1637 'select * from snapshot_binaries '
1638 'where image == ? '
1639 'and date == ? '
1640 'and build == ?',
1641 (self.settings['image'],
1642 small_date,
1643 "0")))):
1644
1645 # - Run the function under test! -
1646 image_url, hwpack_url = (
1647 self.db.get_image_and_hwpack_urls(self.settings))
1648
1649 self.assertTrue(image_url)
1650 self.assertTrue(hwpack_url)
1651
1652 #--- Now test release build lookup ---
1653 self.settings['release_or_snapshot'] = "release"
1654 # -- Select hardware --
1655 for self.settings['hardware'] in (
1656 self.settings['choice']['hardware'].keys()):
1657 compatable_hwpacks = (
1658 self.settings['choice']['hwpack'][self.settings['hardware']])
1659
1660 # -- Iterate through hardware packs --
1661 for self.settings['hwpack'] in compatable_hwpacks:
1662
1663 # If hardware pack is available...
1664 if(self.settings['hwpack']
1665 in self.db.get_hwpacks('release_hwpacks')):
1666
1667 # -- Iterate through images
1668 os_list = self.db.get_os_list_from('release_binaries')
1669
1670 for self.settings['image'] in os_list:
1671 if re.search('old', self.settings['image']):
1672 # Directories with old in the name are of no
1673 # interest to us
1674 continue
1675
1676 for platform, ignore in (
1677 self.settings['choice']['platform'].items()):
1678 self.settings['platform'] = platform
1679
1680 # -- Iterate through available builds --
1681 builds = self.db.get_builds(
1682 self.settings['platform'],
1683 self.settings['image'])
1684
1685 for build in builds:
1686 self.settings['build'] = build
1687
1688 # -- Check build which matches these parameters
1689 #(builds that don't match are excluded in UI)--
1690 if( len(self.db.execute_return_list(
1691 'select * from release_hwpacks '
1692 'where platform == ? '
1693 'and hardware == ? '
1694 'and build == ?',
1695 (self.settings['platform'],
1696 self.settings['hwpack'],
1697 self.settings['build'])))
1698 and len(self.db.execute_return_list(
1699 'select * from release_binaries '
1700 'where platform == ? '
1701 'and image == ? '
1702 'and build == ?',
1703 (self.settings['platform'],
1704 self.settings['image'],
1705 self.settings['build'])))):
1706
1707 # - Run the function under test! -
1708 image_url, hwpack_url = (
1709 self.db.get_image_and_hwpack_urls(self.settings))
1710 self.assertTrue(image_url)
1711 self.assertTrue(hwpack_url)
1712
1713if __name__ == '__main__':
1714 run()
01715
=== modified file 'linaro-android-media-create'
--- linaro-android-media-create 2011-05-26 09:16:35 +0000
+++ linaro-android-media-create 2011-07-18 14:39:34 +0000
@@ -133,12 +133,13 @@
133 unpack_android_binary_tarball(args.system, SYSTEM_DIR)133 unpack_android_binary_tarball(args.system, SYSTEM_DIR)
134 unpack_android_binary_tarball(args.userdata, DATA_DIR)134 unpack_android_binary_tarball(args.userdata, DATA_DIR)
135135
136 # Create partitions 136 # Create partitions
137 boot_partition, system_partition, cache_partition, \137 boot_partition, system_partition, cache_partition, \
138 data_partition, sdcard_partition = setup_android_partitions( \138 data_partition, sdcard_partition = setup_android_partitions( \
139 board_config, media, args.image_size, args.boot_label,139 board_config, media, args.image_size, args.boot_label,
140 args.should_create_partitions, args.should_align_boot_part)140 args.should_create_partitions, args.should_align_boot_part)
141141
142 board_config.populate_raw_partition(args.device, BOOT_DIR)
142 populate_partition(BOOT_DIR + "/boot", BOOT_DISK, boot_partition)143 populate_partition(BOOT_DIR + "/boot", BOOT_DISK, boot_partition)
143 board_config.populate_boot_script(boot_partition, BOOT_DISK, args.consoles)144 board_config.populate_boot_script(boot_partition, BOOT_DISK, args.consoles)
144 populate_partition(SYSTEM_DIR + "/system", SYSTEM_DISK, system_partition)145 populate_partition(SYSTEM_DIR + "/system", SYSTEM_DISK, system_partition)
145146
=== modified file 'linaro-hwpack-install'
--- linaro-hwpack-install 2011-01-29 16:35:06 +0000
+++ linaro-hwpack-install 2011-07-18 14:39:34 +0000
@@ -36,7 +36,7 @@
36FORCE_YES="no"36FORCE_YES="no"
37SOURCES_LIST_FILE="${TEMP_DIR}/sources.list"37SOURCES_LIST_FILE="${TEMP_DIR}/sources.list"
38APT_GET_OPTIONS="Dir::Etc::SourceList=${SOURCES_LIST_FILE}"38APT_GET_OPTIONS="Dir::Etc::SourceList=${SOURCES_LIST_FILE}"
39SUPPORTED_FORMATS="1.0" # A space-separated list of hwpack formats.39SUPPORTED_FORMATS="1.0 2.0" # A space-separated list of hwpack formats.
4040
41sudo="sudo"41sudo="sudo"
42if [ $(id -u) -eq 0 ]; then42if [ $(id -u) -eq 0 ]; then
4343
=== renamed file 'linaro_image_tools/index_server.py' => 'linaro-image-indexer'
--- linaro_image_tools/index_server.py 2011-06-17 18:04:47 +0000
+++ linaro-image-indexer 2011-07-18 14:39:34 +0000
@@ -22,10 +22,10 @@
2222
23import os23import os
24import re24import re
25import FetchImage
26import urlparse25import urlparse
27import logging26import logging
28import bz227import bz2
28import linaro_image_tools.FetchImage
2929
30RELEASES_WWW_DOCUMENT_ROOT = "/srv/releases.linaro.org/www/platform/"30RELEASES_WWW_DOCUMENT_ROOT = "/srv/releases.linaro.org/www/platform/"
31RELEASE_URL = "http://releases.linaro.org/platform/"31RELEASE_URL = "http://releases.linaro.org/platform/"
@@ -41,7 +41,7 @@
41 def __init__(self):41 def __init__(self):
42 self.reset()42 self.reset()
43 self.db_file_name = "server_index"43 self.db_file_name = "server_index"
44 self.db = FetchImage.DB(self.db_file_name)44 self.db = linaro_image_tools.FetchImage.DB(self.db_file_name)
4545
46 def crawl(self):46 def crawl(self):
47 self.db.set_url_parse_info(self.url_parse)47 self.db.set_url_parse_info(self.url_parse)
@@ -89,8 +89,6 @@
89 url_chunks_):89 url_chunks_):
90 90
91 if(not id_ in self.url_parse):91 if(not id_ in self.url_parse):
92
93 print base_dir_
94 self.url_parse[id_] = {"base_dir": base_dir_,92 self.url_parse[id_] = {"base_dir": base_dir_,
95 "base_url": base_url_,93 "base_url": base_url_,
96 "url_validator": url_validator_,94 "url_validator": url_validator_,
9795
=== modified file 'linaro-media-create'
--- linaro-media-create 2011-06-21 09:16:28 +0000
+++ linaro-media-create 2011-07-18 14:39:34 +0000
@@ -104,6 +104,7 @@
104 ROOT_DISK = os.path.join(TMP_DIR, 'root-disc')104 ROOT_DISK = os.path.join(TMP_DIR, 'root-disc')
105105
106 board_config = board_configs[args.board]106 board_config = board_configs[args.board]
107 board_config.set_metadata(args.hwpacks)
107108
108 ensure_required_commands(args)109 ensure_required_commands(args)
109110
110111
=== modified file 'linaro_image_tools/FetchImage.py'
--- linaro_image_tools/FetchImage.py 2011-06-17 18:04:47 +0000
+++ linaro_image_tools/FetchImage.py 2011-07-18 14:39:34 +0000
@@ -52,15 +52,6 @@
52 "image-tools",52 "image-tools",
53 "fetch_image")53 "fetch_image")
5454
55 class DummyEventHandler():
56 """Just a sink for events if no event handler is provided to
57 create_media"""
58 def event_start(self, event):
59 pass
60
61 def event_end(self, event):
62 pass
63
64 def has_key_and_evaluates_True(self, dictionary, key):55 def has_key_and_evaluates_True(self, dictionary, key):
65 return bool(key in dictionary and dictionary[key])56 return bool(key in dictionary and dictionary[key])
6657
@@ -72,17 +63,15 @@
72 list.append(setting_name)63 list.append(setting_name)
73 list.append(dictionary[key])64 list.append(dictionary[key])
7465
75 def create_media(self, image_url, hwpack_url, settings, tools_dir,66 def build_lmc_command(self,
76 run_in_gui=False, event_handler=None):67 binary_file,
77 """Create a command line for linaro-media-create based on the settings68 hwpack_file,
78 provided then run linaro-media-create, either in a separate thread69 settings,
79 (GUI mode) or in the current one (CLI mode)."""70 tools_dir,
71 run_in_gui=False):
8072
81 import linaro_image_tools.utils73 import linaro_image_tools.utils
8274
83 if event_handler == None:
84 event_handler = self.DummyEventHandler()
85
86 args = []75 args = []
87 args.append("pkexec")76 args.append("pkexec")
8877
@@ -100,41 +89,6 @@
100 if run_in_gui:89 if run_in_gui:
101 args.append("--nocheck-mmc")90 args.append("--nocheck-mmc")
10291
103 event_handler.event_start("download OS")
104 try:
105 binary_file = self.download(image_url,
106 settings["force_download"],
107 show_wx_progress=run_in_gui,
108 wx_progress_title=
109 "Downloading file 1 of 2")
110 except Exception:
111 # Download error. Hardly matters what, we can't continue.
112 print "Unexpected error:", sys.exc_info()[0]
113 logging.error("Unable to download " + image_url + " - aborting.")
114 event_handler.event_end("download OS")
115
116 if binary_file == None: # User hit cancel when downloading
117 sys.exit(0)
118
119 event_handler.event_start("download hwpack")
120 try:
121 hwpack_file = self.download(hwpack_url,
122 settings["force_download"],
123 show_wx_progress=run_in_gui,
124 wx_progress_title=
125 "Downloading file 2 of 2")
126 except Exception:
127 # Download error. Hardly matters what, we can't continue.
128 print "Unexpected error:", sys.exc_info()[0]
129 logging.error("Unable to download " + hwpack_url + " - aborting.")
130 event_handler.event_end("download hwpack")
131
132 if hwpack_file == None: # User hit cancel when downloading
133 sys.exit(0)
134
135 logging.info("Have downloaded OS binary to", binary_file,
136 "and hardware pack to", hwpack_file)
137
138 if 'rootfs' in settings and settings['rootfs']:92 if 'rootfs' in settings and settings['rootfs']:
139 args.append("--rootfs")93 args.append("--rootfs")
140 args.append(settings['rootfs'])94 args.append(settings['rootfs'])
@@ -157,34 +111,74 @@
157 args.append("--hwpack")111 args.append("--hwpack")
158 args.append(hwpack_file)112 args.append(hwpack_file)
159113
160 logging.info(args)114 logging.info(" ".join(args))
161115
162 if run_in_gui:116 return args
163 self.lmcargs = args117
164 self.event_handler = event_handler118 def create_media(self, image_url, hwpack_url, settings, tools_dir):
165 self.started_lmc = False119 """Create a command line for linaro-media-create based on the settings
166 return120 provided then run linaro-media-create, either in a separate thread
167121 (GUI mode) or in the current one (CLI mode)."""
168 else:122
169 self.create_process = subprocess.Popen(args)123 to_download = [(image_url, "OS"),
170 self.create_process.wait()124 (hwpack_url, "hwpack")]
125 downloaded_files = self.download_files(to_download,
126 settings)
127
128 args = self.build_lmc_command(downloaded_files['OS'],
129 downloaded_files['hwpack'],
130 settings,
131 tools_dir)
132
133 self.create_process = subprocess.Popen(args)
134 self.create_process.wait()
171135
172 class LinaroMediaCreate(threading.Thread):136 class LinaroMediaCreate(threading.Thread):
173 """Thread class for running linaro-media-create"""137 """Thread class for running linaro-media-create"""
174 def __init__(self, event_handler, lmcargs, event_queue):138 def __init__(self,
139 image_url,
140 hwpack_url,
141 file_handler,
142 event_queue,
143 settings,
144 tools_dir):
145
175 threading.Thread.__init__(self)146 threading.Thread.__init__(self)
176 self.event_handler = event_handler147
177 self.lmcargs = lmcargs148 self.image_url = image_url
178 self.event_queue = event_queue149 self.hwpack_url = hwpack_url
150 self.file_handler = file_handler
151 self.event_queue = event_queue
152 self.settings = settings
153 self.tools_dir = tools_dir
179154
180 def run(self):155 def run(self):
181 """Start linaro-media-create and look for lines in the output that:156 """
182 1. Tell us that an event has happened that we can use to update the157 1. Download required files.
183 UI progress.158 2. Build linaro-media-create command
184 2. Tell us that linaro-media-create is asking a question that needs159 3. Start linaro-media-create and look for lines in the output that:
185 to be re-directed to the GUI"""160 1. Tell us that an event has happened that we can use to update
186161 the UI progress.
187 self.create_process = subprocess.Popen(self.lmcargs,162 2. Tell us that linaro-media-create is asking a question that
163 needs to be re-directed to the GUI
164 """
165
166 to_download = [(self.image_url, "OS"),
167 (self.hwpack_url, "hwpack")]
168
169 downloaded_files = self.file_handler.download_files(
170 to_download,
171 self.settings,
172 self.event_queue)
173
174 lmc_command = self.file_handler.build_lmc_command(
175 downloaded_files['OS'],
176 downloaded_files['hwpack'],
177 self.settings,
178 self.tools_dir,
179 True)
180
181 self.create_process = subprocess.Popen(lmc_command,
188 stdin=subprocess.PIPE,182 stdin=subprocess.PIPE,
189 stdout=subprocess.PIPE,183 stdout=subprocess.PIPE,
190 stderr=subprocess.STDOUT)184 stderr=subprocess.STDOUT)
@@ -262,18 +256,6 @@
262 print >> self.create_process.stdin, text256 print >> self.create_process.stdin, text
263 self.waiting_for_event_response = False257 self.waiting_for_event_response = False
264258
265 def start_lmc_gui_thread(self, event_queue):
266 self.lmc_thread = self.LinaroMediaCreate(self.event_handler,
267 self.lmcargs, event_queue)
268 self.lmc_thread.start()
269
270 def kill_create_media(self):
271 pass # TODO: Something!
272 # Need to make sure all child processes are terminated.
273
274 def send_to_create_process(self, text):
275 self.lmc_thread.send_to_create_process(text)
276
277 def name_and_path_from_url(self, url):259 def name_and_path_from_url(self, url):
278 """Return the file name and the path at which the file will be stored260 """Return the file name and the path at which the file will be stored
279 on the local system based on the URL we are downloading from"""261 on the local system based on the URL we are downloading from"""
@@ -290,34 +272,94 @@
290272
291 return file_name, file_path273 return file_name, file_path
292274
293 def create_wx_progress(self, title, message):275 def urllib2_open(self, url):
294 """Create a standard WX progrss dialog"""276 maxtries = 10
295 import wx277 for trycount in range(0, maxtries):
296 self.dlg = wx.ProgressDialog(title,278 try:
297 message,279 response = urllib2.urlopen(url)
298 maximum=1000,280 except:
299 parent=None,281 if trycount < maxtries - 1:
300 style=wx.PD_CAN_ABORT282 print "Unable to connect to", url, "retrying in 5 seconds..."
301 | wx.PD_APP_MODAL283 time.sleep(5)
302 | wx.PD_ELAPSED_TIME284 continue
303 | wx.PD_AUTO_HIDE285 else:
304 | wx.PD_REMAINING_TIME)286 print "Connect failed:", url
305287 raise
306 def timer_ping(self):288 return None
307 self.update_wx_process(self.download_count)289 else:
308290 return response
309 def update_wx_progress(self, count):291
310 self.download_count = count292 return None
311 (self.do_download, skip) = self.dlg.Update(count)293
312294 def download_files(self,
313 def download(self, url, force_download=False,295 downloads_list,
314 show_wx_progress=False, wx_progress_title=None):296 settings,
297 event_queue=None):
298 """
299 Download files specified in the downloads_list, which is a list of
300 url, name tuples.
301 """
302
303 downloaded_files = {}
304
305 bytes_to_download = 0
306
307 for url, name in downloads_list:
308 file_name, file_path = self.name_and_path_from_url(url)
309
310 file_name = file_path + os.sep + file_name
311 if os.path.exists(file_name):
312 continue # If file already exists, don't download it
313
314 response = self.urllib2_open(url)
315 if response:
316 bytes_to_download += int(response.info()
317 .getheader('Content-Length').strip())
318 response.close()
319
320 if event_queue:
321 event_queue.put(("update",
322 "download",
323 "total bytes",
324 bytes_to_download))
325
326 for url, name in downloads_list:
327 if event_queue:
328 event_queue.put(("start", "download " + name))
329 event_queue.put(("update",
330 "download",
331 "name",
332 name))
333
334 path = None
335 try:
336 path = self.download(url,
337 event_queue,
338 settings["force_download"])
339 except Exception:
340 # Download error. Hardly matters what, we can't continue.
341 print "Unexpected error:", sys.exc_info()[0]
342 logging.error("Unable to download " + url + " - aborting.")
343
344 if event_queue:
345 event_queue.put(("end", "download " + name))
346
347 if path == None: # User hit cancel when downloading
348 sys.exit(0)
349
350 downloaded_files[name] = path
351 logging.info("Have downloaded {0} to {1}".format(name, path))
352
353 return downloaded_files
354
355 def download(self,
356 url,
357 event_queue,
358 force_download=False):
315 """Downloads the file requested buy URL to the local cache and returns359 """Downloads the file requested buy URL to the local cache and returns
316 the full path to the downloaded file"""360 the full path to the downloaded file"""
317361
318 file_name, file_path = self.name_and_path_from_url(url)362 file_name, file_path = self.name_and_path_from_url(url)
319
320 just_file_name = file_name
321 file_name = file_path + os.sep + file_name363 file_name = file_path + os.sep + file_name
322364
323 if not os.path.isdir(file_path):365 if not os.path.isdir(file_path):
@@ -328,23 +370,9 @@
328 "--force-download to override).")370 "--force-download to override).")
329 return file_name371 return file_name
330372
331 logging.info("Fetching", url)373 logging.info("Fetching " + url)
332374
333 maxtries = 10375 response = self.urllib2_open(url)
334 for trycount in range(0, maxtries):
335 try:
336 response = urllib2.urlopen(url)
337 except:
338 if trycount < maxtries - 1:
339 print "Unable to download", url, "retrying in 5 seconds..."
340 time.sleep(5)
341 continue
342 else:
343 print "Download failed for some reason:", url
344 raise
345 return
346 else:
347 break
348376
349 self.do_download = True377 self.do_download = True
350 file_out = open(file_name, 'w')378 file_out = open(file_name, 'w')
@@ -356,28 +384,22 @@
356384
357 if show_progress:385 if show_progress:
358 chunk_size = download_size_in_bytes / 1000386 chunk_size = download_size_in_bytes / 1000
359 if show_wx_progress:387 if not event_queue:
360 if wx_progress_title == None:
361 wx_progress_title = "Downloading File"
362 self.create_wx_progress(wx_progress_title,
363 "Downloading " + just_file_name)
364 else:
365 print "Fetching", url388 print "Fetching", url
366 else:389 else:
367 chunk_size = download_size_in_bytes390 chunk_size = download_size_in_bytes
368391
369 if show_progress and show_wx_progress:
370 # Just update the download box before we get the first %
371 self.update_wx_progress(0)
372
373 printed_progress = False392 printed_progress = False
374 while self.do_download:393 while self.do_download:
375 chunk = response.read(chunk_size)394 chunk = response.read(chunk_size)
376 if len(chunk):395 if len(chunk):
377 # Print a % download complete so we don't get too bored396 # Print a % download complete so we don't get too bored
378 if show_progress:397 if show_progress:
379 if show_wx_progress:398 if event_queue:
380 self.update_wx_progress(chunks_downloaded)399 event_queue.put(("update",
400 "download",
401 "progress",
402 len(chunk)))
381 else:403 else:
382 # Have 1000 chunks so div by 10 to get %...404 # Have 1000 chunks so div by 10 to get %...
383 sys.stdout.write("\r%d%%" % (chunks_downloaded / 10))405 sys.stdout.write("\r%d%%" % (chunks_downloaded / 10))
@@ -400,7 +422,7 @@
400422
401 return file_name423 return file_name
402424
403 def download_if_old(self, url, force_download, show_wx_progress=False):425 def download_if_old(self, url, event_queue, force_download):
404 file_name, file_path = self.name_and_path_from_url(url)426 file_name, file_path = self.name_and_path_from_url(url)
405427
406 file_path_and_name = file_path + os.sep + file_name428 file_path_and_name = file_path + os.sep + file_name
@@ -411,25 +433,25 @@
411 force_download = (force_download == True433 force_download = (force_download == True
412 or ( time.mktime(time.localtime())434 or ( time.mktime(time.localtime())
413 - os.path.getmtime(file_path_and_name)435 - os.path.getmtime(file_path_and_name)
414 > 60 * 60 * 24))436 > 60 * 60))
415 except OSError:437 except OSError:
416 force_download = True # File not found...438 force_download = True # File not found...
417439
418 return self.download(url, force_download, show_wx_progress)440 return self.download(url, event_queue, force_download)
419441
420 def update_files_from_server(self, force_download=False,442 def update_files_from_server(self, force_download=False,
421 show_wx_progress=False):443 event_queue=None):
422444
423 settings_url = "http://z.nanosheep.org/fetch_image_settings.yaml"445 settings_url = "http://releases.linaro.org/fetch_image/fetch_image_settings.yaml"
424 server_index_url = "http://z.nanosheep.org/server_index.bz2"446 server_index_url = "http://releases.linaro.org/fetch_image/server_index.bz2"
425447
426 self.settings_file = self.download_if_old(settings_url,448 self.settings_file = self.download_if_old(settings_url,
427 force_download,449 event_queue,
428 show_wx_progress)450 force_download)
429451
430 self.index_file = self.download_if_old(server_index_url,452 self.index_file = self.download_if_old(server_index_url,
431 force_download,453 event_queue,
432 show_wx_progress)454 force_download)
433455
434 zip_search = re.search(r"^(.*)\.bz2$", self.index_file)456 zip_search = re.search(r"^(.*)\.bz2$", self.index_file)
435457
@@ -484,9 +506,9 @@
484 self.settings['UI']['reverse-translate'][value] = key506 self.settings['UI']['reverse-translate'][value] = key
485507
486 def parse_args(self, args):508 def parse_args(self, args):
487 parser = argparse.ArgumentParser(description=509 parser = argparse.ArgumentParser(description="Create a board image, "
488 "Create a board image, first "510 "first downloading any required "
489 "downloading any required files.")511 "files.")
490512
491 for (key, value) in self.settings['choice'].items():513 for (key, value) in self.settings['choice'].items():
492 parser.add_argument(514 parser.add_argument(
@@ -983,7 +1005,7 @@
983 loop_date_increment = -one_day1005 loop_date_increment = -one_day
9841006
985 test_date[in_the] = current_date1007 test_date[in_the] = current_date
986 1008
987 while test_date[in_the] <= max_search_date:1009 while test_date[in_the] <= max_search_date:
988 test_date[in_the] += loop_date_increment1010 test_date[in_the] += loop_date_increment
9891011
9901012
=== modified file 'linaro_image_tools/fetch_image_settings.yaml'
--- linaro_image_tools/fetch_image_settings.yaml 2011-06-17 18:04:47 +0000
+++ linaro_image_tools/fetch_image_settings.yaml 2011-07-18 14:39:34 +0000
@@ -45,6 +45,7 @@
45 # u8500: U850045 # u8500: U8500
46 overo: Overo46 overo: Overo
47 smdkv310: S5PV31047 smdkv310: S5PV310
48 origen: Origen
48 49
49 hwpack:50 hwpack:
50 beagle:51 beagle:
@@ -88,6 +89,9 @@
88 - lt-s5pv31089 - lt-s5pv310
89 - s5pv31090 - s5pv310
9091
92 origen:
93 - lt-origen
94
91 image:95 image:
92 - alip96 - alip
93 - developer97 - developer
9498
=== modified file 'linaro_image_tools/hwpack/config.py'
--- linaro_image_tools/hwpack/config.py 2011-06-20 13:46:16 +0000
+++ linaro_image_tools/hwpack/config.py 2011-07-18 14:39:34 +0000
@@ -22,7 +22,7 @@
22import ConfigParser22import ConfigParser
23import re23import re
2424
25from hardwarepack_format import (25from linaro_image_tools.hwpack.hardwarepack_format import (
26 HardwarePackFormatV1,26 HardwarePackFormatV1,
27 HardwarePackFormatV2,27 HardwarePackFormatV2,
28 )28 )
@@ -42,7 +42,7 @@
42 SOURCES_ENTRY_KEY = "sources-entry"42 SOURCES_ENTRY_KEY = "sources-entry"
43 PACKAGES_KEY = "packages"43 PACKAGES_KEY = "packages"
44 PACKAGE_REGEX = NAME_REGEX44 PACKAGE_REGEX = NAME_REGEX
45 PATH_REGEX = r"[a-z0-9][a-z0-9+\-./]+$"45 PATH_REGEX = r"[a-z0-9][a-z0-9+\-./_]+$"
46 ORIGIN_KEY = "origin"46 ORIGIN_KEY = "origin"
47 MAINTAINER_KEY = "maintainer"47 MAINTAINER_KEY = "maintainer"
48 ARCHITECTURES_KEY = "architectures"48 ARCHITECTURES_KEY = "architectures"
@@ -58,6 +58,16 @@
58 PARTITION_LAYOUT_KEY = "partition_layout"58 PARTITION_LAYOUT_KEY = "partition_layout"
59 MMC_ID_KEY = "mmc_id"59 MMC_ID_KEY = "mmc_id"
60 FORMAT_KEY = "format"60 FORMAT_KEY = "format"
61 BOOT_MIN_SIZE_KEY = "boot_min_size"
62 ROOT_MIN_SIZE_KEY = "root_min_size"
63 LOADER_MIN_SIZE_KEY = "loader_min_size"
64
65 DEFINED_PARTITION_LAYOUTS = [
66 'bootfs16_rootfs',
67 'bootfs_rootfs',
68 #'reserved_bootfs_rootfs',
69 ]
70
6171
62 def __init__(self, fp):72 def __init__(self, fp):
63 """Create a Config.73 """Create a Config.
@@ -93,6 +103,9 @@
93 self._validate_wireless_interfaces()103 self._validate_wireless_interfaces()
94 self._validate_partition_layout()104 self._validate_partition_layout()
95 self._validate_mmc_id()105 self._validate_mmc_id()
106 self._validate_boot_min_size()
107 self._validate_root_min_size()
108 self._validate_loader_min_size()
96109
97 self._validate_sections()110 self._validate_sections()
98111
@@ -217,6 +230,30 @@
217 return self._get_option_from_main_section(self.MMC_ID_KEY)230 return self._get_option_from_main_section(self.MMC_ID_KEY)
218231
219 @property232 @property
233 def root_min_size(self):
234 """Minimum size of the root partition, in MiB.
235
236 An int.
237 """
238 return self._get_option_from_main_section(self.ROOT_MIN_SIZE_KEY)
239
240 @property
241 def boot_min_size(self):
242 """Minimum size of the boot partition, in MiB.
243
244 An int.
245 """
246 return self._get_option_from_main_section(self.BOOT_MIN_SIZE_KEY)
247
248 @property
249 def loader_min_size(self):
250 """Minimum size of the optional loader partition, in MiB.
251
252 An int.
253 """
254 return self._get_option_from_main_section(self.LOADER_MIN_SIZE_KEY)
255
256 @property
220 def origin(self):257 def origin(self):
221 """The origin that should be recorded in the hwpack.258 """The origin that should be recorded in the hwpack.
222259
@@ -375,17 +412,12 @@
375 pass412 pass
376413
377 def _validate_partition_layout(self):414 def _validate_partition_layout(self):
378 defined_partition_layouts = [415 if self.partition_layout not in self.DEFINED_PARTITION_LAYOUTS:
379 #'bootfs16_rootfs',
380 'bootfs_rootfs',
381 #'reserved_bootfs_rootfs',
382 ]
383 if self.partition_layout not in defined_partition_layouts:
384 raise HwpackConfigError(416 raise HwpackConfigError(
385 "Undefined partition layout %s in the [%s] section. "417 "Undefined partition layout %s in the [%s] section. "
386 "Valid partition layouts are %s."418 "Valid partition layouts are %s."
387 % (self.partition_layout, self.MAIN_SECTION,419 % (self.partition_layout, self.MAIN_SECTION,
388 ", ".join(defined_partition_layouts)))420 ", ".join(self.DEFINED_PARTITION_LAYOUTS)))
389421
390 def _validate_mmc_id(self):422 def _validate_mmc_id(self):
391 mmc_id = self.mmc_id423 mmc_id = self.mmc_id
@@ -396,6 +428,36 @@
396 except:428 except:
397 raise HwpackConfigError("Invalid mmc id %s" % (mmc_id))429 raise HwpackConfigError("Invalid mmc id %s" % (mmc_id))
398430
431 def _validate_root_min_size(self):
432 root_min_size = self.root_min_size
433 if root_min_size is None:
434 return
435 try:
436 assert int(root_min_size) > 0
437 except:
438 raise HwpackConfigError(
439 "Invalid root min size %s" % (root_min_size))
440
441 def _validate_boot_min_size(self):
442 boot_min_size = self.boot_min_size
443 if boot_min_size is None:
444 return
445 try:
446 assert int(boot_min_size) > 0
447 except:
448 raise HwpackConfigError(
449 "Invalid boot min size %s" % (boot_min_size))
450
451 def _validate_loader_min_size(self):
452 loader_min_size = self.loader_min_size
453 if loader_min_size is None:
454 return
455 try:
456 assert int(loader_min_size) > 0
457 except:
458 raise HwpackConfigError(
459 "Invalid loader min size %s" % (loader_min_size))
460
399 def _validate_include_debs(self):461 def _validate_include_debs(self):
400 try:462 try:
401 self.include_debs463 self.include_debs
402464
=== modified file 'linaro_image_tools/hwpack/hardwarepack.py'
--- linaro_image_tools/hwpack/hardwarepack.py 2011-06-20 13:46:16 +0000
+++ linaro_image_tools/hwpack/hardwarepack.py 2011-07-18 14:39:34 +0000
@@ -80,7 +80,8 @@
80 def add_v2_config(self, serial_tty=None, kernel_addr=None, initrd_addr=None,80 def add_v2_config(self, serial_tty=None, kernel_addr=None, initrd_addr=None,
81 load_addr=None, fdt=None, wired_interfaces=[],81 load_addr=None, fdt=None, wired_interfaces=[],
82 wireless_interfaces=[], partition_layout=None,82 wireless_interfaces=[], partition_layout=None,
83 mmc_id=None):83 mmc_id=None, boot_min_size=None, root_min_size=None,
84 loader_min_size=None):
84 """Add fields that are specific to the new format.85 """Add fields that are specific to the new format.
8586
86 These fields are not present in earlier config files.87 These fields are not present in earlier config files.
@@ -94,6 +95,9 @@
94 self.wireless_interfaces = wireless_interfaces95 self.wireless_interfaces = wireless_interfaces
95 self.partition_layout = partition_layout96 self.partition_layout = partition_layout
96 self.mmc_id = mmc_id97 self.mmc_id = mmc_id
98 self.boot_min_size = boot_min_size
99 self.root_min_size = root_min_size
100 self.loader_min_size = loader_min_size
97101
98 @classmethod102 @classmethod
99 def from_config(cls, config, version, architecture):103 def from_config(cls, config, version, architecture):
@@ -126,7 +130,10 @@
126 wired_interfaces=config.wired_interfaces,130 wired_interfaces=config.wired_interfaces,
127 wireless_interfaces=config.wireless_interfaces,131 wireless_interfaces=config.wireless_interfaces,
128 partition_layout=config.partition_layout,132 partition_layout=config.partition_layout,
129 mmc_id=config.mmc_id)133 mmc_id=config.mmc_id,
134 boot_min_size=config.boot_min_size,
135 root_min_size=config.root_min_size,
136 loader_min_size=config.loader_min_size)
130 return metadata137 return metadata
131138
132 def __str__(self):139 def __str__(self):
@@ -163,6 +170,13 @@
163 metadata += "PARTITION_LAYOUT=%s\n" % self.partition_layout170 metadata += "PARTITION_LAYOUT=%s\n" % self.partition_layout
164 if self.mmc_id is not None:171 if self.mmc_id is not None:
165 metadata += "MMC_ID=%s\n" % self.mmc_id172 metadata += "MMC_ID=%s\n" % self.mmc_id
173 if self.boot_min_size is not None:
174 metadata += "BOOT_MIN_SIZE=%s\n" % self.boot_min_size
175 if self.root_min_size is not None:
176 metadata += "ROOT_MIN_SIZE=%s\n" % self.root_min_size
177 if self.loader_min_size is not None:
178 metadata += "LOADER_MIN_SIZE=%s\n" % self.loader_min_size
179
166 return metadata180 return metadata
167181
168182
169183
=== modified file 'linaro_image_tools/hwpack/tests/test_config.py'
--- linaro_image_tools/hwpack/tests/test_config.py 2011-06-17 12:28:43 +0000
+++ linaro_image_tools/hwpack/tests/test_config.py 2011-07-18 14:39:34 +0000
@@ -216,13 +216,16 @@
216 self.assertValidationError("Invalid path: ~~", config)216 self.assertValidationError("Invalid path: ~~", config)
217217
218 def test_validate_partition_layout(self):218 def test_validate_partition_layout(self):
219 config = self.get_config(self.valid_start_v2 + 219 partition_layout = 'apafs_bananfs'
220 "u-boot-package = u-boot-linaro-s5pv310\n" \220 config = self.get_config(self.valid_start_v2 + "u-boot-package = " \
221 "u-boot-file = u-boot.bin\n" \221 "u-boot-linaro-s5pv310\nu-boot-file = " \
222 "partition_layout = apafs_bananfs\n")222 "u-boot.bin\npartition_layout = %s\n" % \
223 partition_layout)
223 self.assertValidationError(224 self.assertValidationError(
224 "Undefined partition layout apafs_bananfs in the [hwpack] " \225 "Undefined partition layout %s in the [%s] section. "
225 "section. Valid partition layouts are bootfs_rootfs.", config)226 "Valid partition layouts are %s."
227 % (partition_layout, 'hwpack',
228 ", ".join(config.DEFINED_PARTITION_LAYOUTS)), config)
226229
227 def test_validate_wired_interfaces(self):230 def test_validate_wired_interfaces(self):
228 self.assertTrue("XXX What is an invalid interface name?")231 self.assertTrue("XXX What is an invalid interface name?")
@@ -246,6 +249,21 @@
246 "mmc_id = x\n")249 "mmc_id = x\n")
247 self.assertValidationError("Invalid mmc id x", config)250 self.assertValidationError("Invalid mmc id x", config)
248251
252 def test_validate_boot_min_size(self):
253 config = self.get_config(self.valid_complete_v2 +
254 "boot_min_size = x\n")
255 self.assertValidationError("Invalid boot min size x", config)
256
257 def test_validate_root_min_size(self):
258 config = self.get_config(self.valid_complete_v2 +
259 "root_min_size = x\n")
260 self.assertValidationError("Invalid root min size x", config)
261
262 def test_validate_loader_min_size(self):
263 config = self.get_config(self.valid_complete_v2 +
264 "loader_min_size = x\n")
265 self.assertValidationError("Invalid loader min size x", config)
266
249 def test_validate_kernel_addr(self):267 def test_validate_kernel_addr(self):
250 config = self.get_config(self.valid_complete_v2 + 268 config = self.get_config(self.valid_complete_v2 +
251 "kernel_addr = 0x8000000\n")269 "kernel_addr = 0x8000000\n")
@@ -327,6 +345,27 @@
327 config.validate()345 config.validate()
328 self.assertEqual("1", config.mmc_id)346 self.assertEqual("1", config.mmc_id)
329347
348 def test_boot_min_size(self):
349 config = self.get_config(self.valid_complete_v2 +
350 "boot_min_size = 50\n" +
351 self.valid_end)
352 config.validate()
353 self.assertEqual("50", config.boot_min_size)
354
355 def test_root_min_size(self):
356 config = self.get_config(self.valid_complete_v2 +
357 "root_min_size = 50\n" +
358 self.valid_end)
359 config.validate()
360 self.assertEqual("50", config.root_min_size)
361
362 def test_loader_min_size(self):
363 config = self.get_config(self.valid_complete_v2 +
364 "loader_min_size = 2\n" +
365 self.valid_end)
366 config.validate()
367 self.assertEqual("2", config.loader_min_size)
368
330 def test_kernel_addr(self):369 def test_kernel_addr(self):
331 config = self.get_config(self.valid_complete_v2 + 370 config = self.get_config(self.valid_complete_v2 +
332 "kernel_addr = 0x80000000\n" + 371 "kernel_addr = 0x80000000\n" +
333372
=== modified file 'linaro_image_tools/hwpack/tests/test_hardwarepack.py'
--- linaro_image_tools/hwpack/tests/test_hardwarepack.py 2011-06-17 15:10:49 +0000
+++ linaro_image_tools/hwpack/tests/test_hardwarepack.py 2011-07-18 14:39:34 +0000
@@ -183,6 +183,33 @@
183 "MMC_ID=1\n",183 "MMC_ID=1\n",
184 str(metadata))184 str(metadata))
185185
186 def test_str_with_boot_min_size(self):
187 metadata = Metadata("ahwpack", "4", "armel",
188 format=HardwarePackFormatV2())
189 metadata.add_v2_config(boot_min_size='50')
190 self.assertEqual(
191 "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\n"
192 "BOOT_MIN_SIZE=50\n",
193 str(metadata))
194
195 def test_str_with_root_min_size(self):
196 metadata = Metadata("ahwpack", "4", "armel",
197 format=HardwarePackFormatV2())
198 metadata.add_v2_config(root_min_size='100')
199 self.assertEqual(
200 "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\n"
201 "ROOT_MIN_SIZE=100\n",
202 str(metadata))
203
204 def test_str_with_loader_min_size(self):
205 metadata = Metadata("ahwpack", "4", "armel",
206 format=HardwarePackFormatV2())
207 metadata.add_v2_config(loader_min_size='1')
208 self.assertEqual(
209 "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\n"
210 "LOADER_MIN_SIZE=1\n",
211 str(metadata))
212
186 def test_from_config(self):213 def test_from_config(self):
187 class Config:214 class Config:
188 name = "foo"215 name = "foo"
189216
=== modified file 'linaro_image_tools/media_create/android_boards.py'
--- linaro_image_tools/media_create/android_boards.py 2011-04-22 15:09:08 +0000
+++ linaro_image_tools/media_create/android_boards.py 2011-07-18 14:39:34 +0000
@@ -28,6 +28,8 @@
28from linaro_image_tools.media_create.boards import PART_ALIGN_S28from linaro_image_tools.media_create.boards import PART_ALIGN_S
29from linaro_image_tools.media_create.boards import BeagleConfig29from linaro_image_tools.media_create.boards import BeagleConfig
30from linaro_image_tools.media_create.boards import PandaConfig30from linaro_image_tools.media_create.boards import PandaConfig
31from linaro_image_tools.media_create.boards import SnowballSdConfig
32from linaro_image_tools.media_create.boards import SnowballEmmcConfig
31from linaro_image_tools.media_create.boards import (33from linaro_image_tools.media_create.boards import (
32 align_up,34 align_up,
33 align_partition,35 align_partition,
@@ -37,6 +39,7 @@
37from linaro_image_tools import cmd_runner39from linaro_image_tools import cmd_runner
38import os40import os
3941
42
40class AndroidBoardConfig(object):43class AndroidBoardConfig(object):
41 @classmethod44 @classmethod
42 def _get_bootargs(cls, consoles):45 def _get_bootargs(cls, consoles):
@@ -78,7 +81,7 @@
78 as_root=True).wait()81 as_root=True).wait()
7982
80 boot_env = cls._get_boot_env(consoles)83 boot_env = cls._get_boot_env(consoles)
81 cmdline_filepath = os.path.join(boot_disk, "cmdline") 84 cmdline_filepath = os.path.join(boot_disk, "cmdline")
82 cmdline_file = open(cmdline_filepath, 'r')85 cmdline_file = open(cmdline_filepath, 'r')
83 android_kernel_cmdline = cmdline_file.read()86 android_kernel_cmdline = cmdline_file.read()
84 boot_env['bootargs'] = boot_env['bootargs'] + ' ' + \87 boot_env['bootargs'] = boot_env['bootargs'] + ' ' + \
@@ -96,7 +99,8 @@
96 pass99 pass
97100
98 @classmethod101 @classmethod
99 def get_sfdisk_cmd(cls, should_align_boot_part=False):102 def get_sfdisk_cmd(cls, should_align_boot_part=False,
103 start_addr=0, extra_part=False):
100 if cls.fat_size == 32:104 if cls.fat_size == 32:
101 partition_type = '0x0C'105 partition_type = '0x0C'
102 else:106 else:
@@ -116,7 +120,7 @@
116120
117 # can only start on sector 1 (sector 0 is MBR / partition table)121 # can only start on sector 1 (sector 0 is MBR / partition table)
118 boot_start, boot_end, boot_len = align_partition(122 boot_start, boot_end, boot_len = align_partition(
119 1, BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)123 start_addr + 1, BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)
120 # apparently OMAP3 ROMs require the vfat length to be an even number124 # apparently OMAP3 ROMs require the vfat length to be an even number
121 # of sectors (multiple of 1 KiB); decrease the length if it's odd,125 # of sectors (multiple of 1 KiB); decrease the length if it's odd,
122 # there should still be enough room126 # there should still be enough room
@@ -131,12 +135,28 @@
131 _cache_end + 1, USERDATA_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)135 _cache_end + 1, USERDATA_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
132 sdcard_start, _sdcard_end, _sdcard_len = align_partition(136 sdcard_start, _sdcard_end, _sdcard_len = align_partition(
133 _userdata_end + 1, SDCARD_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)137 _userdata_end + 1, SDCARD_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
134 138
139 # Snowball board needs a raw partition added to the beginning of image.
140 # If extra_part is True an extra primary partition will be added.
141 # Due to a maximum of 4 primary partitions cache data will be placed in
142 # a extended partition
143 if extra_part == True:
144 assert start_addr > 0, ("Not possible to add extra partition" \
145 "when boot partition starts at '0'")
146 return '%s,%s,%s,*\n%s,%s,L\n%s,-,E\n%s,%s,L\n%s,%s,L\n%s,,,-' % (
147 boot_start, boot_len, partition_type, system_start, _system_len,
148 cache_start, cache_start, _cache_len, userdata_start,
149 _userdata_len, sdcard_start)
150
135 return '%s,%s,%s,*\n%s,%s,L\n%s,%s,L\n%s,-,E\n%s,%s,L\n%s,,,-' % (151 return '%s,%s,%s,*\n%s,%s,L\n%s,%s,L\n%s,-,E\n%s,%s,L\n%s,,,-' % (
136 boot_start, boot_len, partition_type, system_start, _system_len,152 boot_start, boot_len, partition_type, system_start, _system_len,
137 cache_start, _cache_len, userdata_start, userdata_start,153 cache_start, _cache_len, userdata_start, userdata_start,
138 _userdata_len, sdcard_start)154 _userdata_len, sdcard_start)
139155
156 @classmethod
157 def populate_raw_partition(cls, media, boot_dir):
158 super(AndroidBoardConfig, cls).populate_raw_partition(boot_dir, media)
159
140160
141class AndroidOmapConfig(AndroidBoardConfig):161class AndroidOmapConfig(AndroidBoardConfig):
142 pass162 pass
@@ -149,10 +169,50 @@
149169
150class AndroidPandaConfig(AndroidOmapConfig, PandaConfig):170class AndroidPandaConfig(AndroidOmapConfig, PandaConfig):
151 _extra_serial_opts = 'console=tty0 console=ttyO2,115200n8'171 _extra_serial_opts = 'console=tty0 console=ttyO2,115200n8'
172 extra_boot_args_options = (
173 'earlyprintk fixrtc nocompcache vram=48M '
174 'omapfb.vram=0:24M,1:24M mem=456M@0x80000000 mem=512M@0xA0000000')
152 android_specific_args = 'init=/init androidboot.console=ttyO2'175 android_specific_args = 'init=/init androidboot.console=ttyO2'
153176
154177
178class AndroidSnowballSdConfig(AndroidBoardConfig, SnowballSdConfig):
179 extra_boot_args_options = (
180 'earlyprintk rootdelay=1 fixrtc nocompcache '
181 'mem=128M@0 mali.mali_mem=64M@128M mem=24M@192M hwmem=167M@216M '
182 'mem_issw=1M@383M mem=640M@384M vmalloc=256M')
183 _extra_serial_opts = 'console=tty0 console=ttyO2,115200n8'
184 android_specific_args = 'init=/init androidboot.console=ttyAMA2'
185
186
187class AndroidSnowballEmmcConfig(AndroidBoardConfig, SnowballEmmcConfig):
188 extra_boot_args_options = (
189 'earlyprintk rootdelay=1 fixrtc nocompcache '
190 'mem=128M@0 mali.mali_mem=64M@128M mem=24M@192M hwmem=167M@216M '
191 'mem_issw=1M@383M mem=640M@384M vmalloc=256M')
192 _extra_serial_opts = 'console=tty0 console=ttyAMA2,115200n8'
193 android_specific_args = 'init=/init androidboot.console=ttyAMA2'
194
195 @classmethod
196 def get_sfdisk_cmd(cls, should_align_boot_part=False):
197
198 LOADER_MIN_SIZE_S = align_up(
199 1 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
200
201 loader_start, loader_end, loader_len = align_partition(
202 SnowballEmmcConfig.SNOWBALL_LOADER_START_S,
203 LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
204
205 command = super(AndroidSnowballEmmcConfig, cls).get_sfdisk_cmd(
206 should_align_boot_part=True, start_addr=loader_end,
207 extra_part=True)
208
209 return '%s,%s,0xDA\n%s' % (
210 loader_start, loader_len, command)
211
212
155android_board_configs = {213android_board_configs = {
156 'beagle': AndroidBeagleConfig,214 'beagle': AndroidBeagleConfig,
157 'panda': AndroidPandaConfig,215 'panda': AndroidPandaConfig,
216 'snowball_sd': AndroidSnowballSdConfig,
217 'snowball_emmc': AndroidSnowballEmmcConfig,
158 }218 }
159219
=== modified file 'linaro_image_tools/media_create/boards.py'
--- linaro_image_tools/media_create/boards.py 2011-05-26 20:19:23 +0000
+++ linaro_image_tools/media_create/boards.py 2011-07-18 14:39:34 +0000
@@ -31,11 +31,15 @@
31import tempfile31import tempfile
32import struct32import struct
33from binascii import crc3233from binascii import crc32
34import tarfile
35import ConfigParser
36import shutil
3437
35from linaro_image_tools import cmd_runner38from linaro_image_tools import cmd_runner
3639
37from linaro_image_tools.media_create.partitions import SECTOR_SIZE40from linaro_image_tools.media_create.partitions import SECTOR_SIZE
3841
42
39KERNEL_GLOB = 'vmlinuz-*-%(kernel_flavor)s'43KERNEL_GLOB = 'vmlinuz-*-%(kernel_flavor)s'
40INITRD_GLOB = 'initrd.img-*-%(kernel_flavor)s'44INITRD_GLOB = 'initrd.img-*-%(kernel_flavor)s'
41DTB_GLOB = 'dt-*-%(kernel_flavor)s/%(dtb_name)s'45DTB_GLOB = 'dt-*-%(kernel_flavor)s/%(dtb_name)s'
@@ -58,21 +62,11 @@
58# align on 4 MiB62# align on 4 MiB
59PART_ALIGN_S = 4 * 1024 * 1024 / SECTOR_SIZE63PART_ALIGN_S = 4 * 1024 * 1024 / SECTOR_SIZE
6064
65
61def align_up(value, align):66def align_up(value, align):
62 """Round value to the next multiple of align."""67 """Round value to the next multiple of align."""
63 return (value + align - 1) / align * align68 return (value + align - 1) / align * align
6469
65# optional bootloader partition; at least 1 MiB; in theory, an i.MX5x
66# bootloader partition could hold RedBoot, FIS table, RedBoot config, kernel,
67# and initrd, but we typically use U-Boot which is about 167 KiB as of
68# 2011/02/11 and currently doesn't even store its environment there, so this
69# should be enough
70LOADER_MIN_SIZE_S = align_up(1 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
71# boot partition; at least 50 MiB; XXX this shouldn't be hardcoded
72BOOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
73# root partition; at least 50 MiB; XXX this shouldn't be hardcoded
74ROOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
75
76# Samsung v310 implementation notes and terminology70# Samsung v310 implementation notes and terminology
77#71#
78# * BL0, BL1 etc. are the various bootloaders in order of execution72# * BL0, BL1 etc. are the various bootloaders in order of execution
@@ -104,6 +98,7 @@
104assert SAMSUNG_V310_BL2_LEN * SECTOR_SIZE == 512 * 1024, (98assert SAMSUNG_V310_BL2_LEN * SECTOR_SIZE == 512 * 1024, (
105 "BL1 expects BL2 (u-boot) to be 512 KiB")99 "BL1 expects BL2 (u-boot) to be 512 KiB")
106100
101
107def align_partition(min_start, min_length, start_alignment, end_alignment):102def align_partition(min_start, min_length, start_alignment, end_alignment):
108 """Compute partition start and end offsets based on specified constraints.103 """Compute partition start and end offsets based on specified constraints.
109104
@@ -125,10 +120,103 @@
125 """A descriptor that provides @property behavior on class methods."""120 """A descriptor that provides @property behavior on class methods."""
126 def __init__(self, getter):121 def __init__(self, getter):
127 self.getter = getter122 self.getter = getter
123
128 def __get__(self, instance, cls):124 def __get__(self, instance, cls):
129 return self.getter(cls)125 return self.getter(cls)
130126
131127
128class HardwarepackHandler(object):
129 FORMAT_1 = '1.0'
130 FORMAT_2 = '2.0'
131 FORMAT_MIXED = '1.0and2.0'
132 metadata_filename = 'metadata'
133 format_filename = 'FORMAT'
134 main_section = 'main'
135 hwpack_tarfiles = []
136 tempdir = None
137
138 def __init__(self, hwpacks):
139 self.hwpacks = hwpacks
140 self.hwpack_tarfiles = []
141
142 class FakeSecHead(object):
143 """ Add a fake section header to the metadata file.
144
145 This is done so we can use ConfigParser to parse the file.
146 """
147 def __init__(self, fp):
148 self.fp = fp
149 self.sechead = '[%s]\n' % HardwarepackHandler.main_section
150
151 def readline(self):
152 if self.sechead:
153 try:
154 return self.sechead
155 finally:
156 self.sechead = None
157 else:
158 return self.fp.readline()
159
160 def __enter__(self):
161 self.tempdir = tempfile.mkdtemp()
162 for hwpack in self.hwpacks:
163 hwpack_tarfile = tarfile.open(hwpack, mode='r:gz')
164 self.hwpack_tarfiles.append(hwpack_tarfile)
165 return self
166
167 def __exit__(self, type, value, traceback):
168 for hwpack_tarfile in self.hwpack_tarfiles:
169 if hwpack_tarfile is not None:
170 hwpack_tarfile.close()
171 self.hwpack_tarfiles = []
172 if self.tempdir is not None and os.path.exists(self.tempdir):
173 shutil.rmtree(self.tempdir)
174
175 def get_field(self, section, field):
176 data = None
177 hwpack_with_data = None
178 for hwpack_tarfile in self.hwpack_tarfiles:
179 metadata = hwpack_tarfile.extractfile(self.metadata_filename)
180 # Use RawConfigParser which does not support the magical interpolation
181 # behavior of ConfigParser so we don't mess up metadata accidentally.
182 parser = ConfigParser.RawConfigParser()
183 parser.readfp(self.FakeSecHead(metadata))
184 try:
185 new_data = parser.get(section, field)
186 if new_data is not None:
187 assert data is None, "The metadata field '%s' is set to " \
188 "'%s' and new value '%s' is found" % (field, data, new_data)
189 data = new_data
190 hwpack_with_data = hwpack_tarfile
191 except ConfigParser.NoOptionError:
192 continue
193 return data, hwpack_with_data
194
195 def get_format(self):
196 format = None
197 supported_formats = [self.FORMAT_1, self.FORMAT_2]
198 for hwpack_tarfile in self.hwpack_tarfiles:
199 format_file = hwpack_tarfile.extractfile(self.format_filename)
200 format_string = format_file.read().strip()
201 if not format_string in supported_formats:
202 raise AssertionError(
203 "Format version '%s' is not supported." % \
204 format_string)
205 if format is None:
206 format = format_string
207 elif format != format_string:
208 return self.FORMAT_MIXED
209 return format
210
211 def get_file(self, file_alias):
212 file_name, hwpack_tarfile = self.get_field(self.main_section,
213 file_alias)
214 if file_name is not None:
215 hwpack_tarfile.extract(file_name, self.tempdir)
216 file_name = os.path.join(self.tempdir, file_name)
217 return file_name
218
219
132class BoardConfig(object):220class BoardConfig(object):
133 """The configuration used when building an image for a board."""221 """The configuration used when building an image for a board."""
134 # These attributes may not need to be redefined on some subclasses.222 # These attributes may not need to be redefined on some subclasses.
@@ -138,12 +226,17 @@
138 mmc_option = '0:1'226 mmc_option = '0:1'
139 mmc_part_offset = 0227 mmc_part_offset = 0
140 fat_size = 32228 fat_size = 32
141 extra_serial_opts = ''229 _extra_serial_opts = ''
142 live_serial_opts = ''230 _live_serial_opts = ''
143 extra_boot_args_options = None231 extra_boot_args_options = None
144 supports_writing_to_mmc = True232 supports_writing_to_mmc = True
233 LOADER_MIN_SIZE_S = align_up(1 * 1024**2, SECTOR_SIZE) / SECTOR_SIZE
234 BOOT_MIN_SIZE_S = align_up(50 * 1024**2, SECTOR_SIZE) / SECTOR_SIZE
235 ROOT_MIN_SIZE_S = align_up(50 * 1024**2, SECTOR_SIZE) / SECTOR_SIZE
145236
146 # These attributes must be defined on all subclasses.237 # These attributes must be defined on all subclasses for backwards
238 # compatibility with hwpacks v1 format. Hwpacks v2 format allows these to
239 # be specified in the hwpack metadata.
147 kernel_addr = None240 kernel_addr = None
148 initrd_addr = None241 initrd_addr = None
149 load_addr = None242 load_addr = None
@@ -152,6 +245,88 @@
152 kernel_flavors = None245 kernel_flavors = None
153 boot_script = None246 boot_script = None
154 serial_tty = None247 serial_tty = None
248 wired_interfaces = None
249 wireless_interfaces = None
250 mmc_id = None
251
252 hardwarepack_handler = None
253
254 @classmethod
255 def get_metadata_field(cls, target, field_name):
256 """ Return the metadata value for field_name if it can be found.
257 """
258 data, _ = cls.hardwarepack_handler.get_field(
259 cls.hardwarepack_handler.main_section, field_name)
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 (cls.hardwarepack_handler.get_format() ==
267 cls.hardwarepack_handler.FORMAT_1):
268 return
269
270 if (cls.hardwarepack_handler.get_format() ==
271 cls.hardwarepack_handler.FORMAT_2):
272 # Clear V1 defaults.
273 cls.kernel_addr = None
274 cls.initrd_addr = None
275 cls.load_addr = None
276 cls.serial_tty = None
277 cls.fat_size = None
278 cls.BOOT_MIN_SIZE_S = None
279 cls.ROOT_MIN_SIZE_S = None
280 cls.LOADER_MIN_SIZE_S = None
281
282 # Set new values from metadata.
283 cls.kernel_addr = cls.get_metadata_field(
284 cls.kernel_addr, 'kernel_addr')
285 cls.initrd_addr = cls.get_metadata_field(
286 cls.initrd_addr, 'initrd_addr')
287 cls.load_addr = cls.get_metadata_field(
288 cls.load_addr, 'load_addr')
289 cls.serial_tty = cls.get_metadata_field(
290 cls.serial_tty, 'serial_tty')
291 cls.wired_interfaces = cls.get_metadata_field(
292 cls.wired_interfaces, 'wired_interfaces')
293 cls.wireless_interfaces = cls.get_metadata_field(
294 cls.wireless_interfaces, 'wireless_interfaces')
295 cls.mmc_id = cls.get_metadata_field(
296 cls.mmc_id, 'mmc_id')
297
298 partition_layout = cls.get_metadata_field(cls.fat_size, 'partition_layout')
299 if partition_layout == 'bootfs_rootfs' or partition_layout is None:
300 cls.fat_size = 32
301 elif partition_layout == 'bootfs16_rootfs':
302 cls.fat_size = 16
303 else:
304 raise AssertionError("Unknown partition layout '%s'." % partition_layout)
305
306 boot_min_size = cls.get_metadata_field(
307 cls.BOOT_MIN_SIZE_S, 'boot_min_size')
308 if boot_min_size is not None:
309 cls.BOOT_MIN_SIZE_S = align_up(int(boot_min_size) * 1024**2,
310 SECTOR_SIZE) / SECTOR_SIZE
311 root_min_size = cls.get_metadata_field(
312 cls.ROOT_MIN_SIZE_S, 'root_min_size')
313 if root_min_size is not None:
314 cls.ROOT_MIN_SIZE_S = align_up(int(root_min_size) * 1024**2,
315 SECTOR_SIZE) / SECTOR_SIZE
316 loader_min_size = cls.get_metadata_field(
317 cls.LOADER_MIN_SIZE_S, 'loader_min_size')
318 if loader_min_size is not None:
319 cls.LOADER_MIN_SIZE_S = align_up(int(loader_min_size) * 1024**2,
320 SECTOR_SIZE) / SECTOR_SIZE
321
322
323 @classmethod
324 def get_file(cls, file_alias, default=None):
325 file_in_hwpack = cls.hardwarepack_handler.get_file(file_alias)
326 if file_in_hwpack is not None:
327 return file_in_hwpack
328 else:
329 return default
155330
156 @classmethod331 @classmethod
157 def get_sfdisk_cmd(cls, should_align_boot_part=False):332 def get_sfdisk_cmd(cls, should_align_boot_part=False):
@@ -167,9 +342,6 @@
167 else:342 else:
168 partition_type = '0x0E'343 partition_type = '0x0E'
169344
170 BOOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
171 ROOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
172
173 # align on sector 63 for compatibility with broken versions of x-loader345 # align on sector 63 for compatibility with broken versions of x-loader
174 # unless align_boot_part is set346 # unless align_boot_part is set
175 boot_align = 63347 boot_align = 63
@@ -178,7 +350,7 @@
178350
179 # can only start on sector 1 (sector 0 is MBR / partition table)351 # can only start on sector 1 (sector 0 is MBR / partition table)
180 boot_start, boot_end, boot_len = align_partition(352 boot_start, boot_end, boot_len = align_partition(
181 1, BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)353 1, cls.BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)
182 # apparently OMAP3 ROMs require the vfat length to be an even number354 # apparently OMAP3 ROMs require the vfat length to be an even number
183 # of sectors (multiple of 1 KiB); decrease the length if it's odd,355 # of sectors (multiple of 1 KiB); decrease the length if it's odd,
184 # there should still be enough room356 # there should still be enough room
@@ -189,7 +361,7 @@
189 # instruct the use of all remaining space; XXX if we had some root size361 # instruct the use of all remaining space; XXX if we had some root size
190 # config, we could do something more sensible362 # config, we could do something more sensible
191 root_start, _root_end, _root_len = align_partition(363 root_start, _root_end, _root_len = align_partition(
192 boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)364 boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
193365
194 return '%s,%s,%s,*\n%s,,,-' % (366 return '%s,%s,%s,*\n%s,,,-' % (
195 boot_start, boot_len, partition_type, root_start)367 boot_start, boot_len, partition_type, root_start)
@@ -299,10 +471,12 @@
299 if cls.uboot_in_boot_part:471 if cls.uboot_in_boot_part:
300 assert cls.uboot_flavor is not None, (472 assert cls.uboot_flavor is not None, (
301 "uboot_in_boot_part is set but not uboot_flavor")473 "uboot_in_boot_part is set but not uboot_flavor")
302 uboot_bin = os.path.join(chroot_dir, 'usr', 'lib', 'u-boot',474 with cls.hardwarepack_handler:
303 cls.uboot_flavor, 'u-boot.bin')475 uboot_bin = cls.get_file('u_boot', default=os.path.join(
304 cmd_runner.run(476 chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
305 ['cp', '-v', uboot_bin, boot_disk], as_root=True).wait()477 'u-boot.bin'))
478 cmd_runner.run(
479 ['cp', '-v', uboot_bin, boot_disk], as_root=True).wait()
306480
307 cls.make_boot_files(481 cls.make_boot_files(
308 uboot_parts_dir, is_live, is_lowmem, consoles, chroot_dir,482 uboot_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
@@ -337,9 +511,14 @@
337 "No kernel found matching %s for flavors %s" % (511 "No kernel found matching %s for flavors %s" % (
338 KERNEL_GLOB, " ".join(cls.kernel_flavors)))512 KERNEL_GLOB, " ".join(cls.kernel_flavors)))
339513
514 @classmethod
515 def populate_raw_partition(cls, media, boot_dir):
516 # Override in subclass if needed
517 pass
518
340519
341class OmapConfig(BoardConfig):520class OmapConfig(BoardConfig):
342 kernel_flavors = ['linaro-omap4', 'linaro-omap', 'omap4']521 kernel_flavors = ['linaro-omap4', 'linaro-lt-omap', 'linaro-omap', 'omap4']
343 uboot_in_boot_part = True522 uboot_in_boot_part = True
344523
345 # XXX: Here we define these things as dynamic properties because our524 # XXX: Here we define these things as dynamic properties because our
@@ -471,8 +650,8 @@
471650
472class Ux500Config(BoardConfig):651class Ux500Config(BoardConfig):
473 serial_tty = 'ttyAMA2'652 serial_tty = 'ttyAMA2'
474 extra_serial_opts = 'console=tty0 console=%s,115200n8' % serial_tty653 _extra_serial_opts = 'console=tty0 console=%s,115200n8'
475 live_serial_opts = 'serialtty=%s' % serial_tty654 _live_serial_opts = 'serialtty=%s'
476 kernel_addr = '0x00100000'655 kernel_addr = '0x00100000'
477 initrd_addr = '0x08000000'656 initrd_addr = '0x08000000'
478 load_addr = '0x00008000'657 load_addr = '0x00008000'
@@ -485,6 +664,14 @@
485 'hwmem=48M@302M mem=152M@360M')664 'hwmem=48M@302M mem=152M@360M')
486 mmc_option = '1:1'665 mmc_option = '1:1'
487666
667 @classproperty
668 def live_serial_opts(cls):
669 return cls._live_serial_opts % cls.serial_tty
670
671 @classproperty
672 def extra_serial_opts(cls):
673 return cls._extra_serial_opts % cls.serial_tty
674
488 @classmethod675 @classmethod
489 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,676 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
490 boot_device_or_file, k_img_data, i_img_data,677 boot_device_or_file, k_img_data, i_img_data,
@@ -517,7 +704,7 @@
517 and u-boot.'''704 and u-boot.'''
518 # Boot ROM looks for a boot table of contents (TOC) at 0x20000705 # Boot ROM looks for a boot table of contents (TOC) at 0x20000
519 # Actually, it first looks at address 0, but that's where l-m-c706 # Actually, it first looks at address 0, but that's where l-m-c
520 # puts the MBR, so the boot loader skips that address. 707 # puts the MBR, so the boot loader skips that address.
521 supports_writing_to_mmc = False708 supports_writing_to_mmc = False
522 SNOWBALL_LOADER_START_S = (128 * 1024) / SECTOR_SIZE709 SNOWBALL_LOADER_START_S = (128 * 1024) / SECTOR_SIZE
523 SNOWBALL_STARTUP_FILES_CONFIG = 'startfiles.cfg'710 SNOWBALL_STARTUP_FILES_CONFIG = 'startfiles.cfg'
@@ -537,20 +724,20 @@
537 This is done since the boot rom always boots off the internal memory;724 This is done since the boot rom always boots off the internal memory;
538 there simply is no point to having a loader partition on SD card.725 there simply is no point to having a loader partition on SD card.
539 """726 """
540 # boot ROM expects bootloader at 0x20000, which is sector 0x100 727 # boot ROM expects bootloader at 0x20000, which is sector 0x100
541 # with the usual SECTOR_SIZE of 0x200.728 # with the usual SECTOR_SIZE of 0x200.
542 # (sector 0 is MBR / partition table)729 # (sector 0 is MBR / partition table)
543 loader_start, loader_end, loader_len = align_partition(730 loader_start, loader_end, loader_len = align_partition(
544 SnowballEmmcConfig.SNOWBALL_LOADER_START_S, 731 SnowballEmmcConfig.SNOWBALL_LOADER_START_S,
545 LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)732 cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
546733
547 boot_start, boot_end, boot_len = align_partition(734 boot_start, boot_end, boot_len = align_partition(
548 loader_end + 1, BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)735 loader_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
549 # we ignore _root_end / _root_len and return an sfdisk command to736 # we ignore _root_end / _root_len and return an sfdisk command to
550 # instruct the use of all remaining space; XXX if we had some root size737 # instruct the use of all remaining space; XXX if we had some root size
551 # config, we could do something more sensible738 # config, we could do something more sensible
552 root_start, _root_end, _root_len = align_partition(739 root_start, _root_end, _root_len = align_partition(
553 boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)740 boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
554741
555 return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (742 return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
556 loader_start, loader_len, boot_start, boot_len, root_start)743 loader_start, loader_len, boot_start, boot_len, root_start)
@@ -562,15 +749,22 @@
562 make_uImage(cls.load_addr, k_img_data, boot_dir)749 make_uImage(cls.load_addr, k_img_data, boot_dir)
563 boot_script_path = os.path.join(boot_dir, cls.boot_script)750 boot_script_path = os.path.join(boot_dir, cls.boot_script)
564 make_boot_script(boot_env, boot_script_path)751 make_boot_script(boot_env, boot_script_path)
752 cls.populate_raw_partition(chroot_dir, boot_device_or_file)
753
754 @classmethod
755 def populate_raw_partition(cls, chroot_dir, boot_device_or_file):
756 # Populate created raw partition with TOC and startup files.
757 config_files_path = os.path.join(chroot_dir, 'boot')
565 _, toc_filename = tempfile.mkstemp()758 _, toc_filename = tempfile.mkstemp()
566 atexit.register(os.unlink, toc_filename)
567 config_files_path = os.path.join(chroot_dir, 'boot')
568 new_files = cls.get_file_info(config_files_path)759 new_files = cls.get_file_info(config_files_path)
569 with open(toc_filename, 'wb') as toc:760 with open(toc_filename, 'wb') as toc:
570 cls.create_toc(toc, new_files)761 cls.create_toc(toc, new_files)
571 cls.install_snowball_boot_loader(toc_filename, new_files,762 cls.install_snowball_boot_loader(toc_filename, new_files,
572 boot_device_or_file,763 boot_device_or_file,
573 cls.SNOWBALL_LOADER_START_S)764 cls.SNOWBALL_LOADER_START_S)
765 cls.delete_file(toc_filename)
766 cls.delete_file(os.path.join(config_files_path,
767 cls.SNOWBALL_STARTUP_FILES_CONFIG))
574768
575 @classmethod769 @classmethod
576 def install_snowball_boot_loader(cls, toc_file_name, files,770 def install_snowball_boot_loader(cls, toc_file_name, files,
@@ -584,13 +778,21 @@
584 for file in files:778 for file in files:
585 # XXX We need checks that these files do not overwrite each779 # XXX We need checks that these files do not overwrite each
586 # other. This code assumes that offset and file sizes are ok.780 # other. This code assumes that offset and file sizes are ok.
781 filename = file['filename']
587 if (file['offset'] % SECTOR_SIZE) != 0:782 if (file['offset'] % SECTOR_SIZE) != 0:
588 seek_bytes = start_sector * SECTOR_SIZE + file['offset']783 seek_bytes = start_sector * SECTOR_SIZE + file['offset']
589 _dd(file['filename'], boot_device_or_file, block_size=1,784 _dd(filename, boot_device_or_file, block_size=1,
590 seek=seek_bytes)785 seek=seek_bytes)
591 else:786 else:
592 seek_sectors = start_sector + file['offset']/SECTOR_SIZE787 seek_sectors = start_sector + file['offset'] / SECTOR_SIZE
593 _dd(file['filename'], boot_device_or_file, seek=seek_sectors)788 _dd(filename, boot_device_or_file, seek=seek_sectors)
789 cls.delete_file(filename)
790
791 @classmethod
792 def delete_file(cls, file_path):
793 cmd = ["rm", "%s" % file_path]
794 proc = cmd_runner.run(cmd, as_root=True)
795 proc.wait()
594796
595 @classmethod797 @classmethod
596 def create_toc(cls, f, files):798 def create_toc(cls, f, files):
@@ -605,6 +807,8 @@
605 # i; int; load_address,807 # i; int; load_address,
606 # 12s; string of char; name808 # 12s; string of char; name
607 # http://igloocommunity.org/support/index.php/ConfigPartitionOverview809 # http://igloocommunity.org/support/index.php/ConfigPartitionOverview
810 assert len(file['section_name']) < 12, (
811 "Section name %s too large" % file['section_name'])
608 flags = 0812 flags = 0
609 load_adress = file['align']813 load_adress = file['align']
610 data = struct.pack('<IIIii12s', file['offset'], file['size'],814 data = struct.pack('<IIIii12s', file['offset'], file['size'],
@@ -642,12 +846,20 @@
642846
643class Mx5Config(BoardConfig):847class Mx5Config(BoardConfig):
644 serial_tty = 'ttymxc0'848 serial_tty = 'ttymxc0'
645 extra_serial_opts = 'console=tty0 console=%s,115200n8' % serial_tty849 _extra_serial_opts = 'console=tty0 console=%s,115200n8'
646 live_serial_opts = 'serialtty=%s' % serial_tty850 _live_serial_opts = 'serialtty=%s'
647 boot_script = 'boot.scr'851 boot_script = 'boot.scr'
648 mmc_part_offset = 1852 mmc_part_offset = 1
649 mmc_option = '0:2'853 mmc_option = '0:2'
650854
855 @classproperty
856 def live_serial_opts(cls):
857 return cls._live_serial_opts % cls.serial_tty
858
859 @classproperty
860 def extra_serial_opts(cls):
861 return cls._extra_serial_opts % cls.serial_tty
862
651 @classmethod863 @classmethod
652 def get_sfdisk_cmd(cls, should_align_boot_part=None):864 def get_sfdisk_cmd(cls, should_align_boot_part=None):
653 """Return the sfdisk command to partition the media.865 """Return the sfdisk command to partition the media.
@@ -663,15 +875,15 @@
663 # onwards, so it's safer to just start at the first sector, sector 1875 # onwards, so it's safer to just start at the first sector, sector 1
664 # (sector 0 is MBR / partition table)876 # (sector 0 is MBR / partition table)
665 loader_start, loader_end, loader_len = align_partition(877 loader_start, loader_end, loader_len = align_partition(
666 1, LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)878 1, cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
667879
668 boot_start, boot_end, boot_len = align_partition(880 boot_start, boot_end, boot_len = align_partition(
669 loader_end + 1, BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)881 loader_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
670 # we ignore _root_end / _root_len and return a sfdisk command to882 # we ignore _root_end / _root_len and return a sfdisk command to
671 # instruct the use of all remaining space; XXX if we had some root size883 # instruct the use of all remaining space; XXX if we had some root size
672 # config, we could do something more sensible884 # config, we could do something more sensible
673 root_start, _root_end, _root_len = align_partition(885 root_start, _root_end, _root_len = align_partition(
674 boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)886 boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
675887
676 return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (888 return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
677 loader_start, loader_len, boot_start, boot_len, root_start)889 loader_start, loader_len, boot_start, boot_len, root_start)
@@ -680,9 +892,12 @@
680 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,892 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
681 boot_device_or_file, k_img_data, i_img_data,893 boot_device_or_file, k_img_data, i_img_data,
682 d_img_data):894 d_img_data):
683 uboot_file = os.path.join(895 with cls.hardwarepack_handler:
684 chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor, 'u-boot.imx')896 uboot_file = cls.get_file('u_boot', default=os.path.join(
685 install_mx5_boot_loader(uboot_file, boot_device_or_file)897 chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
898 'u-boot.imx'))
899 install_mx5_boot_loader(uboot_file, boot_device_or_file,
900 cls.LOADER_MIN_SIZE_S)
686 make_uImage(cls.load_addr, k_img_data, boot_dir)901 make_uImage(cls.load_addr, k_img_data, boot_dir)
687 make_uInitrd(i_img_data, boot_dir)902 make_uInitrd(i_img_data, boot_dir)
688 make_dtb(d_img_data, boot_dir)903 make_dtb(d_img_data, boot_dir)
@@ -730,8 +945,8 @@
730 uboot_flavor = 'ca9x4_ct_vxp'945 uboot_flavor = 'ca9x4_ct_vxp'
731 uboot_in_boot_part = True946 uboot_in_boot_part = True
732 serial_tty = 'ttyAMA0'947 serial_tty = 'ttyAMA0'
733 extra_serial_opts = 'console=tty0 console=%s,38400n8' % serial_tty948 _extra_serial_opts = 'console=tty0 console=%s,38400n8'
734 live_serial_opts = 'serialtty=%s' % serial_tty949 _live_serial_opts = 'serialtty=%s'
735 kernel_addr = '0x60008000'950 kernel_addr = '0x60008000'
736 initrd_addr = '0x81000000'951 initrd_addr = '0x81000000'
737 load_addr = kernel_addr952 load_addr = kernel_addr
@@ -741,6 +956,14 @@
741 # only allows for FAT16956 # only allows for FAT16
742 fat_size = 16957 fat_size = 16
743958
959 @classproperty
960 def live_serial_opts(cls):
961 return cls._live_serial_opts % cls.serial_tty
962
963 @classproperty
964 def extra_serial_opts(cls):
965 return cls._extra_serial_opts % cls.serial_tty
966
744 @classmethod967 @classmethod
745 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,968 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
746 boot_device_or_file, k_img_data, i_img_data,969 boot_device_or_file, k_img_data, i_img_data,
@@ -748,17 +971,10 @@
748 make_uImage(cls.load_addr, k_img_data, boot_dir)971 make_uImage(cls.load_addr, k_img_data, boot_dir)
749 make_uInitrd(i_img_data, boot_dir)972 make_uInitrd(i_img_data, boot_dir)
750973
751class SMDKV310Config(BoardConfig):974class SamsungConfig(BoardConfig):
752 uboot_flavor = 'smdkv310'975 @classproperty
753 serial_tty = 'ttySAC1'976 def extra_serial_opts(cls):
754 extra_serial_opts = 'console=%s,115200n8' % serial_tty977 return cls._extra_serial_opts % cls.serial_tty
755 kernel_addr = '0x40007000'
756 initrd_addr = '0x42000000'
757 load_addr = '0x40008000'
758 kernel_flavors = ['s5pv310']
759 boot_script = 'boot.scr'
760 mmc_part_offset = 1
761 mmc_option = '0:2'
762978
763 @classmethod979 @classmethod
764 def get_sfdisk_cmd(cls, should_align_boot_part=False):980 def get_sfdisk_cmd(cls, should_align_boot_part=False):
@@ -773,46 +989,23 @@
773989
774 # FAT boot partition990 # FAT boot partition
775 boot_start, boot_end, boot_len = align_partition(991 boot_start, boot_end, boot_len = align_partition(
776 loaders_end + 1, BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)992 loaders_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
777993
778 # root partition994 # root partition
779 # we ignore _root_end / _root_len and return a sfdisk command to995 # we ignore _root_end / _root_len and return a sfdisk command to
780 # instruct the use of all remaining space; XXX if we had some root size996 # instruct the use of all remaining space; XXX if we had some root size
781 # config, we could do something more sensible997 # config, we could do something more sensible
782 root_start, _root_end, _root_len = align_partition(998 root_start, _root_end, _root_len = align_partition(
783 boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)999 boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
7841000
785 return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (1001 return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
786 loaders_start, loaders_len, boot_start, boot_len, root_start)1002 loaders_start, loaders_len, boot_start, boot_len, root_start)
7871003
788 @classmethod1004 @classmethod
789 def _get_boot_env(cls, is_live, is_lowmem, consoles, rootfs_uuid,
790 d_img_data):
791 boot_env = super(SMDKV310Config, cls)._get_boot_env(
792 is_live, is_lowmem, consoles, rootfs_uuid, d_img_data)
793
794 boot_env["ethact"] = "smc911x-0"
795 boot_env["ethaddr"] = "00:40:5c:26:0a:5b"
796
797 return boot_env
798
799 @classmethod
800 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,1005 def _make_boot_files(cls, boot_env, chroot_dir, boot_dir,
801 boot_device_or_file, k_img_data, i_img_data,1006 boot_device_or_file, k_img_data, i_img_data,
802 d_img_data):1007 d_img_data):
803 spl_file = os.path.join(1008 cls.install_samsung_boot_loader(chroot_dir, boot_device_or_file)
804 chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
805 'v310_mmc_spl.bin')
806 # XXX need to check that the length of spl_file is smaller than
807 # SAMSUNG_V310_BL1_LEN
808 _dd(spl_file, boot_device_or_file, seek=SAMSUNG_V310_BL1_START)
809
810 uboot_file = os.path.join(
811 chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor, 'u-boot.bin')
812 # XXX need to check that the length of uboot_file is smaller than
813 # SAMSUNG_V310_BL2_LEN
814 _dd(uboot_file, boot_device_or_file, seek=SAMSUNG_V310_BL2_START)
815
816 env_size = SAMSUNG_V310_ENV_LEN * SECTOR_SIZE1009 env_size = SAMSUNG_V310_ENV_LEN * SECTOR_SIZE
817 env_file = make_flashable_env(boot_env, env_size)1010 env_file = make_flashable_env(boot_env, env_size)
818 _dd(env_file, boot_device_or_file, seek=SAMSUNG_V310_ENV_START)1011 _dd(env_file, boot_device_or_file, seek=SAMSUNG_V310_ENV_START)
@@ -825,6 +1018,84 @@
825 boot_script_path = os.path.join(boot_dir, cls.boot_script)1018 boot_script_path = os.path.join(boot_dir, cls.boot_script)
826 make_boot_script(boot_env, boot_script_path)1019 make_boot_script(boot_env, boot_script_path)
8271020
1021 @classmethod
1022 def _get_samsung_spl(cls, chroot_dir):
1023 spl_dir = os.path.join(
1024 chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor)
1025 old_spl_path = os.path.join(spl_dir, 'v310_mmc_spl.bin')
1026 new_spl_path = os.path.join(spl_dir, 'u-boot-mmc-spl.bin')
1027
1028 spl_file = old_spl_path
1029 # The new upstream u-boot filename has changed
1030 if not os.path.exists(spl_file):
1031 spl_file = new_spl_path
1032
1033 if not os.path.exists(spl_file):
1034 # missing SPL loader
1035 raise AssertionError("Couldn't find the SPL file, tried %s and %s"
1036 % (old_spl_path, new_spl_path))
1037 return spl_file
1038
1039 @classmethod
1040 def _get_samsung_uboot(cls, chroot_dir):
1041 uboot_file = os.path.join(
1042 chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
1043 'u-boot.bin')
1044 return uboot_file
1045
1046 @classmethod
1047 def install_samsung_boot_loader(cls, chroot_dir, boot_device_or_file):
1048 spl_file = cls._get_samsung_spl(chroot_dir)
1049 bl1_max_size = SAMSUNG_V310_BL1_LEN * SECTOR_SIZE
1050 assert os.path.getsize(spl_file) <= bl1_max_size, (
1051 "%s is larger than %s" % (spl_file, bl1_max_size))
1052 _dd(spl_file, boot_device_or_file, seek=SAMSUNG_V310_BL1_START)
1053
1054 with cls.hardwarepack_handler:
1055 uboot_file = cls.get_file(
1056 'u_boot', default=cls._get_samsung_uboot(chroot_dir))
1057 bl2_max_size = SAMSUNG_V310_BL2_LEN * SECTOR_SIZE
1058 assert os.path.getsize(uboot_file) <= bl2_max_size, (
1059 "%s is larger than %s" % (uboot_file, bl2_max_size))
1060 _dd(uboot_file, boot_device_or_file, seek=SAMSUNG_V310_BL2_START)
1061
1062
1063class SMDKV310Config(SamsungConfig):
1064 uboot_flavor = 'smdkv310'
1065 serial_tty = 'ttySAC1'
1066 _extra_serial_opts = 'console=%s,115200n8'
1067 kernel_addr = '0x40007000'
1068 initrd_addr = '0x42000000'
1069 load_addr = '0x40008000'
1070 kernel_flavors = ['s5pv310']
1071 boot_script = 'boot.scr'
1072 mmc_part_offset = 1
1073 mmc_option = '0:2'
1074
1075 @classmethod
1076 def _get_boot_env(cls, is_live, is_lowmem, consoles, rootfs_uuid,
1077 d_img_data):
1078 boot_env = super(SamsungConfig, cls)._get_boot_env(
1079 is_live, is_lowmem, consoles, rootfs_uuid, d_img_data)
1080
1081 boot_env["ethact"] = "smc911x-0"
1082 boot_env["ethaddr"] = "00:40:5c:26:0a:5b"
1083
1084 return boot_env
1085
1086
1087class OrigenConfig(SamsungConfig):
1088 uboot_flavor = 'origen'
1089 serial_tty = 'ttySAC2'
1090 _extra_serial_opts = 'console=%s,115200n8'
1091 kernel_addr = '0x40007000'
1092 initrd_addr = '0x42000000'
1093 load_addr = '0x40008000'
1094 kernel_flavors = ['origen']
1095 boot_script = 'boot.scr'
1096 mmc_part_offset = 1
1097 mmc_option = '0:2'
1098
8281099
829board_configs = {1100board_configs = {
830 'beagle': BeagleConfig,1101 'beagle': BeagleConfig,
@@ -837,9 +1108,10 @@
837 'efikamx': EfikamxConfig,1108 'efikamx': EfikamxConfig,
838 'efikasb': EfikasbConfig,1109 'efikasb': EfikasbConfig,
839 'mx51evk': Mx51evkConfig,1110 'mx51evk': Mx51evkConfig,
840 'mx53loco' : Mx53LoCoConfig,1111 'mx53loco': Mx53LoCoConfig,
841 'overo': OveroConfig,1112 'overo': OveroConfig,
842 'smdkv310': SMDKV310Config,1113 'smdkv310': SMDKV310Config,
1114 'origen': OrigenConfig,
843 }1115 }
8441116
8451117
@@ -961,13 +1233,13 @@
961 return tmpfile1233 return tmpfile
9621234
9631235
964def install_mx5_boot_loader(imx_file, boot_device_or_file):1236def install_mx5_boot_loader(imx_file, boot_device_or_file, loader_min_size):
965 # bootloader partition starts at +1s but we write the file at +2s, so we1237 # bootloader partition starts at +1s but we write the file at +2s, so we
966 # need to check that the bootloader partition minus 1s is at least as large1238 # need to check that the bootloader partition minus 1s is at least as large
967 # as the u-boot binary; note that the real bootloader partition might be1239 # as the u-boot binary; note that the real bootloader partition might be
968 # larger than LOADER_MIN_SIZE_S, but if u-boot is larger it's a sign we1240 # larger than LOADER_MIN_SIZE_S, but if u-boot is larger it's a sign we
969 # need to bump LOADER_MIN_SIZE_S1241 # need to bump LOADER_MIN_SIZE_S
970 max_size = (LOADER_MIN_SIZE_S - 1) * SECTOR_SIZE1242 max_size = (loader_min_size - 1) * SECTOR_SIZE
971 assert os.path.getsize(imx_file) <= max_size, (1243 assert os.path.getsize(imx_file) <= max_size, (
972 "%s is larger than guaranteed bootloader partition size" % imx_file)1244 "%s is larger than guaranteed bootloader partition size" % imx_file)
973 _dd(imx_file, boot_device_or_file, seek=2)1245 _dd(imx_file, boot_device_or_file, seek=2)
@@ -1008,4 +1280,3 @@
1008 ["cp", "-v", boot_script_path, "%s/boot.ini" % boot_disk],1280 ["cp", "-v", boot_script_path, "%s/boot.ini" % boot_disk],
1009 as_root=True)1281 as_root=True)
1010 proc.wait()1282 proc.wait()
1011
10121283
=== modified file 'linaro_image_tools/media_create/partitions.py'
--- linaro_image_tools/media_create/partitions.py 2011-05-31 06:45:22 +0000
+++ linaro_image_tools/media_create/partitions.py 2011-07-18 14:39:34 +0000
@@ -3,7 +3,7 @@
3# Author: Guilherme Salgado <guilherme.salgado@linaro.org>3# Author: Guilherme Salgado <guilherme.salgado@linaro.org>
4#4#
5# This file is part of Linaro Image Tools.5# This file is part of Linaro Image Tools.
6# 6#
7# Linaro Image Tools is free software: you can redistribute it and/or modify7# Linaro Image Tools is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or9# the Free Software Foundation, either version 3 of the License, or
@@ -28,6 +28,7 @@
28 Device,28 Device,
29 Disk,29 Disk,
30 PARTITION_NORMAL,30 PARTITION_NORMAL,
31 PARTITION_EXTENDED,
31 )32 )
3233
33from linaro_image_tools import cmd_runner34from linaro_image_tools import cmd_runner
@@ -71,9 +72,8 @@
71 bootfs = partitions[0]72 bootfs = partitions[0]
72 system = partitions[1]73 system = partitions[1]
73 cache = partitions[2]74 cache = partitions[2]
74 data = partitions[4]75 data = partitions[3]
75 sdcard = partitions[5]76 sdcard = partitions[4]
76
7777
78 print "\nFormating boot partition\n"78 print "\nFormating boot partition\n"
79 proc = cmd_runner.run(79 proc = cmd_runner.run(
@@ -98,6 +98,7 @@
9898
99 return bootfs, system, cache, data, sdcard99 return bootfs, system, cache, data, sdcard
100100
101
101# I wonder if it'd make sense to convert this into a small shim which calls102# I wonder if it'd make sense to convert this into a small shim which calls
102# the appropriate function for the given type of device? I think it's still103# the appropriate function for the given type of device? I think it's still
103# small enough that there's not much benefit in doing that, but if it grows we104# small enough that there's not much benefit in doing that, but if it grows we
@@ -296,18 +297,28 @@
296 # Here we can use parted.Device to read the partitions because we're297 # Here we can use parted.Device to read the partitions because we're
297 # reading from a regular file rather than a block device. If it was a298 # reading from a regular file rather than a block device. If it was a
298 # block device we'd need root rights.299 # block device we'd need root rights.
300 vfat_partition = None
299 disk = Disk(Device(image_file))301 disk = Disk(Device(image_file))
300 partition_info = []302 partition_info = []
301 for partition in disk.partitions:303 for partition in disk.partitions:
302 geometry = partition.geometry304 # Will ignore any partitions before boot and of type EXTENDED
303 partition_info.append((geometry.start * SECTOR_SIZE,305 if 'boot' in partition.getFlagsAsString():
304 geometry.length * SECTOR_SIZE))306 vfat_partition = partition
307 geometry = partition.geometry
308 partition_info.append((geometry.start * SECTOR_SIZE,
309 geometry.length * SECTOR_SIZE))
310 elif (vfat_partition is not None and
311 partition.type != PARTITION_EXTENDED):
312 geometry = partition.geometry
313 partition_info.append((geometry.start * SECTOR_SIZE,
314 geometry.length * SECTOR_SIZE))
305 # NB: don't use vfat_partition.nextPartition() as that might return315 # NB: don't use vfat_partition.nextPartition() as that might return
306 # a partition of type PARTITION_FREESPACE; it's much easier to316 # a partition of type PARTITION_FREESPACE; it's much easier to
307 # iterate disk.partitions which only returns317 # iterate disk.partitions which only returns
308 # parted.PARTITION_NORMAL partitions318 # parted.PARTITION_NORMAL partitions
309319 assert vfat_partition is not None, (
310 assert len(partition_info) == 6320 "Couldn't find boot partition on %s" % image_file)
321 assert len(partition_info) == 5
311 return partition_info322 return partition_info
312323
313324
@@ -347,6 +358,7 @@
347 return boot_partition, system_partition, cache_partition, \358 return boot_partition, system_partition, cache_partition, \
348 data_partition, sdcard_partition359 data_partition, sdcard_partition
349360
361
350def get_boot_and_root_partitions_for_media(media, board_config):362def get_boot_and_root_partitions_for_media(media, board_config):
351 """Return the device files for the boot and root partitions of media.363 """Return the device files for the boot and root partitions of media.
352364
353365
=== modified file 'linaro_image_tools/media_create/rootfs.py'
--- linaro_image_tools/media_create/rootfs.py 2011-04-05 09:26:47 +0000
+++ linaro_image_tools/media_create/rootfs.py 2011-07-18 14:39:34 +0000
@@ -19,6 +19,7 @@
1919
20import glob20import glob
21import os21import os
22import subprocess
22import tempfile23import tempfile
2324
24from linaro_image_tools import cmd_runner25from linaro_image_tools import cmd_runner
@@ -107,13 +108,26 @@
107 flash_kernel, "UBOOT_PART=%s" % target_boot_dev)108 flash_kernel, "UBOOT_PART=%s" % target_boot_dev)
108109
109110
111def _list_files(directory):
112 """List the files and dirs under the given directory.
113
114 Runs as root because we want to list everything, including stuff that may
115 not be world-readable.
116 """
117 p = cmd_runner.run(
118 ['find', directory, '-maxdepth', '1', '-mindepth', '1'],
119 stdout=subprocess.PIPE, as_root=True)
120 stdout, _ = p.communicate()
121 return stdout.split()
122
123
110def move_contents(from_, root_disk):124def move_contents(from_, root_disk):
111 """Move everything under from_ to the given root disk.125 """Move everything under from_ to the given root disk.
112126
113 Uses sudo for moving.127 Uses sudo for moving.
114 """128 """
115 assert os.path.isdir(from_), "%s is not a directory" % from_129 assert os.path.isdir(from_), "%s is not a directory" % from_
116 files = glob.glob(os.path.join(from_, '*'))130 files = _list_files(from_)
117 mv_cmd = ['mv']131 mv_cmd = ['mv']
118 mv_cmd.extend(sorted(files))132 mv_cmd.extend(sorted(files))
119 mv_cmd.append(root_disk)133 mv_cmd.append(root_disk)
120134
=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
--- linaro_image_tools/media_create/tests/test_media_create.py 2011-06-14 09:45:13 +0000
+++ linaro_image_tools/media_create/tests/test_media_create.py 2011-07-18 14:39:34 +0000
@@ -28,7 +28,10 @@
28import textwrap28import textwrap
29import time29import time
30import types30import types
31import struct
32import tarfile
3133
34from StringIO import StringIO
32from testtools import TestCase35from testtools import TestCase
3336
34from linaro_image_tools import cmd_runner37from linaro_image_tools import cmd_runner
@@ -38,9 +41,11 @@
38 boards,41 boards,
39 partitions,42 partitions,
40 rootfs,43 rootfs,
44 android_boards,
41 )45 )
42from linaro_image_tools.media_create.boards import (46from linaro_image_tools.media_create.boards import (
43 LOADER_MIN_SIZE_S,47 SAMSUNG_V310_BL1_START,
48 SAMSUNG_V310_BL2_START,
44 SECTOR_SIZE,49 SECTOR_SIZE,
45 align_up,50 align_up,
46 align_partition,51 align_partition,
@@ -56,6 +61,11 @@
56 _get_file_matching,61 _get_file_matching,
57 _get_mlo_file,62 _get_mlo_file,
58 _run_mkimage,63 _run_mkimage,
64 HardwarepackHandler,
65 BoardConfig,
66 )
67from linaro_image_tools.media_create.android_boards import (
68 android_board_configs,
59 )69 )
60from linaro_image_tools.media_create.chroot_utils import (70from linaro_image_tools.media_create.chroot_utils import (
61 copy_file,71 copy_file,
@@ -113,6 +123,359 @@
113sudo_args = " ".join(cmd_runner.SUDO_ARGS)123sudo_args = " ".join(cmd_runner.SUDO_ARGS)
114124
115125
126class TestHardwarepackHandler(TestCaseWithFixtures):
127 def setUp(self):
128 super(TestHardwarepackHandler, self).setUp()
129 self.tar_dir_fixture = CreateTempDirFixture()
130 self.useFixture(self.tar_dir_fixture)
131
132 self.tarball_fixture = CreateTarballFixture(
133 self.tar_dir_fixture.get_temp_dir())
134 self.useFixture(self.tarball_fixture)
135
136 self.metadata = (
137 "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\nORIGIN=linaro\n")
138
139 def add_to_tarball(self, files, tarball=None):
140 if tarball is None:
141 tarball = self.tarball_fixture.get_tarball()
142 tar_file = tarfile.open(tarball, mode='w:gz')
143 for filename, data in files:
144 tarinfo = tarfile.TarInfo(filename)
145 tarinfo.size = len(data)
146 tar_file.addfile(tarinfo, StringIO(data))
147 tar_file.close()
148 return tarball
149
150 def test_get_format_1(self):
151 data = '1.0'
152 format = "%s\n" % data
153 tarball = self.add_to_tarball(
154 [('FORMAT', format), ('metadata', self.metadata)])
155 hp = HardwarepackHandler([tarball])
156 with hp:
157 self.assertEquals(hp.get_format(), data)
158
159 def test_get_format_2(self):
160 data = '2.0'
161 format = "%s\n" % data
162 tarball = self.add_to_tarball(
163 [('FORMAT', format), ('metadata', self.metadata)])
164 hp = HardwarepackHandler([tarball])
165 with hp:
166 self.assertEquals(hp.get_format(), data)
167
168 def test_get_unknown_format_raises(self):
169 data = '9.9'
170 format = "%s\n" % data
171 tarball = self.add_to_tarball(
172 [('FORMAT', format), ('metadata', self.metadata)])
173 hp = HardwarepackHandler([tarball])
174 with hp:
175 self.assertRaises(AssertionError, hp.get_format)
176
177 def test_mixed_formats(self):
178 format1 = "%s\n" % '1.0'
179 format2 = "%s\n" % '2.0'
180 tarball1 = self.add_to_tarball(
181 [('FORMAT', format1), ('metadata', self.metadata)],
182 tarball=self.tarball_fixture.get_tarball())
183 tarball_fixture2 = CreateTarballFixture(
184 self.tar_dir_fixture.get_temp_dir(), reldir='tarfile2',
185 filename='secondtarball.tar.gz')
186 self.useFixture(tarball_fixture2)
187 tarball2 = self.add_to_tarball(
188 [('FORMAT', format2), ('metadata', self.metadata)],
189 tarball=tarball_fixture2.get_tarball())
190 hp = HardwarepackHandler([tarball2, tarball1])
191 with hp:
192 self.assertEquals(hp.get_format(), '1.0and2.0')
193
194 def test_identical_formats_ok(self):
195 format1 = "%s\n" % '2.0'
196 format2 = "%s\n" % '2.0'
197 tarball1 = self.add_to_tarball(
198 [('FORMAT', format1), ('metadata', self.metadata)],
199 tarball=self.tarball_fixture.get_tarball())
200 tarball_fixture2 = CreateTarballFixture(
201 self.tar_dir_fixture.get_temp_dir(), reldir='tarfile2',
202 filename='secondtarball.tar.gz')
203 self.useFixture(tarball_fixture2)
204 tarball2 = self.add_to_tarball(
205 [('FORMAT', format2), ('metadata', self.metadata)],
206 tarball=tarball_fixture2.get_tarball())
207 hp = HardwarepackHandler([tarball1, tarball2])
208 with hp:
209 self.assertEquals(hp.get_format(), '2.0')
210
211 def test_get_metadata(self):
212 data = 'data to test'
213 metadata = self.metadata + "TEST=%s\n" % data
214 tarball = self.add_to_tarball(
215 [('metadata', metadata)])
216 hp = HardwarepackHandler([tarball])
217 with hp:
218 test_data, _ = hp.get_field(hp.main_section, 'test')
219 self.assertEqual(test_data, data)
220
221 def test_preserves_formatters(self):
222 data = '%s%d'
223 metadata = self.metadata + "TEST=%s\n" % data
224 tarball = self.add_to_tarball(
225 [('metadata', metadata)])
226 hp = HardwarepackHandler([tarball])
227 with hp:
228 test_data, _ = hp.get_field(hp.main_section, 'test')
229 self.assertEqual(test_data, data)
230
231 def test_creates_tempdir(self):
232 tarball = self.add_to_tarball(
233 [('metadata', self.metadata)])
234 hp = HardwarepackHandler([tarball])
235 with hp:
236 self.assertTrue(os.path.exists(hp.tempdir))
237
238 def test_tempfiles_are_removed(self):
239 tempdir = None
240 tarball = self.add_to_tarball(
241 [('metadata', self.metadata)])
242 hp = HardwarepackHandler([tarball])
243 with hp:
244 tempdir = hp.tempdir
245 self.assertFalse(os.path.exists(tempdir))
246
247 def test_get_file(self):
248 data = 'test file contents\n'
249 metadata_file = 'TESTFILE'
250 file_in_archive = 'testfile'
251 metadata = self.metadata + "%s=%s\n" % (metadata_file, file_in_archive)
252 tarball = self.add_to_tarball(
253 [('metadata', metadata),
254 (file_in_archive, data)])
255 hp = HardwarepackHandler([tarball])
256 with hp:
257 test_file = hp.get_file(metadata_file)
258 self.assertEquals(data, open(test_file, 'r').read())
259
260
261class TestSetMetadata(TestCaseWithFixtures):
262
263 class MockHardwarepackHandler(HardwarepackHandler):
264 metadata_dict = {}
265
266 def __enter__(self):
267 return self
268
269 def get_field(self, section, field):
270 try:
271 return self.metadata_dict[field], None
272 except:
273 return None, None
274
275 def get_format(self):
276 return '2.0'
277
278 def get_file(self, file_alias):
279 return None
280
281 def test_does_not_set_if_old_format(self):
282 self.useFixture(MockSomethingFixture(
283 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
284 self.MockHardwarepackHandler))
285
286 class config(BoardConfig):
287 pass
288 config.set_metadata('ahwpack.tar.gz')
289 self.assertEquals(None, config.kernel_addr)
290
291 def test_sets_kernel_addr(self):
292 self.useFixture(MockSomethingFixture(
293 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
294 self.MockHardwarepackHandler))
295 field_to_test = 'kernel_addr'
296 data_to_set = '0x8123ABCD'
297 self.MockHardwarepackHandler.metadata_dict = {
298 field_to_test: data_to_set,
299 }
300 class config(BoardConfig):
301 pass
302 config.set_metadata('ahwpack.tar.gz')
303 self.assertEquals(data_to_set, config.kernel_addr)
304
305 def test_sets_initrd_addr(self):
306 self.useFixture(MockSomethingFixture(
307 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
308 self.MockHardwarepackHandler))
309 field_to_test = 'initrd_addr'
310 data_to_set = '0x8123ABCD'
311 self.MockHardwarepackHandler.metadata_dict = {
312 field_to_test: data_to_set,
313 }
314 class config(BoardConfig):
315 pass
316 config.set_metadata('ahwpack.tar.gz')
317 self.assertEquals(data_to_set, config.initrd_addr)
318
319 def test_sets_load_addr(self):
320 self.useFixture(MockSomethingFixture(
321 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
322 self.MockHardwarepackHandler))
323 field_to_test = 'load_addr'
324 data_to_set = '0x8123ABCD'
325 self.MockHardwarepackHandler.metadata_dict = {
326 field_to_test: data_to_set,
327 }
328 class config(BoardConfig):
329 pass
330 config.set_metadata('ahwpack.tar.gz')
331 self.assertEquals(data_to_set, config.load_addr)
332
333 def test_sets_serial_tty(self):
334 self.useFixture(MockSomethingFixture(
335 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
336 self.MockHardwarepackHandler))
337 field_to_test = 'serial_tty'
338 data_to_set = 'ttyAA'
339 self.MockHardwarepackHandler.metadata_dict = {
340 field_to_test: data_to_set,
341 }
342 class config(BoardConfig):
343 pass
344 config.set_metadata('ahwpack.tar.gz')
345 self.assertEquals(data_to_set, config.serial_tty)
346
347 def test_sets_wired_interfaces(self):
348 self.useFixture(MockSomethingFixture(
349 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
350 self.MockHardwarepackHandler))
351 field_to_test = 'wired_interfaces'
352 data_to_set = 'eth0 eth1'
353 self.MockHardwarepackHandler.metadata_dict = {
354 field_to_test: data_to_set,
355 }
356 class config(BoardConfig):
357 pass
358 config.set_metadata('ahwpack.tar.gz')
359 self.assertEquals(data_to_set, config.wired_interfaces)
360
361 def test_sets_wireless_interfaces(self):
362 self.useFixture(MockSomethingFixture(
363 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
364 self.MockHardwarepackHandler))
365 field_to_test = 'wireless_interfaces'
366 data_to_set = 'wlan0 wl1'
367 self.MockHardwarepackHandler.metadata_dict = {
368 field_to_test: data_to_set,
369 }
370 class config(BoardConfig):
371 pass
372 config.set_metadata('ahwpack.tar.gz')
373 self.assertEquals(data_to_set, config.wireless_interfaces)
374
375 def test_sets_mmc_id(self):
376 self.useFixture(MockSomethingFixture(
377 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
378 self.MockHardwarepackHandler))
379 field_to_test = 'mmc_id'
380 data_to_set = '1'
381 self.MockHardwarepackHandler.metadata_dict = {
382 field_to_test: data_to_set,
383 }
384 class config(BoardConfig):
385 pass
386 config.set_metadata('ahwpack.tar.gz')
387 self.assertEquals(data_to_set, config.mmc_id)
388
389 def test_sets_boot_min_size(self):
390 self.useFixture(MockSomethingFixture(
391 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
392 self.MockHardwarepackHandler))
393 field_to_test = 'boot_min_size'
394 data_to_set = '100'
395 expected = align_up(int(data_to_set) * 1024 * 1024,
396 SECTOR_SIZE) / SECTOR_SIZE
397 self.MockHardwarepackHandler.metadata_dict = {
398 field_to_test: data_to_set,
399 }
400 class config(BoardConfig):
401 pass
402 config.set_metadata('ahwpack.tar.gz')
403 self.assertEquals(expected, config.BOOT_MIN_SIZE_S)
404
405 def test_sets_root_min_size(self):
406 self.useFixture(MockSomethingFixture(
407 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
408 self.MockHardwarepackHandler))
409 field_to_test = 'root_min_size'
410 data_to_set = '3'
411 expected = align_up(int(data_to_set) * 1024 * 1024,
412 SECTOR_SIZE) / SECTOR_SIZE
413 self.MockHardwarepackHandler.metadata_dict = {
414 field_to_test: data_to_set,
415 }
416 class config(BoardConfig):
417 pass
418 config.set_metadata('ahwpack.tar.gz')
419 self.assertEquals(expected, config.ROOT_MIN_SIZE_S)
420
421 def test_sets_loader_min_size(self):
422 self.useFixture(MockSomethingFixture(
423 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
424 self.MockHardwarepackHandler))
425 field_to_test = 'loader_min_size'
426 data_to_set = '2'
427 expected = align_up(int(data_to_set) * 1024 * 1024,
428 SECTOR_SIZE) / SECTOR_SIZE
429 self.MockHardwarepackHandler.metadata_dict = {
430 field_to_test: data_to_set,
431 }
432 class config(BoardConfig):
433 pass
434 config.set_metadata('ahwpack.tar.gz')
435 self.assertEquals(expected, config.LOADER_MIN_SIZE_S)
436
437 def test_sets_partition_layout_32(self):
438 self.useFixture(MockSomethingFixture(
439 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
440 self.MockHardwarepackHandler))
441 field_to_test = 'partition_layout'
442 data_to_set = 'bootfs_rootfs'
443 self.MockHardwarepackHandler.metadata_dict = {
444 field_to_test: data_to_set,
445 }
446 class config(BoardConfig):
447 pass
448 config.set_metadata('ahwpack.tar.gz')
449 self.assertEquals(32, config.fat_size)
450
451 def test_sets_partition_layout_16(self):
452 self.useFixture(MockSomethingFixture(
453 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
454 self.MockHardwarepackHandler))
455 field_to_test = 'partition_layout'
456 data_to_set = 'bootfs16_rootfs'
457 self.MockHardwarepackHandler.metadata_dict = {
458 field_to_test: data_to_set,
459 }
460 class config(BoardConfig):
461 pass
462 config.set_metadata('ahwpack.tar.gz')
463 self.assertEquals(16, config.fat_size)
464
465 def test_sets_partition_layout_raises(self):
466 self.useFixture(MockSomethingFixture(
467 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
468 self.MockHardwarepackHandler))
469 field_to_test = 'partition_layout'
470 data_to_set = 'bootfs_bogus_rootfs'
471 self.MockHardwarepackHandler.metadata_dict = {
472 field_to_test: data_to_set,
473 }
474 class config(BoardConfig):
475 pass
476 self.assertRaises(AssertionError, config.set_metadata, 'ahwpack.tar.gz')
477
478
116class TestGetMLOFile(TestCaseWithFixtures):479class TestGetMLOFile(TestCaseWithFixtures):
117480
118 def test_mlo_from_new_xloader(self):481 def test_mlo_from_new_xloader(self):
@@ -150,6 +513,325 @@
150 AssertionError, _get_mlo_file, tempdir)513 AssertionError, _get_mlo_file, tempdir)
151514
152515
516def _create_uboot_dir(root, flavor):
517 path = os.path.join(root, 'usr', 'lib', 'u-boot', flavor)
518 os.makedirs(path)
519 return path
520
521
522class TestGetSMDKSPL(TestCaseWithFixtures):
523 config = boards.SMDKV310Config
524
525 def test_no_file_present(self):
526 tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
527 self.assertRaises(
528 AssertionError, self.config._get_samsung_spl, tempdir)
529
530 def test_old_file_present(self):
531 tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
532 path = _create_uboot_dir(tempdir, self.config.uboot_flavor)
533 spl_path = os.path.join(path, 'v310_mmc_spl.bin')
534 open(spl_path, 'w').close()
535 self.assertEquals(spl_path, self.config._get_samsung_spl(tempdir))
536
537 def test_new_file_present(self):
538 tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
539 path = _create_uboot_dir(tempdir, self.config.uboot_flavor)
540 spl_path = os.path.join(path, 'u-boot-mmc-spl.bin')
541 open(spl_path, 'w').close()
542 self.assertEquals(spl_path, self.config._get_samsung_spl(tempdir))
543
544 def test_prefers_old_path(self):
545 tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
546 path = _create_uboot_dir(tempdir, self.config.uboot_flavor)
547 old_spl_path = os.path.join(path, 'v310_mmc_spl.bin')
548 new_spl_path = os.path.join(path, 'u-boot-mmc-spl.bin')
549 open(old_spl_path, 'w').close()
550 open(new_spl_path, 'w').close()
551 self.assertEquals(old_spl_path, self.config._get_samsung_spl(tempdir))
552
553
554class TestGetSMDKUboot(TestCaseWithFixtures):
555 config = boards.SMDKV310Config
556
557 def test_uses_uboot_flavour(self):
558 chroot_dir = "chroot"
559 uboot_file = os.path.join(chroot_dir, 'usr', 'lib', 'u-boot',
560 self.config.uboot_flavor, 'u-boot.bin')
561 self.assertEquals(
562 uboot_file, self.config._get_samsung_uboot(chroot_dir))
563
564
565class TestGetOrigenSPL(TestCaseWithFixtures):
566 config = boards.OrigenConfig
567
568 def test_no_file_present(self):
569 tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
570 self.assertRaises(
571 AssertionError, self.config._get_samsung_spl, tempdir)
572
573 def test_new_file_present(self):
574 tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
575 path = _create_uboot_dir(tempdir, self.config.uboot_flavor)
576 spl_path = os.path.join(path, 'u-boot-mmc-spl.bin')
577 open(spl_path, 'w').close()
578 self.assertEquals(spl_path, self.config._get_samsung_spl(tempdir))
579
580
581class TestGetOrigenUboot(TestGetSMDKUboot):
582 config = boards.OrigenConfig
583
584
585class TestCreateToc(TestCaseWithFixtures):
586 ''' Tests boards.SnowballEmmcConfig.create_toc()'''
587
588 def setUp(self):
589 ''' Create a temporary directory to work in'''
590 super(TestCreateToc, self).setUp()
591 self.tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
592 #Create the test's input data structures
593 zero = '\x00\x00\x00\x00'
594 line1 = zero + zero + zero + zero + zero + 'b' + zero + zero + \
595 '\x00\x00\x00'
596 maxint = '\xFF\xFF\xFF\x7F'
597 minint = '\xFF\xFF\xFF\xFF'
598 line2 = maxint + maxint + zero + minint + minint + \
599 'hello' + zero + '\x00\x00\x00'
600 line3 = '\x01\x00\x00\x00' '\x64\x00\x00\x00' + zero + \
601 '\x05\x00\x00\x00' '\x05\x00\x00\x00' \
602 'hello' + zero + '\x00\x00\x00'
603 self.expected = line1 + line2 + line3
604
605 def create_files_structure(self, src_data):
606 ''' Creates the data structure that the tested function
607 needs as input'''
608 files = []
609 for line in src_data:
610 files.append({'section_name': line[5],
611 'filename': 'N/A',
612 'align': line[3],
613 'offset': line[0],
614 'size': line[1],
615 'load_adress': 'N/A'})
616 return files
617
618 def test_create_toc_normal_case(self):
619 ''' Creates a toc file, and then reads the created
620 file and compares it to precomputed data'''
621 correct_data = [(0, 0, 0, 0, 0, 'b'),
622 (0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, -1, -1, 'hello'),
623 (1, 100, 1000, 5, 10, 'hello')]
624 files = self.create_files_structure(correct_data)
625 filename = os.path.join(self.tempdir, 'toc')
626 with open(filename, 'w') as f:
627 boards.SnowballEmmcConfig.create_toc(f, files)
628 with open(filename, 'r') as f:
629 actual = f.read()
630 self.assertEquals(96, len(actual))
631 for i in range(len(actual)):
632 self.assertEquals(self.expected[i], actual[i], 'Mismatch at ix' \
633 ' %d, ref=%c, actual=%c' % (i, self.expected[i], actual[i]))
634
635 def test_create_toc_error_too_large_section_name(self):
636 '''Verify that trying to write past the end of the
637 section name field raises an exception'''
638 illegal_name_data = [(0, 0, 0, 0, 0, 'Too_longName')]
639 files = self.create_files_structure(illegal_name_data)
640 with open(os.path.join(self.tempdir, 'toc'), 'w') as f:
641 self.assertRaises(AssertionError,
642 boards.SnowballEmmcConfig.create_toc,
643 f, files)
644
645 def test_create_toc_error_negative_unsigned(self):
646 '''Verify that trying to write a negative number to an unsigned
647 field raises an exception'''
648 illegal_unsigned_data = [(-3, 0, 0, 0, 0, 'xxx')]
649 files = self.create_files_structure(illegal_unsigned_data)
650 with open(os.path.join(self.tempdir, 'toc'), 'w') as f:
651 self.assertRaises(struct.error,
652 boards.SnowballEmmcConfig.create_toc,
653 f, files)
654
655
656class TestSnowballBootFiles(TestCaseWithFixtures):
657 ''' Tests boards.SnowballEmmcConfig.install_snowball_boot_loader()'''
658 ''' Tests boards.SnowballEmmcConfig._make_boot_files()'''
659 ''' Tests boards.SnowballEmmcConfig.get_file_info()'''
660
661 def setUp(self):
662 ''' Create temporary directory to work in'''
663 super(TestSnowballBootFiles, self).setUp()
664 self.tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
665 self.temp_bootdir_path = os.path.join(self.tempdir, 'boot')
666 if not os.path.exists(self.temp_bootdir_path):
667 os.makedirs(self.temp_bootdir_path)
668
669 def setupFiles(self):
670 ''' Adds some files in the temp dir that the tested function
671 can use as input:
672 * A config file, which the tested function reads to
673 discover which binary files should be written to
674 the loader partition.
675 * Test versions of the binary files themselves,
676 containing dummy data.
677 Returns the expected value that the tested function should
678 return, given these input files. '''
679 src_data = [('ISSW', 'boot_image_issw.bin', -1, 0, '5'),
680 ('X-LOADER', 'boot_image_x-loader.bin', -1, 0, '6'),
681 ('MEM_INIT', 'mem_init.bin', 0, 0x160000, '7'),
682 ('PWR_MGT', 'power_management.bin', 0, 0x170000, '8'),
683 ('NORMAL', 'u-boot.bin', 0, 0xBA0000, '9'),
684 ('UBOOT_ENV', 'u-boot-env.bin', 0, 0x00C1F000, '10')]
685 # Create a config file
686 cfg_file = os.path.join(self.temp_bootdir_path,
687 boards.SnowballEmmcConfig.SNOWBALL_STARTUP_FILES_CONFIG)
688 with open(cfg_file, 'w') as f:
689 for line in src_data:
690 # Write comments, so we test that the parser can read them
691 f.write('#Yet another comment\n')
692 f.write('%s %s %i %#x %s\n' % line)
693 expected = []
694 # Define dummy binary files, containing nothing but their own
695 # section names.
696 for line in src_data:
697 with open(os.path.join(self.temp_bootdir_path, line[1]), 'w') as f:
698 f.write(line[0])
699 #define the expected values read from the config file
700 expected = []
701 ofs = [boards.SnowballEmmcConfig.TOC_SIZE,
702 boards.SnowballEmmcConfig.TOC_SIZE + len('ISSW'), 0x160000,
703 0x170000, 0xBA0000, 0xC1F000]
704 size = [len('ISSW'), len('X-LOADER'), len('MEM_INIT'), \
705 len('PWR_MGT'), len('NORMAL'), len('UBOOT_ENV')]
706 i = 0
707 for line in src_data:
708 filename = os.path.join(self.temp_bootdir_path, line[1])
709 expected.append({'section_name': line[0],
710 'filename': filename,
711 'align': int(line[2]),
712 'offset': ofs[i],
713 'size': long(size[i]),
714 'load_adress': line[4]})
715 i += 1
716 return expected
717
718 def test_file_name_size(self):
719 ''' Test using a to large toc file '''
720 _, toc_filename = tempfile.mkstemp()
721 atexit.register(os.unlink, toc_filename)
722 filedata = 'X'
723 bytes = boards.SnowballEmmcConfig.TOC_SIZE + 1
724 tmpfile = open(toc_filename, 'wb')
725 for n in xrange(bytes):
726 tmpfile.write(filedata)
727 tmpfile.close()
728 files = self.setupFiles()
729 self.assertRaises(AssertionError,
730 boards.SnowballEmmcConfig.install_snowball_boot_loader,
731 toc_filename, files, "boot_device_or_file",
732 boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S)
733
734 def test_install_snowball_boot_loader_toc(self):
735 fixture = self.useFixture(MockCmdRunnerPopenFixture())
736 toc_filename = self.createTempFileAsFixture()
737 files = self.setupFiles()
738 boards.SnowballEmmcConfig.install_snowball_boot_loader(toc_filename,
739 files, "boot_device_or_file",
740 boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S)
741 expected = [
742 '%s dd if=%s of=boot_device_or_file bs=512 conv=notrunc' \
743 ' seek=%s' % (sudo_args, toc_filename,
744 boards.SnowballEmmcConfig.SNOWBALL_LOADER_START_S),
745 '%s dd if=%s/boot_image_issw.bin of=boot_device_or_file bs=512' \
746 ' conv=notrunc seek=257' % (sudo_args, self.temp_bootdir_path),
747 '%s rm %s/boot_image_issw.bin' % (sudo_args,
748 self.temp_bootdir_path),
749 '%s dd if=%s/boot_image_x-loader.bin of=boot_device_or_file' \
750 ' bs=1 conv=notrunc seek=131588'
751 % (sudo_args, self.temp_bootdir_path),
752 '%s rm %s/boot_image_x-loader.bin' % (sudo_args,
753 self.temp_bootdir_path),
754 '%s dd if=%s/mem_init.bin of=boot_device_or_file bs=512' \
755 ' conv=notrunc seek=3072' % (sudo_args, self.temp_bootdir_path),
756 '%s rm %s/mem_init.bin' % (sudo_args, self.temp_bootdir_path),
757 '%s dd if=%s/power_management.bin of=boot_device_or_file bs=512' \
758 ' conv=notrunc seek=3200' % (sudo_args, self.temp_bootdir_path),
759 '%s rm %s/power_management.bin' % (sudo_args,
760 self.temp_bootdir_path),
761 '%s dd if=%s/u-boot.bin of=boot_device_or_file bs=512' \
762 ' conv=notrunc seek=24064' % (sudo_args, self.temp_bootdir_path),
763 '%s rm %s/u-boot.bin' % (sudo_args, self.temp_bootdir_path),
764 '%s dd if=%s/u-boot-env.bin of=boot_device_or_file bs=512'
765 ' conv=notrunc seek=25080' % (sudo_args, self.temp_bootdir_path),
766 '%s rm %s/u-boot-env.bin' % (sudo_args, self.temp_bootdir_path)]
767
768 self.assertEqual(expected, fixture.mock.commands_executed)
769
770 def test_snowball_make_boot_files(self):
771 fixture = self.useFixture(MockCmdRunnerPopenFixture())
772 self.useFixture(MockSomethingFixture(tempfile, 'mkstemp',
773 lambda: (-1, '/tmp/temp_snowball_make_boot_files')))
774 self.setupFiles()
775 k_img_file = os.path.join(self.tempdir, 'vmlinuz-1-ux500')
776 i_img_file = os.path.join(self.tempdir, 'initrd.img-1-ux500')
777
778 boot_env = board_configs['snowball_emmc']._get_boot_env(
779 is_live=False, is_lowmem=False, consoles=[],
780 rootfs_uuid="test_boot_env_uuid", d_img_data=None)
781 boards.SnowballEmmcConfig._make_boot_files(boot_env, self.tempdir,
782 self.temp_bootdir_path, 'boot_device_or_file', k_img_file,
783 i_img_file, None)
784 expected = [
785 '%s mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e' \
786 ' 0x00008000 -n Linux -d %s %s/boot/uImage' % (sudo_args,
787 k_img_file, self.tempdir),
788 '%s cp /tmp/temp_snowball_make_boot_files %s/boot/boot.txt'
789 % (sudo_args, self.tempdir),
790 '%s mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n boot' \
791 ' script -d %s/boot/boot.txt %s/boot/flash.scr'
792 % (sudo_args, self.tempdir, self.tempdir),
793 '%s dd if=/tmp/temp_snowball_make_boot_files' \
794 ' of=boot_device_or_file bs=512 conv=notrunc seek=256'
795 % (sudo_args),
796 '%s dd if=%s/boot/boot_image_issw.bin of=boot_device_or_file' \
797 ' bs=512 conv=notrunc seek=257' % (sudo_args, self.tempdir),
798 '%s rm %s/boot_image_issw.bin' % (sudo_args,
799 self.temp_bootdir_path),
800 '%s dd if=%s/boot/boot_image_x-loader.bin of=boot_device_or_file' \
801 ' bs=1 conv=notrunc seek=131588' % (sudo_args, self.tempdir),
802 '%s rm %s/boot_image_x-loader.bin' % (sudo_args,
803 self.temp_bootdir_path),
804 '%s dd if=%s/boot/mem_init.bin of=boot_device_or_file bs=512' \
805 ' conv=notrunc seek=3072' % (sudo_args, self.tempdir),
806 '%s rm %s/mem_init.bin' % (sudo_args, self.temp_bootdir_path),
807 '%s dd if=%s/boot/power_management.bin of=boot_device_or_file' \
808 ' bs=512 conv=notrunc seek=3200' % (sudo_args, self.tempdir),
809 '%s rm %s/power_management.bin' % (sudo_args,
810 self.temp_bootdir_path),
811 '%s dd if=%s/boot/u-boot.bin of=boot_device_or_file bs=512' \
812 ' conv=notrunc seek=24064' % (sudo_args, self.tempdir),
813 '%s rm %s/u-boot.bin' % (sudo_args, self.temp_bootdir_path),
814 '%s dd if=%s/boot/u-boot-env.bin of=boot_device_or_file bs=512' \
815 ' conv=notrunc seek=25080' % (sudo_args, self.tempdir),
816 '%s rm %s/u-boot-env.bin' % (sudo_args, self.temp_bootdir_path),
817 '%s rm /tmp/temp_snowball_make_boot_files' % (sudo_args),
818 '%s rm %s/startfiles.cfg' % (sudo_args, self.temp_bootdir_path)]
819
820 self.assertEqual(expected, fixture.mock.commands_executed)
821
822 def test_missing_files(self):
823 '''When the files cannot be read, an IOError should be raised'''
824 self.assertRaises(IOError,
825 boards.SnowballEmmcConfig.get_file_info,
826 self.tempdir)
827
828 def test_normal_case(self):
829 expected = self.setupFiles()
830 actual = boards.SnowballEmmcConfig.get_file_info(
831 self.temp_bootdir_path)
832 self.assertEquals(expected, actual)
833
834
153class TestBootSteps(TestCaseWithFixtures):835class TestBootSteps(TestCaseWithFixtures):
154836
155 def setUp(self):837 def setUp(self):
@@ -199,6 +881,10 @@
199 def test_mx5_steps(self):881 def test_mx5_steps(self):
200 class SomeMx5Config(boards.Mx5Config):882 class SomeMx5Config(boards.Mx5Config):
201 uboot_flavor = 'uboot_flavor'883 uboot_flavor = 'uboot_flavor'
884 SomeMx5Config.hardwarepack_handler = (
885 TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
886 SomeMx5Config.hardwarepack_handler.get_format = (
887 lambda: '1.0')
202 self.make_boot_files(SomeMx5Config)888 self.make_boot_files(SomeMx5Config)
203 expected = [889 expected = [
204 'install_mx5_boot_loader', 'make_uImage', 'make_uInitrd',890 'install_mx5_boot_loader', 'make_uImage', 'make_uInitrd',
@@ -206,9 +892,40 @@
206 self.assertEqual(expected, self.funcs_calls)892 self.assertEqual(expected, self.funcs_calls)
207893
208 def test_smdkv310_steps(self):894 def test_smdkv310_steps(self):
895 def mock_func_creator(name):
896 return classmethod(
897 lambda *args, **kwargs: self.funcs_calls.append(name))
898
899 self.useFixture(MockSomethingFixture(
900 linaro_image_tools.media_create.boards.SMDKV310Config,
901 'install_samsung_boot_loader',
902 mock_func_creator('install_samsung_boot_loader')))
903 boards.SMDKV310Config.hardwarepack_handler = (
904 TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
905 boards.SMDKV310Config.hardwarepack_handler.get_format = (
906 lambda: '1.0')
209 self.make_boot_files(boards.SMDKV310Config)907 self.make_boot_files(boards.SMDKV310Config)
210 expected = [908 expected = [
211 '_dd', '_dd', 'make_flashable_env', '_dd', 'make_uImage',909 'install_samsung_boot_loader', 'make_flashable_env', '_dd', 'make_uImage',
910 'make_uInitrd', 'make_boot_script']
911 self.assertEqual(expected, self.funcs_calls)
912
913 def test_origen_steps(self):
914 def mock_func_creator(name):
915 return classmethod(
916 lambda *args, **kwargs: self.funcs_calls.append(name))
917
918 self.useFixture(MockSomethingFixture(
919 linaro_image_tools.media_create.boards.OrigenConfig,
920 'install_samsung_boot_loader',
921 mock_func_creator('install_samsung_boot_loader')))
922 boards.OrigenConfig.hardwarepack_handler = (
923 TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
924 boards.OrigenConfig.hardwarepack_handler.get_format = (
925 lambda: '1.0')
926 self.make_boot_files(boards.OrigenConfig)
927 expected = [
928 'install_samsung_boot_loader', 'make_flashable_env', '_dd', 'make_uImage',
212 'make_uInitrd', 'make_boot_script']929 'make_uInitrd', 'make_boot_script']
213 self.assertEqual(expected, self.funcs_calls)930 self.assertEqual(expected, self.funcs_calls)
214931
@@ -354,6 +1071,23 @@
354 '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',1071 '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
355 board_configs['smdkv310'].get_sfdisk_cmd())1072 board_configs['smdkv310'].get_sfdisk_cmd())
3561073
1074 def test_origen(self):
1075 self.assertEquals(
1076 '1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
1077 board_configs['origen'].get_sfdisk_cmd())
1078
1079 def test_panda_android(self):
1080 self.assertEqual(
1081 '63,270272,0x0C,*\n270336,524288,L\n794624,524288,L\n' \
1082 '1318912,-,E\n1318912,1048576,L\n2367488,,,-',
1083 android_boards.AndroidPandaConfig.get_sfdisk_cmd())
1084
1085 def test_snowball_emmc_android(self):
1086 self.assertEqual(
1087 '256,7936,0xDA\n8192,262144,0x0C,*\n270336,524288,L\n' \
1088 '794624,-,E\n794624,524288,L\n1318912,1048576,L\n2367488,,,-',
1089 android_boards.AndroidSnowballEmmcConfig.get_sfdisk_cmd())
1090
3571091
358class TestGetBootCmd(TestCase):1092class TestGetBootCmd(TestCase):
3591093
@@ -396,6 +1130,18 @@
396 'ethaddr': '00:40:5c:26:0a:5b'}1130 'ethaddr': '00:40:5c:26:0a:5b'}
397 self.assertEqual(expected, boot_commands)1131 self.assertEqual(expected, boot_commands)
3981132
1133 def test_origen(self):
1134 boot_commands = board_configs['origen']._get_boot_env(
1135 is_live=False, is_lowmem=False, consoles=[],
1136 rootfs_uuid="deadbeef", d_img_data=None)
1137 expected = {
1138 'bootargs': 'console=ttySAC2,115200n8 root=UUID=deadbeef '
1139 'rootwait ro',
1140 'bootcmd': 'fatload mmc 0:2 0x40007000 uImage; '
1141 'fatload mmc 0:2 0x42000000 uInitrd; '
1142 'bootm 0x40007000 0x42000000'}
1143 self.assertEqual(expected, boot_commands)
1144
399 def test_ux500(self):1145 def test_ux500(self):
400 boot_commands = board_configs['ux500']._get_boot_env(1146 boot_commands = board_configs['ux500']._get_boot_env(
401 is_live=False, is_lowmem=False, consoles=[],1147 is_live=False, is_lowmem=False, consoles=[],
@@ -509,6 +1255,41 @@
509 self.assertEqual(expected, boot_commands)1255 self.assertEqual(expected, boot_commands)
5101256
5111257
1258class TestGetBootCmdAndroid(TestCase):
1259 def test_panda(self):
1260 # XXX: To fix bug 697824 we have to change class attributes of our
1261 # OMAP board configs, and some tests do that so to make sure they
1262 # don't interfere with us we'll reset that before doing anything.
1263 config = android_board_configs['panda']
1264 config.serial_tty = config._serial_tty
1265 boot_commands = config._get_boot_env(consoles=[])
1266 expected = {
1267 'bootargs': 'console=tty0 console=ttyO2,115200n8 '
1268 'rootwait ro earlyprintk fixrtc '
1269 'nocompcache vram=48M omapfb.vram=0:24M,1:24M '
1270 'mem=456M@0x80000000 mem=512M@0xA0000000 '
1271 'init=/init androidboot.console=ttyO2',
1272 'bootcmd': 'fatload mmc 0:1 0x80200000 uImage; '
1273 'fatload mmc 0:1 0x81600000 uInitrd; '
1274 'bootm 0x80200000 0x81600000'}
1275 self.assertEqual(expected, boot_commands)
1276
1277 def test_android_snowball_emmc(self):
1278 boot_commands = (android_boards.AndroidSnowballEmmcConfig.
1279 _get_boot_env(consoles=[]))
1280 expected = {
1281 'bootargs': 'console=tty0 console=ttyAMA2,115200n8 '
1282 'rootwait ro earlyprintk '
1283 'rootdelay=1 fixrtc nocompcache '
1284 'mem=128M@0 mali.mali_mem=64M@128M mem=24M@192M '
1285 'hwmem=167M@216M mem_issw=1M@383M mem=640M@384M '
1286 'vmalloc=256M init=/init androidboot.console=ttyAMA2',
1287 'bootcmd': 'fatload mmc 1:1 0x00100000 uImage; '
1288 'fatload mmc 1:1 0x08000000 uInitrd; '
1289 'bootm 0x00100000 0x08000000'}
1290 self.assertEqual(expected, boot_commands)
1291
1292
512class TestUnpackBinaryTarball(TestCaseWithFixtures):1293class TestUnpackBinaryTarball(TestCaseWithFixtures):
5131294
514 def setUp(self):1295 def setUp(self):
@@ -607,7 +1388,8 @@
607 def test_install_mx5_boot_loader(self):1388 def test_install_mx5_boot_loader(self):
608 fixture = self._mock_Popen()1389 fixture = self._mock_Popen()
609 imx_file = self.createTempFileAsFixture()1390 imx_file = self.createTempFileAsFixture()
610 install_mx5_boot_loader(imx_file, "boot_device_or_file")1391 install_mx5_boot_loader(imx_file, "boot_device_or_file",
1392 BoardConfig.LOADER_MIN_SIZE_S)
611 expected = [1393 expected = [
612 '%s dd if=%s of=boot_device_or_file bs=512 '1394 '%s dd if=%s of=boot_device_or_file bs=512 '
613 'conv=notrunc seek=2' % (sudo_args, imx_file)]1395 'conv=notrunc seek=2' % (sudo_args, imx_file)]
@@ -616,9 +1398,10 @@
616 def test_install_mx5_boot_loader_too_large(self):1398 def test_install_mx5_boot_loader_too_large(self):
617 self.useFixture(MockSomethingFixture(1399 self.useFixture(MockSomethingFixture(
618 os.path, "getsize",1400 os.path, "getsize",
619 lambda s: (LOADER_MIN_SIZE_S - 1) * SECTOR_SIZE + 1))1401 lambda s: (BoardConfig.LOADER_MIN_SIZE_S - 1) * SECTOR_SIZE + 1))
620 self.assertRaises(AssertionError,1402 self.assertRaises(AssertionError,
621 install_mx5_boot_loader, "imx_file", "boot_device_or_file")1403 install_mx5_boot_loader, "imx_file", "boot_device_or_file",
1404 BoardConfig.LOADER_MIN_SIZE_S)
6221405
623 def test_install_omap_boot_loader(self):1406 def test_install_omap_boot_loader(self):
624 fixture = self._mock_Popen()1407 fixture = self._mock_Popen()
@@ -630,6 +1413,58 @@
630 '%s cp -v chroot_dir/MLO boot_disk' % sudo_args, 'sync']1413 '%s cp -v chroot_dir/MLO boot_disk' % sudo_args, 'sync']
631 self.assertEqual(expected, fixture.mock.commands_executed)1414 self.assertEqual(expected, fixture.mock.commands_executed)
6321415
1416 def test_install_smdk_u_boot(self):
1417 fixture = self._mock_Popen()
1418 uboot_flavor = boards.SMDKV310Config.uboot_flavor
1419 self.useFixture(MockSomethingFixture(
1420 boards.SMDKV310Config, '_get_samsung_spl',
1421 classmethod(lambda cls, chroot_dir: "%s/%s/SPL" % (
1422 chroot_dir, uboot_flavor))))
1423 self.useFixture(MockSomethingFixture(
1424 boards.SMDKV310Config, '_get_samsung_uboot',
1425 classmethod(lambda cls, chroot_dir: "%s/%s/uboot" % (
1426 chroot_dir, uboot_flavor))))
1427 boards.SMDKV310Config.hardwarepack_handler = (
1428 TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
1429 boards.SMDKV310Config.hardwarepack_handler.get_format = (
1430 lambda: '1.0')
1431 self.useFixture(MockSomethingFixture(os.path, 'getsize',
1432 lambda file: 1))
1433 boards.SMDKV310Config.install_samsung_boot_loader(
1434 "chroot_dir", "boot_disk")
1435 expected = [
1436 '%s dd if=chroot_dir/%s/SPL of=boot_disk bs=512 conv=notrunc '
1437 'seek=%d' % (sudo_args, uboot_flavor, SAMSUNG_V310_BL1_START),
1438 '%s dd if=chroot_dir/%s/uboot of=boot_disk bs=512 conv=notrunc '
1439 'seek=%d' % (sudo_args, uboot_flavor, SAMSUNG_V310_BL2_START)]
1440 self.assertEqual(expected, fixture.mock.commands_executed)
1441
1442 def test_install_origen_u_boot(self):
1443 fixture = self._mock_Popen()
1444 uboot_flavor = boards.OrigenConfig.uboot_flavor
1445 self.useFixture(MockSomethingFixture(
1446 boards.OrigenConfig, '_get_samsung_spl',
1447 classmethod(lambda cls, chroot_dir: "%s/%s/SPL" % (
1448 chroot_dir, uboot_flavor))))
1449 self.useFixture(MockSomethingFixture(
1450 boards.OrigenConfig, '_get_samsung_uboot',
1451 classmethod(lambda cls, chroot_dir: "%s/%s/uboot" % (
1452 chroot_dir, uboot_flavor))))
1453 boards.OrigenConfig.hardwarepack_handler = (
1454 TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz'))
1455 boards.OrigenConfig.hardwarepack_handler.get_format = (
1456 lambda: '1.0')
1457 self.useFixture(MockSomethingFixture(os.path, 'getsize',
1458 lambda file: 1))
1459 boards.OrigenConfig.install_samsung_boot_loader(
1460 "chroot_dir", "boot_disk")
1461 expected = [
1462 '%s dd if=chroot_dir/%s/SPL of=boot_disk bs=512 conv=notrunc '
1463 'seek=%d' % (sudo_args, uboot_flavor, SAMSUNG_V310_BL1_START),
1464 '%s dd if=chroot_dir/%s/uboot of=boot_disk bs=512 conv=notrunc '
1465 'seek=%d' % (sudo_args, uboot_flavor, SAMSUNG_V310_BL2_START)]
1466 self.assertEqual(expected, fixture.mock.commands_executed)
1467
633 def test_get_plain_boot_script_contents(self):1468 def test_get_plain_boot_script_contents(self):
634 boot_env = {'bootargs': 'mybootargs', 'bootcmd': 'mybootcmd'}1469 boot_env = {'bootargs': 'mybootargs', 'bootcmd': 'mybootcmd'}
635 boot_script_data = get_plain_boot_script_contents(boot_env)1470 boot_script_data = get_plain_boot_script_contents(boot_env)
@@ -820,6 +1655,25 @@
820 [('1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-', HEADS,1655 [('1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-', HEADS,
821 SECTORS, '', self.media.path)], sfdisk_fixture.mock.calls)1656 SECTORS, '', self.media.path)], sfdisk_fixture.mock.calls)
8221657
1658 def test_create_partitions_for_origen(self):
1659 # For this board we create a one cylinder partition at the beginning.
1660 popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
1661 sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
1662
1663 create_partitions(
1664 board_configs['origen'], self.media, HEADS, SECTORS, '')
1665
1666 self.assertEqual(
1667 ['%s parted -s %s mklabel msdos' % (sudo_args, self.media.path),
1668 'sync'],
1669 popen_fixture.mock.commands_executed)
1670 # Notice that we create all partitions in a single sfdisk run because
1671 # every time we run sfdisk it actually repartitions the device,
1672 # erasing any partitions created previously.
1673 self.assertEqual(
1674 [('1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-', HEADS,
1675 SECTORS, '', self.media.path)], sfdisk_fixture.mock.calls)
1676
823 def test_create_partitions_for_beagle(self):1677 def test_create_partitions_for_beagle(self):
824 popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())1678 popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
825 sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())1679 sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
@@ -893,13 +1747,21 @@
893 (63 * SECTOR_SIZE, 32768 * SECTOR_SIZE),1747 (63 * SECTOR_SIZE, 32768 * SECTOR_SIZE),
894 (32831 * SECTOR_SIZE, 65536 * SECTOR_SIZE),1748 (32831 * SECTOR_SIZE, 65536 * SECTOR_SIZE),
895 (98367 * SECTOR_SIZE, 65536 * SECTOR_SIZE),1749 (98367 * SECTOR_SIZE, 65536 * SECTOR_SIZE),
896 (294975 * SECTOR_SIZE, (self.android_image_size -
897 294975 * SECTOR_SIZE)),
898 ((294975 + ext_part_size) * SECTOR_SIZE,1750 ((294975 + ext_part_size) * SECTOR_SIZE,
899 (131072 - ext_part_size) * SECTOR_SIZE),1751 (131072 - ext_part_size) * SECTOR_SIZE),
900 ((426047 + ext_part_size) * SECTOR_SIZE, 1752 ((426047 + ext_part_size) * SECTOR_SIZE,
901 self.android_image_size - (426047 + ext_part_size) * SECTOR_SIZE)1753 self.android_image_size - (426047 + ext_part_size) * SECTOR_SIZE)
902 ]1754 ]
1755
1756 self.android_snowball_offsets_and_sizes = [
1757 (8192 * SECTOR_SIZE, 24639 * SECTOR_SIZE),
1758 (32831 * SECTOR_SIZE, 65536 * SECTOR_SIZE),
1759 ((98367 + ext_part_size)* SECTOR_SIZE,
1760 (65536 - ext_part_size) * SECTOR_SIZE),
1761 (294975 * SECTOR_SIZE, 131072 * SECTOR_SIZE),
1762 ((426047 + ext_part_size) * SECTOR_SIZE,
1763 self.android_image_size - (426047 + ext_part_size) * SECTOR_SIZE)
1764 ]
9031765
904 def tearDown(self):1766 def tearDown(self):
905 super(TestPartitionSetup, self).tearDown()1767 super(TestPartitionSetup, self).tearDown()
@@ -916,6 +1778,13 @@
916 '63,32768,0x0C,*\n32831,65536,L\n98367,65536,L\n294975,-,E\n' \1778 '63,32768,0x0C,*\n32831,65536,L\n98367,65536,L\n294975,-,E\n' \
917 '294975,131072,L\n426047,,,-', '%s' % self.android_image_size)1779 '294975,131072,L\n426047,,,-', '%s' % self.android_image_size)
9181780
1781 def _create_snowball_android_tmpfile(self):
1782 # raw, boot, system, cache, (extended), userdata and sdcard partitions
1783 return self._create_qemu_img_with_partitions(
1784 '256,7936,0xDA\n8192,24639,0x0C,*\n32831,65536,L\n' \
1785 '98367,-,E\n98367,65536,L\n294975,131072,L\n' \
1786 '426047,,,-', '%s' % self.android_image_size)
1787
919 def test_convert_size_no_suffix(self):1788 def test_convert_size_no_suffix(self):
920 self.assertEqual(524288, convert_size_to_bytes('524288'))1789 self.assertEqual(524288, convert_size_to_bytes('524288'))
9211790
@@ -945,6 +1814,15 @@
945 self.android_offsets_and_sizes):1814 self.android_offsets_and_sizes):
946 self.assertEqual(device_pair, expected_pair)1815 self.assertEqual(device_pair, expected_pair)
9471816
1817 def test_calculate_snowball_android_partition_size_and_offset(self):
1818 tmpfile = self._create_snowball_android_tmpfile()
1819 device_info = calculate_android_partition_size_and_offset(tmpfile)
1820 # We use map(None, ...) since it would catch if the lists are not of
1821 # equal length and zip() would not in all cases.
1822 for device_pair, expected_pair in map(None, device_info,
1823 self.android_snowball_offsets_and_sizes):
1824 self.assertEqual(device_pair, expected_pair)
1825
948 def test_partition_numbering(self):1826 def test_partition_numbering(self):
949 # another Linux partition at +24 MiB after the boot/root parts1827 # another Linux partition at +24 MiB after the boot/root parts
950 tmpfile = self._create_qemu_img_with_partitions(1828 tmpfile = self._create_qemu_img_with_partitions(
@@ -1054,7 +1932,7 @@
10541932
1055 # get_boot_and_root_loopback_devices will also setup two exit handlers1933 # get_boot_and_root_loopback_devices will also setup two exit handlers
1056 # to de-register the loopback devices set up above.1934 # to de-register the loopback devices set up above.
1057 self.assertEqual(6, len(atexit_fixture.mock.funcs))1935 self.assertEqual(5, len(atexit_fixture.mock.funcs))
1058 popen_fixture.mock.calls = []1936 popen_fixture.mock.calls = []
1059 atexit_fixture.mock.run_funcs()1937 atexit_fixture.mock.run_funcs()
1060 # We did not really run losetup above (as it requires root) so here we1938 # We did not really run losetup above (as it requires root) so here we
@@ -1065,7 +1943,6 @@
1065 '%s losetup -d ' % sudo_args,1943 '%s losetup -d ' % sudo_args,
1066 '%s losetup -d ' % sudo_args,1944 '%s losetup -d ' % sudo_args,
1067 '%s losetup -d ' % sudo_args,1945 '%s losetup -d ' % sudo_args,
1068 '%s losetup -d ' % sudo_args,
1069 '%s losetup -d ' % sudo_args],1946 '%s losetup -d ' % sudo_args],
1070 popen_fixture.mock.commands_executed)1947 popen_fixture.mock.commands_executed)
10711948
@@ -1159,6 +2036,9 @@
11592036
1160 self.config = c2037 self.config = c
1161 self.config.boot_script = 'boot_script'2038 self.config.boot_script = 'boot_script'
2039 self.config.hardwarepack_handler = \
2040 TestSetMetadata.MockHardwarepackHandler('ahwpack.tar.gz')
2041 self.config.hardwarepack_handler.get_format = lambda: '1.0'
1162 self.popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())2042 self.popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
1163 self.useFixture(MockSomethingFixture(2043 self.useFixture(MockSomethingFixture(
1164 self.config, 'make_boot_files', self.save_args))2044 self.config, 'make_boot_files', self.save_args))
@@ -1241,6 +2121,14 @@
1241 os.makedirs(contents_bin)2121 os.makedirs(contents_bin)
1242 os.makedirs(contents_etc)2122 os.makedirs(contents_etc)
12432123
2124 # Must mock rootfs._list_files() because populate_rootfs() uses its
2125 # return value but since we mock cmd_runner.run() _list_files() would
2126 # return an invalid value.
2127 def mock_list_files(directory):
2128 return [contents_bin, contents_etc]
2129 self.useFixture(MockSomethingFixture(
2130 rootfs, '_list_files', mock_list_files))
2131
1244 populate_rootfs(2132 populate_rootfs(
1245 contents_dir, root_disk, partition='/dev/rootfs',2133 contents_dir, root_disk, partition='/dev/rootfs',
1246 rootfs_type='ext3', rootfs_uuid='uuid', should_create_swap=True,2134 rootfs_type='ext3', rootfs_uuid='uuid', should_create_swap=True,
@@ -1282,10 +2170,27 @@
1282 fixture.mock.commands_executed[0])2170 fixture.mock.commands_executed[0])
1283 self.assertEqual('UBOOT_PART=/dev/mmcblk0p1', open(tmpfile).read())2171 self.assertEqual('UBOOT_PART=/dev/mmcblk0p1', open(tmpfile).read())
12842172
2173 def test_list_files(self):
2174 tempdir = self.useFixture(CreateTempDirFixture()).tempdir
2175 # We don't want to mock cmd_runner.run() because we're testing the
2176 # command that it runs, but we need to monkey-patch SUDO_ARGS because
2177 # we don't want to use 'sudo' in tests.
2178 orig_sudo_args = cmd_runner.SUDO_ARGS
2179 def restore_sudo_args():
2180 cmd_runner.SUDO_ARGS = orig_sudo_args
2181 self.addCleanup(restore_sudo_args)
2182 cmd_runner.SUDO_ARGS = []
2183 file1 = self.createTempFileAsFixture(dir=tempdir)
2184 self.assertEqual([file1], rootfs._list_files(tempdir))
2185
1285 def test_move_contents(self):2186 def test_move_contents(self):
1286 tempdir = self.useFixture(CreateTempDirFixture()).tempdir2187 tempdir = self.useFixture(CreateTempDirFixture()).tempdir
1287 popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())2188 popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
1288 file1 = self.createTempFileAsFixture(dir=tempdir)2189 file1 = self.createTempFileAsFixture(dir=tempdir)
2190 def mock_list_files(directory):
2191 return [file1]
2192 self.useFixture(MockSomethingFixture(
2193 rootfs, '_list_files', mock_list_files))
12892194
1290 move_contents(tempdir, '/tmp/')2195 move_contents(tempdir, '/tmp/')
12912196
12922197
=== modified file 'setup.py'
--- setup.py 2011-05-26 20:32:40 +0000
+++ setup.py 2011-07-18 14:39:34 +0000
@@ -5,7 +5,7 @@
55
6DistUtilsExtra.auto.setup(6DistUtilsExtra.auto.setup(
7 name="linaro-image-tools",7 name="linaro-image-tools",
8 version="0.4.8.1",8 version="2011.06-1.1",
9 description="Tools to create and write Linaro images",9 description="Tools to create and write Linaro images",
10 url="https://launchpad.net/linaro-image-tools",10 url="https://launchpad.net/linaro-image-tools",
11 license="GPL v3 or later",11 license="GPL v3 or later",

Subscribers

People subscribed via source and target branches

to all changes: