blob: fe6ded4898e2f07d3cbd74782946a1983b232e5c [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 }, {
Simon Glass81ed0792013-07-20 17:36:24 -060082 'path' : '/memory',
83 'reg' : [0x40000000, 0x80000000],
84 }, {
85 'path' : '/iram',
86 'reg' : [0x02020000, 384 << 10],
87 }, {
88 'path' : '/config',
89 'samsung,bl1-offset' : 0x1400,
90 'samsung,bl2-offset' : 0x3400,
91 'u-boot-memory' : '/memory',
92 'u-boot-offset' : [0x3e00000, 0x100000],
93 }, {
Simon Glass4f318912013-07-20 16:13:06 -060094 'path' : '/flash/pre-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -080095 'label' : "bl1 pre-boot",
Simon Glass4f318912013-07-20 16:13:06 -060096 'reg' : [0, 0x2000],
Simon Glass0c54ba52012-11-06 12:36:43 -080097 'read-only' : True,
98 'filename' : "e5250.nbl1.bin",
99 'type' : "blob exynos-bl1",
100 'required' : True,
101 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600102 'path' : '/flash/spl',
Simon Glass0c54ba52012-11-06 12:36:43 -0800103 'label' : "bl2 spl",
Simon Glass4f318912013-07-20 16:13:06 -0600104 'reg' : [0x2000, 0x4000],
Simon Glass0c54ba52012-11-06 12:36:43 -0800105 'read-only' : True,
106 'filename' : "bl2.bin",
107 'type' : "blob exynos-bl2 boot,dtb",
108 'required' : True,
109 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600110 'path' : '/flash/ro-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -0800111 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600112 'reg' : [0x6000, 0x9a000],
Simon Glass0c54ba52012-11-06 12:36:43 -0800113 'read-only' : True,
114 'type' : "blob boot,dtb",
115 'required' : True,
116 }
Simon Glass76958702012-11-08 13:07:53 -0800117 ],
118 'link' : [
119 {
Simon Glass4f318912013-07-20 16:13:06 -0600120 'path' : '/flash',
121 'reg' : [0, 0x800000],
122 }, {
123 'path' : '/flash/si-all',
Simon Glass76958702012-11-08 13:07:53 -0800124 'label' : 'si-all',
Simon Glass4f318912013-07-20 16:13:06 -0600125 'reg' : [0x00000000, 0x00200000],
Simon Glass76958702012-11-08 13:07:53 -0800126 'type' : 'ifd',
127 'required' : True,
128 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600129 'path' : '/flash/ro-boot',
Simon Glass76958702012-11-08 13:07:53 -0800130 'label' : 'boot-stub',
Simon Glass4f318912013-07-20 16:13:06 -0600131 'reg' : [0x00700000, 0x00100000],
Simon Glass76958702012-11-08 13:07:53 -0800132 'read-only' : True,
133 'type' : 'blob coreboot',
134 'required' : True,
135 }
Simon Glassf2534222013-03-20 15:42:02 -0700136 ],
137 'peach' : [
138 {
Simon Glass4f318912013-07-20 16:13:06 -0600139 'path' : '/flash',
140 'reg' : [0, 0x400000],
141 }, {
Simon Glass81ed0792013-07-20 17:36:24 -0600142 'path' : '/memory',
143 'reg' : [0x20000000, 0x80000000], # Assume 2GB of RAM
144 }, {
145 'path' : '/iram',
146 'reg' : [0x02020000, 384 << 10],
147 }, {
148 'path' : '/config',
149 'samsung,bl1-offset' : 0x2400,
150 'samsung,bl2-offset' : 0x4400,
151 'u-boot-memory' : '/memory',
152 'u-boot-offset' : [0x3e00000, 0x100000],
153 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600154 'path' : '/flash/pre-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700155 'label' : "bl1 pre-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600156 'reg' : [0, 0x2000],
Simon Glassf2534222013-03-20 15:42:02 -0700157 'read-only' : True,
158 'filename' : "e5420.nbl1.bin",
159 'type' : "blob exynos-bl1",
160 'required' : True,
161 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600162 'path' : '/flash/spl',
Simon Glassf2534222013-03-20 15:42:02 -0700163 'label' : "bl2 spl",
Simon Glass4f318912013-07-20 16:13:06 -0600164 'reg' : [0x2000, 0x8000],
Simon Glassf2534222013-03-20 15:42:02 -0700165 'read-only' : True,
166 'filename' : "bl2.bin",
167 'type' : "blob exynos-bl2 boot,dtb",
168 'required' : True,
169 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600170 'path' : '/flash/ro-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700171 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600172 'reg' : [0xa000, 0x9a000],
Simon Glassf2534222013-03-20 15:42:02 -0700173 'read-only' : True,
174 'type' : "blob boot,dtb",
175 'required' : True,
176 }
177 ],
Simon Glass0c54ba52012-11-06 12:36:43 -0800178}
179
180
Simon Glass4a887b12012-10-23 16:29:03 -0700181# Build GBB flags.
182# (src/platform/vboot_reference/firmware/include/gbb_header.h)
183gbb_flag_properties = {
184 'dev-screen-short-delay': 0x00000001,
185 'load-option-roms': 0x00000002,
186 'enable-alternate-os': 0x00000004,
187 'force-dev-switch-on': 0x00000008,
188 'force-dev-boot-usb': 0x00000010,
189 'disable-fw-rollback-check': 0x00000020,
190 'enter-triggers-tonorm': 0x00000040,
191 'force-dev-boot-legacy': 0x00000080,
192}
193
Simon Glass49b026b2013-04-26 16:38:42 -0700194# Maps board name to Exynos product number
195type_to_model = {
196 'peach' : '5420',
197 'daisy' : '5250'
198}
199
Simon Glass5076a7f2012-10-23 16:31:54 -0700200def ListGoogleBinaryBlockFlags():
201 """Print out a list of GBB flags."""
202 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
203 for name, value in gbb_flag_properties.iteritems():
204 print ' %-30s %02x' % (name, value)
205
Simon Glass89b86b82011-07-17 23:49:49 -0700206class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -0700207 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -0700208
Simon Glass290a1802011-07-17 13:54:32 -0700209 Sequence of events:
210 bundle = Bundle(tools.Tools(), cros_output.Output())
211 bundle.SetDirs(...)
212 bundle.SetFiles(...)
213 bundle.SetOptions(...)
214 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -0700215 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -0700216 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -0700217
Simon Glass290a1802011-07-17 13:54:32 -0700218 Public properties:
219 fdt: The fdt object that we use for building our image. This wil be the
220 one specified by the user, except that we might add config options
221 to it. This is set up by SelectFdt() which must be called before
222 bundling starts.
223 uboot_fname: Full filename of the U-Boot binary we use.
224 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700225 spl_source: Source device to load U-Boot from, in SPL:
226 straps: Select device according to CPU strap pins
227 spi: Boot from SPI
228 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700229
230 Private attributes:
231 _small: True to create a 'small' signed U-Boot, False to produce a
232 full image. The small U-Boot is enough to boot but will not have
233 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700234 """
Simon Glass89b86b82011-07-17 23:49:49 -0700235
Simon Glass290a1802011-07-17 13:54:32 -0700236 def __init__(self, tools, output):
237 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700238
Simon Glass290a1802011-07-17 13:54:32 -0700239 Args:
240 tools: A tools.Tools object to use for external tools.
241 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700242 """
Simon Glass290a1802011-07-17 13:54:32 -0700243 self._tools = tools
244 self._out = output
245
246 # Set up the things we need to know in order to operate.
247 self._board = None # Board name, e.g. tegra2_seaboard.
248 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700249 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600250 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700251 self._gbb_flags = None
252 self._keydir = None
253 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700254 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700255 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800256 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700257 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700258 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700259 self.ecro_fname = None # Filename of EC read-only file
260 self.ecrw_fname = None # Filename of EC file
Simon Glass7e199222012-03-13 15:51:18 -0700261 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
262 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700263 self.fdt = None # Our Fdt object.
264 self.kernel_fname = None
265 self.postload_fname = None
266 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700267 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700268 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700269
270 def SetDirs(self, keydir):
271 """Set up directories required for Bundle.
272
273 Args:
274 keydir: Directory containing keys to use for signing firmware.
275 """
276 self._keydir = keydir
277
Simon Glass6dcc2f22011-07-28 15:26:49 +1200278 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800279 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700280 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800281 skeleton=None, ecrw=None, ecro=None, kernel=None, blobs=None):
Simon Glass290a1802011-07-17 13:54:32 -0700282 """Set up files required for Bundle.
283
284 Args:
285 board: The name of the board to target (e.g. tegra2_seaboard).
286 uboot: The filename of the u-boot.bin image to use.
287 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800288 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800289 coreboot: The filename of the coreboot image to use (on x86).
290 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200291 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700292 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700293 exynos_bl1: The filename of the exynos BL1 file
294 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
295 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700296 ecrw: The filename of the EC (Embedded Controller) read-write file.
297 ecro: The filename of the EC (Embedded Controller) read-only file.
Simon Glassde9c8072012-07-02 22:29:02 -0700298 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800299 blobs: List of (type, filename) of arbitrary blobs.
Simon Glass290a1802011-07-17 13:54:32 -0700300 """
301 self._board = board
302 self.uboot_fname = uboot
303 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800304 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700305 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800306 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200307 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700308 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700309 self.exynos_bl1 = exynos_bl1
310 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700311 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700312 self.ecrw_fname = ecrw
313 self.ecro_fname = ecro
Simon Glassde9c8072012-07-02 22:29:02 -0700314 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800315 self.blobs = dict(blobs or ())
Simon Glass290a1802011-07-17 13:54:32 -0700316
Simon Glass00d027e2013-07-20 14:51:12 -0600317 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700318 """Set up options supported by Bundle.
319
320 Args:
321 small: Only create a signed U-Boot - don't produce the full packed
322 firmware image. This is useful for devs who want to replace just the
323 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700324 gbb_flags: Specification for string containing adjustments to make.
325 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600326 force_efs: Force firmware to use 'early firmware selection' feature,
327 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700328 """
329 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700330 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700331 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600332 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700333
Simon Glass22f39fb2013-02-09 13:44:14 -0800334 def _GetBuildRoot(self):
335 """Get the path to this board's 'firmware' directory.
336
337 Returns:
338 Path to firmware directory, with ## representing the path to the
339 chroot.
340 """
Simon Glass290a1802011-07-17 13:54:32 -0700341 if not self._board:
342 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800343 return os.path.join('##', 'build', self._board, 'firmware')
344
345 def _CheckFdtFilename(self, fname):
346 """Check provided FDT filename and return the correct name if needed.
347
348 Where the filename lacks a path, add a default path for this board.
349 Where no FDT filename is provided, select a default one for this board.
350
351 Args:
352 fname: Proposed FDT filename.
353
354 Returns:
355 Selected FDT filename, after validation.
356 """
357 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700358 dir_name = os.path.join(build_root, 'dts')
Simon Glass22f39fb2013-02-09 13:44:14 -0800359 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700360 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700361 base_name = re.sub('_', '-', self._board)
362
363 # In case the name exists with a prefix or suffix, find it.
364 wildcard = os.path.join(dir_name, '*%s*.dts' % base_name)
365 found_list = glob.glob(self._tools.Filename(wildcard))
366 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800367 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700368 else:
369 # We didn't find anything definite, so set up our expected name.
Simon Glass22f39fb2013-02-09 13:44:14 -0800370 fname = os.path.join(dir_name, '%s.dts' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700371
Simon Glass881964d2012-04-04 11:34:09 -0700372 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800373 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700374 if not ext and not os.path.dirname(root):
Simon Glass22f39fb2013-02-09 13:44:14 -0800375 fname = os.path.join(dir_name, '%s.dts' % root)
376 return fname
377
378 def CheckOptions(self):
379 """Check provided options and select defaults."""
380 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700381
Simon Glass49b026b2013-04-26 16:38:42 -0700382 board_type = self._board.split('_')[0]
383 model = type_to_model.get(board_type)
384
Simon Glass290a1802011-07-17 13:54:32 -0700385 if not self.uboot_fname:
386 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
387 if not self.bct_fname:
388 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700389 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700390 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700391 if model:
392 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700393 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700394 if not self.exynos_bl2:
Simon Glassd05696e2013-06-13 20:14:00 -0700395 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl-wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700396 if not self.coreboot_fname:
397 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
398 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700399 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700400 if not self.seabios_fname:
401 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700402 if not self.ecrw_fname:
403 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
404 if not self.ecro_fname:
405 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700406
Simon Glass75759302012-03-15 20:26:53 -0700407 def GetFiles(self):
408 """Get a list of files that we know about.
409
410 This is the opposite of SetFiles except that we may have put in some
411 default names. It returns a dictionary containing the filename for
412 each of a number of pre-defined files.
413
414 Returns:
415 Dictionary, with one entry for each file.
416 """
417 file_list = {
418 'bct' : self.bct_fname,
419 'exynos-bl1' : self.exynos_bl1,
420 'exynos-bl2' : self.exynos_bl2,
421 }
422 return file_list
423
Simon Glass4a887b12012-10-23 16:29:03 -0700424 def DecodeGBBFlagsFromFdt(self):
425 """Get Google Binary Block flags from the FDT.
426
427 These should be in the chromeos-config node, like this:
428
429 chromeos-config {
430 gbb-flag-dev-screen-short-delay;
431 gbb-flag-force-dev-switch-on;
432 gbb-flag-force-dev-boot-usb;
433 gbb-flag-disable-fw-rollback-check;
434 };
435
436 Returns:
437 GBB flags value from FDT.
438 """
439 chromeos_config = self.fdt.GetProps("/chromeos-config")
440 gbb_flags = 0
441 for name in chromeos_config:
442 if name.startswith('gbb-flag-'):
443 flag_value = gbb_flag_properties.get(name[9:])
444 if flag_value:
445 gbb_flags |= flag_value
446 self._out.Notice("FDT: Enabling %s." % name)
447 else:
448 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
449 return gbb_flags
450
Simon Glass157c0662012-10-23 13:52:42 -0700451 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
452 """Decode ajustments to the provided GBB flags.
453
454 We support three options:
455
456 hex value: c2
457 defined value: force-dev-boot-usb,load-option-roms
458 adjust default value: -load-option-roms,+force-dev-boot-usb
459
460 The last option starts from the passed-in GBB flags and adds or removes
461 flags.
462
463 Args:
464 gbb_flags: Base (default) FDT flags.
465 adjustments: String containing adjustments to make.
466
467 Returns:
468 Updated FDT flags.
469 """
470 use_base_value = True
471 if adjustments:
472 try:
473 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700474 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700475 pass
476 for flag in adjustments.split(','):
477 oper = None
478 if flag[0] in ['-', '+']:
479 oper = flag[0]
480 flag = flag[1:]
481 value = gbb_flag_properties.get(flag)
482 if not value:
483 raise ValueError("Invalid GBB flag '%s'" % flag)
484 if oper == '+':
485 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800486 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700487 elif oper == '-':
488 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800489 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700490 else:
491 if use_base_value:
492 gbb_flags = 0
493 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800494 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700495 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800496 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700497
498 return gbb_flags
499
Simon Glass56577572011-07-19 11:08:06 +1200500 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700501 """Create a GBB for the image.
502
Simon Glass56577572011-07-19 11:08:06 +1200503 Args:
504 hardware_id: Hardware ID to use for this board. If None, then the
505 default from the Fdt will be used
506
Simon Glass89b86b82011-07-17 23:49:49 -0700507 Returns:
508 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700509 """
Simon Glass56577572011-07-19 11:08:06 +1200510 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800511 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700512 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700513 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700514
Simon Glass4a887b12012-10-23 16:29:03 -0700515 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800516
Simon Glass157c0662012-10-23 13:52:42 -0700517 # Allow command line to override flags
518 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
519
Simon Glass4a887b12012-10-23 16:29:03 -0700520 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700521 self._out.Progress('Creating GBB')
522 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
523 sizes = ['%#x' % size for size in sizes]
524 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700525 keydir = self._tools.Filename(self._keydir)
526 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700527 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200528 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700529 '--rootkey=%s/root_key.vbpubk' % keydir,
530 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700531 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800532 '--flags=%d' % gbb_flags,
Simon Glass89b86b82011-07-17 23:49:49 -0700533 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700534 cwd=odir)
535 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700536
Simon Glasse13ee2c2011-07-28 08:12:28 +1200537 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700538 """Sign an image so that the Tegra SOC will boot it.
539
540 Args:
541 bct: BCT file to use.
542 bootstub: Boot stub (U-Boot + fdt) file to sign.
543 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700544
545 Returns:
546 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700547 """
548 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200549 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700550 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200551 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700552 fd = open(config, 'w')
553 fd.write('Version = 1;\n')
554 fd.write('Redundancy = 1;\n')
555 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700556
557 # TODO(dianders): Right now, we don't have enough space in our flash map
558 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
559 # sure what this does for reliability, but at least things will fit...
560 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
561 if is_nand:
562 fd.write('Bctcopy = 1;\n')
563
Simon Glass89b86b82011-07-17 23:49:49 -0700564 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
565 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700566
Simon Glass89b86b82011-07-17 23:49:49 -0700567 fd.close()
568
569 self._tools.Run('cbootimage', [config, signed])
570 self._tools.OutputSize('BCT', bct)
571 self._tools.OutputSize('Signed image', signed)
572 return signed
573
Doug Anderson86ce5f42011-07-27 10:40:18 -0700574 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700575 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700576
577 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700578 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700579 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700580 """
Simon Glass468d8752012-09-19 16:36:19 -0700581 if bootcmd is not None:
582 if bootcmd == 'none':
583 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800584 self.fdt.PutString('/config', 'bootcmd', bootcmd)
585 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700586 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700587
Simon Glassa4934b72012-05-09 13:35:02 -0700588 def SetNodeEnabled(self, node_name, enabled):
589 """Set whether an node is enabled or disabled.
590
591 This simply sets the 'status' property of a node to "ok", or "disabled".
592
593 The node should either be a full path to the node (like '/uart@10200000')
594 or an alias property.
595
596 Aliases are supported like this:
597
598 aliases {
599 console = "/uart@10200000";
600 };
601
602 pointing to a node:
603
604 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700605 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700606 };
607
608 In this case, this function takes the name of the alias ('console' in
609 this case) and updates the status of the node that is pointed to, to
610 either ok or disabled. If the alias does not exist, a warning is
611 displayed.
612
613 Args:
614 node_name: Name of node (e.g. '/uart@10200000') or alias alias
615 (e.g. 'console') to adjust
616 enabled: True to enable, False to disable
617 """
618 # Look up the alias if this is an alias reference
619 if not node_name.startswith('/'):
620 lookup = self.fdt.GetString('/aliases', node_name, '')
621 if not lookup:
622 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
623 return
624 node_name = lookup
625 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700626 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700627 else:
628 status = 'disabled'
629 self.fdt.PutString(node_name, 'status', status)
630
631 def AddEnableList(self, enable_list):
632 """Process a list of nodes to enable/disable.
633
634 Args:
635 config_list: List of (node, value) tuples to add to the fdt. For each
636 tuple:
637 node: The fdt node to write to will be <node> or pointed to by
638 /aliases/<node>. We can tell which
639 value: 0 to disable the node, 1 to enable it
Vadim Bendebury507c0012013-06-09 12:49:25 -0700640 Raises:
641 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700642 """
643 if enable_list:
644 for node_name, enabled in enable_list:
645 try:
646 enabled = int(enabled)
647 if enabled not in (0, 1):
648 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700649 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700650 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700651 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700652 self.SetNodeEnabled(node_name, enabled)
653
Simon Glass290a1802011-07-17 13:54:32 -0700654 def AddConfigList(self, config_list, use_int=False):
655 """Add a list of config items to the fdt.
656
657 Normally these values are written to the fdt as strings, but integers
658 are also supported, in which case the values will be converted to integers
659 (if necessary) before being stored.
660
661 Args:
662 config_list: List of (config, value) tuples to add to the fdt. For each
663 tuple:
664 config: The fdt node to write to will be /config/<config>.
665 value: An integer or string value to write.
666 use_int: True to only write integer values.
667
668 Raises:
669 CmdError: if a value is required to be converted to integer but can't be.
670 """
671 if config_list:
672 for config in config_list:
673 value = config[1]
674 if use_int:
675 try:
676 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700677 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700678 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700679 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700680 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800681 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700682 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800683 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700684
Simon Glass7c2d5572011-11-15 14:47:08 -0800685 def DecodeTextBase(self, data):
686 """Look at a U-Boot image and try to decode its TEXT_BASE.
687
688 This works because U-Boot has a header with the value 0x12345678
689 immediately followed by the TEXT_BASE value. We can therefore read this
690 from the image with some certainty. We check only the first 40 words
691 since the header should be within that region.
692
Simon Glass96b50302012-07-20 06:55:28 +0100693 Since upstream Tegra has moved to having a 16KB SPL region at the start,
694 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
695 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
696
Simon Glass7c2d5572011-11-15 14:47:08 -0800697 Args:
698 data: U-Boot binary data
699
700 Returns:
701 Text base (integer) or None if none was found
702 """
703 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100704 for start in (0, 0x4000):
705 for i in range(start, start + 160, 4):
706 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800707
Simon Glass96b50302012-07-20 06:55:28 +0100708 # TODO(sjg): This does not cope with a big-endian target
709 value = struct.unpack('<I', word)[0]
710 if found:
711 return value - start
712 if value == 0x12345678:
713 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800714
715 return None
716
717 def CalcTextBase(self, name, fdt, fname):
718 """Calculate the TEXT_BASE to use for U-Boot.
719
720 Normally this value is in the fdt, so we just read it from there. But as
721 a second check we look at the image itself in case this is different, and
722 switch to that if it is.
723
724 This allows us to flash any U-Boot even if its TEXT_BASE is different.
725 This is particularly useful with upstream U-Boot which uses a different
726 value (which we will move to).
727 """
728 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800729 # The value that comes back from fdt.GetInt is signed, which makes no
730 # sense for an address base. Force it to unsigned.
731 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800732 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100733 text_base_str = '%#x' % text_base if text_base else 'None'
734 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
735 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800736
737 # If they are different, issue a warning and switch over.
738 if text_base and text_base != fdt_text_base:
739 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
740 "fdt value of %x. Using %x" % (text_base, name,
741 fdt_text_base, text_base))
742 fdt_text_base = text_base
743 return fdt_text_base
744
Simon Glass6dcc2f22011-07-28 15:26:49 +1200745 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700746 """Create a boot stub and a signed boot stub.
747
Simon Glass6dcc2f22011-07-28 15:26:49 +1200748 For postload:
749 We add a /config/postload-text-offset entry to the signed bootstub's
750 fdt so that U-Boot can find the postload code.
751
752 The raw (unsigned) bootstub will have a value of -1 for this since we will
753 simply append the postload code to the bootstub and it can find it there.
754 This will be used for RW A/B firmware.
755
756 For the signed case this value will specify where in the flash to find
757 the postload code. This will be used for RO firmware.
758
Simon Glass89b86b82011-07-17 23:49:49 -0700759 Args:
760 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800761 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200762 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700763
764 Returns:
765 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200766 Full path to bootstub (uboot + fdt(-1) + postload).
767 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700768
769 Raises:
770 CmdError if a command fails.
771 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200772 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800773 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700774 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200775
776 # Make a copy of the fdt for the bootstub
777 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700778 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700779 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200780
Simon Glass89b86b82011-07-17 23:49:49 -0700781 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700782 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
783 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700784 self._tools.OutputSize('Combined binary', bootstub)
785
Simon Glasse13ee2c2011-07-28 08:12:28 +1200786 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700787 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700788 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200789 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200790
791 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
792 data = self._tools.ReadFile(signed)
793
794 if postload:
795 # We must add postload to the bootstub since A and B will need to
796 # be able to find it without the /config/postload-text-offset mechanism.
797 bs_data = self._tools.ReadFile(bootstub)
798 bs_data += self._tools.ReadFile(postload)
799 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
800 self._tools.WriteFile(bootstub, bs_data)
801 self._tools.OutputSize('Combined binary with postload', bootstub)
802
803 # Now that we know the file size, adjust the fdt and re-sign
804 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800805 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200806 fdt_data = self._tools.ReadFile(fdt.fname)
807 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
808 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
809 postload_bootstub, text_base)
810 if len(data) != os.path.getsize(signed):
811 raise CmdError('Signed file size changed from %d to %d after updating '
812 'fdt' % (len(data), os.path.getsize(signed)))
813
814 # Re-read the signed image, and add the post-load binary.
815 data = self._tools.ReadFile(signed)
816 data += self._tools.ReadFile(postload)
817 self._tools.OutputSize('Post-load binary', postload)
818
819 self._tools.WriteFile(signed_postload, data)
820 self._tools.OutputSize('Final bootstub with postload', signed_postload)
821
822 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700823
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700824 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700825 """Create a coreboot boot stub.
826
827 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700828 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700829
830 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100831 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700832 """
833 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700834 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100835
836 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700837 return bootstub
838
Simon Glass7e199222012-03-13 15:51:18 -0700839
Simon Glass89b86b82011-07-17 23:49:49 -0700840 def _PackOutput(self, msg):
841 """Helper function to write output from PackFirmware (verbose level 2).
842
843 This is passed to PackFirmware for it to use to write output.
844
845 Args:
846 msg: Message to display.
847 """
848 self._out.Notice(msg)
849
Simon Glass439fe7a2012-03-09 16:19:34 -0800850 def _BuildBlob(self, pack, fdt, blob_type):
851 """Build the blob data for a particular blob type.
852
853 Args:
854 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.
Simon Glass439fe7a2012-03-09 16:19:34 -0800860 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700861 # stupid pylint insists that sha256 is not in hashlib.
862 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800863 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700864 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800865 pack.AddProperty('coreboot', coreboot)
866 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700867 elif blob_type == 'legacy':
868 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800869 elif blob_type == 'signed':
870 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
871 self.postload_fname)
872 pack.AddProperty('bootstub', bootstub)
873 pack.AddProperty('signed', signed)
874 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700875 elif blob_type == 'exynos-bl1':
876 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700877
878 # TODO(sjg@chromium.org): Deprecate ecbin
879 elif blob_type in ['ecrw', 'ecbin']:
880 pack.AddProperty('ecrw', self.ecrw_fname)
881 pack.AddProperty('ecbin', self.ecrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800882 elif blob_type == 'ecrwhash':
883 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
884 ecrw = self._tools.ReadFile(self.ecrw_fname)
885 hasher = hashlib.sha256()
886 hasher.update(ecrw)
887 self._tools.WriteFile(ec_hash_file, hasher.digest())
888 pack.AddProperty(blob_type, ec_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700889 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700890 # crosbug.com/p/13143
891 # We cannot have an fmap in the EC image since there can be only one,
892 # which is the main fmap describing the whole image.
893 # Ultimately the EC will not have an fmap, since with software sync
894 # there is no flashrom involvement in updating the EC flash, and thus
895 # no need for the fmap.
896 # For now, mangle the fmap name to avoid problems.
897 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
898 data = self._tools.ReadFile(self.ecro_fname)
899 data = re.sub('__FMAP__', '__fMAP__', data)
900 self._tools.WriteFile(updated_ecro, data)
901 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600902 elif blob_type.startswith('exynos-bl2'):
903 # We need to configure this per node, so do it later
904 pass
Simon Glass439fe7a2012-03-09 16:19:34 -0800905 elif pack.GetProperty(blob_type):
906 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800907 elif blob_type in self.blobs:
908 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800909 else:
910 raise CmdError("Unknown blob type '%s' required in flash map" %
911 blob_type)
912
Simon Glass290a1802011-07-17 13:54:32 -0700913 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700914 """Create a full firmware image, along with various by-products.
915
916 This uses the provided u-boot.bin, fdt and bct to create a firmware
917 image containing all the required parts. If the GBB is not supplied
918 then this will just return a signed U-Boot as the image.
919
920 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +1200921 gbb: Full path to the GBB file, or empty if a GBB is not required.
922 fdt: Fdt object containing required information.
923
924 Returns:
925 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700926 """
Simon Glass02d124a2012-03-02 14:47:20 -0800927 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700928
Simon Glass439fe7a2012-03-09 16:19:34 -0800929 pack = PackFirmware(self._tools, self._out)
Vadim Bendebury238f6442013-03-27 11:23:25 -0700930 # Get the flashmap so we know what to build. For board variants use the
931 # main board name as the key (drop the _<variant> suffix).
Simon Glass81ed0792013-07-20 17:36:24 -0600932 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
Simon Glassb8c6d952012-12-01 06:14:35 -0800933 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700934 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
935 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -0600936 if self._force_efs:
937 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassb8c6d952012-12-01 06:14:35 -0800938
Simon Glass4f318912013-07-20 16:13:06 -0600939 if not fdt.GetProp('/flash', 'reg', ''):
940 fdt.InsertNodes(default_flashmap)
941
Simon Glass81ed0792013-07-20 17:36:24 -0600942 # Insert default values for any essential properties that are missing.
943 # This should only happen for upstream U-Boot, until our changes are
944 # upstreamed.
945 if not fdt.GetProp('/iram', 'reg', ''):
946 self._out.Warning('Cannot find /iram, using default')
947 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
948
949 if not fdt.GetProp('/memory', 'reg', ''):
950 self._out.Warning('Cannot find /memory, using default')
951 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
952
953 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
954 self._out.Warning('Missing properties in /config, using defaults')
955 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
956
Simon Glass4f318912013-07-20 16:13:06 -0600957 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800958
959 # Get all our blobs ready
960 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800961 if self.skeleton_fname:
962 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700963 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700964
Simon Glassde9c8072012-07-02 22:29:02 -0700965 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
966 if self.kernel_fname:
967 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
968
Simon Glass439fe7a2012-03-09 16:19:34 -0800969 pack.AddProperty('gbb', self.uboot_fname)
Simon Glass9d088d92012-07-16 16:27:11 +0100970 blob_list = pack.GetBlobList()
971 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700972 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800973 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -0700974
Simon Glass7306b902012-12-17 15:06:21 -0800975 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700976 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700977 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +0800978 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -0800979 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +0800980 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700981 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800982 pack.AddProperty('fwid', fwid)
983 pack.AddProperty('gbb', gbb)
984 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700985
Simon Glass0a047bc2013-07-19 15:44:43 -0600986 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -0600987 todo = pack.GetMissingBlobs()
988 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -0600989 if blob.key.startswith('exynos-bl2'):
990 bl2 = ExynosBl2(self._tools, self._out)
991 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
992 self.exynos_bl2))
993
Simon Glassc90cf582012-03-13 15:40:47 -0700994 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700995
996 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800997 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700998
Simon Glass4c24f662013-07-19 15:53:02 -0600999 # Recalculate the Exynos BL2, since it may have a hash. The call to
1000 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
1001 # need to recalculate the hash.
1002 for blob in todo:
1003 if blob.key.startswith('exynos-bl2'):
1004 bl2 = ExynosBl2(self._tools, self._out)
1005 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
1006 self.exynos_bl2))
1007
Simon Glass6207efe2012-12-17 15:04:36 -08001008 # Make a copy of the fdt for the bootstub
1009 fdt_data = self._tools.ReadFile(fdt.fname)
1010 uboot_data = self._tools.ReadFile(self.uboot_fname)
1011 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
1012 self._tools.WriteFile(uboot_copy, uboot_data)
1013
1014 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1015 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
1016
Simon Glassa10282a2013-01-08 17:06:41 -08001017 # Fix up the coreboot image here, since we can't do this until we have
1018 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +01001019 if 'coreboot' in blob_list:
1020 bootstub = pack.GetProperty('coreboot')
1021 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001022 if self.coreboot_elf:
1023 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1024 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
1025 else:
Simon Glass0a7cf112013-05-21 23:08:21 -07001026 text_base = 0x1110000
1027
1028 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1029 # 1110015: 66 bb 00 01 mov $0x100,%bx
1030 marker = struct.pack('<L', 0x0100bb66)
1031 pos = uboot_data.find(marker)
1032 if pos == -1 or pos > 0x100:
1033 raise ValueError('Cannot find U-Boot cold boot entry point')
1034 entry = text_base + pos
1035 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001036 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1037 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001038 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001039 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1040 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001041 data = self._tools.ReadFile(bootstub)
1042 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1043 self._tools.WriteFile(bootstub_copy, data)
Gabe Black3df75252013-02-14 21:32:10 -08001044 self._tools.WriteFile(bootstub, data[-0x100000:])
Simon Glasscbc83552012-07-23 15:26:22 +01001045
Simon Glass208ad952013-02-10 11:16:46 -08001046 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001047 image = os.path.join(self._tools.outdir, 'image.bin')
1048 pack.PackImage(self._tools.outdir, image)
1049 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001050
Simon Glass439fe7a2012-03-09 16:19:34 -08001051 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001052 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001053 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001054
Simon Glassdedda6f2013-02-09 13:44:14 -08001055 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001056 """Select an FDT to control the firmware bundling
1057
Simon Glassdedda6f2013-02-09 13:44:14 -08001058 We make a copy of this which will include any on-the-fly changes we want
1059 to make.
1060
Simon Glass290a1802011-07-17 13:54:32 -07001061 Args:
1062 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001063 use_defaults: True to use a default FDT name if available, and to add
1064 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001065
Simon Glassc0f3dc62011-08-09 14:19:05 -07001066 Returns:
1067 The Fdt object of the original fdt file, which we will not modify.
1068
Simon Glassdedda6f2013-02-09 13:44:14 -08001069 Raises:
1070 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1071 False).
Simon Glass290a1802011-07-17 13:54:32 -07001072 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001073 if use_defaults:
1074 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001075 if not fdt_fname:
1076 raise ValueError('Please provide an FDT filename')
1077 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001078 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001079
1080 # For upstream, select the correct architecture .dtsi manually.
1081 if self._board == 'link' or 'x86' in self._board:
1082 arch_dts = 'coreboot.dtsi'
1083 elif self._board == 'daisy':
1084 arch_dts = 'exynos5250.dtsi'
1085 else:
1086 arch_dts = 'tegra20.dtsi'
1087
1088 fdt.Compile(arch_dts)
Simon Glass290a1802011-07-17 13:54:32 -07001089 self.fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Simon Glass32abe2e2013-07-18 18:00:55 -06001090 return self.fdt
Simon Glass290a1802011-07-17 13:54:32 -07001091
Simon Glassc90cf582012-03-13 15:40:47 -07001092 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001093 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001094
1095 - Checks options, tools, output directory, fdt.
1096 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001097
1098 Args:
Simon Glass56577572011-07-19 11:08:06 +12001099 hardware_id: Hardware ID to use for this board. If None, then the
1100 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001101 output_fname: Output filename for the image. If this is not None, then
1102 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001103 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001104
1105 Returns:
1106 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001107 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001108 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1109 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1110 else:
Simon Glass56577572011-07-19 11:08:06 +12001111 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001112
1113 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001114 image, pack = self._CreateImage(gbb, self.fdt)
1115 if show_map:
1116 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001117 if output_fname:
1118 shutil.copyfile(image, output_fname)
1119 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001120 return image, pack.props