blob: 0b18cc5b727763e4d02559c273bdcab325b2f00c [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
Patrick Georgicebb5a22016-08-15 19:07:02 +020028import fmap
Simon Glass439fe7a2012-03-09 16:19:34 -080029from tools import CmdError
Vadim Bendeburyb12e3352013-06-08 17:25:19 -070030from exynos import ExynosBl2
Simon Glass89b86b82011-07-17 23:49:49 -070031
Simon Glass4a887b12012-10-23 16:29:03 -070032# Build GBB flags.
33# (src/platform/vboot_reference/firmware/include/gbb_header.h)
34gbb_flag_properties = {
35 'dev-screen-short-delay': 0x00000001,
36 'load-option-roms': 0x00000002,
37 'enable-alternate-os': 0x00000004,
38 'force-dev-switch-on': 0x00000008,
39 'force-dev-boot-usb': 0x00000010,
40 'disable-fw-rollback-check': 0x00000020,
41 'enter-triggers-tonorm': 0x00000040,
42 'force-dev-boot-legacy': 0x00000080,
Shawn Nematbakhsh07c19882014-08-19 10:21:59 -070043 'faft-key-overide': 0x00000100,
44 'disable-ec-software-sync': 0x00000200,
45 'default-dev-boot-legacy': 0x00000400,
46 'disable-pd-software-sync': 0x00000800,
Furquan Shaikhd4eac3b2015-05-15 18:05:09 -070047 'force-dev-boot-fastboot-full-cap': 0x00002000,
Mary Ruthvena759c322015-11-16 08:23:26 -080048 'enable-serial': 0x00004000,
Simon Glass4a887b12012-10-23 16:29:03 -070049}
50
Simon Glass49b026b2013-04-26 16:38:42 -070051# Maps board name to Exynos product number
52type_to_model = {
53 'peach' : '5420',
54 'daisy' : '5250'
55}
56
Simon Glass5076a7f2012-10-23 16:31:54 -070057def ListGoogleBinaryBlockFlags():
58 """Print out a list of GBB flags."""
59 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
60 for name, value in gbb_flag_properties.iteritems():
61 print ' %-30s %02x' % (name, value)
62
Aaron Durbin41c85b62015-12-17 17:40:29 -060063class BlobDeferral(Exception):
64 """An error indicating deferal of blob generation."""
65 pass
66
Simon Glass89b86b82011-07-17 23:49:49 -070067class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070068 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070069
Simon Glass290a1802011-07-17 13:54:32 -070070 Sequence of events:
71 bundle = Bundle(tools.Tools(), cros_output.Output())
72 bundle.SetDirs(...)
73 bundle.SetFiles(...)
74 bundle.SetOptions(...)
75 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070076 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070077 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070078
Simon Glass290a1802011-07-17 13:54:32 -070079 Public properties:
80 fdt: The fdt object that we use for building our image. This wil be the
81 one specified by the user, except that we might add config options
82 to it. This is set up by SelectFdt() which must be called before
83 bundling starts.
84 uboot_fname: Full filename of the U-Boot binary we use.
85 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -070086 spl_source: Source device to load U-Boot from, in SPL:
87 straps: Select device according to CPU strap pins
88 spi: Boot from SPI
89 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -070090
91 Private attributes:
92 _small: True to create a 'small' signed U-Boot, False to produce a
93 full image. The small U-Boot is enough to boot but will not have
94 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -070095 """
Simon Glass89b86b82011-07-17 23:49:49 -070096
Simon Glass290a1802011-07-17 13:54:32 -070097 def __init__(self, tools, output):
98 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -070099
Simon Glass290a1802011-07-17 13:54:32 -0700100 Args:
101 tools: A tools.Tools object to use for external tools.
102 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700103 """
Simon Glass290a1802011-07-17 13:54:32 -0700104 self._tools = tools
105 self._out = output
106
107 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500108 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700109 self._fdt_fname = None # Filename of our FDT.
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
Patrick Georgi450204a2016-08-15 19:13:29 +0200185 def SetOptions(self, small, gbb_flags, 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.
Simon Glass00d027e2013-07-20 14:51:12 -0600193 force_efs: Force firmware to use 'early firmware selection' feature,
194 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700195 """
196 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700197 self._gbb_flags = gbb_flags
Simon Glass00d027e2013-07-20 14:51:12 -0600198 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700199
Simon Glass22f39fb2013-02-09 13:44:14 -0800200 def _GetBuildRoot(self):
201 """Get the path to this board's 'firmware' directory.
202
203 Returns:
204 Path to firmware directory, with ## representing the path to the
205 chroot.
206 """
Simon Glass290a1802011-07-17 13:54:32 -0700207 if not self._board:
208 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800209 return os.path.join('##', 'build', self._board, 'firmware')
210
211 def _CheckFdtFilename(self, fname):
212 """Check provided FDT filename and return the correct name if needed.
213
214 Where the filename lacks a path, add a default path for this board.
215 Where no FDT filename is provided, select a default one for this board.
216
217 Args:
218 fname: Proposed FDT filename.
219
220 Returns:
221 Selected FDT filename, after validation.
222 """
223 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700224 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800225 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700226 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700227 base_name = re.sub('_', '-', self._board)
228
229 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700230 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700231 found_list = glob.glob(self._tools.Filename(wildcard))
232 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800233 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700234 else:
235 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700236 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700237
Simon Glass881964d2012-04-04 11:34:09 -0700238 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800239 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700240 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700241 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800242 return fname
243
244 def CheckOptions(self):
245 """Check provided options and select defaults."""
246 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700247
Simon Glass49b026b2013-04-26 16:38:42 -0700248 board_type = self._board.split('_')[0]
249 model = type_to_model.get(board_type)
250
Simon Glass290a1802011-07-17 13:54:32 -0700251 if not self.uboot_fname:
252 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
253 if not self.bct_fname:
254 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700255 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700256 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700257 if model:
258 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700259 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700260 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700261 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700262 if not self.coreboot_fname:
263 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
264 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700265 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Simon Glassbe0bc002012-08-16 12:50:48 -0700266 if not self.ecrw_fname:
267 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700268 if not self.pdrw_fname:
269 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700270 if not self.ecro_fname:
271 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700272
Simon Glass75759302012-03-15 20:26:53 -0700273 def GetFiles(self):
274 """Get a list of files that we know about.
275
276 This is the opposite of SetFiles except that we may have put in some
277 default names. It returns a dictionary containing the filename for
278 each of a number of pre-defined files.
279
280 Returns:
281 Dictionary, with one entry for each file.
282 """
283 file_list = {
284 'bct' : self.bct_fname,
285 'exynos-bl1' : self.exynos_bl1,
286 'exynos-bl2' : self.exynos_bl2,
287 }
288 return file_list
289
Simon Glass4a887b12012-10-23 16:29:03 -0700290 def DecodeGBBFlagsFromFdt(self):
291 """Get Google Binary Block flags from the FDT.
292
293 These should be in the chromeos-config node, like this:
294
295 chromeos-config {
296 gbb-flag-dev-screen-short-delay;
297 gbb-flag-force-dev-switch-on;
298 gbb-flag-force-dev-boot-usb;
299 gbb-flag-disable-fw-rollback-check;
300 };
301
302 Returns:
303 GBB flags value from FDT.
304 """
305 chromeos_config = self.fdt.GetProps("/chromeos-config")
306 gbb_flags = 0
307 for name in chromeos_config:
308 if name.startswith('gbb-flag-'):
309 flag_value = gbb_flag_properties.get(name[9:])
310 if flag_value:
311 gbb_flags |= flag_value
312 self._out.Notice("FDT: Enabling %s." % name)
313 else:
314 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
315 return gbb_flags
316
Simon Glass157c0662012-10-23 13:52:42 -0700317 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
318 """Decode ajustments to the provided GBB flags.
319
320 We support three options:
321
322 hex value: c2
323 defined value: force-dev-boot-usb,load-option-roms
324 adjust default value: -load-option-roms,+force-dev-boot-usb
325
326 The last option starts from the passed-in GBB flags and adds or removes
327 flags.
328
329 Args:
330 gbb_flags: Base (default) FDT flags.
331 adjustments: String containing adjustments to make.
332
333 Returns:
334 Updated FDT flags.
335 """
336 use_base_value = True
337 if adjustments:
338 try:
339 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700340 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700341 pass
342 for flag in adjustments.split(','):
343 oper = None
344 if flag[0] in ['-', '+']:
345 oper = flag[0]
346 flag = flag[1:]
347 value = gbb_flag_properties.get(flag)
348 if not value:
349 raise ValueError("Invalid GBB flag '%s'" % flag)
350 if oper == '+':
351 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800352 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700353 elif oper == '-':
354 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800355 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700356 else:
357 if use_base_value:
358 gbb_flags = 0
359 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800360 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700361 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800362 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700363
364 return gbb_flags
365
Simon Glass56577572011-07-19 11:08:06 +1200366 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700367 """Create a GBB for the image.
368
Simon Glass56577572011-07-19 11:08:06 +1200369 Args:
370 hardware_id: Hardware ID to use for this board. If None, then the
371 default from the Fdt will be used
372
Simon Glass89b86b82011-07-17 23:49:49 -0700373 Returns:
374 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700375 """
Simon Glass56577572011-07-19 11:08:06 +1200376 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800377 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700378 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700379 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700380
Simon Glass4a887b12012-10-23 16:29:03 -0700381 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800382
Simon Glass157c0662012-10-23 13:52:42 -0700383 # Allow command line to override flags
384 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
385
Simon Glass4a887b12012-10-23 16:29:03 -0700386 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700387 self._out.Progress('Creating GBB')
Daisuke Nojiri10b193f2016-01-15 17:53:14 -0800388 if self.skip_bmpblk:
389 bmpfv_size = 0
390 else:
391 bmpfv_size = gbb_size - 0x2180
392 sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700393 sizes = ['%#x' % size for size in sizes]
394 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700395 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800396
397 gbb_set_command = ['-s',
398 '--hwid=%s' % hardware_id,
399 '--rootkey=%s/root_key.vbpubk' % keydir,
400 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
401 '--flags=%d' % gbb_flags,
402 gbb]
403 if not self.skip_bmpblk:
404 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
405 self.bmpblk_fname),]
406
Simon Glass290a1802011-07-17 13:54:32 -0700407 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800408 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700409 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700410
Simon Glasse13ee2c2011-07-28 08:12:28 +1200411 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700412 """Sign an image so that the Tegra SOC will boot it.
413
414 Args:
415 bct: BCT file to use.
416 bootstub: Boot stub (U-Boot + fdt) file to sign.
417 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700418
419 Returns:
420 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700421 """
422 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200423 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700424 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200425 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700426 fd = open(config, 'w')
427 fd.write('Version = 1;\n')
428 fd.write('Redundancy = 1;\n')
429 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700430
431 # TODO(dianders): Right now, we don't have enough space in our flash map
432 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
433 # sure what this does for reliability, but at least things will fit...
434 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
435 if is_nand:
436 fd.write('Bctcopy = 1;\n')
437
Simon Glass89b86b82011-07-17 23:49:49 -0700438 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
439 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700440
Simon Glass89b86b82011-07-17 23:49:49 -0700441 fd.close()
442
443 self._tools.Run('cbootimage', [config, signed])
444 self._tools.OutputSize('BCT', bct)
445 self._tools.OutputSize('Signed image', signed)
446 return signed
447
Doug Anderson86ce5f42011-07-27 10:40:18 -0700448 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700449 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700450
451 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700452 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700453 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700454 """
Simon Glass468d8752012-09-19 16:36:19 -0700455 if bootcmd is not None:
456 if bootcmd == 'none':
457 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800458 self.fdt.PutString('/config', 'bootcmd', bootcmd)
459 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700460 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700461
Simon Glassa4934b72012-05-09 13:35:02 -0700462 def SetNodeEnabled(self, node_name, enabled):
463 """Set whether an node is enabled or disabled.
464
465 This simply sets the 'status' property of a node to "ok", or "disabled".
466
467 The node should either be a full path to the node (like '/uart@10200000')
468 or an alias property.
469
470 Aliases are supported like this:
471
472 aliases {
473 console = "/uart@10200000";
474 };
475
476 pointing to a node:
477
478 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700479 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700480 };
481
482 In this case, this function takes the name of the alias ('console' in
483 this case) and updates the status of the node that is pointed to, to
484 either ok or disabled. If the alias does not exist, a warning is
485 displayed.
486
487 Args:
488 node_name: Name of node (e.g. '/uart@10200000') or alias alias
489 (e.g. 'console') to adjust
490 enabled: True to enable, False to disable
491 """
492 # Look up the alias if this is an alias reference
493 if not node_name.startswith('/'):
494 lookup = self.fdt.GetString('/aliases', node_name, '')
495 if not lookup:
496 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
497 return
498 node_name = lookup
499 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700500 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700501 else:
502 status = 'disabled'
503 self.fdt.PutString(node_name, 'status', status)
504
505 def AddEnableList(self, enable_list):
506 """Process a list of nodes to enable/disable.
507
508 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700509 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700510 tuple:
511 node: The fdt node to write to will be <node> or pointed to by
512 /aliases/<node>. We can tell which
513 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700514
Vadim Bendebury507c0012013-06-09 12:49:25 -0700515 Raises:
516 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700517 """
518 if enable_list:
519 for node_name, enabled in enable_list:
520 try:
521 enabled = int(enabled)
522 if enabled not in (0, 1):
523 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700524 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700525 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700526 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700527 self.SetNodeEnabled(node_name, enabled)
528
Simon Glass290a1802011-07-17 13:54:32 -0700529 def AddConfigList(self, config_list, use_int=False):
530 """Add a list of config items to the fdt.
531
532 Normally these values are written to the fdt as strings, but integers
533 are also supported, in which case the values will be converted to integers
534 (if necessary) before being stored.
535
536 Args:
537 config_list: List of (config, value) tuples to add to the fdt. For each
538 tuple:
539 config: The fdt node to write to will be /config/<config>.
540 value: An integer or string value to write.
541 use_int: True to only write integer values.
542
543 Raises:
544 CmdError: if a value is required to be converted to integer but can't be.
545 """
546 if config_list:
547 for config in config_list:
548 value = config[1]
549 if use_int:
550 try:
551 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700552 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700553 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700554 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700555 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800556 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700557 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800558 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700559
Simon Glass7c2d5572011-11-15 14:47:08 -0800560 def DecodeTextBase(self, data):
561 """Look at a U-Boot image and try to decode its TEXT_BASE.
562
563 This works because U-Boot has a header with the value 0x12345678
564 immediately followed by the TEXT_BASE value. We can therefore read this
565 from the image with some certainty. We check only the first 40 words
566 since the header should be within that region.
567
Simon Glass96b50302012-07-20 06:55:28 +0100568 Since upstream Tegra has moved to having a 16KB SPL region at the start,
569 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
570 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
571
Simon Glass7c2d5572011-11-15 14:47:08 -0800572 Args:
573 data: U-Boot binary data
574
575 Returns:
576 Text base (integer) or None if none was found
577 """
578 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100579 for start in (0, 0x4000):
580 for i in range(start, start + 160, 4):
581 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800582
Simon Glass96b50302012-07-20 06:55:28 +0100583 # TODO(sjg): This does not cope with a big-endian target
584 value = struct.unpack('<I', word)[0]
585 if found:
586 return value - start
587 if value == 0x12345678:
588 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800589
590 return None
591
592 def CalcTextBase(self, name, fdt, fname):
593 """Calculate the TEXT_BASE to use for U-Boot.
594
595 Normally this value is in the fdt, so we just read it from there. But as
596 a second check we look at the image itself in case this is different, and
597 switch to that if it is.
598
599 This allows us to flash any U-Boot even if its TEXT_BASE is different.
600 This is particularly useful with upstream U-Boot which uses a different
601 value (which we will move to).
602 """
603 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800604 # The value that comes back from fdt.GetInt is signed, which makes no
605 # sense for an address base. Force it to unsigned.
606 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800607 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100608 text_base_str = '%#x' % text_base if text_base else 'None'
609 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
610 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800611
612 # If they are different, issue a warning and switch over.
613 if text_base and text_base != fdt_text_base:
614 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
615 "fdt value of %x. Using %x" % (text_base, name,
616 fdt_text_base, text_base))
617 fdt_text_base = text_base
618 return fdt_text_base
619
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600620 def _CreateBootStub(self, uboot, base_fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700621 """Create a boot stub and a signed boot stub.
622
623 Args:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600624 uboot: Path to u-boot.bin (may be chroot-relative).
Simon Glass29b96ad2012-03-09 15:34:33 -0800625 base_fdt: Fdt object containing the flat device tree.
Simon Glass89b86b82011-07-17 23:49:49 -0700626
627 Returns:
628 Tuple containing:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600629 Full path to bootstub (uboot + fdt(-1)).
630 Full path to signed (uboot + fdt(flash pos) + bct).
Simon Glass89b86b82011-07-17 23:49:49 -0700631
632 Raises:
633 CmdError if a command fails.
634 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200635 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800636 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700637 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200638
639 # Make a copy of the fdt for the bootstub
640 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glass290a1802011-07-17 13:54:32 -0700641 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200642
Simon Glass89b86b82011-07-17 23:49:49 -0700643 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700644 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
645 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700646 self._tools.OutputSize('Combined binary', bootstub)
647
Simon Glasse13ee2c2011-07-28 08:12:28 +1200648 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700649 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700650 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200651 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200652
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600653 self._tools.OutputSize('Final bootstub', signed)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200654
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600655 return bootstub, signed
Simon Glass89b86b82011-07-17 23:49:49 -0700656
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600657 def _AddCbfsFiles(self, bootstub, cbfs_files):
658 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600659 for file in files:
660 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600661 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600662 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
663 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma'])
664
665 def _CreateCorebootStub(self, pack, coreboot):
666 """Create a coreboot boot stub and add pack properties.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700667
668 Args:
Aaron Durbina113f522016-01-05 09:09:55 -0600669 pack: a PackFirmware object describing the firmware image to build.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700670 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700671 """
672 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700673 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100674
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600675 pack.AddProperty('coreboot', bootstub)
676 pack.AddProperty('image', bootstub)
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700677
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600678 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600679 if self.cbfs_files:
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600680 self._AddCbfsFiles(bootstub, self.cbfs_files)
Simon Glass7e199222012-03-13 15:51:18 -0700681
Aaron Durbina113f522016-01-05 09:09:55 -0600682 # Create a coreboot copy to use as a scratch pad. Order matters. The
683 # cbfs_files were added prior to this action. That's so the RW CBFS
Patrick Georgi3a332672015-11-20 10:02:51 +0100684 # regions inherit the files from the RO CBFS region. Additionally,
685 # include the full FMAP within the file.
686 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600687 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100688 binary = self._tools.ReadFile(bootstub)
689 fmap_offset, fmap = pack.GetFmap()
690 if len(binary) < fmap_offset + len(fmap):
691 raise CmdError('FMAP will not fit')
692 # Splice in FMAP data.
693 binary = binary[:fmap_offset] + fmap + binary[fmap_offset + len(fmap):]
694 self._tools.WriteFile(cb_copy, binary)
695 # Publish where coreboot is with the FMAP data.
696 pack.AddProperty('cb_with_fmap', cb_copy)
Aaron Durbina113f522016-01-05 09:09:55 -0600697
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600698 # Add files to to RO CBFS if provided. This done here such that the
699 # copy above does not contain the RO CBFS files.
700 if self.rocbfs_files:
701 self._AddCbfsFiles(bootstub, self.rocbfs_files)
702
Aaron Durbina113f522016-01-05 09:09:55 -0600703
Simon Glass89b86b82011-07-17 23:49:49 -0700704 def _PackOutput(self, msg):
705 """Helper function to write output from PackFirmware (verbose level 2).
706
707 This is passed to PackFirmware for it to use to write output.
708
709 Args:
710 msg: Message to display.
711 """
712 self._out.Notice(msg)
713
Aaron Durbin80564452015-12-21 15:25:06 -0600714 def _FmapNameByPath(self, path):
715 """ Take list of names to form node path. Return FMAP name.
716
717 Obtain the FMAP name described by the node path.
718
719 Args:
720 path: list forming a node path.
721
722 Returns:
723 FMAP name of fdt node.
724
725 Raises:
726 CmdError if path not found.
727 """
728 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
729 return re.sub('-', '_', lbl).upper()
730
731 def _PrepareCbfsHash(self, pack, blob_name):
732 """Create blob in rw-{a,b}-boothash with 'cbfstool hashcbfs'.
733
734 When the blob name is defined as cbfshash/<section>/<subsection>, fill the
735 <section>_<subsection> area in the flash map with CBFS hash generated
736 using the 'cbfstool hashcbfs' command.
737
738 Args:
739 pack: a PackFirmware object describing the firmware image to build.
740 blob_name: a string, blob name describing what FMAP section this CBFS
741 copy is destined to
742 Raises:
743 CmdError if cbfs-files node has incorrect parameters.
744 BlobDeferral if the CBFS region is not populated yet or if the coreboot
745 image with fmap is not available yet.
746 """
747 cb_copy = pack.GetProperty('cb_with_fmap')
748 if cb_copy is None:
749 raise BlobDeferral("Waiting for '%s'" % cb_copy)
750
751 part_sections = blob_name.split('/')[1:]
752 fmap_dst = self._FmapNameByPath(part_sections)
753
754 # Example of FDT ndoes asking for CBFS hash:
755 # rw-b-boot {
756 # label = "fw-main-b";
757 # reg = <0x00700000 0x002dff80>;
758 # type = "blob cbfs/rw/b-boot";
759 # };
760 # rw-b-boothash {
761 # label = "fw-main-b-hash";
762 # reg = <0x009dff80 0x00000040>;
763 # type = "blob cbfshash/rw/b-boothash";
764 # cbfs-node = "cbfs/rw/b-boot";
765 # };
766 hash_node = self.fdt.GetFlashNode(*part_sections)
767 cbfs_blob_name = self.fdt.GetString(hash_node, 'cbfs-node')
768
769 if not pack.GetProperty(cbfs_blob_name):
770 raise BlobDeferral("Waiting for '%s'" % cbfs_blob_name)
771
772 cbfs_node_path = cbfs_blob_name.split('/')[1:]
773 fmap_src = self._FmapNameByPath(cbfs_node_path)
774
775 # Compute CBFS hash and place it in the corect spot.
776 self._tools.Run('cbfstool', [cb_copy, 'hashcbfs', '-r', fmap_dst,
777 '-R', fmap_src, '-A', 'sha256'])
778
779 # Base address and size of the desitnation partition
780 base, size = self.fdt.GetFlashPart(*part_sections)
781
782 # And extract the blob for the FW section
783 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
784 self._tools.WriteFile(rw_section,
785 self._tools.ReadFile(cb_copy)[base:base+size])
786
787 pack.AddProperty(blob_name, rw_section)
788
789
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800790 def _PrepareCbfs(self, pack, blob_name):
791 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
792
793 When the blob name is defined as cbfs#<section>#<subsection>, fill the
794 <section>_<subsection> area in the flash map with a CBFS copy, putting the
795 CBFS header of the copy at the base of the section.
796
797 If --coreboot-elf parameter was specified during cros_bumdle_firmware
798 invocation, add the parameter of this option as the payload to the new
799 CBFS instance.
800
801 Args:
802 pack: a PackFirmware object describing the firmware image to build.
803 blob_name: a string, blob name describing what FMAP section this CBFS
804 copy is destined to
805 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100806 CmdError if cbfs-files node has incorrect parameters.
Aaron Durbina113f522016-01-05 09:09:55 -0600807 BlobDeferral if coreboot image with fmap is not available yet.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800808 """
Patrick Georgi3a332672015-11-20 10:02:51 +0100809 cb_copy = pack.GetProperty('cb_with_fmap')
Aaron Durbina113f522016-01-05 09:09:55 -0600810 if cb_copy is None:
Patrick Georgi3a332672015-11-20 10:02:51 +0100811 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800812
813 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600814 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800815
816 # Base address and size of the desitnation partition
817 base, size = self.fdt.GetFlashPart(*part_sections)
818
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800819 # Add coreboot payload if so requested. Note that the some images use
820 # different payload for the rw sections, which is passed in as the value
821 # of the --uboot option in the command line.
822 if self.uboot_fname:
823 payload_fname = self.uboot_fname
824 elif self.coreboot_elf:
825 payload_fname = self.coreboot_elf
826 else:
827 payload_fname = None
828
829 if payload_fname:
830 self._tools.Run('cbfstool', [
831 cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100832 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800833
Patrick Georgi964fb542015-10-16 16:52:03 +0200834 if self.ecrw_fname:
835 self._tools.Run('cbfstool', [
836 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100837 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200838
839 if self.pdrw_fname:
840 self._tools.Run('cbfstool', [
841 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100842 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200843
Aaron Durbin880cf952016-01-27 14:11:38 -0600844 # Parse the file list to obtain the last entry. If its empty use its
845 # offset as the size of the CBFS to hash.
846 stdout = self._tools.Run('cbfstool',
847 [ cb_copy, 'print', '-k', '-r', fmap_dst ])
848 # Fields are tab separated in the following order.
849 # Name Offset Type Metadata Size Data Size Total Size
850 last_entry = stdout.strip().splitlines()[-1].split('\t')
851 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
852 size = int(last_entry[1], 16)
853
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800854 # And extract the blob for the FW section
855 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
856 self._tools.WriteFile(rw_section,
857 self._tools.ReadFile(cb_copy)[base:base+size])
858
859 pack.AddProperty(blob_name, rw_section)
860
861
Simon Glass439fe7a2012-03-09 16:19:34 -0800862 def _BuildBlob(self, pack, fdt, blob_type):
863 """Build the blob data for a particular blob type.
864
865 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700866 pack: a PackFirmware object describing the firmware image to build.
867 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800868 blob_type: The type of blob to create data for. Supported types are:
869 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
870 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700871
872 Raises:
873 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -0600874 BlobDeferral if a blob is waiting for a dependency.
Simon Glass439fe7a2012-03-09 16:19:34 -0800875 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700876 # stupid pylint insists that sha256 is not in hashlib.
877 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800878 if blob_type == 'coreboot':
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600879 self._CreateCorebootStub(pack, self.coreboot_fname)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700880 elif blob_type == 'legacy':
881 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800882 elif blob_type == 'signed':
Simon Glass942bedb2016-05-14 16:19:59 -0600883 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt, None)
Simon Glass439fe7a2012-03-09 16:19:34 -0800884 pack.AddProperty('bootstub', bootstub)
885 pack.AddProperty('signed', signed)
886 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700887 elif blob_type == 'exynos-bl1':
888 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700889
890 # TODO(sjg@chromium.org): Deprecate ecbin
891 elif blob_type in ['ecrw', 'ecbin']:
892 pack.AddProperty('ecrw', self.ecrw_fname)
893 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700894 elif blob_type == 'pdrw':
895 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800896 elif blob_type == 'ecrwhash':
897 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
898 ecrw = self._tools.ReadFile(self.ecrw_fname)
899 hasher = hashlib.sha256()
900 hasher.update(ecrw)
901 self._tools.WriteFile(ec_hash_file, hasher.digest())
902 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700903 elif blob_type == 'pdrwhash':
904 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
905 pdrw = self._tools.ReadFile(self.pdrw_fname)
906 hasher = hashlib.sha256()
907 hasher.update(pdrw)
908 self._tools.WriteFile(pd_hash_file, hasher.digest())
909 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700910 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700911 # crosbug.com/p/13143
912 # We cannot have an fmap in the EC image since there can be only one,
913 # which is the main fmap describing the whole image.
914 # Ultimately the EC will not have an fmap, since with software sync
915 # there is no flashrom involvement in updating the EC flash, and thus
916 # no need for the fmap.
917 # For now, mangle the fmap name to avoid problems.
918 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
919 data = self._tools.ReadFile(self.ecro_fname)
920 data = re.sub('__FMAP__', '__fMAP__', data)
921 self._tools.WriteFile(updated_ecro, data)
922 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600923 elif blob_type.startswith('exynos-bl2'):
924 # We need to configure this per node, so do it later
925 pass
Aaron Durbin80564452015-12-21 15:25:06 -0600926 elif blob_type.startswith('cbfshash'):
927 self._PrepareCbfsHash(pack, blob_type)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800928 elif blob_type.startswith('cbfs'):
929 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800930 elif pack.GetProperty(blob_type):
931 pass
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700932 elif blob_type == 'ifwi' or blob_type == 'sig2':
933 # Copy IFWI/CSE_SIGN(sig2) regions from coreboot copy and build a blob
934 # for the blob_type
935 cb_copy = pack.GetProperty('cb_with_fmap')
936 if cb_copy is None:
937 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
938 blob_start, blob_size = fdt.GetFlashPart('ro', blob_type)
939 blob_file = blob_type + '.bin'
940 blob_path = os.path.join(self._tools.outdir, blob_file)
941 data = self._tools.ReadFile(cb_copy)
942 self._tools.WriteFile(blob_path, data[blob_start:blob_start+blob_size])
943 pack.AddProperty(blob_type, blob_path)
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800944 elif blob_type in self.blobs:
945 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800946 else:
947 raise CmdError("Unknown blob type '%s' required in flash map" %
948 blob_type)
949
Aaron Durbin41c85b62015-12-17 17:40:29 -0600950 def _BuildBlobs(self, pack, fdt):
951 """Build the blob data for the list of blobs in the pack.
952
953 Args:
954 pack: a PackFirmware object describing the firmware image to build.
955 fdt: an fdt object including image layout information
956
957 Raises:
958 CmdError if a command fails.
959 BlobDeferral if dependencies cannot be met because of cycles.
960 """
961 blob_list = pack.GetBlobList()
962 self._out.Info('Building blobs %s\n' % blob_list)
963
964 complete = False
965 deferred_list = []
966
967 # Build blobs allowing for dependencies between blobs. While this is
968 # an potential O(n^2) operation, in practice most blobs aren't dependent
969 # and should resolve in a few passes.
970 while not complete:
971 orig = set(blob_list)
972 for blob_type in blob_list:
973 try:
974 self._BuildBlob(pack, fdt, blob_type)
975 except (BlobDeferral):
976 deferred_list.append(blob_type)
977 if not deferred_list:
978 complete = True
979 # If deferred is the same as the original no progress is being made.
980 if not orig - set(deferred_list):
981 raise BlobDeferral("Blob cyle '%s'" % orig)
982 # Process the deferred blobs
983 blob_list = deferred_list[:]
984 deferred_list = []
985
Simon Glass290a1802011-07-17 13:54:32 -0700986 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700987 """Create a full firmware image, along with various by-products.
988
989 This uses the provided u-boot.bin, fdt and bct to create a firmware
990 image containing all the required parts. If the GBB is not supplied
991 then this will just return a signed U-Boot as the image.
992
993 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700994 gbb: a string, full path to the GBB file, or empty if a GBB is not
995 required.
996 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200997
998 Returns:
999 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001000 """
Simon Glass02d124a2012-03-02 14:47:20 -08001001 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001002
Simon Glass439fe7a2012-03-09 16:19:34 -08001003 pack = PackFirmware(self._tools, self._out)
Simon Glass00d027e2013-07-20 14:51:12 -06001004 if self._force_efs:
1005 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -06001006 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
1007 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001008
Simon Glass4f318912013-07-20 16:13:06 -06001009 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -08001010
1011 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001012 if self.uboot_fname:
1013 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001014 if self.skeleton_fname:
1015 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001016 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001017
Simon Glassde9c8072012-07-02 22:29:02 -07001018 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1019 if self.kernel_fname:
1020 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1021
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001022 if gbb:
1023 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -06001024
1025 # Build the blobs out.
1026 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -07001027
Simon Glass7306b902012-12-17 15:06:21 -08001028 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001029 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001030 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001031 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001032 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001033 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001034 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001035 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001036 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001037
Simon Glass0a047bc2013-07-19 15:44:43 -06001038 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001039 todo = pack.GetMissingBlobs()
1040 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001041 if blob.key.startswith('exynos-bl2'):
1042 bl2 = ExynosBl2(self._tools, self._out)
1043 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1044 self.exynos_bl2))
1045
Simon Glassc90cf582012-03-13 15:40:47 -07001046 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001047
1048 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001049 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001050
Simon Glass4c24f662013-07-19 15:53:02 -06001051 # Recalculate the Exynos BL2, since it may have a hash. The call to
1052 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1053 # need to recalculate the hash.
1054 for blob in todo:
1055 if blob.key.startswith('exynos-bl2'):
1056 bl2 = ExynosBl2(self._tools, self._out)
1057 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1058 self.exynos_bl2))
1059
Simon Glass6207efe2012-12-17 15:04:36 -08001060 # Make a copy of the fdt for the bootstub
1061 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001062 if self.uboot_fname:
1063 uboot_data = self._tools.ReadFile(self.uboot_fname)
1064 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1065 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001066
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001067 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1068 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001069
Simon Glassa10282a2013-01-08 17:06:41 -08001070 # Fix up the coreboot image here, since we can't do this until we have
1071 # a final device tree binary.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001072 if 'coreboot' in pack.GetBlobList():
Simon Glasscbc83552012-07-23 15:26:22 +01001073 bootstub = pack.GetProperty('coreboot')
1074 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001075 if self.coreboot_elf:
1076 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1077 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001078 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001079 text_base = 0x1110000
1080
1081 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1082 # 1110015: 66 bb 00 01 mov $0x100,%bx
1083 marker = struct.pack('<L', 0x0100bb66)
1084 pos = uboot_data.find(marker)
1085 if pos == -1 or pos > 0x100:
1086 raise ValueError('Cannot find U-Boot cold boot entry point')
1087 entry = text_base + pos
1088 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001089 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1090 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001091 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001092 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1093 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001094 data = self._tools.ReadFile(bootstub)
1095 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1096 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001097
Julius Werneraa1fe942014-11-21 17:16:11 -08001098 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1099 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1100 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001101
Simon Glass208ad952013-02-10 11:16:46 -08001102 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001103 image = os.path.join(self._tools.outdir, 'image.bin')
1104 pack.PackImage(self._tools.outdir, image)
1105 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001106
Simon Glass439fe7a2012-03-09 16:19:34 -08001107 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001108 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001109 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001110
Simon Glassdedda6f2013-02-09 13:44:14 -08001111 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001112 """Select an FDT to control the firmware bundling
1113
Simon Glassdedda6f2013-02-09 13:44:14 -08001114 We make a copy of this which will include any on-the-fly changes we want
1115 to make.
1116
Simon Glass290a1802011-07-17 13:54:32 -07001117 Args:
1118 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001119 use_defaults: True to use a default FDT name if available, and to add
1120 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001121
Simon Glassc0f3dc62011-08-09 14:19:05 -07001122 Returns:
1123 The Fdt object of the original fdt file, which we will not modify.
1124
Simon Glassdedda6f2013-02-09 13:44:14 -08001125 Raises:
1126 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1127 False).
Simon Glass290a1802011-07-17 13:54:32 -07001128 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001129 if use_defaults:
1130 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001131 if not fdt_fname:
1132 raise ValueError('Please provide an FDT filename')
1133 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001134 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001135
1136 # For upstream, select the correct architecture .dtsi manually.
1137 if self._board == 'link' or 'x86' in self._board:
1138 arch_dts = 'coreboot.dtsi'
1139 elif self._board == 'daisy':
1140 arch_dts = 'exynos5250.dtsi'
1141 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001142 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001143
1144 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001145 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1146
Patrick Georgicebb5a22016-08-15 19:07:02 +02001147 if fdt.GetProp('/flash', 'reg', ''):
1148 raise ValueError('fmap.dts /flash is deprecated. Use chromeos.fmd')
1149
1150 # fill in /flash from binary fmap
1151 # ignore "read-only" attribute, that isn't used anywhere
Julius Wernerbcf0c942016-09-07 16:57:40 -07001152 bootblock_range = None
1153 coreboot_range = None
Patrick Georgicebb5a22016-08-15 19:07:02 +02001154 fmap_blob = open(self.coreboot_fname).read()
1155 f = fmap.fmap_decode(fmap_blob)
1156 fdt.PutString('/flash', 'compatible', 'chromeos,flashmap')
1157 fdt.PutIntList('/flash', 'reg', [f['base'], f['size']])
1158 for area in f['areas']:
1159 label = re.sub('_', '-', area['name']).lower()
1160 fdt_path = '/flash/' + label
1161 slot=label[-1]
1162 if label == 'gbb':
1163 fdt_path = '/flash/ro-gbb'
1164 fdt.PutString(fdt_path, 'type', 'blob gbb')
1165 elif label == 'fmap':
1166 fdt_path = '/flash/ro-fmap'
1167 fdt.PutString(fdt_path, 'type', 'fmap')
1168 fdt.PutIntList(fdt_path, 'ver-major', [1])
1169 fdt.PutIntList(fdt_path, 'ver-minor', [0])
Julius Wernerbcf0c942016-09-07 16:57:40 -07001170 elif label == 'bootblock':
1171 bootblock_range = [area['offset'], area['size']]
1172 continue
Patrick Georgicebb5a22016-08-15 19:07:02 +02001173 elif label == 'coreboot':
Julius Wernerbcf0c942016-09-07 16:57:40 -07001174 coreboot_range = [area['offset'], area['size']]
1175 continue
Patrick Georgicebb5a22016-08-15 19:07:02 +02001176 elif label == 'si-desc':
1177 fdt.PutString(fdt_path, 'type', 'ifd')
1178 elif label == 'rw-shared':
1179 fdt_path = '/flash/shared-section'
1180 elif label == 'rw-section-'+slot:
1181 fdt_path = '/flash/rw-'+slot
1182 elif label == 'rw-legacy' and self.seabios_fname:
1183 fdt.PutString(fdt_path, 'type', 'blob legacy')
1184 elif label in ['rw-mrc-cache', 'rw-elog', 'rw-legacy',
1185 'rw-vpd', 'rw-unused', 'ro-vpd', 'ro-unused',
1186 'ro-frid-pad', 'bios-unusable', 'device-extension',
1187 'unused-hole', 'rw-gpt-primary', 'rw-gpt-secondary',
1188 'rw-nvram', 'ro-unused-1', 'ro-unused-2']:
1189 fdt.PutString(fdt_path, 'type', 'wiped')
1190 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
1191 elif label == 'shared-data':
1192 fdt.PutString(fdt_path, 'type', 'wiped')
1193 fdt.PutIntList(fdt_path, 'wipe-value', [0])
1194 elif label == 'vblock-dev':
1195 fdt_path = '/flash/rw-vblock-dev'
1196 fdt.PutString(fdt_path, 'type', 'wiped')
1197 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
1198 elif label[:-1] == 'vblock-':
1199 fdt_path = '/flash/rw-'+slot+'-vblock'
1200 fdt.PutString(fdt_path, 'type', 'keyblock cbfs/rw/'+slot+'-boot')
1201 fdt.PutString(fdt_path, 'keyblock', 'firmware.keyblock')
1202 fdt.PutString(fdt_path, 'signprivate', 'firmware_data_key.vbprivk')
1203 fdt.PutString(fdt_path, 'kernelkey', 'kernel_subkey.vbpubk')
1204 fdt.PutIntList(fdt_path, 'version', [1])
1205 fdt.PutIntList(fdt_path, 'preamble-flags', [0])
1206 elif label[:-1] == 'fw-main-':
1207 fdt_path = '/flash/rw-'+slot+'-boot'
1208 fdt.PutString(fdt_path, 'type', 'blob cbfs/rw/'+slot+'-boot')
1209 elif label[:-1] == 'rw-fwid-':
1210 fdt_path = '/flash/rw-'+slot+'-firmware-id'
1211 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
1212 elif label == 'ro-frid':
1213 fdt_path = '/flash/ro-firmware-id'
1214 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
1215 elif label == 'ifwi':
1216 fdt_path = '/flash/ro-ifwi'
1217 fdt.PutString(fdt_path, 'type', 'blob ifwi')
1218 elif label == 'sign-cse':
1219 fdt_path = '/flash/ro-sig'
1220 fdt.PutString(fdt_path, 'type', 'blob sig2')
1221 # white list for empty regions
Patrick Georgi56dc9202016-09-07 21:12:04 +02001222 elif label in ['bootblock', 'misc-rw', 'ro-section', 'rw-environment',
1223 'rw-gpt', 'si-all', 'si-bios', 'si-me', 'wp-ro']:
Patrick Georgicebb5a22016-08-15 19:07:02 +02001224 pass
1225 else:
1226 raise ValueError('encountered label "'+label+'" in binary fmap. '+
1227 'Check chromeos.fmd')
1228 fdt.PutString(fdt_path, 'label', label)
1229 fdt.PutIntList(fdt_path, 'reg', [area['offset'], area['size']])
1230
Julius Wernerbcf0c942016-09-07 16:57:40 -07001231 if coreboot_range is not None:
1232 if bootblock_range is not None:
1233 if bootblock_range[0] + bootblock_range[1] != coreboot_range[0]:
1234 raise ValueError('Cannot combine BOOTBLOCK and COREBOOT')
1235 coreboot_range[0] = bootblock_range[0]
1236 coreboot_range[1] += bootblock_range[1]
1237 fdt_path = '/flash/ro-boot'
1238 fdt.PutString(fdt_path, 'type', 'blob coreboot')
1239 fdt.PutString(fdt_path, 'label', 'coreboot')
1240 fdt.PutIntList(fdt_path, 'reg', [coreboot_range[0], coreboot_range[1]])
1241
Simon Glass7df773b2013-08-25 18:02:29 -06001242 # Remember our board type.
1243 fdt.PutString('/chromeos-config', 'board', self._board)
1244
Simon Glasse53abbc2013-08-21 22:29:55 -06001245 self.fdt = fdt
1246 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001247
Simon Glassc90cf582012-03-13 15:40:47 -07001248 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001249 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001250
1251 - Checks options, tools, output directory, fdt.
1252 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001253
1254 Args:
Simon Glass56577572011-07-19 11:08:06 +12001255 hardware_id: Hardware ID to use for this board. If None, then the
1256 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001257 output_fname: Output filename for the image. If this is not None, then
1258 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001259 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001260
1261 Returns:
1262 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001263 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001264 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1265 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1266 else:
Simon Glass56577572011-07-19 11:08:06 +12001267 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001268
1269 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001270 image, pack = self._CreateImage(gbb, self.fdt)
1271 if show_map:
1272 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001273 if output_fname:
1274 shutil.copyfile(image, output_fname)
1275 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001276 return image, pack.props