blob: 67e30b0934e594dfd0f90c8d0a25e28dc2201a01 [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
Patrick Georgicebb5a22016-08-15 19:07:02 +020028import fmap
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
Simon Glass4a887b12012-10-23 16:29:03 -070032# Build GBB flags.
33# (src/platform/vboot_reference/firmware/include/gbb_header.h)
34gbb_flag_properties = {
35 'dev-screen-short-delay': 0x00000001,
36 'load-option-roms': 0x00000002,
37 'enable-alternate-os': 0x00000004,
38 'force-dev-switch-on': 0x00000008,
39 'force-dev-boot-usb': 0x00000010,
40 'disable-fw-rollback-check': 0x00000020,
41 'enter-triggers-tonorm': 0x00000040,
42 'force-dev-boot-legacy': 0x00000080,
Shawn Nematbakhsh07c19882014-08-19 10:21:59 -070043 'faft-key-overide': 0x00000100,
44 'disable-ec-software-sync': 0x00000200,
45 'default-dev-boot-legacy': 0x00000400,
46 'disable-pd-software-sync': 0x00000800,
Furquan Shaikhd4eac3b2015-05-15 18:05:09 -070047 'force-dev-boot-fastboot-full-cap': 0x00002000,
Mary Ruthvena759c322015-11-16 08:23:26 -080048 'enable-serial': 0x00004000,
Simon Glass4a887b12012-10-23 16:29:03 -070049}
50
Simon Glass49b026b2013-04-26 16:38:42 -070051# Maps board name to Exynos product number
52type_to_model = {
53 'peach' : '5420',
54 'daisy' : '5250'
55}
56
Simon Glass5076a7f2012-10-23 16:31:54 -070057def ListGoogleBinaryBlockFlags():
58 """Print out a list of GBB flags."""
59 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
60 for name, value in gbb_flag_properties.iteritems():
61 print ' %-30s %02x' % (name, value)
62
Aaron Durbin41c85b62015-12-17 17:40:29 -060063class BlobDeferral(Exception):
64 """An error indicating deferal of blob generation."""
65 pass
66
Simon Glass89b86b82011-07-17 23:49:49 -070067class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070068 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070069
Simon Glass290a1802011-07-17 13:54:32 -070070 Sequence of events:
71 bundle = Bundle(tools.Tools(), cros_output.Output())
72 bundle.SetDirs(...)
73 bundle.SetFiles(...)
74 bundle.SetOptions(...)
75 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -070076 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -070077 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070078
Simon Glass290a1802011-07-17 13:54:32 -070079 Public properties:
80 fdt: The fdt object that we use for building our image. This wil be the
81 one specified by the user, except that we might add config options
82 to it. This is set up by SelectFdt() which must be called before
83 bundling starts.
84 uboot_fname: Full filename of the U-Boot binary we use.
85 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -070086 spl_source: Source device to load U-Boot from, in SPL:
87 straps: Select device according to CPU strap pins
88 spi: Boot from SPI
89 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -070090
91 Private attributes:
92 _small: True to create a 'small' signed U-Boot, False to produce a
93 full image. The small U-Boot is enough to boot but will not have
94 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -070095 """
Simon Glass89b86b82011-07-17 23:49:49 -070096
Simon Glass290a1802011-07-17 13:54:32 -070097 def __init__(self, tools, output):
98 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -070099
Simon Glass290a1802011-07-17 13:54:32 -0700100 Args:
101 tools: A tools.Tools object to use for external tools.
102 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700103 """
Simon Glass290a1802011-07-17 13:54:32 -0700104 self._tools = tools
105 self._out = output
106
107 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500108 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700109 self._fdt_fname = None # Filename of our FDT.
Simon Glass00d027e2013-07-20 14:51:12 -0600110 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700111 self._gbb_flags = None
112 self._keydir = None
113 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700114 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700115 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700116 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700117 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700118 self.ecro_fname = None # Filename of EC read-only file
119 self.ecrw_fname = None # Filename of EC file
Randall Spangler7307da92014-07-18 12:47:34 -0700120 self.pdrw_fname = None # Filename of PD file
Simon Glass7e199222012-03-13 15:51:18 -0700121 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
122 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700123 self.fdt = None # Our Fdt object.
124 self.kernel_fname = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700125 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700126 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700127 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700128
129 def SetDirs(self, keydir):
130 """Set up directories required for Bundle.
131
132 Args:
133 keydir: Directory containing keys to use for signing firmware.
134 """
135 self._keydir = keydir
136
Patrick Georgi48030572016-09-09 22:55:46 +0200137 def SetFiles(self, board, bct, uboot=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800138 coreboot_elf=None,
Simon Glass942bedb2016-05-14 16:19:59 -0600139 seabios=None, exynos_bl1=None, exynos_bl2=None,
Randall Spangler7307da92014-07-18 12:47:34 -0700140 skeleton=None, ecrw=None, ecro=None, pdrw=None,
Patrick Georgi48030572016-09-09 22:55:46 +0200141 kernel=None, blobs=None, cbfs_files=None,
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600142 rocbfs_files=None):
Simon Glass290a1802011-07-17 13:54:32 -0700143 """Set up files required for Bundle.
144
145 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500146 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700147 uboot: The filename of the u-boot.bin image to use.
148 bct: The filename of the binary BCT file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800149 coreboot: The filename of the coreboot image to use (on x86).
150 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Vincent Palatinf7286772011-10-12 14:31:53 -0700151 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700152 exynos_bl1: The filename of the exynos BL1 file
153 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
154 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700155 ecrw: The filename of the EC (Embedded Controller) read-write file.
156 ecro: The filename of the EC (Embedded Controller) read-only file.
Randall Spangler7307da92014-07-18 12:47:34 -0700157 pdrw: The filename of the PD (PD embedded controller) read-write file.
Simon Glassde9c8072012-07-02 22:29:02 -0700158 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800159 blobs: List of (type, filename) of arbitrary blobs.
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600160 cbfs_files: Root directory of files to be stored in RO and RW CBFS
161 rocbfs_files: Root directory of files to be stored in RO CBFS
Simon Glass290a1802011-07-17 13:54:32 -0700162 """
163 self._board = board
164 self.uboot_fname = uboot
165 self.bct_fname = bct
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700166 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800167 self.coreboot_elf = coreboot_elf
Vincent Palatinf7286772011-10-12 14:31:53 -0700168 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700169 self.exynos_bl1 = exynos_bl1
170 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700171 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700172 self.ecrw_fname = ecrw
173 self.ecro_fname = ecro
Randall Spangler7307da92014-07-18 12:47:34 -0700174 self.pdrw_fname = pdrw
Simon Glassde9c8072012-07-02 22:29:02 -0700175 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800176 self.blobs = dict(blobs or ())
Daisuke Nojiri69662892015-09-25 15:24:04 -0700177 self.cbfs_files = cbfs_files
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600178 self.rocbfs_files = rocbfs_files
Simon Glass290a1802011-07-17 13:54:32 -0700179
Patrick Georgi450204a2016-08-15 19:13:29 +0200180 def SetOptions(self, small, gbb_flags, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700181 """Set up options supported by Bundle.
182
183 Args:
184 small: Only create a signed U-Boot - don't produce the full packed
185 firmware image. This is useful for devs who want to replace just the
186 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700187 gbb_flags: Specification for string containing adjustments to make.
Simon Glass00d027e2013-07-20 14:51:12 -0600188 force_efs: Force firmware to use 'early firmware selection' feature,
189 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700190 """
191 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700192 self._gbb_flags = gbb_flags
Simon Glass00d027e2013-07-20 14:51:12 -0600193 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700194
Simon Glass22f39fb2013-02-09 13:44:14 -0800195 def _GetBuildRoot(self):
196 """Get the path to this board's 'firmware' directory.
197
198 Returns:
199 Path to firmware directory, with ## representing the path to the
200 chroot.
201 """
Simon Glass290a1802011-07-17 13:54:32 -0700202 if not self._board:
203 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800204 return os.path.join('##', 'build', self._board, 'firmware')
205
206 def _CheckFdtFilename(self, fname):
207 """Check provided FDT filename and return the correct name if needed.
208
209 Where the filename lacks a path, add a default path for this board.
210 Where no FDT filename is provided, select a default one for this board.
211
212 Args:
213 fname: Proposed FDT filename.
214
215 Returns:
216 Selected FDT filename, after validation.
217 """
218 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700219 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800220 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700221 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700222 base_name = re.sub('_', '-', self._board)
223
224 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700225 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700226 found_list = glob.glob(self._tools.Filename(wildcard))
227 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800228 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700229 else:
230 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700231 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700232
Simon Glass881964d2012-04-04 11:34:09 -0700233 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800234 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700235 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700236 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800237 return fname
238
239 def CheckOptions(self):
240 """Check provided options and select defaults."""
241 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700242
Simon Glass49b026b2013-04-26 16:38:42 -0700243 board_type = self._board.split('_')[0]
244 model = type_to_model.get(board_type)
245
Simon Glass290a1802011-07-17 13:54:32 -0700246 if not self.uboot_fname:
247 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
248 if not self.bct_fname:
249 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass49b026b2013-04-26 16:38:42 -0700250 if model:
251 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700252 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700253 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700254 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700255 if not self.coreboot_fname:
256 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
257 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700258 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Simon Glassbe0bc002012-08-16 12:50:48 -0700259 if not self.ecrw_fname:
260 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
Randall Spangler7307da92014-07-18 12:47:34 -0700261 if not self.pdrw_fname:
262 self.pdrw_fname = os.path.join(build_root, 'pd.RW.bin')
Simon Glassbe0bc002012-08-16 12:50:48 -0700263 if not self.ecro_fname:
264 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700265
Simon Glass75759302012-03-15 20:26:53 -0700266 def GetFiles(self):
267 """Get a list of files that we know about.
268
269 This is the opposite of SetFiles except that we may have put in some
270 default names. It returns a dictionary containing the filename for
271 each of a number of pre-defined files.
272
273 Returns:
274 Dictionary, with one entry for each file.
275 """
276 file_list = {
277 'bct' : self.bct_fname,
278 'exynos-bl1' : self.exynos_bl1,
279 'exynos-bl2' : self.exynos_bl2,
280 }
281 return file_list
282
Simon Glass4a887b12012-10-23 16:29:03 -0700283 def DecodeGBBFlagsFromFdt(self):
284 """Get Google Binary Block flags from the FDT.
285
286 These should be in the chromeos-config node, like this:
287
288 chromeos-config {
289 gbb-flag-dev-screen-short-delay;
290 gbb-flag-force-dev-switch-on;
291 gbb-flag-force-dev-boot-usb;
292 gbb-flag-disable-fw-rollback-check;
293 };
294
295 Returns:
296 GBB flags value from FDT.
297 """
298 chromeos_config = self.fdt.GetProps("/chromeos-config")
299 gbb_flags = 0
300 for name in chromeos_config:
301 if name.startswith('gbb-flag-'):
302 flag_value = gbb_flag_properties.get(name[9:])
303 if flag_value:
304 gbb_flags |= flag_value
305 self._out.Notice("FDT: Enabling %s." % name)
306 else:
307 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
308 return gbb_flags
309
Simon Glass157c0662012-10-23 13:52:42 -0700310 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
311 """Decode ajustments to the provided GBB flags.
312
313 We support three options:
314
315 hex value: c2
316 defined value: force-dev-boot-usb,load-option-roms
317 adjust default value: -load-option-roms,+force-dev-boot-usb
318
319 The last option starts from the passed-in GBB flags and adds or removes
320 flags.
321
322 Args:
323 gbb_flags: Base (default) FDT flags.
324 adjustments: String containing adjustments to make.
325
326 Returns:
327 Updated FDT flags.
328 """
329 use_base_value = True
330 if adjustments:
331 try:
332 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700333 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700334 pass
335 for flag in adjustments.split(','):
336 oper = None
337 if flag[0] in ['-', '+']:
338 oper = flag[0]
339 flag = flag[1:]
340 value = gbb_flag_properties.get(flag)
341 if not value:
342 raise ValueError("Invalid GBB flag '%s'" % flag)
343 if oper == '+':
344 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800345 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700346 elif oper == '-':
347 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800348 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700349 else:
350 if use_base_value:
351 gbb_flags = 0
352 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800353 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700354 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800355 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700356
357 return gbb_flags
358
Simon Glass56577572011-07-19 11:08:06 +1200359 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700360 """Create a GBB for the image.
361
Simon Glass56577572011-07-19 11:08:06 +1200362 Args:
363 hardware_id: Hardware ID to use for this board. If None, then the
364 default from the Fdt will be used
365
Simon Glass89b86b82011-07-17 23:49:49 -0700366 Returns:
367 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700368 """
Simon Glass56577572011-07-19 11:08:06 +1200369 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800370 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700371 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700372 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700373
Simon Glass4a887b12012-10-23 16:29:03 -0700374 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800375
Simon Glass157c0662012-10-23 13:52:42 -0700376 # Allow command line to override flags
377 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
378
Simon Glass4a887b12012-10-23 16:29:03 -0700379 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700380 self._out.Progress('Creating GBB')
Patrick Georgi48030572016-09-09 22:55:46 +0200381 sizes = [0x100, 0x1000, 0, 0x1000]
Simon Glass89b86b82011-07-17 23:49:49 -0700382 sizes = ['%#x' % size for size in sizes]
383 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700384 keydir = self._tools.Filename(self._keydir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800385
386 gbb_set_command = ['-s',
387 '--hwid=%s' % hardware_id,
388 '--rootkey=%s/root_key.vbpubk' % keydir,
389 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
390 '--flags=%d' % gbb_flags,
391 gbb]
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800392
Simon Glass290a1802011-07-17 13:54:32 -0700393 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Vadim Bendeburybfd227f2014-11-28 22:14:24 -0800394 self._tools.Run('gbb_utility', gbb_set_command, cwd=odir)
Simon Glass290a1802011-07-17 13:54:32 -0700395 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700396
Simon Glasse13ee2c2011-07-28 08:12:28 +1200397 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700398 """Sign an image so that the Tegra SOC will boot it.
399
400 Args:
401 bct: BCT file to use.
402 bootstub: Boot stub (U-Boot + fdt) file to sign.
403 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700404
405 Returns:
406 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700407 """
408 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200409 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700410 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200411 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700412 fd = open(config, 'w')
413 fd.write('Version = 1;\n')
414 fd.write('Redundancy = 1;\n')
415 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700416
417 # TODO(dianders): Right now, we don't have enough space in our flash map
418 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
419 # sure what this does for reliability, but at least things will fit...
420 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
421 if is_nand:
422 fd.write('Bctcopy = 1;\n')
423
Simon Glass89b86b82011-07-17 23:49:49 -0700424 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
425 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700426
Simon Glass89b86b82011-07-17 23:49:49 -0700427 fd.close()
428
429 self._tools.Run('cbootimage', [config, signed])
430 self._tools.OutputSize('BCT', bct)
431 self._tools.OutputSize('Signed image', signed)
432 return signed
433
Doug Anderson86ce5f42011-07-27 10:40:18 -0700434 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700435 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700436
437 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700438 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700439 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700440 """
Simon Glass468d8752012-09-19 16:36:19 -0700441 if bootcmd is not None:
442 if bootcmd == 'none':
443 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800444 self.fdt.PutString('/config', 'bootcmd', bootcmd)
445 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700446 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700447
Simon Glassa4934b72012-05-09 13:35:02 -0700448 def SetNodeEnabled(self, node_name, enabled):
449 """Set whether an node is enabled or disabled.
450
451 This simply sets the 'status' property of a node to "ok", or "disabled".
452
453 The node should either be a full path to the node (like '/uart@10200000')
454 or an alias property.
455
456 Aliases are supported like this:
457
458 aliases {
459 console = "/uart@10200000";
460 };
461
462 pointing to a node:
463
464 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700465 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700466 };
467
468 In this case, this function takes the name of the alias ('console' in
469 this case) and updates the status of the node that is pointed to, to
470 either ok or disabled. If the alias does not exist, a warning is
471 displayed.
472
473 Args:
474 node_name: Name of node (e.g. '/uart@10200000') or alias alias
475 (e.g. 'console') to adjust
476 enabled: True to enable, False to disable
477 """
478 # Look up the alias if this is an alias reference
479 if not node_name.startswith('/'):
480 lookup = self.fdt.GetString('/aliases', node_name, '')
481 if not lookup:
482 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
483 return
484 node_name = lookup
485 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700486 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700487 else:
488 status = 'disabled'
489 self.fdt.PutString(node_name, 'status', status)
490
491 def AddEnableList(self, enable_list):
492 """Process a list of nodes to enable/disable.
493
494 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700495 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700496 tuple:
497 node: The fdt node to write to will be <node> or pointed to by
498 /aliases/<node>. We can tell which
499 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700500
Vadim Bendebury507c0012013-06-09 12:49:25 -0700501 Raises:
502 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700503 """
504 if enable_list:
505 for node_name, enabled in enable_list:
506 try:
507 enabled = int(enabled)
508 if enabled not in (0, 1):
509 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700510 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700511 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700512 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700513 self.SetNodeEnabled(node_name, enabled)
514
Simon Glass290a1802011-07-17 13:54:32 -0700515 def AddConfigList(self, config_list, use_int=False):
516 """Add a list of config items to the fdt.
517
518 Normally these values are written to the fdt as strings, but integers
519 are also supported, in which case the values will be converted to integers
520 (if necessary) before being stored.
521
522 Args:
523 config_list: List of (config, value) tuples to add to the fdt. For each
524 tuple:
525 config: The fdt node to write to will be /config/<config>.
526 value: An integer or string value to write.
527 use_int: True to only write integer values.
528
529 Raises:
530 CmdError: if a value is required to be converted to integer but can't be.
531 """
532 if config_list:
533 for config in config_list:
534 value = config[1]
535 if use_int:
536 try:
537 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700538 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700539 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700540 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700541 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800542 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700543 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800544 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700545
Simon Glass7c2d5572011-11-15 14:47:08 -0800546 def DecodeTextBase(self, data):
547 """Look at a U-Boot image and try to decode its TEXT_BASE.
548
549 This works because U-Boot has a header with the value 0x12345678
550 immediately followed by the TEXT_BASE value. We can therefore read this
551 from the image with some certainty. We check only the first 40 words
552 since the header should be within that region.
553
Simon Glass96b50302012-07-20 06:55:28 +0100554 Since upstream Tegra has moved to having a 16KB SPL region at the start,
555 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
556 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
557
Simon Glass7c2d5572011-11-15 14:47:08 -0800558 Args:
559 data: U-Boot binary data
560
561 Returns:
562 Text base (integer) or None if none was found
563 """
564 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100565 for start in (0, 0x4000):
566 for i in range(start, start + 160, 4):
567 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800568
Simon Glass96b50302012-07-20 06:55:28 +0100569 # TODO(sjg): This does not cope with a big-endian target
570 value = struct.unpack('<I', word)[0]
571 if found:
572 return value - start
573 if value == 0x12345678:
574 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800575
576 return None
577
578 def CalcTextBase(self, name, fdt, fname):
579 """Calculate the TEXT_BASE to use for U-Boot.
580
581 Normally this value is in the fdt, so we just read it from there. But as
582 a second check we look at the image itself in case this is different, and
583 switch to that if it is.
584
585 This allows us to flash any U-Boot even if its TEXT_BASE is different.
586 This is particularly useful with upstream U-Boot which uses a different
587 value (which we will move to).
588 """
589 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800590 # The value that comes back from fdt.GetInt is signed, which makes no
591 # sense for an address base. Force it to unsigned.
592 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800593 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100594 text_base_str = '%#x' % text_base if text_base else 'None'
595 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
596 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800597
598 # If they are different, issue a warning and switch over.
599 if text_base and text_base != fdt_text_base:
600 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
601 "fdt value of %x. Using %x" % (text_base, name,
602 fdt_text_base, text_base))
603 fdt_text_base = text_base
604 return fdt_text_base
605
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600606 def _CreateBootStub(self, uboot, base_fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700607 """Create a boot stub and a signed boot stub.
608
609 Args:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600610 uboot: Path to u-boot.bin (may be chroot-relative).
Simon Glass29b96ad2012-03-09 15:34:33 -0800611 base_fdt: Fdt object containing the flat device tree.
Simon Glass89b86b82011-07-17 23:49:49 -0700612
613 Returns:
614 Tuple containing:
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600615 Full path to bootstub (uboot + fdt(-1)).
616 Full path to signed (uboot + fdt(flash pos) + bct).
Simon Glass89b86b82011-07-17 23:49:49 -0700617
618 Raises:
619 CmdError if a command fails.
620 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200621 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800622 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700623 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200624
625 # Make a copy of the fdt for the bootstub
626 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glass290a1802011-07-17 13:54:32 -0700627 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200628
Simon Glass89b86b82011-07-17 23:49:49 -0700629 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700630 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
631 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700632 self._tools.OutputSize('Combined binary', bootstub)
633
Simon Glasse13ee2c2011-07-28 08:12:28 +1200634 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700635 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700636 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200637 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200638
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600639 self._tools.OutputSize('Final bootstub', signed)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200640
Simon Glass5dcc0ba2016-05-14 16:19:59 -0600641 return bootstub, signed
Simon Glass89b86b82011-07-17 23:49:49 -0700642
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600643 def _AddCbfsFiles(self, bootstub, cbfs_files):
644 for dir, subs, files in os.walk(cbfs_files):
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600645 for file in files:
646 file = os.path.join(dir, file)
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600647 cbfs_name = file.replace(cbfs_files, '', 1).strip('/')
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600648 self._tools.Run('cbfstool', [bootstub, 'add', '-f', file,
649 '-n', cbfs_name, '-t', 'raw', '-c', 'lzma'])
650
651 def _CreateCorebootStub(self, pack, coreboot):
652 """Create a coreboot boot stub and add pack properties.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700653
654 Args:
Aaron Durbina113f522016-01-05 09:09:55 -0600655 pack: a PackFirmware object describing the firmware image to build.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700656 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700657 """
658 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700659 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100660
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600661 pack.AddProperty('coreboot', bootstub)
662 pack.AddProperty('image', bootstub)
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700663
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600664 # Add files to to RO and RW CBFS if provided.
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600665 if self.cbfs_files:
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600666 self._AddCbfsFiles(bootstub, self.cbfs_files)
Simon Glass7e199222012-03-13 15:51:18 -0700667
Aaron Durbina113f522016-01-05 09:09:55 -0600668 # Create a coreboot copy to use as a scratch pad. Order matters. The
669 # cbfs_files were added prior to this action. That's so the RW CBFS
Patrick Georgi3a332672015-11-20 10:02:51 +0100670 # regions inherit the files from the RO CBFS region. Additionally,
671 # include the full FMAP within the file.
672 cb_copy = os.path.abspath(os.path.join(self._tools.outdir, 'cb_with_fmap'))
Aaron Durbina113f522016-01-05 09:09:55 -0600673 self._tools.WriteFile(cb_copy, self._tools.ReadFile(bootstub))
Patrick Georgi3a332672015-11-20 10:02:51 +0100674 binary = self._tools.ReadFile(bootstub)
675 fmap_offset, fmap = pack.GetFmap()
676 if len(binary) < fmap_offset + len(fmap):
677 raise CmdError('FMAP will not fit')
678 # Splice in FMAP data.
679 binary = binary[:fmap_offset] + fmap + binary[fmap_offset + len(fmap):]
680 self._tools.WriteFile(cb_copy, binary)
681 # Publish where coreboot is with the FMAP data.
682 pack.AddProperty('cb_with_fmap', cb_copy)
Aaron Durbina113f522016-01-05 09:09:55 -0600683
Aaron Durbin95ef60c2016-01-06 09:17:21 -0600684 # Add files to to RO CBFS if provided. This done here such that the
685 # copy above does not contain the RO CBFS files.
686 if self.rocbfs_files:
687 self._AddCbfsFiles(bootstub, self.rocbfs_files)
688
Aaron Durbina113f522016-01-05 09:09:55 -0600689
Simon Glass89b86b82011-07-17 23:49:49 -0700690 def _PackOutput(self, msg):
691 """Helper function to write output from PackFirmware (verbose level 2).
692
693 This is passed to PackFirmware for it to use to write output.
694
695 Args:
696 msg: Message to display.
697 """
698 self._out.Notice(msg)
699
Aaron Durbin80564452015-12-21 15:25:06 -0600700 def _FmapNameByPath(self, path):
701 """ Take list of names to form node path. Return FMAP name.
702
703 Obtain the FMAP name described by the node path.
704
705 Args:
706 path: list forming a node path.
707
708 Returns:
709 FMAP name of fdt node.
710
711 Raises:
712 CmdError if path not found.
713 """
714 lbl = self.fdt.GetLabel(self.fdt.GetFlashNode(*path))
715 return re.sub('-', '_', lbl).upper()
716
717 def _PrepareCbfsHash(self, pack, blob_name):
718 """Create blob in rw-{a,b}-boothash with 'cbfstool hashcbfs'.
719
720 When the blob name is defined as cbfshash/<section>/<subsection>, fill the
721 <section>_<subsection> area in the flash map with CBFS hash generated
722 using the 'cbfstool hashcbfs' command.
723
724 Args:
725 pack: a PackFirmware object describing the firmware image to build.
726 blob_name: a string, blob name describing what FMAP section this CBFS
727 copy is destined to
728 Raises:
729 CmdError if cbfs-files node has incorrect parameters.
730 BlobDeferral if the CBFS region is not populated yet or if the coreboot
731 image with fmap is not available yet.
732 """
733 cb_copy = pack.GetProperty('cb_with_fmap')
734 if cb_copy is None:
735 raise BlobDeferral("Waiting for '%s'" % cb_copy)
736
737 part_sections = blob_name.split('/')[1:]
738 fmap_dst = self._FmapNameByPath(part_sections)
739
740 # Example of FDT ndoes asking for CBFS hash:
741 # rw-b-boot {
742 # label = "fw-main-b";
743 # reg = <0x00700000 0x002dff80>;
744 # type = "blob cbfs/rw/b-boot";
745 # };
746 # rw-b-boothash {
747 # label = "fw-main-b-hash";
748 # reg = <0x009dff80 0x00000040>;
749 # type = "blob cbfshash/rw/b-boothash";
750 # cbfs-node = "cbfs/rw/b-boot";
751 # };
752 hash_node = self.fdt.GetFlashNode(*part_sections)
753 cbfs_blob_name = self.fdt.GetString(hash_node, 'cbfs-node')
754
755 if not pack.GetProperty(cbfs_blob_name):
756 raise BlobDeferral("Waiting for '%s'" % cbfs_blob_name)
757
758 cbfs_node_path = cbfs_blob_name.split('/')[1:]
759 fmap_src = self._FmapNameByPath(cbfs_node_path)
760
761 # Compute CBFS hash and place it in the corect spot.
762 self._tools.Run('cbfstool', [cb_copy, 'hashcbfs', '-r', fmap_dst,
763 '-R', fmap_src, '-A', 'sha256'])
764
765 # Base address and size of the desitnation partition
766 base, size = self.fdt.GetFlashPart(*part_sections)
767
768 # And extract the blob for the FW section
769 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
770 self._tools.WriteFile(rw_section,
771 self._tools.ReadFile(cb_copy)[base:base+size])
772
773 pack.AddProperty(blob_name, rw_section)
774
775
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800776 def _PrepareCbfs(self, pack, blob_name):
777 """Create CBFS blob in rw-boot-{a,b} FMAP sections.
778
779 When the blob name is defined as cbfs#<section>#<subsection>, fill the
780 <section>_<subsection> area in the flash map with a CBFS copy, putting the
781 CBFS header of the copy at the base of the section.
782
783 If --coreboot-elf parameter was specified during cros_bumdle_firmware
784 invocation, add the parameter of this option as the payload to the new
785 CBFS instance.
786
787 Args:
788 pack: a PackFirmware object describing the firmware image to build.
789 blob_name: a string, blob name describing what FMAP section this CBFS
790 copy is destined to
791 Raises:
Patrick Georgi3a332672015-11-20 10:02:51 +0100792 CmdError if cbfs-files node has incorrect parameters.
Aaron Durbina113f522016-01-05 09:09:55 -0600793 BlobDeferral if coreboot image with fmap is not available yet.
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800794 """
Patrick Georgi3a332672015-11-20 10:02:51 +0100795 cb_copy = pack.GetProperty('cb_with_fmap')
Aaron Durbina113f522016-01-05 09:09:55 -0600796 if cb_copy is None:
Patrick Georgi3a332672015-11-20 10:02:51 +0100797 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800798
799 part_sections = blob_name.split('/')[1:]
Aaron Durbin80564452015-12-21 15:25:06 -0600800 fmap_dst = self._FmapNameByPath(part_sections)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800801
802 # Base address and size of the desitnation partition
803 base, size = self.fdt.GetFlashPart(*part_sections)
804
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800805 # Add coreboot payload if so requested. Note that the some images use
806 # different payload for the rw sections, which is passed in as the value
807 # of the --uboot option in the command line.
808 if self.uboot_fname:
809 payload_fname = self.uboot_fname
810 elif self.coreboot_elf:
811 payload_fname = self.coreboot_elf
812 else:
813 payload_fname = None
814
815 if payload_fname:
816 self._tools.Run('cbfstool', [
817 cb_copy, 'add-payload', '-f', payload_fname,
Patrick Georgi10690b42015-11-20 22:06:38 +0100818 '-n', 'fallback/payload', '-c', 'lzma' , '-r', fmap_dst])
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800819
Patrick Georgi964fb542015-10-16 16:52:03 +0200820 if self.ecrw_fname:
821 self._tools.Run('cbfstool', [
822 cb_copy, 'add', '-f', self.ecrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100823 '-n', 'ecrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200824
825 if self.pdrw_fname:
826 self._tools.Run('cbfstool', [
827 cb_copy, 'add', '-f', self.pdrw_fname, '-t', 'raw',
Patrick Georgi10690b42015-11-20 22:06:38 +0100828 '-n', 'pdrw', '-A', 'sha256', '-r', fmap_dst ])
Patrick Georgi964fb542015-10-16 16:52:03 +0200829
Aaron Durbin880cf952016-01-27 14:11:38 -0600830 # Parse the file list to obtain the last entry. If its empty use its
831 # offset as the size of the CBFS to hash.
832 stdout = self._tools.Run('cbfstool',
833 [ cb_copy, 'print', '-k', '-r', fmap_dst ])
834 # Fields are tab separated in the following order.
835 # Name Offset Type Metadata Size Data Size Total Size
836 last_entry = stdout.strip().splitlines()[-1].split('\t')
837 if last_entry[0] == '(empty)' and last_entry[2] == 'null':
838 size = int(last_entry[1], 16)
839
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800840 # And extract the blob for the FW section
841 rw_section = os.path.join(self._tools.outdir, '_'.join(part_sections))
842 self._tools.WriteFile(rw_section,
843 self._tools.ReadFile(cb_copy)[base:base+size])
844
845 pack.AddProperty(blob_name, rw_section)
846
847
Simon Glass439fe7a2012-03-09 16:19:34 -0800848 def _BuildBlob(self, pack, fdt, blob_type):
849 """Build the blob data for a particular blob type.
850
851 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700852 pack: a PackFirmware object describing the firmware image to build.
853 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800854 blob_type: The type of blob to create data for. Supported types are:
855 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
856 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700857
858 Raises:
859 CmdError if a command fails.
Aaron Durbin41c85b62015-12-17 17:40:29 -0600860 BlobDeferral if a blob is waiting for a dependency.
Simon Glass439fe7a2012-03-09 16:19:34 -0800861 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700862 # stupid pylint insists that sha256 is not in hashlib.
863 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800864 if blob_type == 'coreboot':
Aaron Durbin5751c3e2016-01-04 11:45:22 -0600865 self._CreateCorebootStub(pack, self.coreboot_fname)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700866 elif blob_type == 'legacy':
867 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800868 elif blob_type == 'signed':
Simon Glass942bedb2016-05-14 16:19:59 -0600869 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt, None)
Simon Glass439fe7a2012-03-09 16:19:34 -0800870 pack.AddProperty('bootstub', bootstub)
871 pack.AddProperty('signed', signed)
872 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700873 elif blob_type == 'exynos-bl1':
874 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700875
Patrick Georgi222c6e22016-09-09 22:20:55 +0200876 elif blob_type == 'ecrw':
Simon Glassbe0bc002012-08-16 12:50:48 -0700877 pack.AddProperty('ecrw', self.ecrw_fname)
Randall Spangler7307da92014-07-18 12:47:34 -0700878 elif blob_type == 'pdrw':
879 pack.AddProperty('pdrw', self.pdrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800880 elif blob_type == 'ecrwhash':
881 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
882 ecrw = self._tools.ReadFile(self.ecrw_fname)
883 hasher = hashlib.sha256()
884 hasher.update(ecrw)
885 self._tools.WriteFile(ec_hash_file, hasher.digest())
886 pack.AddProperty(blob_type, ec_hash_file)
Randall Spangler7307da92014-07-18 12:47:34 -0700887 elif blob_type == 'pdrwhash':
888 pd_hash_file = os.path.join(self._tools.outdir, 'pd_hash.bin')
889 pdrw = self._tools.ReadFile(self.pdrw_fname)
890 hasher = hashlib.sha256()
891 hasher.update(pdrw)
892 self._tools.WriteFile(pd_hash_file, hasher.digest())
893 pack.AddProperty(blob_type, pd_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700894 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700895 # crosbug.com/p/13143
896 # We cannot have an fmap in the EC image since there can be only one,
897 # which is the main fmap describing the whole image.
898 # Ultimately the EC will not have an fmap, since with software sync
899 # there is no flashrom involvement in updating the EC flash, and thus
900 # no need for the fmap.
901 # For now, mangle the fmap name to avoid problems.
902 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
903 data = self._tools.ReadFile(self.ecro_fname)
904 data = re.sub('__FMAP__', '__fMAP__', data)
905 self._tools.WriteFile(updated_ecro, data)
906 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600907 elif blob_type.startswith('exynos-bl2'):
908 # We need to configure this per node, so do it later
909 pass
Aaron Durbin80564452015-12-21 15:25:06 -0600910 elif blob_type.startswith('cbfshash'):
911 self._PrepareCbfsHash(pack, blob_type)
Vadim Bendeburyc9600c62014-12-22 16:31:13 -0800912 elif blob_type.startswith('cbfs'):
913 self._PrepareCbfs(pack, blob_type)
Simon Glass439fe7a2012-03-09 16:19:34 -0800914 elif pack.GetProperty(blob_type):
915 pass
Furquan Shaikh95ee50c2016-05-29 09:46:41 -0700916 elif blob_type == 'ifwi' or blob_type == 'sig2':
917 # Copy IFWI/CSE_SIGN(sig2) regions from coreboot copy and build a blob
918 # for the blob_type
919 cb_copy = pack.GetProperty('cb_with_fmap')
920 if cb_copy is None:
921 raise BlobDeferral("Waiting for 'cb_with_fmap' property")
922 blob_start, blob_size = fdt.GetFlashPart('ro', blob_type)
923 blob_file = blob_type + '.bin'
924 blob_path = os.path.join(self._tools.outdir, blob_file)
925 data = self._tools.ReadFile(cb_copy)
926 self._tools.WriteFile(blob_path, data[blob_start:blob_start+blob_size])
927 pack.AddProperty(blob_type, blob_path)
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800928 elif blob_type in self.blobs:
929 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800930 else:
931 raise CmdError("Unknown blob type '%s' required in flash map" %
932 blob_type)
933
Aaron Durbin41c85b62015-12-17 17:40:29 -0600934 def _BuildBlobs(self, pack, fdt):
935 """Build the blob data for the list of blobs in the pack.
936
937 Args:
938 pack: a PackFirmware object describing the firmware image to build.
939 fdt: an fdt object including image layout information
940
941 Raises:
942 CmdError if a command fails.
943 BlobDeferral if dependencies cannot be met because of cycles.
944 """
945 blob_list = pack.GetBlobList()
946 self._out.Info('Building blobs %s\n' % blob_list)
947
948 complete = False
949 deferred_list = []
950
951 # Build blobs allowing for dependencies between blobs. While this is
952 # an potential O(n^2) operation, in practice most blobs aren't dependent
953 # and should resolve in a few passes.
954 while not complete:
955 orig = set(blob_list)
956 for blob_type in blob_list:
957 try:
958 self._BuildBlob(pack, fdt, blob_type)
959 except (BlobDeferral):
960 deferred_list.append(blob_type)
961 if not deferred_list:
962 complete = True
963 # If deferred is the same as the original no progress is being made.
964 if not orig - set(deferred_list):
965 raise BlobDeferral("Blob cyle '%s'" % orig)
966 # Process the deferred blobs
967 blob_list = deferred_list[:]
968 deferred_list = []
969
Simon Glass290a1802011-07-17 13:54:32 -0700970 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700971 """Create a full firmware image, along with various by-products.
972
973 This uses the provided u-boot.bin, fdt and bct to create a firmware
974 image containing all the required parts. If the GBB is not supplied
975 then this will just return a signed U-Boot as the image.
976
977 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700978 gbb: a string, full path to the GBB file, or empty if a GBB is not
979 required.
980 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200981
982 Returns:
983 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700984 """
Simon Glass02d124a2012-03-02 14:47:20 -0800985 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700986
Simon Glass439fe7a2012-03-09 16:19:34 -0800987 pack = PackFirmware(self._tools, self._out)
Simon Glass00d027e2013-07-20 14:51:12 -0600988 if self._force_efs:
989 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -0600990 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
991 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800992
Simon Glass4f318912013-07-20 16:13:06 -0600993 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800994
995 # Get all our blobs ready
Vadim Bendebury466a7d82014-12-22 10:08:58 -0800996 if self.uboot_fname:
997 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800998 if self.skeleton_fname:
999 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -07001000 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -07001001
Simon Glassde9c8072012-07-02 22:29:02 -07001002 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
1003 if self.kernel_fname:
1004 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
1005
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001006 if gbb:
1007 pack.AddProperty('gbb', gbb)
Aaron Durbin41c85b62015-12-17 17:40:29 -06001008
1009 # Build the blobs out.
1010 self._BuildBlobs(pack, fdt)
Simon Glass89b86b82011-07-17 23:49:49 -07001011
Simon Glass7306b902012-12-17 15:06:21 -08001012 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -07001013 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -07001014 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +08001015 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -08001016 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +08001017 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -07001018 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001019 pack.AddProperty('fwid', fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -08001020 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -07001021
Simon Glass0a047bc2013-07-19 15:44:43 -06001022 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -06001023 todo = pack.GetMissingBlobs()
1024 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -06001025 if blob.key.startswith('exynos-bl2'):
1026 bl2 = ExynosBl2(self._tools, self._out)
1027 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1028 self.exynos_bl2))
1029
Simon Glassc90cf582012-03-13 15:40:47 -07001030 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -07001031
1032 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -08001033 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -07001034
Simon Glass4c24f662013-07-19 15:53:02 -06001035 # Recalculate the Exynos BL2, since it may have a hash. The call to
1036 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1037 # need to recalculate the hash.
1038 for blob in todo:
1039 if blob.key.startswith('exynos-bl2'):
1040 bl2 = ExynosBl2(self._tools, self._out)
1041 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1042 self.exynos_bl2))
1043
Simon Glass6207efe2012-12-17 15:04:36 -08001044 # Make a copy of the fdt for the bootstub
1045 fdt_data = self._tools.ReadFile(fdt.fname)
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001046 if self.uboot_fname:
1047 uboot_data = self._tools.ReadFile(self.uboot_fname)
1048 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1049 self._tools.WriteFile(uboot_copy, uboot_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001050
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001051 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1052 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
Simon Glass6207efe2012-12-17 15:04:36 -08001053
Simon Glassa10282a2013-01-08 17:06:41 -08001054 # Fix up the coreboot image here, since we can't do this until we have
1055 # a final device tree binary.
Aaron Durbin41c85b62015-12-17 17:40:29 -06001056 if 'coreboot' in pack.GetBlobList():
Simon Glasscbc83552012-07-23 15:26:22 +01001057 bootstub = pack.GetProperty('coreboot')
1058 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001059 if self.coreboot_elf:
1060 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1061 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
Vadim Bendebury466a7d82014-12-22 10:08:58 -08001062 elif self.uboot_fname:
Simon Glass0a7cf112013-05-21 23:08:21 -07001063 text_base = 0x1110000
1064
1065 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1066 # 1110015: 66 bb 00 01 mov $0x100,%bx
1067 marker = struct.pack('<L', 0x0100bb66)
1068 pos = uboot_data.find(marker)
1069 if pos == -1 or pos > 0x100:
1070 raise ValueError('Cannot find U-Boot cold boot entry point')
1071 entry = text_base + pos
1072 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001073 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1074 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001075 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001076 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1077 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001078 data = self._tools.ReadFile(bootstub)
1079 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1080 self._tools.WriteFile(bootstub_copy, data)
Vadim Bendebury9f36e712014-06-12 13:37:59 -07001081
Julius Werneraa1fe942014-11-21 17:16:11 -08001082 # Use offset and size from fmap.dts to extract CBFS area from coreboot.rom
1083 cbfs_offset, cbfs_size = fdt.GetFlashPart('ro', 'boot')
1084 self._tools.WriteFile(bootstub, data[cbfs_offset:cbfs_offset+cbfs_size])
Simon Glasscbc83552012-07-23 15:26:22 +01001085
Simon Glass208ad952013-02-10 11:16:46 -08001086 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001087 image = os.path.join(self._tools.outdir, 'image.bin')
1088 pack.PackImage(self._tools.outdir, image)
1089 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001090
Simon Glass439fe7a2012-03-09 16:19:34 -08001091 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001092 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001093 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001094
Simon Glassdedda6f2013-02-09 13:44:14 -08001095 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001096 """Select an FDT to control the firmware bundling
1097
Simon Glassdedda6f2013-02-09 13:44:14 -08001098 We make a copy of this which will include any on-the-fly changes we want
1099 to make.
1100
Simon Glass290a1802011-07-17 13:54:32 -07001101 Args:
1102 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001103 use_defaults: True to use a default FDT name if available, and to add
1104 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001105
Simon Glassc0f3dc62011-08-09 14:19:05 -07001106 Returns:
1107 The Fdt object of the original fdt file, which we will not modify.
1108
Simon Glassdedda6f2013-02-09 13:44:14 -08001109 Raises:
1110 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1111 False).
Simon Glass290a1802011-07-17 13:54:32 -07001112 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001113 if use_defaults:
1114 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001115 if not fdt_fname:
1116 raise ValueError('Please provide an FDT filename')
1117 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001118 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001119
Patrick Georgi81263072016-09-09 22:33:06 +02001120 fdt.Compile(None)
Simon Glasse53abbc2013-08-21 22:29:55 -06001121 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1122
Patrick Georgicebb5a22016-08-15 19:07:02 +02001123 if fdt.GetProp('/flash', 'reg', ''):
1124 raise ValueError('fmap.dts /flash is deprecated. Use chromeos.fmd')
1125
1126 # fill in /flash from binary fmap
1127 # ignore "read-only" attribute, that isn't used anywhere
Julius Wernerbcf0c942016-09-07 16:57:40 -07001128 bootblock_range = None
1129 coreboot_range = None
Patrick Georgicebb5a22016-08-15 19:07:02 +02001130 fmap_blob = open(self.coreboot_fname).read()
1131 f = fmap.fmap_decode(fmap_blob)
1132 fdt.PutString('/flash', 'compatible', 'chromeos,flashmap')
1133 fdt.PutIntList('/flash', 'reg', [f['base'], f['size']])
1134 for area in f['areas']:
1135 label = re.sub('_', '-', area['name']).lower()
1136 fdt_path = '/flash/' + label
1137 slot=label[-1]
1138 if label == 'gbb':
1139 fdt_path = '/flash/ro-gbb'
1140 fdt.PutString(fdt_path, 'type', 'blob gbb')
1141 elif label == 'fmap':
1142 fdt_path = '/flash/ro-fmap'
1143 fdt.PutString(fdt_path, 'type', 'fmap')
1144 fdt.PutIntList(fdt_path, 'ver-major', [1])
1145 fdt.PutIntList(fdt_path, 'ver-minor', [0])
Julius Wernerbcf0c942016-09-07 16:57:40 -07001146 elif label == 'bootblock':
1147 bootblock_range = [area['offset'], area['size']]
1148 continue
Patrick Georgicebb5a22016-08-15 19:07:02 +02001149 elif label == 'coreboot':
Julius Wernerbcf0c942016-09-07 16:57:40 -07001150 coreboot_range = [area['offset'], area['size']]
1151 continue
Patrick Georgicebb5a22016-08-15 19:07:02 +02001152 elif label == 'si-desc':
1153 fdt.PutString(fdt_path, 'type', 'ifd')
1154 elif label == 'rw-shared':
1155 fdt_path = '/flash/shared-section'
1156 elif label == 'rw-section-'+slot:
1157 fdt_path = '/flash/rw-'+slot
1158 elif label == 'rw-legacy' and self.seabios_fname:
1159 fdt.PutString(fdt_path, 'type', 'blob legacy')
1160 elif label in ['rw-mrc-cache', 'rw-elog', 'rw-legacy',
1161 'rw-vpd', 'rw-unused', 'ro-vpd', 'ro-unused',
1162 'ro-frid-pad', 'bios-unusable', 'device-extension',
1163 'unused-hole', 'rw-gpt-primary', 'rw-gpt-secondary',
1164 'rw-nvram', 'ro-unused-1', 'ro-unused-2']:
1165 fdt.PutString(fdt_path, 'type', 'wiped')
1166 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
1167 elif label == 'shared-data':
1168 fdt.PutString(fdt_path, 'type', 'wiped')
1169 fdt.PutIntList(fdt_path, 'wipe-value', [0])
1170 elif label == 'vblock-dev':
1171 fdt_path = '/flash/rw-vblock-dev'
1172 fdt.PutString(fdt_path, 'type', 'wiped')
1173 fdt.PutIntList(fdt_path, 'wipe-value', [0xff])
1174 elif label[:-1] == 'vblock-':
1175 fdt_path = '/flash/rw-'+slot+'-vblock'
1176 fdt.PutString(fdt_path, 'type', 'keyblock cbfs/rw/'+slot+'-boot')
1177 fdt.PutString(fdt_path, 'keyblock', 'firmware.keyblock')
1178 fdt.PutString(fdt_path, 'signprivate', 'firmware_data_key.vbprivk')
1179 fdt.PutString(fdt_path, 'kernelkey', 'kernel_subkey.vbpubk')
1180 fdt.PutIntList(fdt_path, 'version', [1])
1181 fdt.PutIntList(fdt_path, 'preamble-flags', [0])
1182 elif label[:-1] == 'fw-main-':
1183 fdt_path = '/flash/rw-'+slot+'-boot'
1184 fdt.PutString(fdt_path, 'type', 'blob cbfs/rw/'+slot+'-boot')
1185 elif label[:-1] == 'rw-fwid-':
1186 fdt_path = '/flash/rw-'+slot+'-firmware-id'
1187 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
1188 elif label == 'ro-frid':
1189 fdt_path = '/flash/ro-firmware-id'
1190 fdt.PutString(fdt_path, 'type', 'blobstring fwid')
1191 elif label == 'ifwi':
1192 fdt_path = '/flash/ro-ifwi'
1193 fdt.PutString(fdt_path, 'type', 'blob ifwi')
1194 elif label == 'sign-cse':
1195 fdt_path = '/flash/ro-sig'
1196 fdt.PutString(fdt_path, 'type', 'blob sig2')
1197 # white list for empty regions
Patrick Georgi56dc9202016-09-07 21:12:04 +02001198 elif label in ['bootblock', 'misc-rw', 'ro-section', 'rw-environment',
1199 'rw-gpt', 'si-all', 'si-bios', 'si-me', 'wp-ro']:
Patrick Georgicebb5a22016-08-15 19:07:02 +02001200 pass
1201 else:
1202 raise ValueError('encountered label "'+label+'" in binary fmap. '+
1203 'Check chromeos.fmd')
1204 fdt.PutString(fdt_path, 'label', label)
1205 fdt.PutIntList(fdt_path, 'reg', [area['offset'], area['size']])
1206
Julius Wernerbcf0c942016-09-07 16:57:40 -07001207 if coreboot_range is not None:
1208 if bootblock_range is not None:
1209 if bootblock_range[0] + bootblock_range[1] != coreboot_range[0]:
1210 raise ValueError('Cannot combine BOOTBLOCK and COREBOOT')
1211 coreboot_range[0] = bootblock_range[0]
1212 coreboot_range[1] += bootblock_range[1]
1213 fdt_path = '/flash/ro-boot'
1214 fdt.PutString(fdt_path, 'type', 'blob coreboot')
1215 fdt.PutString(fdt_path, 'label', 'coreboot')
1216 fdt.PutIntList(fdt_path, 'reg', [coreboot_range[0], coreboot_range[1]])
1217
Simon Glass7df773b2013-08-25 18:02:29 -06001218 # Remember our board type.
1219 fdt.PutString('/chromeos-config', 'board', self._board)
1220
Simon Glasse53abbc2013-08-21 22:29:55 -06001221 self.fdt = fdt
1222 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001223
Simon Glassc90cf582012-03-13 15:40:47 -07001224 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001225 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001226
1227 - Checks options, tools, output directory, fdt.
1228 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001229
1230 Args:
Simon Glass56577572011-07-19 11:08:06 +12001231 hardware_id: Hardware ID to use for this board. If None, then the
1232 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001233 output_fname: Output filename for the image. If this is not None, then
1234 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001235 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001236
1237 Returns:
1238 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001239 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001240 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1241 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1242 else:
Simon Glass56577572011-07-19 11:08:06 +12001243 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001244
1245 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001246 image, pack = self._CreateImage(gbb, self.fdt)
1247 if show_map:
1248 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001249 if output_fname:
1250 shutil.copyfile(image, output_fname)
1251 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001252 return image, pack.props