blob: 83e4836e125f4dc87ea6cd8cafbfd0289bd8323a [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
Simon Glass439fe7a2012-03-09 16:19:34 -080028from tools import CmdError
Vadim Bendeburyb12e3352013-06-08 17:25:19 -070029from exynos import ExynosBl2
Simon Glass89b86b82011-07-17 23:49:49 -070030
Simon Glass4a887b12012-10-23 16:29:03 -070031# Build GBB flags.
32# (src/platform/vboot_reference/firmware/include/gbb_header.h)
33gbb_flag_properties = {
34 'dev-screen-short-delay': 0x00000001,
35 'load-option-roms': 0x00000002,
36 'enable-alternate-os': 0x00000004,
37 'force-dev-switch-on': 0x00000008,
38 'force-dev-boot-usb': 0x00000010,
39 'disable-fw-rollback-check': 0x00000020,
40 'enter-triggers-tonorm': 0x00000040,
41 'force-dev-boot-legacy': 0x00000080,
Shawn Nematbakhsh07c19882014-08-19 10:21:59 -070042 'faft-key-overide': 0x00000100,
43 'disable-ec-software-sync': 0x00000200,
44 'default-dev-boot-legacy': 0x00000400,
45 'disable-pd-software-sync': 0x00000800,
Furquan Shaikhd4eac3b2015-05-15 18:05:09 -070046 'force-dev-boot-fastboot-full-cap': 0x00002000,
Mary Ruthvena759c322015-11-16 08:23:26 -080047 'enable-serial': 0x00004000,
Simon Glass4a887b12012-10-23 16:29:03 -070048}
49
Simon Glass49b026b2013-04-26 16:38:42 -070050# Maps board name to Exynos product number
51type_to_model = {
52 'peach' : '5420',
53 'daisy' : '5250'
54}
55
Simon Glass5076a7f2012-10-23 16:31:54 -070056def ListGoogleBinaryBlockFlags():
57 """Print out a list of GBB flags."""
58 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
59 for name, value in gbb_flag_properties.iteritems():
60 print ' %-30s %02x' % (name, value)
61
Aaron Durbin41c85b62015-12-17 17:40:29 -060062class BlobDeferral(Exception):
63 """An error indicating deferal of blob generation."""
64 pass
65
Simon Glass89b86b82011-07-17 23:49:49 -070066class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070067 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070068
Simon Glass290a1802011-07-17 13:54:32 -070069 Sequence of events:
70 bundle = Bundle(tools.Tools(), cros_output.Output())
71 bundle.SetDirs(...)
72 bundle.SetFiles(...)
73 bundle.SetOptions(...)
74 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070075 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070076 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070077
Simon Glass290a1802011-07-17 13:54:32 -070078 Public properties:
79 fdt: The fdt object that we use for building our image. This wil be the
80 one specified by the user, except that we might add config options
81 to it. This is set up by SelectFdt() which must be called before
82 bundling starts.
83 uboot_fname: Full filename of the U-Boot binary we use.
84 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -070085 spl_source: Source device to load U-Boot from, in SPL:
86 straps: Select device according to CPU strap pins
87 spi: Boot from SPI
88 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -070089
90 Private attributes:
91 _small: True to create a 'small' signed U-Boot, False to produce a
92 full image. The small U-Boot is enough to boot but will not have
93 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -070094 """
Simon Glass89b86b82011-07-17 23:49:49 -070095
Simon Glass290a1802011-07-17 13:54:32 -070096 def __init__(self, tools, output):
97 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -070098
Simon Glass290a1802011-07-17 13:54:32 -070099 Args:
100 tools: A tools.Tools object to use for external tools.
101 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700102 """
Simon Glass290a1802011-07-17 13:54:32 -0700103 self._tools = tools
104 self._out = output
105
106 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500107 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700108 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700109 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600110 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700111 self._gbb_flags = None
112 self._keydir = None
113 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700114 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700115 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800116 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700117 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700118 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700119 self.ecro_fname = None # Filename of EC read-only file
120 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700121 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700122 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
123 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700124 self.fdt = None # Our Fdt object.
125 self.kernel_fname = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700126 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700127 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700128 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700129
130 def SetDirs(self, keydir):
131 """Set up directories required for Bundle.
132
133 Args:
134 keydir: Directory containing keys to use for signing firmware.
135 """
136 self._keydir = keydir
137
Simon Glass6dcc2f22011-07-28 15:26:49 +1200138 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800139 coreboot_elf=None,
Simon Glass942bedb2016-05-14 16:19:59 -0600140 seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700141 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600142 kernel=None, blobs=None, skip_bmpblk=False, cbfs_files=None,
143 rocbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700144 """Set up files required for Bundle.
145
146 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500147 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700148 uboot: The filename of the u-boot.bin image to use.
149 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800150 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800151 coreboot: The filename of the coreboot image to use (on x86).
152 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Vincent Palatinf7286772011-10-12 14:31:53 -0700153 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700154 exynos_bl1: The filename of the exynos BL1 file
155 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
156 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700157 ecrw: The filename of the EC (Embedded Controller) read-write file.
158 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700159 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700160 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800161 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800162 skip_bmpblk: True if no bmpblk is required
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600163 cbfs_files: Root directory of files to be stored in RO and RW CBFS
164 rocbfs_files: Root directory of files to be stored in RO CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700165 """
166 self._board = board
167 self.uboot_fname = uboot
168 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800169 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700170 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800171 self.coreboot_elf = coreboot_elf
Vincent Palatinf7286772011-10-12 14:31:53 -0700172 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700173 self.exynos_bl1 = exynos_bl1
174 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700175 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700176 self.ecrw_fname = ecrw
177 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700178 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700179 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800180 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800181 self.skip_bmpblk = skip_bmpblk
Daisuke Nojiri69662892015-09-25 15:24:04 -0700182 self.cbfs_files = cbfs_files
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600183 self.rocbfs_files = rocbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700184
Simon Glass00d027e2013-07-20 14:51:12 -0600185 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700186 """Set up options supported by Bundle.
187
188 Args:
189 small: Only create a signed U-Boot - don't produce the full packed
190 firmware image. This is useful for devs who want to replace just the
191 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700192 gbb_flags: Specification for string containing adjustments to make.
193 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600194 force_efs: Force firmware to use 'early firmware selection' feature,
195 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700196 """
197 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700198 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700199 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600200 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700201
Simon Glass22f39fb2013-02-09 13:44:14 -0800202 def _GetBuildRoot(self):
203 """Get the path to this board's 'firmware' directory.
204
205 Returns:
206 Path to firmware directory, with ## representing the path to the
207 chroot.
208 """
Simon Glass290a1802011-07-17 13:54:32 -0700209 if not self._board:
210 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800211 return os.path.join('##', 'build', self._board, 'firmware')
212
213 def _CheckFdtFilename(self, fname):
214 """Check provided FDT filename and return the correct name if needed.
215
216 Where the filename lacks a path, add a default path for this board.
217 Where no FDT filename is provided, select a default one for this board.
218
219 Args:
220 fname: Proposed FDT filename.
221
222 Returns:
223 Selected FDT filename, after validation.
224 """
225 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700226 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800227 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700228 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700229 base_name = re.sub('_', '-', self._board)
230
231 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700232 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700233 found_list = glob.glob(self._tools.Filename(wildcard))
234 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800235 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700236 else:
237 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700238 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700239
Simon Glass881964d2012-04-04 11:34:09 -0700240 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800241 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700242 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700243 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800244 return fname
245
246 def CheckOptions(self):
247 """Check provided options and select defaults."""
248 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700249
Simon Glass49b026b2013-04-26 16:38:42 -0700250 board_type = self._board.split('_')[0]
251 model = type_to_model.get(board_type)
252
Simon Glass290a1802011-07-17 13:54:32 -0700253 if not self.uboot_fname:
254 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
255 if not self.bct_fname:
256 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700257 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700258 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700259 if model:
260 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700261 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700262 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700263 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700264 if not self.coreboot_fname:
265 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
266 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700267 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700268 if not self.seabios_fname:
269 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700270 if not self.ecrw_fname:
271 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700272 if not self.pdrw_fname:
273 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700274 if not self.ecro_fname:
275 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700276
Simon Glass75759302012-03-15 20:26:53 -0700277 def GetFiles(self):
278 """Get a list of files that we know about.
279
280 This is the opposite of SetFiles except that we may have put in some
281 default names. It returns a dictionary containing the filename for
282 each of a number of pre-defined files.
283
284 Returns:
285 Dictionary, with one entry for each file.
286 """
287 file_list = {
288 'bct' : self.bct_fname,
289 'exynos-bl1' : self.exynos_bl1,
290 'exynos-bl2' : self.exynos_bl2,
291 }
292 return file_list
293
Simon Glass4a887b12012-10-23 16:29:03 -0700294 def DecodeGBBFlagsFromFdt(self):
295 """Get Google Binary Block flags from the FDT.
296
297 These should be in the chromeos-config node, like this:
298
299 chromeos-config {
300 gbb-flag-dev-screen-short-delay;
301 gbb-flag-force-dev-switch-on;
302 gbb-flag-force-dev-boot-usb;
303 gbb-flag-disable-fw-rollback-check;
304 };
305
306 Returns:
307 GBB flags value from FDT.
308 """
309 chromeos_config = self.fdt.GetProps("/chromeos-config")
310 gbb_flags = 0
311 for name in chromeos_config:
312 if name.startswith('gbb-flag-'):
313 flag_value = gbb_flag_properties.get(name[9:])
314 if flag_value:
315 gbb_flags |= flag_value
316 self._out.Notice("FDT: Enabling %s." % name)
317 else:
318 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
319 return gbb_flags
320
Simon Glass157c0662012-10-23 13:52:42 -0700321 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
322 """Decode ajustments to the provided GBB flags.
323
324 We support three options:
325
326 hex value: c2
327 defined value: force-dev-boot-usb,load-option-roms
328 adjust default value: -load-option-roms,+force-dev-boot-usb
329
330 The last option starts from the passed-in GBB flags and adds or removes
331 flags.
332
333 Args:
334 gbb_flags: Base (default) FDT flags.
335 adjustments: String containing adjustments to make.
336
337 Returns:
338 Updated FDT flags.
339 """
340 use_base_value = True
341 if adjustments:
342 try:
343 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700344 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700345 pass
346 for flag in adjustments.split(','):
347 oper = None
348 if flag[0] in ['-', '+']:
349 oper = flag[0]
350 flag = flag[1:]
351 value = gbb_flag_properties.get(flag)
352 if not value:
353 raise ValueError("Invalid GBB flag '%s'" % flag)
354 if oper == '+':
355 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800356 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700357 elif oper == '-':
358 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800359 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700360 else:
361 if use_base_value:
362 gbb_flags = 0
363 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800364 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700365 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800366 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700367
368 return gbb_flags
369
Simon Glass56577572011-07-19 11:08:06 +1200370 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700371 """Create a GBB for the image.
372
Simon Glass56577572011-07-19 11:08:06 +1200373 Args:
374 hardware_id: Hardware ID to use for this board. If None, then the
375 default from the Fdt will be used
376
Simon Glass89b86b82011-07-17 23:49:49 -0700377 Returns:
378 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700379 """
Simon Glass56577572011-07-19 11:08:06 +1200380 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800381 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700382 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700383 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700384
Simon Glass4a887b12012-10-23 16:29:03 -0700385 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800386
Simon Glass157c0662012-10-23 13:52:42 -0700387 # Allow command line to override flags
388 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
389
Simon Glass4a887b12012-10-23 16:29:03 -0700390 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700391 self._out.Progress('Creating GBB')
Daisuke Nojiri10b193f2016-01-15 17:53:14 -0800392 if self.skip_bmpblk:
393 bmpfv_size = 0
394 else:
395 bmpfv_size = gbb_size - 0x2180
396 sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700397 sizes = ['%#x' % size for size in sizes]
398 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700399 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800400
401 gbb_set_command = ['-s',
402 '--hwid=%s' % hardware_id,
403 '--rootkey=%s/root_key.vbpubk' % keydir,
404 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
405 '--flags=%d' % gbb_flags,
406 gbb]
407 if not self.skip_bmpblk:
408 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
409 self.bmpblk_fname),]
410
Simon Glass290a1802011-07-17 13:54:32 -0700411 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800412 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700413 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700414
Simon Glasse13ee2c2011-07-28 08:12:28 +1200415 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700416 """Sign an image so that the Tegra SOC will boot it.
417
418 Args:
419 bct: BCT file to use.
420 bootstub: Boot stub (U-Boot + fdt) file to sign.
421 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700422
423 Returns:
424 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700425 """
426 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200427 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700428 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200429 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700430 fd = open(config, 'w')
431 fd.write('Version = 1;\n')
432 fd.write('Redundancy = 1;\n')
433 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700434
435 # TODO(dianders): Right now, we don't have enough space in our flash map
436 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
437 # sure what this does for reliability, but at least things will fit...
438 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
439 if is_nand:
440 fd.write('Bctcopy = 1;\n')
441
Simon Glass89b86b82011-07-17 23:49:49 -0700442 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
443 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700444
Simon Glass89b86b82011-07-17 23:49:49 -0700445 fd.close()
446
447 self._tools.Run('cbootimage', [config, signed])
448 self._tools.OutputSize('BCT', bct)
449 self._tools.OutputSize('Signed image', signed)
450 return signed
451
Doug Anderson86ce5f42011-07-27 10:40:18 -0700452 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700453 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700454
455 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700456 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700457 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700458 """
Simon Glass468d8752012-09-19 16:36:19 -0700459 if bootcmd is not None:
460 if bootcmd == 'none':
461 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800462 self.fdt.PutString('/config', 'bootcmd', bootcmd)
463 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700464 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700465
Simon Glassa4934b72012-05-09 13:35:02 -0700466 def SetNodeEnabled(self, node_name, enabled):
467 """Set whether an node is enabled or disabled.
468
469 This simply sets the 'status' property of a node to "ok", or "disabled".
470
471 The node should either be a full path to the node (like '/uart@10200000')
472 or an alias property.
473
474 Aliases are supported like this:
475
476 aliases {
477 console = "/uart@10200000";
478 };
479
480 pointing to a node:
481
482 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700483 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700484 };
485
486 In this case, this function takes the name of the alias ('console' in
487 this case) and updates the status of the node that is pointed to, to
488 either ok or disabled. If the alias does not exist, a warning is
489 displayed.
490
491 Args:
492 node_name: Name of node (e.g. '/uart@10200000') or alias alias
493 (e.g. 'console') to adjust
494 enabled: True to enable, False to disable
495 """
496 # Look up the alias if this is an alias reference
497 if not node_name.startswith('/'):
498 lookup = self.fdt.GetString('/aliases', node_name, '')
499 if not lookup:
500 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
501 return
502 node_name = lookup
503 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700504 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700505 else:
506 status = 'disabled'
507 self.fdt.PutString(node_name, 'status', status)
508
509 def AddEnableList(self, enable_list):
510 """Process a list of nodes to enable/disable.
511
512 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700513 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700514 tuple:
515 node: The fdt node to write to will be <node> or pointed to by
516 /aliases/<node>. We can tell which
517 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700518
Vadim Bendebury507c0012013-06-09 12:49:25 -0700519 Raises:
520 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700521 """
522 if enable_list:
523 for node_name, enabled in enable_list:
524 try:
525 enabled = int(enabled)
526 if enabled not in (0, 1):
527 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700528 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700529 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700530 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700531 self.SetNodeEnabled(node_name, enabled)
532
Simon Glass290a1802011-07-17 13:54:32 -0700533 def AddConfigList(self, config_list, use_int=False):
534 """Add a list of config items to the fdt.
535
536 Normally these values are written to the fdt as strings, but integers
537 are also supported, in which case the values will be converted to integers
538 (if necessary) before being stored.
539
540 Args:
541 config_list: List of (config, value) tuples to add to the fdt. For each
542 tuple:
543 config: The fdt node to write to will be /config/<config>.
544 value: An integer or string value to write.
545 use_int: True to only write integer values.
546
547 Raises:
548 CmdError: if a value is required to be converted to integer but can't be.
549 """
550 if config_list:
551 for config in config_list:
552 value = config[1]
553 if use_int:
554 try:
555 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700556 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700557 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700558 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700559 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800560 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700561 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800562 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700563
Simon Glass7c2d5572011-11-15 14:47:08 -0800564 def DecodeTextBase(self, data):
565 """Look at a U-Boot image and try to decode its TEXT_BASE.
566
567 This works because U-Boot has a header with the value 0x12345678
568 immediately followed by the TEXT_BASE value. We can therefore read this
569 from the image with some certainty. We check only the first 40 words
570 since the header should be within that region.
571
Simon Glass96b50302012-07-20 06:55:28 +0100572 Since upstream Tegra has moved to having a 16KB SPL region at the start,
573 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
574 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
575
Simon Glass7c2d5572011-11-15 14:47:08 -0800576 Args:
577 data: U-Boot binary data
578
579 Returns:
580 Text base (integer) or None if none was found
581 """
582 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100583 for start in (0, 0x4000):
584 for i in range(start, start + 160, 4):
585 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800586
Simon Glass96b50302012-07-20 06:55:28 +0100587 # TODO(sjg): This does not cope with a big-endian target
588 value = struct.unpack('<I', word)[0]
589 if found:
590 return value - start
591 if value == 0x12345678:
592 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800593
594 return None
595
596 def CalcTextBase(self, name, fdt, fname):
597 """Calculate the TEXT_BASE to use for U-Boot.
598
599 Normally this value is in the fdt, so we just read it from there. But as
600 a second check we look at the image itself in case this is different, and
601 switch to that if it is.
602
603 This allows us to flash any U-Boot even if its TEXT_BASE is different.
604 This is particularly useful with upstream U-Boot which uses a different
605 value (which we will move to).
606 """
607 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800608 # The value that comes back from fdt.GetInt is signed, which makes no
609 # sense for an address base. Force it to unsigned.
610 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800611 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100612 text_base_str = '%#x' % text_base if text_base else 'None'
613 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
614 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800615
616 # If they are different, issue a warning and switch over.
617 if text_base and text_base != fdt_text_base:
618 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
619 "fdt value of %x. Using %x" % (text_base, name,
620 fdt_text_base, text_base))
621 fdt_text_base = text_base
622 return fdt_text_base
623
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600624 def _CreateBootStub(self, uboot, base_fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700625 """Create a boot stub and a signed boot stub.
626
627 Args:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600628 uboot: Path to u-boot.bin (may be chroot-relative).
Simon Glass29b96ad2012-03-09 15:34:33 -0800629 base_fdt: Fdt object containing the flat device tree.
Simon Glass89b86b82011-07-17 23:49:49 -0700630
631 Returns:
632 Tuple containing:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600633 Full path to bootstub (uboot + fdt(-1)).
634 Full path to signed (uboot + fdt(flash pos) + bct).
Simon Glass89b86b82011-07-17 23:49:49 -0700635
636 Raises:
637 CmdError if a command fails.
638 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200639 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800640 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700641 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200642
643 # Make a copy of the fdt for the bootstub
644 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glass290a1802011-07-17 13:54:32 -0700645 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200646
Simon Glass89b86b82011-07-17 23:49:49 -0700647 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700648 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
649 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700650 self._tools.OutputSize('Combined binary', bootstub)
651
Simon Glasse13ee2c2011-07-28 08:12:28 +1200652 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700653 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700654 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200655 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200656
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600657 self._tools.OutputSize('Final bootstub', signed)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200658
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600659 return bootstub, signed
Simon Glass89b86b82011-07-17 23:49:49 -0700660
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600661 def _AddCbfsFiles(self, bootstub, cbfs_files):
662 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600663 for file in files:
664 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600665 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600666 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
667 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma'])
668
669 def _CreateCorebootStub(self, pack, coreboot):
670 """Create a coreboot boot stub and add pack properties.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700671
672 Args:
Aaron Durbina113f522016-01-05 09:09:55 -0600673 pack: a PackFirmware object describing the firmware image to build.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700674 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700675 """
676 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700677 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100678
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600679 pack.AddProperty('coreboot', bootstub)
680 pack.AddProperty('image', bootstub)
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700681
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600682 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600683 if self.cbfs_files:
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600684 self._AddCbfsFiles(bootstub, self.cbfs_files)
Simon Glass7e199222012-03-13 15:51:18 -0700685
Aaron Durbina113f522016-01-05 09:09:55 -0600686 # Create a coreboot copy to use as a scratch pad. Order matters. The
687 # cbfs_files were added prior to this action. That's so the RW CBFS
Patrick Georgi3a332672015-11-20 10:02:51 +0100688 # regions inherit the files from the RO CBFS region. Additionally,
689 # include the full FMAP within the file.
690 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600691 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100692 binary = self._tools.ReadFile(bootstub)
693 fmap_offset, fmap = pack.GetFmap()
694 if len(binary) < fmap_offset + len(fmap):
695 raise CmdError('FMAP will not fit')
696 # Splice in FMAP data.
697 binary = binary[:fmap_offset] + fmap + binary[fmap_offset + len(fmap):]
698 self._tools.WriteFile(cb_copy, binary)
699 # Publish where coreboot is with the FMAP data.
700 pack.AddProperty('cb_with_fmap', cb_copy)
Aaron Durbina113f522016-01-05 09:09:55 -0600701
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600702 # Add files to to RO CBFS if provided. This done here such that the
703 # copy above does not contain the RO CBFS files.
704 if self.rocbfs_files:
705 self._AddCbfsFiles(bootstub, self.rocbfs_files)
706
Aaron Durbina113f522016-01-05 09:09:55 -0600707
Simon Glass89b86b82011-07-17 23:49:49 -0700708 def _PackOutput(self, msg):
709 """Helper function to write output from PackFirmware (verbose level 2).
710
711 This is passed to PackFirmware for it to use to write output.
712
713 Args:
714 msg: Message to display.
715 """
716 self._out.Notice(msg)
717
Aaron Durbin80564452015-12-21 15:25:06 -0600718 def _FmapNameByPath(self, path):
719 """ Take list of names to form node path. Return FMAP name.
720
721 Obtain the FMAP name described by the node path.
722
723 Args:
724 path: list forming a node path.
725
726 Returns:
727 FMAP name of fdt node.
728
729 Raises:
730 CmdError if path not found.
731 """
732 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
733 return re.sub('-', '_', lbl).upper()
734
735 def _PrepareCbfsHash(self, pack, blob_name):
736 """Create blob in rw-{a,b}-boothash with 'cbfstool hashcbfs'.
737
738 When the blob name is defined as cbfshash/<section>/<subsection>, fill the
739 <section>_<subsection> area in the flash map with CBFS hash generated
740 using the 'cbfstool hashcbfs' command.
741
742 Args:
743 pack: a PackFirmware object describing the firmware image to build.
744 blob_name: a string, blob name describing what FMAP section this CBFS
745 copy is destined to
746 Raises:
747 CmdError if cbfs-files node has incorrect parameters.
748 BlobDeferral if the CBFS region is not populated yet or if the coreboot
749 image with fmap is not available yet.
750 """
751 cb_copy = pack.GetProperty('cb_with_fmap')
752 if cb_copy is None:
753 raise BlobDeferral("Waiting for '%s'" % cb_copy)
754
755 part_sections = blob_name.split('/')[1:]
756 fmap_dst = self._FmapNameByPath(part_sections)
757
758 # Example of FDT ndoes asking for CBFS hash:
759 # rw-b-boot {
760 # label = "fw-main-b";
761 # reg = <0x00700000 0x002dff80>;
762 # type = "blob cbfs/rw/b-boot";
763 # };
764 # rw-b-boothash {
765 # label = "fw-main-b-hash";
766 # reg = <0x009dff80 0x00000040>;
767 # type = "blob cbfshash/rw/b-boothash";
768 # cbfs-node = "cbfs/rw/b-boot";
769 # };
770 hash_node = self.fdt.GetFlashNode(*part_sections)
771 cbfs_blob_name = self.fdt.GetString(hash_node, 'cbfs-node')
772
773 if not pack.GetProperty(cbfs_blob_name):
774 raise BlobDeferral("Waiting for '%s'" % cbfs_blob_name)
775
776 cbfs_node_path = cbfs_blob_name.split('/')[1:]
777 fmap_src = self._FmapNameByPath(cbfs_node_path)
778
779 # Compute CBFS hash and place it in the corect spot.
780 self._tools.Run('cbfstool', [cb_copy, 'hashcbfs', '-r', fmap_dst,
781 '-R', fmap_src, '-A', 'sha256'])
782
783 # Base address and size of the desitnation partition
784 base, size = self.fdt.GetFlashPart(*part_sections)
785
786 # And extract the blob for the FW section
787 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
788 self._tools.WriteFile(rw_section,
789 self._tools.ReadFile(cb_copy)[base:base+size])
790
791 pack.AddProperty(blob_name, rw_section)
792
793
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800794 def _PrepareCbfs(self, pack, blob_name):
795 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
796
797 When the blob name is defined as cbfs#<section>#<subsection>, fill the
798 <section>_<subsection> area in the flash map with a CBFS copy, putting the
799 CBFS header of the copy at the base of the section.
800
801 If --coreboot-elf parameter was specified during cros_bumdle_firmware
802 invocation, add the parameter of this option as the payload to the new
803 CBFS instance.
804
805 Args:
806 pack: a PackFirmware object describing the firmware image to build.
807 blob_name: a string, blob name describing what FMAP section this CBFS
808 copy is destined to
809 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100810 CmdError if cbfs-files node has incorrect parameters.
Aaron Durbina113f522016-01-05 09:09:55 -0600811 BlobDeferral if coreboot image with fmap is not available yet.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800812 """
Patrick Georgi3a332672015-11-20 10:02:51 +0100813 cb_copy = pack.GetProperty('cb_with_fmap')
Aaron Durbina113f522016-01-05 09:09:55 -0600814 if cb_copy is None:
Patrick Georgi3a332672015-11-20 10:02:51 +0100815 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800816
817 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600818 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800819
820 # Base address and size of the desitnation partition
821 base, size = self.fdt.GetFlashPart(*part_sections)
822
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800823 # Add coreboot payload if so requested. Note that the some images use
824 # different payload for the rw sections, which is passed in as the value
825 # of the --uboot option in the command line.
826 if self.uboot_fname:
827 payload_fname = self.uboot_fname
828 elif self.coreboot_elf:
829 payload_fname = self.coreboot_elf
830 else:
831 payload_fname = None
832
833 if payload_fname:
834 self._tools.Run('cbfstool', [
835 cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100836 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800837
Patrick Georgi964fb542015-10-16 16:52:03 +0200838 if self.ecrw_fname:
839 self._tools.Run('cbfstool', [
840 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100841 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200842
843 if self.pdrw_fname:
844 self._tools.Run('cbfstool', [
845 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100846 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200847
Aaron Durbin880cf952016-01-27 14:11:38 -0600848 # Parse the file list to obtain the last entry. If its empty use its
849 # offset as the size of the CBFS to hash.
850 stdout = self._tools.Run('cbfstool',
851 [ cb_copy, 'print', '-k', '-r', fmap_dst ])
852 # Fields are tab separated in the following order.
853 # Name Offset Type Metadata Size Data Size Total Size
854 last_entry = stdout.strip().splitlines()[-1].split('\t')
855 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
856 size = int(last_entry[1], 16)
857
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800858 # And extract the blob for the FW section
859 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
860 self._tools.WriteFile(rw_section,
861 self._tools.ReadFile(cb_copy)[base:base+size])
862
863 pack.AddProperty(blob_name, rw_section)
864
865
Simon Glass439fe7a2012-03-09 16:19:34 -0800866 def _BuildBlob(self, pack, fdt, blob_type):
867 """Build the blob data for a particular blob type.
868
869 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700870 pack: a PackFirmware object describing the firmware image to build.
871 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800872 blob_type: The type of blob to create data for. Supported types are:
873 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
874 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700875
876 Raises:
877 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -0600878 BlobDeferral if a blob is waiting for a dependency.
Simon Glass439fe7a2012-03-09 16:19:34 -0800879 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700880 # stupid pylint insists that sha256 is not in hashlib.
881 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800882 if blob_type == 'coreboot':
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600883 self._CreateCorebootStub(pack, self.coreboot_fname)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700884 elif blob_type == 'legacy':
885 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800886 elif blob_type == 'signed':
Simon Glass942bedb2016-05-14 16:19:59 -0600887 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt, None)
Simon Glass439fe7a2012-03-09 16:19:34 -0800888 pack.AddProperty('bootstub', bootstub)
889 pack.AddProperty('signed', signed)
890 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700891 elif blob_type == 'exynos-bl1':
892 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700893
894 # TODO(sjg@chromium.org): Deprecate ecbin
895 elif blob_type in ['ecrw', 'ecbin']:
896 pack.AddProperty('ecrw', self.ecrw_fname)
897 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700898 elif blob_type == 'pdrw':
899 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800900 elif blob_type == 'ecrwhash':
901 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
902 ecrw = self._tools.ReadFile(self.ecrw_fname)
903 hasher = hashlib.sha256()
904 hasher.update(ecrw)
905 self._tools.WriteFile(ec_hash_file, hasher.digest())
906 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700907 elif blob_type == 'pdrwhash':
908 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
909 pdrw = self._tools.ReadFile(self.pdrw_fname)
910 hasher = hashlib.sha256()
911 hasher.update(pdrw)
912 self._tools.WriteFile(pd_hash_file, hasher.digest())
913 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700914 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700915 # crosbug.com/p/13143
916 # We cannot have an fmap in the EC image since there can be only one,
917 # which is the main fmap describing the whole image.
918 # Ultimately the EC will not have an fmap, since with software sync
919 # there is no flashrom involvement in updating the EC flash, and thus
920 # no need for the fmap.
921 # For now, mangle the fmap name to avoid problems.
922 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
923 data = self._tools.ReadFile(self.ecro_fname)
924 data = re.sub('__FMAP__', '__fMAP__', data)
925 self._tools.WriteFile(updated_ecro, data)
926 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600927 elif blob_type.startswith('exynos-bl2'):
928 # We need to configure this per node, so do it later
929 pass
Aaron Durbin80564452015-12-21 15:25:06 -0600930 elif blob_type.startswith('cbfshash'):
931 self._PrepareCbfsHash(pack, blob_type)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800932 elif blob_type.startswith('cbfs'):
933 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800934 elif pack.GetProperty(blob_type):
935 pass
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700936 elif blob_type == 'ifwi' or blob_type == 'sig2':
937 # Copy IFWI/CSE_SIGN(sig2) regions from coreboot copy and build a blob
938 # for the blob_type
939 cb_copy = pack.GetProperty('cb_with_fmap')
940 if cb_copy is None:
941 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
942 blob_start, blob_size = fdt.GetFlashPart('ro', blob_type)
943 blob_file = blob_type + '.bin'
944 blob_path = os.path.join(self._tools.outdir, blob_file)
945 data = self._tools.ReadFile(cb_copy)
946 self._tools.WriteFile(blob_path, data[blob_start:blob_start+blob_size])
947 pack.AddProperty(blob_type, blob_path)
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800948 elif blob_type in self.blobs:
949 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800950 else:
951 raise CmdError("Unknown blob type '%s' required in flash map" %
952 blob_type)
953
Aaron Durbin41c85b62015-12-17 17:40:29 -0600954 def _BuildBlobs(self, pack, fdt):
955 """Build the blob data for the list of blobs in the pack.
956
957 Args:
958 pack: a PackFirmware object describing the firmware image to build.
959 fdt: an fdt object including image layout information
960
961 Raises:
962 CmdError if a command fails.
963 BlobDeferral if dependencies cannot be met because of cycles.
964 """
965 blob_list = pack.GetBlobList()
966 self._out.Info('Building blobs %s\n' % blob_list)
967
968 complete = False
969 deferred_list = []
970
971 # Build blobs allowing for dependencies between blobs. While this is
972 # an potential O(n^2) operation, in practice most blobs aren't dependent
973 # and should resolve in a few passes.
974 while not complete:
975 orig = set(blob_list)
976 for blob_type in blob_list:
977 try:
978 self._BuildBlob(pack, fdt, blob_type)
979 except (BlobDeferral):
980 deferred_list.append(blob_type)
981 if not deferred_list:
982 complete = True
983 # If deferred is the same as the original no progress is being made.
984 if not orig - set(deferred_list):
985 raise BlobDeferral("Blob cyle '%s'" % orig)
986 # Process the deferred blobs
987 blob_list = deferred_list[:]
988 deferred_list = []
989
Simon Glass290a1802011-07-17 13:54:32 -0700990 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700991 """Create a full firmware image, along with various by-products.
992
993 This uses the provided u-boot.bin, fdt and bct to create a firmware
994 image containing all the required parts. If the GBB is not supplied
995 then this will just return a signed U-Boot as the image.
996
997 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700998 gbb: a string, full path to the GBB file, or empty if a GBB is not
999 required.
1000 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +12001001
1002 Returns:
1003 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001004 """
Simon Glass02d124a2012-03-02 14:47:20 -08001005 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001006
Simon Glass439fe7a2012-03-09 16:19:34 -08001007 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -08001008 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001009 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
1010 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -06001011 if self._force_efs:
1012 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -06001013 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
1014 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001015
Simon Glass4f318912013-07-20 16:13:06 -06001016 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -08001017
1018 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001019 if self.uboot_fname:
1020 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001021 if self.skeleton_fname:
1022 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001023 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001024
Simon Glassde9c8072012-07-02 22:29:02 -07001025 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1026 if self.kernel_fname:
1027 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1028
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001029 if gbb:
1030 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -06001031
1032 # Build the blobs out.
1033 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -07001034
Simon Glass7306b902012-12-17 15:06:21 -08001035 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001036 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001037 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001038 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001039 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001040 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001041 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001042 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001043 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001044
Simon Glass0a047bc2013-07-19 15:44:43 -06001045 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001046 todo = pack.GetMissingBlobs()
1047 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001048 if blob.key.startswith('exynos-bl2'):
1049 bl2 = ExynosBl2(self._tools, self._out)
1050 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1051 self.exynos_bl2))
1052
Simon Glassc90cf582012-03-13 15:40:47 -07001053 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001054
1055 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001056 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001057
Simon Glass4c24f662013-07-19 15:53:02 -06001058 # Recalculate the Exynos BL2, since it may have a hash. The call to
1059 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1060 # need to recalculate the hash.
1061 for blob in todo:
1062 if blob.key.startswith('exynos-bl2'):
1063 bl2 = ExynosBl2(self._tools, self._out)
1064 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1065 self.exynos_bl2))
1066
Simon Glass6207efe2012-12-17 15:04:36 -08001067 # Make a copy of the fdt for the bootstub
1068 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001069 if self.uboot_fname:
1070 uboot_data = self._tools.ReadFile(self.uboot_fname)
1071 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1072 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001073
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001074 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1075 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001076
Simon Glassa10282a2013-01-08 17:06:41 -08001077 # Fix up the coreboot image here, since we can't do this until we have
1078 # a final device tree binary.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001079 if 'coreboot' in pack.GetBlobList():
Simon Glasscbc83552012-07-23 15:26:22 +01001080 bootstub = pack.GetProperty('coreboot')
1081 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001082 if self.coreboot_elf:
1083 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1084 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001085 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001086 text_base = 0x1110000
1087
1088 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1089 # 1110015: 66 bb 00 01 mov $0x100,%bx
1090 marker = struct.pack('<L', 0x0100bb66)
1091 pos = uboot_data.find(marker)
1092 if pos == -1 or pos > 0x100:
1093 raise ValueError('Cannot find U-Boot cold boot entry point')
1094 entry = text_base + pos
1095 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001096 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1097 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001098 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001099 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1100 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001101 data = self._tools.ReadFile(bootstub)
1102 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1103 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001104
Julius Werneraa1fe942014-11-21 17:16:11 -08001105 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1106 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1107 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001108
Simon Glass208ad952013-02-10 11:16:46 -08001109 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001110 image = os.path.join(self._tools.outdir, 'image.bin')
1111 pack.PackImage(self._tools.outdir, image)
1112 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001113
Simon Glass439fe7a2012-03-09 16:19:34 -08001114 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001115 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001116 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001117
Simon Glassdedda6f2013-02-09 13:44:14 -08001118 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001119 """Select an FDT to control the firmware bundling
1120
Simon Glassdedda6f2013-02-09 13:44:14 -08001121 We make a copy of this which will include any on-the-fly changes we want
1122 to make.
1123
Simon Glass290a1802011-07-17 13:54:32 -07001124 Args:
1125 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001126 use_defaults: True to use a default FDT name if available, and to add
1127 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001128
Simon Glassc0f3dc62011-08-09 14:19:05 -07001129 Returns:
1130 The Fdt object of the original fdt file, which we will not modify.
1131
Simon Glassdedda6f2013-02-09 13:44:14 -08001132 Raises:
1133 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1134 False).
Simon Glass290a1802011-07-17 13:54:32 -07001135 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001136 if use_defaults:
1137 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001138 if not fdt_fname:
1139 raise ValueError('Please provide an FDT filename')
1140 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001141 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001142
1143 # For upstream, select the correct architecture .dtsi manually.
1144 if self._board == 'link' or 'x86' in self._board:
1145 arch_dts = 'coreboot.dtsi'
1146 elif self._board == 'daisy':
1147 arch_dts = 'exynos5250.dtsi'
1148 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001149 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001150
1151 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001152 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1153
Simon Glass7df773b2013-08-25 18:02:29 -06001154 # Remember our board type.
1155 fdt.PutString('/chromeos-config', 'board', self._board)
1156
Simon Glasse53abbc2013-08-21 22:29:55 -06001157 self.fdt = fdt
1158 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001159
Simon Glassc90cf582012-03-13 15:40:47 -07001160 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001161 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001162
1163 - Checks options, tools, output directory, fdt.
1164 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001165
1166 Args:
Simon Glass56577572011-07-19 11:08:06 +12001167 hardware_id: Hardware ID to use for this board. If None, then the
1168 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001169 output_fname: Output filename for the image. If this is not None, then
1170 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001171 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001172
1173 Returns:
1174 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001175 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001176 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1177 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1178 else:
Simon Glass56577572011-07-19 11:08:06 +12001179 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001180
1181 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001182 image, pack = self._CreateImage(gbb, self.fdt)
1183 if show_map:
1184 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001185 if output_fname:
1186 shutil.copyfile(image, output_fname)
1187 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001188 return image, pack.props