blob: d16bac2d1183fdbbb70a267e99c621d1d7fc8cf3 [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.
466
467 Raises:
468 CmdError if a command fails.
469 """
Simon Glass56577572011-07-19 11:08:06 +1200470 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800471 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700472 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700473 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700474
Simon Glass4a887b12012-10-23 16:29:03 -0700475 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800476
Simon Glass157c0662012-10-23 13:52:42 -0700477 # Allow command line to override flags
478 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
479
Simon Glass4a887b12012-10-23 16:29:03 -0700480 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700481 self._out.Progress('Creating GBB')
482 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
483 sizes = ['%#x' % size for size in sizes]
484 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700485 keydir = self._tools.Filename(self._keydir)
486 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700487 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200488 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700489 '--rootkey=%s/root_key.vbpubk' % keydir,
490 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700491 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800492 '--flags=%d' % gbb_flags,
Simon Glass89b86b82011-07-17 23:49:49 -0700493 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700494 cwd=odir)
495 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700496
Simon Glasse13ee2c2011-07-28 08:12:28 +1200497 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700498 """Sign an image so that the Tegra SOC will boot it.
499
500 Args:
501 bct: BCT file to use.
502 bootstub: Boot stub (U-Boot + fdt) file to sign.
503 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700504
505 Returns:
506 filename of signed image.
507
508 Raises:
509 CmdError if a command fails.
510 """
511 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200512 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700513 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200514 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700515 fd = open(config, 'w')
516 fd.write('Version = 1;\n')
517 fd.write('Redundancy = 1;\n')
518 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700519
520 # TODO(dianders): Right now, we don't have enough space in our flash map
521 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
522 # sure what this does for reliability, but at least things will fit...
523 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
524 if is_nand:
525 fd.write('Bctcopy = 1;\n')
526
Simon Glass89b86b82011-07-17 23:49:49 -0700527 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
528 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700529
Simon Glass89b86b82011-07-17 23:49:49 -0700530 fd.close()
531
532 self._tools.Run('cbootimage', [config, signed])
533 self._tools.OutputSize('BCT', bct)
534 self._tools.OutputSize('Signed image', signed)
535 return signed
536
Doug Anderson86ce5f42011-07-27 10:40:18 -0700537 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700538 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700539
540 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700541 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700542 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700543 """
Simon Glass468d8752012-09-19 16:36:19 -0700544 if bootcmd is not None:
545 if bootcmd == 'none':
546 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800547 self.fdt.PutString('/config', 'bootcmd', bootcmd)
548 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700549 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700550
Simon Glassa4934b72012-05-09 13:35:02 -0700551 def SetNodeEnabled(self, node_name, enabled):
552 """Set whether an node is enabled or disabled.
553
554 This simply sets the 'status' property of a node to "ok", or "disabled".
555
556 The node should either be a full path to the node (like '/uart@10200000')
557 or an alias property.
558
559 Aliases are supported like this:
560
561 aliases {
562 console = "/uart@10200000";
563 };
564
565 pointing to a node:
566
567 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700568 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700569 };
570
571 In this case, this function takes the name of the alias ('console' in
572 this case) and updates the status of the node that is pointed to, to
573 either ok or disabled. If the alias does not exist, a warning is
574 displayed.
575
576 Args:
577 node_name: Name of node (e.g. '/uart@10200000') or alias alias
578 (e.g. 'console') to adjust
579 enabled: True to enable, False to disable
580 """
581 # Look up the alias if this is an alias reference
582 if not node_name.startswith('/'):
583 lookup = self.fdt.GetString('/aliases', node_name, '')
584 if not lookup:
585 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
586 return
587 node_name = lookup
588 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700589 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700590 else:
591 status = 'disabled'
592 self.fdt.PutString(node_name, 'status', status)
593
594 def AddEnableList(self, enable_list):
595 """Process a list of nodes to enable/disable.
596
597 Args:
598 config_list: List of (node, value) tuples to add to the fdt. For each
599 tuple:
600 node: The fdt node to write to will be <node> or pointed to by
601 /aliases/<node>. We can tell which
602 value: 0 to disable the node, 1 to enable it
603 """
604 if enable_list:
605 for node_name, enabled in enable_list:
606 try:
607 enabled = int(enabled)
608 if enabled not in (0, 1):
609 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700610 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700611 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700612 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700613 self.SetNodeEnabled(node_name, enabled)
614
Simon Glass290a1802011-07-17 13:54:32 -0700615 def AddConfigList(self, config_list, use_int=False):
616 """Add a list of config items to the fdt.
617
618 Normally these values are written to the fdt as strings, but integers
619 are also supported, in which case the values will be converted to integers
620 (if necessary) before being stored.
621
622 Args:
623 config_list: List of (config, value) tuples to add to the fdt. For each
624 tuple:
625 config: The fdt node to write to will be /config/<config>.
626 value: An integer or string value to write.
627 use_int: True to only write integer values.
628
629 Raises:
630 CmdError: if a value is required to be converted to integer but can't be.
631 """
632 if config_list:
633 for config in config_list:
634 value = config[1]
635 if use_int:
636 try:
637 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700638 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700639 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700640 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700641 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800642 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700643 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800644 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700645
Simon Glass7c2d5572011-11-15 14:47:08 -0800646 def DecodeTextBase(self, data):
647 """Look at a U-Boot image and try to decode its TEXT_BASE.
648
649 This works because U-Boot has a header with the value 0x12345678
650 immediately followed by the TEXT_BASE value. We can therefore read this
651 from the image with some certainty. We check only the first 40 words
652 since the header should be within that region.
653
Simon Glass96b50302012-07-20 06:55:28 +0100654 Since upstream Tegra has moved to having a 16KB SPL region at the start,
655 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
656 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
657
Simon Glass7c2d5572011-11-15 14:47:08 -0800658 Args:
659 data: U-Boot binary data
660
661 Returns:
662 Text base (integer) or None if none was found
663 """
664 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100665 for start in (0, 0x4000):
666 for i in range(start, start + 160, 4):
667 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800668
Simon Glass96b50302012-07-20 06:55:28 +0100669 # TODO(sjg): This does not cope with a big-endian target
670 value = struct.unpack('<I', word)[0]
671 if found:
672 return value - start
673 if value == 0x12345678:
674 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800675
676 return None
677
678 def CalcTextBase(self, name, fdt, fname):
679 """Calculate the TEXT_BASE to use for U-Boot.
680
681 Normally this value is in the fdt, so we just read it from there. But as
682 a second check we look at the image itself in case this is different, and
683 switch to that if it is.
684
685 This allows us to flash any U-Boot even if its TEXT_BASE is different.
686 This is particularly useful with upstream U-Boot which uses a different
687 value (which we will move to).
688 """
689 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800690 # The value that comes back from fdt.GetInt is signed, which makes no
691 # sense for an address base. Force it to unsigned.
692 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800693 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100694 text_base_str = '%#x' % text_base if text_base else 'None'
695 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
696 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800697
698 # If they are different, issue a warning and switch over.
699 if text_base and text_base != fdt_text_base:
700 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
701 "fdt value of %x. Using %x" % (text_base, name,
702 fdt_text_base, text_base))
703 fdt_text_base = text_base
704 return fdt_text_base
705
Simon Glass6dcc2f22011-07-28 15:26:49 +1200706 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700707 """Create a boot stub and a signed boot stub.
708
Simon Glass6dcc2f22011-07-28 15:26:49 +1200709 For postload:
710 We add a /config/postload-text-offset entry to the signed bootstub's
711 fdt so that U-Boot can find the postload code.
712
713 The raw (unsigned) bootstub will have a value of -1 for this since we will
714 simply append the postload code to the bootstub and it can find it there.
715 This will be used for RW A/B firmware.
716
717 For the signed case this value will specify where in the flash to find
718 the postload code. This will be used for RO firmware.
719
Simon Glass89b86b82011-07-17 23:49:49 -0700720 Args:
721 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800722 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200723 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700724
725 Returns:
726 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200727 Full path to bootstub (uboot + fdt(-1) + postload).
728 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700729
730 Raises:
731 CmdError if a command fails.
732 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200733 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800734 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700735 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200736
737 # Make a copy of the fdt for the bootstub
738 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700739 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700740 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200741
Simon Glass89b86b82011-07-17 23:49:49 -0700742 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700743 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
744 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700745 self._tools.OutputSize('Combined binary', bootstub)
746
Simon Glasse13ee2c2011-07-28 08:12:28 +1200747 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700748 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700749 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200750 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200751
752 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
753 data = self._tools.ReadFile(signed)
754
755 if postload:
756 # We must add postload to the bootstub since A and B will need to
757 # be able to find it without the /config/postload-text-offset mechanism.
758 bs_data = self._tools.ReadFile(bootstub)
759 bs_data += self._tools.ReadFile(postload)
760 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
761 self._tools.WriteFile(bootstub, bs_data)
762 self._tools.OutputSize('Combined binary with postload', bootstub)
763
764 # Now that we know the file size, adjust the fdt and re-sign
765 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800766 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200767 fdt_data = self._tools.ReadFile(fdt.fname)
768 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
769 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
770 postload_bootstub, text_base)
771 if len(data) != os.path.getsize(signed):
772 raise CmdError('Signed file size changed from %d to %d after updating '
773 'fdt' % (len(data), os.path.getsize(signed)))
774
775 # Re-read the signed image, and add the post-load binary.
776 data = self._tools.ReadFile(signed)
777 data += self._tools.ReadFile(postload)
778 self._tools.OutputSize('Post-load binary', postload)
779
780 self._tools.WriteFile(signed_postload, data)
781 self._tools.OutputSize('Final bootstub with postload', signed_postload)
782
783 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700784
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700785 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700786 """Create a coreboot boot stub.
787
788 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700789 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700790
791 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100792 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700793
794 Raises:
795 CmdError if a command fails.
796 """
797 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700798 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100799
800 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700801 return bootstub
802
Simon Glass3b404092012-05-23 13:10:36 -0700803 def _UpdateBl2Parameters(self, fdt, spl_load_size, data, pos):
Simon Glassdf95dd22012-03-13 15:46:16 -0700804 """Update the parameters in a BL2 blob.
805
806 We look at the list in the parameter block, extract the value of each
807 from the device tree, and write that value to the parameter block.
808
809 Args:
810 fdt: Device tree containing the parameter values.
Simon Glass3b404092012-05-23 13:10:36 -0700811 spl_load_size: Size of U-Boot image that SPL must load
Simon Glassdf95dd22012-03-13 15:46:16 -0700812 data: The BL2 data.
813 pos: The position of the start of the parameter block.
814
815 Returns:
816 The new contents of the parameter block, after updating.
817 """
Simon Glassdf95dd22012-03-13 15:46:16 -0700818 version, size = struct.unpack('<2L', data[pos + 4:pos + 12])
819 if version != 1:
820 raise CmdError("Cannot update machine parameter block version '%d'" %
821 version)
822 if size < 0 or pos + size > len(data):
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700823 raise CmdError("Machine parameter block size %d is invalid: "
824 "pos=%d, size=%d, space=%d, len=%d" %
825 (size, pos, size, len(data) - pos, len(data)))
Simon Glassdf95dd22012-03-13 15:46:16 -0700826
827 # Move past the header and read the parameter list, which is terminated
828 # with \0.
829 pos += 12
830 param_list = struct.unpack('<%ds' % (len(data) - pos), data[pos:])[0]
831 param_len = param_list.find('\0')
832 param_list = param_list[:param_len]
Simon Glass66c1a9f2012-03-22 19:15:53 -0700833 pos += (param_len + 4) & ~3
Simon Glassdf95dd22012-03-13 15:46:16 -0700834
835 # Work through the parameters one at a time, adding each value
836 new_data = ''
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700837 upto = 0
Simon Glassdf95dd22012-03-13 15:46:16 -0700838 for param in param_list:
Simon Glass2c48ddf2012-03-23 16:55:22 -0700839 value = struct.unpack('<1L', data[pos + upto:pos + upto + 4])[0]
Simon Glass56583742012-11-06 12:34:47 -0800840
841 # Use this to detect a missing value from the fdt.
842 not_given = 'not-given-invalid-value'
Simon Glassdf95dd22012-03-13 15:46:16 -0700843 if param == 'm' :
Simon Glass56583742012-11-06 12:34:47 -0800844 mem_type = fdt.GetString('/dmc', 'mem-type', not_given)
845 if mem_type == not_given:
846 mem_type = 'ddr3'
847 self._out.Warning("No value for memory type: using '%s'" % mem_type)
Simon Glassdf95dd22012-03-13 15:46:16 -0700848 mem_types = ['ddr2', 'ddr3', 'lpddr2', 'lpddr3']
849 if not mem_type in mem_types:
850 raise CmdError("Unknown memory type '%s'" % mem_type)
851 value = mem_types.index(mem_type)
852 self._out.Info(' Memory type: %s (%d)' % (mem_type, value))
Doug Andersonee46cfe2012-05-18 09:53:08 -0700853 elif param == 'M' :
Simon Glass56583742012-11-06 12:34:47 -0800854 mem_manuf = fdt.GetString('/dmc', 'mem-manuf', not_given)
855 if mem_manuf == not_given:
856 mem_manuf = 'samsung'
857 self._out.Warning("No value for memory manufacturer: using '%s'" %
858 mem_manuf)
Doug Andersonee46cfe2012-05-18 09:53:08 -0700859 mem_manufs = ['autodetect', 'elpida', 'samsung']
860 if not mem_manuf in mem_manufs:
861 raise CmdError("Unknown memory manufacturer: '%s'" % mem_manuf)
862 value = mem_manufs.index(mem_manuf)
863 self._out.Info(' Memory manufacturer: %s (%d)' % (mem_manuf, value))
Simon Glass158289e2012-09-14 11:42:25 -0700864 elif param == 'f' :
Simon Glass56583742012-11-06 12:34:47 -0800865 mem_freq = fdt.GetInt('/dmc', 'clock-frequency', -1)
866 if mem_freq == -1:
867 mem_freq = 800000000
868 self._out.Warning("No value for memory frequency: using '%s'" %
869 mem_freq)
870 mem_freq /= 1000000
Simon Glass158289e2012-09-14 11:42:25 -0700871 if not mem_freq in [533, 667, 800]:
872 self._out.Warning("Unexpected memory speed '%s'" % mem_freq)
873 value = mem_freq
874 self._out.Info(' Memory speed: %d' % mem_freq)
Simon Glass5d23e312013-05-25 22:47:56 -0700875 elif param == 'a' :
876 arm_freq = fdt.GetInt('/dmc', 'arm-frequency', -1)
877 if arm_freq == -1:
878 arm_freq = 1700000000
879 self._out.Warning("No value for ARM frequency: using '%s'" %
880 arm_freq)
881 arm_freq /= 1000000
882 value = arm_freq
883 self._out.Info(' ARM speed: %d' % arm_freq)
884 elif param == 'i':
885 i2c_addr = -1
886 lookup = fdt.GetString('/aliases', 'pmic', '')
887 if lookup:
888 i2c_addr, size = fdt.GetIntList(lookup, 'reg', 2)
889 if i2c_addr == -1:
890 self._out.Warning("No value for PMIC I2C address: using %#08x" %
891 value)
892 else:
893 value = i2c_addr
894 self._out.Info(' PMIC I2C Address: %#08x' % value)
895 elif param == 's':
896 serial_addr = -1
897 lookup = fdt.GetString('/aliases', 'console', '')
898 if lookup:
899 serial_addr, size = fdt.GetIntList(lookup, 'reg', 2)
900 if serial_addr == -1:
901 self._out.Warning("No value for Console address: using %#08x" %
902 value)
903 else:
904 value = serial_addr
905 self._out.Info(' Console Address: %#08x' % value)
Simon Glassdf95dd22012-03-13 15:46:16 -0700906 elif param == 'v':
907 value = 31
908 self._out.Info(' Memory interleave: %#0x' % value)
Simon Glass8e1fdb22012-03-15 21:02:10 -0700909 elif param == 'u':
Simon Glass3b404092012-05-23 13:10:36 -0700910 value = (spl_load_size + 0xfff) & ~0xfff
911 self._out.Info(' U-Boot size: %#0x (rounded up from %#0x)' %
912 (value, spl_load_size))
Simon Glass5d23e312013-05-25 22:47:56 -0700913 elif param == 'l':
914 load_addr = fdt.GetInt('/config', 'u-boot-load-addr', -1)
915 if load_addr == -1:
916 self._out.Warning("No value for U-Boot load address: using '%08x'" %
917 value)
918 else:
919 value = load_addr
920 self._out.Info(' U-Boot load address: %#0x' % value)
Simon Glass559b6612012-05-23 13:28:45 -0700921 elif param == 'b':
922 # These values come from enum boot_mode in U-Boot's cpu.h
923 if self.spl_source == 'straps':
924 value = 32
925 elif self.spl_source == 'emmc':
926 value = 4
927 elif self.spl_source == 'spi':
928 value = 20
929 elif self.spl_source == 'usb':
930 value = 33
931 else:
932 raise CmdError("Invalid boot source '%s'" % self.spl_source)
933 self._out.Info(' Boot source: %#0x' % value)
Simon Glass5d23e312013-05-25 22:47:56 -0700934 elif param in ['r', 'R']:
935 records = fdt.GetIntList('/board-rev', 'google,board-rev-gpios',
936 None, '0 0')
937 gpios = []
938 for i in range(1, len(records), 3):
939 gpios.append(records[i])
940 gpios.extend([0, 0, 0, 0])
941 if param == 'r':
942 value = gpios[0] + (gpios[1] << 16)
943 self._out.Info(' Board ID GPIOs: tit0=%d, tit1=%d' % (gpios[0],
944 gpios[1]))
945 else:
946 value = gpios[2] + (gpios[3] << 16)
947 self._out.Info(' Board ID GPIOs: tit2=%d, tit3=%d' % (gpios[2],
948 gpios[3]))
Tom Wai-Hong Tam99b7f112013-02-06 09:10:10 +0800949 elif param == 'z':
950 compress = fdt.GetString('/flash/ro-boot', 'compress', 'none')
951 compress_types = ['none', 'lzo']
952 if not compress in compress_types:
953 raise CmdError("Unknown compression type '%s'" % compress)
954 value = compress_types.index(compress)
955 self._out.Info(' Compression type: %#0x' % value)
Simon Glassdf95dd22012-03-13 15:46:16 -0700956 else:
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700957 self._out.Warning("Unknown machine parameter type '%s'" % param)
Simon Glass2c48ddf2012-03-23 16:55:22 -0700958 self._out.Info(' Unknown value: %#0x' % value)
Simon Glassdf95dd22012-03-13 15:46:16 -0700959 new_data += struct.pack('<L', value)
Simon Glass7dbdf5b2012-03-15 20:58:04 -0700960 upto += 4
Simon Glassdf95dd22012-03-13 15:46:16 -0700961
962 # Put the data into our block.
963 data = data[:pos] + new_data + data[pos + len(new_data):]
964 self._out.Info('BL2 configuration complete')
965 return data
966
Simon Glasse5e8afb2012-05-23 11:19:23 -0700967 def _UpdateChecksum(self, data):
968 """Update the BL2 checksum.
969
970 The checksum is a 4 byte sum of all the bytes in the image before the
971 last 4 bytes (which hold the checksum).
972
973 Args:
974 data: The BL2 data to update.
975
976 Returns:
977 The new contents of the BL2 data, after updating the checksum.
978 """
979 checksum = 0
980 for ch in data[:-4]:
981 checksum += ord(ch)
982 return data[:-4] + struct.pack('<L', checksum & 0xffffffff)
983
Simon Glass559b6612012-05-23 13:28:45 -0700984 def ConfigureExynosBl2(self, fdt, spl_load_size, orig_bl2, name=''):
Simon Glass7e199222012-03-13 15:51:18 -0700985 """Configure an Exynos BL2 binary for our needs.
986
987 We create a new modified BL2 and return its filename.
988
989 Args:
990 fdt: Device tree containing the parameter values.
Simon Glass3b404092012-05-23 13:10:36 -0700991 spl_load_size: Size of U-Boot image that SPL must load
Simon Glass7e199222012-03-13 15:51:18 -0700992 orig_bl2: Filename of original BL2 file to modify.
993 """
Simon Glass66c1a9f2012-03-22 19:15:53 -0700994 self._out.Info('Configuring BL2')
Simon Glass559b6612012-05-23 13:28:45 -0700995 bl2 = os.path.join(self._tools.outdir, 'updated-spl%s.bin' % name)
Simon Glass66c1a9f2012-03-22 19:15:53 -0700996 data = self._tools.ReadFile(orig_bl2)
997 self._tools.WriteFile(bl2, data)
Simon Glass7e199222012-03-13 15:51:18 -0700998
999 # Locate the parameter block
1000 data = self._tools.ReadFile(bl2)
1001 marker = struct.pack('<L', 0xdeadbeef)
1002 pos = data.rfind(marker)
1003 if not pos:
1004 raise CmdError("Could not find machine parameter block in '%s'" %
1005 orig_bl2)
Simon Glass3b404092012-05-23 13:10:36 -07001006 data = self._UpdateBl2Parameters(fdt, spl_load_size, data, pos)
Simon Glasse5e8afb2012-05-23 11:19:23 -07001007 data = self._UpdateChecksum(data)
Simon Glass7e199222012-03-13 15:51:18 -07001008 self._tools.WriteFile(bl2, data)
1009 return bl2
1010
Simon Glass89b86b82011-07-17 23:49:49 -07001011 def _PackOutput(self, msg):
1012 """Helper function to write output from PackFirmware (verbose level 2).
1013
1014 This is passed to PackFirmware for it to use to write output.
1015
1016 Args:
1017 msg: Message to display.
1018 """
1019 self._out.Notice(msg)
1020
Simon Glass439fe7a2012-03-09 16:19:34 -08001021 def _BuildBlob(self, pack, fdt, blob_type):
1022 """Build the blob data for a particular blob type.
1023
1024 Args:
1025 blob_type: The type of blob to create data for. Supported types are:
1026 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
1027 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
1028 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001029 # stupid pylint insists that sha256 is not in hashlib.
1030 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -08001031 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001032 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -08001033 pack.AddProperty('coreboot', coreboot)
1034 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -07001035 elif blob_type == 'legacy':
1036 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -08001037 elif blob_type == 'signed':
1038 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
1039 self.postload_fname)
1040 pack.AddProperty('bootstub', bootstub)
1041 pack.AddProperty('signed', signed)
1042 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -07001043 elif blob_type == 'exynos-bl1':
1044 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -07001045
1046 # TODO(sjg@chromium.org): Deprecate ecbin
1047 elif blob_type in ['ecrw', 'ecbin']:
1048 pack.AddProperty('ecrw', self.ecrw_fname)
1049 pack.AddProperty('ecbin', self.ecrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -08001050 elif blob_type == 'ecrwhash':
1051 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
1052 ecrw = self._tools.ReadFile(self.ecrw_fname)
1053 hasher = hashlib.sha256()
1054 hasher.update(ecrw)
1055 self._tools.WriteFile(ec_hash_file, hasher.digest())
1056 pack.AddProperty(blob_type, ec_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -07001057 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -07001058 # crosbug.com/p/13143
1059 # We cannot have an fmap in the EC image since there can be only one,
1060 # which is the main fmap describing the whole image.
1061 # Ultimately the EC will not have an fmap, since with software sync
1062 # there is no flashrom involvement in updating the EC flash, and thus
1063 # no need for the fmap.
1064 # For now, mangle the fmap name to avoid problems.
1065 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
1066 data = self._tools.ReadFile(self.ecro_fname)
1067 data = re.sub('__FMAP__', '__fMAP__', data)
1068 self._tools.WriteFile(updated_ecro, data)
1069 pack.AddProperty(blob_type, updated_ecro)
Simon Glass7e199222012-03-13 15:51:18 -07001070 elif blob_type == 'exynos-bl2':
Simon Glass7d2542f2012-06-21 07:10:59 -07001071 spl_payload = pack.GetBlobParams(blob_type)
1072
1073 # TODO(sjg@chromium): Remove this later, when we remove boot+dtb
1074 # from all flash map files.
1075 if not spl_payload:
1076 spl_load_size = os.stat(pack.GetProperty('boot+dtb')).st_size
1077 prop_list = 'boot+dtb'
1078
1079 # Do this later, when we remove boot+dtb.
1080 # raise CmdError("No parameters provided for blob type '%s'" %
1081 # blob_type)
1082 else:
1083 prop_list = spl_payload[0].split(',')
Tom Wai-Hong Tam26e3a4c2013-02-06 09:36:47 +08001084 compress = fdt.GetString('/flash/ro-boot', 'compress', 'none')
1085 if compress == 'none':
1086 compress = None
1087 spl_load_size = len(pack.ConcatPropContents(prop_list, compress,
1088 False)[0])
Simon Glass7d2542f2012-06-21 07:10:59 -07001089 self._out.Info("BL2/SPL contains '%s', size is %d / %#x" %
1090 (', '.join(prop_list), spl_load_size, spl_load_size))
Simon Glass3b404092012-05-23 13:10:36 -07001091 bl2 = self.ConfigureExynosBl2(fdt, spl_load_size, self.exynos_bl2)
Simon Glass7e199222012-03-13 15:51:18 -07001092 pack.AddProperty(blob_type, bl2)
Simon Glass439fe7a2012-03-09 16:19:34 -08001093 elif pack.GetProperty(blob_type):
1094 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -08001095 elif blob_type in self.blobs:
1096 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -08001097 else:
1098 raise CmdError("Unknown blob type '%s' required in flash map" %
1099 blob_type)
1100
Simon Glass290a1802011-07-17 13:54:32 -07001101 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -07001102 """Create a full firmware image, along with various by-products.
1103
1104 This uses the provided u-boot.bin, fdt and bct to create a firmware
1105 image containing all the required parts. If the GBB is not supplied
1106 then this will just return a signed U-Boot as the image.
1107
1108 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +12001109 gbb: Full path to the GBB file, or empty if a GBB is not required.
1110 fdt: Fdt object containing required information.
1111
1112 Returns:
1113 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001114
1115 Raises:
1116 CmdError if a command fails.
1117 """
Simon Glass02d124a2012-03-02 14:47:20 -08001118 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001119
Simon Glass439fe7a2012-03-09 16:19:34 -08001120 pack = PackFirmware(self._tools, self._out)
Vadim Bendebury238f6442013-03-27 11:23:25 -07001121 # Get the flashmap so we know what to build. For board variants use the
1122 # main board name as the key (drop the _<variant> suffix).
1123 default_flashmap = default_flashmaps.get(self._board.split('_')[0])
Simon Glassb8c6d952012-12-01 06:14:35 -08001124 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001125 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
1126 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001127
Simon Glass0c54ba52012-11-06 12:36:43 -08001128 pack.SelectFdt(fdt, self._board, default_flashmap)
Simon Glass439fe7a2012-03-09 16:19:34 -08001129
1130 # Get all our blobs ready
1131 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001132 if self.skeleton_fname:
1133 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001134 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001135
Simon Glass47817052012-10-20 13:30:07 -07001136 # Let's create some copies of the fdt for vboot. These can be used to
1137 # pass a different fdt to each firmware type. For now it is just used to
1138 # check that the right fdt comes through.
1139 fdt_rwa = fdt.Copy(os.path.join(self._tools.outdir, 'updated-rwa.dtb'))
1140 fdt_rwa.PutString('/chromeos-config', 'firmware-type', 'rw-a')
1141 pack.AddProperty('dtb-rwa', fdt_rwa.fname)
1142 fdt_rwb = fdt.Copy(os.path.join(self._tools.outdir, 'updated-rwb.dtb'))
1143 fdt_rwb.PutString('/chromeos-config', 'firmware-type', 'rw-b')
1144 pack.AddProperty('dtb-rwb', fdt_rwb.fname)
1145 fdt.PutString('/chromeos-config', 'firmware-type', 'ro')
1146
Simon Glassde9c8072012-07-02 22:29:02 -07001147 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1148 if self.kernel_fname:
1149 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1150
Simon Glass439fe7a2012-03-09 16:19:34 -08001151 pack.AddProperty('gbb', self.uboot_fname)
Simon Glass9d088d92012-07-16 16:27:11 +01001152 blob_list = pack.GetBlobList()
1153 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -07001154 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -08001155 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -07001156
Simon Glass7306b902012-12-17 15:06:21 -08001157 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001158 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001159 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001160 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001161 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001162 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001163 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001164 pack.AddProperty('fwid', fwid)
1165 pack.AddProperty('gbb', gbb)
1166 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001167
1168 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001169
1170 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001171 pack.UpdateBlobPositionsAndHashes(fdt)
1172 pack.UpdateBlobPositionsAndHashes(fdt_rwa)
1173 pack.UpdateBlobPositionsAndHashes(fdt_rwb)
Simon Glass8884b982012-06-21 12:41:41 -07001174
Simon Glass6207efe2012-12-17 15:04:36 -08001175 # Make a copy of the fdt for the bootstub
1176 fdt_data = self._tools.ReadFile(fdt.fname)
1177 uboot_data = self._tools.ReadFile(self.uboot_fname)
1178 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1179 self._tools.WriteFile(uboot_copy, uboot_data)
1180
1181 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1182 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
1183
Simon Glassa10282a2013-01-08 17:06:41 -08001184 # Fix up the coreboot image here, since we can't do this until we have
1185 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +01001186 if 'coreboot' in blob_list:
1187 bootstub = pack.GetProperty('coreboot')
1188 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001189 if self.coreboot_elf:
1190 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1191 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
1192 else:
Simon Glass0a7cf112013-05-21 23:08:21 -07001193 text_base = 0x1110000
1194
1195 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1196 # 1110015: 66 bb 00 01 mov $0x100,%bx
1197 marker = struct.pack('<L', 0x0100bb66)
1198 pos = uboot_data.find(marker)
1199 if pos == -1 or pos > 0x100:
1200 raise ValueError('Cannot find U-Boot cold boot entry point')
1201 entry = text_base + pos
1202 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001203 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1204 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001205 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001206 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1207 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001208 data = self._tools.ReadFile(bootstub)
1209 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1210 self._tools.WriteFile(bootstub_copy, data)
Gabe Black3df75252013-02-14 21:32:10 -08001211 self._tools.WriteFile(bootstub, data[-0x100000:])
Simon Glasscbc83552012-07-23 15:26:22 +01001212
Simon Glass208ad952013-02-10 11:16:46 -08001213 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001214 image = os.path.join(self._tools.outdir, 'image.bin')
1215 pack.PackImage(self._tools.outdir, image)
1216 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001217
Simon Glass439fe7a2012-03-09 16:19:34 -08001218 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001219 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001220 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001221
Simon Glassdedda6f2013-02-09 13:44:14 -08001222 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001223 """Select an FDT to control the firmware bundling
1224
Simon Glassdedda6f2013-02-09 13:44:14 -08001225 We make a copy of this which will include any on-the-fly changes we want
1226 to make.
1227
Simon Glass290a1802011-07-17 13:54:32 -07001228 Args:
1229 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001230 use_defaults: True to use a default FDT name if available, and to add
1231 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001232
Simon Glassc0f3dc62011-08-09 14:19:05 -07001233 Returns:
1234 The Fdt object of the original fdt file, which we will not modify.
1235
Simon Glassdedda6f2013-02-09 13:44:14 -08001236 Raises:
1237 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1238 False).
Simon Glass290a1802011-07-17 13:54:32 -07001239 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001240 if use_defaults:
1241 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001242 if not fdt_fname:
1243 raise ValueError('Please provide an FDT filename')
1244 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001245 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001246
1247 # For upstream, select the correct architecture .dtsi manually.
1248 if self._board == 'link' or 'x86' in self._board:
1249 arch_dts = 'coreboot.dtsi'
1250 elif self._board == 'daisy':
1251 arch_dts = 'exynos5250.dtsi'
1252 else:
1253 arch_dts = 'tegra20.dtsi'
1254
1255 fdt.Compile(arch_dts)
Simon Glass290a1802011-07-17 13:54:32 -07001256 self.fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Simon Glassc0f3dc62011-08-09 14:19:05 -07001257 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001258
Simon Glassc90cf582012-03-13 15:40:47 -07001259 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001260 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001261
1262 - Checks options, tools, output directory, fdt.
1263 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001264
1265 Args:
Simon Glass56577572011-07-19 11:08:06 +12001266 hardware_id: Hardware ID to use for this board. If None, then the
1267 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001268 output_fname: Output filename for the image. If this is not None, then
1269 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001270 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001271
1272 Returns:
1273 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001274 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001275 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1276 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1277 else:
Simon Glass56577572011-07-19 11:08:06 +12001278 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001279
1280 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001281 image, pack = self._CreateImage(gbb, self.fdt)
1282 if show_map:
1283 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001284 if output_fname:
1285 shutil.copyfile(image, output_fname)
1286 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001287 return image, pack.props