blob: c7f4a13aebcd3cd0aefcd54cc787c84b0c77b399 [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,
Simon Glass4a887b12012-10-23 16:29:03 -070074}
75
Simon Glass49b026b2013-04-26 16:38:42 -070076# Maps board name to Exynos product number
77type_to_model = {
78 'peach' : '5420',
79 'daisy' : '5250'
80}
81
Simon Glass5076a7f2012-10-23 16:31:54 -070082def ListGoogleBinaryBlockFlags():
83 """Print out a list of GBB flags."""
84 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
85 for name, value in gbb_flag_properties.iteritems():
86 print ' %-30s %02x' % (name, value)
87
Simon Glass89b86b82011-07-17 23:49:49 -070088class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070089 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070090
Simon Glass290a1802011-07-17 13:54:32 -070091 Sequence of events:
92 bundle = Bundle(tools.Tools(), cros_output.Output())
93 bundle.SetDirs(...)
94 bundle.SetFiles(...)
95 bundle.SetOptions(...)
96 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070097 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070098 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070099
Simon Glass290a1802011-07-17 13:54:32 -0700100 Public properties:
101 fdt: The fdt object that we use for building our image. This wil be the
102 one specified by the user, except that we might add config options
103 to it. This is set up by SelectFdt() which must be called before
104 bundling starts.
105 uboot_fname: Full filename of the U-Boot binary we use.
106 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700107 spl_source: Source device to load U-Boot from, in SPL:
108 straps: Select device according to CPU strap pins
109 spi: Boot from SPI
110 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700111
112 Private attributes:
113 _small: True to create a 'small' signed U-Boot, False to produce a
114 full image. The small U-Boot is enough to boot but will not have
115 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700116 """
Simon Glass89b86b82011-07-17 23:49:49 -0700117
Simon Glass290a1802011-07-17 13:54:32 -0700118 def __init__(self, tools, output):
119 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700120
Simon Glass290a1802011-07-17 13:54:32 -0700121 Args:
122 tools: A tools.Tools object to use for external tools.
123 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700124 """
Simon Glass290a1802011-07-17 13:54:32 -0700125 self._tools = tools
126 self._out = output
127
128 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500129 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700130 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700131 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600132 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700133 self._gbb_flags = None
134 self._keydir = None
135 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700136 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700137 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800138 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700139 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700140 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700141 self.ecro_fname = None # Filename of EC read-only file
142 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700143 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700144 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
145 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700146 self.fdt = None # Our Fdt object.
147 self.kernel_fname = None
148 self.postload_fname = None
149 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700150 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700151 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700152
153 def SetDirs(self, keydir):
154 """Set up directories required for Bundle.
155
156 Args:
157 keydir: Directory containing keys to use for signing firmware.
158 """
159 self._keydir = keydir
160
Simon Glass6dcc2f22011-07-28 15:26:49 +1200161 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800162 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700163 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700164 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Daisuke Nojiri69662892015-09-25 15:24:04 -0700165 kernel=None, blobs=None, skip_bmpblk=False, cbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700166 """Set up files required for Bundle.
167
168 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500169 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700170 uboot: The filename of the u-boot.bin image to use.
171 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800172 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800173 coreboot: The filename of the coreboot image to use (on x86).
174 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200175 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700176 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700177 exynos_bl1: The filename of the exynos BL1 file
178 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
179 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700180 ecrw: The filename of the EC (Embedded Controller) read-write file.
181 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700182 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700183 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800184 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800185 skip_bmpblk: True if no bmpblk is required
Daisuke Nojiri69662892015-09-25 15:24:04 -0700186 cbfs_files: Root directory of files to be stored in CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700187 """
188 self._board = board
189 self.uboot_fname = uboot
190 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800191 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700192 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800193 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200194 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700195 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700196 self.exynos_bl1 = exynos_bl1
197 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700198 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700199 self.ecrw_fname = ecrw
200 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700201 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700202 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800203 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800204 self.skip_bmpblk = skip_bmpblk
Daisuke Nojiri69662892015-09-25 15:24:04 -0700205 self.cbfs_files = cbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700206
Simon Glass00d027e2013-07-20 14:51:12 -0600207 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700208 """Set up options supported by Bundle.
209
210 Args:
211 small: Only create a signed U-Boot - don't produce the full packed
212 firmware image. This is useful for devs who want to replace just the
213 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700214 gbb_flags: Specification for string containing adjustments to make.
215 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600216 force_efs: Force firmware to use 'early firmware selection' feature,
217 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700218 """
219 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700220 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700221 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600222 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700223
Simon Glass22f39fb2013-02-09 13:44:14 -0800224 def _GetBuildRoot(self):
225 """Get the path to this board's 'firmware' directory.
226
227 Returns:
228 Path to firmware directory, with ## representing the path to the
229 chroot.
230 """
Simon Glass290a1802011-07-17 13:54:32 -0700231 if not self._board:
232 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800233 return os.path.join('##', 'build', self._board, 'firmware')
234
235 def _CheckFdtFilename(self, fname):
236 """Check provided FDT filename and return the correct name if needed.
237
238 Where the filename lacks a path, add a default path for this board.
239 Where no FDT filename is provided, select a default one for this board.
240
241 Args:
242 fname: Proposed FDT filename.
243
244 Returns:
245 Selected FDT filename, after validation.
246 """
247 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700248 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800249 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700250 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700251 base_name = re.sub('_', '-', self._board)
252
253 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700254 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700255 found_list = glob.glob(self._tools.Filename(wildcard))
256 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800257 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700258 else:
259 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700260 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700261
Simon Glass881964d2012-04-04 11:34:09 -0700262 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800263 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700264 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700265 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800266 return fname
267
268 def CheckOptions(self):
269 """Check provided options and select defaults."""
270 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700271
Simon Glass49b026b2013-04-26 16:38:42 -0700272 board_type = self._board.split('_')[0]
273 model = type_to_model.get(board_type)
274
Simon Glass290a1802011-07-17 13:54:32 -0700275 if not self.uboot_fname:
276 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
277 if not self.bct_fname:
278 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700279 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700280 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700281 if model:
282 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700283 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700284 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700285 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700286 if not self.coreboot_fname:
287 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
288 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700289 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700290 if not self.seabios_fname:
291 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700292 if not self.ecrw_fname:
293 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700294 if not self.pdrw_fname:
295 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700296 if not self.ecro_fname:
297 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700298
Simon Glass75759302012-03-15 20:26:53 -0700299 def GetFiles(self):
300 """Get a list of files that we know about.
301
302 This is the opposite of SetFiles except that we may have put in some
303 default names. It returns a dictionary containing the filename for
304 each of a number of pre-defined files.
305
306 Returns:
307 Dictionary, with one entry for each file.
308 """
309 file_list = {
310 'bct' : self.bct_fname,
311 'exynos-bl1' : self.exynos_bl1,
312 'exynos-bl2' : self.exynos_bl2,
313 }
314 return file_list
315
Simon Glass4a887b12012-10-23 16:29:03 -0700316 def DecodeGBBFlagsFromFdt(self):
317 """Get Google Binary Block flags from the FDT.
318
319 These should be in the chromeos-config node, like this:
320
321 chromeos-config {
322 gbb-flag-dev-screen-short-delay;
323 gbb-flag-force-dev-switch-on;
324 gbb-flag-force-dev-boot-usb;
325 gbb-flag-disable-fw-rollback-check;
326 };
327
328 Returns:
329 GBB flags value from FDT.
330 """
331 chromeos_config = self.fdt.GetProps("/chromeos-config")
332 gbb_flags = 0
333 for name in chromeos_config:
334 if name.startswith('gbb-flag-'):
335 flag_value = gbb_flag_properties.get(name[9:])
336 if flag_value:
337 gbb_flags |= flag_value
338 self._out.Notice("FDT: Enabling %s." % name)
339 else:
340 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
341 return gbb_flags
342
Simon Glass157c0662012-10-23 13:52:42 -0700343 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
344 """Decode ajustments to the provided GBB flags.
345
346 We support three options:
347
348 hex value: c2
349 defined value: force-dev-boot-usb,load-option-roms
350 adjust default value: -load-option-roms,+force-dev-boot-usb
351
352 The last option starts from the passed-in GBB flags and adds or removes
353 flags.
354
355 Args:
356 gbb_flags: Base (default) FDT flags.
357 adjustments: String containing adjustments to make.
358
359 Returns:
360 Updated FDT flags.
361 """
362 use_base_value = True
363 if adjustments:
364 try:
365 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700366 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700367 pass
368 for flag in adjustments.split(','):
369 oper = None
370 if flag[0] in ['-', '+']:
371 oper = flag[0]
372 flag = flag[1:]
373 value = gbb_flag_properties.get(flag)
374 if not value:
375 raise ValueError("Invalid GBB flag '%s'" % flag)
376 if oper == '+':
377 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800378 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700379 elif oper == '-':
380 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800381 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700382 else:
383 if use_base_value:
384 gbb_flags = 0
385 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800386 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700387 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800388 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700389
390 return gbb_flags
391
Simon Glass56577572011-07-19 11:08:06 +1200392 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700393 """Create a GBB for the image.
394
Simon Glass56577572011-07-19 11:08:06 +1200395 Args:
396 hardware_id: Hardware ID to use for this board. If None, then the
397 default from the Fdt will be used
398
Simon Glass89b86b82011-07-17 23:49:49 -0700399 Returns:
400 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700401 """
Simon Glass56577572011-07-19 11:08:06 +1200402 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800403 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700404 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700405 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700406
Simon Glass4a887b12012-10-23 16:29:03 -0700407 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800408
Simon Glass157c0662012-10-23 13:52:42 -0700409 # Allow command line to override flags
410 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
411
Simon Glass4a887b12012-10-23 16:29:03 -0700412 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700413 self._out.Progress('Creating GBB')
414 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
415 sizes = ['%#x' % size for size in sizes]
416 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700417 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800418
419 gbb_set_command = ['-s',
420 '--hwid=%s' % hardware_id,
421 '--rootkey=%s/root_key.vbpubk' % keydir,
422 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
423 '--flags=%d' % gbb_flags,
424 gbb]
425 if not self.skip_bmpblk:
426 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
427 self.bmpblk_fname),]
428
Simon Glass290a1802011-07-17 13:54:32 -0700429 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800430 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700431 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700432
Simon Glasse13ee2c2011-07-28 08:12:28 +1200433 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700434 """Sign an image so that the Tegra SOC will boot it.
435
436 Args:
437 bct: BCT file to use.
438 bootstub: Boot stub (U-Boot + fdt) file to sign.
439 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700440
441 Returns:
442 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700443 """
444 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200445 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700446 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200447 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700448 fd = open(config, 'w')
449 fd.write('Version = 1;\n')
450 fd.write('Redundancy = 1;\n')
451 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700452
453 # TODO(dianders): Right now, we don't have enough space in our flash map
454 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
455 # sure what this does for reliability, but at least things will fit...
456 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
457 if is_nand:
458 fd.write('Bctcopy = 1;\n')
459
Simon Glass89b86b82011-07-17 23:49:49 -0700460 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
461 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700462
Simon Glass89b86b82011-07-17 23:49:49 -0700463 fd.close()
464
465 self._tools.Run('cbootimage', [config, signed])
466 self._tools.OutputSize('BCT', bct)
467 self._tools.OutputSize('Signed image', signed)
468 return signed
469
Doug Anderson86ce5f42011-07-27 10:40:18 -0700470 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700471 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700472
473 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700474 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700475 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700476 """
Simon Glass468d8752012-09-19 16:36:19 -0700477 if bootcmd is not None:
478 if bootcmd == 'none':
479 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800480 self.fdt.PutString('/config', 'bootcmd', bootcmd)
481 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700482 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700483
Simon Glassa4934b72012-05-09 13:35:02 -0700484 def SetNodeEnabled(self, node_name, enabled):
485 """Set whether an node is enabled or disabled.
486
487 This simply sets the 'status' property of a node to "ok", or "disabled".
488
489 The node should either be a full path to the node (like '/uart@10200000')
490 or an alias property.
491
492 Aliases are supported like this:
493
494 aliases {
495 console = "/uart@10200000";
496 };
497
498 pointing to a node:
499
500 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700501 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700502 };
503
504 In this case, this function takes the name of the alias ('console' in
505 this case) and updates the status of the node that is pointed to, to
506 either ok or disabled. If the alias does not exist, a warning is
507 displayed.
508
509 Args:
510 node_name: Name of node (e.g. '/uart@10200000') or alias alias
511 (e.g. 'console') to adjust
512 enabled: True to enable, False to disable
513 """
514 # Look up the alias if this is an alias reference
515 if not node_name.startswith('/'):
516 lookup = self.fdt.GetString('/aliases', node_name, '')
517 if not lookup:
518 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
519 return
520 node_name = lookup
521 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700522 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700523 else:
524 status = 'disabled'
525 self.fdt.PutString(node_name, 'status', status)
526
527 def AddEnableList(self, enable_list):
528 """Process a list of nodes to enable/disable.
529
530 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700531 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700532 tuple:
533 node: The fdt node to write to will be <node> or pointed to by
534 /aliases/<node>. We can tell which
535 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700536
Vadim Bendebury507c0012013-06-09 12:49:25 -0700537 Raises:
538 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700539 """
540 if enable_list:
541 for node_name, enabled in enable_list:
542 try:
543 enabled = int(enabled)
544 if enabled not in (0, 1):
545 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700546 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700547 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700548 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700549 self.SetNodeEnabled(node_name, enabled)
550
Simon Glass290a1802011-07-17 13:54:32 -0700551 def AddConfigList(self, config_list, use_int=False):
552 """Add a list of config items to the fdt.
553
554 Normally these values are written to the fdt as strings, but integers
555 are also supported, in which case the values will be converted to integers
556 (if necessary) before being stored.
557
558 Args:
559 config_list: List of (config, value) tuples to add to the fdt. For each
560 tuple:
561 config: The fdt node to write to will be /config/<config>.
562 value: An integer or string value to write.
563 use_int: True to only write integer values.
564
565 Raises:
566 CmdError: if a value is required to be converted to integer but can't be.
567 """
568 if config_list:
569 for config in config_list:
570 value = config[1]
571 if use_int:
572 try:
573 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700574 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700575 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700576 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700577 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800578 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700579 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800580 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700581
Simon Glass7c2d5572011-11-15 14:47:08 -0800582 def DecodeTextBase(self, data):
583 """Look at a U-Boot image and try to decode its TEXT_BASE.
584
585 This works because U-Boot has a header with the value 0x12345678
586 immediately followed by the TEXT_BASE value. We can therefore read this
587 from the image with some certainty. We check only the first 40 words
588 since the header should be within that region.
589
Simon Glass96b50302012-07-20 06:55:28 +0100590 Since upstream Tegra has moved to having a 16KB SPL region at the start,
591 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
592 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
593
Simon Glass7c2d5572011-11-15 14:47:08 -0800594 Args:
595 data: U-Boot binary data
596
597 Returns:
598 Text base (integer) or None if none was found
599 """
600 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100601 for start in (0, 0x4000):
602 for i in range(start, start + 160, 4):
603 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800604
Simon Glass96b50302012-07-20 06:55:28 +0100605 # TODO(sjg): This does not cope with a big-endian target
606 value = struct.unpack('<I', word)[0]
607 if found:
608 return value - start
609 if value == 0x12345678:
610 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800611
612 return None
613
614 def CalcTextBase(self, name, fdt, fname):
615 """Calculate the TEXT_BASE to use for U-Boot.
616
617 Normally this value is in the fdt, so we just read it from there. But as
618 a second check we look at the image itself in case this is different, and
619 switch to that if it is.
620
621 This allows us to flash any U-Boot even if its TEXT_BASE is different.
622 This is particularly useful with upstream U-Boot which uses a different
623 value (which we will move to).
624 """
625 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800626 # The value that comes back from fdt.GetInt is signed, which makes no
627 # sense for an address base. Force it to unsigned.
628 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800629 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100630 text_base_str = '%#x' % text_base if text_base else 'None'
631 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
632 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800633
634 # If they are different, issue a warning and switch over.
635 if text_base and text_base != fdt_text_base:
636 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
637 "fdt value of %x. Using %x" % (text_base, name,
638 fdt_text_base, text_base))
639 fdt_text_base = text_base
640 return fdt_text_base
641
Simon Glass6dcc2f22011-07-28 15:26:49 +1200642 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700643 """Create a boot stub and a signed boot stub.
644
Simon Glass6dcc2f22011-07-28 15:26:49 +1200645 For postload:
646 We add a /config/postload-text-offset entry to the signed bootstub's
647 fdt so that U-Boot can find the postload code.
648
649 The raw (unsigned) bootstub will have a value of -1 for this since we will
650 simply append the postload code to the bootstub and it can find it there.
651 This will be used for RW A/B firmware.
652
653 For the signed case this value will specify where in the flash to find
654 the postload code. This will be used for RO firmware.
655
Simon Glass89b86b82011-07-17 23:49:49 -0700656 Args:
657 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800658 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200659 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700660
661 Returns:
662 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200663 Full path to bootstub (uboot + fdt(-1) + postload).
664 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700665
666 Raises:
667 CmdError if a command fails.
668 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200669 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800670 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700671 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200672
673 # Make a copy of the fdt for the bootstub
674 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700675 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700676 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200677
Simon Glass89b86b82011-07-17 23:49:49 -0700678 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700679 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
680 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700681 self._tools.OutputSize('Combined binary', bootstub)
682
Simon Glasse13ee2c2011-07-28 08:12:28 +1200683 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700684 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700685 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200686 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200687
688 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
689 data = self._tools.ReadFile(signed)
690
691 if postload:
692 # We must add postload to the bootstub since A and B will need to
693 # be able to find it without the /config/postload-text-offset mechanism.
694 bs_data = self._tools.ReadFile(bootstub)
695 bs_data += self._tools.ReadFile(postload)
696 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
697 self._tools.WriteFile(bootstub, bs_data)
698 self._tools.OutputSize('Combined binary with postload', bootstub)
699
700 # Now that we know the file size, adjust the fdt and re-sign
701 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800702 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200703 fdt_data = self._tools.ReadFile(fdt.fname)
704 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
705 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
706 postload_bootstub, text_base)
707 if len(data) != os.path.getsize(signed):
708 raise CmdError('Signed file size changed from %d to %d after updating '
709 'fdt' % (len(data), os.path.getsize(signed)))
710
711 # Re-read the signed image, and add the post-load binary.
712 data = self._tools.ReadFile(signed)
713 data += self._tools.ReadFile(postload)
714 self._tools.OutputSize('Post-load binary', postload)
715
716 self._tools.WriteFile(signed_postload, data)
717 self._tools.OutputSize('Final bootstub with postload', signed_postload)
718
719 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700720
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700721 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700722 """Create a coreboot boot stub.
723
724 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700725 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700726
727 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100728 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700729 """
730 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700731 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100732
733 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700734 return bootstub
735
Simon Glass7e199222012-03-13 15:51:18 -0700736
Simon Glass89b86b82011-07-17 23:49:49 -0700737 def _PackOutput(self, msg):
738 """Helper function to write output from PackFirmware (verbose level 2).
739
740 This is passed to PackFirmware for it to use to write output.
741
742 Args:
743 msg: Message to display.
744 """
745 self._out.Notice(msg)
746
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800747 def _PrepareCbfs(self, pack, blob_name):
748 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
749
750 When the blob name is defined as cbfs#<section>#<subsection>, fill the
751 <section>_<subsection> area in the flash map with a CBFS copy, putting the
752 CBFS header of the copy at the base of the section.
753
754 If --coreboot-elf parameter was specified during cros_bumdle_firmware
755 invocation, add the parameter of this option as the payload to the new
756 CBFS instance.
757
758 Args:
759 pack: a PackFirmware object describing the firmware image to build.
760 blob_name: a string, blob name describing what FMAP section this CBFS
761 copy is destined to
762 Raises:
763 CmdError if base coreboot image does not contain CBFS
764 """
765
766 if not self.coreboot_fname:
767 raise CmdError("coreboot file needed for blob % s", blob_name)
768
769 part_sections = blob_name.split('/')[1:]
770
771 # Base address and size of the desitnation partition
772 base, size = self.fdt.GetFlashPart(*part_sections)
773
774 # Create a coreboot copy to use as a scratch pad.
775 cb_copy = os.path.join(self._tools.outdir, 'cb_copy')
776 if not os.path.exists(cb_copy):
777 self._tools.WriteFile(cb_copy, self._tools.ReadFile(self.coreboot_fname))
778
779 # Copy CBFS to the required offset
780 self._tools.Run('cbfstool', [cb_copy, 'copy', '-D',
781 '%d' % base, '-s', '%d' % size])
782
783 # Add coreboot payload if so requested. Note that the some images use
784 # different payload for the rw sections, which is passed in as the value
785 # of the --uboot option in the command line.
786 if self.uboot_fname:
787 payload_fname = self.uboot_fname
788 elif self.coreboot_elf:
789 payload_fname = self.coreboot_elf
790 else:
791 payload_fname = None
792
793 if payload_fname:
794 self._tools.Run('cbfstool', [
795 cb_copy, 'add-payload', '-f', payload_fname,
796 '-n', 'fallback/payload', '-c', 'lzma' , '-H', '%d' % base])
797
Patrick Georgi964fb542015-10-16 16:52:03 +0200798 if self.ecrw_fname:
799 self._tools.Run('cbfstool', [
800 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
801 '-n', 'ecrw', '-A', 'sha256', '-H', '%d' % base ])
802
803 if self.pdrw_fname:
804 self._tools.Run('cbfstool', [
805 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
806 '-n', 'pdrw', '-A', 'sha256', '-H', '%d' % base ])
807
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800808 # And extract the blob for the FW section
809 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
810 self._tools.WriteFile(rw_section,
811 self._tools.ReadFile(cb_copy)[base:base+size])
812
813 pack.AddProperty(blob_name, rw_section)
814
815
Simon Glass439fe7a2012-03-09 16:19:34 -0800816 def _BuildBlob(self, pack, fdt, blob_type):
817 """Build the blob data for a particular blob type.
818
819 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700820 pack: a PackFirmware object describing the firmware image to build.
821 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800822 blob_type: The type of blob to create data for. Supported types are:
823 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
824 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700825
826 Raises:
827 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800828 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700829 # stupid pylint insists that sha256 is not in hashlib.
830 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800831 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700832 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800833 pack.AddProperty('coreboot', coreboot)
834 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700835 elif blob_type == 'legacy':
836 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800837 elif blob_type == 'signed':
838 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
839 self.postload_fname)
840 pack.AddProperty('bootstub', bootstub)
841 pack.AddProperty('signed', signed)
842 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700843 elif blob_type == 'exynos-bl1':
844 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700845
846 # TODO(sjg@chromium.org): Deprecate ecbin
847 elif blob_type in ['ecrw', 'ecbin']:
848 pack.AddProperty('ecrw', self.ecrw_fname)
849 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700850 elif blob_type == 'pdrw':
851 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800852 elif blob_type == 'ecrwhash':
853 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
854 ecrw = self._tools.ReadFile(self.ecrw_fname)
855 hasher = hashlib.sha256()
856 hasher.update(ecrw)
857 self._tools.WriteFile(ec_hash_file, hasher.digest())
858 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700859 elif blob_type == 'pdrwhash':
860 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
861 pdrw = self._tools.ReadFile(self.pdrw_fname)
862 hasher = hashlib.sha256()
863 hasher.update(pdrw)
864 self._tools.WriteFile(pd_hash_file, hasher.digest())
865 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700866 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700867 # crosbug.com/p/13143
868 # We cannot have an fmap in the EC image since there can be only one,
869 # which is the main fmap describing the whole image.
870 # Ultimately the EC will not have an fmap, since with software sync
871 # there is no flashrom involvement in updating the EC flash, and thus
872 # no need for the fmap.
873 # For now, mangle the fmap name to avoid problems.
874 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
875 data = self._tools.ReadFile(self.ecro_fname)
876 data = re.sub('__FMAP__', '__fMAP__', data)
877 self._tools.WriteFile(updated_ecro, data)
878 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600879 elif blob_type.startswith('exynos-bl2'):
880 # We need to configure this per node, so do it later
881 pass
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800882 elif blob_type.startswith('cbfs'):
883 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800884 elif pack.GetProperty(blob_type):
885 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800886 elif blob_type in self.blobs:
887 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800888 else:
889 raise CmdError("Unknown blob type '%s' required in flash map" %
890 blob_type)
891
Daisuke Nojiri69662892015-09-25 15:24:04 -0700892 def _AddCbfsFiles(self, bootstub):
893 for dir, subs, files in os.walk(self.cbfs_files):
894 for file in files:
895 file = os.path.join(dir, file)
896 cbfs_name = file.replace(self.cbfs_files, '', 1).strip('/')
897 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
898 '-n', cbfs_name, '-t', '0x50', '-c', 'lzma'])
899
Simon Glass290a1802011-07-17 13:54:32 -0700900 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700901 """Create a full firmware image, along with various by-products.
902
903 This uses the provided u-boot.bin, fdt and bct to create a firmware
904 image containing all the required parts. If the GBB is not supplied
905 then this will just return a signed U-Boot as the image.
906
907 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700908 gbb: a string, full path to the GBB file, or empty if a GBB is not
909 required.
910 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200911
912 Returns:
913 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700914 """
Simon Glass02d124a2012-03-02 14:47:20 -0800915 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700916
Simon Glass439fe7a2012-03-09 16:19:34 -0800917 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -0800918 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700919 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
920 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -0600921 if self._force_efs:
922 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -0600923 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
924 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800925
Simon Glass4f318912013-07-20 16:13:06 -0600926 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800927
928 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800929 if self.uboot_fname:
930 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800931 if self.skeleton_fname:
932 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700933 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700934
Simon Glassde9c8072012-07-02 22:29:02 -0700935 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
936 if self.kernel_fname:
937 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
938
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800939 if gbb:
940 pack.AddProperty('gbb', gbb)
Simon Glass9d088d92012-07-16 16:27:11 +0100941 blob_list = pack.GetBlobList()
942 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700943 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800944 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -0700945
Simon Glass7306b902012-12-17 15:06:21 -0800946 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700947 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700948 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +0800949 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -0800950 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +0800951 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700952 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800953 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800954 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700955
Simon Glass0a047bc2013-07-19 15:44:43 -0600956 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -0600957 todo = pack.GetMissingBlobs()
958 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -0600959 if blob.key.startswith('exynos-bl2'):
960 bl2 = ExynosBl2(self._tools, self._out)
961 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
962 self.exynos_bl2))
963
Simon Glassc90cf582012-03-13 15:40:47 -0700964 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700965
966 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800967 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700968
Simon Glass4c24f662013-07-19 15:53:02 -0600969 # Recalculate the Exynos BL2, since it may have a hash. The call to
970 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
971 # need to recalculate the hash.
972 for blob in todo:
973 if blob.key.startswith('exynos-bl2'):
974 bl2 = ExynosBl2(self._tools, self._out)
975 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
976 self.exynos_bl2))
977
Simon Glass6207efe2012-12-17 15:04:36 -0800978 # Make a copy of the fdt for the bootstub
979 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800980 if self.uboot_fname:
981 uboot_data = self._tools.ReadFile(self.uboot_fname)
982 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
983 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -0800984
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800985 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
986 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -0800987
Simon Glassa10282a2013-01-08 17:06:41 -0800988 # Fix up the coreboot image here, since we can't do this until we have
989 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +0100990 if 'coreboot' in blob_list:
991 bootstub = pack.GetProperty('coreboot')
992 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -0800993 if self.coreboot_elf:
994 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
995 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800996 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -0700997 text_base = 0x1110000
998
999 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1000 # 1110015: 66 bb 00 01 mov $0x100,%bx
1001 marker = struct.pack('<L', 0x0100bb66)
1002 pos = uboot_data.find(marker)
1003 if pos == -1 or pos > 0x100:
1004 raise ValueError('Cannot find U-Boot cold boot entry point')
1005 entry = text_base + pos
1006 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001007 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1008 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001009 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001010 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1011 '-n', 'u-boot.dtb', '-t', '0xac'])
Daisuke Nojiri69662892015-09-25 15:24:04 -07001012 if self.cbfs_files:
1013 self._AddCbfsFiles(bootstub)
Simon Glassb8ea1802012-12-17 15:08:00 -08001014 data = self._tools.ReadFile(bootstub)
1015 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1016 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001017
Julius Werneraa1fe942014-11-21 17:16:11 -08001018 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1019 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1020 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001021
Simon Glass208ad952013-02-10 11:16:46 -08001022 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001023 image = os.path.join(self._tools.outdir, 'image.bin')
1024 pack.PackImage(self._tools.outdir, image)
1025 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001026
Simon Glass439fe7a2012-03-09 16:19:34 -08001027 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001028 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001029 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001030
Simon Glassdedda6f2013-02-09 13:44:14 -08001031 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001032 """Select an FDT to control the firmware bundling
1033
Simon Glassdedda6f2013-02-09 13:44:14 -08001034 We make a copy of this which will include any on-the-fly changes we want
1035 to make.
1036
Simon Glass290a1802011-07-17 13:54:32 -07001037 Args:
1038 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001039 use_defaults: True to use a default FDT name if available, and to add
1040 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001041
Simon Glassc0f3dc62011-08-09 14:19:05 -07001042 Returns:
1043 The Fdt object of the original fdt file, which we will not modify.
1044
Simon Glassdedda6f2013-02-09 13:44:14 -08001045 Raises:
1046 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1047 False).
Simon Glass290a1802011-07-17 13:54:32 -07001048 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001049 if use_defaults:
1050 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001051 if not fdt_fname:
1052 raise ValueError('Please provide an FDT filename')
1053 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001054 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001055
1056 # For upstream, select the correct architecture .dtsi manually.
1057 if self._board == 'link' or 'x86' in self._board:
1058 arch_dts = 'coreboot.dtsi'
1059 elif self._board == 'daisy':
1060 arch_dts = 'exynos5250.dtsi'
1061 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001062 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001063
1064 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001065 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1066
1067 # Get the flashmap so we know what to build. For board variants use the
1068 # main board name as the key (drop the _<variant> suffix).
1069 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1070
1071 if not fdt.GetProp('/flash', 'reg', ''):
1072 fdt.InsertNodes(default_flashmap)
1073
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001074 # Only check for /iram and /config nodes for boards that require it.
1075 if self._board in ('daisy', 'peach'):
1076 # Insert default values for any essential properties that are missing.
1077 # This should only happen for upstream U-Boot, until our changes are
1078 # upstreamed.
1079 if not fdt.GetProp('/iram', 'reg', ''):
1080 self._out.Warning('Cannot find /iram, using default')
1081 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001082
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001083 # Sadly the pit branch has an invalid /memory node. Work around it
1084 # for now. crosbug.com/p/22184
1085 if (not fdt.GetProp('/memory', 'reg', '') or
1086 fdt.GetIntList('/memory', 'reg')[0] == 0):
1087 self._out.Warning('Cannot find /memory, using default')
1088 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001089
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001090 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
1091 self._out.Warning('Missing properties in /config, using defaults')
1092 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001093
Simon Glass7df773b2013-08-25 18:02:29 -06001094 # Remember our board type.
1095 fdt.PutString('/chromeos-config', 'board', self._board)
1096
Simon Glasse53abbc2013-08-21 22:29:55 -06001097 self.fdt = fdt
1098 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001099
Simon Glassc90cf582012-03-13 15:40:47 -07001100 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001101 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001102
1103 - Checks options, tools, output directory, fdt.
1104 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001105
1106 Args:
Simon Glass56577572011-07-19 11:08:06 +12001107 hardware_id: Hardware ID to use for this board. If None, then the
1108 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001109 output_fname: Output filename for the image. If this is not None, then
1110 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001111 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001112
1113 Returns:
1114 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001115 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001116 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1117 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1118 else:
Simon Glass56577572011-07-19 11:08:06 +12001119 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001120
1121 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001122 image, pack = self._CreateImage(gbb, self.fdt)
1123 if show_map:
1124 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001125 if output_fname:
1126 shutil.copyfile(image, output_fname)
1127 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001128 return image, pack.props