blob: 7b4c2fa60713eeb1e7660e5086c62664d5658931 [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
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05005"""This module builds a firmware image.
Simon Glass89b86b82011-07-17 23:49:49 -07006
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
Vadim Bendebury8c35e2e2014-05-06 12:55:50 -070028from flashmaps import default_flashmaps
Simon Glass439fe7a2012-03-09 16:19:34 -080029from tools import CmdError
Vadim Bendeburyb12e3352013-06-08 17:25:19 -070030from exynos import ExynosBl2
Simon Glass89b86b82011-07-17 23:49:49 -070031
Simon Glass4a887b12012-10-23 16:29:03 -070032# Build GBB flags.
33# (src/platform/vboot_reference/firmware/include/gbb_header.h)
34gbb_flag_properties = {
35 'dev-screen-short-delay': 0x00000001,
36 'load-option-roms': 0x00000002,
37 'enable-alternate-os': 0x00000004,
38 'force-dev-switch-on': 0x00000008,
39 'force-dev-boot-usb': 0x00000010,
40 'disable-fw-rollback-check': 0x00000020,
41 'enter-triggers-tonorm': 0x00000040,
42 'force-dev-boot-legacy': 0x00000080,
Shawn Nematbakhsh07c19882014-08-19 10:21:59 -070043 'faft-key-overide': 0x00000100,
44 'disable-ec-software-sync': 0x00000200,
45 'default-dev-boot-legacy': 0x00000400,
46 'disable-pd-software-sync': 0x00000800,
Furquan Shaikhd4eac3b2015-05-15 18:05:09 -070047 'force-dev-boot-fastboot-full-cap': 0x00002000,
Mary Ruthvena759c322015-11-16 08:23:26 -080048 'enable-serial': 0x00004000,
Simon Glass4a887b12012-10-23 16:29:03 -070049}
50
Simon Glass49b026b2013-04-26 16:38:42 -070051# Maps board name to Exynos product number
52type_to_model = {
53 'peach' : '5420',
54 'daisy' : '5250'
55}
56
Simon Glass5076a7f2012-10-23 16:31:54 -070057def ListGoogleBinaryBlockFlags():
58 """Print out a list of GBB flags."""
59 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
60 for name, value in gbb_flag_properties.iteritems():
61 print ' %-30s %02x' % (name, value)
62
Aaron Durbin41c85b62015-12-17 17:40:29 -060063class BlobDeferral(Exception):
64 """An error indicating deferal of blob generation."""
65 pass
66
Simon Glass89b86b82011-07-17 23:49:49 -070067class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070068 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070069
Simon Glass290a1802011-07-17 13:54:32 -070070 Sequence of events:
71 bundle = Bundle(tools.Tools(), cros_output.Output())
72 bundle.SetDirs(...)
73 bundle.SetFiles(...)
74 bundle.SetOptions(...)
75 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070076 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070077 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070078
Simon Glass290a1802011-07-17 13:54:32 -070079 Public properties:
80 fdt: The fdt object that we use for building our image. This wil be the
81 one specified by the user, except that we might add config options
82 to it. This is set up by SelectFdt() which must be called before
83 bundling starts.
84 uboot_fname: Full filename of the U-Boot binary we use.
85 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -070086 spl_source: Source device to load U-Boot from, in SPL:
87 straps: Select device according to CPU strap pins
88 spi: Boot from SPI
89 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -070090
91 Private attributes:
92 _small: True to create a 'small' signed U-Boot, False to produce a
93 full image. The small U-Boot is enough to boot but will not have
94 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -070095 """
Simon Glass89b86b82011-07-17 23:49:49 -070096
Simon Glass290a1802011-07-17 13:54:32 -070097 def __init__(self, tools, output):
98 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -070099
Simon Glass290a1802011-07-17 13:54:32 -0700100 Args:
101 tools: A tools.Tools object to use for external tools.
102 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700103 """
Simon Glass290a1802011-07-17 13:54:32 -0700104 self._tools = tools
105 self._out = output
106
107 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500108 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700109 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700110 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600111 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700112 self._gbb_flags = None
113 self._keydir = None
114 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700115 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700116 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800117 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700118 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700119 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700120 self.ecro_fname = None # Filename of EC read-only file
121 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700122 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700123 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
124 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700125 self.fdt = None # Our Fdt object.
126 self.kernel_fname = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700127 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700128 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700129 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700130
131 def SetDirs(self, keydir):
132 """Set up directories required for Bundle.
133
134 Args:
135 keydir: Directory containing keys to use for signing firmware.
136 """
137 self._keydir = keydir
138
Simon Glass6dcc2f22011-07-28 15:26:49 +1200139 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800140 coreboot_elf=None,
Simon Glass942bedb2016-05-14 16:19:59 -0600141 seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700142 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600143 kernel=None, blobs=None, skip_bmpblk=False, cbfs_files=None,
144 rocbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700145 """Set up files required for Bundle.
146
147 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500148 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700149 uboot: The filename of the u-boot.bin image to use.
150 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800151 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800152 coreboot: The filename of the coreboot image to use (on x86).
153 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Vincent Palatinf7286772011-10-12 14:31:53 -0700154 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700155 exynos_bl1: The filename of the exynos BL1 file
156 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
157 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700158 ecrw: The filename of the EC (Embedded Controller) read-write file.
159 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700160 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700161 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800162 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800163 skip_bmpblk: True if no bmpblk is required
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600164 cbfs_files: Root directory of files to be stored in RO and RW CBFS
165 rocbfs_files: Root directory of files to be stored in RO CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700166 """
167 self._board = board
168 self.uboot_fname = uboot
169 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800170 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700171 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800172 self.coreboot_elf = coreboot_elf
Vincent Palatinf7286772011-10-12 14:31:53 -0700173 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700174 self.exynos_bl1 = exynos_bl1
175 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700176 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700177 self.ecrw_fname = ecrw
178 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700179 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700180 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800181 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800182 self.skip_bmpblk = skip_bmpblk
Daisuke Nojiri69662892015-09-25 15:24:04 -0700183 self.cbfs_files = cbfs_files
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600184 self.rocbfs_files = rocbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700185
Simon Glass00d027e2013-07-20 14:51:12 -0600186 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700187 """Set up options supported by Bundle.
188
189 Args:
190 small: Only create a signed U-Boot - don't produce the full packed
191 firmware image. This is useful for devs who want to replace just the
192 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700193 gbb_flags: Specification for string containing adjustments to make.
194 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600195 force_efs: Force firmware to use 'early firmware selection' feature,
196 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700197 """
198 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700199 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700200 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600201 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700202
Simon Glass22f39fb2013-02-09 13:44:14 -0800203 def _GetBuildRoot(self):
204 """Get the path to this board's 'firmware' directory.
205
206 Returns:
207 Path to firmware directory, with ## representing the path to the
208 chroot.
209 """
Simon Glass290a1802011-07-17 13:54:32 -0700210 if not self._board:
211 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800212 return os.path.join('##', 'build', self._board, 'firmware')
213
214 def _CheckFdtFilename(self, fname):
215 """Check provided FDT filename and return the correct name if needed.
216
217 Where the filename lacks a path, add a default path for this board.
218 Where no FDT filename is provided, select a default one for this board.
219
220 Args:
221 fname: Proposed FDT filename.
222
223 Returns:
224 Selected FDT filename, after validation.
225 """
226 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700227 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800228 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700229 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700230 base_name = re.sub('_', '-', self._board)
231
232 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700233 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700234 found_list = glob.glob(self._tools.Filename(wildcard))
235 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800236 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700237 else:
238 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700239 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700240
Simon Glass881964d2012-04-04 11:34:09 -0700241 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800242 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700243 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700244 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800245 return fname
246
247 def CheckOptions(self):
248 """Check provided options and select defaults."""
249 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700250
Simon Glass49b026b2013-04-26 16:38:42 -0700251 board_type = self._board.split('_')[0]
252 model = type_to_model.get(board_type)
253
Simon Glass290a1802011-07-17 13:54:32 -0700254 if not self.uboot_fname:
255 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
256 if not self.bct_fname:
257 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700258 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700259 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700260 if model:
261 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700262 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700263 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700264 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700265 if not self.coreboot_fname:
266 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
267 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700268 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700269 if not self.seabios_fname:
270 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700271 if not self.ecrw_fname:
272 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700273 if not self.pdrw_fname:
274 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700275 if not self.ecro_fname:
276 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700277
Simon Glass75759302012-03-15 20:26:53 -0700278 def GetFiles(self):
279 """Get a list of files that we know about.
280
281 This is the opposite of SetFiles except that we may have put in some
282 default names. It returns a dictionary containing the filename for
283 each of a number of pre-defined files.
284
285 Returns:
286 Dictionary, with one entry for each file.
287 """
288 file_list = {
289 'bct' : self.bct_fname,
290 'exynos-bl1' : self.exynos_bl1,
291 'exynos-bl2' : self.exynos_bl2,
292 }
293 return file_list
294
Simon Glass4a887b12012-10-23 16:29:03 -0700295 def DecodeGBBFlagsFromFdt(self):
296 """Get Google Binary Block flags from the FDT.
297
298 These should be in the chromeos-config node, like this:
299
300 chromeos-config {
301 gbb-flag-dev-screen-short-delay;
302 gbb-flag-force-dev-switch-on;
303 gbb-flag-force-dev-boot-usb;
304 gbb-flag-disable-fw-rollback-check;
305 };
306
307 Returns:
308 GBB flags value from FDT.
309 """
310 chromeos_config = self.fdt.GetProps("/chromeos-config")
311 gbb_flags = 0
312 for name in chromeos_config:
313 if name.startswith('gbb-flag-'):
314 flag_value = gbb_flag_properties.get(name[9:])
315 if flag_value:
316 gbb_flags |= flag_value
317 self._out.Notice("FDT: Enabling %s." % name)
318 else:
319 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
320 return gbb_flags
321
Simon Glass157c0662012-10-23 13:52:42 -0700322 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
323 """Decode ajustments to the provided GBB flags.
324
325 We support three options:
326
327 hex value: c2
328 defined value: force-dev-boot-usb,load-option-roms
329 adjust default value: -load-option-roms,+force-dev-boot-usb
330
331 The last option starts from the passed-in GBB flags and adds or removes
332 flags.
333
334 Args:
335 gbb_flags: Base (default) FDT flags.
336 adjustments: String containing adjustments to make.
337
338 Returns:
339 Updated FDT flags.
340 """
341 use_base_value = True
342 if adjustments:
343 try:
344 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700345 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700346 pass
347 for flag in adjustments.split(','):
348 oper = None
349 if flag[0] in ['-', '+']:
350 oper = flag[0]
351 flag = flag[1:]
352 value = gbb_flag_properties.get(flag)
353 if not value:
354 raise ValueError("Invalid GBB flag '%s'" % flag)
355 if oper == '+':
356 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800357 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700358 elif oper == '-':
359 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800360 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700361 else:
362 if use_base_value:
363 gbb_flags = 0
364 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800365 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700366 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800367 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700368
369 return gbb_flags
370
Simon Glass56577572011-07-19 11:08:06 +1200371 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700372 """Create a GBB for the image.
373
Simon Glass56577572011-07-19 11:08:06 +1200374 Args:
375 hardware_id: Hardware ID to use for this board. If None, then the
376 default from the Fdt will be used
377
Simon Glass89b86b82011-07-17 23:49:49 -0700378 Returns:
379 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700380 """
Simon Glass56577572011-07-19 11:08:06 +1200381 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800382 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700383 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700384 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700385
Simon Glass4a887b12012-10-23 16:29:03 -0700386 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800387
Simon Glass157c0662012-10-23 13:52:42 -0700388 # Allow command line to override flags
389 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
390
Simon Glass4a887b12012-10-23 16:29:03 -0700391 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700392 self._out.Progress('Creating GBB')
Daisuke Nojiri10b193f2016-01-15 17:53:14 -0800393 if self.skip_bmpblk:
394 bmpfv_size = 0
395 else:
396 bmpfv_size = gbb_size - 0x2180
397 sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700398 sizes = ['%#x' % size for size in sizes]
399 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700400 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800401
402 gbb_set_command = ['-s',
403 '--hwid=%s' % hardware_id,
404 '--rootkey=%s/root_key.vbpubk' % keydir,
405 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
406 '--flags=%d' % gbb_flags,
407 gbb]
408 if not self.skip_bmpblk:
409 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
410 self.bmpblk_fname),]
411
Simon Glass290a1802011-07-17 13:54:32 -0700412 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800413 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700414 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700415
Simon Glasse13ee2c2011-07-28 08:12:28 +1200416 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700417 """Sign an image so that the Tegra SOC will boot it.
418
419 Args:
420 bct: BCT file to use.
421 bootstub: Boot stub (U-Boot + fdt) file to sign.
422 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700423
424 Returns:
425 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700426 """
427 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200428 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700429 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200430 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700431 fd = open(config, 'w')
432 fd.write('Version = 1;\n')
433 fd.write('Redundancy = 1;\n')
434 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700435
436 # TODO(dianders): Right now, we don't have enough space in our flash map
437 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
438 # sure what this does for reliability, but at least things will fit...
439 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
440 if is_nand:
441 fd.write('Bctcopy = 1;\n')
442
Simon Glass89b86b82011-07-17 23:49:49 -0700443 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
444 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700445
Simon Glass89b86b82011-07-17 23:49:49 -0700446 fd.close()
447
448 self._tools.Run('cbootimage', [config, signed])
449 self._tools.OutputSize('BCT', bct)
450 self._tools.OutputSize('Signed image', signed)
451 return signed
452
Doug Anderson86ce5f42011-07-27 10:40:18 -0700453 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700454 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700455
456 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700457 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700458 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700459 """
Simon Glass468d8752012-09-19 16:36:19 -0700460 if bootcmd is not None:
461 if bootcmd == 'none':
462 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800463 self.fdt.PutString('/config', 'bootcmd', bootcmd)
464 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700465 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700466
Simon Glassa4934b72012-05-09 13:35:02 -0700467 def SetNodeEnabled(self, node_name, enabled):
468 """Set whether an node is enabled or disabled.
469
470 This simply sets the 'status' property of a node to "ok", or "disabled".
471
472 The node should either be a full path to the node (like '/uart@10200000')
473 or an alias property.
474
475 Aliases are supported like this:
476
477 aliases {
478 console = "/uart@10200000";
479 };
480
481 pointing to a node:
482
483 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700484 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700485 };
486
487 In this case, this function takes the name of the alias ('console' in
488 this case) and updates the status of the node that is pointed to, to
489 either ok or disabled. If the alias does not exist, a warning is
490 displayed.
491
492 Args:
493 node_name: Name of node (e.g. '/uart@10200000') or alias alias
494 (e.g. 'console') to adjust
495 enabled: True to enable, False to disable
496 """
497 # Look up the alias if this is an alias reference
498 if not node_name.startswith('/'):
499 lookup = self.fdt.GetString('/aliases', node_name, '')
500 if not lookup:
501 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
502 return
503 node_name = lookup
504 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700505 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700506 else:
507 status = 'disabled'
508 self.fdt.PutString(node_name, 'status', status)
509
510 def AddEnableList(self, enable_list):
511 """Process a list of nodes to enable/disable.
512
513 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700514 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700515 tuple:
516 node: The fdt node to write to will be <node> or pointed to by
517 /aliases/<node>. We can tell which
518 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700519
Vadim Bendebury507c0012013-06-09 12:49:25 -0700520 Raises:
521 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700522 """
523 if enable_list:
524 for node_name, enabled in enable_list:
525 try:
526 enabled = int(enabled)
527 if enabled not in (0, 1):
528 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700529 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700530 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700531 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700532 self.SetNodeEnabled(node_name, enabled)
533
Simon Glass290a1802011-07-17 13:54:32 -0700534 def AddConfigList(self, config_list, use_int=False):
535 """Add a list of config items to the fdt.
536
537 Normally these values are written to the fdt as strings, but integers
538 are also supported, in which case the values will be converted to integers
539 (if necessary) before being stored.
540
541 Args:
542 config_list: List of (config, value) tuples to add to the fdt. For each
543 tuple:
544 config: The fdt node to write to will be /config/<config>.
545 value: An integer or string value to write.
546 use_int: True to only write integer values.
547
548 Raises:
549 CmdError: if a value is required to be converted to integer but can't be.
550 """
551 if config_list:
552 for config in config_list:
553 value = config[1]
554 if use_int:
555 try:
556 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700557 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700558 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700559 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700560 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800561 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700562 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800563 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700564
Simon Glass7c2d5572011-11-15 14:47:08 -0800565 def DecodeTextBase(self, data):
566 """Look at a U-Boot image and try to decode its TEXT_BASE.
567
568 This works because U-Boot has a header with the value 0x12345678
569 immediately followed by the TEXT_BASE value. We can therefore read this
570 from the image with some certainty. We check only the first 40 words
571 since the header should be within that region.
572
Simon Glass96b50302012-07-20 06:55:28 +0100573 Since upstream Tegra has moved to having a 16KB SPL region at the start,
574 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
575 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
576
Simon Glass7c2d5572011-11-15 14:47:08 -0800577 Args:
578 data: U-Boot binary data
579
580 Returns:
581 Text base (integer) or None if none was found
582 """
583 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100584 for start in (0, 0x4000):
585 for i in range(start, start + 160, 4):
586 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800587
Simon Glass96b50302012-07-20 06:55:28 +0100588 # TODO(sjg): This does not cope with a big-endian target
589 value = struct.unpack('<I', word)[0]
590 if found:
591 return value - start
592 if value == 0x12345678:
593 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800594
595 return None
596
597 def CalcTextBase(self, name, fdt, fname):
598 """Calculate the TEXT_BASE to use for U-Boot.
599
600 Normally this value is in the fdt, so we just read it from there. But as
601 a second check we look at the image itself in case this is different, and
602 switch to that if it is.
603
604 This allows us to flash any U-Boot even if its TEXT_BASE is different.
605 This is particularly useful with upstream U-Boot which uses a different
606 value (which we will move to).
607 """
608 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800609 # The value that comes back from fdt.GetInt is signed, which makes no
610 # sense for an address base. Force it to unsigned.
611 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800612 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100613 text_base_str = '%#x' % text_base if text_base else 'None'
614 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
615 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800616
617 # If they are different, issue a warning and switch over.
618 if text_base and text_base != fdt_text_base:
619 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
620 "fdt value of %x. Using %x" % (text_base, name,
621 fdt_text_base, text_base))
622 fdt_text_base = text_base
623 return fdt_text_base
624
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600625 def _CreateBootStub(self, uboot, base_fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700626 """Create a boot stub and a signed boot stub.
627
628 Args:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600629 uboot: Path to u-boot.bin (may be chroot-relative).
Simon Glass29b96ad2012-03-09 15:34:33 -0800630 base_fdt: Fdt object containing the flat device tree.
Simon Glass89b86b82011-07-17 23:49:49 -0700631
632 Returns:
633 Tuple containing:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600634 Full path to bootstub (uboot + fdt(-1)).
635 Full path to signed (uboot + fdt(flash pos) + bct).
Simon Glass89b86b82011-07-17 23:49:49 -0700636
637 Raises:
638 CmdError if a command fails.
639 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200640 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800641 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700642 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200643
644 # Make a copy of the fdt for the bootstub
645 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glass290a1802011-07-17 13:54:32 -0700646 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200647
Simon Glass89b86b82011-07-17 23:49:49 -0700648 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700649 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
650 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700651 self._tools.OutputSize('Combined binary', bootstub)
652
Simon Glasse13ee2c2011-07-28 08:12:28 +1200653 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700654 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700655 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200656 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200657
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600658 self._tools.OutputSize('Final bootstub', signed)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200659
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600660 return bootstub, signed
Simon Glass89b86b82011-07-17 23:49:49 -0700661
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600662 def _AddCbfsFiles(self, bootstub, cbfs_files):
663 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600664 for file in files:
665 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600666 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600667 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
668 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma'])
669
670 def _CreateCorebootStub(self, pack, coreboot):
671 """Create a coreboot boot stub and add pack properties.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700672
673 Args:
Aaron Durbina113f522016-01-05 09:09:55 -0600674 pack: a PackFirmware object describing the firmware image to build.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700675 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700676 """
677 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700678 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100679
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600680 pack.AddProperty('coreboot', bootstub)
681 pack.AddProperty('image', bootstub)
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700682
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600683 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600684 if self.cbfs_files:
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600685 self._AddCbfsFiles(bootstub, self.cbfs_files)
Simon Glass7e199222012-03-13 15:51:18 -0700686
Aaron Durbina113f522016-01-05 09:09:55 -0600687 # Create a coreboot copy to use as a scratch pad. Order matters. The
688 # cbfs_files were added prior to this action. That's so the RW CBFS
Patrick Georgi3a332672015-11-20 10:02:51 +0100689 # regions inherit the files from the RO CBFS region. Additionally,
690 # include the full FMAP within the file.
691 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600692 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100693 binary = self._tools.ReadFile(bootstub)
694 fmap_offset, fmap = pack.GetFmap()
695 if len(binary) < fmap_offset + len(fmap):
696 raise CmdError('FMAP will not fit')
697 # Splice in FMAP data.
698 binary = binary[:fmap_offset] + fmap + binary[fmap_offset + len(fmap):]
699 self._tools.WriteFile(cb_copy, binary)
700 # Publish where coreboot is with the FMAP data.
701 pack.AddProperty('cb_with_fmap', cb_copy)
Aaron Durbina113f522016-01-05 09:09:55 -0600702
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600703 # Add files to to RO CBFS if provided. This done here such that the
704 # copy above does not contain the RO CBFS files.
705 if self.rocbfs_files:
706 self._AddCbfsFiles(bootstub, self.rocbfs_files)
707
Aaron Durbina113f522016-01-05 09:09:55 -0600708
Simon Glass89b86b82011-07-17 23:49:49 -0700709 def _PackOutput(self, msg):
710 """Helper function to write output from PackFirmware (verbose level 2).
711
712 This is passed to PackFirmware for it to use to write output.
713
714 Args:
715 msg: Message to display.
716 """
717 self._out.Notice(msg)
718
Aaron Durbin80564452015-12-21 15:25:06 -0600719 def _FmapNameByPath(self, path):
720 """ Take list of names to form node path. Return FMAP name.
721
722 Obtain the FMAP name described by the node path.
723
724 Args:
725 path: list forming a node path.
726
727 Returns:
728 FMAP name of fdt node.
729
730 Raises:
731 CmdError if path not found.
732 """
733 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
734 return re.sub('-', '_', lbl).upper()
735
736 def _PrepareCbfsHash(self, pack, blob_name):
737 """Create blob in rw-{a,b}-boothash with 'cbfstool hashcbfs'.
738
739 When the blob name is defined as cbfshash/<section>/<subsection>, fill the
740 <section>_<subsection> area in the flash map with CBFS hash generated
741 using the 'cbfstool hashcbfs' command.
742
743 Args:
744 pack: a PackFirmware object describing the firmware image to build.
745 blob_name: a string, blob name describing what FMAP section this CBFS
746 copy is destined to
747 Raises:
748 CmdError if cbfs-files node has incorrect parameters.
749 BlobDeferral if the CBFS region is not populated yet or if the coreboot
750 image with fmap is not available yet.
751 """
752 cb_copy = pack.GetProperty('cb_with_fmap')
753 if cb_copy is None:
754 raise BlobDeferral("Waiting for '%s'" % cb_copy)
755
756 part_sections = blob_name.split('/')[1:]
757 fmap_dst = self._FmapNameByPath(part_sections)
758
759 # Example of FDT ndoes asking for CBFS hash:
760 # rw-b-boot {
761 # label = "fw-main-b";
762 # reg = <0x00700000 0x002dff80>;
763 # type = "blob cbfs/rw/b-boot";
764 # };
765 # rw-b-boothash {
766 # label = "fw-main-b-hash";
767 # reg = <0x009dff80 0x00000040>;
768 # type = "blob cbfshash/rw/b-boothash";
769 # cbfs-node = "cbfs/rw/b-boot";
770 # };
771 hash_node = self.fdt.GetFlashNode(*part_sections)
772 cbfs_blob_name = self.fdt.GetString(hash_node, 'cbfs-node')
773
774 if not pack.GetProperty(cbfs_blob_name):
775 raise BlobDeferral("Waiting for '%s'" % cbfs_blob_name)
776
777 cbfs_node_path = cbfs_blob_name.split('/')[1:]
778 fmap_src = self._FmapNameByPath(cbfs_node_path)
779
780 # Compute CBFS hash and place it in the corect spot.
781 self._tools.Run('cbfstool', [cb_copy, 'hashcbfs', '-r', fmap_dst,
782 '-R', fmap_src, '-A', 'sha256'])
783
784 # Base address and size of the desitnation partition
785 base, size = self.fdt.GetFlashPart(*part_sections)
786
787 # And extract the blob for the FW section
788 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
789 self._tools.WriteFile(rw_section,
790 self._tools.ReadFile(cb_copy)[base:base+size])
791
792 pack.AddProperty(blob_name, rw_section)
793
794
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800795 def _PrepareCbfs(self, pack, blob_name):
796 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
797
798 When the blob name is defined as cbfs#<section>#<subsection>, fill the
799 <section>_<subsection> area in the flash map with a CBFS copy, putting the
800 CBFS header of the copy at the base of the section.
801
802 If --coreboot-elf parameter was specified during cros_bumdle_firmware
803 invocation, add the parameter of this option as the payload to the new
804 CBFS instance.
805
806 Args:
807 pack: a PackFirmware object describing the firmware image to build.
808 blob_name: a string, blob name describing what FMAP section this CBFS
809 copy is destined to
810 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100811 CmdError if cbfs-files node has incorrect parameters.
Aaron Durbina113f522016-01-05 09:09:55 -0600812 BlobDeferral if coreboot image with fmap is not available yet.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800813 """
Patrick Georgi3a332672015-11-20 10:02:51 +0100814 cb_copy = pack.GetProperty('cb_with_fmap')
Aaron Durbina113f522016-01-05 09:09:55 -0600815 if cb_copy is None:
Patrick Georgi3a332672015-11-20 10:02:51 +0100816 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800817
818 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600819 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800820
821 # Base address and size of the desitnation partition
822 base, size = self.fdt.GetFlashPart(*part_sections)
823
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800824 # Add coreboot payload if so requested. Note that the some images use
825 # different payload for the rw sections, which is passed in as the value
826 # of the --uboot option in the command line.
827 if self.uboot_fname:
828 payload_fname = self.uboot_fname
829 elif self.coreboot_elf:
830 payload_fname = self.coreboot_elf
831 else:
832 payload_fname = None
833
834 if payload_fname:
835 self._tools.Run('cbfstool', [
836 cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100837 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800838
Patrick Georgi964fb542015-10-16 16:52:03 +0200839 if self.ecrw_fname:
840 self._tools.Run('cbfstool', [
841 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100842 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200843
844 if self.pdrw_fname:
845 self._tools.Run('cbfstool', [
846 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100847 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200848
Aaron Durbin880cf952016-01-27 14:11:38 -0600849 # Parse the file list to obtain the last entry. If its empty use its
850 # offset as the size of the CBFS to hash.
851 stdout = self._tools.Run('cbfstool',
852 [ cb_copy, 'print', '-k', '-r', fmap_dst ])
853 # Fields are tab separated in the following order.
854 # Name Offset Type Metadata Size Data Size Total Size
855 last_entry = stdout.strip().splitlines()[-1].split('\t')
856 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
857 size = int(last_entry[1], 16)
858
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800859 # And extract the blob for the FW section
860 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
861 self._tools.WriteFile(rw_section,
862 self._tools.ReadFile(cb_copy)[base:base+size])
863
864 pack.AddProperty(blob_name, rw_section)
865
866
Simon Glass439fe7a2012-03-09 16:19:34 -0800867 def _BuildBlob(self, pack, fdt, blob_type):
868 """Build the blob data for a particular blob type.
869
870 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700871 pack: a PackFirmware object describing the firmware image to build.
872 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800873 blob_type: The type of blob to create data for. Supported types are:
874 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
875 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700876
877 Raises:
878 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -0600879 BlobDeferral if a blob is waiting for a dependency.
Simon Glass439fe7a2012-03-09 16:19:34 -0800880 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700881 # stupid pylint insists that sha256 is not in hashlib.
882 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800883 if blob_type == 'coreboot':
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600884 self._CreateCorebootStub(pack, self.coreboot_fname)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700885 elif blob_type == 'legacy':
886 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800887 elif blob_type == 'signed':
Simon Glass942bedb2016-05-14 16:19:59 -0600888 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt, None)
Simon Glass439fe7a2012-03-09 16:19:34 -0800889 pack.AddProperty('bootstub', bootstub)
890 pack.AddProperty('signed', signed)
891 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700892 elif blob_type == 'exynos-bl1':
893 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700894
895 # TODO(sjg@chromium.org): Deprecate ecbin
896 elif blob_type in ['ecrw', 'ecbin']:
897 pack.AddProperty('ecrw', self.ecrw_fname)
898 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700899 elif blob_type == 'pdrw':
900 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800901 elif blob_type == 'ecrwhash':
902 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
903 ecrw = self._tools.ReadFile(self.ecrw_fname)
904 hasher = hashlib.sha256()
905 hasher.update(ecrw)
906 self._tools.WriteFile(ec_hash_file, hasher.digest())
907 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700908 elif blob_type == 'pdrwhash':
909 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
910 pdrw = self._tools.ReadFile(self.pdrw_fname)
911 hasher = hashlib.sha256()
912 hasher.update(pdrw)
913 self._tools.WriteFile(pd_hash_file, hasher.digest())
914 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700915 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700916 # crosbug.com/p/13143
917 # We cannot have an fmap in the EC image since there can be only one,
918 # which is the main fmap describing the whole image.
919 # Ultimately the EC will not have an fmap, since with software sync
920 # there is no flashrom involvement in updating the EC flash, and thus
921 # no need for the fmap.
922 # For now, mangle the fmap name to avoid problems.
923 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
924 data = self._tools.ReadFile(self.ecro_fname)
925 data = re.sub('__FMAP__', '__fMAP__', data)
926 self._tools.WriteFile(updated_ecro, data)
927 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600928 elif blob_type.startswith('exynos-bl2'):
929 # We need to configure this per node, so do it later
930 pass
Aaron Durbin80564452015-12-21 15:25:06 -0600931 elif blob_type.startswith('cbfshash'):
932 self._PrepareCbfsHash(pack, blob_type)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800933 elif blob_type.startswith('cbfs'):
934 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800935 elif pack.GetProperty(blob_type):
936 pass
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700937 elif blob_type == 'ifwi' or blob_type == 'sig2':
938 # Copy IFWI/CSE_SIGN(sig2) regions from coreboot copy and build a blob
939 # for the blob_type
940 cb_copy = pack.GetProperty('cb_with_fmap')
941 if cb_copy is None:
942 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
943 blob_start, blob_size = fdt.GetFlashPart('ro', blob_type)
944 blob_file = blob_type + '.bin'
945 blob_path = os.path.join(self._tools.outdir, blob_file)
946 data = self._tools.ReadFile(cb_copy)
947 self._tools.WriteFile(blob_path, data[blob_start:blob_start+blob_size])
948 pack.AddProperty(blob_type, blob_path)
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800949 elif blob_type in self.blobs:
950 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800951 else:
952 raise CmdError("Unknown blob type '%s' required in flash map" %
953 blob_type)
954
Aaron Durbin41c85b62015-12-17 17:40:29 -0600955 def _BuildBlobs(self, pack, fdt):
956 """Build the blob data for the list of blobs in the pack.
957
958 Args:
959 pack: a PackFirmware object describing the firmware image to build.
960 fdt: an fdt object including image layout information
961
962 Raises:
963 CmdError if a command fails.
964 BlobDeferral if dependencies cannot be met because of cycles.
965 """
966 blob_list = pack.GetBlobList()
967 self._out.Info('Building blobs %s\n' % blob_list)
968
969 complete = False
970 deferred_list = []
971
972 # Build blobs allowing for dependencies between blobs. While this is
973 # an potential O(n^2) operation, in practice most blobs aren't dependent
974 # and should resolve in a few passes.
975 while not complete:
976 orig = set(blob_list)
977 for blob_type in blob_list:
978 try:
979 self._BuildBlob(pack, fdt, blob_type)
980 except (BlobDeferral):
981 deferred_list.append(blob_type)
982 if not deferred_list:
983 complete = True
984 # If deferred is the same as the original no progress is being made.
985 if not orig - set(deferred_list):
986 raise BlobDeferral("Blob cyle '%s'" % orig)
987 # Process the deferred blobs
988 blob_list = deferred_list[:]
989 deferred_list = []
990
Simon Glass290a1802011-07-17 13:54:32 -0700991 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700992 """Create a full firmware image, along with various by-products.
993
994 This uses the provided u-boot.bin, fdt and bct to create a firmware
995 image containing all the required parts. If the GBB is not supplied
996 then this will just return a signed U-Boot as the image.
997
998 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700999 gbb: a string, full path to the GBB file, or empty if a GBB is not
1000 required.
1001 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +12001002
1003 Returns:
1004 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001005 """
Simon Glass02d124a2012-03-02 14:47:20 -08001006 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001007
Simon Glass439fe7a2012-03-09 16:19:34 -08001008 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -08001009 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001010 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
1011 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -06001012 if self._force_efs:
1013 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -06001014 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
1015 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001016
Simon Glass4f318912013-07-20 16:13:06 -06001017 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -08001018
1019 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001020 if self.uboot_fname:
1021 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001022 if self.skeleton_fname:
1023 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001024 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001025
Simon Glassde9c8072012-07-02 22:29:02 -07001026 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1027 if self.kernel_fname:
1028 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1029
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001030 if gbb:
1031 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -06001032
1033 # Build the blobs out.
1034 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -07001035
Simon Glass7306b902012-12-17 15:06:21 -08001036 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001037 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001038 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001039 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001040 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001041 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001042 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001043 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001044 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001045
Simon Glass0a047bc2013-07-19 15:44:43 -06001046 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001047 todo = pack.GetMissingBlobs()
1048 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001049 if blob.key.startswith('exynos-bl2'):
1050 bl2 = ExynosBl2(self._tools, self._out)
1051 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1052 self.exynos_bl2))
1053
Simon Glassc90cf582012-03-13 15:40:47 -07001054 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001055
1056 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001057 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001058
Simon Glass4c24f662013-07-19 15:53:02 -06001059 # Recalculate the Exynos BL2, since it may have a hash. The call to
1060 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1061 # need to recalculate the hash.
1062 for blob in todo:
1063 if blob.key.startswith('exynos-bl2'):
1064 bl2 = ExynosBl2(self._tools, self._out)
1065 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1066 self.exynos_bl2))
1067
Simon Glass6207efe2012-12-17 15:04:36 -08001068 # Make a copy of the fdt for the bootstub
1069 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001070 if self.uboot_fname:
1071 uboot_data = self._tools.ReadFile(self.uboot_fname)
1072 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1073 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001074
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001075 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1076 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001077
Simon Glassa10282a2013-01-08 17:06:41 -08001078 # Fix up the coreboot image here, since we can't do this until we have
1079 # a final device tree binary.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001080 if 'coreboot' in pack.GetBlobList():
Simon Glasscbc83552012-07-23 15:26:22 +01001081 bootstub = pack.GetProperty('coreboot')
1082 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001083 if self.coreboot_elf:
1084 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1085 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001086 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001087 text_base = 0x1110000
1088
1089 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1090 # 1110015: 66 bb 00 01 mov $0x100,%bx
1091 marker = struct.pack('<L', 0x0100bb66)
1092 pos = uboot_data.find(marker)
1093 if pos == -1 or pos > 0x100:
1094 raise ValueError('Cannot find U-Boot cold boot entry point')
1095 entry = text_base + pos
1096 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001097 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1098 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001099 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001100 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1101 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001102 data = self._tools.ReadFile(bootstub)
1103 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1104 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001105
Julius Werneraa1fe942014-11-21 17:16:11 -08001106 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1107 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1108 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001109
Simon Glass208ad952013-02-10 11:16:46 -08001110 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001111 image = os.path.join(self._tools.outdir, 'image.bin')
1112 pack.PackImage(self._tools.outdir, image)
1113 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001114
Simon Glass439fe7a2012-03-09 16:19:34 -08001115 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001116 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001117 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001118
Simon Glassdedda6f2013-02-09 13:44:14 -08001119 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001120 """Select an FDT to control the firmware bundling
1121
Simon Glassdedda6f2013-02-09 13:44:14 -08001122 We make a copy of this which will include any on-the-fly changes we want
1123 to make.
1124
Simon Glass290a1802011-07-17 13:54:32 -07001125 Args:
1126 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001127 use_defaults: True to use a default FDT name if available, and to add
1128 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001129
Simon Glassc0f3dc62011-08-09 14:19:05 -07001130 Returns:
1131 The Fdt object of the original fdt file, which we will not modify.
1132
Simon Glassdedda6f2013-02-09 13:44:14 -08001133 Raises:
1134 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1135 False).
Simon Glass290a1802011-07-17 13:54:32 -07001136 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001137 if use_defaults:
1138 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001139 if not fdt_fname:
1140 raise ValueError('Please provide an FDT filename')
1141 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001142 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001143
1144 # For upstream, select the correct architecture .dtsi manually.
1145 if self._board == 'link' or 'x86' in self._board:
1146 arch_dts = 'coreboot.dtsi'
1147 elif self._board == 'daisy':
1148 arch_dts = 'exynos5250.dtsi'
1149 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001150 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001151
1152 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001153 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1154
1155 # Get the flashmap so we know what to build. For board variants use the
1156 # main board name as the key (drop the _<variant> suffix).
1157 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1158
1159 if not fdt.GetProp('/flash', 'reg', ''):
1160 fdt.InsertNodes(default_flashmap)
1161
Simon Glass7df773b2013-08-25 18:02:29 -06001162 # Remember our board type.
1163 fdt.PutString('/chromeos-config', 'board', self._board)
1164
Simon Glasse53abbc2013-08-21 22:29:55 -06001165 self.fdt = fdt
1166 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001167
Simon Glassc90cf582012-03-13 15:40:47 -07001168 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001169 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001170
1171 - Checks options, tools, output directory, fdt.
1172 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001173
1174 Args:
Simon Glass56577572011-07-19 11:08:06 +12001175 hardware_id: Hardware ID to use for this board. If None, then the
1176 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001177 output_fname: Output filename for the image. If this is not None, then
1178 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001179 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001180
1181 Returns:
1182 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001183 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001184 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1185 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1186 else:
Simon Glass56577572011-07-19 11:08:06 +12001187 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001188
1189 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001190 image, pack = self._CreateImage(gbb, self.fdt)
1191 if show_map:
1192 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001193 if output_fname:
1194 shutil.copyfile(image, output_fname)
1195 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001196 return image, pack.props