blob: 2c3fa49e70cd15a076a6217573e1868f8eddbb7c [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
153 self.postload_fname = None
154 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700155 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700156 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700157
158 def SetDirs(self, keydir):
159 """Set up directories required for Bundle.
160
161 Args:
162 keydir: Directory containing keys to use for signing firmware.
163 """
164 self._keydir = keydir
165
Simon Glass6dcc2f22011-07-28 15:26:49 +1200166 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800167 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700168 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700169 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600170 kernel=None, blobs=None, skip_bmpblk=False, cbfs_files=None,
171 rocbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700172 """Set up files required for Bundle.
173
174 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500175 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700176 uboot: The filename of the u-boot.bin image to use.
177 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800178 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800179 coreboot: The filename of the coreboot image to use (on x86).
180 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200181 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700182 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700183 exynos_bl1: The filename of the exynos BL1 file
184 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
185 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700186 ecrw: The filename of the EC (Embedded Controller) read-write file.
187 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700188 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700189 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800190 blobs: List of (type, filename) of arbitrary blobs.
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800191 skip_bmpblk: True if no bmpblk is required
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600192 cbfs_files: Root directory of files to be stored in RO and RW CBFS
193 rocbfs_files: Root directory of files to be stored in RO CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700194 """
195 self._board = board
196 self.uboot_fname = uboot
197 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800198 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700199 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800200 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200201 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700202 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700203 self.exynos_bl1 = exynos_bl1
204 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700205 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700206 self.ecrw_fname = ecrw
207 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700208 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700209 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800210 self.blobs = dict(blobs or ())
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800211 self.skip_bmpblk = skip_bmpblk
Daisuke Nojiri69662892015-09-25 15:24:04 -0700212 self.cbfs_files = cbfs_files
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600213 self.rocbfs_files = rocbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700214
Simon Glass00d027e2013-07-20 14:51:12 -0600215 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700216 """Set up options supported by Bundle.
217
218 Args:
219 small: Only create a signed U-Boot - don't produce the full packed
220 firmware image. This is useful for devs who want to replace just the
221 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700222 gbb_flags: Specification for string containing adjustments to make.
223 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600224 force_efs: Force firmware to use 'early firmware selection' feature,
225 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700226 """
227 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700228 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700229 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600230 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700231
Simon Glass22f39fb2013-02-09 13:44:14 -0800232 def _GetBuildRoot(self):
233 """Get the path to this board's 'firmware' directory.
234
235 Returns:
236 Path to firmware directory, with ## representing the path to the
237 chroot.
238 """
Simon Glass290a1802011-07-17 13:54:32 -0700239 if not self._board:
240 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800241 return os.path.join('##', 'build', self._board, 'firmware')
242
243 def _CheckFdtFilename(self, fname):
244 """Check provided FDT filename and return the correct name if needed.
245
246 Where the filename lacks a path, add a default path for this board.
247 Where no FDT filename is provided, select a default one for this board.
248
249 Args:
250 fname: Proposed FDT filename.
251
252 Returns:
253 Selected FDT filename, after validation.
254 """
255 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700256 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800257 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700258 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700259 base_name = re.sub('_', '-', self._board)
260
261 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700262 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700263 found_list = glob.glob(self._tools.Filename(wildcard))
264 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800265 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700266 else:
267 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700268 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700269
Simon Glass881964d2012-04-04 11:34:09 -0700270 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800271 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700272 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700273 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800274 return fname
275
276 def CheckOptions(self):
277 """Check provided options and select defaults."""
278 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700279
Simon Glass49b026b2013-04-26 16:38:42 -0700280 board_type = self._board.split('_')[0]
281 model = type_to_model.get(board_type)
282
Simon Glass290a1802011-07-17 13:54:32 -0700283 if not self.uboot_fname:
284 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
285 if not self.bct_fname:
286 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700287 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700288 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700289 if model:
290 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700291 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700292 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700293 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700294 if not self.coreboot_fname:
295 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
296 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700297 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700298 if not self.seabios_fname:
299 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700300 if not self.ecrw_fname:
301 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700302 if not self.pdrw_fname:
303 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700304 if not self.ecro_fname:
305 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700306
Simon Glass75759302012-03-15 20:26:53 -0700307 def GetFiles(self):
308 """Get a list of files that we know about.
309
310 This is the opposite of SetFiles except that we may have put in some
311 default names. It returns a dictionary containing the filename for
312 each of a number of pre-defined files.
313
314 Returns:
315 Dictionary, with one entry for each file.
316 """
317 file_list = {
318 'bct' : self.bct_fname,
319 'exynos-bl1' : self.exynos_bl1,
320 'exynos-bl2' : self.exynos_bl2,
321 }
322 return file_list
323
Simon Glass4a887b12012-10-23 16:29:03 -0700324 def DecodeGBBFlagsFromFdt(self):
325 """Get Google Binary Block flags from the FDT.
326
327 These should be in the chromeos-config node, like this:
328
329 chromeos-config {
330 gbb-flag-dev-screen-short-delay;
331 gbb-flag-force-dev-switch-on;
332 gbb-flag-force-dev-boot-usb;
333 gbb-flag-disable-fw-rollback-check;
334 };
335
336 Returns:
337 GBB flags value from FDT.
338 """
339 chromeos_config = self.fdt.GetProps("/chromeos-config")
340 gbb_flags = 0
341 for name in chromeos_config:
342 if name.startswith('gbb-flag-'):
343 flag_value = gbb_flag_properties.get(name[9:])
344 if flag_value:
345 gbb_flags |= flag_value
346 self._out.Notice("FDT: Enabling %s." % name)
347 else:
348 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
349 return gbb_flags
350
Simon Glass157c0662012-10-23 13:52:42 -0700351 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
352 """Decode ajustments to the provided GBB flags.
353
354 We support three options:
355
356 hex value: c2
357 defined value: force-dev-boot-usb,load-option-roms
358 adjust default value: -load-option-roms,+force-dev-boot-usb
359
360 The last option starts from the passed-in GBB flags and adds or removes
361 flags.
362
363 Args:
364 gbb_flags: Base (default) FDT flags.
365 adjustments: String containing adjustments to make.
366
367 Returns:
368 Updated FDT flags.
369 """
370 use_base_value = True
371 if adjustments:
372 try:
373 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700374 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700375 pass
376 for flag in adjustments.split(','):
377 oper = None
378 if flag[0] in ['-', '+']:
379 oper = flag[0]
380 flag = flag[1:]
381 value = gbb_flag_properties.get(flag)
382 if not value:
383 raise ValueError("Invalid GBB flag '%s'" % flag)
384 if oper == '+':
385 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800386 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700387 elif oper == '-':
388 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800389 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700390 else:
391 if use_base_value:
392 gbb_flags = 0
393 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800394 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700395 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800396 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700397
398 return gbb_flags
399
Simon Glass56577572011-07-19 11:08:06 +1200400 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700401 """Create a GBB for the image.
402
Simon Glass56577572011-07-19 11:08:06 +1200403 Args:
404 hardware_id: Hardware ID to use for this board. If None, then the
405 default from the Fdt will be used
406
Simon Glass89b86b82011-07-17 23:49:49 -0700407 Returns:
408 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700409 """
Simon Glass56577572011-07-19 11:08:06 +1200410 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800411 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700412 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700413 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700414
Simon Glass4a887b12012-10-23 16:29:03 -0700415 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800416
Simon Glass157c0662012-10-23 13:52:42 -0700417 # Allow command line to override flags
418 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
419
Simon Glass4a887b12012-10-23 16:29:03 -0700420 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700421 self._out.Progress('Creating GBB')
Daisuke Nojiri10b193f2016-01-15 17:53:14 -0800422 if self.skip_bmpblk:
423 bmpfv_size = 0
424 else:
425 bmpfv_size = gbb_size - 0x2180
426 sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700427 sizes = ['%#x' % size for size in sizes]
428 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700429 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800430
431 gbb_set_command = ['-s',
432 '--hwid=%s' % hardware_id,
433 '--rootkey=%s/root_key.vbpubk' % keydir,
434 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
435 '--flags=%d' % gbb_flags,
436 gbb]
437 if not self.skip_bmpblk:
438 gbb_set_command[-1:-1] = ['--bmpfv=%s' % self._tools.Filename(
439 self.bmpblk_fname),]
440
Simon Glass290a1802011-07-17 13:54:32 -0700441 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800442 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700443 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700444
Simon Glasse13ee2c2011-07-28 08:12:28 +1200445 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700446 """Sign an image so that the Tegra SOC will boot it.
447
448 Args:
449 bct: BCT file to use.
450 bootstub: Boot stub (U-Boot + fdt) file to sign.
451 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700452
453 Returns:
454 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700455 """
456 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200457 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700458 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200459 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700460 fd = open(config, 'w')
461 fd.write('Version = 1;\n')
462 fd.write('Redundancy = 1;\n')
463 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700464
465 # TODO(dianders): Right now, we don't have enough space in our flash map
466 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
467 # sure what this does for reliability, but at least things will fit...
468 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
469 if is_nand:
470 fd.write('Bctcopy = 1;\n')
471
Simon Glass89b86b82011-07-17 23:49:49 -0700472 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
473 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700474
Simon Glass89b86b82011-07-17 23:49:49 -0700475 fd.close()
476
477 self._tools.Run('cbootimage', [config, signed])
478 self._tools.OutputSize('BCT', bct)
479 self._tools.OutputSize('Signed image', signed)
480 return signed
481
Doug Anderson86ce5f42011-07-27 10:40:18 -0700482 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700483 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700484
485 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700486 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700487 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700488 """
Simon Glass468d8752012-09-19 16:36:19 -0700489 if bootcmd is not None:
490 if bootcmd == 'none':
491 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800492 self.fdt.PutString('/config', 'bootcmd', bootcmd)
493 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700494 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700495
Simon Glassa4934b72012-05-09 13:35:02 -0700496 def SetNodeEnabled(self, node_name, enabled):
497 """Set whether an node is enabled or disabled.
498
499 This simply sets the 'status' property of a node to "ok", or "disabled".
500
501 The node should either be a full path to the node (like '/uart@10200000')
502 or an alias property.
503
504 Aliases are supported like this:
505
506 aliases {
507 console = "/uart@10200000";
508 };
509
510 pointing to a node:
511
512 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700513 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700514 };
515
516 In this case, this function takes the name of the alias ('console' in
517 this case) and updates the status of the node that is pointed to, to
518 either ok or disabled. If the alias does not exist, a warning is
519 displayed.
520
521 Args:
522 node_name: Name of node (e.g. '/uart@10200000') or alias alias
523 (e.g. 'console') to adjust
524 enabled: True to enable, False to disable
525 """
526 # Look up the alias if this is an alias reference
527 if not node_name.startswith('/'):
528 lookup = self.fdt.GetString('/aliases', node_name, '')
529 if not lookup:
530 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
531 return
532 node_name = lookup
533 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700534 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700535 else:
536 status = 'disabled'
537 self.fdt.PutString(node_name, 'status', status)
538
539 def AddEnableList(self, enable_list):
540 """Process a list of nodes to enable/disable.
541
542 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700543 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700544 tuple:
545 node: The fdt node to write to will be <node> or pointed to by
546 /aliases/<node>. We can tell which
547 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700548
Vadim Bendebury507c0012013-06-09 12:49:25 -0700549 Raises:
550 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700551 """
552 if enable_list:
553 for node_name, enabled in enable_list:
554 try:
555 enabled = int(enabled)
556 if enabled not in (0, 1):
557 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700558 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700559 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700560 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700561 self.SetNodeEnabled(node_name, enabled)
562
Simon Glass290a1802011-07-17 13:54:32 -0700563 def AddConfigList(self, config_list, use_int=False):
564 """Add a list of config items to the fdt.
565
566 Normally these values are written to the fdt as strings, but integers
567 are also supported, in which case the values will be converted to integers
568 (if necessary) before being stored.
569
570 Args:
571 config_list: List of (config, value) tuples to add to the fdt. For each
572 tuple:
573 config: The fdt node to write to will be /config/<config>.
574 value: An integer or string value to write.
575 use_int: True to only write integer values.
576
577 Raises:
578 CmdError: if a value is required to be converted to integer but can't be.
579 """
580 if config_list:
581 for config in config_list:
582 value = config[1]
583 if use_int:
584 try:
585 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700586 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700587 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700588 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700589 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800590 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700591 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800592 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700593
Simon Glass7c2d5572011-11-15 14:47:08 -0800594 def DecodeTextBase(self, data):
595 """Look at a U-Boot image and try to decode its TEXT_BASE.
596
597 This works because U-Boot has a header with the value 0x12345678
598 immediately followed by the TEXT_BASE value. We can therefore read this
599 from the image with some certainty. We check only the first 40 words
600 since the header should be within that region.
601
Simon Glass96b50302012-07-20 06:55:28 +0100602 Since upstream Tegra has moved to having a 16KB SPL region at the start,
603 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
604 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
605
Simon Glass7c2d5572011-11-15 14:47:08 -0800606 Args:
607 data: U-Boot binary data
608
609 Returns:
610 Text base (integer) or None if none was found
611 """
612 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100613 for start in (0, 0x4000):
614 for i in range(start, start + 160, 4):
615 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800616
Simon Glass96b50302012-07-20 06:55:28 +0100617 # TODO(sjg): This does not cope with a big-endian target
618 value = struct.unpack('<I', word)[0]
619 if found:
620 return value - start
621 if value == 0x12345678:
622 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800623
624 return None
625
626 def CalcTextBase(self, name, fdt, fname):
627 """Calculate the TEXT_BASE to use for U-Boot.
628
629 Normally this value is in the fdt, so we just read it from there. But as
630 a second check we look at the image itself in case this is different, and
631 switch to that if it is.
632
633 This allows us to flash any U-Boot even if its TEXT_BASE is different.
634 This is particularly useful with upstream U-Boot which uses a different
635 value (which we will move to).
636 """
637 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800638 # The value that comes back from fdt.GetInt is signed, which makes no
639 # sense for an address base. Force it to unsigned.
640 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800641 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100642 text_base_str = '%#x' % text_base if text_base else 'None'
643 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
644 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800645
646 # If they are different, issue a warning and switch over.
647 if text_base and text_base != fdt_text_base:
648 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
649 "fdt value of %x. Using %x" % (text_base, name,
650 fdt_text_base, text_base))
651 fdt_text_base = text_base
652 return fdt_text_base
653
Simon Glass6dcc2f22011-07-28 15:26:49 +1200654 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700655 """Create a boot stub and a signed boot stub.
656
Simon Glass6dcc2f22011-07-28 15:26:49 +1200657 For postload:
658 We add a /config/postload-text-offset entry to the signed bootstub's
659 fdt so that U-Boot can find the postload code.
660
661 The raw (unsigned) bootstub will have a value of -1 for this since we will
662 simply append the postload code to the bootstub and it can find it there.
663 This will be used for RW A/B firmware.
664
665 For the signed case this value will specify where in the flash to find
666 the postload code. This will be used for RO firmware.
667
Simon Glass89b86b82011-07-17 23:49:49 -0700668 Args:
669 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800670 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200671 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700672
673 Returns:
674 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200675 Full path to bootstub (uboot + fdt(-1) + postload).
676 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700677
678 Raises:
679 CmdError if a command fails.
680 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200681 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800682 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700683 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200684
685 # Make a copy of the fdt for the bootstub
686 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700687 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700688 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200689
Simon Glass89b86b82011-07-17 23:49:49 -0700690 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700691 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
692 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700693 self._tools.OutputSize('Combined binary', bootstub)
694
Simon Glasse13ee2c2011-07-28 08:12:28 +1200695 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700696 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700697 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200698 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200699
700 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
701 data = self._tools.ReadFile(signed)
702
703 if postload:
704 # We must add postload to the bootstub since A and B will need to
705 # be able to find it without the /config/postload-text-offset mechanism.
706 bs_data = self._tools.ReadFile(bootstub)
707 bs_data += self._tools.ReadFile(postload)
708 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
709 self._tools.WriteFile(bootstub, bs_data)
710 self._tools.OutputSize('Combined binary with postload', bootstub)
711
712 # Now that we know the file size, adjust the fdt and re-sign
713 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800714 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200715 fdt_data = self._tools.ReadFile(fdt.fname)
716 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
717 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
718 postload_bootstub, text_base)
719 if len(data) != os.path.getsize(signed):
720 raise CmdError('Signed file size changed from %d to %d after updating '
721 'fdt' % (len(data), os.path.getsize(signed)))
722
723 # Re-read the signed image, and add the post-load binary.
724 data = self._tools.ReadFile(signed)
725 data += self._tools.ReadFile(postload)
726 self._tools.OutputSize('Post-load binary', postload)
727
728 self._tools.WriteFile(signed_postload, data)
729 self._tools.OutputSize('Final bootstub with postload', signed_postload)
730
731 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700732
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600733 def _AddCbfsFiles(self, bootstub, cbfs_files):
734 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600735 for file in files:
736 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600737 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600738 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
739 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma'])
740
Patrick Georgib064d982016-01-13 22:17:35 +0100741 def _ProcessCbfsFileProperty(self, cb_copy, node):
742 """Add files to CBFS in RW regions using a specification in fmap.dts
743
744 rw-a-boot {
745 ...
746 cbfs-files {
747 ecfoo = "add -n ecrw-copy -f ec.RW.bin -t raw -A sha256";
748 };
749 };
750
751 Adds a file called "ecrw-copy" of raw type to FW_MAIN_A with the
752 content of ec.RW.bin in the build root, with a SHA256 hash.
753 The dts property name ("ecfoo") is ignored but should be unique,
754 all cbfstool commands that start with "add" are allowed, as is "remove".
755 The second and third argument need to be "-n <cbfs file name>".
756 """
757 try:
758 cbfs_config = self.fdt.GetProps(node + '/cbfs-files')
759 except CmdError:
760 cbfs_config = None
761
762 # Ignore first character of node string,
763 # so both /flash/foo and flash/foo work.
764 region = node[1:].split('/')[1]
765 part_sections = region.split('-', 1)
766 fmap_dst = self._FmapNameByPath(part_sections)
767
768 if cbfs_config != None:
769 # remove all files slated for addition, in case they already exist
770 for val in cbfs_config.itervalues():
771 f = val.split(' ')
772 command = f[0]
773 if command[:3] != 'add' and command != 'remove':
774 raise CmdError("'%s' doesn't add or remove a file", f)
775 if f[1] != '-n':
776 raise CmdError("second argument in '%s' must be '-n'", f)
777 cbfsname = f[2]
778 try:
779 # Calling through shell isn't strictly necessary here, but we still
780 # do it to keep operation more similar to the invocation in the next
781 # loop.
782 self._tools.Run('sh', [ '-c',
783 ' '.join(['cbfstool', cb_copy, 'remove', '-r', fmap_dst,
784 '-n', cbfsname]) ])
785 except CmdError:
786 pass # the most likely error is that the file doesn't already exist
787
Aaron Durbin880cf952016-01-27 14:11:38 -0600788 # Compact the CBFS image after removing the files so all the non-empty
789 # files are at the beginning of the region.
790 self._tools.Run('sh', [ '-c',
791 ' '.join(['cbfstool', cb_copy, 'compact', '-r', fmap_dst]) ])
792
Patrick Georgib064d982016-01-13 22:17:35 +0100793 # now add the files
794 for val in cbfs_config.itervalues():
795 f = val.split(' ')
796 command = f[0]
797 cbfsname = f[2]
798 args = f[3:]
799 if command == 'remove':
800 continue
801 # Call through shell so variable expansion can happen. With a change
802 # to the ebuild this enables specifying filename arguments to
803 # cbfstool as -f romstage.elf${COREBOOT_VARIANT} and have that be
804 # resolved to romstage.elf.serial when appropriate.
805 self._tools.Run('sh', [ '-c',
806 ' '.join(['cbfstool', cb_copy, command, '-r', fmap_dst,
807 '-n', cbfsname] + args)],
808 self._tools.Filename(self._GetBuildRoot()))
809
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600810 def _CreateCorebootStub(self, pack, coreboot):
811 """Create a coreboot boot stub and add pack properties.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700812
813 Args:
Aaron Durbina113f522016-01-05 09:09:55 -0600814 pack: a PackFirmware object describing the firmware image to build.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700815 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700816 """
817 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700818 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100819
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600820 pack.AddProperty('coreboot', bootstub)
821 pack.AddProperty('image', bootstub)
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700822
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600823 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600824 if self.cbfs_files:
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600825 self._AddCbfsFiles(bootstub, self.cbfs_files)
Simon Glass7e199222012-03-13 15:51:18 -0700826
Aaron Durbina113f522016-01-05 09:09:55 -0600827 # Create a coreboot copy to use as a scratch pad. Order matters. The
828 # cbfs_files were added prior to this action. That's so the RW CBFS
Patrick Georgi3a332672015-11-20 10:02:51 +0100829 # regions inherit the files from the RO CBFS region. Additionally,
830 # include the full FMAP within the file.
831 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600832 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100833 binary = self._tools.ReadFile(bootstub)
834 fmap_offset, fmap = pack.GetFmap()
835 if len(binary) < fmap_offset + len(fmap):
836 raise CmdError('FMAP will not fit')
837 # Splice in FMAP data.
838 binary = binary[:fmap_offset] + fmap + binary[fmap_offset + len(fmap):]
839 self._tools.WriteFile(cb_copy, binary)
840 # Publish where coreboot is with the FMAP data.
841 pack.AddProperty('cb_with_fmap', cb_copy)
Aaron Durbina113f522016-01-05 09:09:55 -0600842
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600843 # Add files to to RO CBFS if provided. This done here such that the
844 # copy above does not contain the RO CBFS files.
845 if self.rocbfs_files:
846 self._AddCbfsFiles(bootstub, self.rocbfs_files)
847
Patrick Georgib064d982016-01-13 22:17:35 +0100848 # As a final step, do whatever is requested in /flash/ro-boot/cbfs-files.
849 # It's done after creating the copy for the RW regions so that ro-boot's
850 # cbfs-files property has no side-effects on the RW regions.
851 node = self.fdt.GetFlashNode('ro', 'boot')
852 self._ProcessCbfsFileProperty(os.path.abspath(bootstub), node)
853
Aaron Durbina113f522016-01-05 09:09:55 -0600854
Simon Glass89b86b82011-07-17 23:49:49 -0700855 def _PackOutput(self, msg):
856 """Helper function to write output from PackFirmware (verbose level 2).
857
858 This is passed to PackFirmware for it to use to write output.
859
860 Args:
861 msg: Message to display.
862 """
863 self._out.Notice(msg)
864
Aaron Durbin80564452015-12-21 15:25:06 -0600865 def _FmapNameByPath(self, path):
866 """ Take list of names to form node path. Return FMAP name.
867
868 Obtain the FMAP name described by the node path.
869
870 Args:
871 path: list forming a node path.
872
873 Returns:
874 FMAP name of fdt node.
875
876 Raises:
877 CmdError if path not found.
878 """
879 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
880 return re.sub('-', '_', lbl).upper()
881
882 def _PrepareCbfsHash(self, pack, blob_name):
883 """Create blob in rw-{a,b}-boothash with 'cbfstool hashcbfs'.
884
885 When the blob name is defined as cbfshash/<section>/<subsection>, fill the
886 <section>_<subsection> area in the flash map with CBFS hash generated
887 using the 'cbfstool hashcbfs' command.
888
889 Args:
890 pack: a PackFirmware object describing the firmware image to build.
891 blob_name: a string, blob name describing what FMAP section this CBFS
892 copy is destined to
893 Raises:
894 CmdError if cbfs-files node has incorrect parameters.
895 BlobDeferral if the CBFS region is not populated yet or if the coreboot
896 image with fmap is not available yet.
897 """
898 cb_copy = pack.GetProperty('cb_with_fmap')
899 if cb_copy is None:
900 raise BlobDeferral("Waiting for '%s'" % cb_copy)
901
902 part_sections = blob_name.split('/')[1:]
903 fmap_dst = self._FmapNameByPath(part_sections)
904
905 # Example of FDT ndoes asking for CBFS hash:
906 # rw-b-boot {
907 # label = "fw-main-b";
908 # reg = <0x00700000 0x002dff80>;
909 # type = "blob cbfs/rw/b-boot";
910 # };
911 # rw-b-boothash {
912 # label = "fw-main-b-hash";
913 # reg = <0x009dff80 0x00000040>;
914 # type = "blob cbfshash/rw/b-boothash";
915 # cbfs-node = "cbfs/rw/b-boot";
916 # };
917 hash_node = self.fdt.GetFlashNode(*part_sections)
918 cbfs_blob_name = self.fdt.GetString(hash_node, 'cbfs-node')
919
920 if not pack.GetProperty(cbfs_blob_name):
921 raise BlobDeferral("Waiting for '%s'" % cbfs_blob_name)
922
923 cbfs_node_path = cbfs_blob_name.split('/')[1:]
924 fmap_src = self._FmapNameByPath(cbfs_node_path)
925
926 # Compute CBFS hash and place it in the corect spot.
927 self._tools.Run('cbfstool', [cb_copy, 'hashcbfs', '-r', fmap_dst,
928 '-R', fmap_src, '-A', 'sha256'])
929
930 # Base address and size of the desitnation partition
931 base, size = self.fdt.GetFlashPart(*part_sections)
932
933 # And extract the blob for the FW section
934 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
935 self._tools.WriteFile(rw_section,
936 self._tools.ReadFile(cb_copy)[base:base+size])
937
938 pack.AddProperty(blob_name, rw_section)
939
940
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800941 def _PrepareCbfs(self, pack, blob_name):
942 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
943
944 When the blob name is defined as cbfs#<section>#<subsection>, fill the
945 <section>_<subsection> area in the flash map with a CBFS copy, putting the
946 CBFS header of the copy at the base of the section.
947
948 If --coreboot-elf parameter was specified during cros_bumdle_firmware
949 invocation, add the parameter of this option as the payload to the new
950 CBFS instance.
951
952 Args:
953 pack: a PackFirmware object describing the firmware image to build.
954 blob_name: a string, blob name describing what FMAP section this CBFS
955 copy is destined to
956 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100957 CmdError if cbfs-files node has incorrect parameters.
Aaron Durbina113f522016-01-05 09:09:55 -0600958 BlobDeferral if coreboot image with fmap is not available yet.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800959 """
Patrick Georgi3a332672015-11-20 10:02:51 +0100960 cb_copy = pack.GetProperty('cb_with_fmap')
Aaron Durbina113f522016-01-05 09:09:55 -0600961 if cb_copy is None:
Patrick Georgi3a332672015-11-20 10:02:51 +0100962 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800963
964 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600965 fmap_src = self._FmapNameByPath('ro-boot'.split('-'))
966 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800967
968 # Base address and size of the desitnation partition
969 base, size = self.fdt.GetFlashPart(*part_sections)
970
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800971 # Copy CBFS to the required offset
Patrick Georgi10690b42015-11-20 22:06:38 +0100972 self._tools.Run('cbfstool', [cb_copy, 'copy', '-r', fmap_dst,
973 '-R', fmap_src])
974
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800975 # Add coreboot payload if so requested. Note that the some images use
976 # different payload for the rw sections, which is passed in as the value
977 # of the --uboot option in the command line.
978 if self.uboot_fname:
979 payload_fname = self.uboot_fname
980 elif self.coreboot_elf:
981 payload_fname = self.coreboot_elf
982 else:
983 payload_fname = None
984
985 if payload_fname:
986 self._tools.Run('cbfstool', [
987 cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100988 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800989
Patrick Georgi964fb542015-10-16 16:52:03 +0200990 if self.ecrw_fname:
991 self._tools.Run('cbfstool', [
992 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100993 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200994
995 if self.pdrw_fname:
996 self._tools.Run('cbfstool', [
997 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100998 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200999
Patrick Georgib064d982016-01-13 22:17:35 +01001000 # Check if there's an advanced CBFS configuration request
1001 node = self.fdt.GetFlashNode(*part_sections)
1002 self._ProcessCbfsFileProperty(cb_copy, node)
Patrick Georgi10ea5ef2015-10-22 19:14:26 +02001003
Aaron Durbin880cf952016-01-27 14:11:38 -06001004 # Parse the file list to obtain the last entry. If its empty use its
1005 # offset as the size of the CBFS to hash.
1006 stdout = self._tools.Run('cbfstool',
1007 [ cb_copy, 'print', '-k', '-r', fmap_dst ])
1008 # Fields are tab separated in the following order.
1009 # Name Offset Type Metadata Size Data Size Total Size
1010 last_entry = stdout.strip().splitlines()[-1].split('\t')
1011 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
1012 size = int(last_entry[1], 16)
1013
Vadim Bendeburyc9600c62014-12-22 16:31:13 -08001014 # And extract the blob for the FW section
1015 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
1016 self._tools.WriteFile(rw_section,
1017 self._tools.ReadFile(cb_copy)[base:base+size])
1018
1019 pack.AddProperty(blob_name, rw_section)
1020
1021
Simon Glass439fe7a2012-03-09 16:19:34 -08001022 def _BuildBlob(self, pack, fdt, blob_type):
1023 """Build the blob data for a particular blob type.
1024
1025 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -07001026 pack: a PackFirmware object describing the firmware image to build.
1027 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -08001028 blob_type: The type of blob to create data for. Supported types are:
1029 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
1030 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -07001031
1032 Raises:
1033 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001034 BlobDeferral if a blob is waiting for a dependency.
Simon Glass439fe7a2012-03-09 16:19:34 -08001035 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001036 # stupid pylint insists that sha256 is not in hashlib.
1037 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -08001038 if blob_type == 'coreboot':
Aaron Durbin5751c3e2016-01-04 11:45:22 -06001039 self._CreateCorebootStub(pack, self.coreboot_fname)
Stefan Reinauer9ad54842012-10-10 12:25:23 -07001040 elif blob_type == 'legacy':
1041 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -08001042 elif blob_type == 'signed':
1043 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
1044 self.postload_fname)
1045 pack.AddProperty('bootstub', bootstub)
1046 pack.AddProperty('signed', signed)
1047 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -07001048 elif blob_type == 'exynos-bl1':
1049 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -07001050
1051 # TODO(sjg@chromium.org): Deprecate ecbin
1052 elif blob_type in ['ecrw', 'ecbin']:
1053 pack.AddProperty('ecrw', self.ecrw_fname)
1054 pack.AddProperty('ecbin', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -07001055 elif blob_type == 'pdrw':
1056 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -08001057 elif blob_type == 'ecrwhash':
1058 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
1059 ecrw = self._tools.ReadFile(self.ecrw_fname)
1060 hasher = hashlib.sha256()
1061 hasher.update(ecrw)
1062 self._tools.WriteFile(ec_hash_file, hasher.digest())
1063 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -07001064 elif blob_type == 'pdrwhash':
1065 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
1066 pdrw = self._tools.ReadFile(self.pdrw_fname)
1067 hasher = hashlib.sha256()
1068 hasher.update(pdrw)
1069 self._tools.WriteFile(pd_hash_file, hasher.digest())
1070 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -07001071 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -07001072 # crosbug.com/p/13143
1073 # We cannot have an fmap in the EC image since there can be only one,
1074 # which is the main fmap describing the whole image.
1075 # Ultimately the EC will not have an fmap, since with software sync
1076 # there is no flashrom involvement in updating the EC flash, and thus
1077 # no need for the fmap.
1078 # For now, mangle the fmap name to avoid problems.
1079 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
1080 data = self._tools.ReadFile(self.ecro_fname)
1081 data = re.sub('__FMAP__', '__fMAP__', data)
1082 self._tools.WriteFile(updated_ecro, data)
1083 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -06001084 elif blob_type.startswith('exynos-bl2'):
1085 # We need to configure this per node, so do it later
1086 pass
Aaron Durbin80564452015-12-21 15:25:06 -06001087 elif blob_type.startswith('cbfshash'):
1088 self._PrepareCbfsHash(pack, blob_type)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -08001089 elif blob_type.startswith('cbfs'):
1090 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -08001091 elif pack.GetProperty(blob_type):
1092 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -08001093 elif blob_type in self.blobs:
1094 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -08001095 else:
1096 raise CmdError("Unknown blob type '%s' required in flash map" %
1097 blob_type)
1098
Aaron Durbin41c85b62015-12-17 17:40:29 -06001099 def _BuildBlobs(self, pack, fdt):
1100 """Build the blob data for the list of blobs in the pack.
1101
1102 Args:
1103 pack: a PackFirmware object describing the firmware image to build.
1104 fdt: an fdt object including image layout information
1105
1106 Raises:
1107 CmdError if a command fails.
1108 BlobDeferral if dependencies cannot be met because of cycles.
1109 """
1110 blob_list = pack.GetBlobList()
1111 self._out.Info('Building blobs %s\n' % blob_list)
1112
1113 complete = False
1114 deferred_list = []
1115
1116 # Build blobs allowing for dependencies between blobs. While this is
1117 # an potential O(n^2) operation, in practice most blobs aren't dependent
1118 # and should resolve in a few passes.
1119 while not complete:
1120 orig = set(blob_list)
1121 for blob_type in blob_list:
1122 try:
1123 self._BuildBlob(pack, fdt, blob_type)
1124 except (BlobDeferral):
1125 deferred_list.append(blob_type)
1126 if not deferred_list:
1127 complete = True
1128 # If deferred is the same as the original no progress is being made.
1129 if not orig - set(deferred_list):
1130 raise BlobDeferral("Blob cyle '%s'" % orig)
1131 # Process the deferred blobs
1132 blob_list = deferred_list[:]
1133 deferred_list = []
1134
Simon Glass290a1802011-07-17 13:54:32 -07001135 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -07001136 """Create a full firmware image, along with various by-products.
1137
1138 This uses the provided u-boot.bin, fdt and bct to create a firmware
1139 image containing all the required parts. If the GBB is not supplied
1140 then this will just return a signed U-Boot as the image.
1141
1142 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -07001143 gbb: a string, full path to the GBB file, or empty if a GBB is not
1144 required.
1145 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +12001146
1147 Returns:
1148 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -07001149 """
Simon Glass02d124a2012-03-02 14:47:20 -08001150 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -07001151
Simon Glass439fe7a2012-03-09 16:19:34 -08001152 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -08001153 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -07001154 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
1155 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -06001156 if self._force_efs:
1157 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -06001158 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
1159 0)
Simon Glassb8c6d952012-12-01 06:14:35 -08001160
Simon Glass4f318912013-07-20 16:13:06 -06001161 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -08001162
1163 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001164 if self.uboot_fname:
1165 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -08001166 if self.skeleton_fname:
1167 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001168 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001169
Simon Glassde9c8072012-07-02 22:29:02 -07001170 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1171 if self.kernel_fname:
1172 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1173
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001174 if gbb:
1175 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -06001176
1177 # Build the blobs out.
1178 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -07001179
Simon Glass7306b902012-12-17 15:06:21 -08001180 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001181 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001182 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001183 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001184 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001185 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001186 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001187 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001188 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001189
Simon Glass0a047bc2013-07-19 15:44:43 -06001190 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001191 todo = pack.GetMissingBlobs()
1192 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001193 if blob.key.startswith('exynos-bl2'):
1194 bl2 = ExynosBl2(self._tools, self._out)
1195 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1196 self.exynos_bl2))
1197
Simon Glassc90cf582012-03-13 15:40:47 -07001198 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001199
1200 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001201 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001202
Simon Glass4c24f662013-07-19 15:53:02 -06001203 # Recalculate the Exynos BL2, since it may have a hash. The call to
1204 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1205 # need to recalculate the hash.
1206 for blob in todo:
1207 if blob.key.startswith('exynos-bl2'):
1208 bl2 = ExynosBl2(self._tools, self._out)
1209 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1210 self.exynos_bl2))
1211
Simon Glass6207efe2012-12-17 15:04:36 -08001212 # Make a copy of the fdt for the bootstub
1213 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001214 if self.uboot_fname:
1215 uboot_data = self._tools.ReadFile(self.uboot_fname)
1216 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1217 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001218
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001219 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1220 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001221
Simon Glassa10282a2013-01-08 17:06:41 -08001222 # Fix up the coreboot image here, since we can't do this until we have
1223 # a final device tree binary.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001224 if 'coreboot' in pack.GetBlobList():
Simon Glasscbc83552012-07-23 15:26:22 +01001225 bootstub = pack.GetProperty('coreboot')
1226 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001227 if self.coreboot_elf:
1228 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1229 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001230 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001231 text_base = 0x1110000
1232
1233 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1234 # 1110015: 66 bb 00 01 mov $0x100,%bx
1235 marker = struct.pack('<L', 0x0100bb66)
1236 pos = uboot_data.find(marker)
1237 if pos == -1 or pos > 0x100:
1238 raise ValueError('Cannot find U-Boot cold boot entry point')
1239 entry = text_base + pos
1240 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001241 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1242 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001243 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001244 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1245 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001246 data = self._tools.ReadFile(bootstub)
1247 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1248 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001249
Julius Werneraa1fe942014-11-21 17:16:11 -08001250 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1251 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1252 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001253
Simon Glass208ad952013-02-10 11:16:46 -08001254 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001255 image = os.path.join(self._tools.outdir, 'image.bin')
1256 pack.PackImage(self._tools.outdir, image)
1257 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001258
Simon Glass439fe7a2012-03-09 16:19:34 -08001259 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001260 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001261 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001262
Simon Glassdedda6f2013-02-09 13:44:14 -08001263 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001264 """Select an FDT to control the firmware bundling
1265
Simon Glassdedda6f2013-02-09 13:44:14 -08001266 We make a copy of this which will include any on-the-fly changes we want
1267 to make.
1268
Simon Glass290a1802011-07-17 13:54:32 -07001269 Args:
1270 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001271 use_defaults: True to use a default FDT name if available, and to add
1272 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001273
Simon Glassc0f3dc62011-08-09 14:19:05 -07001274 Returns:
1275 The Fdt object of the original fdt file, which we will not modify.
1276
Simon Glassdedda6f2013-02-09 13:44:14 -08001277 Raises:
1278 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1279 False).
Simon Glass290a1802011-07-17 13:54:32 -07001280 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001281 if use_defaults:
1282 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001283 if not fdt_fname:
1284 raise ValueError('Please provide an FDT filename')
1285 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001286 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001287
1288 # For upstream, select the correct architecture .dtsi manually.
1289 if self._board == 'link' or 'x86' in self._board:
1290 arch_dts = 'coreboot.dtsi'
1291 elif self._board == 'daisy':
1292 arch_dts = 'exynos5250.dtsi'
1293 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001294 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001295
1296 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001297 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1298
1299 # Get the flashmap so we know what to build. For board variants use the
1300 # main board name as the key (drop the _<variant> suffix).
1301 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1302
1303 if not fdt.GetProp('/flash', 'reg', ''):
1304 fdt.InsertNodes(default_flashmap)
1305
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001306 # Only check for /iram and /config nodes for boards that require it.
1307 if self._board in ('daisy', 'peach'):
1308 # Insert default values for any essential properties that are missing.
1309 # This should only happen for upstream U-Boot, until our changes are
1310 # upstreamed.
1311 if not fdt.GetProp('/iram', 'reg', ''):
1312 self._out.Warning('Cannot find /iram, using default')
1313 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001314
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001315 # Sadly the pit branch has an invalid /memory node. Work around it
1316 # for now. crosbug.com/p/22184
1317 if (not fdt.GetProp('/memory', 'reg', '') or
1318 fdt.GetIntList('/memory', 'reg')[0] == 0):
1319 self._out.Warning('Cannot find /memory, using default')
1320 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001321
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001322 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
1323 self._out.Warning('Missing properties in /config, using defaults')
1324 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001325
Simon Glass7df773b2013-08-25 18:02:29 -06001326 # Remember our board type.
1327 fdt.PutString('/chromeos-config', 'board', self._board)
1328
Simon Glasse53abbc2013-08-21 22:29:55 -06001329 self.fdt = fdt
1330 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001331
Simon Glassc90cf582012-03-13 15:40:47 -07001332 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001333 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001334
1335 - Checks options, tools, output directory, fdt.
1336 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001337
1338 Args:
Simon Glass56577572011-07-19 11:08:06 +12001339 hardware_id: Hardware ID to use for this board. If None, then the
1340 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001341 output_fname: Output filename for the image. If this is not None, then
1342 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001343 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001344
1345 Returns:
1346 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001347 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001348 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1349 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1350 else:
Simon Glass56577572011-07-19 11:08:06 +12001351 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001352
1353 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001354 image, pack = self._CreateImage(gbb, self.fdt)
1355 if show_map:
1356 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001357 if output_fname:
1358 shutil.copyfile(image, output_fname)
1359 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001360 return image, pack.props