blob: 89d30e3dc71c5176b644c6a400f44f57f160ef8c [file] [log] [blame]
Simon Glass89b86b82011-07-17 23:49:49 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05005"""This module builds a firmware image.
Simon Glass89b86b82011-07-17 23:49:49 -07006
7This modules uses a few rudimentary other libraries for its activity.
8
9Here are the names we give to the various files we deal with. It is important
10to keep these consistent!
11
12 uboot u-boot.bin (with no device tree)
13 fdt the fdt blob
14 bct the BCT file
15 bootstub uboot + fdt
16 signed (uboot + fdt + bct) signed blob
17"""
18
Simon Glassceff3ff2012-04-04 11:23:45 -070019import glob
Gabe Blackcdbdfe12013-02-06 05:37:52 -080020import hashlib
Simon Glass89b86b82011-07-17 23:49:49 -070021import os
22import re
23
Simon Glass89b86b82011-07-17 23:49:49 -070024from fdt import Fdt
25from pack_firmware import PackFirmware
26import shutil
Simon Glass7c2d5572011-11-15 14:47:08 -080027import struct
Vadim Bendebury8c35e2e2014-05-06 12:55:50 -070028from flashmaps import default_flashmaps
Simon Glass439fe7a2012-03-09 16:19:34 -080029from tools import CmdError
Vadim Bendeburyb12e3352013-06-08 17:25:19 -070030from exynos import ExynosBl2
Simon Glass89b86b82011-07-17 23:49:49 -070031
32# This data is required by bmpblk_utility. Does it ever change?
33# It was stored with the chromeos-bootimage ebuild, but we want
34# this utility to work outside the chroot.
35yaml_data = '''
36bmpblock: 1.0
37
38images:
39 devmode: DeveloperBmp/DeveloperBmp.bmp
40 recovery: RecoveryBmp/RecoveryBmp.bmp
41 rec_yuck: RecoveryNoOSBmp/RecoveryNoOSBmp.bmp
42 rec_insert: RecoveryMissingOSBmp/RecoveryMissingOSBmp.bmp
43
44screens:
45 dev_en:
46 - [0, 0, devmode]
47 rec_en:
48 - [0, 0, recovery]
49 yuck_en:
50 - [0, 0, rec_yuck]
51 ins_en:
52 - [0, 0, rec_insert]
53
54localizations:
55 - [ dev_en, rec_en, yuck_en, ins_en ]
56'''
57
Simon Glass4a887b12012-10-23 16:29:03 -070058# Build GBB flags.
59# (src/platform/vboot_reference/firmware/include/gbb_header.h)
60gbb_flag_properties = {
61 'dev-screen-short-delay': 0x00000001,
62 'load-option-roms': 0x00000002,
63 'enable-alternate-os': 0x00000004,
64 'force-dev-switch-on': 0x00000008,
65 'force-dev-boot-usb': 0x00000010,
66 'disable-fw-rollback-check': 0x00000020,
67 'enter-triggers-tonorm': 0x00000040,
68 'force-dev-boot-legacy': 0x00000080,
Shawn Nematbakhsh07c19882014-08-19 10:21:59 -070069 'faft-key-overide': 0x00000100,
70 'disable-ec-software-sync': 0x00000200,
71 'default-dev-boot-legacy': 0x00000400,
72 'disable-pd-software-sync': 0x00000800,
Furquan Shaikhd4eac3b2015-05-15 18:05:09 -070073 'force-dev-boot-fastboot-full-cap': 0x00002000,
Mary Ruthvena759c322015-11-16 08:23:26 -080074 'enable-serial': 0x00004000,
Simon Glass4a887b12012-10-23 16:29:03 -070075}
76
Simon Glass49b026b2013-04-26 16:38:42 -070077# Maps board name to Exynos product number
78type_to_model = {
79 'peach' : '5420',
80 'daisy' : '5250'
81}
82
Simon Glass5076a7f2012-10-23 16:31:54 -070083def ListGoogleBinaryBlockFlags():
84 """Print out a list of GBB flags."""
85 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
86 for name, value in gbb_flag_properties.iteritems():
87 print ' %-30s %02x' % (name, value)
88
Aaron Durbin41c85b62015-12-17 17:40:29 -060089class BlobDeferral(Exception):
90 """An error indicating deferal of blob generation."""
91 pass
92
Simon Glass89b86b82011-07-17 23:49:49 -070093class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070094 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070095
Simon Glass290a1802011-07-17 13:54:32 -070096 Sequence of events:
97 bundle = Bundle(tools.Tools(), cros_output.Output())
98 bundle.SetDirs(...)
99 bundle.SetFiles(...)
100 bundle.SetOptions(...)
101 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -0700102 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -0700103 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -0700104
Simon Glass290a1802011-07-17 13:54:32 -0700105 Public properties:
106 fdt: The fdt object that we use for building our image. This wil be the
107 one specified by the user, except that we might add config options
108 to it. This is set up by SelectFdt() which must be called before
109 bundling starts.
110 uboot_fname: Full filename of the U-Boot binary we use.
111 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700112 spl_source: Source device to load U-Boot from, in SPL:
113 straps: Select device according to CPU strap pins
114 spi: Boot from SPI
115 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700116
117 Private attributes:
118 _small: True to create a 'small' signed U-Boot, False to produce a
119 full image. The small U-Boot is enough to boot but will not have
120 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700121 """
Simon Glass89b86b82011-07-17 23:49:49 -0700122
Simon Glass290a1802011-07-17 13:54:32 -0700123 def __init__(self, tools, output):
124 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700125
Simon Glass290a1802011-07-17 13:54:32 -0700126 Args:
127 tools: A tools.Tools object to use for external tools.
128 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700129 """
Simon Glass290a1802011-07-17 13:54:32 -0700130 self._tools = tools
131 self._out = output
132
133 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500134 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700135 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700136 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600137 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700138 self._gbb_flags = None
139 self._keydir = None
140 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700141 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700142 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800143 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700144 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700145 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700146 self.ecro_fname = None # Filename of EC read-only file
147 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700148 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700149 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
150 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700151 self.fdt = None # Our Fdt object.
152 self.kernel_fname = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700153 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700154 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700155 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700156
157 def SetDirs(self, keydir):
158 """Set up directories required for Bundle.
159
160 Args:
161 keydir: Directory containing keys to use for signing firmware.
162 """
163 self._keydir = keydir
164
Simon Glass6dcc2f22011-07-28 15:26:49 +1200165 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800166 coreboot_elf=None,
Simon Glass942bedb2016-05-14 16:19:59 -0600167 seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700168 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600169 kernel=None, blobs=None, skip_bmpblk=False, cbfs_files=None,
170 rocbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700171 """Set up files required for Bundle.
172
173 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500174 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700175 uboot: The filename of the u-boot.bin image to use.
176 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800177 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800178 coreboot: The filename of the coreboot image to use (on x86).
179 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Vincent Palatinf7286772011-10-12 14:31:53 -0700180 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700181 exynos_bl1: The filename of the exynos BL1 file
182 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
183 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700184 ecrw: The filename of the EC (Embedded Controller) read-write file.
185 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700186 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700187 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800188 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800189 skip_bmpblk: True if no bmpblk is required
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600190 cbfs_files: Root directory of files to be stored in RO and RW CBFS
191 rocbfs_files: Root directory of files to be stored in RO CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700192 """
193 self._board = board
194 self.uboot_fname = uboot
195 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800196 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700197 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800198 self.coreboot_elf = coreboot_elf
Vincent Palatinf7286772011-10-12 14:31:53 -0700199 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700200 self.exynos_bl1 = exynos_bl1
201 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700202 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700203 self.ecrw_fname = ecrw
204 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700205 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700206 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800207 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800208 self.skip_bmpblk = skip_bmpblk
Daisuke Nojiri69662892015-09-25 15:24:04 -0700209 self.cbfs_files = cbfs_files
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600210 self.rocbfs_files = rocbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700211
Simon Glass00d027e2013-07-20 14:51:12 -0600212 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700213 """Set up options supported by Bundle.
214
215 Args:
216 small: Only create a signed U-Boot - don't produce the full packed
217 firmware image. This is useful for devs who want to replace just the
218 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700219 gbb_flags: Specification for string containing adjustments to make.
220 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600221 force_efs: Force firmware to use 'early firmware selection' feature,
222 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700223 """
224 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700225 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700226 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600227 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700228
Simon Glass22f39fb2013-02-09 13:44:14 -0800229 def _GetBuildRoot(self):
230 """Get the path to this board's 'firmware' directory.
231
232 Returns:
233 Path to firmware directory, with ## representing the path to the
234 chroot.
235 """
Simon Glass290a1802011-07-17 13:54:32 -0700236 if not self._board:
237 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800238 return os.path.join('##', 'build', self._board, 'firmware')
239
240 def _CheckFdtFilename(self, fname):
241 """Check provided FDT filename and return the correct name if needed.
242
243 Where the filename lacks a path, add a default path for this board.
244 Where no FDT filename is provided, select a default one for this board.
245
246 Args:
247 fname: Proposed FDT filename.
248
249 Returns:
250 Selected FDT filename, after validation.
251 """
252 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700253 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800254 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700255 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700256 base_name = re.sub('_', '-', self._board)
257
258 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700259 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700260 found_list = glob.glob(self._tools.Filename(wildcard))
261 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800262 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700263 else:
264 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700265 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700266
Simon Glass881964d2012-04-04 11:34:09 -0700267 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800268 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700269 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700270 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800271 return fname
272
273 def CheckOptions(self):
274 """Check provided options and select defaults."""
275 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700276
Simon Glass49b026b2013-04-26 16:38:42 -0700277 board_type = self._board.split('_')[0]
278 model = type_to_model.get(board_type)
279
Simon Glass290a1802011-07-17 13:54:32 -0700280 if not self.uboot_fname:
281 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
282 if not self.bct_fname:
283 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700284 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700285 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700286 if model:
287 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700288 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700289 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700290 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700291 if not self.coreboot_fname:
292 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
293 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700294 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700295 if not self.seabios_fname:
296 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700297 if not self.ecrw_fname:
298 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700299 if not self.pdrw_fname:
300 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700301 if not self.ecro_fname:
302 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700303
Simon Glass75759302012-03-15 20:26:53 -0700304 def GetFiles(self):
305 """Get a list of files that we know about.
306
307 This is the opposite of SetFiles except that we may have put in some
308 default names. It returns a dictionary containing the filename for
309 each of a number of pre-defined files.
310
311 Returns:
312 Dictionary, with one entry for each file.
313 """
314 file_list = {
315 'bct' : self.bct_fname,
316 'exynos-bl1' : self.exynos_bl1,
317 'exynos-bl2' : self.exynos_bl2,
318 }
319 return file_list
320
Simon Glass4a887b12012-10-23 16:29:03 -0700321 def DecodeGBBFlagsFromFdt(self):
322 """Get Google Binary Block flags from the FDT.
323
324 These should be in the chromeos-config node, like this:
325
326 chromeos-config {
327 gbb-flag-dev-screen-short-delay;
328 gbb-flag-force-dev-switch-on;
329 gbb-flag-force-dev-boot-usb;
330 gbb-flag-disable-fw-rollback-check;
331 };
332
333 Returns:
334 GBB flags value from FDT.
335 """
336 chromeos_config = self.fdt.GetProps("/chromeos-config")
337 gbb_flags = 0
338 for name in chromeos_config:
339 if name.startswith('gbb-flag-'):
340 flag_value = gbb_flag_properties.get(name[9:])
341 if flag_value:
342 gbb_flags |= flag_value
343 self._out.Notice("FDT: Enabling %s." % name)
344 else:
345 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
346 return gbb_flags
347
Simon Glass157c0662012-10-23 13:52:42 -0700348 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
349 """Decode ajustments to the provided GBB flags.
350
351 We support three options:
352
353 hex value: c2
354 defined value: force-dev-boot-usb,load-option-roms
355 adjust default value: -load-option-roms,+force-dev-boot-usb
356
357 The last option starts from the passed-in GBB flags and adds or removes
358 flags.
359
360 Args:
361 gbb_flags: Base (default) FDT flags.
362 adjustments: String containing adjustments to make.
363
364 Returns:
365 Updated FDT flags.
366 """
367 use_base_value = True
368 if adjustments:
369 try:
370 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700371 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700372 pass
373 for flag in adjustments.split(','):
374 oper = None
375 if flag[0] in ['-', '+']:
376 oper = flag[0]
377 flag = flag[1:]
378 value = gbb_flag_properties.get(flag)
379 if not value:
380 raise ValueError("Invalid GBB flag '%s'" % flag)
381 if oper == '+':
382 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800383 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700384 elif oper == '-':
385 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800386 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700387 else:
388 if use_base_value:
389 gbb_flags = 0
390 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800391 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700392 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800393 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700394
395 return gbb_flags
396
Simon Glass56577572011-07-19 11:08:06 +1200397 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700398 """Create a GBB for the image.
399
Simon Glass56577572011-07-19 11:08:06 +1200400 Args:
401 hardware_id: Hardware ID to use for this board. If None, then the
402 default from the Fdt will be used
403
Simon Glass89b86b82011-07-17 23:49:49 -0700404 Returns:
405 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700406 """
Simon Glass56577572011-07-19 11:08:06 +1200407 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800408 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700409 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700410 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700411
Simon Glass4a887b12012-10-23 16:29:03 -0700412 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800413
Simon Glass157c0662012-10-23 13:52:42 -0700414 # Allow command line to override flags
415 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
416
Simon Glass4a887b12012-10-23 16:29:03 -0700417 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700418 self._out.Progress('Creating GBB')
Daisuke Nojiri10b193f2016-01-15 17:53:14 -0800419 if self.skip_bmpblk:
420 bmpfv_size = 0
421 else:
422 bmpfv_size = gbb_size - 0x2180
423 sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700424 sizes = ['%#x' % size for size in sizes]
425 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700426 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800427
428 gbb_set_command = ['-s',
429 '--hwid=%s' % hardware_id,
430 '--rootkey=%s/root_key.vbpubk' % keydir,
431 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
432 '--flags=%d' % gbb_flags,
433 gbb]
434 if not self.skip_bmpblk:
435 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
436 self.bmpblk_fname),]
437
Simon Glass290a1802011-07-17 13:54:32 -0700438 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800439 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700440 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700441
Simon Glasse13ee2c2011-07-28 08:12:28 +1200442 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700443 """Sign an image so that the Tegra SOC will boot it.
444
445 Args:
446 bct: BCT file to use.
447 bootstub: Boot stub (U-Boot + fdt) file to sign.
448 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700449
450 Returns:
451 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700452 """
453 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200454 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700455 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200456 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700457 fd = open(config, 'w')
458 fd.write('Version = 1;\n')
459 fd.write('Redundancy = 1;\n')
460 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700461
462 # TODO(dianders): Right now, we don't have enough space in our flash map
463 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
464 # sure what this does for reliability, but at least things will fit...
465 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
466 if is_nand:
467 fd.write('Bctcopy = 1;\n')
468
Simon Glass89b86b82011-07-17 23:49:49 -0700469 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
470 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700471
Simon Glass89b86b82011-07-17 23:49:49 -0700472 fd.close()
473
474 self._tools.Run('cbootimage', [config, signed])
475 self._tools.OutputSize('BCT', bct)
476 self._tools.OutputSize('Signed image', signed)
477 return signed
478
Doug Anderson86ce5f42011-07-27 10:40:18 -0700479 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700480 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700481
482 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700483 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700484 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700485 """
Simon Glass468d8752012-09-19 16:36:19 -0700486 if bootcmd is not None:
487 if bootcmd == 'none':
488 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800489 self.fdt.PutString('/config', 'bootcmd', bootcmd)
490 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700491 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700492
Simon Glassa4934b72012-05-09 13:35:02 -0700493 def SetNodeEnabled(self, node_name, enabled):
494 """Set whether an node is enabled or disabled.
495
496 This simply sets the 'status' property of a node to "ok", or "disabled".
497
498 The node should either be a full path to the node (like '/uart@10200000')
499 or an alias property.
500
501 Aliases are supported like this:
502
503 aliases {
504 console = "/uart@10200000";
505 };
506
507 pointing to a node:
508
509 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700510 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700511 };
512
513 In this case, this function takes the name of the alias ('console' in
514 this case) and updates the status of the node that is pointed to, to
515 either ok or disabled. If the alias does not exist, a warning is
516 displayed.
517
518 Args:
519 node_name: Name of node (e.g. '/uart@10200000') or alias alias
520 (e.g. 'console') to adjust
521 enabled: True to enable, False to disable
522 """
523 # Look up the alias if this is an alias reference
524 if not node_name.startswith('/'):
525 lookup = self.fdt.GetString('/aliases', node_name, '')
526 if not lookup:
527 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
528 return
529 node_name = lookup
530 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700531 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700532 else:
533 status = 'disabled'
534 self.fdt.PutString(node_name, 'status', status)
535
536 def AddEnableList(self, enable_list):
537 """Process a list of nodes to enable/disable.
538
539 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700540 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700541 tuple:
542 node: The fdt node to write to will be <node> or pointed to by
543 /aliases/<node>. We can tell which
544 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700545
Vadim Bendebury507c0012013-06-09 12:49:25 -0700546 Raises:
547 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700548 """
549 if enable_list:
550 for node_name, enabled in enable_list:
551 try:
552 enabled = int(enabled)
553 if enabled not in (0, 1):
554 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700555 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700556 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700557 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700558 self.SetNodeEnabled(node_name, enabled)
559
Simon Glass290a1802011-07-17 13:54:32 -0700560 def AddConfigList(self, config_list, use_int=False):
561 """Add a list of config items to the fdt.
562
563 Normally these values are written to the fdt as strings, but integers
564 are also supported, in which case the values will be converted to integers
565 (if necessary) before being stored.
566
567 Args:
568 config_list: List of (config, value) tuples to add to the fdt. For each
569 tuple:
570 config: The fdt node to write to will be /config/<config>.
571 value: An integer or string value to write.
572 use_int: True to only write integer values.
573
574 Raises:
575 CmdError: if a value is required to be converted to integer but can't be.
576 """
577 if config_list:
578 for config in config_list:
579 value = config[1]
580 if use_int:
581 try:
582 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700583 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700584 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700585 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700586 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800587 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700588 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800589 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700590
Simon Glass7c2d5572011-11-15 14:47:08 -0800591 def DecodeTextBase(self, data):
592 """Look at a U-Boot image and try to decode its TEXT_BASE.
593
594 This works because U-Boot has a header with the value 0x12345678
595 immediately followed by the TEXT_BASE value. We can therefore read this
596 from the image with some certainty. We check only the first 40 words
597 since the header should be within that region.
598
Simon Glass96b50302012-07-20 06:55:28 +0100599 Since upstream Tegra has moved to having a 16KB SPL region at the start,
600 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
601 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
602
Simon Glass7c2d5572011-11-15 14:47:08 -0800603 Args:
604 data: U-Boot binary data
605
606 Returns:
607 Text base (integer) or None if none was found
608 """
609 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100610 for start in (0, 0x4000):
611 for i in range(start, start + 160, 4):
612 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800613
Simon Glass96b50302012-07-20 06:55:28 +0100614 # TODO(sjg): This does not cope with a big-endian target
615 value = struct.unpack('<I', word)[0]
616 if found:
617 return value - start
618 if value == 0x12345678:
619 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800620
621 return None
622
623 def CalcTextBase(self, name, fdt, fname):
624 """Calculate the TEXT_BASE to use for U-Boot.
625
626 Normally this value is in the fdt, so we just read it from there. But as
627 a second check we look at the image itself in case this is different, and
628 switch to that if it is.
629
630 This allows us to flash any U-Boot even if its TEXT_BASE is different.
631 This is particularly useful with upstream U-Boot which uses a different
632 value (which we will move to).
633 """
634 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800635 # The value that comes back from fdt.GetInt is signed, which makes no
636 # sense for an address base. Force it to unsigned.
637 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800638 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100639 text_base_str = '%#x' % text_base if text_base else 'None'
640 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
641 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800642
643 # If they are different, issue a warning and switch over.
644 if text_base and text_base != fdt_text_base:
645 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
646 "fdt value of %x. Using %x" % (text_base, name,
647 fdt_text_base, text_base))
648 fdt_text_base = text_base
649 return fdt_text_base
650
Simon Glass6dcc2f22011-07-28 15:26:49 +1200651 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700652 """Create a boot stub and a signed boot stub.
653
Simon Glass6dcc2f22011-07-28 15:26:49 +1200654 For postload:
655 We add a /config/postload-text-offset entry to the signed bootstub's
656 fdt so that U-Boot can find the postload code.
657
658 The raw (unsigned) bootstub will have a value of -1 for this since we will
659 simply append the postload code to the bootstub and it can find it there.
660 This will be used for RW A/B firmware.
661
662 For the signed case this value will specify where in the flash to find
663 the postload code. This will be used for RO firmware.
664
Simon Glass89b86b82011-07-17 23:49:49 -0700665 Args:
666 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800667 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200668 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700669
670 Returns:
671 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200672 Full path to bootstub (uboot + fdt(-1) + postload).
673 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700674
675 Raises:
676 CmdError if a command fails.
677 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200678 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800679 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700680 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200681
682 # Make a copy of the fdt for the bootstub
683 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700684 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700685 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200686
Simon Glass89b86b82011-07-17 23:49:49 -0700687 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700688 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
689 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700690 self._tools.OutputSize('Combined binary', bootstub)
691
Simon Glasse13ee2c2011-07-28 08:12:28 +1200692 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700693 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700694 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200695 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200696
697 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
698 data = self._tools.ReadFile(signed)
699
700 if postload:
701 # We must add postload to the bootstub since A and B will need to
702 # be able to find it without the /config/postload-text-offset mechanism.
703 bs_data = self._tools.ReadFile(bootstub)
704 bs_data += self._tools.ReadFile(postload)
705 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
706 self._tools.WriteFile(bootstub, bs_data)
707 self._tools.OutputSize('Combined binary with postload', bootstub)
708
709 # Now that we know the file size, adjust the fdt and re-sign
710 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800711 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200712 fdt_data = self._tools.ReadFile(fdt.fname)
713 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
714 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
715 postload_bootstub, text_base)
716 if len(data) != os.path.getsize(signed):
717 raise CmdError('Signed file size changed from %d to %d after updating '
718 'fdt' % (len(data), os.path.getsize(signed)))
719
720 # Re-read the signed image, and add the post-load binary.
721 data = self._tools.ReadFile(signed)
722 data += self._tools.ReadFile(postload)
723 self._tools.OutputSize('Post-load binary', postload)
724
725 self._tools.WriteFile(signed_postload, data)
726 self._tools.OutputSize('Final bootstub with postload', signed_postload)
727
728 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700729
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600730 def _AddCbfsFiles(self, bootstub, cbfs_files):
731 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600732 for file in files:
733 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600734 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600735 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
736 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma'])
737
738 def _CreateCorebootStub(self, pack, coreboot):
739 """Create a coreboot boot stub and add pack properties.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700740
741 Args:
Aaron Durbina113f522016-01-05 09:09:55 -0600742 pack: a PackFirmware object describing the firmware image to build.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700743 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700744 """
745 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700746 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100747
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600748 pack.AddProperty('coreboot', bootstub)
749 pack.AddProperty('image', bootstub)
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700750
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600751 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600752 if self.cbfs_files:
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600753 self._AddCbfsFiles(bootstub, self.cbfs_files)
Simon Glass7e199222012-03-13 15:51:18 -0700754
Aaron Durbina113f522016-01-05 09:09:55 -0600755 # Create a coreboot copy to use as a scratch pad. Order matters. The
756 # cbfs_files were added prior to this action. That's so the RW CBFS
Patrick Georgi3a332672015-11-20 10:02:51 +0100757 # regions inherit the files from the RO CBFS region. Additionally,
758 # include the full FMAP within the file.
759 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600760 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100761 binary = self._tools.ReadFile(bootstub)
762 fmap_offset, fmap = pack.GetFmap()
763 if len(binary) < fmap_offset + len(fmap):
764 raise CmdError('FMAP will not fit')
765 # Splice in FMAP data.
766 binary = binary[:fmap_offset] + fmap + binary[fmap_offset + len(fmap):]
767 self._tools.WriteFile(cb_copy, binary)
768 # Publish where coreboot is with the FMAP data.
769 pack.AddProperty('cb_with_fmap', cb_copy)
Aaron Durbina113f522016-01-05 09:09:55 -0600770
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600771 # Add files to to RO CBFS if provided. This done here such that the
772 # copy above does not contain the RO CBFS files.
773 if self.rocbfs_files:
774 self._AddCbfsFiles(bootstub, self.rocbfs_files)
775
Aaron Durbina113f522016-01-05 09:09:55 -0600776
Simon Glass89b86b82011-07-17 23:49:49 -0700777 def _PackOutput(self, msg):
778 """Helper function to write output from PackFirmware (verbose level 2).
779
780 This is passed to PackFirmware for it to use to write output.
781
782 Args:
783 msg: Message to display.
784 """
785 self._out.Notice(msg)
786
Aaron Durbin80564452015-12-21 15:25:06 -0600787 def _FmapNameByPath(self, path):
788 """ Take list of names to form node path. Return FMAP name.
789
790 Obtain the FMAP name described by the node path.
791
792 Args:
793 path: list forming a node path.
794
795 Returns:
796 FMAP name of fdt node.
797
798 Raises:
799 CmdError if path not found.
800 """
801 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
802 return re.sub('-', '_', lbl).upper()
803
804 def _PrepareCbfsHash(self, pack, blob_name):
805 """Create blob in rw-{a,b}-boothash with 'cbfstool hashcbfs'.
806
807 When the blob name is defined as cbfshash/<section>/<subsection>, fill the
808 <section>_<subsection> area in the flash map with CBFS hash generated
809 using the 'cbfstool hashcbfs' command.
810
811 Args:
812 pack: a PackFirmware object describing the firmware image to build.
813 blob_name: a string, blob name describing what FMAP section this CBFS
814 copy is destined to
815 Raises:
816 CmdError if cbfs-files node has incorrect parameters.
817 BlobDeferral if the CBFS region is not populated yet or if the coreboot
818 image with fmap is not available yet.
819 """
820 cb_copy = pack.GetProperty('cb_with_fmap')
821 if cb_copy is None:
822 raise BlobDeferral("Waiting for '%s'" % cb_copy)
823
824 part_sections = blob_name.split('/')[1:]
825 fmap_dst = self._FmapNameByPath(part_sections)
826
827 # Example of FDT ndoes asking for CBFS hash:
828 # rw-b-boot {
829 # label = "fw-main-b";
830 # reg = <0x00700000 0x002dff80>;
831 # type = "blob cbfs/rw/b-boot";
832 # };
833 # rw-b-boothash {
834 # label = "fw-main-b-hash";
835 # reg = <0x009dff80 0x00000040>;
836 # type = "blob cbfshash/rw/b-boothash";
837 # cbfs-node = "cbfs/rw/b-boot";
838 # };
839 hash_node = self.fdt.GetFlashNode(*part_sections)
840 cbfs_blob_name = self.fdt.GetString(hash_node, 'cbfs-node')
841
842 if not pack.GetProperty(cbfs_blob_name):
843 raise BlobDeferral("Waiting for '%s'" % cbfs_blob_name)
844
845 cbfs_node_path = cbfs_blob_name.split('/')[1:]
846 fmap_src = self._FmapNameByPath(cbfs_node_path)
847
848 # Compute CBFS hash and place it in the corect spot.
849 self._tools.Run('cbfstool', [cb_copy, 'hashcbfs', '-r', fmap_dst,
850 '-R', fmap_src, '-A', 'sha256'])
851
852 # Base address and size of the desitnation partition
853 base, size = self.fdt.GetFlashPart(*part_sections)
854
855 # And extract the blob for the FW section
856 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
857 self._tools.WriteFile(rw_section,
858 self._tools.ReadFile(cb_copy)[base:base+size])
859
860 pack.AddProperty(blob_name, rw_section)
861
862
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800863 def _PrepareCbfs(self, pack, blob_name):
864 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
865
866 When the blob name is defined as cbfs#<section>#<subsection>, fill the
867 <section>_<subsection> area in the flash map with a CBFS copy, putting the
868 CBFS header of the copy at the base of the section.
869
870 If --coreboot-elf parameter was specified during cros_bumdle_firmware
871 invocation, add the parameter of this option as the payload to the new
872 CBFS instance.
873
874 Args:
875 pack: a PackFirmware object describing the firmware image to build.
876 blob_name: a string, blob name describing what FMAP section this CBFS
877 copy is destined to
878 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100879 CmdError if cbfs-files node has incorrect parameters.
Aaron Durbina113f522016-01-05 09:09:55 -0600880 BlobDeferral if coreboot image with fmap is not available yet.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800881 """
Patrick Georgi3a332672015-11-20 10:02:51 +0100882 cb_copy = pack.GetProperty('cb_with_fmap')
Aaron Durbina113f522016-01-05 09:09:55 -0600883 if cb_copy is None:
Patrick Georgi3a332672015-11-20 10:02:51 +0100884 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800885
886 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600887 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800888
889 # Base address and size of the desitnation partition
890 base, size = self.fdt.GetFlashPart(*part_sections)
891
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800892 # Add coreboot payload if so requested. Note that the some images use
893 # different payload for the rw sections, which is passed in as the value
894 # of the --uboot option in the command line.
895 if self.uboot_fname:
896 payload_fname = self.uboot_fname
897 elif self.coreboot_elf:
898 payload_fname = self.coreboot_elf
899 else:
900 payload_fname = None
901
902 if payload_fname:
903 self._tools.Run('cbfstool', [
904 cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100905 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800906
Patrick Georgi964fb542015-10-16 16:52:03 +0200907 if self.ecrw_fname:
908 self._tools.Run('cbfstool', [
909 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100910 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200911
912 if self.pdrw_fname:
913 self._tools.Run('cbfstool', [
914 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100915 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200916
Aaron Durbin880cf952016-01-27 14:11:38 -0600917 # Parse the file list to obtain the last entry. If its empty use its
918 # offset as the size of the CBFS to hash.
919 stdout = self._tools.Run('cbfstool',
920 [ cb_copy, 'print', '-k', '-r', fmap_dst ])
921 # Fields are tab separated in the following order.
922 # Name Offset Type Metadata Size Data Size Total Size
923 last_entry = stdout.strip().splitlines()[-1].split('\t')
924 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
925 size = int(last_entry[1], 16)
926
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800927 # And extract the blob for the FW section
928 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
929 self._tools.WriteFile(rw_section,
930 self._tools.ReadFile(cb_copy)[base:base+size])
931
932 pack.AddProperty(blob_name, rw_section)
933
934
Simon Glass439fe7a2012-03-09 16:19:34 -0800935 def _BuildBlob(self, pack, fdt, blob_type):
936 """Build the blob data for a particular blob type.
937
938 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700939 pack: a PackFirmware object describing the firmware image to build.
940 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800941 blob_type: The type of blob to create data for. Supported types are:
942 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
943 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700944
945 Raises:
946 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -0600947 BlobDeferral if a blob is waiting for a dependency.
Simon Glass439fe7a2012-03-09 16:19:34 -0800948 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700949 # stupid pylint insists that sha256 is not in hashlib.
950 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800951 if blob_type == 'coreboot':
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600952 self._CreateCorebootStub(pack, self.coreboot_fname)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700953 elif blob_type == 'legacy':
954 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800955 elif blob_type == 'signed':
Simon Glass942bedb2016-05-14 16:19:59 -0600956 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt, None)
Simon Glass439fe7a2012-03-09 16:19:34 -0800957 pack.AddProperty('bootstub', bootstub)
958 pack.AddProperty('signed', signed)
959 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700960 elif blob_type == 'exynos-bl1':
961 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700962
963 # TODO(sjg@chromium.org): Deprecate ecbin
964 elif blob_type in ['ecrw', 'ecbin']:
965 pack.AddProperty('ecrw', self.ecrw_fname)
966 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700967 elif blob_type == 'pdrw':
968 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800969 elif blob_type == 'ecrwhash':
970 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
971 ecrw = self._tools.ReadFile(self.ecrw_fname)
972 hasher = hashlib.sha256()
973 hasher.update(ecrw)
974 self._tools.WriteFile(ec_hash_file, hasher.digest())
975 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700976 elif blob_type == 'pdrwhash':
977 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
978 pdrw = self._tools.ReadFile(self.pdrw_fname)
979 hasher = hashlib.sha256()
980 hasher.update(pdrw)
981 self._tools.WriteFile(pd_hash_file, hasher.digest())
982 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700983 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700984 # crosbug.com/p/13143
985 # We cannot have an fmap in the EC image since there can be only one,
986 # which is the main fmap describing the whole image.
987 # Ultimately the EC will not have an fmap, since with software sync
988 # there is no flashrom involvement in updating the EC flash, and thus
989 # no need for the fmap.
990 # For now, mangle the fmap name to avoid problems.
991 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
992 data = self._tools.ReadFile(self.ecro_fname)
993 data = re.sub('__FMAP__', '__fMAP__', data)
994 self._tools.WriteFile(updated_ecro, data)
995 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600996 elif blob_type.startswith('exynos-bl2'):
997 # We need to configure this per node, so do it later
998 pass
Aaron Durbin80564452015-12-21 15:25:06 -0600999 elif blob_type.startswith('cbfshash'):
1000 self._PrepareCbfsHash(pack, blob_type)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -08001001 elif blob_type.startswith('cbfs'):
1002 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -08001003 elif pack.GetProperty(blob_type):
1004 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -08001005 elif blob_type in self.blobs:
1006 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -08001007 else:
1008 raise CmdError("Unknown blob type '%s' required in flash map" %
1009 blob_type)
1010
Aaron Durbin41c85b62015-12-17 17:40:29 -06001011 def _BuildBlobs(self, pack, fdt):
1012 """Build the blob data for the list of blobs in the pack.
1013
1014 Args:
1015 pack: a PackFirmware object describing the firmware image to build.
1016 fdt: an fdt object including image layout information
1017
1018 Raises:
1019 CmdError if a command fails.
1020 BlobDeferral if dependencies cannot be met because of cycles.
1021 """
1022 blob_list = pack.GetBlobList()
1023 self._out.Info('Building blobs %s\n' % blob_list)
1024
1025 complete = False
1026 deferred_list = []
1027
1028 # Build blobs allowing for dependencies between blobs. While this is
1029 # an potential O(n^2) operation, in practice most blobs aren't dependent
1030 # and should resolve in a few passes.
1031 while not complete:
1032 orig = set(blob_list)
1033 for blob_type in blob_list:
1034 try:
1035 self._BuildBlob(pack, fdt, blob_type)
1036 except (BlobDeferral):
1037 deferred_list.append(blob_type)
1038 if not deferred_list:
1039 complete = True
1040 # If deferred is the same as the original no progress is being made.
1041 if not orig - set(deferred_list):
1042 raise BlobDeferral("Blob cyle '%s'" % orig)
1043 # Process the deferred blobs
1044 blob_list = deferred_list[:]
1045 deferred_list = []
1046
Simon Glass290a1802011-07-17 13:54:32 -07001047 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -07001048 """Create a full firmware image, along with various by-products.
1049
1050 This uses the provided u-boot.bin, fdt and bct to create a firmware
1051 image containing all the required parts. If the GBB is not supplied
1052 then this will just return a signed U-Boot as the image.
1053
1054 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -07001055 gbb: a string, full path to the GBB file, or empty if a GBB is not
1056 required.
1057 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +12001058
1059 Returns:
1060 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001061 """
Simon Glass02d124a2012-03-02 14:47:20 -08001062 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001063
Simon Glass439fe7a2012-03-09 16:19:34 -08001064 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -08001065 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001066 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
1067 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -06001068 if self._force_efs:
1069 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -06001070 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
1071 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001072
Simon Glass4f318912013-07-20 16:13:06 -06001073 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -08001074
1075 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001076 if self.uboot_fname:
1077 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001078 if self.skeleton_fname:
1079 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001080 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001081
Simon Glassde9c8072012-07-02 22:29:02 -07001082 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1083 if self.kernel_fname:
1084 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1085
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001086 if gbb:
1087 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -06001088
1089 # Build the blobs out.
1090 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -07001091
Simon Glass7306b902012-12-17 15:06:21 -08001092 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001093 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001094 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001095 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001096 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001097 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001098 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001099 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001100 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001101
Simon Glass0a047bc2013-07-19 15:44:43 -06001102 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001103 todo = pack.GetMissingBlobs()
1104 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001105 if blob.key.startswith('exynos-bl2'):
1106 bl2 = ExynosBl2(self._tools, self._out)
1107 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1108 self.exynos_bl2))
1109
Simon Glassc90cf582012-03-13 15:40:47 -07001110 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001111
1112 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001113 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001114
Simon Glass4c24f662013-07-19 15:53:02 -06001115 # Recalculate the Exynos BL2, since it may have a hash. The call to
1116 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1117 # need to recalculate the hash.
1118 for blob in todo:
1119 if blob.key.startswith('exynos-bl2'):
1120 bl2 = ExynosBl2(self._tools, self._out)
1121 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1122 self.exynos_bl2))
1123
Simon Glass6207efe2012-12-17 15:04:36 -08001124 # Make a copy of the fdt for the bootstub
1125 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001126 if self.uboot_fname:
1127 uboot_data = self._tools.ReadFile(self.uboot_fname)
1128 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1129 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001130
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001131 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1132 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001133
Simon Glassa10282a2013-01-08 17:06:41 -08001134 # Fix up the coreboot image here, since we can't do this until we have
1135 # a final device tree binary.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001136 if 'coreboot' in pack.GetBlobList():
Simon Glasscbc83552012-07-23 15:26:22 +01001137 bootstub = pack.GetProperty('coreboot')
1138 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001139 if self.coreboot_elf:
1140 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1141 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001142 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001143 text_base = 0x1110000
1144
1145 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1146 # 1110015: 66 bb 00 01 mov $0x100,%bx
1147 marker = struct.pack('<L', 0x0100bb66)
1148 pos = uboot_data.find(marker)
1149 if pos == -1 or pos > 0x100:
1150 raise ValueError('Cannot find U-Boot cold boot entry point')
1151 entry = text_base + pos
1152 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001153 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1154 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001155 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001156 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1157 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001158 data = self._tools.ReadFile(bootstub)
1159 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1160 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001161
Julius Werneraa1fe942014-11-21 17:16:11 -08001162 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1163 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1164 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001165
Simon Glass208ad952013-02-10 11:16:46 -08001166 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001167 image = os.path.join(self._tools.outdir, 'image.bin')
1168 pack.PackImage(self._tools.outdir, image)
1169 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001170
Simon Glass439fe7a2012-03-09 16:19:34 -08001171 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001172 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001173 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001174
Simon Glassdedda6f2013-02-09 13:44:14 -08001175 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001176 """Select an FDT to control the firmware bundling
1177
Simon Glassdedda6f2013-02-09 13:44:14 -08001178 We make a copy of this which will include any on-the-fly changes we want
1179 to make.
1180
Simon Glass290a1802011-07-17 13:54:32 -07001181 Args:
1182 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001183 use_defaults: True to use a default FDT name if available, and to add
1184 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001185
Simon Glassc0f3dc62011-08-09 14:19:05 -07001186 Returns:
1187 The Fdt object of the original fdt file, which we will not modify.
1188
Simon Glassdedda6f2013-02-09 13:44:14 -08001189 Raises:
1190 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1191 False).
Simon Glass290a1802011-07-17 13:54:32 -07001192 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001193 if use_defaults:
1194 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001195 if not fdt_fname:
1196 raise ValueError('Please provide an FDT filename')
1197 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001198 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001199
1200 # For upstream, select the correct architecture .dtsi manually.
1201 if self._board == 'link' or 'x86' in self._board:
1202 arch_dts = 'coreboot.dtsi'
1203 elif self._board == 'daisy':
1204 arch_dts = 'exynos5250.dtsi'
1205 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001206 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001207
1208 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001209 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1210
1211 # Get the flashmap so we know what to build. For board variants use the
1212 # main board name as the key (drop the _<variant> suffix).
1213 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1214
1215 if not fdt.GetProp('/flash', 'reg', ''):
1216 fdt.InsertNodes(default_flashmap)
1217
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001218 # Only check for /iram and /config nodes for boards that require it.
1219 if self._board in ('daisy', 'peach'):
1220 # Insert default values for any essential properties that are missing.
1221 # This should only happen for upstream U-Boot, until our changes are
1222 # upstreamed.
1223 if not fdt.GetProp('/iram', 'reg', ''):
1224 self._out.Warning('Cannot find /iram, using default')
1225 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001226
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001227 # Sadly the pit branch has an invalid /memory node. Work around it
1228 # for now. crosbug.com/p/22184
1229 if (not fdt.GetProp('/memory', 'reg', '') or
1230 fdt.GetIntList('/memory', 'reg')[0] == 0):
1231 self._out.Warning('Cannot find /memory, using default')
1232 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001233
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001234 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
1235 self._out.Warning('Missing properties in /config, using defaults')
1236 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001237
Simon Glass7df773b2013-08-25 18:02:29 -06001238 # Remember our board type.
1239 fdt.PutString('/chromeos-config', 'board', self._board)
1240
Simon Glasse53abbc2013-08-21 22:29:55 -06001241 self.fdt = fdt
1242 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001243
Simon Glassc90cf582012-03-13 15:40:47 -07001244 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001245 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001246
1247 - Checks options, tools, output directory, fdt.
1248 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001249
1250 Args:
Simon Glass56577572011-07-19 11:08:06 +12001251 hardware_id: Hardware ID to use for this board. If None, then the
1252 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001253 output_fname: Output filename for the image. If this is not None, then
1254 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001255 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001256
1257 Returns:
1258 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001259 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001260 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1261 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1262 else:
Simon Glass56577572011-07-19 11:08:06 +12001263 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001264
1265 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001266 image, pack = self._CreateImage(gbb, self.fdt)
1267 if show_map:
1268 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001269 if output_fname:
1270 shutil.copyfile(image, output_fname)
1271 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001272 return image, pack.props