blob: 998039ed385d2c37eae5bdf063acef3a67bd9d3a [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
5"""This module builds a firmware image for a tegra-based board.
6
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
Simon Glass439fe7a2012-03-09 16:19:34 -080028from tools import CmdError
Vadim Bendeburyb12e3352013-06-08 17:25:19 -070029from exynos import ExynosBl2
Simon Glass89b86b82011-07-17 23:49:49 -070030
31# This data is required by bmpblk_utility. Does it ever change?
32# It was stored with the chromeos-bootimage ebuild, but we want
33# this utility to work outside the chroot.
34yaml_data = '''
35bmpblock: 1.0
36
37images:
38 devmode: DeveloperBmp/DeveloperBmp.bmp
39 recovery: RecoveryBmp/RecoveryBmp.bmp
40 rec_yuck: RecoveryNoOSBmp/RecoveryNoOSBmp.bmp
41 rec_insert: RecoveryMissingOSBmp/RecoveryMissingOSBmp.bmp
42
43screens:
44 dev_en:
45 - [0, 0, devmode]
46 rec_en:
47 - [0, 0, recovery]
48 yuck_en:
49 - [0, 0, rec_yuck]
50 ins_en:
51 - [0, 0, rec_insert]
52
53localizations:
54 - [ dev_en, rec_en, yuck_en, ins_en ]
55'''
56
Simon Glass0c54ba52012-11-06 12:36:43 -080057# Default flash maps for various boards we support.
58# These are used when no fdt is provided (e.g. upstream U-Boot with no
59# fdt. Each is a list of nodes.
Simon Glass4f318912013-07-20 16:13:06 -060060# Note: Use 'reg' instead of 'size' to fully specify the start and end of
61# each area, since there is no guarantee what order the nodes will appear
62# in the fdt, and if they are out of order the image will not boot.
Simon Glass0c54ba52012-11-06 12:36:43 -080063default_flashmaps = {
Simon Glass76958702012-11-08 13:07:53 -080064 'tegra' : [
65 {
Simon Glass4f318912013-07-20 16:13:06 -060066 'path' : '/flash',
67 'reg' : [0, 0x400000],
68 }, {
69 'path' : '/flash/ro-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -080070 'label' : 'boot-stub',
71 'size' : 512 << 10,
72 'read-only' : True,
73 'type' : 'blob signed',
74 'required' : True
75 }
76 ],
77 'daisy' : [
78 {
Simon Glass4f318912013-07-20 16:13:06 -060079 'path' : '/flash',
80 'reg' : [0, 0x400000],
81 }, {
82 'path' : '/flash/pre-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -080083 'label' : "bl1 pre-boot",
Simon Glass4f318912013-07-20 16:13:06 -060084 'reg' : [0, 0x2000],
Simon Glass0c54ba52012-11-06 12:36:43 -080085 'read-only' : True,
86 'filename' : "e5250.nbl1.bin",
87 'type' : "blob exynos-bl1",
88 'required' : True,
89 }, {
Simon Glass4f318912013-07-20 16:13:06 -060090 'path' : '/flash/spl',
Simon Glass0c54ba52012-11-06 12:36:43 -080091 'label' : "bl2 spl",
Simon Glass4f318912013-07-20 16:13:06 -060092 'reg' : [0x2000, 0x4000],
Simon Glass0c54ba52012-11-06 12:36:43 -080093 'read-only' : True,
94 'filename' : "bl2.bin",
95 'type' : "blob exynos-bl2 boot,dtb",
96 'required' : True,
97 }, {
Simon Glass4f318912013-07-20 16:13:06 -060098 'path' : '/flash/ro-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -080099 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600100 'reg' : [0x6000, 0x9a000],
Simon Glass0c54ba52012-11-06 12:36:43 -0800101 'read-only' : True,
102 'type' : "blob boot,dtb",
103 'required' : True,
104 }
Simon Glass76958702012-11-08 13:07:53 -0800105 ],
106 'link' : [
107 {
Simon Glass4f318912013-07-20 16:13:06 -0600108 'path' : '/flash',
109 'reg' : [0, 0x800000],
110 }, {
111 'path' : '/flash/si-all',
Simon Glass76958702012-11-08 13:07:53 -0800112 'label' : 'si-all',
Simon Glass4f318912013-07-20 16:13:06 -0600113 'reg' : [0x00000000, 0x00200000],
Simon Glass76958702012-11-08 13:07:53 -0800114 'type' : 'ifd',
115 'required' : True,
116 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600117 'path' : '/flash/ro-boot',
Simon Glass76958702012-11-08 13:07:53 -0800118 'label' : 'boot-stub',
Simon Glass4f318912013-07-20 16:13:06 -0600119 'reg' : [0x00700000, 0x00100000],
Simon Glass76958702012-11-08 13:07:53 -0800120 'read-only' : True,
121 'type' : 'blob coreboot',
122 'required' : True,
123 }
Simon Glassf2534222013-03-20 15:42:02 -0700124 ],
125 'peach' : [
126 {
Simon Glass4f318912013-07-20 16:13:06 -0600127 'path' : '/flash',
128 'reg' : [0, 0x400000],
129 }, {
130 'path' : '/flash/pre-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700131 'label' : "bl1 pre-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600132 'reg' : [0, 0x2000],
Simon Glassf2534222013-03-20 15:42:02 -0700133 'read-only' : True,
134 'filename' : "e5420.nbl1.bin",
135 'type' : "blob exynos-bl1",
136 'required' : True,
137 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600138 'path' : '/flash/spl',
Simon Glassf2534222013-03-20 15:42:02 -0700139 'label' : "bl2 spl",
Simon Glass4f318912013-07-20 16:13:06 -0600140 'reg' : [0x2000, 0x8000],
Simon Glassf2534222013-03-20 15:42:02 -0700141 'read-only' : True,
142 'filename' : "bl2.bin",
143 'type' : "blob exynos-bl2 boot,dtb",
144 'required' : True,
145 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600146 'path' : '/flash/ro-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700147 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600148 'reg' : [0xa000, 0x9a000],
Simon Glassf2534222013-03-20 15:42:02 -0700149 'read-only' : True,
150 'type' : "blob boot,dtb",
151 'required' : True,
152 }
153 ],
Simon Glass0c54ba52012-11-06 12:36:43 -0800154}
155
156
Simon Glass4a887b12012-10-23 16:29:03 -0700157# Build GBB flags.
158# (src/platform/vboot_reference/firmware/include/gbb_header.h)
159gbb_flag_properties = {
160 'dev-screen-short-delay': 0x00000001,
161 'load-option-roms': 0x00000002,
162 'enable-alternate-os': 0x00000004,
163 'force-dev-switch-on': 0x00000008,
164 'force-dev-boot-usb': 0x00000010,
165 'disable-fw-rollback-check': 0x00000020,
166 'enter-triggers-tonorm': 0x00000040,
167 'force-dev-boot-legacy': 0x00000080,
168}
169
Simon Glass49b026b2013-04-26 16:38:42 -0700170# Maps board name to Exynos product number
171type_to_model = {
172 'peach' : '5420',
173 'daisy' : '5250'
174}
175
Simon Glass5076a7f2012-10-23 16:31:54 -0700176def ListGoogleBinaryBlockFlags():
177 """Print out a list of GBB flags."""
178 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
179 for name, value in gbb_flag_properties.iteritems():
180 print ' %-30s %02x' % (name, value)
181
Simon Glass89b86b82011-07-17 23:49:49 -0700182class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -0700183 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -0700184
Simon Glass290a1802011-07-17 13:54:32 -0700185 Sequence of events:
186 bundle = Bundle(tools.Tools(), cros_output.Output())
187 bundle.SetDirs(...)
188 bundle.SetFiles(...)
189 bundle.SetOptions(...)
190 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -0700191 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -0700192 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -0700193
Simon Glass290a1802011-07-17 13:54:32 -0700194 Public properties:
195 fdt: The fdt object that we use for building our image. This wil be the
196 one specified by the user, except that we might add config options
197 to it. This is set up by SelectFdt() which must be called before
198 bundling starts.
199 uboot_fname: Full filename of the U-Boot binary we use.
200 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700201 spl_source: Source device to load U-Boot from, in SPL:
202 straps: Select device according to CPU strap pins
203 spi: Boot from SPI
204 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700205
206 Private attributes:
207 _small: True to create a 'small' signed U-Boot, False to produce a
208 full image. The small U-Boot is enough to boot but will not have
209 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700210 """
Simon Glass89b86b82011-07-17 23:49:49 -0700211
Simon Glass290a1802011-07-17 13:54:32 -0700212 def __init__(self, tools, output):
213 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700214
Simon Glass290a1802011-07-17 13:54:32 -0700215 Args:
216 tools: A tools.Tools object to use for external tools.
217 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700218 """
Simon Glass290a1802011-07-17 13:54:32 -0700219 self._tools = tools
220 self._out = output
221
222 # Set up the things we need to know in order to operate.
223 self._board = None # Board name, e.g. tegra2_seaboard.
224 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700225 self._force_rw = None
226 self._gbb_flags = None
227 self._keydir = None
228 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700229 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700230 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800231 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700232 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700233 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700234 self.ecro_fname = None # Filename of EC read-only file
235 self.ecrw_fname = None # Filename of EC file
Simon Glass7e199222012-03-13 15:51:18 -0700236 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
237 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700238 self.fdt = None # Our Fdt object.
239 self.kernel_fname = None
240 self.postload_fname = None
241 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700242 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700243 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700244
245 def SetDirs(self, keydir):
246 """Set up directories required for Bundle.
247
248 Args:
249 keydir: Directory containing keys to use for signing firmware.
250 """
251 self._keydir = keydir
252
Simon Glass6dcc2f22011-07-28 15:26:49 +1200253 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800254 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700255 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800256 skeleton=None, ecrw=None, ecro=None, kernel=None, blobs=None):
Simon Glass290a1802011-07-17 13:54:32 -0700257 """Set up files required for Bundle.
258
259 Args:
260 board: The name of the board to target (e.g. tegra2_seaboard).
261 uboot: The filename of the u-boot.bin image to use.
262 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800263 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800264 coreboot: The filename of the coreboot image to use (on x86).
265 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200266 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700267 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700268 exynos_bl1: The filename of the exynos BL1 file
269 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
270 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700271 ecrw: The filename of the EC (Embedded Controller) read-write file.
272 ecro: The filename of the EC (Embedded Controller) read-only file.
Simon Glassde9c8072012-07-02 22:29:02 -0700273 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800274 blobs: List of (type, filename) of arbitrary blobs.
Simon Glass290a1802011-07-17 13:54:32 -0700275 """
276 self._board = board
277 self.uboot_fname = uboot
278 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800279 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700280 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800281 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200282 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700283 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700284 self.exynos_bl1 = exynos_bl1
285 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700286 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700287 self.ecrw_fname = ecrw
288 self.ecro_fname = ecro
Simon Glassde9c8072012-07-02 22:29:02 -0700289 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800290 self.blobs = dict(blobs or ())
Simon Glass290a1802011-07-17 13:54:32 -0700291
Simon Glass6e486c22012-10-26 15:43:42 -0700292 def SetOptions(self, small, gbb_flags, force_rw=False):
Simon Glass290a1802011-07-17 13:54:32 -0700293 """Set up options supported by Bundle.
294
295 Args:
296 small: Only create a signed U-Boot - don't produce the full packed
297 firmware image. This is useful for devs who want to replace just the
298 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700299 gbb_flags: Specification for string containing adjustments to make.
300 force_rw: Force firmware into RW mode.
Simon Glass290a1802011-07-17 13:54:32 -0700301 """
302 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700303 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700304 self._force_rw = force_rw
Simon Glass290a1802011-07-17 13:54:32 -0700305
Simon Glass22f39fb2013-02-09 13:44:14 -0800306 def _GetBuildRoot(self):
307 """Get the path to this board's 'firmware' directory.
308
309 Returns:
310 Path to firmware directory, with ## representing the path to the
311 chroot.
312 """
Simon Glass290a1802011-07-17 13:54:32 -0700313 if not self._board:
314 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800315 return os.path.join('##', 'build', self._board, 'firmware')
316
317 def _CheckFdtFilename(self, fname):
318 """Check provided FDT filename and return the correct name if needed.
319
320 Where the filename lacks a path, add a default path for this board.
321 Where no FDT filename is provided, select a default one for this board.
322
323 Args:
324 fname: Proposed FDT filename.
325
326 Returns:
327 Selected FDT filename, after validation.
328 """
329 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700330 dir_name = os.path.join(build_root, 'dts')
Simon Glass22f39fb2013-02-09 13:44:14 -0800331 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700332 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700333 base_name = re.sub('_', '-', self._board)
334
335 # In case the name exists with a prefix or suffix, find it.
336 wildcard = os.path.join(dir_name, '*%s*.dts' % base_name)
337 found_list = glob.glob(self._tools.Filename(wildcard))
338 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800339 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700340 else:
341 # We didn't find anything definite, so set up our expected name.
Simon Glass22f39fb2013-02-09 13:44:14 -0800342 fname = os.path.join(dir_name, '%s.dts' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700343
Simon Glass881964d2012-04-04 11:34:09 -0700344 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800345 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700346 if not ext and not os.path.dirname(root):
Simon Glass22f39fb2013-02-09 13:44:14 -0800347 fname = os.path.join(dir_name, '%s.dts' % root)
348 return fname
349
350 def CheckOptions(self):
351 """Check provided options and select defaults."""
352 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700353
Simon Glass49b026b2013-04-26 16:38:42 -0700354 board_type = self._board.split('_')[0]
355 model = type_to_model.get(board_type)
356
Simon Glass290a1802011-07-17 13:54:32 -0700357 if not self.uboot_fname:
358 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
359 if not self.bct_fname:
360 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700361 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700362 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700363 if model:
364 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700365 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700366 if not self.exynos_bl2:
Simon Glassd05696e2013-06-13 20:14:00 -0700367 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl-wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700368 if not self.coreboot_fname:
369 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
370 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700371 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700372 if not self.seabios_fname:
373 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700374 if not self.ecrw_fname:
375 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
376 if not self.ecro_fname:
377 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700378
Simon Glass75759302012-03-15 20:26:53 -0700379 def GetFiles(self):
380 """Get a list of files that we know about.
381
382 This is the opposite of SetFiles except that we may have put in some
383 default names. It returns a dictionary containing the filename for
384 each of a number of pre-defined files.
385
386 Returns:
387 Dictionary, with one entry for each file.
388 """
389 file_list = {
390 'bct' : self.bct_fname,
391 'exynos-bl1' : self.exynos_bl1,
392 'exynos-bl2' : self.exynos_bl2,
393 }
394 return file_list
395
Simon Glass4a887b12012-10-23 16:29:03 -0700396 def DecodeGBBFlagsFromFdt(self):
397 """Get Google Binary Block flags from the FDT.
398
399 These should be in the chromeos-config node, like this:
400
401 chromeos-config {
402 gbb-flag-dev-screen-short-delay;
403 gbb-flag-force-dev-switch-on;
404 gbb-flag-force-dev-boot-usb;
405 gbb-flag-disable-fw-rollback-check;
406 };
407
408 Returns:
409 GBB flags value from FDT.
410 """
411 chromeos_config = self.fdt.GetProps("/chromeos-config")
412 gbb_flags = 0
413 for name in chromeos_config:
414 if name.startswith('gbb-flag-'):
415 flag_value = gbb_flag_properties.get(name[9:])
416 if flag_value:
417 gbb_flags |= flag_value
418 self._out.Notice("FDT: Enabling %s." % name)
419 else:
420 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
421 return gbb_flags
422
Simon Glass157c0662012-10-23 13:52:42 -0700423 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
424 """Decode ajustments to the provided GBB flags.
425
426 We support three options:
427
428 hex value: c2
429 defined value: force-dev-boot-usb,load-option-roms
430 adjust default value: -load-option-roms,+force-dev-boot-usb
431
432 The last option starts from the passed-in GBB flags and adds or removes
433 flags.
434
435 Args:
436 gbb_flags: Base (default) FDT flags.
437 adjustments: String containing adjustments to make.
438
439 Returns:
440 Updated FDT flags.
441 """
442 use_base_value = True
443 if adjustments:
444 try:
445 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700446 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700447 pass
448 for flag in adjustments.split(','):
449 oper = None
450 if flag[0] in ['-', '+']:
451 oper = flag[0]
452 flag = flag[1:]
453 value = gbb_flag_properties.get(flag)
454 if not value:
455 raise ValueError("Invalid GBB flag '%s'" % flag)
456 if oper == '+':
457 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800458 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700459 elif oper == '-':
460 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800461 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700462 else:
463 if use_base_value:
464 gbb_flags = 0
465 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800466 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700467 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800468 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700469
470 return gbb_flags
471
Simon Glass56577572011-07-19 11:08:06 +1200472 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700473 """Create a GBB for the image.
474
Simon Glass56577572011-07-19 11:08:06 +1200475 Args:
476 hardware_id: Hardware ID to use for this board. If None, then the
477 default from the Fdt will be used
478
Simon Glass89b86b82011-07-17 23:49:49 -0700479 Returns:
480 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700481 """
Simon Glass56577572011-07-19 11:08:06 +1200482 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800483 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700484 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700485 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700486
Simon Glass4a887b12012-10-23 16:29:03 -0700487 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800488
Simon Glass157c0662012-10-23 13:52:42 -0700489 # Allow command line to override flags
490 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
491
Simon Glass4a887b12012-10-23 16:29:03 -0700492 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700493 self._out.Progress('Creating GBB')
494 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
495 sizes = ['%#x' % size for size in sizes]
496 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700497 keydir = self._tools.Filename(self._keydir)
498 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700499 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200500 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700501 '--rootkey=%s/root_key.vbpubk' % keydir,
502 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700503 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800504 '--flags=%d' % gbb_flags,
Simon Glass89b86b82011-07-17 23:49:49 -0700505 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700506 cwd=odir)
507 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700508
Simon Glasse13ee2c2011-07-28 08:12:28 +1200509 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700510 """Sign an image so that the Tegra SOC will boot it.
511
512 Args:
513 bct: BCT file to use.
514 bootstub: Boot stub (U-Boot + fdt) file to sign.
515 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700516
517 Returns:
518 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700519 """
520 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200521 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700522 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200523 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700524 fd = open(config, 'w')
525 fd.write('Version = 1;\n')
526 fd.write('Redundancy = 1;\n')
527 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700528
529 # TODO(dianders): Right now, we don't have enough space in our flash map
530 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
531 # sure what this does for reliability, but at least things will fit...
532 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
533 if is_nand:
534 fd.write('Bctcopy = 1;\n')
535
Simon Glass89b86b82011-07-17 23:49:49 -0700536 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
537 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700538
Simon Glass89b86b82011-07-17 23:49:49 -0700539 fd.close()
540
541 self._tools.Run('cbootimage', [config, signed])
542 self._tools.OutputSize('BCT', bct)
543 self._tools.OutputSize('Signed image', signed)
544 return signed
545
Doug Anderson86ce5f42011-07-27 10:40:18 -0700546 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700547 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700548
549 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700550 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700551 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700552 """
Simon Glass468d8752012-09-19 16:36:19 -0700553 if bootcmd is not None:
554 if bootcmd == 'none':
555 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800556 self.fdt.PutString('/config', 'bootcmd', bootcmd)
557 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700558 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700559
Simon Glassa4934b72012-05-09 13:35:02 -0700560 def SetNodeEnabled(self, node_name, enabled):
561 """Set whether an node is enabled or disabled.
562
563 This simply sets the 'status' property of a node to "ok", or "disabled".
564
565 The node should either be a full path to the node (like '/uart@10200000')
566 or an alias property.
567
568 Aliases are supported like this:
569
570 aliases {
571 console = "/uart@10200000";
572 };
573
574 pointing to a node:
575
576 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700577 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700578 };
579
580 In this case, this function takes the name of the alias ('console' in
581 this case) and updates the status of the node that is pointed to, to
582 either ok or disabled. If the alias does not exist, a warning is
583 displayed.
584
585 Args:
586 node_name: Name of node (e.g. '/uart@10200000') or alias alias
587 (e.g. 'console') to adjust
588 enabled: True to enable, False to disable
589 """
590 # Look up the alias if this is an alias reference
591 if not node_name.startswith('/'):
592 lookup = self.fdt.GetString('/aliases', node_name, '')
593 if not lookup:
594 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
595 return
596 node_name = lookup
597 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700598 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700599 else:
600 status = 'disabled'
601 self.fdt.PutString(node_name, 'status', status)
602
603 def AddEnableList(self, enable_list):
604 """Process a list of nodes to enable/disable.
605
606 Args:
607 config_list: List of (node, value) tuples to add to the fdt. For each
608 tuple:
609 node: The fdt node to write to will be <node> or pointed to by
610 /aliases/<node>. We can tell which
611 value: 0 to disable the node, 1 to enable it
Vadim Bendebury507c0012013-06-09 12:49:25 -0700612 Raises:
613 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700614 """
615 if enable_list:
616 for node_name, enabled in enable_list:
617 try:
618 enabled = int(enabled)
619 if enabled not in (0, 1):
620 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700621 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700622 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700623 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700624 self.SetNodeEnabled(node_name, enabled)
625
Simon Glass290a1802011-07-17 13:54:32 -0700626 def AddConfigList(self, config_list, use_int=False):
627 """Add a list of config items to the fdt.
628
629 Normally these values are written to the fdt as strings, but integers
630 are also supported, in which case the values will be converted to integers
631 (if necessary) before being stored.
632
633 Args:
634 config_list: List of (config, value) tuples to add to the fdt. For each
635 tuple:
636 config: The fdt node to write to will be /config/<config>.
637 value: An integer or string value to write.
638 use_int: True to only write integer values.
639
640 Raises:
641 CmdError: if a value is required to be converted to integer but can't be.
642 """
643 if config_list:
644 for config in config_list:
645 value = config[1]
646 if use_int:
647 try:
648 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700649 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700650 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700651 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700652 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800653 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700654 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800655 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700656
Simon Glass7c2d5572011-11-15 14:47:08 -0800657 def DecodeTextBase(self, data):
658 """Look at a U-Boot image and try to decode its TEXT_BASE.
659
660 This works because U-Boot has a header with the value 0x12345678
661 immediately followed by the TEXT_BASE value. We can therefore read this
662 from the image with some certainty. We check only the first 40 words
663 since the header should be within that region.
664
Simon Glass96b50302012-07-20 06:55:28 +0100665 Since upstream Tegra has moved to having a 16KB SPL region at the start,
666 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
667 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
668
Simon Glass7c2d5572011-11-15 14:47:08 -0800669 Args:
670 data: U-Boot binary data
671
672 Returns:
673 Text base (integer) or None if none was found
674 """
675 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100676 for start in (0, 0x4000):
677 for i in range(start, start + 160, 4):
678 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800679
Simon Glass96b50302012-07-20 06:55:28 +0100680 # TODO(sjg): This does not cope with a big-endian target
681 value = struct.unpack('<I', word)[0]
682 if found:
683 return value - start
684 if value == 0x12345678:
685 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800686
687 return None
688
689 def CalcTextBase(self, name, fdt, fname):
690 """Calculate the TEXT_BASE to use for U-Boot.
691
692 Normally this value is in the fdt, so we just read it from there. But as
693 a second check we look at the image itself in case this is different, and
694 switch to that if it is.
695
696 This allows us to flash any U-Boot even if its TEXT_BASE is different.
697 This is particularly useful with upstream U-Boot which uses a different
698 value (which we will move to).
699 """
700 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800701 # The value that comes back from fdt.GetInt is signed, which makes no
702 # sense for an address base. Force it to unsigned.
703 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800704 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100705 text_base_str = '%#x' % text_base if text_base else 'None'
706 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
707 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800708
709 # If they are different, issue a warning and switch over.
710 if text_base and text_base != fdt_text_base:
711 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
712 "fdt value of %x. Using %x" % (text_base, name,
713 fdt_text_base, text_base))
714 fdt_text_base = text_base
715 return fdt_text_base
716
Simon Glass6dcc2f22011-07-28 15:26:49 +1200717 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700718 """Create a boot stub and a signed boot stub.
719
Simon Glass6dcc2f22011-07-28 15:26:49 +1200720 For postload:
721 We add a /config/postload-text-offset entry to the signed bootstub's
722 fdt so that U-Boot can find the postload code.
723
724 The raw (unsigned) bootstub will have a value of -1 for this since we will
725 simply append the postload code to the bootstub and it can find it there.
726 This will be used for RW A/B firmware.
727
728 For the signed case this value will specify where in the flash to find
729 the postload code. This will be used for RO firmware.
730
Simon Glass89b86b82011-07-17 23:49:49 -0700731 Args:
732 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800733 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200734 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700735
736 Returns:
737 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200738 Full path to bootstub (uboot + fdt(-1) + postload).
739 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700740
741 Raises:
742 CmdError if a command fails.
743 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200744 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800745 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700746 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200747
748 # Make a copy of the fdt for the bootstub
749 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700750 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700751 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200752
Simon Glass89b86b82011-07-17 23:49:49 -0700753 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700754 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
755 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700756 self._tools.OutputSize('Combined binary', bootstub)
757
Simon Glasse13ee2c2011-07-28 08:12:28 +1200758 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700759 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700760 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200761 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200762
763 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
764 data = self._tools.ReadFile(signed)
765
766 if postload:
767 # We must add postload to the bootstub since A and B will need to
768 # be able to find it without the /config/postload-text-offset mechanism.
769 bs_data = self._tools.ReadFile(bootstub)
770 bs_data += self._tools.ReadFile(postload)
771 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
772 self._tools.WriteFile(bootstub, bs_data)
773 self._tools.OutputSize('Combined binary with postload', bootstub)
774
775 # Now that we know the file size, adjust the fdt and re-sign
776 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800777 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200778 fdt_data = self._tools.ReadFile(fdt.fname)
779 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
780 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
781 postload_bootstub, text_base)
782 if len(data) != os.path.getsize(signed):
783 raise CmdError('Signed file size changed from %d to %d after updating '
784 'fdt' % (len(data), os.path.getsize(signed)))
785
786 # Re-read the signed image, and add the post-load binary.
787 data = self._tools.ReadFile(signed)
788 data += self._tools.ReadFile(postload)
789 self._tools.OutputSize('Post-load binary', postload)
790
791 self._tools.WriteFile(signed_postload, data)
792 self._tools.OutputSize('Final bootstub with postload', signed_postload)
793
794 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700795
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700796 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700797 """Create a coreboot boot stub.
798
799 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700800 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700801
802 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100803 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700804 """
805 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700806 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100807
808 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700809 return bootstub
810
Simon Glass7e199222012-03-13 15:51:18 -0700811
Simon Glass89b86b82011-07-17 23:49:49 -0700812 def _PackOutput(self, msg):
813 """Helper function to write output from PackFirmware (verbose level 2).
814
815 This is passed to PackFirmware for it to use to write output.
816
817 Args:
818 msg: Message to display.
819 """
820 self._out.Notice(msg)
821
Simon Glass439fe7a2012-03-09 16:19:34 -0800822 def _BuildBlob(self, pack, fdt, blob_type):
823 """Build the blob data for a particular blob type.
824
825 Args:
826 blob_type: The type of blob to create data for. Supported types are:
827 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
828 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700829
830 Raises:
831 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800832 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700833 # stupid pylint insists that sha256 is not in hashlib.
834 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800835 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700836 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800837 pack.AddProperty('coreboot', coreboot)
838 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700839 elif blob_type == 'legacy':
840 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800841 elif blob_type == 'signed':
842 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
843 self.postload_fname)
844 pack.AddProperty('bootstub', bootstub)
845 pack.AddProperty('signed', signed)
846 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700847 elif blob_type == 'exynos-bl1':
848 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700849
850 # TODO(sjg@chromium.org): Deprecate ecbin
851 elif blob_type in ['ecrw', 'ecbin']:
852 pack.AddProperty('ecrw', self.ecrw_fname)
853 pack.AddProperty('ecbin', self.ecrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800854 elif blob_type == 'ecrwhash':
855 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
856 ecrw = self._tools.ReadFile(self.ecrw_fname)
857 hasher = hashlib.sha256()
858 hasher.update(ecrw)
859 self._tools.WriteFile(ec_hash_file, hasher.digest())
860 pack.AddProperty(blob_type, ec_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700861 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700862 # crosbug.com/p/13143
863 # We cannot have an fmap in the EC image since there can be only one,
864 # which is the main fmap describing the whole image.
865 # Ultimately the EC will not have an fmap, since with software sync
866 # there is no flashrom involvement in updating the EC flash, and thus
867 # no need for the fmap.
868 # For now, mangle the fmap name to avoid problems.
869 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
870 data = self._tools.ReadFile(self.ecro_fname)
871 data = re.sub('__FMAP__', '__fMAP__', data)
872 self._tools.WriteFile(updated_ecro, data)
873 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600874 elif blob_type.startswith('exynos-bl2'):
875 # We need to configure this per node, so do it later
876 pass
Simon Glass439fe7a2012-03-09 16:19:34 -0800877 elif pack.GetProperty(blob_type):
878 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800879 elif blob_type in self.blobs:
880 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800881 else:
882 raise CmdError("Unknown blob type '%s' required in flash map" %
883 blob_type)
884
Simon Glass290a1802011-07-17 13:54:32 -0700885 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700886 """Create a full firmware image, along with various by-products.
887
888 This uses the provided u-boot.bin, fdt and bct to create a firmware
889 image containing all the required parts. If the GBB is not supplied
890 then this will just return a signed U-Boot as the image.
891
892 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +1200893 gbb: Full path to the GBB file, or empty if a GBB is not required.
894 fdt: Fdt object containing required information.
895
896 Returns:
897 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700898 """
Simon Glass02d124a2012-03-02 14:47:20 -0800899 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700900
Simon Glass439fe7a2012-03-09 16:19:34 -0800901 pack = PackFirmware(self._tools, self._out)
Vadim Bendebury238f6442013-03-27 11:23:25 -0700902 # Get the flashmap so we know what to build. For board variants use the
903 # main board name as the key (drop the _<variant> suffix).
904 default_flashmap = default_flashmaps.get(self._board.split('_')[0])
Simon Glassb8c6d952012-12-01 06:14:35 -0800905 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700906 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
907 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800908
Simon Glass4f318912013-07-20 16:13:06 -0600909 if not fdt.GetProp('/flash', 'reg', ''):
910 fdt.InsertNodes(default_flashmap)
911
912 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800913
914 # Get all our blobs ready
915 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800916 if self.skeleton_fname:
917 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700918 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700919
Simon Glassde9c8072012-07-02 22:29:02 -0700920 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
921 if self.kernel_fname:
922 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
923
Simon Glass439fe7a2012-03-09 16:19:34 -0800924 pack.AddProperty('gbb', self.uboot_fname)
Simon Glass9d088d92012-07-16 16:27:11 +0100925 blob_list = pack.GetBlobList()
926 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700927 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800928 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -0700929
Simon Glass7306b902012-12-17 15:06:21 -0800930 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700931 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700932 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +0800933 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -0800934 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +0800935 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700936 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800937 pack.AddProperty('fwid', fwid)
938 pack.AddProperty('gbb', gbb)
939 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700940
Simon Glass0a047bc2013-07-19 15:44:43 -0600941 # Some blobs need to be configured according to the node they are in.
942 for blob in pack.GetMissingBlobs():
943 if blob.key.startswith('exynos-bl2'):
944 bl2 = ExynosBl2(self._tools, self._out)
945 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
946 self.exynos_bl2))
947
Simon Glassc90cf582012-03-13 15:40:47 -0700948 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700949
950 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800951 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700952
Simon Glass6207efe2012-12-17 15:04:36 -0800953 # Make a copy of the fdt for the bootstub
954 fdt_data = self._tools.ReadFile(fdt.fname)
955 uboot_data = self._tools.ReadFile(self.uboot_fname)
956 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
957 self._tools.WriteFile(uboot_copy, uboot_data)
958
959 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
960 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
961
Simon Glassa10282a2013-01-08 17:06:41 -0800962 # Fix up the coreboot image here, since we can't do this until we have
963 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +0100964 if 'coreboot' in blob_list:
965 bootstub = pack.GetProperty('coreboot')
966 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -0800967 if self.coreboot_elf:
968 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
969 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
970 else:
Simon Glass0a7cf112013-05-21 23:08:21 -0700971 text_base = 0x1110000
972
973 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
974 # 1110015: 66 bb 00 01 mov $0x100,%bx
975 marker = struct.pack('<L', 0x0100bb66)
976 pos = uboot_data.find(marker)
977 if pos == -1 or pos > 0x100:
978 raise ValueError('Cannot find U-Boot cold boot entry point')
979 entry = text_base + pos
980 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -0800981 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
982 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -0700983 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -0700984 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
985 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -0800986 data = self._tools.ReadFile(bootstub)
987 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
988 self._tools.WriteFile(bootstub_copy, data)
Gabe Black3df75252013-02-14 21:32:10 -0800989 self._tools.WriteFile(bootstub, data[-0x100000:])
Simon Glasscbc83552012-07-23 15:26:22 +0100990
Simon Glass208ad952013-02-10 11:16:46 -0800991 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -0700992 image = os.path.join(self._tools.outdir, 'image.bin')
993 pack.PackImage(self._tools.outdir, image)
994 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -0700995
Simon Glass439fe7a2012-03-09 16:19:34 -0800996 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -0700997 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -0700998 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -0700999
Simon Glassdedda6f2013-02-09 13:44:14 -08001000 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001001 """Select an FDT to control the firmware bundling
1002
Simon Glassdedda6f2013-02-09 13:44:14 -08001003 We make a copy of this which will include any on-the-fly changes we want
1004 to make.
1005
Simon Glass290a1802011-07-17 13:54:32 -07001006 Args:
1007 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001008 use_defaults: True to use a default FDT name if available, and to add
1009 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001010
Simon Glassc0f3dc62011-08-09 14:19:05 -07001011 Returns:
1012 The Fdt object of the original fdt file, which we will not modify.
1013
Simon Glassdedda6f2013-02-09 13:44:14 -08001014 Raises:
1015 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1016 False).
Simon Glass290a1802011-07-17 13:54:32 -07001017 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001018 if use_defaults:
1019 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001020 if not fdt_fname:
1021 raise ValueError('Please provide an FDT filename')
1022 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001023 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001024
1025 # For upstream, select the correct architecture .dtsi manually.
1026 if self._board == 'link' or 'x86' in self._board:
1027 arch_dts = 'coreboot.dtsi'
1028 elif self._board == 'daisy':
1029 arch_dts = 'exynos5250.dtsi'
1030 else:
1031 arch_dts = 'tegra20.dtsi'
1032
1033 fdt.Compile(arch_dts)
Simon Glass290a1802011-07-17 13:54:32 -07001034 self.fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Simon Glass32abe2e2013-07-18 18:00:55 -06001035 return self.fdt
Simon Glass290a1802011-07-17 13:54:32 -07001036
Simon Glassc90cf582012-03-13 15:40:47 -07001037 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001038 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001039
1040 - Checks options, tools, output directory, fdt.
1041 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001042
1043 Args:
Simon Glass56577572011-07-19 11:08:06 +12001044 hardware_id: Hardware ID to use for this board. If None, then the
1045 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001046 output_fname: Output filename for the image. If this is not None, then
1047 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001048 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001049
1050 Returns:
1051 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001052 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001053 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1054 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1055 else:
Simon Glass56577572011-07-19 11:08:06 +12001056 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001057
1058 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001059 image, pack = self._CreateImage(gbb, self.fdt)
1060 if show_map:
1061 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001062 if output_fname:
1063 shutil.copyfile(image, output_fname)
1064 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001065 return image, pack.props