blob: 5ab7a5ebfaee003c1d220f0a23ace6674b18f959 [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,
Simon Glass4a887b12012-10-23 16:29:03 -070073}
74
Simon Glass49b026b2013-04-26 16:38:42 -070075# Maps board name to Exynos product number
76type_to_model = {
77 'peach' : '5420',
78 'daisy' : '5250'
79}
80
Simon Glass5076a7f2012-10-23 16:31:54 -070081def ListGoogleBinaryBlockFlags():
82 """Print out a list of GBB flags."""
83 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
84 for name, value in gbb_flag_properties.iteritems():
85 print ' %-30s %02x' % (name, value)
86
Simon Glass89b86b82011-07-17 23:49:49 -070087class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070088 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070089
Simon Glass290a1802011-07-17 13:54:32 -070090 Sequence of events:
91 bundle = Bundle(tools.Tools(), cros_output.Output())
92 bundle.SetDirs(...)
93 bundle.SetFiles(...)
94 bundle.SetOptions(...)
95 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070096 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070097 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070098
Simon Glass290a1802011-07-17 13:54:32 -070099 Public properties:
100 fdt: The fdt object that we use for building our image. This wil be the
101 one specified by the user, except that we might add config options
102 to it. This is set up by SelectFdt() which must be called before
103 bundling starts.
104 uboot_fname: Full filename of the U-Boot binary we use.
105 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700106 spl_source: Source device to load U-Boot from, in SPL:
107 straps: Select device according to CPU strap pins
108 spi: Boot from SPI
109 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700110
111 Private attributes:
112 _small: True to create a 'small' signed U-Boot, False to produce a
113 full image. The small U-Boot is enough to boot but will not have
114 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700115 """
Simon Glass89b86b82011-07-17 23:49:49 -0700116
Simon Glass290a1802011-07-17 13:54:32 -0700117 def __init__(self, tools, output):
118 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700119
Simon Glass290a1802011-07-17 13:54:32 -0700120 Args:
121 tools: A tools.Tools object to use for external tools.
122 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700123 """
Simon Glass290a1802011-07-17 13:54:32 -0700124 self._tools = tools
125 self._out = output
126
127 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500128 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700129 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700130 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600131 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700132 self._gbb_flags = None
133 self._keydir = None
134 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700135 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700136 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800137 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700138 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700139 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700140 self.ecro_fname = None # Filename of EC read-only file
141 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700142 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700143 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
144 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700145 self.fdt = None # Our Fdt object.
146 self.kernel_fname = None
147 self.postload_fname = None
148 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700149 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700150 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700151
152 def SetDirs(self, keydir):
153 """Set up directories required for Bundle.
154
155 Args:
156 keydir: Directory containing keys to use for signing firmware.
157 """
158 self._keydir = keydir
159
Simon Glass6dcc2f22011-07-28 15:26:49 +1200160 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800161 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700162 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700163 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800164 kernel=None, blobs=None, skip_bmpblk=False):
Simon Glass290a1802011-07-17 13:54:32 -0700165 """Set up files required for Bundle.
166
167 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500168 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700169 uboot: The filename of the u-boot.bin image to use.
170 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800171 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800172 coreboot: The filename of the coreboot image to use (on x86).
173 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200174 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700175 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700176 exynos_bl1: The filename of the exynos BL1 file
177 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
178 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700179 ecrw: The filename of the EC (Embedded Controller) read-write file.
180 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700181 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700182 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800183 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800184 skip_bmpblk: True if no bmpblk is required
Simon Glass290a1802011-07-17 13:54:32 -0700185 """
186 self._board = board
187 self.uboot_fname = uboot
188 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800189 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700190 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800191 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200192 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700193 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700194 self.exynos_bl1 = exynos_bl1
195 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700196 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700197 self.ecrw_fname = ecrw
198 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700199 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700200 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800201 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800202 self.skip_bmpblk = skip_bmpblk
Simon Glass290a1802011-07-17 13:54:32 -0700203
Simon Glass00d027e2013-07-20 14:51:12 -0600204 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700205 """Set up options supported by Bundle.
206
207 Args:
208 small: Only create a signed U-Boot - don't produce the full packed
209 firmware image. This is useful for devs who want to replace just the
210 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700211 gbb_flags: Specification for string containing adjustments to make.
212 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600213 force_efs: Force firmware to use 'early firmware selection' feature,
214 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700215 """
216 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700217 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700218 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600219 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700220
Simon Glass22f39fb2013-02-09 13:44:14 -0800221 def _GetBuildRoot(self):
222 """Get the path to this board's 'firmware' directory.
223
224 Returns:
225 Path to firmware directory, with ## representing the path to the
226 chroot.
227 """
Simon Glass290a1802011-07-17 13:54:32 -0700228 if not self._board:
229 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800230 return os.path.join('##', 'build', self._board, 'firmware')
231
232 def _CheckFdtFilename(self, fname):
233 """Check provided FDT filename and return the correct name if needed.
234
235 Where the filename lacks a path, add a default path for this board.
236 Where no FDT filename is provided, select a default one for this board.
237
238 Args:
239 fname: Proposed FDT filename.
240
241 Returns:
242 Selected FDT filename, after validation.
243 """
244 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700245 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800246 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700247 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700248 base_name = re.sub('_', '-', self._board)
249
250 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700251 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700252 found_list = glob.glob(self._tools.Filename(wildcard))
253 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800254 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700255 else:
256 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700257 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700258
Simon Glass881964d2012-04-04 11:34:09 -0700259 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800260 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700261 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700262 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800263 return fname
264
265 def CheckOptions(self):
266 """Check provided options and select defaults."""
267 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700268
Simon Glass49b026b2013-04-26 16:38:42 -0700269 board_type = self._board.split('_')[0]
270 model = type_to_model.get(board_type)
271
Simon Glass290a1802011-07-17 13:54:32 -0700272 if not self.uboot_fname:
273 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
274 if not self.bct_fname:
275 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700276 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700277 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700278 if model:
279 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700280 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700281 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700282 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700283 if not self.coreboot_fname:
284 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
285 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700286 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700287 if not self.seabios_fname:
288 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700289 if not self.ecrw_fname:
290 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700291 if not self.pdrw_fname:
292 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700293 if not self.ecro_fname:
294 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700295
Simon Glass75759302012-03-15 20:26:53 -0700296 def GetFiles(self):
297 """Get a list of files that we know about.
298
299 This is the opposite of SetFiles except that we may have put in some
300 default names. It returns a dictionary containing the filename for
301 each of a number of pre-defined files.
302
303 Returns:
304 Dictionary, with one entry for each file.
305 """
306 file_list = {
307 'bct' : self.bct_fname,
308 'exynos-bl1' : self.exynos_bl1,
309 'exynos-bl2' : self.exynos_bl2,
310 }
311 return file_list
312
Simon Glass4a887b12012-10-23 16:29:03 -0700313 def DecodeGBBFlagsFromFdt(self):
314 """Get Google Binary Block flags from the FDT.
315
316 These should be in the chromeos-config node, like this:
317
318 chromeos-config {
319 gbb-flag-dev-screen-short-delay;
320 gbb-flag-force-dev-switch-on;
321 gbb-flag-force-dev-boot-usb;
322 gbb-flag-disable-fw-rollback-check;
323 };
324
325 Returns:
326 GBB flags value from FDT.
327 """
328 chromeos_config = self.fdt.GetProps("/chromeos-config")
329 gbb_flags = 0
330 for name in chromeos_config:
331 if name.startswith('gbb-flag-'):
332 flag_value = gbb_flag_properties.get(name[9:])
333 if flag_value:
334 gbb_flags |= flag_value
335 self._out.Notice("FDT: Enabling %s." % name)
336 else:
337 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
338 return gbb_flags
339
Simon Glass157c0662012-10-23 13:52:42 -0700340 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
341 """Decode ajustments to the provided GBB flags.
342
343 We support three options:
344
345 hex value: c2
346 defined value: force-dev-boot-usb,load-option-roms
347 adjust default value: -load-option-roms,+force-dev-boot-usb
348
349 The last option starts from the passed-in GBB flags and adds or removes
350 flags.
351
352 Args:
353 gbb_flags: Base (default) FDT flags.
354 adjustments: String containing adjustments to make.
355
356 Returns:
357 Updated FDT flags.
358 """
359 use_base_value = True
360 if adjustments:
361 try:
362 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700363 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700364 pass
365 for flag in adjustments.split(','):
366 oper = None
367 if flag[0] in ['-', '+']:
368 oper = flag[0]
369 flag = flag[1:]
370 value = gbb_flag_properties.get(flag)
371 if not value:
372 raise ValueError("Invalid GBB flag '%s'" % flag)
373 if oper == '+':
374 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800375 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700376 elif oper == '-':
377 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800378 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700379 else:
380 if use_base_value:
381 gbb_flags = 0
382 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800383 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700384 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800385 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700386
387 return gbb_flags
388
Simon Glass56577572011-07-19 11:08:06 +1200389 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700390 """Create a GBB for the image.
391
Simon Glass56577572011-07-19 11:08:06 +1200392 Args:
393 hardware_id: Hardware ID to use for this board. If None, then the
394 default from the Fdt will be used
395
Simon Glass89b86b82011-07-17 23:49:49 -0700396 Returns:
397 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700398 """
Simon Glass56577572011-07-19 11:08:06 +1200399 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800400 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700401 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700402 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700403
Simon Glass4a887b12012-10-23 16:29:03 -0700404 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800405
Simon Glass157c0662012-10-23 13:52:42 -0700406 # Allow command line to override flags
407 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
408
Simon Glass4a887b12012-10-23 16:29:03 -0700409 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700410 self._out.Progress('Creating GBB')
411 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
412 sizes = ['%#x' % size for size in sizes]
413 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700414 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800415
416 gbb_set_command = ['-s',
417 '--hwid=%s' % hardware_id,
418 '--rootkey=%s/root_key.vbpubk' % keydir,
419 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
420 '--flags=%d' % gbb_flags,
421 gbb]
422 if not self.skip_bmpblk:
423 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
424 self.bmpblk_fname),]
425
Simon Glass290a1802011-07-17 13:54:32 -0700426 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800427 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700428 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700429
Simon Glasse13ee2c2011-07-28 08:12:28 +1200430 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700431 """Sign an image so that the Tegra SOC will boot it.
432
433 Args:
434 bct: BCT file to use.
435 bootstub: Boot stub (U-Boot + fdt) file to sign.
436 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700437
438 Returns:
439 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700440 """
441 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200442 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700443 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200444 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700445 fd = open(config, 'w')
446 fd.write('Version = 1;\n')
447 fd.write('Redundancy = 1;\n')
448 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700449
450 # TODO(dianders): Right now, we don't have enough space in our flash map
451 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
452 # sure what this does for reliability, but at least things will fit...
453 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
454 if is_nand:
455 fd.write('Bctcopy = 1;\n')
456
Simon Glass89b86b82011-07-17 23:49:49 -0700457 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
458 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700459
Simon Glass89b86b82011-07-17 23:49:49 -0700460 fd.close()
461
462 self._tools.Run('cbootimage', [config, signed])
463 self._tools.OutputSize('BCT', bct)
464 self._tools.OutputSize('Signed image', signed)
465 return signed
466
Doug Anderson86ce5f42011-07-27 10:40:18 -0700467 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700468 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700469
470 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700471 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700472 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700473 """
Simon Glass468d8752012-09-19 16:36:19 -0700474 if bootcmd is not None:
475 if bootcmd == 'none':
476 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800477 self.fdt.PutString('/config', 'bootcmd', bootcmd)
478 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700479 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700480
Simon Glassa4934b72012-05-09 13:35:02 -0700481 def SetNodeEnabled(self, node_name, enabled):
482 """Set whether an node is enabled or disabled.
483
484 This simply sets the 'status' property of a node to "ok", or "disabled".
485
486 The node should either be a full path to the node (like '/uart@10200000')
487 or an alias property.
488
489 Aliases are supported like this:
490
491 aliases {
492 console = "/uart@10200000";
493 };
494
495 pointing to a node:
496
497 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700498 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700499 };
500
501 In this case, this function takes the name of the alias ('console' in
502 this case) and updates the status of the node that is pointed to, to
503 either ok or disabled. If the alias does not exist, a warning is
504 displayed.
505
506 Args:
507 node_name: Name of node (e.g. '/uart@10200000') or alias alias
508 (e.g. 'console') to adjust
509 enabled: True to enable, False to disable
510 """
511 # Look up the alias if this is an alias reference
512 if not node_name.startswith('/'):
513 lookup = self.fdt.GetString('/aliases', node_name, '')
514 if not lookup:
515 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
516 return
517 node_name = lookup
518 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700519 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700520 else:
521 status = 'disabled'
522 self.fdt.PutString(node_name, 'status', status)
523
524 def AddEnableList(self, enable_list):
525 """Process a list of nodes to enable/disable.
526
527 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700528 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700529 tuple:
530 node: The fdt node to write to will be <node> or pointed to by
531 /aliases/<node>. We can tell which
532 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700533
Vadim Bendebury507c0012013-06-09 12:49:25 -0700534 Raises:
535 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700536 """
537 if enable_list:
538 for node_name, enabled in enable_list:
539 try:
540 enabled = int(enabled)
541 if enabled not in (0, 1):
542 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700543 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700544 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700545 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700546 self.SetNodeEnabled(node_name, enabled)
547
Simon Glass290a1802011-07-17 13:54:32 -0700548 def AddConfigList(self, config_list, use_int=False):
549 """Add a list of config items to the fdt.
550
551 Normally these values are written to the fdt as strings, but integers
552 are also supported, in which case the values will be converted to integers
553 (if necessary) before being stored.
554
555 Args:
556 config_list: List of (config, value) tuples to add to the fdt. For each
557 tuple:
558 config: The fdt node to write to will be /config/<config>.
559 value: An integer or string value to write.
560 use_int: True to only write integer values.
561
562 Raises:
563 CmdError: if a value is required to be converted to integer but can't be.
564 """
565 if config_list:
566 for config in config_list:
567 value = config[1]
568 if use_int:
569 try:
570 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700571 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700572 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700573 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700574 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800575 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700576 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800577 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700578
Simon Glass7c2d5572011-11-15 14:47:08 -0800579 def DecodeTextBase(self, data):
580 """Look at a U-Boot image and try to decode its TEXT_BASE.
581
582 This works because U-Boot has a header with the value 0x12345678
583 immediately followed by the TEXT_BASE value. We can therefore read this
584 from the image with some certainty. We check only the first 40 words
585 since the header should be within that region.
586
Simon Glass96b50302012-07-20 06:55:28 +0100587 Since upstream Tegra has moved to having a 16KB SPL region at the start,
588 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
589 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
590
Simon Glass7c2d5572011-11-15 14:47:08 -0800591 Args:
592 data: U-Boot binary data
593
594 Returns:
595 Text base (integer) or None if none was found
596 """
597 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100598 for start in (0, 0x4000):
599 for i in range(start, start + 160, 4):
600 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800601
Simon Glass96b50302012-07-20 06:55:28 +0100602 # TODO(sjg): This does not cope with a big-endian target
603 value = struct.unpack('<I', word)[0]
604 if found:
605 return value - start
606 if value == 0x12345678:
607 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800608
609 return None
610
611 def CalcTextBase(self, name, fdt, fname):
612 """Calculate the TEXT_BASE to use for U-Boot.
613
614 Normally this value is in the fdt, so we just read it from there. But as
615 a second check we look at the image itself in case this is different, and
616 switch to that if it is.
617
618 This allows us to flash any U-Boot even if its TEXT_BASE is different.
619 This is particularly useful with upstream U-Boot which uses a different
620 value (which we will move to).
621 """
622 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800623 # The value that comes back from fdt.GetInt is signed, which makes no
624 # sense for an address base. Force it to unsigned.
625 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800626 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100627 text_base_str = '%#x' % text_base if text_base else 'None'
628 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
629 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800630
631 # If they are different, issue a warning and switch over.
632 if text_base and text_base != fdt_text_base:
633 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
634 "fdt value of %x. Using %x" % (text_base, name,
635 fdt_text_base, text_base))
636 fdt_text_base = text_base
637 return fdt_text_base
638
Simon Glass6dcc2f22011-07-28 15:26:49 +1200639 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700640 """Create a boot stub and a signed boot stub.
641
Simon Glass6dcc2f22011-07-28 15:26:49 +1200642 For postload:
643 We add a /config/postload-text-offset entry to the signed bootstub's
644 fdt so that U-Boot can find the postload code.
645
646 The raw (unsigned) bootstub will have a value of -1 for this since we will
647 simply append the postload code to the bootstub and it can find it there.
648 This will be used for RW A/B firmware.
649
650 For the signed case this value will specify where in the flash to find
651 the postload code. This will be used for RO firmware.
652
Simon Glass89b86b82011-07-17 23:49:49 -0700653 Args:
654 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800655 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200656 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700657
658 Returns:
659 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200660 Full path to bootstub (uboot + fdt(-1) + postload).
661 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700662
663 Raises:
664 CmdError if a command fails.
665 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200666 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800667 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700668 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200669
670 # Make a copy of the fdt for the bootstub
671 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700672 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700673 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200674
Simon Glass89b86b82011-07-17 23:49:49 -0700675 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700676 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
677 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700678 self._tools.OutputSize('Combined binary', bootstub)
679
Simon Glasse13ee2c2011-07-28 08:12:28 +1200680 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700681 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700682 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200683 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200684
685 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
686 data = self._tools.ReadFile(signed)
687
688 if postload:
689 # We must add postload to the bootstub since A and B will need to
690 # be able to find it without the /config/postload-text-offset mechanism.
691 bs_data = self._tools.ReadFile(bootstub)
692 bs_data += self._tools.ReadFile(postload)
693 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
694 self._tools.WriteFile(bootstub, bs_data)
695 self._tools.OutputSize('Combined binary with postload', bootstub)
696
697 # Now that we know the file size, adjust the fdt and re-sign
698 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800699 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200700 fdt_data = self._tools.ReadFile(fdt.fname)
701 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
702 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
703 postload_bootstub, text_base)
704 if len(data) != os.path.getsize(signed):
705 raise CmdError('Signed file size changed from %d to %d after updating '
706 'fdt' % (len(data), os.path.getsize(signed)))
707
708 # Re-read the signed image, and add the post-load binary.
709 data = self._tools.ReadFile(signed)
710 data += self._tools.ReadFile(postload)
711 self._tools.OutputSize('Post-load binary', postload)
712
713 self._tools.WriteFile(signed_postload, data)
714 self._tools.OutputSize('Final bootstub with postload', signed_postload)
715
716 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700717
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700718 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700719 """Create a coreboot boot stub.
720
721 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700722 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700723
724 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100725 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700726 """
727 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700728 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100729
730 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700731 return bootstub
732
Simon Glass7e199222012-03-13 15:51:18 -0700733
Simon Glass89b86b82011-07-17 23:49:49 -0700734 def _PackOutput(self, msg):
735 """Helper function to write output from PackFirmware (verbose level 2).
736
737 This is passed to PackFirmware for it to use to write output.
738
739 Args:
740 msg: Message to display.
741 """
742 self._out.Notice(msg)
743
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800744 def _PrepareCbfs(self, pack, blob_name):
745 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
746
747 When the blob name is defined as cbfs#<section>#<subsection>, fill the
748 <section>_<subsection> area in the flash map with a CBFS copy, putting the
749 CBFS header of the copy at the base of the section.
750
751 If --coreboot-elf parameter was specified during cros_bumdle_firmware
752 invocation, add the parameter of this option as the payload to the new
753 CBFS instance.
754
755 Args:
756 pack: a PackFirmware object describing the firmware image to build.
757 blob_name: a string, blob name describing what FMAP section this CBFS
758 copy is destined to
759 Raises:
760 CmdError if base coreboot image does not contain CBFS
761 """
762
763 if not self.coreboot_fname:
764 raise CmdError("coreboot file needed for blob % s", blob_name)
765
766 part_sections = blob_name.split('/')[1:]
767
768 # Base address and size of the desitnation partition
769 base, size = self.fdt.GetFlashPart(*part_sections)
770
771 # Create a coreboot copy to use as a scratch pad.
772 cb_copy = os.path.join(self._tools.outdir, 'cb_copy')
773 if not os.path.exists(cb_copy):
774 self._tools.WriteFile(cb_copy, self._tools.ReadFile(self.coreboot_fname))
775
776 # Copy CBFS to the required offset
777 self._tools.Run('cbfstool', [cb_copy, 'copy', '-D',
778 '%d' % base, '-s', '%d' % size])
779
780 # Add coreboot payload if so requested. Note that the some images use
781 # different payload for the rw sections, which is passed in as the value
782 # of the --uboot option in the command line.
783 if self.uboot_fname:
784 payload_fname = self.uboot_fname
785 elif self.coreboot_elf:
786 payload_fname = self.coreboot_elf
787 else:
788 payload_fname = None
789
790 if payload_fname:
791 self._tools.Run('cbfstool', [
792 cb_copy, 'add-payload', '-f', payload_fname,
793 '-n', 'fallback/payload', '-c', 'lzma' , '-H', '%d' % base])
794
795 # And extract the blob for the FW section
796 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
797 self._tools.WriteFile(rw_section,
798 self._tools.ReadFile(cb_copy)[base:base+size])
799
800 pack.AddProperty(blob_name, rw_section)
801
802
Simon Glass439fe7a2012-03-09 16:19:34 -0800803 def _BuildBlob(self, pack, fdt, blob_type):
804 """Build the blob data for a particular blob type.
805
806 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700807 pack: a PackFirmware object describing the firmware image to build.
808 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800809 blob_type: The type of blob to create data for. Supported types are:
810 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
811 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700812
813 Raises:
814 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800815 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700816 # stupid pylint insists that sha256 is not in hashlib.
817 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800818 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700819 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800820 pack.AddProperty('coreboot', coreboot)
821 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700822 elif blob_type == 'legacy':
823 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800824 elif blob_type == 'signed':
825 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
826 self.postload_fname)
827 pack.AddProperty('bootstub', bootstub)
828 pack.AddProperty('signed', signed)
829 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700830 elif blob_type == 'exynos-bl1':
831 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700832
833 # TODO(sjg@chromium.org): Deprecate ecbin
834 elif blob_type in ['ecrw', 'ecbin']:
835 pack.AddProperty('ecrw', self.ecrw_fname)
836 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700837 elif blob_type == 'pdrw':
838 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800839 elif blob_type == 'ecrwhash':
840 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
841 ecrw = self._tools.ReadFile(self.ecrw_fname)
842 hasher = hashlib.sha256()
843 hasher.update(ecrw)
844 self._tools.WriteFile(ec_hash_file, hasher.digest())
845 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700846 elif blob_type == 'pdrwhash':
847 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
848 pdrw = self._tools.ReadFile(self.pdrw_fname)
849 hasher = hashlib.sha256()
850 hasher.update(pdrw)
851 self._tools.WriteFile(pd_hash_file, hasher.digest())
852 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700853 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700854 # crosbug.com/p/13143
855 # We cannot have an fmap in the EC image since there can be only one,
856 # which is the main fmap describing the whole image.
857 # Ultimately the EC will not have an fmap, since with software sync
858 # there is no flashrom involvement in updating the EC flash, and thus
859 # no need for the fmap.
860 # For now, mangle the fmap name to avoid problems.
861 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
862 data = self._tools.ReadFile(self.ecro_fname)
863 data = re.sub('__FMAP__', '__fMAP__', data)
864 self._tools.WriteFile(updated_ecro, data)
865 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600866 elif blob_type.startswith('exynos-bl2'):
867 # We need to configure this per node, so do it later
868 pass
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800869 elif blob_type.startswith('cbfs'):
870 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800871 elif pack.GetProperty(blob_type):
872 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800873 elif blob_type in self.blobs:
874 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800875 else:
876 raise CmdError("Unknown blob type '%s' required in flash map" %
877 blob_type)
878
Simon Glass290a1802011-07-17 13:54:32 -0700879 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700880 """Create a full firmware image, along with various by-products.
881
882 This uses the provided u-boot.bin, fdt and bct to create a firmware
883 image containing all the required parts. If the GBB is not supplied
884 then this will just return a signed U-Boot as the image.
885
886 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700887 gbb: a string, full path to the GBB file, or empty if a GBB is not
888 required.
889 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200890
891 Returns:
892 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700893 """
Simon Glass02d124a2012-03-02 14:47:20 -0800894 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700895
Simon Glass439fe7a2012-03-09 16:19:34 -0800896 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -0800897 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700898 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
899 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -0600900 if self._force_efs:
901 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -0600902 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
903 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800904
Simon Glass4f318912013-07-20 16:13:06 -0600905 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800906
907 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800908 if self.uboot_fname:
909 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800910 if self.skeleton_fname:
911 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700912 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700913
Simon Glassde9c8072012-07-02 22:29:02 -0700914 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
915 if self.kernel_fname:
916 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
917
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800918 if gbb:
919 pack.AddProperty('gbb', gbb)
Simon Glass9d088d92012-07-16 16:27:11 +0100920 blob_list = pack.GetBlobList()
921 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700922 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800923 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -0700924
Simon Glass7306b902012-12-17 15:06:21 -0800925 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700926 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700927 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +0800928 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -0800929 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +0800930 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700931 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800932 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800933 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700934
Simon Glass0a047bc2013-07-19 15:44:43 -0600935 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -0600936 todo = pack.GetMissingBlobs()
937 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -0600938 if blob.key.startswith('exynos-bl2'):
939 bl2 = ExynosBl2(self._tools, self._out)
940 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
941 self.exynos_bl2))
942
Simon Glassc90cf582012-03-13 15:40:47 -0700943 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700944
945 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800946 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700947
Simon Glass4c24f662013-07-19 15:53:02 -0600948 # Recalculate the Exynos BL2, since it may have a hash. The call to
949 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
950 # need to recalculate the hash.
951 for blob in todo:
952 if blob.key.startswith('exynos-bl2'):
953 bl2 = ExynosBl2(self._tools, self._out)
954 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
955 self.exynos_bl2))
956
Simon Glass6207efe2012-12-17 15:04:36 -0800957 # Make a copy of the fdt for the bootstub
958 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800959 if self.uboot_fname:
960 uboot_data = self._tools.ReadFile(self.uboot_fname)
961 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
962 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -0800963
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800964 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
965 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -0800966
Simon Glassa10282a2013-01-08 17:06:41 -0800967 # Fix up the coreboot image here, since we can't do this until we have
968 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +0100969 if 'coreboot' in blob_list:
970 bootstub = pack.GetProperty('coreboot')
971 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -0800972 if self.coreboot_elf:
973 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
974 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800975 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -0700976 text_base = 0x1110000
977
978 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
979 # 1110015: 66 bb 00 01 mov $0x100,%bx
980 marker = struct.pack('<L', 0x0100bb66)
981 pos = uboot_data.find(marker)
982 if pos == -1 or pos > 0x100:
983 raise ValueError('Cannot find U-Boot cold boot entry point')
984 entry = text_base + pos
985 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -0800986 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
987 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -0700988 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -0700989 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
990 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -0800991 data = self._tools.ReadFile(bootstub)
992 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
993 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -0700994
Julius Werneraa1fe942014-11-21 17:16:11 -0800995 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
996 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
997 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +0100998
Simon Glass208ad952013-02-10 11:16:46 -0800999 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001000 image = os.path.join(self._tools.outdir, 'image.bin')
1001 pack.PackImage(self._tools.outdir, image)
1002 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001003
Simon Glass439fe7a2012-03-09 16:19:34 -08001004 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001005 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001006 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001007
Simon Glassdedda6f2013-02-09 13:44:14 -08001008 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001009 """Select an FDT to control the firmware bundling
1010
Simon Glassdedda6f2013-02-09 13:44:14 -08001011 We make a copy of this which will include any on-the-fly changes we want
1012 to make.
1013
Simon Glass290a1802011-07-17 13:54:32 -07001014 Args:
1015 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001016 use_defaults: True to use a default FDT name if available, and to add
1017 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001018
Simon Glassc0f3dc62011-08-09 14:19:05 -07001019 Returns:
1020 The Fdt object of the original fdt file, which we will not modify.
1021
Simon Glassdedda6f2013-02-09 13:44:14 -08001022 Raises:
1023 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1024 False).
Simon Glass290a1802011-07-17 13:54:32 -07001025 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001026 if use_defaults:
1027 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001028 if not fdt_fname:
1029 raise ValueError('Please provide an FDT filename')
1030 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001031 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001032
1033 # For upstream, select the correct architecture .dtsi manually.
1034 if self._board == 'link' or 'x86' in self._board:
1035 arch_dts = 'coreboot.dtsi'
1036 elif self._board == 'daisy':
1037 arch_dts = 'exynos5250.dtsi'
1038 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001039 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001040
1041 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001042 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1043
1044 # Get the flashmap so we know what to build. For board variants use the
1045 # main board name as the key (drop the _<variant> suffix).
1046 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1047
1048 if not fdt.GetProp('/flash', 'reg', ''):
1049 fdt.InsertNodes(default_flashmap)
1050
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001051 # Only check for /iram and /config nodes for boards that require it.
1052 if self._board in ('daisy', 'peach'):
1053 # Insert default values for any essential properties that are missing.
1054 # This should only happen for upstream U-Boot, until our changes are
1055 # upstreamed.
1056 if not fdt.GetProp('/iram', 'reg', ''):
1057 self._out.Warning('Cannot find /iram, using default')
1058 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001059
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001060 # Sadly the pit branch has an invalid /memory node. Work around it
1061 # for now. crosbug.com/p/22184
1062 if (not fdt.GetProp('/memory', 'reg', '') or
1063 fdt.GetIntList('/memory', 'reg')[0] == 0):
1064 self._out.Warning('Cannot find /memory, using default')
1065 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001066
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001067 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
1068 self._out.Warning('Missing properties in /config, using defaults')
1069 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001070
Simon Glass7df773b2013-08-25 18:02:29 -06001071 # Remember our board type.
1072 fdt.PutString('/chromeos-config', 'board', self._board)
1073
Simon Glasse53abbc2013-08-21 22:29:55 -06001074 self.fdt = fdt
1075 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001076
Simon Glassc90cf582012-03-13 15:40:47 -07001077 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001078 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001079
1080 - Checks options, tools, output directory, fdt.
1081 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001082
1083 Args:
Simon Glass56577572011-07-19 11:08:06 +12001084 hardware_id: Hardware ID to use for this board. If None, then the
1085 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001086 output_fname: Output filename for the image. If this is not None, then
1087 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001088 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001089
1090 Returns:
1091 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001092 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001093 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1094 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1095 else:
Simon Glass56577572011-07-19 11:08:06 +12001096 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001097
1098 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001099 image, pack = self._CreateImage(gbb, self.fdt)
1100 if show_map:
1101 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001102 if output_fname:
1103 shutil.copyfile(image, output_fname)
1104 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001105 return image, pack.props