blob: 1543dcafd91c930d5b7e95966c8578d8e1809b13 [file] [log] [blame]
Simon Glass89b86b82011-07-17 23:49:49 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""This module builds a firmware image for a tegra-based board.
6
7This modules uses a few rudimentary other libraries for its activity.
8
9Here are the names we give to the various files we deal with. It is important
10to keep these consistent!
11
12 uboot u-boot.bin (with no device tree)
13 fdt the fdt blob
14 bct the BCT file
15 bootstub uboot + fdt
16 signed (uboot + fdt + bct) signed blob
17"""
18
Simon Glassceff3ff2012-04-04 11:23:45 -070019import glob
Gabe Blackcdbdfe12013-02-06 05:37:52 -080020import hashlib
Simon Glass89b86b82011-07-17 23:49:49 -070021import os
22import re
23
Simon Glass89b86b82011-07-17 23:49:49 -070024from fdt import Fdt
25from pack_firmware import PackFirmware
26import shutil
Simon Glass7c2d5572011-11-15 14:47:08 -080027import struct
Simon Glass439fe7a2012-03-09 16:19:34 -080028from tools import CmdError
Simon Glass89b86b82011-07-17 23:49:49 -070029
30# This data is required by bmpblk_utility. Does it ever change?
31# It was stored with the chromeos-bootimage ebuild, but we want
32# this utility to work outside the chroot.
33yaml_data = '''
34bmpblock: 1.0
35
36images:
37 devmode: DeveloperBmp/DeveloperBmp.bmp
38 recovery: RecoveryBmp/RecoveryBmp.bmp
39 rec_yuck: RecoveryNoOSBmp/RecoveryNoOSBmp.bmp
40 rec_insert: RecoveryMissingOSBmp/RecoveryMissingOSBmp.bmp
41
42screens:
43 dev_en:
44 - [0, 0, devmode]
45 rec_en:
46 - [0, 0, recovery]
47 yuck_en:
48 - [0, 0, rec_yuck]
49 ins_en:
50 - [0, 0, rec_insert]
51
52localizations:
53 - [ dev_en, rec_en, yuck_en, ins_en ]
54'''
55
Simon Glass0c54ba52012-11-06 12:36:43 -080056# Default flash maps for various boards we support.
57# These are used when no fdt is provided (e.g. upstream U-Boot with no
58# fdt. Each is a list of nodes.
59default_flashmaps = {
Simon Glass76958702012-11-08 13:07:53 -080060 'tegra' : [
61 {
Simon Glass0c54ba52012-11-06 12:36:43 -080062 'node' : 'ro-boot',
63 'label' : 'boot-stub',
64 'size' : 512 << 10,
65 'read-only' : True,
66 'type' : 'blob signed',
67 'required' : True
68 }
69 ],
70 'daisy' : [
71 {
72 'node' : 'pre-boot',
73 'label' : "bl1 pre-boot",
74 'size' : 0x2000,
75 'read-only' : True,
76 'filename' : "e5250.nbl1.bin",
77 'type' : "blob exynos-bl1",
78 'required' : True,
79 }, {
80 'node' : 'spl',
81 'label' : "bl2 spl",
82 'size' : 0x4000,
83 'read-only' : True,
84 'filename' : "bl2.bin",
85 'type' : "blob exynos-bl2 boot,dtb",
86 'required' : True,
87 }, {
88 'node' : 'ro-boot',
89 'label' : "u-boot",
90 'size' : 0x9a000,
91 'read-only' : True,
92 'type' : "blob boot,dtb",
93 'required' : True,
94 }
Simon Glass76958702012-11-08 13:07:53 -080095 ],
96 'link' : [
97 {
98 'node' : 'si-all',
99 'label' : 'si-all',
100 'reg' : '%d %d' % (0x00000000, 0x00200000),
101 'type' : 'ifd',
102 'required' : True,
103 }, {
104 'node' : 'ro-boot',
105 'label' : 'boot-stub',
106 'reg' : '%d %d' % (0x00700000, 0x00100000),
107 'read-only' : True,
108 'type' : 'blob coreboot',
109 'required' : True,
110 }
Simon Glassf2534222013-03-20 15:42:02 -0700111 ],
112 'peach' : [
113 {
114 'node' : 'pre-boot',
115 'label' : "bl1 pre-boot",
116 'size' : 0x2000,
117 'read-only' : True,
118 'filename' : "e5420.nbl1.bin",
119 'type' : "blob exynos-bl1",
120 'required' : True,
121 }, {
122 'node' : 'spl',
123 'label' : "bl2 spl",
124 'size' : 0x4000,
125 'read-only' : True,
126 'filename' : "bl2.bin",
127 'type' : "blob exynos-bl2 boot,dtb",
128 'required' : True,
129 }, {
130 'node' : 'ro-boot',
131 'label' : "u-boot",
132 'size' : 0x9a000,
133 'read-only' : True,
134 'type' : "blob boot,dtb",
135 'required' : True,
136 }
137 ],
Simon Glass0c54ba52012-11-06 12:36:43 -0800138}
139
140
Simon Glass4a887b12012-10-23 16:29:03 -0700141# Build GBB flags.
142# (src/platform/vboot_reference/firmware/include/gbb_header.h)
143gbb_flag_properties = {
144 'dev-screen-short-delay': 0x00000001,
145 'load-option-roms': 0x00000002,
146 'enable-alternate-os': 0x00000004,
147 'force-dev-switch-on': 0x00000008,
148 'force-dev-boot-usb': 0x00000010,
149 'disable-fw-rollback-check': 0x00000020,
150 'enter-triggers-tonorm': 0x00000040,
151 'force-dev-boot-legacy': 0x00000080,
152}
153
Simon Glass49b026b2013-04-26 16:38:42 -0700154# Maps board name to Exynos product number
155type_to_model = {
156 'peach' : '5420',
157 'daisy' : '5250'
158}
159
Simon Glass5076a7f2012-10-23 16:31:54 -0700160def ListGoogleBinaryBlockFlags():
161 """Print out a list of GBB flags."""
162 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
163 for name, value in gbb_flag_properties.iteritems():
164 print ' %-30s %02x' % (name, value)
165
Simon Glass89b86b82011-07-17 23:49:49 -0700166class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -0700167 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -0700168
Simon Glass290a1802011-07-17 13:54:32 -0700169 Sequence of events:
170 bundle = Bundle(tools.Tools(), cros_output.Output())
171 bundle.SetDirs(...)
172 bundle.SetFiles(...)
173 bundle.SetOptions(...)
174 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -0700175 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -0700176 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -0700177
Simon Glass290a1802011-07-17 13:54:32 -0700178 Public properties:
179 fdt: The fdt object that we use for building our image. This wil be the
180 one specified by the user, except that we might add config options
181 to it. This is set up by SelectFdt() which must be called before
182 bundling starts.
183 uboot_fname: Full filename of the U-Boot binary we use.
184 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700185 spl_source: Source device to load U-Boot from, in SPL:
186 straps: Select device according to CPU strap pins
187 spi: Boot from SPI
188 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700189
190 Private attributes:
191 _small: True to create a 'small' signed U-Boot, False to produce a
192 full image. The small U-Boot is enough to boot but will not have
193 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700194 """
Simon Glass89b86b82011-07-17 23:49:49 -0700195
Simon Glass290a1802011-07-17 13:54:32 -0700196 def __init__(self, tools, output):
197 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700198
Simon Glass290a1802011-07-17 13:54:32 -0700199 Args:
200 tools: A tools.Tools object to use for external tools.
201 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700202 """
Simon Glass290a1802011-07-17 13:54:32 -0700203 self._tools = tools
204 self._out = output
205
206 # Set up the things we need to know in order to operate.
207 self._board = None # Board name, e.g. tegra2_seaboard.
208 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700209 self._force_rw = None
210 self._gbb_flags = None
211 self._keydir = None
212 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700213 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700214 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800215 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700216 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700217 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700218 self.ecro_fname = None # Filename of EC read-only file
219 self.ecrw_fname = None # Filename of EC file
Simon Glass7e199222012-03-13 15:51:18 -0700220 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
221 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700222 self.fdt = None # Our Fdt object.
223 self.kernel_fname = None
224 self.postload_fname = None
225 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700226 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700227 self.spl_source = 'straps' # SPL boot according to board settings
228 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700229
230 def SetDirs(self, keydir):
231 """Set up directories required for Bundle.
232
233 Args:
234 keydir: Directory containing keys to use for signing firmware.
235 """
236 self._keydir = keydir
237
Simon Glass6dcc2f22011-07-28 15:26:49 +1200238 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800239 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700240 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800241 skeleton=None, ecrw=None, ecro=None, kernel=None, blobs=None):
Simon Glass290a1802011-07-17 13:54:32 -0700242 """Set up files required for Bundle.
243
244 Args:
245 board: The name of the board to target (e.g. tegra2_seaboard).
246 uboot: The filename of the u-boot.bin image to use.
247 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800248 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800249 coreboot: The filename of the coreboot image to use (on x86).
250 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200251 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700252 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700253 exynos_bl1: The filename of the exynos BL1 file
254 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
255 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700256 ecrw: The filename of the EC (Embedded Controller) read-write file.
257 ecro: The filename of the EC (Embedded Controller) read-only file.
Simon Glassde9c8072012-07-02 22:29:02 -0700258 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800259 blobs: List of (type, filename) of arbitrary blobs.
Simon Glass290a1802011-07-17 13:54:32 -0700260 """
261 self._board = board
262 self.uboot_fname = uboot
263 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800264 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700265 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800266 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200267 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700268 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700269 self.exynos_bl1 = exynos_bl1
270 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700271 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700272 self.ecrw_fname = ecrw
273 self.ecro_fname = ecro
Simon Glassde9c8072012-07-02 22:29:02 -0700274 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800275 self.blobs = dict(blobs or ())
Simon Glass290a1802011-07-17 13:54:32 -0700276
Simon Glass6e486c22012-10-26 15:43:42 -0700277 def SetOptions(self, small, gbb_flags, force_rw=False):
Simon Glass290a1802011-07-17 13:54:32 -0700278 """Set up options supported by Bundle.
279
280 Args:
281 small: Only create a signed U-Boot - don't produce the full packed
282 firmware image. This is useful for devs who want to replace just the
283 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700284 gbb_flags: Specification for string containing adjustments to make.
285 force_rw: Force firmware into RW mode.
Simon Glass290a1802011-07-17 13:54:32 -0700286 """
287 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700288 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700289 self._force_rw = force_rw
Simon Glass290a1802011-07-17 13:54:32 -0700290
Simon Glass22f39fb2013-02-09 13:44:14 -0800291 def _GetBuildRoot(self):
292 """Get the path to this board's 'firmware' directory.
293
294 Returns:
295 Path to firmware directory, with ## representing the path to the
296 chroot.
297 """
Simon Glass290a1802011-07-17 13:54:32 -0700298 if not self._board:
299 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800300 return os.path.join('##', 'build', self._board, 'firmware')
301
302 def _CheckFdtFilename(self, fname):
303 """Check provided FDT filename and return the correct name if needed.
304
305 Where the filename lacks a path, add a default path for this board.
306 Where no FDT filename is provided, select a default one for this board.
307
308 Args:
309 fname: Proposed FDT filename.
310
311 Returns:
312 Selected FDT filename, after validation.
313 """
314 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700315 dir_name = os.path.join(build_root, 'dts')
Simon Glass22f39fb2013-02-09 13:44:14 -0800316 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700317 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700318 base_name = re.sub('_', '-', self._board)
319
320 # In case the name exists with a prefix or suffix, find it.
321 wildcard = os.path.join(dir_name, '*%s*.dts' % base_name)
322 found_list = glob.glob(self._tools.Filename(wildcard))
323 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800324 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700325 else:
326 # We didn't find anything definite, so set up our expected name.
Simon Glass22f39fb2013-02-09 13:44:14 -0800327 fname = os.path.join(dir_name, '%s.dts' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700328
Simon Glass881964d2012-04-04 11:34:09 -0700329 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800330 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700331 if not ext and not os.path.dirname(root):
Simon Glass22f39fb2013-02-09 13:44:14 -0800332 fname = os.path.join(dir_name, '%s.dts' % root)
333 return fname
334
335 def CheckOptions(self):
336 """Check provided options and select defaults."""
337 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700338
Simon Glass49b026b2013-04-26 16:38:42 -0700339 board_type = self._board.split('_')[0]
340 model = type_to_model.get(board_type)
341
Simon Glass290a1802011-07-17 13:54:32 -0700342 if not self.uboot_fname:
343 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
344 if not self.bct_fname:
345 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700346 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700347 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700348 if model:
349 if not self.exynos_bl1:
350 self.exynos_bl1 = os.path.join(build_root, 'E%s.nbl1.bin' % model)
351 if not self.exynos_bl2:
352 self.exynos_bl2 = os.path.join(build_root, 'smdk%s-spl.bin' % model)
Simon Glass07267952012-06-08 12:45:13 -0700353 if not self.coreboot_fname:
354 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
355 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700356 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700357 if not self.seabios_fname:
358 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700359 if not self.ecrw_fname:
360 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
361 if not self.ecro_fname:
362 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700363
Simon Glass75759302012-03-15 20:26:53 -0700364 def GetFiles(self):
365 """Get a list of files that we know about.
366
367 This is the opposite of SetFiles except that we may have put in some
368 default names. It returns a dictionary containing the filename for
369 each of a number of pre-defined files.
370
371 Returns:
372 Dictionary, with one entry for each file.
373 """
374 file_list = {
375 'bct' : self.bct_fname,
376 'exynos-bl1' : self.exynos_bl1,
377 'exynos-bl2' : self.exynos_bl2,
378 }
379 return file_list
380
Simon Glass4a887b12012-10-23 16:29:03 -0700381 def DecodeGBBFlagsFromFdt(self):
382 """Get Google Binary Block flags from the FDT.
383
384 These should be in the chromeos-config node, like this:
385
386 chromeos-config {
387 gbb-flag-dev-screen-short-delay;
388 gbb-flag-force-dev-switch-on;
389 gbb-flag-force-dev-boot-usb;
390 gbb-flag-disable-fw-rollback-check;
391 };
392
393 Returns:
394 GBB flags value from FDT.
395 """
396 chromeos_config = self.fdt.GetProps("/chromeos-config")
397 gbb_flags = 0
398 for name in chromeos_config:
399 if name.startswith('gbb-flag-'):
400 flag_value = gbb_flag_properties.get(name[9:])
401 if flag_value:
402 gbb_flags |= flag_value
403 self._out.Notice("FDT: Enabling %s." % name)
404 else:
405 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
406 return gbb_flags
407
Simon Glass157c0662012-10-23 13:52:42 -0700408 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
409 """Decode ajustments to the provided GBB flags.
410
411 We support three options:
412
413 hex value: c2
414 defined value: force-dev-boot-usb,load-option-roms
415 adjust default value: -load-option-roms,+force-dev-boot-usb
416
417 The last option starts from the passed-in GBB flags and adds or removes
418 flags.
419
420 Args:
421 gbb_flags: Base (default) FDT flags.
422 adjustments: String containing adjustments to make.
423
424 Returns:
425 Updated FDT flags.
426 """
427 use_base_value = True
428 if adjustments:
429 try:
430 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700431 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700432 pass
433 for flag in adjustments.split(','):
434 oper = None
435 if flag[0] in ['-', '+']:
436 oper = flag[0]
437 flag = flag[1:]
438 value = gbb_flag_properties.get(flag)
439 if not value:
440 raise ValueError("Invalid GBB flag '%s'" % flag)
441 if oper == '+':
442 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800443 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700444 elif oper == '-':
445 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800446 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700447 else:
448 if use_base_value:
449 gbb_flags = 0
450 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800451 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700452 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800453 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700454
455 return gbb_flags
456
Simon Glass56577572011-07-19 11:08:06 +1200457 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700458 """Create a GBB for the image.
459
Simon Glass56577572011-07-19 11:08:06 +1200460 Args:
461 hardware_id: Hardware ID to use for this board. If None, then the
462 default from the Fdt will be used
463
Simon Glass89b86b82011-07-17 23:49:49 -0700464 Returns:
465 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700466 """
Simon Glass56577572011-07-19 11:08:06 +1200467 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800468 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700469 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700470 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700471
Simon Glass4a887b12012-10-23 16:29:03 -0700472 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800473
Simon Glass157c0662012-10-23 13:52:42 -0700474 # Allow command line to override flags
475 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
476
Simon Glass4a887b12012-10-23 16:29:03 -0700477 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700478 self._out.Progress('Creating GBB')
479 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
480 sizes = ['%#x' % size for size in sizes]
481 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700482 keydir = self._tools.Filename(self._keydir)
483 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700484 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200485 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700486 '--rootkey=%s/root_key.vbpubk' % keydir,
487 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700488 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800489 '--flags=%d' % gbb_flags,
Simon Glass89b86b82011-07-17 23:49:49 -0700490 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700491 cwd=odir)
492 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700493
Simon Glasse13ee2c2011-07-28 08:12:28 +1200494 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700495 """Sign an image so that the Tegra SOC will boot it.
496
497 Args:
498 bct: BCT file to use.
499 bootstub: Boot stub (U-Boot + fdt) file to sign.
500 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700501
502 Returns:
503 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700504 """
505 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200506 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700507 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200508 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700509 fd = open(config, 'w')
510 fd.write('Version = 1;\n')
511 fd.write('Redundancy = 1;\n')
512 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700513
514 # TODO(dianders): Right now, we don't have enough space in our flash map
515 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
516 # sure what this does for reliability, but at least things will fit...
517 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
518 if is_nand:
519 fd.write('Bctcopy = 1;\n')
520
Simon Glass89b86b82011-07-17 23:49:49 -0700521 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
522 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700523
Simon Glass89b86b82011-07-17 23:49:49 -0700524 fd.close()
525
526 self._tools.Run('cbootimage', [config, signed])
527 self._tools.OutputSize('BCT', bct)
528 self._tools.OutputSize('Signed image', signed)
529 return signed
530
Doug Anderson86ce5f42011-07-27 10:40:18 -0700531 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700532 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700533
534 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700535 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700536 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700537 """
Simon Glass468d8752012-09-19 16:36:19 -0700538 if bootcmd is not None:
539 if bootcmd == 'none':
540 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800541 self.fdt.PutString('/config', 'bootcmd', bootcmd)
542 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700543 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700544
Simon Glassa4934b72012-05-09 13:35:02 -0700545 def SetNodeEnabled(self, node_name, enabled):
546 """Set whether an node is enabled or disabled.
547
548 This simply sets the 'status' property of a node to "ok", or "disabled".
549
550 The node should either be a full path to the node (like '/uart@10200000')
551 or an alias property.
552
553 Aliases are supported like this:
554
555 aliases {
556 console = "/uart@10200000";
557 };
558
559 pointing to a node:
560
561 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700562 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700563 };
564
565 In this case, this function takes the name of the alias ('console' in
566 this case) and updates the status of the node that is pointed to, to
567 either ok or disabled. If the alias does not exist, a warning is
568 displayed.
569
570 Args:
571 node_name: Name of node (e.g. '/uart@10200000') or alias alias
572 (e.g. 'console') to adjust
573 enabled: True to enable, False to disable
574 """
575 # Look up the alias if this is an alias reference
576 if not node_name.startswith('/'):
577 lookup = self.fdt.GetString('/aliases', node_name, '')
578 if not lookup:
579 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
580 return
581 node_name = lookup
582 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700583 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700584 else:
585 status = 'disabled'
586 self.fdt.PutString(node_name, 'status', status)
587
588 def AddEnableList(self, enable_list):
589 """Process a list of nodes to enable/disable.
590
591 Args:
592 config_list: List of (node, value) tuples to add to the fdt. For each
593 tuple:
594 node: The fdt node to write to will be <node> or pointed to by
595 /aliases/<node>. We can tell which
596 value: 0 to disable the node, 1 to enable it
Vadim Bendebury507c0012013-06-09 12:49:25 -0700597 Raises:
598 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700599 """
600 if enable_list:
601 for node_name, enabled in enable_list:
602 try:
603 enabled = int(enabled)
604 if enabled not in (0, 1):
605 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700606 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700607 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700608 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700609 self.SetNodeEnabled(node_name, enabled)
610
Simon Glass290a1802011-07-17 13:54:32 -0700611 def AddConfigList(self, config_list, use_int=False):
612 """Add a list of config items to the fdt.
613
614 Normally these values are written to the fdt as strings, but integers
615 are also supported, in which case the values will be converted to integers
616 (if necessary) before being stored.
617
618 Args:
619 config_list: List of (config, value) tuples to add to the fdt. For each
620 tuple:
621 config: The fdt node to write to will be /config/<config>.
622 value: An integer or string value to write.
623 use_int: True to only write integer values.
624
625 Raises:
626 CmdError: if a value is required to be converted to integer but can't be.
627 """
628 if config_list:
629 for config in config_list:
630 value = config[1]
631 if use_int:
632 try:
633 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700634 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700635 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700636 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700637 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800638 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700639 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800640 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700641
Simon Glass7c2d5572011-11-15 14:47:08 -0800642 def DecodeTextBase(self, data):
643 """Look at a U-Boot image and try to decode its TEXT_BASE.
644
645 This works because U-Boot has a header with the value 0x12345678
646 immediately followed by the TEXT_BASE value. We can therefore read this
647 from the image with some certainty. We check only the first 40 words
648 since the header should be within that region.
649
Simon Glass96b50302012-07-20 06:55:28 +0100650 Since upstream Tegra has moved to having a 16KB SPL region at the start,
651 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
652 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
653
Simon Glass7c2d5572011-11-15 14:47:08 -0800654 Args:
655 data: U-Boot binary data
656
657 Returns:
658 Text base (integer) or None if none was found
659 """
660 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100661 for start in (0, 0x4000):
662 for i in range(start, start + 160, 4):
663 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800664
Simon Glass96b50302012-07-20 06:55:28 +0100665 # TODO(sjg): This does not cope with a big-endian target
666 value = struct.unpack('<I', word)[0]
667 if found:
668 return value - start
669 if value == 0x12345678:
670 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800671
672 return None
673
674 def CalcTextBase(self, name, fdt, fname):
675 """Calculate the TEXT_BASE to use for U-Boot.
676
677 Normally this value is in the fdt, so we just read it from there. But as
678 a second check we look at the image itself in case this is different, and
679 switch to that if it is.
680
681 This allows us to flash any U-Boot even if its TEXT_BASE is different.
682 This is particularly useful with upstream U-Boot which uses a different
683 value (which we will move to).
684 """
685 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800686 # The value that comes back from fdt.GetInt is signed, which makes no
687 # sense for an address base. Force it to unsigned.
688 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800689 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100690 text_base_str = '%#x' % text_base if text_base else 'None'
691 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
692 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800693
694 # If they are different, issue a warning and switch over.
695 if text_base and text_base != fdt_text_base:
696 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
697 "fdt value of %x. Using %x" % (text_base, name,
698 fdt_text_base, text_base))
699 fdt_text_base = text_base
700 return fdt_text_base
701
Simon Glass6dcc2f22011-07-28 15:26:49 +1200702 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700703 """Create a boot stub and a signed boot stub.
704
Simon Glass6dcc2f22011-07-28 15:26:49 +1200705 For postload:
706 We add a /config/postload-text-offset entry to the signed bootstub's
707 fdt so that U-Boot can find the postload code.
708
709 The raw (unsigned) bootstub will have a value of -1 for this since we will
710 simply append the postload code to the bootstub and it can find it there.
711 This will be used for RW A/B firmware.
712
713 For the signed case this value will specify where in the flash to find
714 the postload code. This will be used for RO firmware.
715
Simon Glass89b86b82011-07-17 23:49:49 -0700716 Args:
717 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800718 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200719 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700720
721 Returns:
722 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200723 Full path to bootstub (uboot + fdt(-1) + postload).
724 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700725
726 Raises:
727 CmdError if a command fails.
728 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200729 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800730 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700731 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200732
733 # Make a copy of the fdt for the bootstub
734 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700735 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700736 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200737
Simon Glass89b86b82011-07-17 23:49:49 -0700738 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700739 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
740 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700741 self._tools.OutputSize('Combined binary', bootstub)
742
Simon Glasse13ee2c2011-07-28 08:12:28 +1200743 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700744 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700745 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200746 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200747
748 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
749 data = self._tools.ReadFile(signed)
750
751 if postload:
752 # We must add postload to the bootstub since A and B will need to
753 # be able to find it without the /config/postload-text-offset mechanism.
754 bs_data = self._tools.ReadFile(bootstub)
755 bs_data += self._tools.ReadFile(postload)
756 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
757 self._tools.WriteFile(bootstub, bs_data)
758 self._tools.OutputSize('Combined binary with postload', bootstub)
759
760 # Now that we know the file size, adjust the fdt and re-sign
761 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800762 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200763 fdt_data = self._tools.ReadFile(fdt.fname)
764 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
765 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
766 postload_bootstub, text_base)
767 if len(data) != os.path.getsize(signed):
768 raise CmdError('Signed file size changed from %d to %d after updating '
769 'fdt' % (len(data), os.path.getsize(signed)))
770
771 # Re-read the signed image, and add the post-load binary.
772 data = self._tools.ReadFile(signed)
773 data += self._tools.ReadFile(postload)
774 self._tools.OutputSize('Post-load binary', postload)
775
776 self._tools.WriteFile(signed_postload, data)
777 self._tools.OutputSize('Final bootstub with postload', signed_postload)
778
779 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700780
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700781 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700782 """Create a coreboot boot stub.
783
784 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700785 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700786
787 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100788 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700789 """
790 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700791 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100792
793 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700794 return bootstub
795
Simon Glass3b404092012-05-23 13:10:36 -0700796 def _UpdateBl2Parameters(self, fdt, spl_load_size, data, pos):
Simon Glassdf95dd22012-03-13 15:46:16 -0700797 """Update the parameters in a BL2 blob.
798
799 We look at the list in the parameter block, extract the value of each
800 from the device tree, and write that value to the parameter block.
801
802 Args:
803 fdt: Device tree containing the parameter values.
Simon Glass3b404092012-05-23 13:10:36 -0700804 spl_load_size: Size of U-Boot image that SPL must load
Simon Glassdf95dd22012-03-13 15:46:16 -0700805 data: The BL2 data.
806 pos: The position of the start of the parameter block.
807
808 Returns:
809 The new contents of the parameter block, after updating.
810 """
Simon Glassdf95dd22012-03-13 15:46:16 -0700811 version, size = struct.unpack('<2L', data[pos + 4:pos + 12])
812 if version != 1:
813 raise CmdError("Cannot update machine parameter block version '%d'" %
814 version)
815 if size < 0 or pos + size > len(data):
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700816 raise CmdError("Machine parameter block size %d is invalid: "
817 "pos=%d, size=%d, space=%d, len=%d" %
818 (size, pos, size, len(data) - pos, len(data)))
Simon Glassdf95dd22012-03-13 15:46:16 -0700819
820 # Move past the header and read the parameter list, which is terminated
821 # with \0.
822 pos += 12
823 param_list = struct.unpack('<%ds' % (len(data) - pos), data[pos:])[0]
824 param_len = param_list.find('\0')
825 param_list = param_list[:param_len]
Simon Glass66c1a9f2012-03-22 19:15:53 -0700826 pos += (param_len + 4) & ~3
Simon Glassdf95dd22012-03-13 15:46:16 -0700827
828 # Work through the parameters one at a time, adding each value
829 new_data = ''
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700830 upto = 0
Simon Glassdf95dd22012-03-13 15:46:16 -0700831 for param in param_list:
Simon Glass2c48ddf2012-03-23 16:55:22 -0700832 value = struct.unpack('<1L', data[pos + upto:pos + upto + 4])[0]
Simon Glass56583742012-11-06 12:34:47 -0800833
834 # Use this to detect a missing value from the fdt.
835 not_given = 'not-given-invalid-value'
Simon Glassdf95dd22012-03-13 15:46:16 -0700836 if param == 'm' :
Simon Glass56583742012-11-06 12:34:47 -0800837 mem_type = fdt.GetString('/dmc', 'mem-type', not_given)
838 if mem_type == not_given:
839 mem_type = 'ddr3'
840 self._out.Warning("No value for memory type: using '%s'" % mem_type)
Simon Glassdf95dd22012-03-13 15:46:16 -0700841 mem_types = ['ddr2', 'ddr3', 'lpddr2', 'lpddr3']
842 if not mem_type in mem_types:
843 raise CmdError("Unknown memory type '%s'" % mem_type)
844 value = mem_types.index(mem_type)
845 self._out.Info(' Memory type: %s (%d)' % (mem_type, value))
Doug Andersonee46cfe2012-05-18 09:53:08 -0700846 elif param == 'M' :
Simon Glass56583742012-11-06 12:34:47 -0800847 mem_manuf = fdt.GetString('/dmc', 'mem-manuf', not_given)
848 if mem_manuf == not_given:
849 mem_manuf = 'samsung'
850 self._out.Warning("No value for memory manufacturer: using '%s'" %
851 mem_manuf)
Doug Andersonee46cfe2012-05-18 09:53:08 -0700852 mem_manufs = ['autodetect', 'elpida', 'samsung']
853 if not mem_manuf in mem_manufs:
854 raise CmdError("Unknown memory manufacturer: '%s'" % mem_manuf)
855 value = mem_manufs.index(mem_manuf)
856 self._out.Info(' Memory manufacturer: %s (%d)' % (mem_manuf, value))
Simon Glass158289e2012-09-14 11:42:25 -0700857 elif param == 'f' :
Simon Glass56583742012-11-06 12:34:47 -0800858 mem_freq = fdt.GetInt('/dmc', 'clock-frequency', -1)
859 if mem_freq == -1:
860 mem_freq = 800000000
861 self._out.Warning("No value for memory frequency: using '%s'" %
862 mem_freq)
863 mem_freq /= 1000000
Simon Glass158289e2012-09-14 11:42:25 -0700864 if not mem_freq in [533, 667, 800]:
865 self._out.Warning("Unexpected memory speed '%s'" % mem_freq)
866 value = mem_freq
867 self._out.Info(' Memory speed: %d' % mem_freq)
Simon Glass5d23e312013-05-25 22:47:56 -0700868 elif param == 'a' :
869 arm_freq = fdt.GetInt('/dmc', 'arm-frequency', -1)
870 if arm_freq == -1:
871 arm_freq = 1700000000
872 self._out.Warning("No value for ARM frequency: using '%s'" %
873 arm_freq)
874 arm_freq /= 1000000
875 value = arm_freq
876 self._out.Info(' ARM speed: %d' % arm_freq)
877 elif param == 'i':
878 i2c_addr = -1
879 lookup = fdt.GetString('/aliases', 'pmic', '')
880 if lookup:
881 i2c_addr, size = fdt.GetIntList(lookup, 'reg', 2)
882 if i2c_addr == -1:
883 self._out.Warning("No value for PMIC I2C address: using %#08x" %
884 value)
885 else:
886 value = i2c_addr
887 self._out.Info(' PMIC I2C Address: %#08x' % value)
888 elif param == 's':
889 serial_addr = -1
890 lookup = fdt.GetString('/aliases', 'console', '')
891 if lookup:
892 serial_addr, size = fdt.GetIntList(lookup, 'reg', 2)
893 if serial_addr == -1:
894 self._out.Warning("No value for Console address: using %#08x" %
895 value)
896 else:
897 value = serial_addr
898 self._out.Info(' Console Address: %#08x' % value)
Simon Glassdf95dd22012-03-13 15:46:16 -0700899 elif param == 'v':
900 value = 31
901 self._out.Info(' Memory interleave: %#0x' % value)
Simon Glass8e1fdb22012-03-15 21:02:10 -0700902 elif param == 'u':
Simon Glass3b404092012-05-23 13:10:36 -0700903 value = (spl_load_size + 0xfff) & ~0xfff
904 self._out.Info(' U-Boot size: %#0x (rounded up from %#0x)' %
905 (value, spl_load_size))
Simon Glass5d23e312013-05-25 22:47:56 -0700906 elif param == 'l':
907 load_addr = fdt.GetInt('/config', 'u-boot-load-addr', -1)
908 if load_addr == -1:
909 self._out.Warning("No value for U-Boot load address: using '%08x'" %
910 value)
911 else:
912 value = load_addr
913 self._out.Info(' U-Boot load address: %#0x' % value)
Simon Glass559b6612012-05-23 13:28:45 -0700914 elif param == 'b':
915 # These values come from enum boot_mode in U-Boot's cpu.h
916 if self.spl_source == 'straps':
917 value = 32
918 elif self.spl_source == 'emmc':
919 value = 4
920 elif self.spl_source == 'spi':
921 value = 20
922 elif self.spl_source == 'usb':
923 value = 33
924 else:
925 raise CmdError("Invalid boot source '%s'" % self.spl_source)
926 self._out.Info(' Boot source: %#0x' % value)
Simon Glass5d23e312013-05-25 22:47:56 -0700927 elif param in ['r', 'R']:
928 records = fdt.GetIntList('/board-rev', 'google,board-rev-gpios',
929 None, '0 0')
930 gpios = []
931 for i in range(1, len(records), 3):
932 gpios.append(records[i])
933 gpios.extend([0, 0, 0, 0])
934 if param == 'r':
935 value = gpios[0] + (gpios[1] << 16)
936 self._out.Info(' Board ID GPIOs: tit0=%d, tit1=%d' % (gpios[0],
937 gpios[1]))
938 else:
939 value = gpios[2] + (gpios[3] << 16)
940 self._out.Info(' Board ID GPIOs: tit2=%d, tit3=%d' % (gpios[2],
941 gpios[3]))
Tom Wai-Hong Tam99b7f112013-02-06 09:10:10 +0800942 elif param == 'z':
943 compress = fdt.GetString('/flash/ro-boot', 'compress', 'none')
944 compress_types = ['none', 'lzo']
945 if not compress in compress_types:
946 raise CmdError("Unknown compression type '%s'" % compress)
947 value = compress_types.index(compress)
948 self._out.Info(' Compression type: %#0x' % value)
Gabe Blackcd14f452013-05-16 05:03:59 -0700949 elif param == 'c':
950 rtc_type = 0
951 try:
952 rtc_alias = fdt.GetString('/aliases/', 'rtc')
953 rtc_compat = fdt.GetString(rtc_alias, 'compatible')
954 if rtc_compat == 'samsung,s5m8767-pmic':
955 rtc_type = 1
956 except CmdError:
957 self._out.Warning("Failed to find rtc")
958 value = rtc_type
Simon Glassdf95dd22012-03-13 15:46:16 -0700959 else:
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700960 self._out.Warning("Unknown machine parameter type '%s'" % param)
Simon Glass2c48ddf2012-03-23 16:55:22 -0700961 self._out.Info(' Unknown value: %#0x' % value)
Simon Glassdf95dd22012-03-13 15:46:16 -0700962 new_data += struct.pack('<L', value)
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700963 upto += 4
Simon Glassdf95dd22012-03-13 15:46:16 -0700964
965 # Put the data into our block.
966 data = data[:pos] + new_data + data[pos + len(new_data):]
967 self._out.Info('BL2 configuration complete')
968 return data
969
Simon Glasse5e8afb2012-05-23 11:19:23 -0700970 def _UpdateChecksum(self, data):
971 """Update the BL2 checksum.
972
973 The checksum is a 4 byte sum of all the bytes in the image before the
974 last 4 bytes (which hold the checksum).
975
976 Args:
977 data: The BL2 data to update.
978
979 Returns:
980 The new contents of the BL2 data, after updating the checksum.
981 """
982 checksum = 0
983 for ch in data[:-4]:
984 checksum += ord(ch)
985 return data[:-4] + struct.pack('<L', checksum & 0xffffffff)
986
Simon Glass559b6612012-05-23 13:28:45 -0700987 def ConfigureExynosBl2(self, fdt, spl_load_size, orig_bl2, name=''):
Simon Glass7e199222012-03-13 15:51:18 -0700988 """Configure an Exynos BL2 binary for our needs.
989
990 We create a new modified BL2 and return its filename.
991
992 Args:
993 fdt: Device tree containing the parameter values.
Simon Glass3b404092012-05-23 13:10:36 -0700994 spl_load_size: Size of U-Boot image that SPL must load
Simon Glass7e199222012-03-13 15:51:18 -0700995 orig_bl2: Filename of original BL2 file to modify.
996 """
Simon Glass66c1a9f2012-03-22 19:15:53 -0700997 self._out.Info('Configuring BL2')
Simon Glass559b6612012-05-23 13:28:45 -0700998 bl2 = os.path.join(self._tools.outdir, 'updated-spl%s.bin' % name)
Simon Glass66c1a9f2012-03-22 19:15:53 -0700999 data = self._tools.ReadFile(orig_bl2)
1000 self._tools.WriteFile(bl2, data)
Simon Glass7e199222012-03-13 15:51:18 -07001001
1002 # Locate the parameter block
1003 data = self._tools.ReadFile(bl2)
1004 marker = struct.pack('<L', 0xdeadbeef)
1005 pos = data.rfind(marker)
1006 if not pos:
1007 raise CmdError("Could not find machine parameter block in '%s'" %
1008 orig_bl2)
Simon Glass3b404092012-05-23 13:10:36 -07001009 data = self._UpdateBl2Parameters(fdt, spl_load_size, data, pos)
Simon Glasse5e8afb2012-05-23 11:19:23 -07001010 data = self._UpdateChecksum(data)
Simon Glass7e199222012-03-13 15:51:18 -07001011 self._tools.WriteFile(bl2, data)
1012 return bl2
1013
Simon Glass89b86b82011-07-17 23:49:49 -07001014 def _PackOutput(self, msg):
1015 """Helper function to write output from PackFirmware (verbose level 2).
1016
1017 This is passed to PackFirmware for it to use to write output.
1018
1019 Args:
1020 msg: Message to display.
1021 """
1022 self._out.Notice(msg)
1023
Simon Glass439fe7a2012-03-09 16:19:34 -08001024 def _BuildBlob(self, pack, fdt, blob_type):
1025 """Build the blob data for a particular blob type.
1026
1027 Args:
1028 blob_type: The type of blob to create data for. Supported types are:
1029 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
1030 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -07001031
1032 Raises:
1033 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -08001034 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001035 # stupid pylint insists that sha256 is not in hashlib.
1036 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -08001037 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001038 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -08001039 pack.AddProperty('coreboot', coreboot)
1040 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -07001041 elif blob_type == 'legacy':
1042 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -08001043 elif blob_type == 'signed':
1044 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
1045 self.postload_fname)
1046 pack.AddProperty('bootstub', bootstub)
1047 pack.AddProperty('signed', signed)
1048 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -07001049 elif blob_type == 'exynos-bl1':
1050 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -07001051
1052 # TODO(sjg@chromium.org): Deprecate ecbin
1053 elif blob_type in ['ecrw', 'ecbin']:
1054 pack.AddProperty('ecrw', self.ecrw_fname)
1055 pack.AddProperty('ecbin', self.ecrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -08001056 elif blob_type == 'ecrwhash':
1057 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
1058 ecrw = self._tools.ReadFile(self.ecrw_fname)
1059 hasher = hashlib.sha256()
1060 hasher.update(ecrw)
1061 self._tools.WriteFile(ec_hash_file, hasher.digest())
1062 pack.AddProperty(blob_type, ec_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -07001063 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -07001064 # crosbug.com/p/13143
1065 # We cannot have an fmap in the EC image since there can be only one,
1066 # which is the main fmap describing the whole image.
1067 # Ultimately the EC will not have an fmap, since with software sync
1068 # there is no flashrom involvement in updating the EC flash, and thus
1069 # no need for the fmap.
1070 # For now, mangle the fmap name to avoid problems.
1071 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
1072 data = self._tools.ReadFile(self.ecro_fname)
1073 data = re.sub('__FMAP__', '__fMAP__', data)
1074 self._tools.WriteFile(updated_ecro, data)
1075 pack.AddProperty(blob_type, updated_ecro)
Simon Glass7e199222012-03-13 15:51:18 -07001076 elif blob_type == 'exynos-bl2':
Simon Glass7d2542f2012-06-21 07:10:59 -07001077 spl_payload = pack.GetBlobParams(blob_type)
1078
1079 # TODO(sjg@chromium): Remove this later, when we remove boot+dtb
1080 # from all flash map files.
1081 if not spl_payload:
1082 spl_load_size = os.stat(pack.GetProperty('boot+dtb')).st_size
1083 prop_list = 'boot+dtb'
1084
1085 # Do this later, when we remove boot+dtb.
1086 # raise CmdError("No parameters provided for blob type '%s'" %
1087 # blob_type)
1088 else:
1089 prop_list = spl_payload[0].split(',')
Tom Wai-Hong Tam26e3a4c2013-02-06 09:36:47 +08001090 compress = fdt.GetString('/flash/ro-boot', 'compress', 'none')
1091 if compress == 'none':
1092 compress = None
1093 spl_load_size = len(pack.ConcatPropContents(prop_list, compress,
1094 False)[0])
Simon Glass7d2542f2012-06-21 07:10:59 -07001095 self._out.Info("BL2/SPL contains '%s', size is %d / %#x" %
1096 (', '.join(prop_list), spl_load_size, spl_load_size))
Simon Glass3b404092012-05-23 13:10:36 -07001097 bl2 = self.ConfigureExynosBl2(fdt, spl_load_size, self.exynos_bl2)
Simon Glass7e199222012-03-13 15:51:18 -07001098 pack.AddProperty(blob_type, bl2)
Simon Glass439fe7a2012-03-09 16:19:34 -08001099 elif pack.GetProperty(blob_type):
1100 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -08001101 elif blob_type in self.blobs:
1102 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -08001103 else:
1104 raise CmdError("Unknown blob type '%s' required in flash map" %
1105 blob_type)
1106
Simon Glass290a1802011-07-17 13:54:32 -07001107 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -07001108 """Create a full firmware image, along with various by-products.
1109
1110 This uses the provided u-boot.bin, fdt and bct to create a firmware
1111 image containing all the required parts. If the GBB is not supplied
1112 then this will just return a signed U-Boot as the image.
1113
1114 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +12001115 gbb: Full path to the GBB file, or empty if a GBB is not required.
1116 fdt: Fdt object containing required information.
1117
1118 Returns:
1119 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001120 """
Simon Glass02d124a2012-03-02 14:47:20 -08001121 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001122
Simon Glass439fe7a2012-03-09 16:19:34 -08001123 pack = PackFirmware(self._tools, self._out)
Vadim Bendebury238f6442013-03-27 11:23:25 -07001124 # Get the flashmap so we know what to build. For board variants use the
1125 # main board name as the key (drop the _<variant> suffix).
1126 default_flashmap = default_flashmaps.get(self._board.split('_')[0])
Simon Glassb8c6d952012-12-01 06:14:35 -08001127 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001128 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
1129 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001130
Simon Glass0c54ba52012-11-06 12:36:43 -08001131 pack.SelectFdt(fdt, self._board, default_flashmap)
Simon Glass439fe7a2012-03-09 16:19:34 -08001132
1133 # Get all our blobs ready
1134 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001135 if self.skeleton_fname:
1136 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001137 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001138
Simon Glass47817052012-10-20 13:30:07 -07001139 # Let's create some copies of the fdt for vboot. These can be used to
1140 # pass a different fdt to each firmware type. For now it is just used to
1141 # check that the right fdt comes through.
1142 fdt_rwa = fdt.Copy(os.path.join(self._tools.outdir, 'updated-rwa.dtb'))
1143 fdt_rwa.PutString('/chromeos-config', 'firmware-type', 'rw-a')
1144 pack.AddProperty('dtb-rwa', fdt_rwa.fname)
1145 fdt_rwb = fdt.Copy(os.path.join(self._tools.outdir, 'updated-rwb.dtb'))
1146 fdt_rwb.PutString('/chromeos-config', 'firmware-type', 'rw-b')
1147 pack.AddProperty('dtb-rwb', fdt_rwb.fname)
1148 fdt.PutString('/chromeos-config', 'firmware-type', 'ro')
1149
Simon Glassde9c8072012-07-02 22:29:02 -07001150 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1151 if self.kernel_fname:
1152 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1153
Simon Glass439fe7a2012-03-09 16:19:34 -08001154 pack.AddProperty('gbb', self.uboot_fname)
Simon Glass9d088d92012-07-16 16:27:11 +01001155 blob_list = pack.GetBlobList()
1156 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -07001157 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -08001158 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -07001159
Simon Glass7306b902012-12-17 15:06:21 -08001160 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001161 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001162 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001163 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001164 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001165 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001166 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001167 pack.AddProperty('fwid', fwid)
1168 pack.AddProperty('gbb', gbb)
1169 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001170
1171 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001172
1173 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001174 pack.UpdateBlobPositionsAndHashes(fdt)
1175 pack.UpdateBlobPositionsAndHashes(fdt_rwa)
1176 pack.UpdateBlobPositionsAndHashes(fdt_rwb)
Simon Glass8884b982012-06-21 12:41:41 -07001177
Simon Glass6207efe2012-12-17 15:04:36 -08001178 # Make a copy of the fdt for the bootstub
1179 fdt_data = self._tools.ReadFile(fdt.fname)
1180 uboot_data = self._tools.ReadFile(self.uboot_fname)
1181 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1182 self._tools.WriteFile(uboot_copy, uboot_data)
1183
1184 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1185 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
1186
Simon Glassa10282a2013-01-08 17:06:41 -08001187 # Fix up the coreboot image here, since we can't do this until we have
1188 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +01001189 if 'coreboot' in blob_list:
1190 bootstub = pack.GetProperty('coreboot')
1191 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001192 if self.coreboot_elf:
1193 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1194 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
1195 else:
Simon Glass0a7cf112013-05-21 23:08:21 -07001196 text_base = 0x1110000
1197
1198 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1199 # 1110015: 66 bb 00 01 mov $0x100,%bx
1200 marker = struct.pack('<L', 0x0100bb66)
1201 pos = uboot_data.find(marker)
1202 if pos == -1 or pos > 0x100:
1203 raise ValueError('Cannot find U-Boot cold boot entry point')
1204 entry = text_base + pos
1205 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001206 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1207 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001208 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001209 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1210 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001211 data = self._tools.ReadFile(bootstub)
1212 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1213 self._tools.WriteFile(bootstub_copy, data)
Gabe Black3df75252013-02-14 21:32:10 -08001214 self._tools.WriteFile(bootstub, data[-0x100000:])
Simon Glasscbc83552012-07-23 15:26:22 +01001215
Simon Glass208ad952013-02-10 11:16:46 -08001216 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001217 image = os.path.join(self._tools.outdir, 'image.bin')
1218 pack.PackImage(self._tools.outdir, image)
1219 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001220
Simon Glass439fe7a2012-03-09 16:19:34 -08001221 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001222 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001223 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001224
Simon Glassdedda6f2013-02-09 13:44:14 -08001225 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001226 """Select an FDT to control the firmware bundling
1227
Simon Glassdedda6f2013-02-09 13:44:14 -08001228 We make a copy of this which will include any on-the-fly changes we want
1229 to make.
1230
Simon Glass290a1802011-07-17 13:54:32 -07001231 Args:
1232 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001233 use_defaults: True to use a default FDT name if available, and to add
1234 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001235
Simon Glassc0f3dc62011-08-09 14:19:05 -07001236 Returns:
1237 The Fdt object of the original fdt file, which we will not modify.
1238
Simon Glassdedda6f2013-02-09 13:44:14 -08001239 Raises:
1240 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1241 False).
Simon Glass290a1802011-07-17 13:54:32 -07001242 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001243 if use_defaults:
1244 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001245 if not fdt_fname:
1246 raise ValueError('Please provide an FDT filename')
1247 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001248 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001249
1250 # For upstream, select the correct architecture .dtsi manually.
1251 if self._board == 'link' or 'x86' in self._board:
1252 arch_dts = 'coreboot.dtsi'
1253 elif self._board == 'daisy':
1254 arch_dts = 'exynos5250.dtsi'
1255 else:
1256 arch_dts = 'tegra20.dtsi'
1257
1258 fdt.Compile(arch_dts)
Simon Glass290a1802011-07-17 13:54:32 -07001259 self.fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Simon Glassc0f3dc62011-08-09 14:19:05 -07001260 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001261
Simon Glassc90cf582012-03-13 15:40:47 -07001262 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001263 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001264
1265 - Checks options, tools, output directory, fdt.
1266 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001267
1268 Args:
Simon Glass56577572011-07-19 11:08:06 +12001269 hardware_id: Hardware ID to use for this board. If None, then the
1270 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001271 output_fname: Output filename for the image. If this is not None, then
1272 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001273 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001274
1275 Returns:
1276 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001277 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001278 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1279 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1280 else:
Simon Glass56577572011-07-19 11:08:06 +12001281 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001282
1283 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001284 image, pack = self._CreateImage(gbb, self.fdt)
1285 if show_map:
1286 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001287 if output_fname:
1288 shutil.copyfile(image, output_fname)
1289 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001290 return image, pack.props