blob: 2717dae645654771aef07fb1ea437d6ed4b2b4ab [file] [log] [blame]
Simon Glass89b86b82011-07-17 23:49:49 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05005"""This module builds a firmware image.
Simon Glass89b86b82011-07-17 23:49:49 -07006
7This modules uses a few rudimentary other libraries for its activity.
8
9Here are the names we give to the various files we deal with. It is important
10to keep these consistent!
11
12 uboot u-boot.bin (with no device tree)
13 fdt the fdt blob
14 bct the BCT file
15 bootstub uboot + fdt
16 signed (uboot + fdt + bct) signed blob
17"""
18
Simon Glassceff3ff2012-04-04 11:23:45 -070019import glob
Gabe Blackcdbdfe12013-02-06 05:37:52 -080020import hashlib
Simon Glass89b86b82011-07-17 23:49:49 -070021import os
22import re
23
Simon Glass89b86b82011-07-17 23:49:49 -070024from fdt import Fdt
25from pack_firmware import PackFirmware
26import shutil
Simon Glass7c2d5572011-11-15 14:47:08 -080027import struct
Vadim Bendebury8c35e2e2014-05-06 12:55:50 -070028from flashmaps import default_flashmaps
Simon Glass439fe7a2012-03-09 16:19:34 -080029from tools import CmdError
Vadim Bendeburyb12e3352013-06-08 17:25:19 -070030from exynos import ExynosBl2
Simon Glass89b86b82011-07-17 23:49:49 -070031
32# This data is required by bmpblk_utility. Does it ever change?
33# It was stored with the chromeos-bootimage ebuild, but we want
34# this utility to work outside the chroot.
35yaml_data = '''
36bmpblock: 1.0
37
38images:
39 devmode: DeveloperBmp/DeveloperBmp.bmp
40 recovery: RecoveryBmp/RecoveryBmp.bmp
41 rec_yuck: RecoveryNoOSBmp/RecoveryNoOSBmp.bmp
42 rec_insert: RecoveryMissingOSBmp/RecoveryMissingOSBmp.bmp
43
44screens:
45 dev_en:
46 - [0, 0, devmode]
47 rec_en:
48 - [0, 0, recovery]
49 yuck_en:
50 - [0, 0, rec_yuck]
51 ins_en:
52 - [0, 0, rec_insert]
53
54localizations:
55 - [ dev_en, rec_en, yuck_en, ins_en ]
56'''
57
Simon Glass4a887b12012-10-23 16:29:03 -070058# Build GBB flags.
59# (src/platform/vboot_reference/firmware/include/gbb_header.h)
60gbb_flag_properties = {
61 'dev-screen-short-delay': 0x00000001,
62 'load-option-roms': 0x00000002,
63 'enable-alternate-os': 0x00000004,
64 'force-dev-switch-on': 0x00000008,
65 'force-dev-boot-usb': 0x00000010,
66 'disable-fw-rollback-check': 0x00000020,
67 'enter-triggers-tonorm': 0x00000040,
68 'force-dev-boot-legacy': 0x00000080,
Shawn Nematbakhsh07c19882014-08-19 10:21:59 -070069 'faft-key-overide': 0x00000100,
70 'disable-ec-software-sync': 0x00000200,
71 'default-dev-boot-legacy': 0x00000400,
72 'disable-pd-software-sync': 0x00000800,
Furquan Shaikhd4eac3b2015-05-15 18:05:09 -070073 'force-dev-boot-fastboot-full-cap': 0x00002000,
Mary Ruthvena759c322015-11-16 08:23:26 -080074 'enable-serial': 0x00004000,
Simon Glass4a887b12012-10-23 16:29:03 -070075}
76
Simon Glass49b026b2013-04-26 16:38:42 -070077# Maps board name to Exynos product number
78type_to_model = {
79 'peach' : '5420',
80 'daisy' : '5250'
81}
82
Simon Glass5076a7f2012-10-23 16:31:54 -070083def ListGoogleBinaryBlockFlags():
84 """Print out a list of GBB flags."""
85 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
86 for name, value in gbb_flag_properties.iteritems():
87 print ' %-30s %02x' % (name, value)
88
Simon Glass89b86b82011-07-17 23:49:49 -070089class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070090 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070091
Simon Glass290a1802011-07-17 13:54:32 -070092 Sequence of events:
93 bundle = Bundle(tools.Tools(), cros_output.Output())
94 bundle.SetDirs(...)
95 bundle.SetFiles(...)
96 bundle.SetOptions(...)
97 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070098 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070099 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -0700100
Simon Glass290a1802011-07-17 13:54:32 -0700101 Public properties:
102 fdt: The fdt object that we use for building our image. This wil be the
103 one specified by the user, except that we might add config options
104 to it. This is set up by SelectFdt() which must be called before
105 bundling starts.
106 uboot_fname: Full filename of the U-Boot binary we use.
107 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700108 spl_source: Source device to load U-Boot from, in SPL:
109 straps: Select device according to CPU strap pins
110 spi: Boot from SPI
111 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700112
113 Private attributes:
114 _small: True to create a 'small' signed U-Boot, False to produce a
115 full image. The small U-Boot is enough to boot but will not have
116 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700117 """
Simon Glass89b86b82011-07-17 23:49:49 -0700118
Simon Glass290a1802011-07-17 13:54:32 -0700119 def __init__(self, tools, output):
120 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700121
Simon Glass290a1802011-07-17 13:54:32 -0700122 Args:
123 tools: A tools.Tools object to use for external tools.
124 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700125 """
Simon Glass290a1802011-07-17 13:54:32 -0700126 self._tools = tools
127 self._out = output
128
129 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500130 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700131 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700132 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600133 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700134 self._gbb_flags = None
135 self._keydir = None
136 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700137 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700138 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800139 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700140 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700141 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700142 self.ecro_fname = None # Filename of EC read-only file
143 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700144 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700145 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
146 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700147 self.fdt = None # Our Fdt object.
148 self.kernel_fname = None
149 self.postload_fname = None
150 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700151 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700152 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700153
154 def SetDirs(self, keydir):
155 """Set up directories required for Bundle.
156
157 Args:
158 keydir: Directory containing keys to use for signing firmware.
159 """
160 self._keydir = keydir
161
Simon Glass6dcc2f22011-07-28 15:26:49 +1200162 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800163 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700164 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700165 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Daisuke Nojiri69662892015-09-25 15:24:04 -0700166 kernel=None, blobs=None, skip_bmpblk=False, cbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700167 """Set up files required for Bundle.
168
169 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500170 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700171 uboot: The filename of the u-boot.bin image to use.
172 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800173 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800174 coreboot: The filename of the coreboot image to use (on x86).
175 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200176 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700177 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700178 exynos_bl1: The filename of the exynos BL1 file
179 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
180 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700181 ecrw: The filename of the EC (Embedded Controller) read-write file.
182 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700183 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700184 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800185 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800186 skip_bmpblk: True if no bmpblk is required
Daisuke Nojiri69662892015-09-25 15:24:04 -0700187 cbfs_files: Root directory of files to be stored in CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700188 """
189 self._board = board
190 self.uboot_fname = uboot
191 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800192 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700193 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800194 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200195 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700196 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700197 self.exynos_bl1 = exynos_bl1
198 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700199 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700200 self.ecrw_fname = ecrw
201 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700202 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700203 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800204 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800205 self.skip_bmpblk = skip_bmpblk
Daisuke Nojiri69662892015-09-25 15:24:04 -0700206 self.cbfs_files = cbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700207
Simon Glass00d027e2013-07-20 14:51:12 -0600208 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700209 """Set up options supported by Bundle.
210
211 Args:
212 small: Only create a signed U-Boot - don't produce the full packed
213 firmware image. This is useful for devs who want to replace just the
214 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700215 gbb_flags: Specification for string containing adjustments to make.
216 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600217 force_efs: Force firmware to use 'early firmware selection' feature,
218 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700219 """
220 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700221 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700222 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600223 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700224
Simon Glass22f39fb2013-02-09 13:44:14 -0800225 def _GetBuildRoot(self):
226 """Get the path to this board's 'firmware' directory.
227
228 Returns:
229 Path to firmware directory, with ## representing the path to the
230 chroot.
231 """
Simon Glass290a1802011-07-17 13:54:32 -0700232 if not self._board:
233 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800234 return os.path.join('##', 'build', self._board, 'firmware')
235
236 def _CheckFdtFilename(self, fname):
237 """Check provided FDT filename and return the correct name if needed.
238
239 Where the filename lacks a path, add a default path for this board.
240 Where no FDT filename is provided, select a default one for this board.
241
242 Args:
243 fname: Proposed FDT filename.
244
245 Returns:
246 Selected FDT filename, after validation.
247 """
248 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700249 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800250 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700251 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700252 base_name = re.sub('_', '-', self._board)
253
254 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700255 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700256 found_list = glob.glob(self._tools.Filename(wildcard))
257 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800258 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700259 else:
260 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700261 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700262
Simon Glass881964d2012-04-04 11:34:09 -0700263 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800264 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700265 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700266 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800267 return fname
268
269 def CheckOptions(self):
270 """Check provided options and select defaults."""
271 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700272
Simon Glass49b026b2013-04-26 16:38:42 -0700273 board_type = self._board.split('_')[0]
274 model = type_to_model.get(board_type)
275
Simon Glass290a1802011-07-17 13:54:32 -0700276 if not self.uboot_fname:
277 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
278 if not self.bct_fname:
279 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700280 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700281 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700282 if model:
283 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700284 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700285 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700286 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700287 if not self.coreboot_fname:
288 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
289 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700290 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700291 if not self.seabios_fname:
292 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700293 if not self.ecrw_fname:
294 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700295 if not self.pdrw_fname:
296 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700297 if not self.ecro_fname:
298 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700299
Simon Glass75759302012-03-15 20:26:53 -0700300 def GetFiles(self):
301 """Get a list of files that we know about.
302
303 This is the opposite of SetFiles except that we may have put in some
304 default names. It returns a dictionary containing the filename for
305 each of a number of pre-defined files.
306
307 Returns:
308 Dictionary, with one entry for each file.
309 """
310 file_list = {
311 'bct' : self.bct_fname,
312 'exynos-bl1' : self.exynos_bl1,
313 'exynos-bl2' : self.exynos_bl2,
314 }
315 return file_list
316
Simon Glass4a887b12012-10-23 16:29:03 -0700317 def DecodeGBBFlagsFromFdt(self):
318 """Get Google Binary Block flags from the FDT.
319
320 These should be in the chromeos-config node, like this:
321
322 chromeos-config {
323 gbb-flag-dev-screen-short-delay;
324 gbb-flag-force-dev-switch-on;
325 gbb-flag-force-dev-boot-usb;
326 gbb-flag-disable-fw-rollback-check;
327 };
328
329 Returns:
330 GBB flags value from FDT.
331 """
332 chromeos_config = self.fdt.GetProps("/chromeos-config")
333 gbb_flags = 0
334 for name in chromeos_config:
335 if name.startswith('gbb-flag-'):
336 flag_value = gbb_flag_properties.get(name[9:])
337 if flag_value:
338 gbb_flags |= flag_value
339 self._out.Notice("FDT: Enabling %s." % name)
340 else:
341 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
342 return gbb_flags
343
Simon Glass157c0662012-10-23 13:52:42 -0700344 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
345 """Decode ajustments to the provided GBB flags.
346
347 We support three options:
348
349 hex value: c2
350 defined value: force-dev-boot-usb,load-option-roms
351 adjust default value: -load-option-roms,+force-dev-boot-usb
352
353 The last option starts from the passed-in GBB flags and adds or removes
354 flags.
355
356 Args:
357 gbb_flags: Base (default) FDT flags.
358 adjustments: String containing adjustments to make.
359
360 Returns:
361 Updated FDT flags.
362 """
363 use_base_value = True
364 if adjustments:
365 try:
366 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700367 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700368 pass
369 for flag in adjustments.split(','):
370 oper = None
371 if flag[0] in ['-', '+']:
372 oper = flag[0]
373 flag = flag[1:]
374 value = gbb_flag_properties.get(flag)
375 if not value:
376 raise ValueError("Invalid GBB flag '%s'" % flag)
377 if oper == '+':
378 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800379 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700380 elif oper == '-':
381 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800382 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700383 else:
384 if use_base_value:
385 gbb_flags = 0
386 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800387 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700388 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800389 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700390
391 return gbb_flags
392
Simon Glass56577572011-07-19 11:08:06 +1200393 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700394 """Create a GBB for the image.
395
Simon Glass56577572011-07-19 11:08:06 +1200396 Args:
397 hardware_id: Hardware ID to use for this board. If None, then the
398 default from the Fdt will be used
399
Simon Glass89b86b82011-07-17 23:49:49 -0700400 Returns:
401 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700402 """
Simon Glass56577572011-07-19 11:08:06 +1200403 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800404 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700405 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700406 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700407
Simon Glass4a887b12012-10-23 16:29:03 -0700408 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800409
Simon Glass157c0662012-10-23 13:52:42 -0700410 # Allow command line to override flags
411 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
412
Simon Glass4a887b12012-10-23 16:29:03 -0700413 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700414 self._out.Progress('Creating GBB')
415 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
416 sizes = ['%#x' % size for size in sizes]
417 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700418 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800419
420 gbb_set_command = ['-s',
421 '--hwid=%s' % hardware_id,
422 '--rootkey=%s/root_key.vbpubk' % keydir,
423 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
424 '--flags=%d' % gbb_flags,
425 gbb]
426 if not self.skip_bmpblk:
427 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
428 self.bmpblk_fname),]
429
Simon Glass290a1802011-07-17 13:54:32 -0700430 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800431 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700432 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700433
Simon Glasse13ee2c2011-07-28 08:12:28 +1200434 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700435 """Sign an image so that the Tegra SOC will boot it.
436
437 Args:
438 bct: BCT file to use.
439 bootstub: Boot stub (U-Boot + fdt) file to sign.
440 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700441
442 Returns:
443 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700444 """
445 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200446 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700447 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200448 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700449 fd = open(config, 'w')
450 fd.write('Version = 1;\n')
451 fd.write('Redundancy = 1;\n')
452 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700453
454 # TODO(dianders): Right now, we don't have enough space in our flash map
455 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
456 # sure what this does for reliability, but at least things will fit...
457 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
458 if is_nand:
459 fd.write('Bctcopy = 1;\n')
460
Simon Glass89b86b82011-07-17 23:49:49 -0700461 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
462 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700463
Simon Glass89b86b82011-07-17 23:49:49 -0700464 fd.close()
465
466 self._tools.Run('cbootimage', [config, signed])
467 self._tools.OutputSize('BCT', bct)
468 self._tools.OutputSize('Signed image', signed)
469 return signed
470
Doug Anderson86ce5f42011-07-27 10:40:18 -0700471 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700472 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700473
474 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700475 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700476 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700477 """
Simon Glass468d8752012-09-19 16:36:19 -0700478 if bootcmd is not None:
479 if bootcmd == 'none':
480 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800481 self.fdt.PutString('/config', 'bootcmd', bootcmd)
482 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700483 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700484
Simon Glassa4934b72012-05-09 13:35:02 -0700485 def SetNodeEnabled(self, node_name, enabled):
486 """Set whether an node is enabled or disabled.
487
488 This simply sets the 'status' property of a node to "ok", or "disabled".
489
490 The node should either be a full path to the node (like '/uart@10200000')
491 or an alias property.
492
493 Aliases are supported like this:
494
495 aliases {
496 console = "/uart@10200000";
497 };
498
499 pointing to a node:
500
501 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700502 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700503 };
504
505 In this case, this function takes the name of the alias ('console' in
506 this case) and updates the status of the node that is pointed to, to
507 either ok or disabled. If the alias does not exist, a warning is
508 displayed.
509
510 Args:
511 node_name: Name of node (e.g. '/uart@10200000') or alias alias
512 (e.g. 'console') to adjust
513 enabled: True to enable, False to disable
514 """
515 # Look up the alias if this is an alias reference
516 if not node_name.startswith('/'):
517 lookup = self.fdt.GetString('/aliases', node_name, '')
518 if not lookup:
519 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
520 return
521 node_name = lookup
522 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700523 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700524 else:
525 status = 'disabled'
526 self.fdt.PutString(node_name, 'status', status)
527
528 def AddEnableList(self, enable_list):
529 """Process a list of nodes to enable/disable.
530
531 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700532 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700533 tuple:
534 node: The fdt node to write to will be <node> or pointed to by
535 /aliases/<node>. We can tell which
536 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700537
Vadim Bendebury507c0012013-06-09 12:49:25 -0700538 Raises:
539 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700540 """
541 if enable_list:
542 for node_name, enabled in enable_list:
543 try:
544 enabled = int(enabled)
545 if enabled not in (0, 1):
546 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700547 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700548 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700549 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700550 self.SetNodeEnabled(node_name, enabled)
551
Simon Glass290a1802011-07-17 13:54:32 -0700552 def AddConfigList(self, config_list, use_int=False):
553 """Add a list of config items to the fdt.
554
555 Normally these values are written to the fdt as strings, but integers
556 are also supported, in which case the values will be converted to integers
557 (if necessary) before being stored.
558
559 Args:
560 config_list: List of (config, value) tuples to add to the fdt. For each
561 tuple:
562 config: The fdt node to write to will be /config/<config>.
563 value: An integer or string value to write.
564 use_int: True to only write integer values.
565
566 Raises:
567 CmdError: if a value is required to be converted to integer but can't be.
568 """
569 if config_list:
570 for config in config_list:
571 value = config[1]
572 if use_int:
573 try:
574 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700575 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700576 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700577 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700578 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800579 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700580 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800581 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700582
Simon Glass7c2d5572011-11-15 14:47:08 -0800583 def DecodeTextBase(self, data):
584 """Look at a U-Boot image and try to decode its TEXT_BASE.
585
586 This works because U-Boot has a header with the value 0x12345678
587 immediately followed by the TEXT_BASE value. We can therefore read this
588 from the image with some certainty. We check only the first 40 words
589 since the header should be within that region.
590
Simon Glass96b50302012-07-20 06:55:28 +0100591 Since upstream Tegra has moved to having a 16KB SPL region at the start,
592 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
593 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
594
Simon Glass7c2d5572011-11-15 14:47:08 -0800595 Args:
596 data: U-Boot binary data
597
598 Returns:
599 Text base (integer) or None if none was found
600 """
601 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100602 for start in (0, 0x4000):
603 for i in range(start, start + 160, 4):
604 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800605
Simon Glass96b50302012-07-20 06:55:28 +0100606 # TODO(sjg): This does not cope with a big-endian target
607 value = struct.unpack('<I', word)[0]
608 if found:
609 return value - start
610 if value == 0x12345678:
611 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800612
613 return None
614
615 def CalcTextBase(self, name, fdt, fname):
616 """Calculate the TEXT_BASE to use for U-Boot.
617
618 Normally this value is in the fdt, so we just read it from there. But as
619 a second check we look at the image itself in case this is different, and
620 switch to that if it is.
621
622 This allows us to flash any U-Boot even if its TEXT_BASE is different.
623 This is particularly useful with upstream U-Boot which uses a different
624 value (which we will move to).
625 """
626 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800627 # The value that comes back from fdt.GetInt is signed, which makes no
628 # sense for an address base. Force it to unsigned.
629 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800630 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100631 text_base_str = '%#x' % text_base if text_base else 'None'
632 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
633 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800634
635 # If they are different, issue a warning and switch over.
636 if text_base and text_base != fdt_text_base:
637 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
638 "fdt value of %x. Using %x" % (text_base, name,
639 fdt_text_base, text_base))
640 fdt_text_base = text_base
641 return fdt_text_base
642
Simon Glass6dcc2f22011-07-28 15:26:49 +1200643 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700644 """Create a boot stub and a signed boot stub.
645
Simon Glass6dcc2f22011-07-28 15:26:49 +1200646 For postload:
647 We add a /config/postload-text-offset entry to the signed bootstub's
648 fdt so that U-Boot can find the postload code.
649
650 The raw (unsigned) bootstub will have a value of -1 for this since we will
651 simply append the postload code to the bootstub and it can find it there.
652 This will be used for RW A/B firmware.
653
654 For the signed case this value will specify where in the flash to find
655 the postload code. This will be used for RO firmware.
656
Simon Glass89b86b82011-07-17 23:49:49 -0700657 Args:
658 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800659 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200660 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700661
662 Returns:
663 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200664 Full path to bootstub (uboot + fdt(-1) + postload).
665 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700666
667 Raises:
668 CmdError if a command fails.
669 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200670 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800671 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700672 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200673
674 # Make a copy of the fdt for the bootstub
675 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700676 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700677 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200678
Simon Glass89b86b82011-07-17 23:49:49 -0700679 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700680 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
681 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700682 self._tools.OutputSize('Combined binary', bootstub)
683
Simon Glasse13ee2c2011-07-28 08:12:28 +1200684 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700685 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700686 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200687 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200688
689 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
690 data = self._tools.ReadFile(signed)
691
692 if postload:
693 # We must add postload to the bootstub since A and B will need to
694 # be able to find it without the /config/postload-text-offset mechanism.
695 bs_data = self._tools.ReadFile(bootstub)
696 bs_data += self._tools.ReadFile(postload)
697 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
698 self._tools.WriteFile(bootstub, bs_data)
699 self._tools.OutputSize('Combined binary with postload', bootstub)
700
701 # Now that we know the file size, adjust the fdt and re-sign
702 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800703 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200704 fdt_data = self._tools.ReadFile(fdt.fname)
705 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
706 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
707 postload_bootstub, text_base)
708 if len(data) != os.path.getsize(signed):
709 raise CmdError('Signed file size changed from %d to %d after updating '
710 'fdt' % (len(data), os.path.getsize(signed)))
711
712 # Re-read the signed image, and add the post-load binary.
713 data = self._tools.ReadFile(signed)
714 data += self._tools.ReadFile(postload)
715 self._tools.OutputSize('Post-load binary', postload)
716
717 self._tools.WriteFile(signed_postload, data)
718 self._tools.OutputSize('Final bootstub with postload', signed_postload)
719
720 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700721
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700722 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700723 """Create a coreboot boot stub.
724
725 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700726 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700727
728 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100729 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700730 """
731 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700732 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100733
734 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700735 return bootstub
736
Simon Glass7e199222012-03-13 15:51:18 -0700737
Simon Glass89b86b82011-07-17 23:49:49 -0700738 def _PackOutput(self, msg):
739 """Helper function to write output from PackFirmware (verbose level 2).
740
741 This is passed to PackFirmware for it to use to write output.
742
743 Args:
744 msg: Message to display.
745 """
746 self._out.Notice(msg)
747
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800748 def _PrepareCbfs(self, pack, blob_name):
749 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
750
751 When the blob name is defined as cbfs#<section>#<subsection>, fill the
752 <section>_<subsection> area in the flash map with a CBFS copy, putting the
753 CBFS header of the copy at the base of the section.
754
755 If --coreboot-elf parameter was specified during cros_bumdle_firmware
756 invocation, add the parameter of this option as the payload to the new
757 CBFS instance.
758
759 Args:
760 pack: a PackFirmware object describing the firmware image to build.
761 blob_name: a string, blob name describing what FMAP section this CBFS
762 copy is destined to
763 Raises:
764 CmdError if base coreboot image does not contain CBFS
765 """
766
767 if not self.coreboot_fname:
768 raise CmdError("coreboot file needed for blob % s", blob_name)
769
770 part_sections = blob_name.split('/')[1:]
771
772 # Base address and size of the desitnation partition
773 base, size = self.fdt.GetFlashPart(*part_sections)
774
Patrick Georgi10ea5ef2015-10-22 19:14:26 +0200775 # Check if there's an advanced CBFS configuration request
776 node = self.fdt.GetFlashNode(*part_sections)
777 try:
778 cbfs_config = self.fdt.GetProps(node + '/cbfs-files')
779 except CmdError:
780 cbfs_config = None
781
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800782 # Create a coreboot copy to use as a scratch pad.
Patrick Georgi10ea5ef2015-10-22 19:14:26 +0200783 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_copy'))
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800784 if not os.path.exists(cb_copy):
785 self._tools.WriteFile(cb_copy, self._tools.ReadFile(self.coreboot_fname))
786
787 # Copy CBFS to the required offset
788 self._tools.Run('cbfstool', [cb_copy, 'copy', '-D',
789 '%d' % base, '-s', '%d' % size])
790
791 # Add coreboot payload if so requested. Note that the some images use
792 # different payload for the rw sections, which is passed in as the value
793 # of the --uboot option in the command line.
794 if self.uboot_fname:
795 payload_fname = self.uboot_fname
796 elif self.coreboot_elf:
797 payload_fname = self.coreboot_elf
798 else:
799 payload_fname = None
800
801 if payload_fname:
802 self._tools.Run('cbfstool', [
803 cb_copy, 'add-payload', '-f', payload_fname,
804 '-n', 'fallback/payload', '-c', 'lzma' , '-H', '%d' % base])
805
Patrick Georgi964fb542015-10-16 16:52:03 +0200806 if self.ecrw_fname:
807 self._tools.Run('cbfstool', [
808 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
809 '-n', 'ecrw', '-A', 'sha256', '-H', '%d' % base ])
810
811 if self.pdrw_fname:
812 self._tools.Run('cbfstool', [
813 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
814 '-n', 'pdrw', '-A', 'sha256', '-H', '%d' % base ])
815
Patrick Georgi10ea5ef2015-10-22 19:14:26 +0200816 # add files to CBFS in RW regions more flexibly:
817 # rw-a-boot {
818 # ...
819 # cbfs-files {
820 # ecfoo = "add -n ecrw-copy -f ec.RW.bin -t raw -A sha256";
821 # };
822 # };
823 # adds a file called "ecrw-copy" of raw type to FW_MAIN_A with the
824 # content of ec.RW.bin in the build root, with a SHA256 hash.
825 # The dts property name ("ecfoo") is ignored but should be unique,
826 # all cbfstool commands that start with "add" are allowed.
827 # The second and third argument need to be "-n <cbfs file name>".
828 if cbfs_config != None:
829 # remove all files slated for addition, in case they already exist
830 for val in cbfs_config.itervalues():
831 f = val.split(' ')
832 command = f[0]
833 if command[:3] != 'add':
834 raise CmdError("first argument in '%s' must start with 'add'", f)
835 if f[1] != '-n':
836 raise CmdError("second argument in '%s' must be '-n'", f)
837 cbfsname = f[2]
838 try:
Patrick Georgie920c2b2015-12-10 21:59:56 +0100839 # Calling through shell isn't strictly necessary here, but we still
840 # do it to keep operation more similar to the invocation in the next
841 # loop.
842 self._tools.Run('sh', [ '-c',
843 ' '.join(['cbfstool', cb_copy, 'remove', '-H', '%d' % base,
844 '-n', cbfsname]) ])
Patrick Georgi10ea5ef2015-10-22 19:14:26 +0200845 except CmdError:
846 pass # the most likely error is that the file doesn't already exist
847
848 # now add the files
849 for val in cbfs_config.itervalues():
850 f = val.split(' ')
851 command = f[0]
852 cbfsname = f[2]
853 args = f[3:]
Patrick Georgie920c2b2015-12-10 21:59:56 +0100854 # Call through shell so variable expansion can happen. With a change
855 # to the ebuild this enables specifying filename arguments to
856 # cbfstool as -f romstage.elf${COREBOOT_VARIANT} and have that be
857 # resolved to romstage.elf.serial when appropriate.
858 self._tools.Run('sh', [ '-c',
859 ' '.join(['cbfstool', cb_copy, command, '-H', '%d' % base,
860 '-n', cbfsname] + args)],
861 self._tools.Filename(self._GetBuildRoot()))
Patrick Georgi10ea5ef2015-10-22 19:14:26 +0200862
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800863 # And extract the blob for the FW section
864 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
865 self._tools.WriteFile(rw_section,
866 self._tools.ReadFile(cb_copy)[base:base+size])
867
868 pack.AddProperty(blob_name, rw_section)
869
870
Simon Glass439fe7a2012-03-09 16:19:34 -0800871 def _BuildBlob(self, pack, fdt, blob_type):
872 """Build the blob data for a particular blob type.
873
874 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700875 pack: a PackFirmware object describing the firmware image to build.
876 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800877 blob_type: The type of blob to create data for. Supported types are:
878 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
879 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700880
881 Raises:
882 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800883 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700884 # stupid pylint insists that sha256 is not in hashlib.
885 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800886 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700887 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800888 pack.AddProperty('coreboot', coreboot)
889 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700890 elif blob_type == 'legacy':
891 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800892 elif blob_type == 'signed':
893 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
894 self.postload_fname)
895 pack.AddProperty('bootstub', bootstub)
896 pack.AddProperty('signed', signed)
897 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700898 elif blob_type == 'exynos-bl1':
899 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700900
901 # TODO(sjg@chromium.org): Deprecate ecbin
902 elif blob_type in ['ecrw', 'ecbin']:
903 pack.AddProperty('ecrw', self.ecrw_fname)
904 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700905 elif blob_type == 'pdrw':
906 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800907 elif blob_type == 'ecrwhash':
908 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
909 ecrw = self._tools.ReadFile(self.ecrw_fname)
910 hasher = hashlib.sha256()
911 hasher.update(ecrw)
912 self._tools.WriteFile(ec_hash_file, hasher.digest())
913 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700914 elif blob_type == 'pdrwhash':
915 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
916 pdrw = self._tools.ReadFile(self.pdrw_fname)
917 hasher = hashlib.sha256()
918 hasher.update(pdrw)
919 self._tools.WriteFile(pd_hash_file, hasher.digest())
920 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700921 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700922 # crosbug.com/p/13143
923 # We cannot have an fmap in the EC image since there can be only one,
924 # which is the main fmap describing the whole image.
925 # Ultimately the EC will not have an fmap, since with software sync
926 # there is no flashrom involvement in updating the EC flash, and thus
927 # no need for the fmap.
928 # For now, mangle the fmap name to avoid problems.
929 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
930 data = self._tools.ReadFile(self.ecro_fname)
931 data = re.sub('__FMAP__', '__fMAP__', data)
932 self._tools.WriteFile(updated_ecro, data)
933 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600934 elif blob_type.startswith('exynos-bl2'):
935 # We need to configure this per node, so do it later
936 pass
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800937 elif blob_type.startswith('cbfs'):
938 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800939 elif pack.GetProperty(blob_type):
940 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800941 elif blob_type in self.blobs:
942 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800943 else:
944 raise CmdError("Unknown blob type '%s' required in flash map" %
945 blob_type)
946
Daisuke Nojiri69662892015-09-25 15:24:04 -0700947 def _AddCbfsFiles(self, bootstub):
948 for dir, subs, files in os.walk(self.cbfs_files):
949 for file in files:
950 file = os.path.join(dir, file)
951 cbfs_name = file.replace(self.cbfs_files, '', 1).strip('/')
952 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
953 '-n', cbfs_name, '-t', '0x50', '-c', 'lzma'])
954
Simon Glass290a1802011-07-17 13:54:32 -0700955 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700956 """Create a full firmware image, along with various by-products.
957
958 This uses the provided u-boot.bin, fdt and bct to create a firmware
959 image containing all the required parts. If the GBB is not supplied
960 then this will just return a signed U-Boot as the image.
961
962 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700963 gbb: a string, full path to the GBB file, or empty if a GBB is not
964 required.
965 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200966
967 Returns:
968 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700969 """
Simon Glass02d124a2012-03-02 14:47:20 -0800970 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700971
Simon Glass439fe7a2012-03-09 16:19:34 -0800972 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -0800973 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700974 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
975 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -0600976 if self._force_efs:
977 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -0600978 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
979 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800980
Simon Glass4f318912013-07-20 16:13:06 -0600981 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800982
983 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800984 if self.uboot_fname:
985 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800986 if self.skeleton_fname:
987 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700988 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700989
Simon Glassde9c8072012-07-02 22:29:02 -0700990 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
991 if self.kernel_fname:
992 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
993
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800994 if gbb:
995 pack.AddProperty('gbb', gbb)
Simon Glass9d088d92012-07-16 16:27:11 +0100996 blob_list = pack.GetBlobList()
997 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700998 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800999 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -07001000
Simon Glass7306b902012-12-17 15:06:21 -08001001 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001002 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001003 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001004 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001005 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001006 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001007 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001008 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001009 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001010
Simon Glass0a047bc2013-07-19 15:44:43 -06001011 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001012 todo = pack.GetMissingBlobs()
1013 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001014 if blob.key.startswith('exynos-bl2'):
1015 bl2 = ExynosBl2(self._tools, self._out)
1016 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1017 self.exynos_bl2))
1018
Simon Glassc90cf582012-03-13 15:40:47 -07001019 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001020
1021 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001022 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001023
Simon Glass4c24f662013-07-19 15:53:02 -06001024 # Recalculate the Exynos BL2, since it may have a hash. The call to
1025 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1026 # need to recalculate the hash.
1027 for blob in todo:
1028 if blob.key.startswith('exynos-bl2'):
1029 bl2 = ExynosBl2(self._tools, self._out)
1030 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1031 self.exynos_bl2))
1032
Simon Glass6207efe2012-12-17 15:04:36 -08001033 # Make a copy of the fdt for the bootstub
1034 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001035 if self.uboot_fname:
1036 uboot_data = self._tools.ReadFile(self.uboot_fname)
1037 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1038 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001039
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001040 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1041 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001042
Simon Glassa10282a2013-01-08 17:06:41 -08001043 # Fix up the coreboot image here, since we can't do this until we have
1044 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +01001045 if 'coreboot' in blob_list:
1046 bootstub = pack.GetProperty('coreboot')
1047 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001048 if self.coreboot_elf:
1049 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1050 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001051 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001052 text_base = 0x1110000
1053
1054 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1055 # 1110015: 66 bb 00 01 mov $0x100,%bx
1056 marker = struct.pack('<L', 0x0100bb66)
1057 pos = uboot_data.find(marker)
1058 if pos == -1 or pos > 0x100:
1059 raise ValueError('Cannot find U-Boot cold boot entry point')
1060 entry = text_base + pos
1061 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001062 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1063 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001064 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001065 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1066 '-n', 'u-boot.dtb', '-t', '0xac'])
Daisuke Nojiri69662892015-09-25 15:24:04 -07001067 if self.cbfs_files:
1068 self._AddCbfsFiles(bootstub)
Simon Glassb8ea1802012-12-17 15:08:00 -08001069 data = self._tools.ReadFile(bootstub)
1070 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1071 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001072
Julius Werneraa1fe942014-11-21 17:16:11 -08001073 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1074 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1075 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001076
Simon Glass208ad952013-02-10 11:16:46 -08001077 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001078 image = os.path.join(self._tools.outdir, 'image.bin')
1079 pack.PackImage(self._tools.outdir, image)
1080 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001081
Simon Glass439fe7a2012-03-09 16:19:34 -08001082 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001083 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001084 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001085
Simon Glassdedda6f2013-02-09 13:44:14 -08001086 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001087 """Select an FDT to control the firmware bundling
1088
Simon Glassdedda6f2013-02-09 13:44:14 -08001089 We make a copy of this which will include any on-the-fly changes we want
1090 to make.
1091
Simon Glass290a1802011-07-17 13:54:32 -07001092 Args:
1093 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001094 use_defaults: True to use a default FDT name if available, and to add
1095 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001096
Simon Glassc0f3dc62011-08-09 14:19:05 -07001097 Returns:
1098 The Fdt object of the original fdt file, which we will not modify.
1099
Simon Glassdedda6f2013-02-09 13:44:14 -08001100 Raises:
1101 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1102 False).
Simon Glass290a1802011-07-17 13:54:32 -07001103 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001104 if use_defaults:
1105 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001106 if not fdt_fname:
1107 raise ValueError('Please provide an FDT filename')
1108 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001109 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001110
1111 # For upstream, select the correct architecture .dtsi manually.
1112 if self._board == 'link' or 'x86' in self._board:
1113 arch_dts = 'coreboot.dtsi'
1114 elif self._board == 'daisy':
1115 arch_dts = 'exynos5250.dtsi'
1116 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001117 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001118
1119 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001120 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1121
1122 # Get the flashmap so we know what to build. For board variants use the
1123 # main board name as the key (drop the _<variant> suffix).
1124 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1125
1126 if not fdt.GetProp('/flash', 'reg', ''):
1127 fdt.InsertNodes(default_flashmap)
1128
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001129 # Only check for /iram and /config nodes for boards that require it.
1130 if self._board in ('daisy', 'peach'):
1131 # Insert default values for any essential properties that are missing.
1132 # This should only happen for upstream U-Boot, until our changes are
1133 # upstreamed.
1134 if not fdt.GetProp('/iram', 'reg', ''):
1135 self._out.Warning('Cannot find /iram, using default')
1136 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001137
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001138 # Sadly the pit branch has an invalid /memory node. Work around it
1139 # for now. crosbug.com/p/22184
1140 if (not fdt.GetProp('/memory', 'reg', '') or
1141 fdt.GetIntList('/memory', 'reg')[0] == 0):
1142 self._out.Warning('Cannot find /memory, using default')
1143 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001144
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001145 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
1146 self._out.Warning('Missing properties in /config, using defaults')
1147 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001148
Simon Glass7df773b2013-08-25 18:02:29 -06001149 # Remember our board type.
1150 fdt.PutString('/chromeos-config', 'board', self._board)
1151
Simon Glasse53abbc2013-08-21 22:29:55 -06001152 self.fdt = fdt
1153 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001154
Simon Glassc90cf582012-03-13 15:40:47 -07001155 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001156 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001157
1158 - Checks options, tools, output directory, fdt.
1159 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001160
1161 Args:
Simon Glass56577572011-07-19 11:08:06 +12001162 hardware_id: Hardware ID to use for this board. If None, then the
1163 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001164 output_fname: Output filename for the image. If this is not None, then
1165 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001166 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001167
1168 Returns:
1169 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001170 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001171 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1172 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1173 else:
Simon Glass56577572011-07-19 11:08:06 +12001174 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001175
1176 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001177 image, pack = self._CreateImage(gbb, self.fdt)
1178 if show_map:
1179 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001180 if output_fname:
1181 shutil.copyfile(image, output_fname)
1182 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001183 return image, pack.props