blob: 6884fb54fdf3cae3f6e843b8bcb20fbe0632691b [file] [log] [blame]
Simon Glass89b86b82011-07-17 23:49:49 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05005"""This module builds a firmware image.
Simon Glass89b86b82011-07-17 23:49:49 -07006
7This modules uses a few rudimentary other libraries for its activity.
8
9Here are the names we give to the various files we deal with. It is important
10to keep these consistent!
11
12 uboot u-boot.bin (with no device tree)
13 fdt the fdt blob
14 bct the BCT file
15 bootstub uboot + fdt
16 signed (uboot + fdt + bct) signed blob
17"""
18
Simon Glassceff3ff2012-04-04 11:23:45 -070019import glob
Gabe Blackcdbdfe12013-02-06 05:37:52 -080020import hashlib
Simon Glass89b86b82011-07-17 23:49:49 -070021import os
22import re
23
Simon Glass89b86b82011-07-17 23:49:49 -070024from fdt import Fdt
25from pack_firmware import PackFirmware
26import shutil
Simon Glass7c2d5572011-11-15 14:47:08 -080027import struct
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 = {
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -050064 'nyan' : [
Simon Glass76958702012-11-08 13:07:53 -080065 {
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",
Simon Glassa7e66e22013-07-23 07:21:16 -0600108 'payload' : '/flash/ro-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -0800109 'required' : True,
110 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600111 'path' : '/flash/ro-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -0800112 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600113 'reg' : [0x6000, 0x9a000],
Simon Glass0c54ba52012-11-06 12:36:43 -0800114 'read-only' : True,
115 'type' : "blob boot,dtb",
116 'required' : True,
117 }
Simon Glass76958702012-11-08 13:07:53 -0800118 ],
119 'link' : [
120 {
Simon Glass4f318912013-07-20 16:13:06 -0600121 'path' : '/flash',
122 'reg' : [0, 0x800000],
123 }, {
124 'path' : '/flash/si-all',
Simon Glass76958702012-11-08 13:07:53 -0800125 'label' : 'si-all',
Simon Glass4f318912013-07-20 16:13:06 -0600126 'reg' : [0x00000000, 0x00200000],
Simon Glass76958702012-11-08 13:07:53 -0800127 'type' : 'ifd',
128 'required' : True,
129 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600130 'path' : '/flash/ro-boot',
Simon Glass76958702012-11-08 13:07:53 -0800131 'label' : 'boot-stub',
Simon Glass4f318912013-07-20 16:13:06 -0600132 'reg' : [0x00700000, 0x00100000],
Simon Glass76958702012-11-08 13:07:53 -0800133 'read-only' : True,
134 'type' : 'blob coreboot',
135 'required' : True,
136 }
Simon Glassf2534222013-03-20 15:42:02 -0700137 ],
138 'peach' : [
139 {
Simon Glass4f318912013-07-20 16:13:06 -0600140 'path' : '/flash',
141 'reg' : [0, 0x400000],
142 }, {
Simon Glass81ed0792013-07-20 17:36:24 -0600143 'path' : '/memory',
144 'reg' : [0x20000000, 0x80000000], # Assume 2GB of RAM
145 }, {
146 'path' : '/iram',
147 'reg' : [0x02020000, 384 << 10],
148 }, {
149 'path' : '/config',
150 'samsung,bl1-offset' : 0x2400,
151 'samsung,bl2-offset' : 0x4400,
152 'u-boot-memory' : '/memory',
153 'u-boot-offset' : [0x3e00000, 0x100000],
154 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600155 'path' : '/flash/pre-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700156 'label' : "bl1 pre-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600157 'reg' : [0, 0x2000],
Simon Glassf2534222013-03-20 15:42:02 -0700158 'read-only' : True,
159 'filename' : "e5420.nbl1.bin",
160 'type' : "blob exynos-bl1",
161 'required' : True,
162 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600163 'path' : '/flash/spl',
Simon Glassf2534222013-03-20 15:42:02 -0700164 'label' : "bl2 spl",
Simon Glass4f318912013-07-20 16:13:06 -0600165 'reg' : [0x2000, 0x8000],
Simon Glassf2534222013-03-20 15:42:02 -0700166 'read-only' : True,
167 'filename' : "bl2.bin",
168 'type' : "blob exynos-bl2 boot,dtb",
Simon Glassa7e66e22013-07-23 07:21:16 -0600169 'payload' : '/flash/ro-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700170 'required' : True,
171 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600172 'path' : '/flash/ro-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700173 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600174 'reg' : [0xa000, 0x9a000],
Simon Glassf2534222013-03-20 15:42:02 -0700175 'read-only' : True,
176 'type' : "blob boot,dtb",
177 'required' : True,
178 }
179 ],
Simon Glass0c54ba52012-11-06 12:36:43 -0800180}
181
182
Simon Glass4a887b12012-10-23 16:29:03 -0700183# Build GBB flags.
184# (src/platform/vboot_reference/firmware/include/gbb_header.h)
185gbb_flag_properties = {
186 'dev-screen-short-delay': 0x00000001,
187 'load-option-roms': 0x00000002,
188 'enable-alternate-os': 0x00000004,
189 'force-dev-switch-on': 0x00000008,
190 'force-dev-boot-usb': 0x00000010,
191 'disable-fw-rollback-check': 0x00000020,
192 'enter-triggers-tonorm': 0x00000040,
193 'force-dev-boot-legacy': 0x00000080,
194}
195
Simon Glass49b026b2013-04-26 16:38:42 -0700196# Maps board name to Exynos product number
197type_to_model = {
198 'peach' : '5420',
199 'daisy' : '5250'
200}
201
Simon Glass5076a7f2012-10-23 16:31:54 -0700202def ListGoogleBinaryBlockFlags():
203 """Print out a list of GBB flags."""
204 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
205 for name, value in gbb_flag_properties.iteritems():
206 print ' %-30s %02x' % (name, value)
207
Simon Glass89b86b82011-07-17 23:49:49 -0700208class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -0700209 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -0700210
Simon Glass290a1802011-07-17 13:54:32 -0700211 Sequence of events:
212 bundle = Bundle(tools.Tools(), cros_output.Output())
213 bundle.SetDirs(...)
214 bundle.SetFiles(...)
215 bundle.SetOptions(...)
216 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -0700217 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -0700218 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -0700219
Simon Glass290a1802011-07-17 13:54:32 -0700220 Public properties:
221 fdt: The fdt object that we use for building our image. This wil be the
222 one specified by the user, except that we might add config options
223 to it. This is set up by SelectFdt() which must be called before
224 bundling starts.
225 uboot_fname: Full filename of the U-Boot binary we use.
226 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700227 spl_source: Source device to load U-Boot from, in SPL:
228 straps: Select device according to CPU strap pins
229 spi: Boot from SPI
230 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700231
232 Private attributes:
233 _small: True to create a 'small' signed U-Boot, False to produce a
234 full image. The small U-Boot is enough to boot but will not have
235 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700236 """
Simon Glass89b86b82011-07-17 23:49:49 -0700237
Simon Glass290a1802011-07-17 13:54:32 -0700238 def __init__(self, tools, output):
239 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700240
Simon Glass290a1802011-07-17 13:54:32 -0700241 Args:
242 tools: A tools.Tools object to use for external tools.
243 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700244 """
Simon Glass290a1802011-07-17 13:54:32 -0700245 self._tools = tools
246 self._out = output
247
248 # Set up the things we need to know in order to operate.
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500249 self._board = None # Board name, e.g. nyan.
Simon Glass290a1802011-07-17 13:54:32 -0700250 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700251 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600252 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700253 self._gbb_flags = None
254 self._keydir = None
255 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700256 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700257 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800258 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700259 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700260 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700261 self.ecro_fname = None # Filename of EC read-only file
262 self.ecrw_fname = None # Filename of EC file
Simon Glass7e199222012-03-13 15:51:18 -0700263 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
264 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700265 self.fdt = None # Our Fdt object.
266 self.kernel_fname = None
267 self.postload_fname = None
268 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700269 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700270 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700271
272 def SetDirs(self, keydir):
273 """Set up directories required for Bundle.
274
275 Args:
276 keydir: Directory containing keys to use for signing firmware.
277 """
278 self._keydir = keydir
279
Simon Glass6dcc2f22011-07-28 15:26:49 +1200280 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800281 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700282 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800283 skeleton=None, ecrw=None, ecro=None, kernel=None, blobs=None):
Simon Glass290a1802011-07-17 13:54:32 -0700284 """Set up files required for Bundle.
285
286 Args:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -0500287 board: The name of the board to target (e.g. nyan).
Simon Glass290a1802011-07-17 13:54:32 -0700288 uboot: The filename of the u-boot.bin image to use.
289 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800290 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800291 coreboot: The filename of the coreboot image to use (on x86).
292 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200293 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700294 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700295 exynos_bl1: The filename of the exynos BL1 file
296 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
297 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700298 ecrw: The filename of the EC (Embedded Controller) read-write file.
299 ecro: The filename of the EC (Embedded Controller) read-only file.
Simon Glassde9c8072012-07-02 22:29:02 -0700300 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800301 blobs: List of (type, filename) of arbitrary blobs.
Simon Glass290a1802011-07-17 13:54:32 -0700302 """
303 self._board = board
304 self.uboot_fname = uboot
305 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800306 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700307 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800308 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200309 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700310 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700311 self.exynos_bl1 = exynos_bl1
312 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700313 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700314 self.ecrw_fname = ecrw
315 self.ecro_fname = ecro
Simon Glassde9c8072012-07-02 22:29:02 -0700316 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800317 self.blobs = dict(blobs or ())
Simon Glass290a1802011-07-17 13:54:32 -0700318
Simon Glass00d027e2013-07-20 14:51:12 -0600319 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700320 """Set up options supported by Bundle.
321
322 Args:
323 small: Only create a signed U-Boot - don't produce the full packed
324 firmware image. This is useful for devs who want to replace just the
325 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700326 gbb_flags: Specification for string containing adjustments to make.
327 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600328 force_efs: Force firmware to use 'early firmware selection' feature,
329 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700330 """
331 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700332 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700333 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600334 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700335
Simon Glass22f39fb2013-02-09 13:44:14 -0800336 def _GetBuildRoot(self):
337 """Get the path to this board's 'firmware' directory.
338
339 Returns:
340 Path to firmware directory, with ## representing the path to the
341 chroot.
342 """
Simon Glass290a1802011-07-17 13:54:32 -0700343 if not self._board:
344 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800345 return os.path.join('##', 'build', self._board, 'firmware')
346
347 def _CheckFdtFilename(self, fname):
348 """Check provided FDT filename and return the correct name if needed.
349
350 Where the filename lacks a path, add a default path for this board.
351 Where no FDT filename is provided, select a default one for this board.
352
353 Args:
354 fname: Proposed FDT filename.
355
356 Returns:
357 Selected FDT filename, after validation.
358 """
359 build_root = self._GetBuildRoot()
Julius Wernerb4b14392013-08-09 14:41:40 -0700360 dir_name = os.path.join(build_root, 'dtb')
Simon Glass22f39fb2013-02-09 13:44:14 -0800361 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700362 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700363 base_name = re.sub('_', '-', self._board)
364
365 # In case the name exists with a prefix or suffix, find it.
Julius Wernerb4b14392013-08-09 14:41:40 -0700366 wildcard = os.path.join(dir_name, '*%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700367 found_list = glob.glob(self._tools.Filename(wildcard))
368 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800369 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700370 else:
371 # We didn't find anything definite, so set up our expected name.
Julius Wernerb4b14392013-08-09 14:41:40 -0700372 fname = os.path.join(dir_name, '%s.dtb' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700373
Simon Glass881964d2012-04-04 11:34:09 -0700374 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800375 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700376 if not ext and not os.path.dirname(root):
Julius Wernerb4b14392013-08-09 14:41:40 -0700377 fname = os.path.join(dir_name, '%s.dtb' % root)
Simon Glass22f39fb2013-02-09 13:44:14 -0800378 return fname
379
380 def CheckOptions(self):
381 """Check provided options and select defaults."""
382 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700383
Simon Glass49b026b2013-04-26 16:38:42 -0700384 board_type = self._board.split('_')[0]
385 model = type_to_model.get(board_type)
386
Simon Glass290a1802011-07-17 13:54:32 -0700387 if not self.uboot_fname:
388 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
389 if not self.bct_fname:
390 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700391 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700392 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700393 if model:
394 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700395 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700396 if not self.exynos_bl2:
Julius Wernerb12c0052013-08-14 13:57:04 -0700397 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl.wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700398 if not self.coreboot_fname:
399 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
400 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700401 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700402 if not self.seabios_fname:
403 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700404 if not self.ecrw_fname:
405 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
406 if not self.ecro_fname:
407 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700408
Simon Glass75759302012-03-15 20:26:53 -0700409 def GetFiles(self):
410 """Get a list of files that we know about.
411
412 This is the opposite of SetFiles except that we may have put in some
413 default names. It returns a dictionary containing the filename for
414 each of a number of pre-defined files.
415
416 Returns:
417 Dictionary, with one entry for each file.
418 """
419 file_list = {
420 'bct' : self.bct_fname,
421 'exynos-bl1' : self.exynos_bl1,
422 'exynos-bl2' : self.exynos_bl2,
423 }
424 return file_list
425
Simon Glass4a887b12012-10-23 16:29:03 -0700426 def DecodeGBBFlagsFromFdt(self):
427 """Get Google Binary Block flags from the FDT.
428
429 These should be in the chromeos-config node, like this:
430
431 chromeos-config {
432 gbb-flag-dev-screen-short-delay;
433 gbb-flag-force-dev-switch-on;
434 gbb-flag-force-dev-boot-usb;
435 gbb-flag-disable-fw-rollback-check;
436 };
437
438 Returns:
439 GBB flags value from FDT.
440 """
441 chromeos_config = self.fdt.GetProps("/chromeos-config")
442 gbb_flags = 0
443 for name in chromeos_config:
444 if name.startswith('gbb-flag-'):
445 flag_value = gbb_flag_properties.get(name[9:])
446 if flag_value:
447 gbb_flags |= flag_value
448 self._out.Notice("FDT: Enabling %s." % name)
449 else:
450 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
451 return gbb_flags
452
Simon Glass157c0662012-10-23 13:52:42 -0700453 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
454 """Decode ajustments to the provided GBB flags.
455
456 We support three options:
457
458 hex value: c2
459 defined value: force-dev-boot-usb,load-option-roms
460 adjust default value: -load-option-roms,+force-dev-boot-usb
461
462 The last option starts from the passed-in GBB flags and adds or removes
463 flags.
464
465 Args:
466 gbb_flags: Base (default) FDT flags.
467 adjustments: String containing adjustments to make.
468
469 Returns:
470 Updated FDT flags.
471 """
472 use_base_value = True
473 if adjustments:
474 try:
475 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700476 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700477 pass
478 for flag in adjustments.split(','):
479 oper = None
480 if flag[0] in ['-', '+']:
481 oper = flag[0]
482 flag = flag[1:]
483 value = gbb_flag_properties.get(flag)
484 if not value:
485 raise ValueError("Invalid GBB flag '%s'" % flag)
486 if oper == '+':
487 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800488 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700489 elif oper == '-':
490 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800491 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700492 else:
493 if use_base_value:
494 gbb_flags = 0
495 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800496 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700497 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800498 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700499
500 return gbb_flags
501
Simon Glass56577572011-07-19 11:08:06 +1200502 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700503 """Create a GBB for the image.
504
Simon Glass56577572011-07-19 11:08:06 +1200505 Args:
506 hardware_id: Hardware ID to use for this board. If None, then the
507 default from the Fdt will be used
508
Simon Glass89b86b82011-07-17 23:49:49 -0700509 Returns:
510 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700511 """
Simon Glass56577572011-07-19 11:08:06 +1200512 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800513 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700514 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700515 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700516
Simon Glass4a887b12012-10-23 16:29:03 -0700517 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800518
Simon Glass157c0662012-10-23 13:52:42 -0700519 # Allow command line to override flags
520 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
521
Simon Glass4a887b12012-10-23 16:29:03 -0700522 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700523 self._out.Progress('Creating GBB')
524 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
525 sizes = ['%#x' % size for size in sizes]
526 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700527 keydir = self._tools.Filename(self._keydir)
528 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700529 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200530 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700531 '--rootkey=%s/root_key.vbpubk' % keydir,
532 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700533 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800534 '--flags=%d' % gbb_flags,
Simon Glass89b86b82011-07-17 23:49:49 -0700535 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700536 cwd=odir)
537 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700538
Simon Glasse13ee2c2011-07-28 08:12:28 +1200539 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700540 """Sign an image so that the Tegra SOC will boot it.
541
542 Args:
543 bct: BCT file to use.
544 bootstub: Boot stub (U-Boot + fdt) file to sign.
545 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700546
547 Returns:
548 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700549 """
550 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200551 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700552 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200553 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700554 fd = open(config, 'w')
555 fd.write('Version = 1;\n')
556 fd.write('Redundancy = 1;\n')
557 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700558
559 # TODO(dianders): Right now, we don't have enough space in our flash map
560 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
561 # sure what this does for reliability, but at least things will fit...
562 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
563 if is_nand:
564 fd.write('Bctcopy = 1;\n')
565
Simon Glass89b86b82011-07-17 23:49:49 -0700566 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
567 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700568
Simon Glass89b86b82011-07-17 23:49:49 -0700569 fd.close()
570
571 self._tools.Run('cbootimage', [config, signed])
572 self._tools.OutputSize('BCT', bct)
573 self._tools.OutputSize('Signed image', signed)
574 return signed
575
Doug Anderson86ce5f42011-07-27 10:40:18 -0700576 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700577 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700578
579 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700580 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700581 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700582 """
Simon Glass468d8752012-09-19 16:36:19 -0700583 if bootcmd is not None:
584 if bootcmd == 'none':
585 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800586 self.fdt.PutString('/config', 'bootcmd', bootcmd)
587 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700588 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700589
Simon Glassa4934b72012-05-09 13:35:02 -0700590 def SetNodeEnabled(self, node_name, enabled):
591 """Set whether an node is enabled or disabled.
592
593 This simply sets the 'status' property of a node to "ok", or "disabled".
594
595 The node should either be a full path to the node (like '/uart@10200000')
596 or an alias property.
597
598 Aliases are supported like this:
599
600 aliases {
601 console = "/uart@10200000";
602 };
603
604 pointing to a node:
605
606 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700607 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700608 };
609
610 In this case, this function takes the name of the alias ('console' in
611 this case) and updates the status of the node that is pointed to, to
612 either ok or disabled. If the alias does not exist, a warning is
613 displayed.
614
615 Args:
616 node_name: Name of node (e.g. '/uart@10200000') or alias alias
617 (e.g. 'console') to adjust
618 enabled: True to enable, False to disable
619 """
620 # Look up the alias if this is an alias reference
621 if not node_name.startswith('/'):
622 lookup = self.fdt.GetString('/aliases', node_name, '')
623 if not lookup:
624 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
625 return
626 node_name = lookup
627 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700628 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700629 else:
630 status = 'disabled'
631 self.fdt.PutString(node_name, 'status', status)
632
633 def AddEnableList(self, enable_list):
634 """Process a list of nodes to enable/disable.
635
636 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700637 enable_list: List of (node, value) tuples to add to the fdt. For each
Simon Glassa4934b72012-05-09 13:35:02 -0700638 tuple:
639 node: The fdt node to write to will be <node> or pointed to by
640 /aliases/<node>. We can tell which
641 value: 0 to disable the node, 1 to enable it
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700642
Vadim Bendebury507c0012013-06-09 12:49:25 -0700643 Raises:
644 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700645 """
646 if enable_list:
647 for node_name, enabled in enable_list:
648 try:
649 enabled = int(enabled)
650 if enabled not in (0, 1):
651 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700652 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700653 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700654 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700655 self.SetNodeEnabled(node_name, enabled)
656
Simon Glass290a1802011-07-17 13:54:32 -0700657 def AddConfigList(self, config_list, use_int=False):
658 """Add a list of config items to the fdt.
659
660 Normally these values are written to the fdt as strings, but integers
661 are also supported, in which case the values will be converted to integers
662 (if necessary) before being stored.
663
664 Args:
665 config_list: List of (config, value) tuples to add to the fdt. For each
666 tuple:
667 config: The fdt node to write to will be /config/<config>.
668 value: An integer or string value to write.
669 use_int: True to only write integer values.
670
671 Raises:
672 CmdError: if a value is required to be converted to integer but can't be.
673 """
674 if config_list:
675 for config in config_list:
676 value = config[1]
677 if use_int:
678 try:
679 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700680 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700681 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700682 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700683 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800684 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700685 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800686 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700687
Simon Glass7c2d5572011-11-15 14:47:08 -0800688 def DecodeTextBase(self, data):
689 """Look at a U-Boot image and try to decode its TEXT_BASE.
690
691 This works because U-Boot has a header with the value 0x12345678
692 immediately followed by the TEXT_BASE value. We can therefore read this
693 from the image with some certainty. We check only the first 40 words
694 since the header should be within that region.
695
Simon Glass96b50302012-07-20 06:55:28 +0100696 Since upstream Tegra has moved to having a 16KB SPL region at the start,
697 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
698 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
699
Simon Glass7c2d5572011-11-15 14:47:08 -0800700 Args:
701 data: U-Boot binary data
702
703 Returns:
704 Text base (integer) or None if none was found
705 """
706 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100707 for start in (0, 0x4000):
708 for i in range(start, start + 160, 4):
709 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800710
Simon Glass96b50302012-07-20 06:55:28 +0100711 # TODO(sjg): This does not cope with a big-endian target
712 value = struct.unpack('<I', word)[0]
713 if found:
714 return value - start
715 if value == 0x12345678:
716 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800717
718 return None
719
720 def CalcTextBase(self, name, fdt, fname):
721 """Calculate the TEXT_BASE to use for U-Boot.
722
723 Normally this value is in the fdt, so we just read it from there. But as
724 a second check we look at the image itself in case this is different, and
725 switch to that if it is.
726
727 This allows us to flash any U-Boot even if its TEXT_BASE is different.
728 This is particularly useful with upstream U-Boot which uses a different
729 value (which we will move to).
730 """
731 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800732 # The value that comes back from fdt.GetInt is signed, which makes no
733 # sense for an address base. Force it to unsigned.
734 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800735 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100736 text_base_str = '%#x' % text_base if text_base else 'None'
737 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
738 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800739
740 # If they are different, issue a warning and switch over.
741 if text_base and text_base != fdt_text_base:
742 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
743 "fdt value of %x. Using %x" % (text_base, name,
744 fdt_text_base, text_base))
745 fdt_text_base = text_base
746 return fdt_text_base
747
Simon Glass6dcc2f22011-07-28 15:26:49 +1200748 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700749 """Create a boot stub and a signed boot stub.
750
Simon Glass6dcc2f22011-07-28 15:26:49 +1200751 For postload:
752 We add a /config/postload-text-offset entry to the signed bootstub's
753 fdt so that U-Boot can find the postload code.
754
755 The raw (unsigned) bootstub will have a value of -1 for this since we will
756 simply append the postload code to the bootstub and it can find it there.
757 This will be used for RW A/B firmware.
758
759 For the signed case this value will specify where in the flash to find
760 the postload code. This will be used for RO firmware.
761
Simon Glass89b86b82011-07-17 23:49:49 -0700762 Args:
763 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800764 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200765 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700766
767 Returns:
768 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200769 Full path to bootstub (uboot + fdt(-1) + postload).
770 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700771
772 Raises:
773 CmdError if a command fails.
774 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200775 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800776 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700777 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200778
779 # Make a copy of the fdt for the bootstub
780 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700781 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700782 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200783
Simon Glass89b86b82011-07-17 23:49:49 -0700784 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700785 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
786 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700787 self._tools.OutputSize('Combined binary', bootstub)
788
Simon Glasse13ee2c2011-07-28 08:12:28 +1200789 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700790 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700791 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200792 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200793
794 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
795 data = self._tools.ReadFile(signed)
796
797 if postload:
798 # We must add postload to the bootstub since A and B will need to
799 # be able to find it without the /config/postload-text-offset mechanism.
800 bs_data = self._tools.ReadFile(bootstub)
801 bs_data += self._tools.ReadFile(postload)
802 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
803 self._tools.WriteFile(bootstub, bs_data)
804 self._tools.OutputSize('Combined binary with postload', bootstub)
805
806 # Now that we know the file size, adjust the fdt and re-sign
807 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800808 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200809 fdt_data = self._tools.ReadFile(fdt.fname)
810 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
811 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
812 postload_bootstub, text_base)
813 if len(data) != os.path.getsize(signed):
814 raise CmdError('Signed file size changed from %d to %d after updating '
815 'fdt' % (len(data), os.path.getsize(signed)))
816
817 # Re-read the signed image, and add the post-load binary.
818 data = self._tools.ReadFile(signed)
819 data += self._tools.ReadFile(postload)
820 self._tools.OutputSize('Post-load binary', postload)
821
822 self._tools.WriteFile(signed_postload, data)
823 self._tools.OutputSize('Final bootstub with postload', signed_postload)
824
825 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700826
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700827 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700828 """Create a coreboot boot stub.
829
830 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700831 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700832
833 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100834 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700835 """
836 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700837 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100838
839 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700840 return bootstub
841
Simon Glass7e199222012-03-13 15:51:18 -0700842
Simon Glass89b86b82011-07-17 23:49:49 -0700843 def _PackOutput(self, msg):
844 """Helper function to write output from PackFirmware (verbose level 2).
845
846 This is passed to PackFirmware for it to use to write output.
847
848 Args:
849 msg: Message to display.
850 """
851 self._out.Notice(msg)
852
Simon Glass439fe7a2012-03-09 16:19:34 -0800853 def _BuildBlob(self, pack, fdt, blob_type):
854 """Build the blob data for a particular blob type.
855
856 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700857 pack: a PackFirmware object describing the firmware image to build.
858 fdt: an fdt object including image layout information
Simon Glass439fe7a2012-03-09 16:19:34 -0800859 blob_type: The type of blob to create data for. Supported types are:
860 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
861 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700862
863 Raises:
864 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800865 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700866 # stupid pylint insists that sha256 is not in hashlib.
867 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800868 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700869 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800870 pack.AddProperty('coreboot', coreboot)
871 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700872 elif blob_type == 'legacy':
873 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800874 elif blob_type == 'signed':
875 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
876 self.postload_fname)
877 pack.AddProperty('bootstub', bootstub)
878 pack.AddProperty('signed', signed)
879 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700880 elif blob_type == 'exynos-bl1':
881 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700882
883 # TODO(sjg@chromium.org): Deprecate ecbin
884 elif blob_type in ['ecrw', 'ecbin']:
885 pack.AddProperty('ecrw', self.ecrw_fname)
886 pack.AddProperty('ecbin', self.ecrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800887 elif blob_type == 'ecrwhash':
888 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
889 ecrw = self._tools.ReadFile(self.ecrw_fname)
890 hasher = hashlib.sha256()
891 hasher.update(ecrw)
892 self._tools.WriteFile(ec_hash_file, hasher.digest())
893 pack.AddProperty(blob_type, ec_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700894 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700895 # crosbug.com/p/13143
896 # We cannot have an fmap in the EC image since there can be only one,
897 # which is the main fmap describing the whole image.
898 # Ultimately the EC will not have an fmap, since with software sync
899 # there is no flashrom involvement in updating the EC flash, and thus
900 # no need for the fmap.
901 # For now, mangle the fmap name to avoid problems.
902 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
903 data = self._tools.ReadFile(self.ecro_fname)
904 data = re.sub('__FMAP__', '__fMAP__', data)
905 self._tools.WriteFile(updated_ecro, data)
906 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600907 elif blob_type.startswith('exynos-bl2'):
908 # We need to configure this per node, so do it later
909 pass
Simon Glass439fe7a2012-03-09 16:19:34 -0800910 elif pack.GetProperty(blob_type):
911 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800912 elif blob_type in self.blobs:
913 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800914 else:
915 raise CmdError("Unknown blob type '%s' required in flash map" %
916 blob_type)
917
Simon Glass290a1802011-07-17 13:54:32 -0700918 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700919 """Create a full firmware image, along with various by-products.
920
921 This uses the provided u-boot.bin, fdt and bct to create a firmware
922 image containing all the required parts. If the GBB is not supplied
923 then this will just return a signed U-Boot as the image.
924
925 Args:
Vadim Bendebury7dac18c2014-05-06 14:13:35 -0700926 gbb: a string, full path to the GBB file, or empty if a GBB is not
927 required.
928 fdt: an fdt object containing required information.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200929
930 Returns:
931 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700932 """
Simon Glass02d124a2012-03-02 14:47:20 -0800933 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700934
Simon Glass439fe7a2012-03-09 16:19:34 -0800935 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -0800936 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700937 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
938 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -0600939 if self._force_efs:
940 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -0600941 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
942 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800943
Simon Glass4f318912013-07-20 16:13:06 -0600944 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800945
946 # Get all our blobs ready
947 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800948 if self.skeleton_fname:
949 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700950 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700951
Simon Glassde9c8072012-07-02 22:29:02 -0700952 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
953 if self.kernel_fname:
954 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
955
Simon Glass439fe7a2012-03-09 16:19:34 -0800956 pack.AddProperty('gbb', self.uboot_fname)
Simon Glass9d088d92012-07-16 16:27:11 +0100957 blob_list = pack.GetBlobList()
958 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700959 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800960 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -0700961
Simon Glass7306b902012-12-17 15:06:21 -0800962 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700963 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700964 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +0800965 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -0800966 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +0800967 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700968 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800969 pack.AddProperty('fwid', fwid)
970 pack.AddProperty('gbb', gbb)
971 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700972
Simon Glass0a047bc2013-07-19 15:44:43 -0600973 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -0600974 todo = pack.GetMissingBlobs()
975 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -0600976 if blob.key.startswith('exynos-bl2'):
977 bl2 = ExynosBl2(self._tools, self._out)
978 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
979 self.exynos_bl2))
980
Simon Glassc90cf582012-03-13 15:40:47 -0700981 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700982
983 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800984 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700985
Simon Glass4c24f662013-07-19 15:53:02 -0600986 # Recalculate the Exynos BL2, since it may have a hash. The call to
987 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
988 # need to recalculate the hash.
989 for blob in todo:
990 if blob.key.startswith('exynos-bl2'):
991 bl2 = ExynosBl2(self._tools, self._out)
992 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
993 self.exynos_bl2))
994
Simon Glass6207efe2012-12-17 15:04:36 -0800995 # Make a copy of the fdt for the bootstub
996 fdt_data = self._tools.ReadFile(fdt.fname)
997 uboot_data = self._tools.ReadFile(self.uboot_fname)
998 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
999 self._tools.WriteFile(uboot_copy, uboot_data)
1000
1001 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
1002 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
1003
Simon Glassa10282a2013-01-08 17:06:41 -08001004 # Fix up the coreboot image here, since we can't do this until we have
1005 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +01001006 if 'coreboot' in blob_list:
1007 bootstub = pack.GetProperty('coreboot')
1008 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001009 if self.coreboot_elf:
1010 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1011 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
1012 else:
Simon Glass0a7cf112013-05-21 23:08:21 -07001013 text_base = 0x1110000
1014
1015 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1016 # 1110015: 66 bb 00 01 mov $0x100,%bx
1017 marker = struct.pack('<L', 0x0100bb66)
1018 pos = uboot_data.find(marker)
1019 if pos == -1 or pos > 0x100:
1020 raise ValueError('Cannot find U-Boot cold boot entry point')
1021 entry = text_base + pos
1022 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001023 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1024 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001025 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001026 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1027 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001028 data = self._tools.ReadFile(bootstub)
1029 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1030 self._tools.WriteFile(bootstub_copy, data)
Gabe Black3df75252013-02-14 21:32:10 -08001031 self._tools.WriteFile(bootstub, data[-0x100000:])
Simon Glasscbc83552012-07-23 15:26:22 +01001032
Simon Glass208ad952013-02-10 11:16:46 -08001033 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001034 image = os.path.join(self._tools.outdir, 'image.bin')
1035 pack.PackImage(self._tools.outdir, image)
1036 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001037
Simon Glass439fe7a2012-03-09 16:19:34 -08001038 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001039 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001040 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001041
Simon Glassdedda6f2013-02-09 13:44:14 -08001042 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001043 """Select an FDT to control the firmware bundling
1044
Simon Glassdedda6f2013-02-09 13:44:14 -08001045 We make a copy of this which will include any on-the-fly changes we want
1046 to make.
1047
Simon Glass290a1802011-07-17 13:54:32 -07001048 Args:
1049 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001050 use_defaults: True to use a default FDT name if available, and to add
1051 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001052
Simon Glassc0f3dc62011-08-09 14:19:05 -07001053 Returns:
1054 The Fdt object of the original fdt file, which we will not modify.
1055
Simon Glassdedda6f2013-02-09 13:44:14 -08001056 Raises:
1057 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1058 False).
Simon Glass290a1802011-07-17 13:54:32 -07001059 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001060 if use_defaults:
1061 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001062 if not fdt_fname:
1063 raise ValueError('Please provide an FDT filename')
1064 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001065 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001066
1067 # For upstream, select the correct architecture .dtsi manually.
1068 if self._board == 'link' or 'x86' in self._board:
1069 arch_dts = 'coreboot.dtsi'
1070 elif self._board == 'daisy':
1071 arch_dts = 'exynos5250.dtsi'
1072 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001073 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001074
1075 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001076 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1077
1078 # Get the flashmap so we know what to build. For board variants use the
1079 # main board name as the key (drop the _<variant> suffix).
1080 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1081
1082 if not fdt.GetProp('/flash', 'reg', ''):
1083 fdt.InsertNodes(default_flashmap)
1084
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001085 # Only check for /iram and /config nodes for boards that require it.
1086 if self._board in ('daisy', 'peach'):
1087 # Insert default values for any essential properties that are missing.
1088 # This should only happen for upstream U-Boot, until our changes are
1089 # upstreamed.
1090 if not fdt.GetProp('/iram', 'reg', ''):
1091 self._out.Warning('Cannot find /iram, using default')
1092 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001093
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001094 # Sadly the pit branch has an invalid /memory node. Work around it
1095 # for now. crosbug.com/p/22184
1096 if (not fdt.GetProp('/memory', 'reg', '') or
1097 fdt.GetIntList('/memory', 'reg')[0] == 0):
1098 self._out.Warning('Cannot find /memory, using default')
1099 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001100
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001101 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
1102 self._out.Warning('Missing properties in /config, using defaults')
1103 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001104
Simon Glass7df773b2013-08-25 18:02:29 -06001105 # Remember our board type.
1106 fdt.PutString('/chromeos-config', 'board', self._board)
1107
Simon Glasse53abbc2013-08-21 22:29:55 -06001108 self.fdt = fdt
1109 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001110
Simon Glassc90cf582012-03-13 15:40:47 -07001111 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001112 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001113
1114 - Checks options, tools, output directory, fdt.
1115 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001116
1117 Args:
Simon Glass56577572011-07-19 11:08:06 +12001118 hardware_id: Hardware ID to use for this board. If None, then the
1119 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001120 output_fname: Output filename for the image. If this is not None, then
1121 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001122 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001123
1124 Returns:
1125 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001126 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001127 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1128 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1129 else:
Simon Glass56577572011-07-19 11:08:06 +12001130 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001131
1132 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001133 image, pack = self._CreateImage(gbb, self.fdt)
1134 if show_map:
1135 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001136 if output_fname:
1137 shutil.copyfile(image, output_fname)
1138 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001139 return image, pack.props