blob: 82350fa5f489fdab70637fff860f4a70749f3e84 [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.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700110 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600111 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700112 self._gbb_flags = None
113 self._keydir = None
114 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700115 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700116 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800117 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700118 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700119 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700120 self.ecro_fname = None # Filename of EC read-only file
121 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700122 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700123 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
124 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700125 self.fdt = None # Our Fdt object.
126 self.kernel_fname = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700127 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700128 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700129 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700130
131 def SetDirs(self, keydir):
132 """Set up directories required for Bundle.
133
134 Args:
135 keydir: Directory containing keys to use for signing firmware.
136 """
137 self._keydir = keydir
138
Simon Glass6dcc2f22011-07-28 15:26:49 +1200139 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800140 coreboot_elf=None,
Simon Glass942bedb2016-05-14 16:19:59 -0600141 seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700142 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600143 kernel=None, blobs=None, skip_bmpblk=False, cbfs_files=None,
144 rocbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700145 """Set up files required for Bundle.
146
147 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500148 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700149 uboot: The filename of the u-boot.bin image to use.
150 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800151 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800152 coreboot: The filename of the coreboot image to use (on x86).
153 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Vincent Palatinf7286772011-10-12 14:31:53 -0700154 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700155 exynos_bl1: The filename of the exynos BL1 file
156 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
157 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700158 ecrw: The filename of the EC (Embedded Controller) read-write file.
159 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700160 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700161 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800162 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800163 skip_bmpblk: True if no bmpblk is required
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600164 cbfs_files: Root directory of files to be stored in RO and RW CBFS
165 rocbfs_files: Root directory of files to be stored in RO CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700166 """
167 self._board = board
168 self.uboot_fname = uboot
169 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800170 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700171 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800172 self.coreboot_elf = coreboot_elf
Vincent Palatinf7286772011-10-12 14:31:53 -0700173 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700174 self.exynos_bl1 = exynos_bl1
175 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700176 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700177 self.ecrw_fname = ecrw
178 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700179 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700180 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800181 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800182 self.skip_bmpblk = skip_bmpblk
Daisuke Nojiri69662892015-09-25 15:24:04 -0700183 self.cbfs_files = cbfs_files
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600184 self.rocbfs_files = rocbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700185
Simon Glass00d027e2013-07-20 14:51:12 -0600186 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700187 """Set up options supported by Bundle.
188
189 Args:
190 small: Only create a signed U-Boot - don't produce the full packed
191 firmware image. This is useful for devs who want to replace just the
192 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700193 gbb_flags: Specification for string containing adjustments to make.
194 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600195 force_efs: Force firmware to use 'early firmware selection' feature,
196 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700197 """
198 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700199 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700200 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600201 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700202
Simon Glass22f39fb2013-02-09 13:44:14 -0800203 def _GetBuildRoot(self):
204 """Get the path to this board's 'firmware' directory.
205
206 Returns:
207 Path to firmware directory, with ## representing the path to the
208 chroot.
209 """
Simon Glass290a1802011-07-17 13:54:32 -0700210 if not self._board:
211 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800212 return os.path.join('##', 'build', self._board, 'firmware')
213
214 def _CheckFdtFilename(self, fname):
215 """Check provided FDT filename and return the correct name if needed.
216
217 Where the filename lacks a path, add a default path for this board.
218 Where no FDT filename is provided, select a default one for this board.
219
220 Args:
221 fname: Proposed FDT filename.
222
223 Returns:
224 Selected FDT filename, after validation.
225 """
226 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700227 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800228 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700229 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700230 base_name = re.sub('_', '-', self._board)
231
232 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700233 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700234 found_list = glob.glob(self._tools.Filename(wildcard))
235 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800236 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700237 else:
238 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700239 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700240
Simon Glass881964d2012-04-04 11:34:09 -0700241 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800242 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700243 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700244 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800245 return fname
246
247 def CheckOptions(self):
248 """Check provided options and select defaults."""
249 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700250
Simon Glass49b026b2013-04-26 16:38:42 -0700251 board_type = self._board.split('_')[0]
252 model = type_to_model.get(board_type)
253
Simon Glass290a1802011-07-17 13:54:32 -0700254 if not self.uboot_fname:
255 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
256 if not self.bct_fname:
257 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700258 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700259 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700260 if model:
261 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700262 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700263 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700264 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700265 if not self.coreboot_fname:
266 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
267 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700268 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Simon Glassbe0bc002012-08-16 12:50:48 -0700269 if not self.ecrw_fname:
270 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700271 if not self.pdrw_fname:
272 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700273 if not self.ecro_fname:
274 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700275
Simon Glass75759302012-03-15 20:26:53 -0700276 def GetFiles(self):
277 """Get a list of files that we know about.
278
279 This is the opposite of SetFiles except that we may have put in some
280 default names. It returns a dictionary containing the filename for
281 each of a number of pre-defined files.
282
283 Returns:
284 Dictionary, with one entry for each file.
285 """
286 file_list = {
287 'bct' : self.bct_fname,
288 'exynos-bl1' : self.exynos_bl1,
289 'exynos-bl2' : self.exynos_bl2,
290 }
291 return file_list
292
Simon Glass4a887b12012-10-23 16:29:03 -0700293 def DecodeGBBFlagsFromFdt(self):
294 """Get Google Binary Block flags from the FDT.
295
296 These should be in the chromeos-config node, like this:
297
298 chromeos-config {
299 gbb-flag-dev-screen-short-delay;
300 gbb-flag-force-dev-switch-on;
301 gbb-flag-force-dev-boot-usb;
302 gbb-flag-disable-fw-rollback-check;
303 };
304
305 Returns:
306 GBB flags value from FDT.
307 """
308 chromeos_config = self.fdt.GetProps("/chromeos-config")
309 gbb_flags = 0
310 for name in chromeos_config:
311 if name.startswith('gbb-flag-'):
312 flag_value = gbb_flag_properties.get(name[9:])
313 if flag_value:
314 gbb_flags |= flag_value
315 self._out.Notice("FDT: Enabling %s." % name)
316 else:
317 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
318 return gbb_flags
319
Simon Glass157c0662012-10-23 13:52:42 -0700320 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
321 """Decode ajustments to the provided GBB flags.
322
323 We support three options:
324
325 hex value: c2
326 defined value: force-dev-boot-usb,load-option-roms
327 adjust default value: -load-option-roms,+force-dev-boot-usb
328
329 The last option starts from the passed-in GBB flags and adds or removes
330 flags.
331
332 Args:
333 gbb_flags: Base (default) FDT flags.
334 adjustments: String containing adjustments to make.
335
336 Returns:
337 Updated FDT flags.
338 """
339 use_base_value = True
340 if adjustments:
341 try:
342 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700343 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700344 pass
345 for flag in adjustments.split(','):
346 oper = None
347 if flag[0] in ['-', '+']:
348 oper = flag[0]
349 flag = flag[1:]
350 value = gbb_flag_properties.get(flag)
351 if not value:
352 raise ValueError("Invalid GBB flag '%s'" % flag)
353 if oper == '+':
354 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800355 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700356 elif oper == '-':
357 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800358 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700359 else:
360 if use_base_value:
361 gbb_flags = 0
362 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800363 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700364 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800365 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700366
367 return gbb_flags
368
Simon Glass56577572011-07-19 11:08:06 +1200369 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700370 """Create a GBB for the image.
371
Simon Glass56577572011-07-19 11:08:06 +1200372 Args:
373 hardware_id: Hardware ID to use for this board. If None, then the
374 default from the Fdt will be used
375
Simon Glass89b86b82011-07-17 23:49:49 -0700376 Returns:
377 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700378 """
Simon Glass56577572011-07-19 11:08:06 +1200379 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800380 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700381 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700382 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700383
Simon Glass4a887b12012-10-23 16:29:03 -0700384 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800385
Simon Glass157c0662012-10-23 13:52:42 -0700386 # Allow command line to override flags
387 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
388
Simon Glass4a887b12012-10-23 16:29:03 -0700389 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700390 self._out.Progress('Creating GBB')
Daisuke Nojiri10b193f2016-01-15 17:53:14 -0800391 if self.skip_bmpblk:
392 bmpfv_size = 0
393 else:
394 bmpfv_size = gbb_size - 0x2180
395 sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700396 sizes = ['%#x' % size for size in sizes]
397 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700398 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800399
400 gbb_set_command = ['-s',
401 '--hwid=%s' % hardware_id,
402 '--rootkey=%s/root_key.vbpubk' % keydir,
403 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
404 '--flags=%d' % gbb_flags,
405 gbb]
406 if not self.skip_bmpblk:
407 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
408 self.bmpblk_fname),]
409
Simon Glass290a1802011-07-17 13:54:32 -0700410 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800411 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700412 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700413
Simon Glasse13ee2c2011-07-28 08:12:28 +1200414 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700415 """Sign an image so that the Tegra SOC will boot it.
416
417 Args:
418 bct: BCT file to use.
419 bootstub: Boot stub (U-Boot + fdt) file to sign.
420 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700421
422 Returns:
423 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700424 """
425 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200426 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700427 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200428 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700429 fd = open(config, 'w')
430 fd.write('Version = 1;\n')
431 fd.write('Redundancy = 1;\n')
432 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700433
434 # TODO(dianders): Right now, we don't have enough space in our flash map
435 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
436 # sure what this does for reliability, but at least things will fit...
437 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
438 if is_nand:
439 fd.write('Bctcopy = 1;\n')
440
Simon Glass89b86b82011-07-17 23:49:49 -0700441 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
442 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700443
Simon Glass89b86b82011-07-17 23:49:49 -0700444 fd.close()
445
446 self._tools.Run('cbootimage', [config, signed])
447 self._tools.OutputSize('BCT', bct)
448 self._tools.OutputSize('Signed image', signed)
449 return signed
450
Doug Anderson86ce5f42011-07-27 10:40:18 -0700451 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700452 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700453
454 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700455 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700456 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700457 """
Simon Glass468d8752012-09-19 16:36:19 -0700458 if bootcmd is not None:
459 if bootcmd == 'none':
460 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800461 self.fdt.PutString('/config', 'bootcmd', bootcmd)
462 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700463 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700464
Simon Glassa4934b72012-05-09 13:35:02 -0700465 def SetNodeEnabled(self, node_name, enabled):
466 """Set whether an node is enabled or disabled.
467
468 This simply sets the 'status' property of a node to "ok", or "disabled".
469
470 The node should either be a full path to the node (like '/uart@10200000')
471 or an alias property.
472
473 Aliases are supported like this:
474
475 aliases {
476 console = "/uart@10200000";
477 };
478
479 pointing to a node:
480
481 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700482 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700483 };
484
485 In this case, this function takes the name of the alias ('console' in
486 this case) and updates the status of the node that is pointed to, to
487 either ok or disabled. If the alias does not exist, a warning is
488 displayed.
489
490 Args:
491 node_name: Name of node (e.g. '/uart@10200000') or alias alias
492 (e.g. 'console') to adjust
493 enabled: True to enable, False to disable
494 """
495 # Look up the alias if this is an alias reference
496 if not node_name.startswith('/'):
497 lookup = self.fdt.GetString('/aliases', node_name, '')
498 if not lookup:
499 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
500 return
501 node_name = lookup
502 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700503 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700504 else:
505 status = 'disabled'
506 self.fdt.PutString(node_name, 'status', status)
507
508 def AddEnableList(self, enable_list):
509 """Process a list of nodes to enable/disable.
510
511 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700512 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700513 tuple:
514 node: The fdt node to write to will be <node> or pointed to by
515 /aliases/<node>. We can tell which
516 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700517
Vadim Bendebury507c0012013-06-09 12:49:25 -0700518 Raises:
519 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700520 """
521 if enable_list:
522 for node_name, enabled in enable_list:
523 try:
524 enabled = int(enabled)
525 if enabled not in (0, 1):
526 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700527 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700528 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700529 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700530 self.SetNodeEnabled(node_name, enabled)
531
Simon Glass290a1802011-07-17 13:54:32 -0700532 def AddConfigList(self, config_list, use_int=False):
533 """Add a list of config items to the fdt.
534
535 Normally these values are written to the fdt as strings, but integers
536 are also supported, in which case the values will be converted to integers
537 (if necessary) before being stored.
538
539 Args:
540 config_list: List of (config, value) tuples to add to the fdt. For each
541 tuple:
542 config: The fdt node to write to will be /config/<config>.
543 value: An integer or string value to write.
544 use_int: True to only write integer values.
545
546 Raises:
547 CmdError: if a value is required to be converted to integer but can't be.
548 """
549 if config_list:
550 for config in config_list:
551 value = config[1]
552 if use_int:
553 try:
554 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700555 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700556 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700557 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700558 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800559 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700560 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800561 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700562
Simon Glass7c2d5572011-11-15 14:47:08 -0800563 def DecodeTextBase(self, data):
564 """Look at a U-Boot image and try to decode its TEXT_BASE.
565
566 This works because U-Boot has a header with the value 0x12345678
567 immediately followed by the TEXT_BASE value. We can therefore read this
568 from the image with some certainty. We check only the first 40 words
569 since the header should be within that region.
570
Simon Glass96b50302012-07-20 06:55:28 +0100571 Since upstream Tegra has moved to having a 16KB SPL region at the start,
572 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
573 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
574
Simon Glass7c2d5572011-11-15 14:47:08 -0800575 Args:
576 data: U-Boot binary data
577
578 Returns:
579 Text base (integer) or None if none was found
580 """
581 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100582 for start in (0, 0x4000):
583 for i in range(start, start + 160, 4):
584 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800585
Simon Glass96b50302012-07-20 06:55:28 +0100586 # TODO(sjg): This does not cope with a big-endian target
587 value = struct.unpack('<I', word)[0]
588 if found:
589 return value - start
590 if value == 0x12345678:
591 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800592
593 return None
594
595 def CalcTextBase(self, name, fdt, fname):
596 """Calculate the TEXT_BASE to use for U-Boot.
597
598 Normally this value is in the fdt, so we just read it from there. But as
599 a second check we look at the image itself in case this is different, and
600 switch to that if it is.
601
602 This allows us to flash any U-Boot even if its TEXT_BASE is different.
603 This is particularly useful with upstream U-Boot which uses a different
604 value (which we will move to).
605 """
606 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800607 # The value that comes back from fdt.GetInt is signed, which makes no
608 # sense for an address base. Force it to unsigned.
609 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800610 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100611 text_base_str = '%#x' % text_base if text_base else 'None'
612 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
613 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800614
615 # If they are different, issue a warning and switch over.
616 if text_base and text_base != fdt_text_base:
617 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
618 "fdt value of %x. Using %x" % (text_base, name,
619 fdt_text_base, text_base))
620 fdt_text_base = text_base
621 return fdt_text_base
622
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600623 def _CreateBootStub(self, uboot, base_fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700624 """Create a boot stub and a signed boot stub.
625
626 Args:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600627 uboot: Path to u-boot.bin (may be chroot-relative).
Simon Glass29b96ad2012-03-09 15:34:33 -0800628 base_fdt: Fdt object containing the flat device tree.
Simon Glass89b86b82011-07-17 23:49:49 -0700629
630 Returns:
631 Tuple containing:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600632 Full path to bootstub (uboot + fdt(-1)).
633 Full path to signed (uboot + fdt(flash pos) + bct).
Simon Glass89b86b82011-07-17 23:49:49 -0700634
635 Raises:
636 CmdError if a command fails.
637 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200638 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800639 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700640 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200641
642 # Make a copy of the fdt for the bootstub
643 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glass290a1802011-07-17 13:54:32 -0700644 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200645
Simon Glass89b86b82011-07-17 23:49:49 -0700646 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700647 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
648 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700649 self._tools.OutputSize('Combined binary', bootstub)
650
Simon Glasse13ee2c2011-07-28 08:12:28 +1200651 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700652 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700653 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200654 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200655
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600656 self._tools.OutputSize('Final bootstub', signed)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200657
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600658 return bootstub, signed
Simon Glass89b86b82011-07-17 23:49:49 -0700659
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600660 def _AddCbfsFiles(self, bootstub, cbfs_files):
661 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600662 for file in files:
663 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600664 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600665 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
666 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma'])
667
668 def _CreateCorebootStub(self, pack, coreboot):
669 """Create a coreboot boot stub and add pack properties.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700670
671 Args:
Aaron Durbina113f522016-01-05 09:09:55 -0600672 pack: a PackFirmware object describing the firmware image to build.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700673 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700674 """
675 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700676 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100677
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600678 pack.AddProperty('coreboot', bootstub)
679 pack.AddProperty('image', bootstub)
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700680
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600681 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600682 if self.cbfs_files:
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600683 self._AddCbfsFiles(bootstub, self.cbfs_files)
Simon Glass7e199222012-03-13 15:51:18 -0700684
Aaron Durbina113f522016-01-05 09:09:55 -0600685 # Create a coreboot copy to use as a scratch pad. Order matters. The
686 # cbfs_files were added prior to this action. That's so the RW CBFS
Patrick Georgi3a332672015-11-20 10:02:51 +0100687 # regions inherit the files from the RO CBFS region. Additionally,
688 # include the full FMAP within the file.
689 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600690 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100691 binary = self._tools.ReadFile(bootstub)
692 fmap_offset, fmap = pack.GetFmap()
693 if len(binary) < fmap_offset + len(fmap):
694 raise CmdError('FMAP will not fit')
695 # Splice in FMAP data.
696 binary = binary[:fmap_offset] + fmap + binary[fmap_offset + len(fmap):]
697 self._tools.WriteFile(cb_copy, binary)
698 # Publish where coreboot is with the FMAP data.
699 pack.AddProperty('cb_with_fmap', cb_copy)
Aaron Durbina113f522016-01-05 09:09:55 -0600700
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600701 # Add files to to RO CBFS if provided. This done here such that the
702 # copy above does not contain the RO CBFS files.
703 if self.rocbfs_files:
704 self._AddCbfsFiles(bootstub, self.rocbfs_files)
705
Aaron Durbina113f522016-01-05 09:09:55 -0600706
Simon Glass89b86b82011-07-17 23:49:49 -0700707 def _PackOutput(self, msg):
708 """Helper function to write output from PackFirmware (verbose level 2).
709
710 This is passed to PackFirmware for it to use to write output.
711
712 Args:
713 msg: Message to display.
714 """
715 self._out.Notice(msg)
716
Aaron Durbin80564452015-12-21 15:25:06 -0600717 def _FmapNameByPath(self, path):
718 """ Take list of names to form node path. Return FMAP name.
719
720 Obtain the FMAP name described by the node path.
721
722 Args:
723 path: list forming a node path.
724
725 Returns:
726 FMAP name of fdt node.
727
728 Raises:
729 CmdError if path not found.
730 """
731 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
732 return re.sub('-', '_', lbl).upper()
733
734 def _PrepareCbfsHash(self, pack, blob_name):
735 """Create blob in rw-{a,b}-boothash with 'cbfstool hashcbfs'.
736
737 When the blob name is defined as cbfshash/<section>/<subsection>, fill the
738 <section>_<subsection> area in the flash map with CBFS hash generated
739 using the 'cbfstool hashcbfs' command.
740
741 Args:
742 pack: a PackFirmware object describing the firmware image to build.
743 blob_name: a string, blob name describing what FMAP section this CBFS
744 copy is destined to
745 Raises:
746 CmdError if cbfs-files node has incorrect parameters.
747 BlobDeferral if the CBFS region is not populated yet or if the coreboot
748 image with fmap is not available yet.
749 """
750 cb_copy = pack.GetProperty('cb_with_fmap')
751 if cb_copy is None:
752 raise BlobDeferral("Waiting for '%s'" % cb_copy)
753
754 part_sections = blob_name.split('/')[1:]
755 fmap_dst = self._FmapNameByPath(part_sections)
756
757 # Example of FDT ndoes asking for CBFS hash:
758 # rw-b-boot {
759 # label = "fw-main-b";
760 # reg = <0x00700000 0x002dff80>;
761 # type = "blob cbfs/rw/b-boot";
762 # };
763 # rw-b-boothash {
764 # label = "fw-main-b-hash";
765 # reg = <0x009dff80 0x00000040>;
766 # type = "blob cbfshash/rw/b-boothash";
767 # cbfs-node = "cbfs/rw/b-boot";
768 # };
769 hash_node = self.fdt.GetFlashNode(*part_sections)
770 cbfs_blob_name = self.fdt.GetString(hash_node, 'cbfs-node')
771
772 if not pack.GetProperty(cbfs_blob_name):
773 raise BlobDeferral("Waiting for '%s'" % cbfs_blob_name)
774
775 cbfs_node_path = cbfs_blob_name.split('/')[1:]
776 fmap_src = self._FmapNameByPath(cbfs_node_path)
777
778 # Compute CBFS hash and place it in the corect spot.
779 self._tools.Run('cbfstool', [cb_copy, 'hashcbfs', '-r', fmap_dst,
780 '-R', fmap_src, '-A', 'sha256'])
781
782 # Base address and size of the desitnation partition
783 base, size = self.fdt.GetFlashPart(*part_sections)
784
785 # And extract the blob for the FW section
786 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
787 self._tools.WriteFile(rw_section,
788 self._tools.ReadFile(cb_copy)[base:base+size])
789
790 pack.AddProperty(blob_name, rw_section)
791
792
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800793 def _PrepareCbfs(self, pack, blob_name):
794 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
795
796 When the blob name is defined as cbfs#<section>#<subsection>, fill the
797 <section>_<subsection> area in the flash map with a CBFS copy, putting the
798 CBFS header of the copy at the base of the section.
799
800 If --coreboot-elf parameter was specified during cros_bumdle_firmware
801 invocation, add the parameter of this option as the payload to the new
802 CBFS instance.
803
804 Args:
805 pack: a PackFirmware object describing the firmware image to build.
806 blob_name: a string, blob name describing what FMAP section this CBFS
807 copy is destined to
808 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100809 CmdError if cbfs-files node has incorrect parameters.
Aaron Durbina113f522016-01-05 09:09:55 -0600810 BlobDeferral if coreboot image with fmap is not available yet.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800811 """
Patrick Georgi3a332672015-11-20 10:02:51 +0100812 cb_copy = pack.GetProperty('cb_with_fmap')
Aaron Durbina113f522016-01-05 09:09:55 -0600813 if cb_copy is None:
Patrick Georgi3a332672015-11-20 10:02:51 +0100814 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800815
816 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600817 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800818
819 # Base address and size of the desitnation partition
820 base, size = self.fdt.GetFlashPart(*part_sections)
821
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800822 # Add coreboot payload if so requested. Note that the some images use
823 # different payload for the rw sections, which is passed in as the value
824 # of the --uboot option in the command line.
825 if self.uboot_fname:
826 payload_fname = self.uboot_fname
827 elif self.coreboot_elf:
828 payload_fname = self.coreboot_elf
829 else:
830 payload_fname = None
831
832 if payload_fname:
833 self._tools.Run('cbfstool', [
834 cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100835 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800836
Patrick Georgi964fb542015-10-16 16:52:03 +0200837 if self.ecrw_fname:
838 self._tools.Run('cbfstool', [
839 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100840 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200841
842 if self.pdrw_fname:
843 self._tools.Run('cbfstool', [
844 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100845 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200846
Aaron Durbin880cf952016-01-27 14:11:38 -0600847 # Parse the file list to obtain the last entry. If its empty use its
848 # offset as the size of the CBFS to hash.
849 stdout = self._tools.Run('cbfstool',
850 [ cb_copy, 'print', '-k', '-r', fmap_dst ])
851 # Fields are tab separated in the following order.
852 # Name Offset Type Metadata Size Data Size Total Size
853 last_entry = stdout.strip().splitlines()[-1].split('\t')
854 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
855 size = int(last_entry[1], 16)
856
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800857 # And extract the blob for the FW section
858 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
859 self._tools.WriteFile(rw_section,
860 self._tools.ReadFile(cb_copy)[base:base+size])
861
862 pack.AddProperty(blob_name, rw_section)
863
864
Simon Glass439fe7a2012-03-09 16:19:34 -0800865 def _BuildBlob(self, pack, fdt, blob_type):
866 """Build the blob data for a particular blob type.
867
868 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700869 pack: a PackFirmware object describing the firmware image to build.
870 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800871 blob_type: The type of blob to create data for. Supported types are:
872 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
873 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700874
875 Raises:
876 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -0600877 BlobDeferral if a blob is waiting for a dependency.
Simon Glass439fe7a2012-03-09 16:19:34 -0800878 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700879 # stupid pylint insists that sha256 is not in hashlib.
880 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800881 if blob_type == 'coreboot':
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600882 self._CreateCorebootStub(pack, self.coreboot_fname)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700883 elif blob_type == 'legacy':
884 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800885 elif blob_type == 'signed':
Simon Glass942bedb2016-05-14 16:19:59 -0600886 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt, None)
Simon Glass439fe7a2012-03-09 16:19:34 -0800887 pack.AddProperty('bootstub', bootstub)
888 pack.AddProperty('signed', signed)
889 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700890 elif blob_type == 'exynos-bl1':
891 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700892
893 # TODO(sjg@chromium.org): Deprecate ecbin
894 elif blob_type in ['ecrw', 'ecbin']:
895 pack.AddProperty('ecrw', self.ecrw_fname)
896 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700897 elif blob_type == 'pdrw':
898 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800899 elif blob_type == 'ecrwhash':
900 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
901 ecrw = self._tools.ReadFile(self.ecrw_fname)
902 hasher = hashlib.sha256()
903 hasher.update(ecrw)
904 self._tools.WriteFile(ec_hash_file, hasher.digest())
905 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700906 elif blob_type == 'pdrwhash':
907 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
908 pdrw = self._tools.ReadFile(self.pdrw_fname)
909 hasher = hashlib.sha256()
910 hasher.update(pdrw)
911 self._tools.WriteFile(pd_hash_file, hasher.digest())
912 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700913 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700914 # crosbug.com/p/13143
915 # We cannot have an fmap in the EC image since there can be only one,
916 # which is the main fmap describing the whole image.
917 # Ultimately the EC will not have an fmap, since with software sync
918 # there is no flashrom involvement in updating the EC flash, and thus
919 # no need for the fmap.
920 # For now, mangle the fmap name to avoid problems.
921 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
922 data = self._tools.ReadFile(self.ecro_fname)
923 data = re.sub('__FMAP__', '__fMAP__', data)
924 self._tools.WriteFile(updated_ecro, data)
925 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600926 elif blob_type.startswith('exynos-bl2'):
927 # We need to configure this per node, so do it later
928 pass
Aaron Durbin80564452015-12-21 15:25:06 -0600929 elif blob_type.startswith('cbfshash'):
930 self._PrepareCbfsHash(pack, blob_type)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800931 elif blob_type.startswith('cbfs'):
932 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800933 elif pack.GetProperty(blob_type):
934 pass
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700935 elif blob_type == 'ifwi' or blob_type == 'sig2':
936 # Copy IFWI/CSE_SIGN(sig2) regions from coreboot copy and build a blob
937 # for the blob_type
938 cb_copy = pack.GetProperty('cb_with_fmap')
939 if cb_copy is None:
940 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
941 blob_start, blob_size = fdt.GetFlashPart('ro', blob_type)
942 blob_file = blob_type + '.bin'
943 blob_path = os.path.join(self._tools.outdir, blob_file)
944 data = self._tools.ReadFile(cb_copy)
945 self._tools.WriteFile(blob_path, data[blob_start:blob_start+blob_size])
946 pack.AddProperty(blob_type, blob_path)
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800947 elif blob_type in self.blobs:
948 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800949 else:
950 raise CmdError("Unknown blob type '%s' required in flash map" %
951 blob_type)
952
Aaron Durbin41c85b62015-12-17 17:40:29 -0600953 def _BuildBlobs(self, pack, fdt):
954 """Build the blob data for the list of blobs in the pack.
955
956 Args:
957 pack: a PackFirmware object describing the firmware image to build.
958 fdt: an fdt object including image layout information
959
960 Raises:
961 CmdError if a command fails.
962 BlobDeferral if dependencies cannot be met because of cycles.
963 """
964 blob_list = pack.GetBlobList()
965 self._out.Info('Building blobs %s\n' % blob_list)
966
967 complete = False
968 deferred_list = []
969
970 # Build blobs allowing for dependencies between blobs. While this is
971 # an potential O(n^2) operation, in practice most blobs aren't dependent
972 # and should resolve in a few passes.
973 while not complete:
974 orig = set(blob_list)
975 for blob_type in blob_list:
976 try:
977 self._BuildBlob(pack, fdt, blob_type)
978 except (BlobDeferral):
979 deferred_list.append(blob_type)
980 if not deferred_list:
981 complete = True
982 # If deferred is the same as the original no progress is being made.
983 if not orig - set(deferred_list):
984 raise BlobDeferral("Blob cyle '%s'" % orig)
985 # Process the deferred blobs
986 blob_list = deferred_list[:]
987 deferred_list = []
988
Simon Glass290a1802011-07-17 13:54:32 -0700989 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700990 """Create a full firmware image, along with various by-products.
991
992 This uses the provided u-boot.bin, fdt and bct to create a firmware
993 image containing all the required parts. If the GBB is not supplied
994 then this will just return a signed U-Boot as the image.
995
996 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700997 gbb: a string, full path to the GBB file, or empty if a GBB is not
998 required.
999 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +12001000
1001 Returns:
1002 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001003 """
Simon Glass02d124a2012-03-02 14:47:20 -08001004 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001005
Simon Glass439fe7a2012-03-09 16:19:34 -08001006 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -08001007 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001008 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
1009 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -06001010 if self._force_efs:
1011 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -06001012 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
1013 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001014
Simon Glass4f318912013-07-20 16:13:06 -06001015 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -08001016
1017 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001018 if self.uboot_fname:
1019 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001020 if self.skeleton_fname:
1021 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001022 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001023
Simon Glassde9c8072012-07-02 22:29:02 -07001024 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1025 if self.kernel_fname:
1026 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1027
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001028 if gbb:
1029 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -06001030
1031 # Build the blobs out.
1032 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -07001033
Simon Glass7306b902012-12-17 15:06:21 -08001034 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001035 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001036 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001037 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001038 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001039 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001040 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001041 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001042 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001043
Simon Glass0a047bc2013-07-19 15:44:43 -06001044 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001045 todo = pack.GetMissingBlobs()
1046 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001047 if blob.key.startswith('exynos-bl2'):
1048 bl2 = ExynosBl2(self._tools, self._out)
1049 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1050 self.exynos_bl2))
1051
Simon Glassc90cf582012-03-13 15:40:47 -07001052 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001053
1054 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001055 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001056
Simon Glass4c24f662013-07-19 15:53:02 -06001057 # Recalculate the Exynos BL2, since it may have a hash. The call to
1058 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1059 # need to recalculate the hash.
1060 for blob in todo:
1061 if blob.key.startswith('exynos-bl2'):
1062 bl2 = ExynosBl2(self._tools, self._out)
1063 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1064 self.exynos_bl2))
1065
Simon Glass6207efe2012-12-17 15:04:36 -08001066 # Make a copy of the fdt for the bootstub
1067 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001068 if self.uboot_fname:
1069 uboot_data = self._tools.ReadFile(self.uboot_fname)
1070 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1071 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001072
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001073 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1074 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001075
Simon Glassa10282a2013-01-08 17:06:41 -08001076 # Fix up the coreboot image here, since we can't do this until we have
1077 # a final device tree binary.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001078 if 'coreboot' in pack.GetBlobList():
Simon Glasscbc83552012-07-23 15:26:22 +01001079 bootstub = pack.GetProperty('coreboot')
1080 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001081 if self.coreboot_elf:
1082 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1083 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001084 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001085 text_base = 0x1110000
1086
1087 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1088 # 1110015: 66 bb 00 01 mov $0x100,%bx
1089 marker = struct.pack('<L', 0x0100bb66)
1090 pos = uboot_data.find(marker)
1091 if pos == -1 or pos > 0x100:
1092 raise ValueError('Cannot find U-Boot cold boot entry point')
1093 entry = text_base + pos
1094 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001095 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1096 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001097 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001098 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1099 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001100 data = self._tools.ReadFile(bootstub)
1101 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1102 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001103
Julius Werneraa1fe942014-11-21 17:16:11 -08001104 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1105 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1106 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001107
Simon Glass208ad952013-02-10 11:16:46 -08001108 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001109 image = os.path.join(self._tools.outdir, 'image.bin')
1110 pack.PackImage(self._tools.outdir, image)
1111 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001112
Simon Glass439fe7a2012-03-09 16:19:34 -08001113 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001114 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001115 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001116
Simon Glassdedda6f2013-02-09 13:44:14 -08001117 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001118 """Select an FDT to control the firmware bundling
1119
Simon Glassdedda6f2013-02-09 13:44:14 -08001120 We make a copy of this which will include any on-the-fly changes we want
1121 to make.
1122
Simon Glass290a1802011-07-17 13:54:32 -07001123 Args:
1124 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001125 use_defaults: True to use a default FDT name if available, and to add
1126 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001127
Simon Glassc0f3dc62011-08-09 14:19:05 -07001128 Returns:
1129 The Fdt object of the original fdt file, which we will not modify.
1130
Simon Glassdedda6f2013-02-09 13:44:14 -08001131 Raises:
1132 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1133 False).
Simon Glass290a1802011-07-17 13:54:32 -07001134 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001135 if use_defaults:
1136 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001137 if not fdt_fname:
1138 raise ValueError('Please provide an FDT filename')
1139 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001140 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001141
1142 # For upstream, select the correct architecture .dtsi manually.
1143 if self._board == 'link' or 'x86' in self._board:
1144 arch_dts = 'coreboot.dtsi'
1145 elif self._board == 'daisy':
1146 arch_dts = 'exynos5250.dtsi'
1147 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001148 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001149
1150 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001151 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1152
Patrick Georgicebb5a22016-08-15 19:07:02 +02001153 if fdt.GetProp('/flash', 'reg', ''):
1154 raise ValueError('fmap.dts /flash is deprecated. Use chromeos.fmd')
1155
1156 # fill in /flash from binary fmap
1157 # ignore "read-only" attribute, that isn't used anywhere
1158 fmap_blob = open(self.coreboot_fname).read()
1159 f = fmap.fmap_decode(fmap_blob)
1160 fdt.PutString('/flash', 'compatible', 'chromeos,flashmap')
1161 fdt.PutIntList('/flash', 'reg', [f['base'], f['size']])
1162 for area in f['areas']:
1163 label = re.sub('_', '-', area['name']).lower()
1164 fdt_path = '/flash/' + label
1165 slot=label[-1]
1166 if label == 'gbb':
1167 fdt_path = '/flash/ro-gbb'
1168 fdt.PutString(fdt_path, 'type', 'blob gbb')
1169 elif label == 'fmap':
1170 fdt_path = '/flash/ro-fmap'
1171 fdt.PutString(fdt_path, 'type', 'fmap')
1172 fdt.PutIntList(fdt_path, 'ver-major', [1])
1173 fdt.PutIntList(fdt_path, 'ver-minor', [0])
1174 elif label == 'coreboot':
1175 fdt_path = '/flash/ro-boot'
1176 fdt.PutString(fdt_path, 'type', 'blob coreboot')
1177 elif label == 'si-desc':
1178 fdt.PutString(fdt_path, 'type', 'ifd')
1179 elif label == 'rw-shared':
1180 fdt_path = '/flash/shared-section'
1181 elif label == 'rw-section-'+slot:
1182 fdt_path = '/flash/rw-'+slot
1183 elif label == 'rw-legacy' and self.seabios_fname:
1184 fdt.PutString(fdt_path, 'type', 'blob legacy')
1185 elif label in ['rw-mrc-cache', 'rw-elog', 'rw-legacy',
1186 'rw-vpd', 'rw-unused', 'ro-vpd', 'ro-unused',
1187 'ro-frid-pad', 'bios-unusable', 'device-extension',
1188 'unused-hole', 'rw-gpt-primary', 'rw-gpt-secondary',
1189 'rw-nvram', 'ro-unused-1', 'ro-unused-2']:
1190 fdt.PutString(fdt_path, 'type', 'wiped')
1191 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
1192 elif label == 'shared-data':
1193 fdt.PutString(fdt_path, 'type', 'wiped')
1194 fdt.PutIntList(fdt_path, 'wipe-value', [0])
1195 elif label == 'vblock-dev':
1196 fdt_path = '/flash/rw-vblock-dev'
1197 fdt.PutString(fdt_path, 'type', 'wiped')
1198 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
1199 elif label[:-1] == 'vblock-':
1200 fdt_path = '/flash/rw-'+slot+'-vblock'
1201 fdt.PutString(fdt_path, 'type', 'keyblock cbfs/rw/'+slot+'-boot')
1202 fdt.PutString(fdt_path, 'keyblock', 'firmware.keyblock')
1203 fdt.PutString(fdt_path, 'signprivate', 'firmware_data_key.vbprivk')
1204 fdt.PutString(fdt_path, 'kernelkey', 'kernel_subkey.vbpubk')
1205 fdt.PutIntList(fdt_path, 'version', [1])
1206 fdt.PutIntList(fdt_path, 'preamble-flags', [0])
1207 elif label[:-1] == 'fw-main-':
1208 fdt_path = '/flash/rw-'+slot+'-boot'
1209 fdt.PutString(fdt_path, 'type', 'blob cbfs/rw/'+slot+'-boot')
1210 elif label[:-1] == 'rw-fwid-':
1211 fdt_path = '/flash/rw-'+slot+'-firmware-id'
1212 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
1213 elif label == 'ro-frid':
1214 fdt_path = '/flash/ro-firmware-id'
1215 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
1216 elif label == 'ifwi':
1217 fdt_path = '/flash/ro-ifwi'
1218 fdt.PutString(fdt_path, 'type', 'blob ifwi')
1219 elif label == 'sign-cse':
1220 fdt_path = '/flash/ro-sig'
1221 fdt.PutString(fdt_path, 'type', 'blob sig2')
1222 # white list for empty regions
1223 elif label in ['bootblock', 'ro-section', 'rw-environment', 'rw-gpt',
1224 'si-all', 'si-bios', 'si-me', 'wp-ro']:
1225 pass
1226 else:
1227 raise ValueError('encountered label "'+label+'" in binary fmap. '+
1228 'Check chromeos.fmd')
1229 fdt.PutString(fdt_path, 'label', label)
1230 fdt.PutIntList(fdt_path, 'reg', [area['offset'], area['size']])
1231
Simon Glass7df773b2013-08-25 18:02:29 -06001232 # Remember our board type.
1233 fdt.PutString('/chromeos-config', 'board', self._board)
1234
Simon Glasse53abbc2013-08-21 22:29:55 -06001235 self.fdt = fdt
1236 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001237
Simon Glassc90cf582012-03-13 15:40:47 -07001238 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001239 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001240
1241 - Checks options, tools, output directory, fdt.
1242 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001243
1244 Args:
Simon Glass56577572011-07-19 11:08:06 +12001245 hardware_id: Hardware ID to use for this board. If None, then the
1246 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001247 output_fname: Output filename for the image. If this is not None, then
1248 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001249 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001250
1251 Returns:
1252 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001253 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001254 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1255 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1256 else:
Simon Glass56577572011-07-19 11:08:06 +12001257 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001258
1259 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001260 image, pack = self._CreateImage(gbb, self.fdt)
1261 if show_map:
1262 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001263 if output_fname:
1264 shutil.copyfile(image, output_fname)
1265 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001266 return image, pack.props