blob: 224bae60c96b7b143c37b63b485999da18b67173 [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
Simon Glass89b86b82011-07-17 23:49:49 -070020import os
21import re
22
Simon Glass89b86b82011-07-17 23:49:49 -070023from fdt import Fdt
24from pack_firmware import PackFirmware
25import shutil
Simon Glass7c2d5572011-11-15 14:47:08 -080026import struct
Patrick Georgicebb5a22016-08-15 19:07:02 +020027import fmap
Simon Glass439fe7a2012-03-09 16:19:34 -080028from tools import CmdError
Simon Glass89b86b82011-07-17 23:49:49 -070029
Simon Glass4a887b12012-10-23 16:29:03 -070030# Build GBB flags.
31# (src/platform/vboot_reference/firmware/include/gbb_header.h)
32gbb_flag_properties = {
33 'dev-screen-short-delay': 0x00000001,
34 'load-option-roms': 0x00000002,
35 'enable-alternate-os': 0x00000004,
36 'force-dev-switch-on': 0x00000008,
37 'force-dev-boot-usb': 0x00000010,
38 'disable-fw-rollback-check': 0x00000020,
39 'enter-triggers-tonorm': 0x00000040,
40 'force-dev-boot-legacy': 0x00000080,
Shawn Nematbakhsh07c19882014-08-19 10:21:59 -070041 'faft-key-overide': 0x00000100,
42 'disable-ec-software-sync': 0x00000200,
43 'default-dev-boot-legacy': 0x00000400,
44 'disable-pd-software-sync': 0x00000800,
Furquan Shaikhd4eac3b2015-05-15 18:05:09 -070045 'force-dev-boot-fastboot-full-cap': 0x00002000,
Mary Ruthvena759c322015-11-16 08:23:26 -080046 'enable-serial': 0x00004000,
Simon Glass4a887b12012-10-23 16:29:03 -070047}
48
Simon Glass49b026b2013-04-26 16:38:42 -070049# Maps board name to Exynos product number
50type_to_model = {
51 'peach' : '5420',
52 'daisy' : '5250'
53}
54
Simon Glass5076a7f2012-10-23 16:31:54 -070055def ListGoogleBinaryBlockFlags():
56 """Print out a list of GBB flags."""
57 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
58 for name, value in gbb_flag_properties.iteritems():
59 print ' %-30s %02x' % (name, value)
60
Simon Glass89b86b82011-07-17 23:49:49 -070061class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070062 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070063
Simon Glass290a1802011-07-17 13:54:32 -070064 Sequence of events:
65 bundle = Bundle(tools.Tools(), cros_output.Output())
66 bundle.SetDirs(...)
67 bundle.SetFiles(...)
68 bundle.SetOptions(...)
69 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070070 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070071 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070072
Simon Glass290a1802011-07-17 13:54:32 -070073 Public properties:
74 fdt: The fdt object that we use for building our image. This wil be the
75 one specified by the user, except that we might add config options
76 to it. This is set up by SelectFdt() which must be called before
77 bundling starts.
78 uboot_fname: Full filename of the U-Boot binary we use.
79 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -070080 spl_source: Source device to load U-Boot from, in SPL:
81 straps: Select device according to CPU strap pins
82 spi: Boot from SPI
83 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -070084
85 Private attributes:
86 _small: True to create a 'small' signed U-Boot, False to produce a
87 full image. The small U-Boot is enough to boot but will not have
88 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -070089 """
Simon Glass89b86b82011-07-17 23:49:49 -070090
Simon Glass290a1802011-07-17 13:54:32 -070091 def __init__(self, tools, output):
92 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -070093
Simon Glass290a1802011-07-17 13:54:32 -070094 Args:
95 tools: A tools.Tools object to use for external tools.
96 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -070097 """
Simon Glass290a1802011-07-17 13:54:32 -070098 self._tools = tools
99 self._out = output
100
101 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500102 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700103 self._fdt_fname = None # Filename of our FDT.
Simon Glass00d027e2013-07-20 14:51:12 -0600104 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700105 self._gbb_flags = None
106 self._keydir = None
107 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700108 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700109 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700110 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700111 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700112 self.ecro_fname = None # Filename of EC read-only file
113 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700114 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700115 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
116 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700117 self.fdt = None # Our Fdt object.
118 self.kernel_fname = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700119 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700120 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700121 self.uboot_fname = None # Filename of our U-Boot binary.
Patrick Georgi5f949ad2016-10-12 16:03:13 +0200122 self.hardware_id = None
Patrick Georgi29d2eed2016-10-12 15:45:08 +0200123 self.bootstub = None
124 self.cb_copy = None
Patrick Georgi35147f62016-10-12 18:08:22 +0200125 self.fwid = None
Simon Glass290a1802011-07-17 13:54:32 -0700126
127 def SetDirs(self, keydir):
128 """Set up directories required for Bundle.
129
130 Args:
131 keydir: Directory containing keys to use for signing firmware.
132 """
133 self._keydir = keydir
134
Patrick Georgi48030572016-09-09 22:55:46 +0200135 def SetFiles(self, board, bct, uboot=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800136 coreboot_elf=None,
Simon Glass942bedb2016-05-14 16:19:59 -0600137 seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700138 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Patrick Georgi48030572016-09-09 22:55:46 +0200139 kernel=None, blobs=None, cbfs_files=None,
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600140 rocbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700141 """Set up files required for Bundle.
142
143 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500144 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700145 uboot: The filename of the u-boot.bin image to use.
146 bct: The filename of the binary BCT file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800147 coreboot: The filename of the coreboot image to use (on x86).
148 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Vincent Palatinf7286772011-10-12 14:31:53 -0700149 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700150 exynos_bl1: The filename of the exynos BL1 file
151 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
152 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700153 ecrw: The filename of the EC (Embedded Controller) read-write file.
154 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700155 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700156 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800157 blobs: List of (type, filename) of arbitrary blobs.
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600158 cbfs_files: Root directory of files to be stored in RO and RW CBFS
159 rocbfs_files: Root directory of files to be stored in RO CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700160 """
161 self._board = board
162 self.uboot_fname = uboot
163 self.bct_fname = bct
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700164 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800165 self.coreboot_elf = coreboot_elf
Vincent Palatinf7286772011-10-12 14:31:53 -0700166 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700167 self.exynos_bl1 = exynos_bl1
168 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700169 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700170 self.ecrw_fname = ecrw
171 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700172 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700173 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800174 self.blobs = dict(blobs or ())
Daisuke Nojiri69662892015-09-25 15:24:04 -0700175 self.cbfs_files = cbfs_files
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600176 self.rocbfs_files = rocbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700177
Patrick Georgi450204a2016-08-15 19:13:29 +0200178 def SetOptions(self, small, gbb_flags, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700179 """Set up options supported by Bundle.
180
181 Args:
182 small: Only create a signed U-Boot - don't produce the full packed
183 firmware image. This is useful for devs who want to replace just the
184 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700185 gbb_flags: Specification for string containing adjustments to make.
Simon Glass00d027e2013-07-20 14:51:12 -0600186 force_efs: Force firmware to use 'early firmware selection' feature,
187 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700188 """
189 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700190 self._gbb_flags = gbb_flags
Simon Glass00d027e2013-07-20 14:51:12 -0600191 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700192
Simon Glass22f39fb2013-02-09 13:44:14 -0800193 def _GetBuildRoot(self):
194 """Get the path to this board's 'firmware' directory.
195
196 Returns:
197 Path to firmware directory, with ## representing the path to the
198 chroot.
199 """
Simon Glass290a1802011-07-17 13:54:32 -0700200 if not self._board:
201 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800202 return os.path.join('##', 'build', self._board, 'firmware')
203
204 def _CheckFdtFilename(self, fname):
205 """Check provided FDT filename and return the correct name if needed.
206
207 Where the filename lacks a path, add a default path for this board.
208 Where no FDT filename is provided, select a default one for this board.
209
210 Args:
211 fname: Proposed FDT filename.
212
213 Returns:
214 Selected FDT filename, after validation.
215 """
216 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700217 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800218 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700219 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700220 base_name = re.sub('_', '-', self._board)
221
222 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700223 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700224 found_list = glob.glob(self._tools.Filename(wildcard))
225 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800226 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700227 else:
228 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700229 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700230
Simon Glass881964d2012-04-04 11:34:09 -0700231 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800232 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700233 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700234 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800235 return fname
236
237 def CheckOptions(self):
238 """Check provided options and select defaults."""
239 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700240
Simon Glass49b026b2013-04-26 16:38:42 -0700241 board_type = self._board.split('_')[0]
242 model = type_to_model.get(board_type)
243
Simon Glass290a1802011-07-17 13:54:32 -0700244 if not self.uboot_fname:
245 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
246 if not self.bct_fname:
247 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass49b026b2013-04-26 16:38:42 -0700248 if model:
249 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700250 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700251 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700252 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700253 if not self.coreboot_fname:
254 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
255 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700256 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Simon Glassbe0bc002012-08-16 12:50:48 -0700257 if not self.ecrw_fname:
258 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700259 if not self.pdrw_fname:
260 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700261 if not self.ecro_fname:
262 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700263
Simon Glass75759302012-03-15 20:26:53 -0700264 def GetFiles(self):
265 """Get a list of files that we know about.
266
267 This is the opposite of SetFiles except that we may have put in some
268 default names. It returns a dictionary containing the filename for
269 each of a number of pre-defined files.
270
271 Returns:
272 Dictionary, with one entry for each file.
273 """
274 file_list = {
275 'bct' : self.bct_fname,
276 'exynos-bl1' : self.exynos_bl1,
277 'exynos-bl2' : self.exynos_bl2,
278 }
279 return file_list
280
Simon Glass4a887b12012-10-23 16:29:03 -0700281 def DecodeGBBFlagsFromFdt(self):
282 """Get Google Binary Block flags from the FDT.
283
284 These should be in the chromeos-config node, like this:
285
286 chromeos-config {
287 gbb-flag-dev-screen-short-delay;
288 gbb-flag-force-dev-switch-on;
289 gbb-flag-force-dev-boot-usb;
290 gbb-flag-disable-fw-rollback-check;
291 };
292
293 Returns:
294 GBB flags value from FDT.
295 """
296 chromeos_config = self.fdt.GetProps("/chromeos-config")
297 gbb_flags = 0
298 for name in chromeos_config:
299 if name.startswith('gbb-flag-'):
300 flag_value = gbb_flag_properties.get(name[9:])
301 if flag_value:
302 gbb_flags |= flag_value
303 self._out.Notice("FDT: Enabling %s." % name)
304 else:
305 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
306 return gbb_flags
307
Simon Glass157c0662012-10-23 13:52:42 -0700308 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
309 """Decode ajustments to the provided GBB flags.
310
311 We support three options:
312
313 hex value: c2
314 defined value: force-dev-boot-usb,load-option-roms
315 adjust default value: -load-option-roms,+force-dev-boot-usb
316
317 The last option starts from the passed-in GBB flags and adds or removes
318 flags.
319
320 Args:
321 gbb_flags: Base (default) FDT flags.
322 adjustments: String containing adjustments to make.
323
324 Returns:
325 Updated FDT flags.
326 """
327 use_base_value = True
328 if adjustments:
329 try:
330 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700331 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700332 pass
333 for flag in adjustments.split(','):
334 oper = None
335 if flag[0] in ['-', '+']:
336 oper = flag[0]
337 flag = flag[1:]
338 value = gbb_flag_properties.get(flag)
339 if not value:
340 raise ValueError("Invalid GBB flag '%s'" % flag)
341 if oper == '+':
342 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800343 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700344 elif oper == '-':
345 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800346 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700347 else:
348 if use_base_value:
349 gbb_flags = 0
350 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800351 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700352 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800353 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700354
355 return gbb_flags
356
Patrick Georgi5f949ad2016-10-12 16:03:13 +0200357 def _CreateGoogleBinaryBlock(self):
Simon Glass89b86b82011-07-17 23:49:49 -0700358 """Create a GBB for the image.
359
Simon Glass56577572011-07-19 11:08:06 +1200360 Args:
361 hardware_id: Hardware ID to use for this board. If None, then the
362 default from the Fdt will be used
363
Simon Glass89b86b82011-07-17 23:49:49 -0700364 Returns:
365 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700366 """
Patrick Georgi5f949ad2016-10-12 16:03:13 +0200367 hardware_id = self.hardware_id
Simon Glass56577572011-07-19 11:08:06 +1200368 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800369 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass290a1802011-07-17 13:54:32 -0700370 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700371
Simon Glass4a887b12012-10-23 16:29:03 -0700372 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800373
Simon Glass157c0662012-10-23 13:52:42 -0700374 # Allow command line to override flags
375 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
376
Simon Glass4a887b12012-10-23 16:29:03 -0700377 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700378 self._out.Progress('Creating GBB')
Patrick Georgi48030572016-09-09 22:55:46 +0200379 sizes = [0x100, 0x1000, 0, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700380 sizes = ['%#x' % size for size in sizes]
381 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700382 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800383
384 gbb_set_command = ['-s',
385 '--hwid=%s' % hardware_id,
386 '--rootkey=%s/root_key.vbpubk' % keydir,
387 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
388 '--flags=%d' % gbb_flags,
389 gbb]
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800390
Simon Glass290a1802011-07-17 13:54:32 -0700391 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800392 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700393 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700394
Simon Glasse13ee2c2011-07-28 08:12:28 +1200395 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700396 """Sign an image so that the Tegra SOC will boot it.
397
398 Args:
399 bct: BCT file to use.
400 bootstub: Boot stub (U-Boot + fdt) file to sign.
401 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700402
403 Returns:
404 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700405 """
406 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200407 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700408 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200409 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700410 fd = open(config, 'w')
411 fd.write('Version = 1;\n')
412 fd.write('Redundancy = 1;\n')
413 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700414
415 # TODO(dianders): Right now, we don't have enough space in our flash map
416 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
417 # sure what this does for reliability, but at least things will fit...
418 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
419 if is_nand:
420 fd.write('Bctcopy = 1;\n')
421
Simon Glass89b86b82011-07-17 23:49:49 -0700422 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
423 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700424
Simon Glass89b86b82011-07-17 23:49:49 -0700425 fd.close()
426
427 self._tools.Run('cbootimage', [config, signed])
428 self._tools.OutputSize('BCT', bct)
429 self._tools.OutputSize('Signed image', signed)
430 return signed
431
Doug Anderson86ce5f42011-07-27 10:40:18 -0700432 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700433 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700434
435 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700436 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700437 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700438 """
Simon Glass468d8752012-09-19 16:36:19 -0700439 if bootcmd is not None:
440 if bootcmd == 'none':
441 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800442 self.fdt.PutString('/config', 'bootcmd', bootcmd)
443 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700444 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700445
Simon Glassa4934b72012-05-09 13:35:02 -0700446 def SetNodeEnabled(self, node_name, enabled):
447 """Set whether an node is enabled or disabled.
448
449 This simply sets the 'status' property of a node to "ok", or "disabled".
450
451 The node should either be a full path to the node (like '/uart@10200000')
452 or an alias property.
453
454 Aliases are supported like this:
455
456 aliases {
457 console = "/uart@10200000";
458 };
459
460 pointing to a node:
461
462 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700463 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700464 };
465
466 In this case, this function takes the name of the alias ('console' in
467 this case) and updates the status of the node that is pointed to, to
468 either ok or disabled. If the alias does not exist, a warning is
469 displayed.
470
471 Args:
472 node_name: Name of node (e.g. '/uart@10200000') or alias alias
473 (e.g. 'console') to adjust
474 enabled: True to enable, False to disable
475 """
476 # Look up the alias if this is an alias reference
477 if not node_name.startswith('/'):
478 lookup = self.fdt.GetString('/aliases', node_name, '')
479 if not lookup:
480 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
481 return
482 node_name = lookup
483 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700484 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700485 else:
486 status = 'disabled'
487 self.fdt.PutString(node_name, 'status', status)
488
489 def AddEnableList(self, enable_list):
490 """Process a list of nodes to enable/disable.
491
492 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700493 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700494 tuple:
495 node: The fdt node to write to will be <node> or pointed to by
496 /aliases/<node>. We can tell which
497 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700498
Vadim Bendebury507c0012013-06-09 12:49:25 -0700499 Raises:
500 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700501 """
502 if enable_list:
503 for node_name, enabled in enable_list:
504 try:
505 enabled = int(enabled)
506 if enabled not in (0, 1):
507 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700508 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700509 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700510 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700511 self.SetNodeEnabled(node_name, enabled)
512
Simon Glass290a1802011-07-17 13:54:32 -0700513 def AddConfigList(self, config_list, use_int=False):
514 """Add a list of config items to the fdt.
515
516 Normally these values are written to the fdt as strings, but integers
517 are also supported, in which case the values will be converted to integers
518 (if necessary) before being stored.
519
520 Args:
521 config_list: List of (config, value) tuples to add to the fdt. For each
522 tuple:
523 config: The fdt node to write to will be /config/<config>.
524 value: An integer or string value to write.
525 use_int: True to only write integer values.
526
527 Raises:
528 CmdError: if a value is required to be converted to integer but can't be.
529 """
530 if config_list:
531 for config in config_list:
532 value = config[1]
533 if use_int:
534 try:
535 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700536 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700537 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700538 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700539 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800540 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700541 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800542 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700543
Simon Glass7c2d5572011-11-15 14:47:08 -0800544 def DecodeTextBase(self, data):
545 """Look at a U-Boot image and try to decode its TEXT_BASE.
546
547 This works because U-Boot has a header with the value 0x12345678
548 immediately followed by the TEXT_BASE value. We can therefore read this
549 from the image with some certainty. We check only the first 40 words
550 since the header should be within that region.
551
Simon Glass96b50302012-07-20 06:55:28 +0100552 Since upstream Tegra has moved to having a 16KB SPL region at the start,
553 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
554 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
555
Simon Glass7c2d5572011-11-15 14:47:08 -0800556 Args:
557 data: U-Boot binary data
558
559 Returns:
560 Text base (integer) or None if none was found
561 """
562 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100563 for start in (0, 0x4000):
564 for i in range(start, start + 160, 4):
565 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800566
Simon Glass96b50302012-07-20 06:55:28 +0100567 # TODO(sjg): This does not cope with a big-endian target
568 value = struct.unpack('<I', word)[0]
569 if found:
570 return value - start
571 if value == 0x12345678:
572 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800573
574 return None
575
576 def CalcTextBase(self, name, fdt, fname):
577 """Calculate the TEXT_BASE to use for U-Boot.
578
579 Normally this value is in the fdt, so we just read it from there. But as
580 a second check we look at the image itself in case this is different, and
581 switch to that if it is.
582
583 This allows us to flash any U-Boot even if its TEXT_BASE is different.
584 This is particularly useful with upstream U-Boot which uses a different
585 value (which we will move to).
586 """
587 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800588 # The value that comes back from fdt.GetInt is signed, which makes no
589 # sense for an address base. Force it to unsigned.
590 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800591 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100592 text_base_str = '%#x' % text_base if text_base else 'None'
593 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
594 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800595
596 # If they are different, issue a warning and switch over.
597 if text_base and text_base != fdt_text_base:
598 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
599 "fdt value of %x. Using %x" % (text_base, name,
600 fdt_text_base, text_base))
601 fdt_text_base = text_base
602 return fdt_text_base
603
Patrick Georgie5fec8c2016-10-12 19:36:09 +0200604 def _AddCbfsFiles(self, bootstub, cbfs_files, regions='COREBOOT'):
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600605 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600606 for file in files:
607 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600608 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600609 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
Patrick Georgie5fec8c2016-10-12 19:36:09 +0200610 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma',
611 '-r', regions])
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600612
Patrick Georgi29d2eed2016-10-12 15:45:08 +0200613 def _CreateCorebootStub(self, coreboot):
614 """Create a coreboot boot stub.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700615
616 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700617 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700618 """
619 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700620 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100621
Patrick Georgi29d2eed2016-10-12 15:45:08 +0200622 self.bootstub = bootstub
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700623
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600624 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600625 if self.cbfs_files:
Patrick Georgie5fec8c2016-10-12 19:36:09 +0200626 self._AddCbfsFiles(bootstub, self.cbfs_files,
627 'COREBOOT,FW_MAIN_A,FW_MAIN_B')
Simon Glass7e199222012-03-13 15:51:18 -0700628
Patrick Georgi2fc662e2016-10-12 19:28:53 +0200629 # Add files to to RO CBFS if provided.
630 if self.rocbfs_files:
631 self._AddCbfsFiles(bootstub, self.rocbfs_files)
632
633 # Create a coreboot copy to use as a scratch pad.
Patrick Georgi3a332672015-11-20 10:02:51 +0100634 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600635 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100636 binary = self._tools.ReadFile(bootstub)
Patrick Georgi3a332672015-11-20 10:02:51 +0100637 self._tools.WriteFile(cb_copy, binary)
Patrick Georgi29d2eed2016-10-12 15:45:08 +0200638 self.cb_copy = cb_copy
Aaron Durbina113f522016-01-05 09:09:55 -0600639
Simon Glass89b86b82011-07-17 23:49:49 -0700640 def _PackOutput(self, msg):
641 """Helper function to write output from PackFirmware (verbose level 2).
642
643 This is passed to PackFirmware for it to use to write output.
644
645 Args:
646 msg: Message to display.
647 """
648 self._out.Notice(msg)
649
Patrick Georgic1064f42016-10-12 11:34:24 +0200650 def _FdtNameToFmap(self, fdtstr):
651 return re.sub('-', '_', fdtstr).upper()
652
Aaron Durbin80564452015-12-21 15:25:06 -0600653 def _FmapNameByPath(self, path):
654 """ Take list of names to form node path. Return FMAP name.
655
656 Obtain the FMAP name described by the node path.
657
658 Args:
659 path: list forming a node path.
660
661 Returns:
662 FMAP name of fdt node.
663
664 Raises:
665 CmdError if path not found.
666 """
667 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
Patrick Georgic1064f42016-10-12 11:34:24 +0200668 return self._FdtNameToFmap(lbl)
Aaron Durbin80564452015-12-21 15:25:06 -0600669
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800670 def _PrepareCbfs(self, pack, blob_name):
671 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
672
673 When the blob name is defined as cbfs#<section>#<subsection>, fill the
674 <section>_<subsection> area in the flash map with a CBFS copy, putting the
675 CBFS header of the copy at the base of the section.
676
677 If --coreboot-elf parameter was specified during cros_bumdle_firmware
678 invocation, add the parameter of this option as the payload to the new
679 CBFS instance.
680
681 Args:
682 pack: a PackFirmware object describing the firmware image to build.
683 blob_name: a string, blob name describing what FMAP section this CBFS
684 copy is destined to
685 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100686 CmdError if cbfs-files node has incorrect parameters.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800687 """
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800688 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600689 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800690
691 # Base address and size of the desitnation partition
692 base, size = self.fdt.GetFlashPart(*part_sections)
693
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800694 # Add coreboot payload if so requested. Note that the some images use
695 # different payload for the rw sections, which is passed in as the value
696 # of the --uboot option in the command line.
697 if self.uboot_fname:
698 payload_fname = self.uboot_fname
699 elif self.coreboot_elf:
700 payload_fname = self.coreboot_elf
701 else:
702 payload_fname = None
703
704 if payload_fname:
705 self._tools.Run('cbfstool', [
Patrick Georgi69d47622016-10-12 15:53:06 +0200706 self.cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100707 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800708
Patrick Georgi964fb542015-10-16 16:52:03 +0200709 if self.ecrw_fname:
710 self._tools.Run('cbfstool', [
Patrick Georgi69d47622016-10-12 15:53:06 +0200711 self.cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100712 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200713
714 if self.pdrw_fname:
715 self._tools.Run('cbfstool', [
Patrick Georgi69d47622016-10-12 15:53:06 +0200716 self.cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100717 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200718
Aaron Durbin880cf952016-01-27 14:11:38 -0600719 # Parse the file list to obtain the last entry. If its empty use its
720 # offset as the size of the CBFS to hash.
721 stdout = self._tools.Run('cbfstool',
Patrick Georgi69d47622016-10-12 15:53:06 +0200722 [ self.cb_copy, 'print', '-k', '-r', fmap_dst ])
Aaron Durbin880cf952016-01-27 14:11:38 -0600723 # Fields are tab separated in the following order.
724 # Name Offset Type Metadata Size Data Size Total Size
725 last_entry = stdout.strip().splitlines()[-1].split('\t')
726 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
727 size = int(last_entry[1], 16)
728
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800729 # And extract the blob for the FW section
730 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
731 self._tools.WriteFile(rw_section,
Patrick Georgi69d47622016-10-12 15:53:06 +0200732 self._tools.ReadFile(self.cb_copy)[base:base+size])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800733
734 pack.AddProperty(blob_name, rw_section)
735
Patrick Georgidf772712016-10-05 16:24:20 +0200736 def _PrepareBootblock(self, pack):
737 """Copy bootblock into blob file for packaging
738
739 Args:
740 pack: a PackFirmware object describing the firmware image to build.
741 Raises:
742 CmdError if cbfs-files node has incorrect parameters.
743 """
Patrick Georgidf772712016-10-05 16:24:20 +0200744 bootblock_section = os.path.join(self._tools.outdir, 'bootblock.section')
745
746 self._tools.Run('cbfstool', [
Patrick Georgi69d47622016-10-12 15:53:06 +0200747 self.cb_copy, 'read', '-r', 'BOOTBLOCK', '-f', bootblock_section])
Patrick Georgidf772712016-10-05 16:24:20 +0200748
749 pack.AddProperty('bootblock', bootblock_section)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800750
Patrick Georgi9c2686b2016-10-12 16:36:42 +0200751 def _GenerateWiped(self, label, size, value):
Patrick Georgi35147f62016-10-12 18:08:22 +0200752 """Fill a CBFS region in cb_copy with a given value
Patrick Georgi9c2686b2016-10-12 16:36:42 +0200753
754 Args:
755 label: fdt-style region name
756 size: size of region
757 value: value to fill region with (int)
758 """
759 wipedfile = os.path.join(self._tools.outdir, 'wiped.%s' % label)
760 fmaplabel = self._FdtNameToFmap(label)
761
762 self._tools.WriteFile(wipedfile, size*chr(value))
763 self._tools.Run('cbfstool', [
764 self.cb_copy, 'write',
765 '--force',
766 '-r', fmaplabel, '-f', wipedfile])
767
Patrick Georgi35147f62016-10-12 18:08:22 +0200768 def _GenerateBlobstring(self, label, size, string):
769 """Fill a CBFS region in cb_copy with a given string.
770 The remainder of the region will be filled with \x00
771
772 Args:
773 label: ftd-style region name
774 size: size of region
775 string: string to fill in.
776 """
777 stringfile = os.path.join(self._tools.outdir, 'blobstring.%s' % label)
778 fmaplabel = self._FdtNameToFmap(label)
779
780 self._tools.WriteFile(stringfile, (string + size*chr(0))[:size])
781 self._tools.Run('cbfstool', [
782 self.cb_copy, 'write',
783 '--force',
784 '-r', fmaplabel, '-f', stringfile])
785
Simon Glass439fe7a2012-03-09 16:19:34 -0800786 def _BuildBlob(self, pack, fdt, blob_type):
787 """Build the blob data for a particular blob type.
788
789 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700790 pack: a PackFirmware object describing the firmware image to build.
791 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800792 blob_type: The type of blob to create data for. Supported types are:
793 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
794 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700795
796 Raises:
797 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800798 """
799 if blob_type == 'coreboot':
Patrick Georgifa20ddc2016-09-27 14:10:51 +0200800 pass
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700801 elif blob_type == 'legacy':
Patrick Georgi69d47622016-10-12 15:53:06 +0200802 self._tools.Run('cbfstool', [self.cb_copy, 'write',
Patrick Georgi44092222016-10-12 12:15:48 +0200803 '-f', self.seabios_fname,
804 '--force',
805 '-r', 'RW_LEGACY'])
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700806 pack.AddProperty('legacy', self.seabios_fname)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800807 elif blob_type.startswith('cbfs'):
808 self._PrepareCbfs(pack, blob_type)
Patrick Georgidf772712016-10-05 16:24:20 +0200809 elif blob_type == 'bootblock':
810 self._PrepareBootblock(pack)
Simon Glass439fe7a2012-03-09 16:19:34 -0800811 elif pack.GetProperty(blob_type):
812 pass
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700813 elif blob_type == 'ifwi' or blob_type == 'sig2':
814 # Copy IFWI/CSE_SIGN(sig2) regions from coreboot copy and build a blob
815 # for the blob_type
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700816 blob_start, blob_size = fdt.GetFlashPart('ro', blob_type)
817 blob_file = blob_type + '.bin'
818 blob_path = os.path.join(self._tools.outdir, blob_file)
Patrick Georgi69d47622016-10-12 15:53:06 +0200819 data = self._tools.ReadFile(self.cb_copy)
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700820 self._tools.WriteFile(blob_path, data[blob_start:blob_start+blob_size])
821 pack.AddProperty(blob_type, blob_path)
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800822 elif blob_type in self.blobs:
Patrick Georgi69d47622016-10-12 15:53:06 +0200823 self._tools.Run('cbfstool', [self.cb_copy, 'write',
Patrick Georgi44092222016-10-12 12:15:48 +0200824 '--fill-upward',
825 '-f', self.blobs[blob_type],
826 '-r', _FdtNameToFmap(blob_type)])
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800827 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800828 else:
829 raise CmdError("Unknown blob type '%s' required in flash map" %
830 blob_type)
831
Aaron Durbin41c85b62015-12-17 17:40:29 -0600832 def _BuildBlobs(self, pack, fdt):
833 """Build the blob data for the list of blobs in the pack.
834
835 Args:
836 pack: a PackFirmware object describing the firmware image to build.
837 fdt: an fdt object including image layout information
838
839 Raises:
840 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -0600841 """
842 blob_list = pack.GetBlobList()
843 self._out.Info('Building blobs %s\n' % blob_list)
844
845 complete = False
846 deferred_list = []
847
Patrick Georgi29d2eed2016-10-12 15:45:08 +0200848 pack.AddProperty('coreboot', self.bootstub)
849 pack.AddProperty('image', self.bootstub)
Patrick Georgifa20ddc2016-09-27 14:10:51 +0200850
Patrick Georgi49cf7b22016-09-27 14:25:03 +0200851 for blob_type in blob_list:
852 self._BuildBlob(pack, fdt, blob_type)
Aaron Durbin41c85b62015-12-17 17:40:29 -0600853
Patrick Georgi9d57ea42016-10-12 12:23:50 +0200854 def _BuildKeyblocks(self, pack):
855 """Compute vblocks and write them into their FMAP regions.
856 Works for the (VBLOCK_?,FW_MAIN_?) pairs
857 """
Patrick Georgi9d57ea42016-10-12 12:23:50 +0200858 fmap_blob = open(self.coreboot_fname).read()
859 f = fmap.fmap_decode(fmap_blob)
860 for area in f['areas']:
861 label = area['name']
862 slot = label[-1]
863 if label[:-1] == 'VBLOCK_':
864 region_in = 'FW_MAIN_' + slot
865 region_out = label
866
867 input_data = os.path.join(self._tools.outdir, 'input.%s' % region_in)
868 output_data = os.path.join(self._tools.outdir, 'vblock.%s' % region_out)
869 self._tools.Run('cbfstool', [
Patrick Georgi69d47622016-10-12 15:53:06 +0200870 self.cb_copy, 'read', '-r', region_in, '-f', input_data])
Patrick Georgi9d57ea42016-10-12 12:23:50 +0200871
872 # Parse the file list to obtain the last entry. If its empty use
873 # its offset as the size of the CBFS to hash.
874 stdout = self._tools.Run('cbfstool',
Patrick Georgi69d47622016-10-12 15:53:06 +0200875 [ self.cb_copy, 'print', '-k', '-r', region_in ])
Patrick Georgi9d57ea42016-10-12 12:23:50 +0200876 # Fields are tab separated in the following order.
877 # Name Offset Type Metadata Size Data Size Total Size
878 last_entry = stdout.strip().splitlines()[-1].split('\t')
879 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
880 size = int(last_entry[1], 16)
881 self._tools.Run('truncate', [
882 '--no-create', '--size', str(size), input_data])
883 self._out.Info('truncated FW_MAIN_%s to %d bytes' %
884 (slot, size))
885
886 try:
887 prefix = self._keydir + '/'
888
889 self._tools.Run('vbutil_firmware', [
890 '--vblock', output_data,
891 '--keyblock', prefix + 'firmware.keyblock',
892 '--signprivate', prefix + 'firmware_data_key.vbprivk',
893 '--version', '1',
894 '--fv', input_data,
895 '--kernelkey', prefix + 'kernel_subkey.vbpubk',
896 '--flags', '0',
897 ])
898
899 except CmdError as err:
900 raise PackError('Cannot make key block: vbutil_firmware failed\n%s' %
901 err)
Patrick Georgi69d47622016-10-12 15:53:06 +0200902 self._tools.Run('cbfstool', [self.cb_copy, 'write',
Patrick Georgi9d57ea42016-10-12 12:23:50 +0200903 '--fill-upward',
904 '-f', output_data,
905 '-r', label])
906
Simon Glass290a1802011-07-17 13:54:32 -0700907 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700908 """Create a full firmware image, along with various by-products.
909
910 This uses the provided u-boot.bin, fdt and bct to create a firmware
911 image containing all the required parts. If the GBB is not supplied
912 then this will just return a signed U-Boot as the image.
913
914 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700915 gbb: a string, full path to the GBB file, or empty if a GBB is not
916 required.
917 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200918
919 Returns:
920 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700921 """
Simon Glass02d124a2012-03-02 14:47:20 -0800922 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700923
Simon Glass439fe7a2012-03-09 16:19:34 -0800924 pack = PackFirmware(self._tools, self._out)
Simon Glass00d027e2013-07-20 14:51:12 -0600925 if self._force_efs:
926 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -0600927 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
928 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800929
Simon Glass4f318912013-07-20 16:13:06 -0600930 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800931
932 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800933 if self.uboot_fname:
934 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800935 if self.skeleton_fname:
936 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700937 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700938
Simon Glassde9c8072012-07-02 22:29:02 -0700939 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
940 if self.kernel_fname:
941 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
942
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800943 if gbb:
944 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -0600945
946 # Build the blobs out.
947 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -0700948
Patrick Georgi9d57ea42016-10-12 12:23:50 +0200949 # Now that blobs are built (and written into cb_with_fmap),
950 # create the vblocks
951 self._BuildKeyblocks(pack)
952
Simon Glass7306b902012-12-17 15:06:21 -0800953 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700954 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700955 pack.RequireAllEntries()
Patrick Georgi35147f62016-10-12 18:08:22 +0200956 self._out.Notice('Firmware ID: %s' % self.fwid)
957 pack.AddProperty('fwid', self.fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800958 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700959
960 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700961
962 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800963 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700964
Simon Glass6207efe2012-12-17 15:04:36 -0800965 # Make a copy of the fdt for the bootstub
966 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800967 if self.uboot_fname:
968 uboot_data = self._tools.ReadFile(self.uboot_fname)
969 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
970 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -0800971
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800972 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
973 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -0800974
Simon Glassa10282a2013-01-08 17:06:41 -0800975 # Fix up the coreboot image here, since we can't do this until we have
976 # a final device tree binary.
Patrick Georgi50561e82016-10-06 18:45:05 +0200977 bootstub = pack.GetProperty('coreboot')
978 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
979 if self.coreboot_elf:
980 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
981 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
982 elif self.uboot_fname:
983 text_base = 0x1110000
Simon Glass0a7cf112013-05-21 23:08:21 -0700984
Patrick Georgi50561e82016-10-06 18:45:05 +0200985 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
986 # 1110015: 66 bb 00 01 mov $0x100,%bx
987 marker = struct.pack('<L', 0x0100bb66)
988 pos = uboot_data.find(marker)
989 if pos == -1 or pos > 0x100:
990 raise ValueError('Cannot find U-Boot cold boot entry point')
991 entry = text_base + pos
992 self._out.Notice('U-Boot entry point %#08x' % entry)
993 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
994 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
995 '-l', '%#x' % text_base, '-e', '%#x' % entry])
996 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
997 '-n', 'u-boot.dtb', '-t', '0xac'])
998 data = self._tools.ReadFile(bootstub)
999 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1000 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001001
Patrick Georgi50561e82016-10-06 18:45:05 +02001002 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1003 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1004 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001005
Simon Glass208ad952013-02-10 11:16:46 -08001006 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001007 image = os.path.join(self._tools.outdir, 'image.bin')
1008 pack.PackImage(self._tools.outdir, image)
1009 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001010
Simon Glass439fe7a2012-03-09 16:19:34 -08001011 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001012 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001013 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001014
Simon Glassdedda6f2013-02-09 13:44:14 -08001015 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001016 """Select an FDT to control the firmware bundling
1017
Simon Glassdedda6f2013-02-09 13:44:14 -08001018 We make a copy of this which will include any on-the-fly changes we want
1019 to make.
1020
Simon Glass290a1802011-07-17 13:54:32 -07001021 Args:
1022 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001023 use_defaults: True to use a default FDT name if available, and to add
1024 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001025
Simon Glassc0f3dc62011-08-09 14:19:05 -07001026 Returns:
1027 The Fdt object of the original fdt file, which we will not modify.
1028
Simon Glassdedda6f2013-02-09 13:44:14 -08001029 Raises:
1030 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1031 False).
Simon Glass290a1802011-07-17 13:54:32 -07001032 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001033 if use_defaults:
1034 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001035 if not fdt_fname:
1036 raise ValueError('Please provide an FDT filename')
1037 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001038 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001039
Patrick Georgi81263072016-09-09 22:33:06 +02001040 fdt.Compile(None)
Simon Glasse53abbc2013-08-21 22:29:55 -06001041 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Patrick Georgi35147f62016-10-12 18:08:22 +02001042 self.fdt = fdt
1043 fdt.PutString('/chromeos-config', 'board', self._board)
Simon Glasse53abbc2013-08-21 22:29:55 -06001044
Patrick Georgicebb5a22016-08-15 19:07:02 +02001045 if fdt.GetProp('/flash', 'reg', ''):
1046 raise ValueError('fmap.dts /flash is deprecated. Use chromeos.fmd')
1047
Patrick Georgic092b382016-10-12 16:35:14 +02001048 self._CreateCorebootStub(self.coreboot_fname)
1049
Patrick Georgi35147f62016-10-12 18:08:22 +02001050 self.fwid = '.'.join([
1051 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
1052 self._tools.GetChromeosVersion()])
1053
Patrick Georgicebb5a22016-08-15 19:07:02 +02001054 # fill in /flash from binary fmap
1055 # ignore "read-only" attribute, that isn't used anywhere
1056 fmap_blob = open(self.coreboot_fname).read()
1057 f = fmap.fmap_decode(fmap_blob)
1058 fdt.PutString('/flash', 'compatible', 'chromeos,flashmap')
1059 fdt.PutIntList('/flash', 'reg', [f['base'], f['size']])
1060 for area in f['areas']:
1061 label = re.sub('_', '-', area['name']).lower()
1062 fdt_path = '/flash/' + label
1063 slot=label[-1]
1064 if label == 'gbb':
1065 fdt_path = '/flash/ro-gbb'
1066 fdt.PutString(fdt_path, 'type', 'blob gbb')
Patrick Georgi250ecd42016-10-12 18:22:50 +02001067 gbb = self._CreateGoogleBinaryBlock()
1068 gbbdata = (self._tools.ReadFile(gbb) +
1069 area['size']*'\x00')[:area['size']]
1070 self._tools.WriteFile(gbb, gbbdata)
1071 self._tools.Run('cbfstool', [
1072 self.cb_copy, 'write',
1073 '-r', 'GBB', '-f', gbb])
Patrick Georgicebb5a22016-08-15 19:07:02 +02001074 elif label == 'fmap':
1075 fdt_path = '/flash/ro-fmap'
1076 fdt.PutString(fdt_path, 'type', 'fmap')
1077 fdt.PutIntList(fdt_path, 'ver-major', [1])
1078 fdt.PutIntList(fdt_path, 'ver-minor', [0])
Julius Wernerbcf0c942016-09-07 16:57:40 -07001079 elif label == 'bootblock':
Patrick Georgidf772712016-10-05 16:24:20 +02001080 fdt.PutString(fdt_path, 'type', 'blob bootblock')
Patrick Georgicebb5a22016-08-15 19:07:02 +02001081 elif label == 'coreboot':
Patrick Georgidf772712016-10-05 16:24:20 +02001082 fdt_path = '/flash/ro-boot'
1083 fdt.PutString(fdt_path, 'type', 'blob coreboot')
Patrick Georgicebb5a22016-08-15 19:07:02 +02001084 elif label == 'si-desc':
1085 fdt.PutString(fdt_path, 'type', 'ifd')
1086 elif label == 'rw-shared':
1087 fdt_path = '/flash/shared-section'
1088 elif label == 'rw-section-'+slot:
1089 fdt_path = '/flash/rw-'+slot
1090 elif label == 'rw-legacy' and self.seabios_fname:
1091 fdt.PutString(fdt_path, 'type', 'blob legacy')
Furquan Shaikha9876542016-11-07 15:44:27 -08001092 elif label in ['rw-mrc-cache', 'recovery-mrc-cache', 'rw-elog',
1093 'rw-legacy', 'rw-vpd', 'rw-unused', 'ro-vpd',
1094 'ro-unused', 'ro-frid-pad', 'bios-unusable',
1095 'device-extension', 'unused-hole', 'rw-gpt-primary',
1096 'rw-gpt-secondary', 'rw-nvram', 'ro-unused-1',
1097 'ro-unused-2']:
Patrick Georgicebb5a22016-08-15 19:07:02 +02001098 fdt.PutString(fdt_path, 'type', 'wiped')
1099 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
Patrick Georgi9c2686b2016-10-12 16:36:42 +02001100 self._GenerateWiped(label, area['size'], 0xff)
Patrick Georgicebb5a22016-08-15 19:07:02 +02001101 elif label == 'shared-data':
1102 fdt.PutString(fdt_path, 'type', 'wiped')
1103 fdt.PutIntList(fdt_path, 'wipe-value', [0])
Patrick Georgi9c2686b2016-10-12 16:36:42 +02001104 self._GenerateWiped(label, area['size'], 0)
Patrick Georgicebb5a22016-08-15 19:07:02 +02001105 elif label == 'vblock-dev':
1106 fdt_path = '/flash/rw-vblock-dev'
1107 fdt.PutString(fdt_path, 'type', 'wiped')
1108 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
Patrick Georgi9c2686b2016-10-12 16:36:42 +02001109 self._GenerateWiped(label, area['size'], 0xff)
Patrick Georgicebb5a22016-08-15 19:07:02 +02001110 elif label[:-1] == 'vblock-':
1111 fdt_path = '/flash/rw-'+slot+'-vblock'
1112 fdt.PutString(fdt_path, 'type', 'keyblock cbfs/rw/'+slot+'-boot')
1113 fdt.PutString(fdt_path, 'keyblock', 'firmware.keyblock')
1114 fdt.PutString(fdt_path, 'signprivate', 'firmware_data_key.vbprivk')
1115 fdt.PutString(fdt_path, 'kernelkey', 'kernel_subkey.vbpubk')
1116 fdt.PutIntList(fdt_path, 'version', [1])
1117 fdt.PutIntList(fdt_path, 'preamble-flags', [0])
1118 elif label[:-1] == 'fw-main-':
1119 fdt_path = '/flash/rw-'+slot+'-boot'
1120 fdt.PutString(fdt_path, 'type', 'blob cbfs/rw/'+slot+'-boot')
1121 elif label[:-1] == 'rw-fwid-':
1122 fdt_path = '/flash/rw-'+slot+'-firmware-id'
1123 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
Patrick Georgi35147f62016-10-12 18:08:22 +02001124 self._GenerateBlobstring(label, area['size'], self.fwid)
Patrick Georgicebb5a22016-08-15 19:07:02 +02001125 elif label == 'ro-frid':
1126 fdt_path = '/flash/ro-firmware-id'
1127 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
Patrick Georgi35147f62016-10-12 18:08:22 +02001128 self._GenerateBlobstring(label, area['size'], self.fwid)
Patrick Georgicebb5a22016-08-15 19:07:02 +02001129 elif label == 'ifwi':
1130 fdt_path = '/flash/ro-ifwi'
1131 fdt.PutString(fdt_path, 'type', 'blob ifwi')
1132 elif label == 'sign-cse':
1133 fdt_path = '/flash/ro-sig'
1134 fdt.PutString(fdt_path, 'type', 'blob sig2')
1135 # white list for empty regions
Patrick Georgi56dc9202016-09-07 21:12:04 +02001136 elif label in ['bootblock', 'misc-rw', 'ro-section', 'rw-environment',
Furquan Shaikha9876542016-11-07 15:44:27 -08001137 'rw-gpt', 'si-all', 'si-bios', 'si-me', 'wp-ro',
1138 'unified-mrc-cache']:
Patrick Georgicebb5a22016-08-15 19:07:02 +02001139 pass
1140 else:
1141 raise ValueError('encountered label "'+label+'" in binary fmap. '+
1142 'Check chromeos.fmd')
1143 fdt.PutString(fdt_path, 'label', label)
1144 fdt.PutIntList(fdt_path, 'reg', [area['offset'], area['size']])
Simon Glasse53abbc2013-08-21 22:29:55 -06001145 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001146
Simon Glassc90cf582012-03-13 15:40:47 -07001147 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001148 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001149
1150 - Checks options, tools, output directory, fdt.
1151 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001152
1153 Args:
Simon Glass56577572011-07-19 11:08:06 +12001154 hardware_id: Hardware ID to use for this board. If None, then the
1155 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001156 output_fname: Output filename for the image. If this is not None, then
1157 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001158 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001159
1160 Returns:
1161 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001162 """
Patrick Georgi5f949ad2016-10-12 16:03:13 +02001163 self.hardware_id = hardware_id
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001164 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1165 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1166 else:
Patrick Georgi5f949ad2016-10-12 16:03:13 +02001167 gbb = self._CreateGoogleBinaryBlock()
Simon Glass89b86b82011-07-17 23:49:49 -07001168
1169 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001170 image, pack = self._CreateImage(gbb, self.fdt)
1171 if show_map:
1172 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001173 if output_fname:
1174 shutil.copyfile(image, output_fname)
1175 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001176 return image, pack.props