blob: 68c6b50c5930b42f0b2fa154b9e490c7e1234ee4 [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:
637 config_list: List of (node, value) tuples to add to the fdt. For each
638 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 Bendebury507c0012013-06-09 12:49:25 -0700642 Raises:
643 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700644 """
645 if enable_list:
646 for node_name, enabled in enable_list:
647 try:
648 enabled = int(enabled)
649 if enabled not in (0, 1):
650 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700651 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700652 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700653 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700654 self.SetNodeEnabled(node_name, enabled)
655
Simon Glass290a1802011-07-17 13:54:32 -0700656 def AddConfigList(self, config_list, use_int=False):
657 """Add a list of config items to the fdt.
658
659 Normally these values are written to the fdt as strings, but integers
660 are also supported, in which case the values will be converted to integers
661 (if necessary) before being stored.
662
663 Args:
664 config_list: List of (config, value) tuples to add to the fdt. For each
665 tuple:
666 config: The fdt node to write to will be /config/<config>.
667 value: An integer or string value to write.
668 use_int: True to only write integer values.
669
670 Raises:
671 CmdError: if a value is required to be converted to integer but can't be.
672 """
673 if config_list:
674 for config in config_list:
675 value = config[1]
676 if use_int:
677 try:
678 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700679 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700680 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700681 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700682 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800683 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700684 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800685 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700686
Simon Glass7c2d5572011-11-15 14:47:08 -0800687 def DecodeTextBase(self, data):
688 """Look at a U-Boot image and try to decode its TEXT_BASE.
689
690 This works because U-Boot has a header with the value 0x12345678
691 immediately followed by the TEXT_BASE value. We can therefore read this
692 from the image with some certainty. We check only the first 40 words
693 since the header should be within that region.
694
Simon Glass96b50302012-07-20 06:55:28 +0100695 Since upstream Tegra has moved to having a 16KB SPL region at the start,
696 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
697 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
698
Simon Glass7c2d5572011-11-15 14:47:08 -0800699 Args:
700 data: U-Boot binary data
701
702 Returns:
703 Text base (integer) or None if none was found
704 """
705 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100706 for start in (0, 0x4000):
707 for i in range(start, start + 160, 4):
708 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800709
Simon Glass96b50302012-07-20 06:55:28 +0100710 # TODO(sjg): This does not cope with a big-endian target
711 value = struct.unpack('<I', word)[0]
712 if found:
713 return value - start
714 if value == 0x12345678:
715 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800716
717 return None
718
719 def CalcTextBase(self, name, fdt, fname):
720 """Calculate the TEXT_BASE to use for U-Boot.
721
722 Normally this value is in the fdt, so we just read it from there. But as
723 a second check we look at the image itself in case this is different, and
724 switch to that if it is.
725
726 This allows us to flash any U-Boot even if its TEXT_BASE is different.
727 This is particularly useful with upstream U-Boot which uses a different
728 value (which we will move to).
729 """
730 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800731 # The value that comes back from fdt.GetInt is signed, which makes no
732 # sense for an address base. Force it to unsigned.
733 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800734 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100735 text_base_str = '%#x' % text_base if text_base else 'None'
736 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
737 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800738
739 # If they are different, issue a warning and switch over.
740 if text_base and text_base != fdt_text_base:
741 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
742 "fdt value of %x. Using %x" % (text_base, name,
743 fdt_text_base, text_base))
744 fdt_text_base = text_base
745 return fdt_text_base
746
Simon Glass6dcc2f22011-07-28 15:26:49 +1200747 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700748 """Create a boot stub and a signed boot stub.
749
Simon Glass6dcc2f22011-07-28 15:26:49 +1200750 For postload:
751 We add a /config/postload-text-offset entry to the signed bootstub's
752 fdt so that U-Boot can find the postload code.
753
754 The raw (unsigned) bootstub will have a value of -1 for this since we will
755 simply append the postload code to the bootstub and it can find it there.
756 This will be used for RW A/B firmware.
757
758 For the signed case this value will specify where in the flash to find
759 the postload code. This will be used for RO firmware.
760
Simon Glass89b86b82011-07-17 23:49:49 -0700761 Args:
762 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800763 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200764 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700765
766 Returns:
767 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200768 Full path to bootstub (uboot + fdt(-1) + postload).
769 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700770
771 Raises:
772 CmdError if a command fails.
773 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200774 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800775 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700776 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200777
778 # Make a copy of the fdt for the bootstub
779 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700780 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700781 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200782
Simon Glass89b86b82011-07-17 23:49:49 -0700783 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700784 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
785 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700786 self._tools.OutputSize('Combined binary', bootstub)
787
Simon Glasse13ee2c2011-07-28 08:12:28 +1200788 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700789 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700790 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200791 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200792
793 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
794 data = self._tools.ReadFile(signed)
795
796 if postload:
797 # We must add postload to the bootstub since A and B will need to
798 # be able to find it without the /config/postload-text-offset mechanism.
799 bs_data = self._tools.ReadFile(bootstub)
800 bs_data += self._tools.ReadFile(postload)
801 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
802 self._tools.WriteFile(bootstub, bs_data)
803 self._tools.OutputSize('Combined binary with postload', bootstub)
804
805 # Now that we know the file size, adjust the fdt and re-sign
806 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800807 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200808 fdt_data = self._tools.ReadFile(fdt.fname)
809 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
810 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
811 postload_bootstub, text_base)
812 if len(data) != os.path.getsize(signed):
813 raise CmdError('Signed file size changed from %d to %d after updating '
814 'fdt' % (len(data), os.path.getsize(signed)))
815
816 # Re-read the signed image, and add the post-load binary.
817 data = self._tools.ReadFile(signed)
818 data += self._tools.ReadFile(postload)
819 self._tools.OutputSize('Post-load binary', postload)
820
821 self._tools.WriteFile(signed_postload, data)
822 self._tools.OutputSize('Final bootstub with postload', signed_postload)
823
824 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700825
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700826 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700827 """Create a coreboot boot stub.
828
829 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700830 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700831
832 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100833 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700834 """
835 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700836 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100837
838 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700839 return bootstub
840
Simon Glass7e199222012-03-13 15:51:18 -0700841
Simon Glass89b86b82011-07-17 23:49:49 -0700842 def _PackOutput(self, msg):
843 """Helper function to write output from PackFirmware (verbose level 2).
844
845 This is passed to PackFirmware for it to use to write output.
846
847 Args:
848 msg: Message to display.
849 """
850 self._out.Notice(msg)
851
Simon Glass439fe7a2012-03-09 16:19:34 -0800852 def _BuildBlob(self, pack, fdt, blob_type):
853 """Build the blob data for a particular blob type.
854
855 Args:
856 blob_type: The type of blob to create data for. Supported types are:
857 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
858 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700859
860 Raises:
861 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800862 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700863 # stupid pylint insists that sha256 is not in hashlib.
864 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800865 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700866 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800867 pack.AddProperty('coreboot', coreboot)
868 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700869 elif blob_type == 'legacy':
870 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800871 elif blob_type == 'signed':
872 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
873 self.postload_fname)
874 pack.AddProperty('bootstub', bootstub)
875 pack.AddProperty('signed', signed)
876 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700877 elif blob_type == 'exynos-bl1':
878 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700879
880 # TODO(sjg@chromium.org): Deprecate ecbin
881 elif blob_type in ['ecrw', 'ecbin']:
882 pack.AddProperty('ecrw', self.ecrw_fname)
883 pack.AddProperty('ecbin', self.ecrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800884 elif blob_type == 'ecrwhash':
885 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
886 ecrw = self._tools.ReadFile(self.ecrw_fname)
887 hasher = hashlib.sha256()
888 hasher.update(ecrw)
889 self._tools.WriteFile(ec_hash_file, hasher.digest())
890 pack.AddProperty(blob_type, ec_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700891 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700892 # crosbug.com/p/13143
893 # We cannot have an fmap in the EC image since there can be only one,
894 # which is the main fmap describing the whole image.
895 # Ultimately the EC will not have an fmap, since with software sync
896 # there is no flashrom involvement in updating the EC flash, and thus
897 # no need for the fmap.
898 # For now, mangle the fmap name to avoid problems.
899 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
900 data = self._tools.ReadFile(self.ecro_fname)
901 data = re.sub('__FMAP__', '__fMAP__', data)
902 self._tools.WriteFile(updated_ecro, data)
903 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600904 elif blob_type.startswith('exynos-bl2'):
905 # We need to configure this per node, so do it later
906 pass
Simon Glass439fe7a2012-03-09 16:19:34 -0800907 elif pack.GetProperty(blob_type):
908 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800909 elif blob_type in self.blobs:
910 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800911 else:
912 raise CmdError("Unknown blob type '%s' required in flash map" %
913 blob_type)
914
Simon Glass290a1802011-07-17 13:54:32 -0700915 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700916 """Create a full firmware image, along with various by-products.
917
918 This uses the provided u-boot.bin, fdt and bct to create a firmware
919 image containing all the required parts. If the GBB is not supplied
920 then this will just return a signed U-Boot as the image.
921
922 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +1200923 gbb: Full path to the GBB file, or empty if a GBB is not required.
924 fdt: Fdt object containing required information.
925
926 Returns:
927 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700928 """
Simon Glass02d124a2012-03-02 14:47:20 -0800929 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700930
Simon Glass439fe7a2012-03-09 16:19:34 -0800931 pack = PackFirmware(self._tools, self._out)
Simon Glassb8c6d952012-12-01 06:14:35 -0800932 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700933 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
934 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -0600935 if self._force_efs:
936 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassa7e66e22013-07-23 07:21:16 -0600937 pack.use_efs = fdt.GetInt('/chromeos-config', 'early-firmware-selection',
938 0)
Simon Glassb8c6d952012-12-01 06:14:35 -0800939
Simon Glass4f318912013-07-20 16:13:06 -0600940 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800941
942 # Get all our blobs ready
943 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800944 if self.skeleton_fname:
945 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700946 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700947
Simon Glassde9c8072012-07-02 22:29:02 -0700948 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
949 if self.kernel_fname:
950 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
951
Simon Glass439fe7a2012-03-09 16:19:34 -0800952 pack.AddProperty('gbb', self.uboot_fname)
Simon Glass9d088d92012-07-16 16:27:11 +0100953 blob_list = pack.GetBlobList()
954 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700955 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800956 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -0700957
Simon Glass7306b902012-12-17 15:06:21 -0800958 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700959 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700960 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +0800961 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -0800962 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +0800963 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700964 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800965 pack.AddProperty('fwid', fwid)
966 pack.AddProperty('gbb', gbb)
967 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700968
Simon Glass0a047bc2013-07-19 15:44:43 -0600969 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -0600970 todo = pack.GetMissingBlobs()
971 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -0600972 if blob.key.startswith('exynos-bl2'):
973 bl2 = ExynosBl2(self._tools, self._out)
974 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
975 self.exynos_bl2))
976
Simon Glassc90cf582012-03-13 15:40:47 -0700977 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700978
979 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800980 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700981
Simon Glass4c24f662013-07-19 15:53:02 -0600982 # Recalculate the Exynos BL2, since it may have a hash. The call to
983 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
984 # need to recalculate the hash.
985 for blob in todo:
986 if blob.key.startswith('exynos-bl2'):
987 bl2 = ExynosBl2(self._tools, self._out)
988 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
989 self.exynos_bl2))
990
Simon Glass6207efe2012-12-17 15:04:36 -0800991 # Make a copy of the fdt for the bootstub
992 fdt_data = self._tools.ReadFile(fdt.fname)
993 uboot_data = self._tools.ReadFile(self.uboot_fname)
994 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
995 self._tools.WriteFile(uboot_copy, uboot_data)
996
997 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
998 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
999
Simon Glassa10282a2013-01-08 17:06:41 -08001000 # Fix up the coreboot image here, since we can't do this until we have
1001 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +01001002 if 'coreboot' in blob_list:
1003 bootstub = pack.GetProperty('coreboot')
1004 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -08001005 if self.coreboot_elf:
1006 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
1007 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
1008 else:
Simon Glass0a7cf112013-05-21 23:08:21 -07001009 text_base = 0x1110000
1010
1011 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
1012 # 1110015: 66 bb 00 01 mov $0x100,%bx
1013 marker = struct.pack('<L', 0x0100bb66)
1014 pos = uboot_data.find(marker)
1015 if pos == -1 or pos > 0x100:
1016 raise ValueError('Cannot find U-Boot cold boot entry point')
1017 entry = text_base + pos
1018 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -08001019 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
1020 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -07001021 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001022 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1023 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001024 data = self._tools.ReadFile(bootstub)
1025 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1026 self._tools.WriteFile(bootstub_copy, data)
Gabe Black3df75252013-02-14 21:32:10 -08001027 self._tools.WriteFile(bootstub, data[-0x100000:])
Simon Glasscbc83552012-07-23 15:26:22 +01001028
Simon Glass208ad952013-02-10 11:16:46 -08001029 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001030 image = os.path.join(self._tools.outdir, 'image.bin')
1031 pack.PackImage(self._tools.outdir, image)
1032 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001033
Simon Glass439fe7a2012-03-09 16:19:34 -08001034 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001035 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001036 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001037
Simon Glassdedda6f2013-02-09 13:44:14 -08001038 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001039 """Select an FDT to control the firmware bundling
1040
Simon Glassdedda6f2013-02-09 13:44:14 -08001041 We make a copy of this which will include any on-the-fly changes we want
1042 to make.
1043
Simon Glass290a1802011-07-17 13:54:32 -07001044 Args:
1045 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001046 use_defaults: True to use a default FDT name if available, and to add
1047 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001048
Simon Glassc0f3dc62011-08-09 14:19:05 -07001049 Returns:
1050 The Fdt object of the original fdt file, which we will not modify.
1051
Simon Glassdedda6f2013-02-09 13:44:14 -08001052 Raises:
1053 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1054 False).
Simon Glass290a1802011-07-17 13:54:32 -07001055 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001056 if use_defaults:
1057 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001058 if not fdt_fname:
1059 raise ValueError('Please provide an FDT filename')
1060 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001061 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001062
1063 # For upstream, select the correct architecture .dtsi manually.
1064 if self._board == 'link' or 'x86' in self._board:
1065 arch_dts = 'coreboot.dtsi'
1066 elif self._board == 'daisy':
1067 arch_dts = 'exynos5250.dtsi'
1068 else:
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001069 arch_dts = 'tegra124.dtsi'
Simon Glassc3e42c32012-12-17 15:00:04 -08001070
1071 fdt.Compile(arch_dts)
Simon Glasse53abbc2013-08-21 22:29:55 -06001072 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
1073
1074 # Get the flashmap so we know what to build. For board variants use the
1075 # main board name as the key (drop the _<variant> suffix).
1076 default_flashmap = default_flashmaps.get(self._board.split('_')[0], [])
1077
1078 if not fdt.GetProp('/flash', 'reg', ''):
1079 fdt.InsertNodes(default_flashmap)
1080
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001081 # Only check for /iram and /config nodes for boards that require it.
1082 if self._board in ('daisy', 'peach'):
1083 # Insert default values for any essential properties that are missing.
1084 # This should only happen for upstream U-Boot, until our changes are
1085 # upstreamed.
1086 if not fdt.GetProp('/iram', 'reg', ''):
1087 self._out.Warning('Cannot find /iram, using default')
1088 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/iram'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001089
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001090 # Sadly the pit branch has an invalid /memory node. Work around it
1091 # for now. crosbug.com/p/22184
1092 if (not fdt.GetProp('/memory', 'reg', '') or
1093 fdt.GetIntList('/memory', 'reg')[0] == 0):
1094 self._out.Warning('Cannot find /memory, using default')
1095 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/memory'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001096
Rhyland Kleinc2df3ca2014-01-06 15:15:34 -05001097 if not fdt.GetProp('/config', 'samsung,bl1-offset', ''):
1098 self._out.Warning('Missing properties in /config, using defaults')
1099 fdt.InsertNodes([i for i in default_flashmap if i['path'] == '/config'])
Simon Glasse53abbc2013-08-21 22:29:55 -06001100
Simon Glass7df773b2013-08-25 18:02:29 -06001101 # Remember our board type.
1102 fdt.PutString('/chromeos-config', 'board', self._board)
1103
Simon Glasse53abbc2013-08-21 22:29:55 -06001104 self.fdt = fdt
1105 return fdt
Simon Glass290a1802011-07-17 13:54:32 -07001106
Simon Glassc90cf582012-03-13 15:40:47 -07001107 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001108 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001109
1110 - Checks options, tools, output directory, fdt.
1111 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001112
1113 Args:
Simon Glass56577572011-07-19 11:08:06 +12001114 hardware_id: Hardware ID to use for this board. If None, then the
1115 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001116 output_fname: Output filename for the image. If this is not None, then
1117 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001118 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001119
1120 Returns:
1121 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001122 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001123 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1124 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1125 else:
Simon Glass56577572011-07-19 11:08:06 +12001126 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001127
1128 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001129 image, pack = self._CreateImage(gbb, self.fdt)
1130 if show_map:
1131 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001132 if output_fname:
1133 shutil.copyfile(image, output_fname)
1134 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001135 return image, pack.props