blob: cf732044749aa7f64132474bde89e1733f2ce064 [file] [log] [blame]
Simon Glass89b86b82011-07-17 23:49:49 -07001# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""This module builds a firmware image for a tegra-based board.
6
7This modules uses a few rudimentary other libraries for its activity.
8
9Here are the names we give to the various files we deal with. It is important
10to keep these consistent!
11
12 uboot u-boot.bin (with no device tree)
13 fdt the fdt blob
14 bct the BCT file
15 bootstub uboot + fdt
16 signed (uboot + fdt + bct) signed blob
17"""
18
Simon Glassceff3ff2012-04-04 11:23:45 -070019import glob
Gabe Blackcdbdfe12013-02-06 05:37:52 -080020import hashlib
Simon Glass89b86b82011-07-17 23:49:49 -070021import os
22import re
23
Simon Glass89b86b82011-07-17 23:49:49 -070024from fdt import Fdt
25from pack_firmware import PackFirmware
26import shutil
Simon Glass7c2d5572011-11-15 14:47:08 -080027import struct
Simon Glass439fe7a2012-03-09 16:19:34 -080028from tools import CmdError
Vadim Bendeburyb12e3352013-06-08 17:25:19 -070029from exynos import ExynosBl2
Simon Glass89b86b82011-07-17 23:49:49 -070030
31# This data is required by bmpblk_utility. Does it ever change?
32# It was stored with the chromeos-bootimage ebuild, but we want
33# this utility to work outside the chroot.
34yaml_data = '''
35bmpblock: 1.0
36
37images:
38 devmode: DeveloperBmp/DeveloperBmp.bmp
39 recovery: RecoveryBmp/RecoveryBmp.bmp
40 rec_yuck: RecoveryNoOSBmp/RecoveryNoOSBmp.bmp
41 rec_insert: RecoveryMissingOSBmp/RecoveryMissingOSBmp.bmp
42
43screens:
44 dev_en:
45 - [0, 0, devmode]
46 rec_en:
47 - [0, 0, recovery]
48 yuck_en:
49 - [0, 0, rec_yuck]
50 ins_en:
51 - [0, 0, rec_insert]
52
53localizations:
54 - [ dev_en, rec_en, yuck_en, ins_en ]
55'''
56
Simon Glass0c54ba52012-11-06 12:36:43 -080057# Default flash maps for various boards we support.
58# These are used when no fdt is provided (e.g. upstream U-Boot with no
59# fdt. Each is a list of nodes.
Simon Glass4f318912013-07-20 16:13:06 -060060# Note: Use 'reg' instead of 'size' to fully specify the start and end of
61# each area, since there is no guarantee what order the nodes will appear
62# in the fdt, and if they are out of order the image will not boot.
Simon Glass0c54ba52012-11-06 12:36:43 -080063default_flashmaps = {
Simon Glass76958702012-11-08 13:07:53 -080064 'tegra' : [
65 {
Simon Glass4f318912013-07-20 16:13:06 -060066 'path' : '/flash',
67 'reg' : [0, 0x400000],
68 }, {
69 'path' : '/flash/ro-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -080070 'label' : 'boot-stub',
71 'size' : 512 << 10,
72 'read-only' : True,
73 'type' : 'blob signed',
74 'required' : True
75 }
76 ],
77 'daisy' : [
78 {
Simon Glass4f318912013-07-20 16:13:06 -060079 'path' : '/flash',
80 'reg' : [0, 0x400000],
81 }, {
82 'path' : '/flash/pre-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -080083 'label' : "bl1 pre-boot",
Simon Glass4f318912013-07-20 16:13:06 -060084 'reg' : [0, 0x2000],
Simon Glass0c54ba52012-11-06 12:36:43 -080085 'read-only' : True,
86 'filename' : "e5250.nbl1.bin",
87 'type' : "blob exynos-bl1",
88 'required' : True,
89 }, {
Simon Glass4f318912013-07-20 16:13:06 -060090 'path' : '/flash/spl',
Simon Glass0c54ba52012-11-06 12:36:43 -080091 'label' : "bl2 spl",
Simon Glass4f318912013-07-20 16:13:06 -060092 'reg' : [0x2000, 0x4000],
Simon Glass0c54ba52012-11-06 12:36:43 -080093 'read-only' : True,
94 'filename' : "bl2.bin",
95 'type' : "blob exynos-bl2 boot,dtb",
96 'required' : True,
97 }, {
Simon Glass4f318912013-07-20 16:13:06 -060098 'path' : '/flash/ro-boot',
Simon Glass0c54ba52012-11-06 12:36:43 -080099 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600100 'reg' : [0x6000, 0x9a000],
Simon Glass0c54ba52012-11-06 12:36:43 -0800101 'read-only' : True,
102 'type' : "blob boot,dtb",
103 'required' : True,
104 }
Simon Glass76958702012-11-08 13:07:53 -0800105 ],
106 'link' : [
107 {
Simon Glass4f318912013-07-20 16:13:06 -0600108 'path' : '/flash',
109 'reg' : [0, 0x800000],
110 }, {
111 'path' : '/flash/si-all',
Simon Glass76958702012-11-08 13:07:53 -0800112 'label' : 'si-all',
Simon Glass4f318912013-07-20 16:13:06 -0600113 'reg' : [0x00000000, 0x00200000],
Simon Glass76958702012-11-08 13:07:53 -0800114 'type' : 'ifd',
115 'required' : True,
116 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600117 'path' : '/flash/ro-boot',
Simon Glass76958702012-11-08 13:07:53 -0800118 'label' : 'boot-stub',
Simon Glass4f318912013-07-20 16:13:06 -0600119 'reg' : [0x00700000, 0x00100000],
Simon Glass76958702012-11-08 13:07:53 -0800120 'read-only' : True,
121 'type' : 'blob coreboot',
122 'required' : True,
123 }
Simon Glassf2534222013-03-20 15:42:02 -0700124 ],
125 'peach' : [
126 {
Simon Glass4f318912013-07-20 16:13:06 -0600127 'path' : '/flash',
128 'reg' : [0, 0x400000],
129 }, {
130 'path' : '/flash/pre-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700131 'label' : "bl1 pre-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600132 'reg' : [0, 0x2000],
Simon Glassf2534222013-03-20 15:42:02 -0700133 'read-only' : True,
134 'filename' : "e5420.nbl1.bin",
135 'type' : "blob exynos-bl1",
136 'required' : True,
137 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600138 'path' : '/flash/spl',
Simon Glassf2534222013-03-20 15:42:02 -0700139 'label' : "bl2 spl",
Simon Glass4f318912013-07-20 16:13:06 -0600140 'reg' : [0x2000, 0x8000],
Simon Glassf2534222013-03-20 15:42:02 -0700141 'read-only' : True,
142 'filename' : "bl2.bin",
143 'type' : "blob exynos-bl2 boot,dtb",
144 'required' : True,
145 }, {
Simon Glass4f318912013-07-20 16:13:06 -0600146 'path' : '/flash/ro-boot',
Simon Glassf2534222013-03-20 15:42:02 -0700147 'label' : "u-boot",
Simon Glass4f318912013-07-20 16:13:06 -0600148 'reg' : [0xa000, 0x9a000],
Simon Glassf2534222013-03-20 15:42:02 -0700149 'read-only' : True,
150 'type' : "blob boot,dtb",
151 'required' : True,
152 }
153 ],
Simon Glass0c54ba52012-11-06 12:36:43 -0800154}
155
156
Simon Glass4a887b12012-10-23 16:29:03 -0700157# Build GBB flags.
158# (src/platform/vboot_reference/firmware/include/gbb_header.h)
159gbb_flag_properties = {
160 'dev-screen-short-delay': 0x00000001,
161 'load-option-roms': 0x00000002,
162 'enable-alternate-os': 0x00000004,
163 'force-dev-switch-on': 0x00000008,
164 'force-dev-boot-usb': 0x00000010,
165 'disable-fw-rollback-check': 0x00000020,
166 'enter-triggers-tonorm': 0x00000040,
167 'force-dev-boot-legacy': 0x00000080,
168}
169
Simon Glass49b026b2013-04-26 16:38:42 -0700170# Maps board name to Exynos product number
171type_to_model = {
172 'peach' : '5420',
173 'daisy' : '5250'
174}
175
Simon Glass5076a7f2012-10-23 16:31:54 -0700176def ListGoogleBinaryBlockFlags():
177 """Print out a list of GBB flags."""
178 print ' %-30s %s' % ('Available GBB flags:', 'Hex')
179 for name, value in gbb_flag_properties.iteritems():
180 print ' %-30s %02x' % (name, value)
181
Simon Glass89b86b82011-07-17 23:49:49 -0700182class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -0700183 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -0700184
Simon Glass290a1802011-07-17 13:54:32 -0700185 Sequence of events:
186 bundle = Bundle(tools.Tools(), cros_output.Output())
187 bundle.SetDirs(...)
188 bundle.SetFiles(...)
189 bundle.SetOptions(...)
190 bundle.SelectFdt(fdt.Fdt('filename.dtb')
Simon Glassa4934b72012-05-09 13:35:02 -0700191 .. can call bundle.AddConfigList(), AddEnableList() if required
Simon Glass290a1802011-07-17 13:54:32 -0700192 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -0700193
Simon Glass290a1802011-07-17 13:54:32 -0700194 Public properties:
195 fdt: The fdt object that we use for building our image. This wil be the
196 one specified by the user, except that we might add config options
197 to it. This is set up by SelectFdt() which must be called before
198 bundling starts.
199 uboot_fname: Full filename of the U-Boot binary we use.
200 bct_fname: Full filename of the BCT file we use.
Simon Glass559b6612012-05-23 13:28:45 -0700201 spl_source: Source device to load U-Boot from, in SPL:
202 straps: Select device according to CPU strap pins
203 spi: Boot from SPI
204 emmc: Boot from eMMC
Simon Glass23988ae2012-03-23 16:55:22 -0700205
206 Private attributes:
207 _small: True to create a 'small' signed U-Boot, False to produce a
208 full image. The small U-Boot is enough to boot but will not have
209 access to GBB, RW U-Boot, etc.
Simon Glass290a1802011-07-17 13:54:32 -0700210 """
Simon Glass89b86b82011-07-17 23:49:49 -0700211
Simon Glass290a1802011-07-17 13:54:32 -0700212 def __init__(self, tools, output):
213 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -0700214
Simon Glass290a1802011-07-17 13:54:32 -0700215 Args:
216 tools: A tools.Tools object to use for external tools.
217 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -0700218 """
Simon Glass290a1802011-07-17 13:54:32 -0700219 self._tools = tools
220 self._out = output
221
222 # Set up the things we need to know in order to operate.
223 self._board = None # Board name, e.g. tegra2_seaboard.
224 self._fdt_fname = None # Filename of our FDT.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700225 self._force_rw = None
Simon Glass00d027e2013-07-20 14:51:12 -0600226 self._force_efs = None
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700227 self._gbb_flags = None
228 self._keydir = None
229 self._small = False
Simon Glass290a1802011-07-17 13:54:32 -0700230 self.bct_fname = None # Filename of our BCT file.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700231 self.blobs = {} # Table of (type, filename) of arbitrary blobs
Hung-Te Lin5b649382011-08-03 15:01:16 +0800232 self.bmpblk_fname = None # Filename of our Bitmap Block
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700233 self.coreboot_elf = None
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700234 self.coreboot_fname = None # Filename of our coreboot binary.
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700235 self.ecro_fname = None # Filename of EC read-only file
236 self.ecrw_fname = None # Filename of EC file
Simon Glass7e199222012-03-13 15:51:18 -0700237 self.exynos_bl1 = None # Filename of Exynos BL1 (pre-boot)
238 self.exynos_bl2 = None # Filename of Exynos BL2 (SPL)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700239 self.fdt = None # Our Fdt object.
240 self.kernel_fname = None
241 self.postload_fname = None
242 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass07267952012-06-08 12:45:13 -0700243 self.skeleton_fname = None # Filename of Coreboot skeleton file
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700244 self.uboot_fname = None # Filename of our U-Boot binary.
Simon Glass290a1802011-07-17 13:54:32 -0700245
246 def SetDirs(self, keydir):
247 """Set up directories required for Bundle.
248
249 Args:
250 keydir: Directory containing keys to use for signing firmware.
251 """
252 self._keydir = keydir
253
Simon Glass6dcc2f22011-07-28 15:26:49 +1200254 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Simon Glassa10282a2013-01-08 17:06:41 -0800255 coreboot_elf=None,
Simon Glass07267952012-06-08 12:45:13 -0700256 postload=None, seabios=None, exynos_bl1=None, exynos_bl2=None,
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800257 skeleton=None, ecrw=None, ecro=None, kernel=None, blobs=None):
Simon Glass290a1802011-07-17 13:54:32 -0700258 """Set up files required for Bundle.
259
260 Args:
261 board: The name of the board to target (e.g. tegra2_seaboard).
262 uboot: The filename of the u-boot.bin image to use.
263 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800264 bmpblk: The filename of bitmap block file to use.
Simon Glassa10282a2013-01-08 17:06:41 -0800265 coreboot: The filename of the coreboot image to use (on x86).
266 coreboot_elf: If not none, the ELF file to add as a Coreboot payload.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200267 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700268 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass07267952012-06-08 12:45:13 -0700269 exynos_bl1: The filename of the exynos BL1 file
270 exynos_bl2: The filename of the exynos BL2 file (U-Boot spl)
271 skeleton: The filename of the coreboot skeleton file.
Simon Glassbe0bc002012-08-16 12:50:48 -0700272 ecrw: The filename of the EC (Embedded Controller) read-write file.
273 ecro: The filename of the EC (Embedded Controller) read-only file.
Simon Glassde9c8072012-07-02 22:29:02 -0700274 kernel: The filename of the kernel file if any.
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800275 blobs: List of (type, filename) of arbitrary blobs.
Simon Glass290a1802011-07-17 13:54:32 -0700276 """
277 self._board = board
278 self.uboot_fname = uboot
279 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800280 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700281 self.coreboot_fname = coreboot
Simon Glassa10282a2013-01-08 17:06:41 -0800282 self.coreboot_elf = coreboot_elf
Simon Glass6dcc2f22011-07-28 15:26:49 +1200283 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700284 self.seabios_fname = seabios
Simon Glass7e199222012-03-13 15:51:18 -0700285 self.exynos_bl1 = exynos_bl1
286 self.exynos_bl2 = exynos_bl2
Simon Glass07267952012-06-08 12:45:13 -0700287 self.skeleton_fname = skeleton
Simon Glassbe0bc002012-08-16 12:50:48 -0700288 self.ecrw_fname = ecrw
289 self.ecro_fname = ecro
Simon Glassde9c8072012-07-02 22:29:02 -0700290 self.kernel_fname = kernel
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800291 self.blobs = dict(blobs or ())
Simon Glass290a1802011-07-17 13:54:32 -0700292
Simon Glass00d027e2013-07-20 14:51:12 -0600293 def SetOptions(self, small, gbb_flags, force_rw=False, force_efs=False):
Simon Glass290a1802011-07-17 13:54:32 -0700294 """Set up options supported by Bundle.
295
296 Args:
297 small: Only create a signed U-Boot - don't produce the full packed
298 firmware image. This is useful for devs who want to replace just the
299 U-Boot part while keeping the keys, gbb, etc. the same.
Simon Glass6e486c22012-10-26 15:43:42 -0700300 gbb_flags: Specification for string containing adjustments to make.
301 force_rw: Force firmware into RW mode.
Simon Glass00d027e2013-07-20 14:51:12 -0600302 force_efs: Force firmware to use 'early firmware selection' feature,
303 where RW firmware is selected before SDRAM is initialized.
Simon Glass290a1802011-07-17 13:54:32 -0700304 """
305 self._small = small
Simon Glass157c0662012-10-23 13:52:42 -0700306 self._gbb_flags = gbb_flags
Simon Glass6e486c22012-10-26 15:43:42 -0700307 self._force_rw = force_rw
Simon Glass00d027e2013-07-20 14:51:12 -0600308 self._force_efs = force_efs
Simon Glass290a1802011-07-17 13:54:32 -0700309
Simon Glass22f39fb2013-02-09 13:44:14 -0800310 def _GetBuildRoot(self):
311 """Get the path to this board's 'firmware' directory.
312
313 Returns:
314 Path to firmware directory, with ## representing the path to the
315 chroot.
316 """
Simon Glass290a1802011-07-17 13:54:32 -0700317 if not self._board:
318 raise ValueError('No board defined - please define a board to use')
Simon Glass22f39fb2013-02-09 13:44:14 -0800319 return os.path.join('##', 'build', self._board, 'firmware')
320
321 def _CheckFdtFilename(self, fname):
322 """Check provided FDT filename and return the correct name if needed.
323
324 Where the filename lacks a path, add a default path for this board.
325 Where no FDT filename is provided, select a default one for this board.
326
327 Args:
328 fname: Proposed FDT filename.
329
330 Returns:
331 Selected FDT filename, after validation.
332 """
333 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700334 dir_name = os.path.join(build_root, 'dts')
Simon Glass22f39fb2013-02-09 13:44:14 -0800335 if not fname:
Simon Glassceff3ff2012-04-04 11:23:45 -0700336 # Figure out where the file should be, and the name we expect.
Simon Glassceff3ff2012-04-04 11:23:45 -0700337 base_name = re.sub('_', '-', self._board)
338
339 # In case the name exists with a prefix or suffix, find it.
340 wildcard = os.path.join(dir_name, '*%s*.dts' % base_name)
341 found_list = glob.glob(self._tools.Filename(wildcard))
342 if len(found_list) == 1:
Simon Glass22f39fb2013-02-09 13:44:14 -0800343 fname = found_list[0]
Simon Glassceff3ff2012-04-04 11:23:45 -0700344 else:
345 # We didn't find anything definite, so set up our expected name.
Simon Glass22f39fb2013-02-09 13:44:14 -0800346 fname = os.path.join(dir_name, '%s.dts' % base_name)
Simon Glassceff3ff2012-04-04 11:23:45 -0700347
Simon Glass881964d2012-04-04 11:34:09 -0700348 # Convert things like 'exynos5250-daisy' into a full path.
Simon Glass22f39fb2013-02-09 13:44:14 -0800349 root, ext = os.path.splitext(fname)
Simon Glass881964d2012-04-04 11:34:09 -0700350 if not ext and not os.path.dirname(root):
Simon Glass22f39fb2013-02-09 13:44:14 -0800351 fname = os.path.join(dir_name, '%s.dts' % root)
352 return fname
353
354 def CheckOptions(self):
355 """Check provided options and select defaults."""
356 build_root = self._GetBuildRoot()
Simon Glass881964d2012-04-04 11:34:09 -0700357
Simon Glass49b026b2013-04-26 16:38:42 -0700358 board_type = self._board.split('_')[0]
359 model = type_to_model.get(board_type)
360
Simon Glass290a1802011-07-17 13:54:32 -0700361 if not self.uboot_fname:
362 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
363 if not self.bct_fname:
364 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700365 if not self.bmpblk_fname:
David Hendricksbdecc542012-08-21 13:53:58 -0700366 self.bmpblk_fname = os.path.join(build_root, 'bmpblk.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700367 if model:
368 if not self.exynos_bl1:
Simon Glassd05696e2013-06-13 20:14:00 -0700369 self.exynos_bl1 = os.path.join(build_root, 'u-boot.bl1.bin')
Simon Glass49b026b2013-04-26 16:38:42 -0700370 if not self.exynos_bl2:
Simon Glassd05696e2013-06-13 20:14:00 -0700371 self.exynos_bl2 = os.path.join(build_root, 'u-boot-spl-wrapped.bin')
Simon Glass07267952012-06-08 12:45:13 -0700372 if not self.coreboot_fname:
373 self.coreboot_fname = os.path.join(build_root, 'coreboot.rom')
374 if not self.skeleton_fname:
Stefan Reinauer728be822012-10-02 16:54:09 -0700375 self.skeleton_fname = os.path.join(build_root, 'coreboot.rom')
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700376 if not self.seabios_fname:
377 self.seabios_fname = 'seabios.cbfs'
Simon Glassbe0bc002012-08-16 12:50:48 -0700378 if not self.ecrw_fname:
379 self.ecrw_fname = os.path.join(build_root, 'ec.RW.bin')
380 if not self.ecro_fname:
381 self.ecro_fname = os.path.join(build_root, 'ec.RO.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700382
Simon Glass75759302012-03-15 20:26:53 -0700383 def GetFiles(self):
384 """Get a list of files that we know about.
385
386 This is the opposite of SetFiles except that we may have put in some
387 default names. It returns a dictionary containing the filename for
388 each of a number of pre-defined files.
389
390 Returns:
391 Dictionary, with one entry for each file.
392 """
393 file_list = {
394 'bct' : self.bct_fname,
395 'exynos-bl1' : self.exynos_bl1,
396 'exynos-bl2' : self.exynos_bl2,
397 }
398 return file_list
399
Simon Glass4a887b12012-10-23 16:29:03 -0700400 def DecodeGBBFlagsFromFdt(self):
401 """Get Google Binary Block flags from the FDT.
402
403 These should be in the chromeos-config node, like this:
404
405 chromeos-config {
406 gbb-flag-dev-screen-short-delay;
407 gbb-flag-force-dev-switch-on;
408 gbb-flag-force-dev-boot-usb;
409 gbb-flag-disable-fw-rollback-check;
410 };
411
412 Returns:
413 GBB flags value from FDT.
414 """
415 chromeos_config = self.fdt.GetProps("/chromeos-config")
416 gbb_flags = 0
417 for name in chromeos_config:
418 if name.startswith('gbb-flag-'):
419 flag_value = gbb_flag_properties.get(name[9:])
420 if flag_value:
421 gbb_flags |= flag_value
422 self._out.Notice("FDT: Enabling %s." % name)
423 else:
424 raise ValueError("FDT contains invalid GBB flags '%s'" % name)
425 return gbb_flags
426
Simon Glass157c0662012-10-23 13:52:42 -0700427 def DecodeGBBFlagsFromOptions(self, gbb_flags, adjustments):
428 """Decode ajustments to the provided GBB flags.
429
430 We support three options:
431
432 hex value: c2
433 defined value: force-dev-boot-usb,load-option-roms
434 adjust default value: -load-option-roms,+force-dev-boot-usb
435
436 The last option starts from the passed-in GBB flags and adds or removes
437 flags.
438
439 Args:
440 gbb_flags: Base (default) FDT flags.
441 adjustments: String containing adjustments to make.
442
443 Returns:
444 Updated FDT flags.
445 """
446 use_base_value = True
447 if adjustments:
448 try:
449 return int(adjustments, base=16)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700450 except (ValueError, TypeError):
Simon Glass157c0662012-10-23 13:52:42 -0700451 pass
452 for flag in adjustments.split(','):
453 oper = None
454 if flag[0] in ['-', '+']:
455 oper = flag[0]
456 flag = flag[1:]
457 value = gbb_flag_properties.get(flag)
458 if not value:
459 raise ValueError("Invalid GBB flag '%s'" % flag)
460 if oper == '+':
461 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800462 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700463 elif oper == '-':
464 gbb_flags &= ~value
Simon Glass84816582012-11-20 10:53:10 -0800465 self._out.Notice("Cmdline: Disabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700466 else:
467 if use_base_value:
468 gbb_flags = 0
469 use_base_value = False
Simon Glass84816582012-11-20 10:53:10 -0800470 self._out.Notice('Cmdline: Resetting flags to 0')
Simon Glass157c0662012-10-23 13:52:42 -0700471 gbb_flags |= value
Simon Glass84816582012-11-20 10:53:10 -0800472 self._out.Notice("Cmdline: Enabling %s." % flag)
Simon Glass157c0662012-10-23 13:52:42 -0700473
474 return gbb_flags
475
Simon Glass56577572011-07-19 11:08:06 +1200476 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700477 """Create a GBB for the image.
478
Simon Glass56577572011-07-19 11:08:06 +1200479 Args:
480 hardware_id: Hardware ID to use for this board. If None, then the
481 default from the Fdt will be used
482
Simon Glass89b86b82011-07-17 23:49:49 -0700483 Returns:
484 Path of the created GBB file.
Simon Glass89b86b82011-07-17 23:49:49 -0700485 """
Simon Glass56577572011-07-19 11:08:06 +1200486 if not hardware_id:
Simon Glass02d124a2012-03-02 14:47:20 -0800487 hardware_id = self.fdt.GetString('/config', 'hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700488 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700489 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700490
Simon Glass4a887b12012-10-23 16:29:03 -0700491 gbb_flags = self.DecodeGBBFlagsFromFdt()
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800492
Simon Glass157c0662012-10-23 13:52:42 -0700493 # Allow command line to override flags
494 gbb_flags = self.DecodeGBBFlagsFromOptions(gbb_flags, self._gbb_flags)
495
Simon Glass4a887b12012-10-23 16:29:03 -0700496 self._out.Notice("GBB flags value %#x" % gbb_flags)
Simon Glass89b86b82011-07-17 23:49:49 -0700497 self._out.Progress('Creating GBB')
498 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
499 sizes = ['%#x' % size for size in sizes]
500 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700501 keydir = self._tools.Filename(self._keydir)
502 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700503 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200504 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700505 '--rootkey=%s/root_key.vbpubk' % keydir,
506 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700507 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Stefan Reinauer975e68f2012-02-27 13:27:08 -0800508 '--flags=%d' % gbb_flags,
Simon Glass89b86b82011-07-17 23:49:49 -0700509 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700510 cwd=odir)
511 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700512
Simon Glasse13ee2c2011-07-28 08:12:28 +1200513 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700514 """Sign an image so that the Tegra SOC will boot it.
515
516 Args:
517 bct: BCT file to use.
518 bootstub: Boot stub (U-Boot + fdt) file to sign.
519 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700520
521 Returns:
522 filename of signed image.
Simon Glass89b86b82011-07-17 23:49:49 -0700523 """
524 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200525 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700526 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200527 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700528 fd = open(config, 'w')
529 fd.write('Version = 1;\n')
530 fd.write('Redundancy = 1;\n')
531 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700532
533 # TODO(dianders): Right now, we don't have enough space in our flash map
534 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
535 # sure what this does for reliability, but at least things will fit...
536 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
537 if is_nand:
538 fd.write('Bctcopy = 1;\n')
539
Simon Glass89b86b82011-07-17 23:49:49 -0700540 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
541 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700542
Simon Glass89b86b82011-07-17 23:49:49 -0700543 fd.close()
544
545 self._tools.Run('cbootimage', [config, signed])
546 self._tools.OutputSize('BCT', bct)
547 self._tools.OutputSize('Signed image', signed)
548 return signed
549
Doug Anderson86ce5f42011-07-27 10:40:18 -0700550 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700551 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700552
553 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700554 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700555 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700556 """
Simon Glass468d8752012-09-19 16:36:19 -0700557 if bootcmd is not None:
558 if bootcmd == 'none':
559 bootcmd = ''
Simon Glass02d124a2012-03-02 14:47:20 -0800560 self.fdt.PutString('/config', 'bootcmd', bootcmd)
561 self.fdt.PutInteger('/config', 'bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700562 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700563
Simon Glassa4934b72012-05-09 13:35:02 -0700564 def SetNodeEnabled(self, node_name, enabled):
565 """Set whether an node is enabled or disabled.
566
567 This simply sets the 'status' property of a node to "ok", or "disabled".
568
569 The node should either be a full path to the node (like '/uart@10200000')
570 or an alias property.
571
572 Aliases are supported like this:
573
574 aliases {
575 console = "/uart@10200000";
576 };
577
578 pointing to a node:
579
580 uart@10200000 {
Simon Glass4c5066f2012-06-20 16:51:19 -0700581 status = "okay";
Simon Glassa4934b72012-05-09 13:35:02 -0700582 };
583
584 In this case, this function takes the name of the alias ('console' in
585 this case) and updates the status of the node that is pointed to, to
586 either ok or disabled. If the alias does not exist, a warning is
587 displayed.
588
589 Args:
590 node_name: Name of node (e.g. '/uart@10200000') or alias alias
591 (e.g. 'console') to adjust
592 enabled: True to enable, False to disable
593 """
594 # Look up the alias if this is an alias reference
595 if not node_name.startswith('/'):
596 lookup = self.fdt.GetString('/aliases', node_name, '')
597 if not lookup:
598 self._out.Warning("Cannot find alias '%s' - ignoring" % node_name)
599 return
600 node_name = lookup
601 if enabled:
Simon Glass4c5066f2012-06-20 16:51:19 -0700602 status = 'okay'
Simon Glassa4934b72012-05-09 13:35:02 -0700603 else:
604 status = 'disabled'
605 self.fdt.PutString(node_name, 'status', status)
606
607 def AddEnableList(self, enable_list):
608 """Process a list of nodes to enable/disable.
609
610 Args:
611 config_list: List of (node, value) tuples to add to the fdt. For each
612 tuple:
613 node: The fdt node to write to will be <node> or pointed to by
614 /aliases/<node>. We can tell which
615 value: 0 to disable the node, 1 to enable it
Vadim Bendebury507c0012013-06-09 12:49:25 -0700616 Raises:
617 CmdError if a command fails.
Simon Glassa4934b72012-05-09 13:35:02 -0700618 """
619 if enable_list:
620 for node_name, enabled in enable_list:
621 try:
622 enabled = int(enabled)
623 if enabled not in (0, 1):
624 raise ValueError
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700625 except ValueError:
Simon Glassa4934b72012-05-09 13:35:02 -0700626 raise CmdError("Invalid enable option value '%s' "
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700627 "(should be 0 or 1)" % str(enabled))
Simon Glassa4934b72012-05-09 13:35:02 -0700628 self.SetNodeEnabled(node_name, enabled)
629
Simon Glass290a1802011-07-17 13:54:32 -0700630 def AddConfigList(self, config_list, use_int=False):
631 """Add a list of config items to the fdt.
632
633 Normally these values are written to the fdt as strings, but integers
634 are also supported, in which case the values will be converted to integers
635 (if necessary) before being stored.
636
637 Args:
638 config_list: List of (config, value) tuples to add to the fdt. For each
639 tuple:
640 config: The fdt node to write to will be /config/<config>.
641 value: An integer or string value to write.
642 use_int: True to only write integer values.
643
644 Raises:
645 CmdError: if a value is required to be converted to integer but can't be.
646 """
647 if config_list:
648 for config in config_list:
649 value = config[1]
650 if use_int:
651 try:
652 value = int(value)
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700653 except ValueError:
Simon Glass290a1802011-07-17 13:54:32 -0700654 raise CmdError("Cannot convert config option '%s' to integer" %
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700655 str(value))
Simon Glass290a1802011-07-17 13:54:32 -0700656 if type(value) == type(1):
Simon Glass02d124a2012-03-02 14:47:20 -0800657 self.fdt.PutInteger('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700658 else:
Simon Glass02d124a2012-03-02 14:47:20 -0800659 self.fdt.PutString('/config', '%s' % config[0], value)
Simon Glass290a1802011-07-17 13:54:32 -0700660
Simon Glass7c2d5572011-11-15 14:47:08 -0800661 def DecodeTextBase(self, data):
662 """Look at a U-Boot image and try to decode its TEXT_BASE.
663
664 This works because U-Boot has a header with the value 0x12345678
665 immediately followed by the TEXT_BASE value. We can therefore read this
666 from the image with some certainty. We check only the first 40 words
667 since the header should be within that region.
668
Simon Glass96b50302012-07-20 06:55:28 +0100669 Since upstream Tegra has moved to having a 16KB SPL region at the start,
670 and currently this does holds the U-Boot text base (e.g. 0x10c000) instead
671 of the SPL one (e.g. 0x108000), we search in the U-Boot part as well.
672
Simon Glass7c2d5572011-11-15 14:47:08 -0800673 Args:
674 data: U-Boot binary data
675
676 Returns:
677 Text base (integer) or None if none was found
678 """
679 found = False
Simon Glass96b50302012-07-20 06:55:28 +0100680 for start in (0, 0x4000):
681 for i in range(start, start + 160, 4):
682 word = data[i:i + 4]
Simon Glass7c2d5572011-11-15 14:47:08 -0800683
Simon Glass96b50302012-07-20 06:55:28 +0100684 # TODO(sjg): This does not cope with a big-endian target
685 value = struct.unpack('<I', word)[0]
686 if found:
687 return value - start
688 if value == 0x12345678:
689 found = True
Simon Glass7c2d5572011-11-15 14:47:08 -0800690
691 return None
692
693 def CalcTextBase(self, name, fdt, fname):
694 """Calculate the TEXT_BASE to use for U-Boot.
695
696 Normally this value is in the fdt, so we just read it from there. But as
697 a second check we look at the image itself in case this is different, and
698 switch to that if it is.
699
700 This allows us to flash any U-Boot even if its TEXT_BASE is different.
701 This is particularly useful with upstream U-Boot which uses a different
702 value (which we will move to).
703 """
704 data = self._tools.ReadFile(fname)
Andrew Chewaa092542013-01-09 16:30:52 -0800705 # The value that comes back from fdt.GetInt is signed, which makes no
706 # sense for an address base. Force it to unsigned.
707 fdt_text_base = fdt.GetInt('/chromeos-config', 'textbase', 0) & 0xffffffff
Simon Glass7c2d5572011-11-15 14:47:08 -0800708 text_base = self.DecodeTextBase(data)
Simon Glass96b50302012-07-20 06:55:28 +0100709 text_base_str = '%#x' % text_base if text_base else 'None'
710 self._out.Info('TEXT_BASE: fdt says %#x, %s says %s' % (fdt_text_base,
711 fname, text_base_str))
Simon Glass7c2d5572011-11-15 14:47:08 -0800712
713 # If they are different, issue a warning and switch over.
714 if text_base and text_base != fdt_text_base:
715 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
716 "fdt value of %x. Using %x" % (text_base, name,
717 fdt_text_base, text_base))
718 fdt_text_base = text_base
719 return fdt_text_base
720
Simon Glass6dcc2f22011-07-28 15:26:49 +1200721 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700722 """Create a boot stub and a signed boot stub.
723
Simon Glass6dcc2f22011-07-28 15:26:49 +1200724 For postload:
725 We add a /config/postload-text-offset entry to the signed bootstub's
726 fdt so that U-Boot can find the postload code.
727
728 The raw (unsigned) bootstub will have a value of -1 for this since we will
729 simply append the postload code to the bootstub and it can find it there.
730 This will be used for RW A/B firmware.
731
732 For the signed case this value will specify where in the flash to find
733 the postload code. This will be used for RO firmware.
734
Simon Glass89b86b82011-07-17 23:49:49 -0700735 Args:
736 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass29b96ad2012-03-09 15:34:33 -0800737 base_fdt: Fdt object containing the flat device tree.
Simon Glass6dcc2f22011-07-28 15:26:49 +1200738 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700739
740 Returns:
741 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200742 Full path to bootstub (uboot + fdt(-1) + postload).
743 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700744
745 Raises:
746 CmdError if a command fails.
747 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200748 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800749 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700750 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200751
752 # Make a copy of the fdt for the bootstub
753 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700754 fdt.PutInteger('/config', 'postload-text-offset', 0xffffffff)
Simon Glass290a1802011-07-17 13:54:32 -0700755 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200756
Simon Glass89b86b82011-07-17 23:49:49 -0700757 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700758 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
759 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700760 self._tools.OutputSize('Combined binary', bootstub)
761
Simon Glasse13ee2c2011-07-28 08:12:28 +1200762 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700763 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700764 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200765 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200766
767 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
768 data = self._tools.ReadFile(signed)
769
770 if postload:
771 # We must add postload to the bootstub since A and B will need to
772 # be able to find it without the /config/postload-text-offset mechanism.
773 bs_data = self._tools.ReadFile(bootstub)
774 bs_data += self._tools.ReadFile(postload)
775 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
776 self._tools.WriteFile(bootstub, bs_data)
777 self._tools.OutputSize('Combined binary with postload', bootstub)
778
779 # Now that we know the file size, adjust the fdt and re-sign
780 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
Simon Glass02d124a2012-03-02 14:47:20 -0800781 fdt.PutInteger('/config', 'postload-text-offset', len(data))
Simon Glass6dcc2f22011-07-28 15:26:49 +1200782 fdt_data = self._tools.ReadFile(fdt.fname)
783 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
784 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
785 postload_bootstub, text_base)
786 if len(data) != os.path.getsize(signed):
787 raise CmdError('Signed file size changed from %d to %d after updating '
788 'fdt' % (len(data), os.path.getsize(signed)))
789
790 # Re-read the signed image, and add the post-load binary.
791 data = self._tools.ReadFile(signed)
792 data += self._tools.ReadFile(postload)
793 self._tools.OutputSize('Post-load binary', postload)
794
795 self._tools.WriteFile(signed_postload, data)
796 self._tools.OutputSize('Final bootstub with postload', signed_postload)
797
798 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700799
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700800 def _CreateCorebootStub(self, coreboot):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700801 """Create a coreboot boot stub.
802
803 Args:
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700804 coreboot: Path to coreboot.rom
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700805
806 Returns:
Simon Glasscbc83552012-07-23 15:26:22 +0100807 Full path to bootstub (coreboot + uboot).
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700808 """
809 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Simon Glassf2b3a5c2012-06-07 14:02:36 -0700810 shutil.copyfile(self._tools.Filename(coreboot), bootstub)
Simon Glasscbc83552012-07-23 15:26:22 +0100811
812 # Don't add the fdt yet since it is not in final form
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700813 return bootstub
814
Simon Glass7e199222012-03-13 15:51:18 -0700815
Simon Glass89b86b82011-07-17 23:49:49 -0700816 def _PackOutput(self, msg):
817 """Helper function to write output from PackFirmware (verbose level 2).
818
819 This is passed to PackFirmware for it to use to write output.
820
821 Args:
822 msg: Message to display.
823 """
824 self._out.Notice(msg)
825
Simon Glass439fe7a2012-03-09 16:19:34 -0800826 def _BuildBlob(self, pack, fdt, blob_type):
827 """Build the blob data for a particular blob type.
828
829 Args:
830 blob_type: The type of blob to create data for. Supported types are:
831 coreboot A coreboot image (ROM plus U-boot and .dtb payloads).
832 signed Nvidia T20/T30 signed image (BCT, U-Boot, .dtb).
Vadim Bendebury507c0012013-06-09 12:49:25 -0700833
834 Raises:
835 CmdError if a command fails.
Simon Glass439fe7a2012-03-09 16:19:34 -0800836 """
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700837 # stupid pylint insists that sha256 is not in hashlib.
838 # pylint: disable=E1101
Simon Glass439fe7a2012-03-09 16:19:34 -0800839 if blob_type == 'coreboot':
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700840 coreboot = self._CreateCorebootStub(self.coreboot_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800841 pack.AddProperty('coreboot', coreboot)
842 pack.AddProperty('image', coreboot)
Stefan Reinauer9ad54842012-10-10 12:25:23 -0700843 elif blob_type == 'legacy':
844 pack.AddProperty('legacy', self.seabios_fname)
Simon Glass439fe7a2012-03-09 16:19:34 -0800845 elif blob_type == 'signed':
846 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
847 self.postload_fname)
848 pack.AddProperty('bootstub', bootstub)
849 pack.AddProperty('signed', signed)
850 pack.AddProperty('image', signed)
Simon Glass7e199222012-03-13 15:51:18 -0700851 elif blob_type == 'exynos-bl1':
852 pack.AddProperty(blob_type, self.exynos_bl1)
Simon Glassbe0bc002012-08-16 12:50:48 -0700853
854 # TODO(sjg@chromium.org): Deprecate ecbin
855 elif blob_type in ['ecrw', 'ecbin']:
856 pack.AddProperty('ecrw', self.ecrw_fname)
857 pack.AddProperty('ecbin', self.ecrw_fname)
Gabe Blackcdbdfe12013-02-06 05:37:52 -0800858 elif blob_type == 'ecrwhash':
859 ec_hash_file = os.path.join(self._tools.outdir, 'ec_hash.bin')
860 ecrw = self._tools.ReadFile(self.ecrw_fname)
861 hasher = hashlib.sha256()
862 hasher.update(ecrw)
863 self._tools.WriteFile(ec_hash_file, hasher.digest())
864 pack.AddProperty(blob_type, ec_hash_file)
Simon Glassbe0bc002012-08-16 12:50:48 -0700865 elif blob_type == 'ecro':
Simon Glass693b40f2012-08-28 10:51:05 -0700866 # crosbug.com/p/13143
867 # We cannot have an fmap in the EC image since there can be only one,
868 # which is the main fmap describing the whole image.
869 # Ultimately the EC will not have an fmap, since with software sync
870 # there is no flashrom involvement in updating the EC flash, and thus
871 # no need for the fmap.
872 # For now, mangle the fmap name to avoid problems.
873 updated_ecro = os.path.join(self._tools.outdir, 'updated-ecro.bin')
874 data = self._tools.ReadFile(self.ecro_fname)
875 data = re.sub('__FMAP__', '__fMAP__', data)
876 self._tools.WriteFile(updated_ecro, data)
877 pack.AddProperty(blob_type, updated_ecro)
Simon Glass0a047bc2013-07-19 15:44:43 -0600878 elif blob_type.startswith('exynos-bl2'):
879 # We need to configure this per node, so do it later
880 pass
Simon Glass439fe7a2012-03-09 16:19:34 -0800881 elif pack.GetProperty(blob_type):
882 pass
Che-Liang Chiou3bc344c2013-02-21 15:18:03 -0800883 elif blob_type in self.blobs:
884 pack.AddProperty(blob_type, self.blobs[blob_type])
Simon Glass439fe7a2012-03-09 16:19:34 -0800885 else:
886 raise CmdError("Unknown blob type '%s' required in flash map" %
887 blob_type)
888
Simon Glass290a1802011-07-17 13:54:32 -0700889 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700890 """Create a full firmware image, along with various by-products.
891
892 This uses the provided u-boot.bin, fdt and bct to create a firmware
893 image containing all the required parts. If the GBB is not supplied
894 then this will just return a signed U-Boot as the image.
895
896 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +1200897 gbb: Full path to the GBB file, or empty if a GBB is not required.
898 fdt: Fdt object containing required information.
899
900 Returns:
901 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700902 """
Simon Glass02d124a2012-03-02 14:47:20 -0800903 self._out.Notice("Model: %s" % fdt.GetString('/', 'model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700904
Simon Glass439fe7a2012-03-09 16:19:34 -0800905 pack = PackFirmware(self._tools, self._out)
Vadim Bendebury238f6442013-03-27 11:23:25 -0700906 # Get the flashmap so we know what to build. For board variants use the
907 # main board name as the key (drop the _<variant> suffix).
908 default_flashmap = default_flashmaps.get(self._board.split('_')[0])
Simon Glassb8c6d952012-12-01 06:14:35 -0800909 if self._force_rw:
Vadim Bendebury7bfdb372013-03-27 11:52:58 -0700910 fdt.PutInteger('/flash/rw-a-vblock', 'preamble-flags', 0)
911 fdt.PutInteger('/flash/rw-b-vblock', 'preamble-flags', 0)
Simon Glass00d027e2013-07-20 14:51:12 -0600912 if self._force_efs:
913 fdt.PutInteger('/chromeos-config', 'early-firmware-selection', 1)
Simon Glassb8c6d952012-12-01 06:14:35 -0800914
Simon Glass4f318912013-07-20 16:13:06 -0600915 if not fdt.GetProp('/flash', 'reg', ''):
916 fdt.InsertNodes(default_flashmap)
917
918 pack.SelectFdt(fdt, self._board)
Simon Glass439fe7a2012-03-09 16:19:34 -0800919
920 # Get all our blobs ready
921 pack.AddProperty('boot', self.uboot_fname)
Simon Glass284cb892013-02-09 13:38:03 -0800922 if self.skeleton_fname:
923 pack.AddProperty('skeleton', self.skeleton_fname)
Simon Glass3b85f712012-06-21 07:06:46 -0700924 pack.AddProperty('dtb', fdt.fname)
Simon Glass50f74602012-03-15 21:04:25 -0700925
Simon Glassde9c8072012-07-02 22:29:02 -0700926 # If we are writing a kernel, add its offset from TEXT_BASE to the fdt.
927 if self.kernel_fname:
928 fdt.PutInteger('/config', 'kernel-offset', pack.image_size)
929
Simon Glass439fe7a2012-03-09 16:19:34 -0800930 pack.AddProperty('gbb', self.uboot_fname)
Simon Glass9d088d92012-07-16 16:27:11 +0100931 blob_list = pack.GetBlobList()
932 self._out.Info('Building blobs %s\n' % blob_list)
Simon Glass07267952012-06-08 12:45:13 -0700933 for blob_type in pack.GetBlobList():
Simon Glass439fe7a2012-03-09 16:19:34 -0800934 self._BuildBlob(pack, fdt, blob_type)
Simon Glass89b86b82011-07-17 23:49:49 -0700935
Simon Glass7306b902012-12-17 15:06:21 -0800936 self._out.Progress('Packing image')
Simon Glass89b86b82011-07-17 23:49:49 -0700937 if gbb:
Simon Glasse76bf7b2012-03-13 15:34:41 -0700938 pack.RequireAllEntries()
Hung-Te Lina7462e72011-07-27 19:17:10 +0800939 fwid = '.'.join([
Simon Glass02d124a2012-03-02 14:47:20 -0800940 re.sub('[ ,]+', '_', fdt.GetString('/', 'model')),
Hung-Te Lina7462e72011-07-27 19:17:10 +0800941 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700942 self._out.Notice('Firmware ID: %s' % fwid)
Simon Glass439fe7a2012-03-09 16:19:34 -0800943 pack.AddProperty('fwid', fwid)
944 pack.AddProperty('gbb', gbb)
945 pack.AddProperty('keydir', self._keydir)
Simon Glassc90cf582012-03-13 15:40:47 -0700946
Simon Glass0a047bc2013-07-19 15:44:43 -0600947 # Some blobs need to be configured according to the node they are in.
Simon Glass4c24f662013-07-19 15:53:02 -0600948 todo = pack.GetMissingBlobs()
949 for blob in todo:
Simon Glass0a047bc2013-07-19 15:44:43 -0600950 if blob.key.startswith('exynos-bl2'):
951 bl2 = ExynosBl2(self._tools, self._out)
952 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
953 self.exynos_bl2))
954
Simon Glassc90cf582012-03-13 15:40:47 -0700955 pack.CheckProperties()
Simon Glass8884b982012-06-21 12:41:41 -0700956
957 # Record position and size of all blob members in the FDT
Gabe Blackcc22d772013-02-04 23:12:02 -0800958 pack.UpdateBlobPositionsAndHashes(fdt)
Simon Glass8884b982012-06-21 12:41:41 -0700959
Simon Glass4c24f662013-07-19 15:53:02 -0600960 # Recalculate the Exynos BL2, since it may have a hash. The call to
961 # UpdateBlobPositionsAndHashes() may have updated the hash-target so we
962 # need to recalculate the hash.
963 for blob in todo:
964 if blob.key.startswith('exynos-bl2'):
965 bl2 = ExynosBl2(self._tools, self._out)
966 pack.AddProperty(blob.key, bl2.MakeSpl(pack, fdt, blob,
967 self.exynos_bl2))
968
Simon Glass6207efe2012-12-17 15:04:36 -0800969 # Make a copy of the fdt for the bootstub
970 fdt_data = self._tools.ReadFile(fdt.fname)
971 uboot_data = self._tools.ReadFile(self.uboot_fname)
972 uboot_copy = os.path.join(self._tools.outdir, 'u-boot.bin')
973 self._tools.WriteFile(uboot_copy, uboot_data)
974
975 uboot_dtb = os.path.join(self._tools.outdir, 'u-boot-dtb.bin')
976 self._tools.WriteFile(uboot_dtb, uboot_data + fdt_data)
977
Simon Glassa10282a2013-01-08 17:06:41 -0800978 # Fix up the coreboot image here, since we can't do this until we have
979 # a final device tree binary.
Simon Glasscbc83552012-07-23 15:26:22 +0100980 if 'coreboot' in blob_list:
981 bootstub = pack.GetProperty('coreboot')
982 fdt = fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
Simon Glassa10282a2013-01-08 17:06:41 -0800983 if self.coreboot_elf:
984 self._tools.Run('cbfstool', [bootstub, 'add-payload', '-f',
985 self.coreboot_elf, '-n', 'fallback/payload', '-c', 'lzma'])
986 else:
Simon Glass0a7cf112013-05-21 23:08:21 -0700987 text_base = 0x1110000
988
989 # This is the the 'movw $GD_FLG_COLD_BOOT, %bx' instruction
990 # 1110015: 66 bb 00 01 mov $0x100,%bx
991 marker = struct.pack('<L', 0x0100bb66)
992 pos = uboot_data.find(marker)
993 if pos == -1 or pos > 0x100:
994 raise ValueError('Cannot find U-Boot cold boot entry point')
995 entry = text_base + pos
996 self._out.Notice('U-Boot entry point %#08x' % entry)
Simon Glassa10282a2013-01-08 17:06:41 -0800997 self._tools.Run('cbfstool', [bootstub, 'add-flat-binary', '-f',
998 uboot_dtb, '-n', 'fallback/payload', '-c', 'lzma',
Simon Glass0a7cf112013-05-21 23:08:21 -0700999 '-l', '%#x' % text_base, '-e', '%#x' % entry])
Stefan Reinauer1502ea62012-11-01 10:15:38 -07001000 self._tools.Run('cbfstool', [bootstub, 'add', '-f', fdt.fname,
1001 '-n', 'u-boot.dtb', '-t', '0xac'])
Simon Glassb8ea1802012-12-17 15:08:00 -08001002 data = self._tools.ReadFile(bootstub)
1003 bootstub_copy = os.path.join(self._tools.outdir, 'coreboot-8mb.rom')
1004 self._tools.WriteFile(bootstub_copy, data)
Gabe Black3df75252013-02-14 21:32:10 -08001005 self._tools.WriteFile(bootstub, data[-0x100000:])
Simon Glasscbc83552012-07-23 15:26:22 +01001006
Simon Glass208ad952013-02-10 11:16:46 -08001007 pack.AddProperty('fdtmap', fdt.fname)
Simon Glassc90cf582012-03-13 15:40:47 -07001008 image = os.path.join(self._tools.outdir, 'image.bin')
1009 pack.PackImage(self._tools.outdir, image)
1010 pack.AddProperty('image', image)
Simon Glass89b86b82011-07-17 23:49:49 -07001011
Simon Glass439fe7a2012-03-09 16:19:34 -08001012 image = pack.GetProperty('image')
Simon Glass89b86b82011-07-17 23:49:49 -07001013 self._tools.OutputSize('Final image', image)
Simon Glassc90cf582012-03-13 15:40:47 -07001014 return image, pack
Simon Glass89b86b82011-07-17 23:49:49 -07001015
Simon Glassdedda6f2013-02-09 13:44:14 -08001016 def SelectFdt(self, fdt_fname, use_defaults):
Simon Glass290a1802011-07-17 13:54:32 -07001017 """Select an FDT to control the firmware bundling
1018
Simon Glassdedda6f2013-02-09 13:44:14 -08001019 We make a copy of this which will include any on-the-fly changes we want
1020 to make.
1021
Simon Glass290a1802011-07-17 13:54:32 -07001022 Args:
1023 fdt_fname: The filename of the fdt to use.
Simon Glassdedda6f2013-02-09 13:44:14 -08001024 use_defaults: True to use a default FDT name if available, and to add
1025 a full path to the provided filename if necessary.
Simon Glass290a1802011-07-17 13:54:32 -07001026
Simon Glassc0f3dc62011-08-09 14:19:05 -07001027 Returns:
1028 The Fdt object of the original fdt file, which we will not modify.
1029
Simon Glassdedda6f2013-02-09 13:44:14 -08001030 Raises:
1031 ValueError if no FDT is provided (fdt_fname is None and use_defaults is
1032 False).
Simon Glass290a1802011-07-17 13:54:32 -07001033 """
Simon Glassdedda6f2013-02-09 13:44:14 -08001034 if use_defaults:
1035 fdt_fname = self._CheckFdtFilename(fdt_fname)
Simon Glass22f39fb2013-02-09 13:44:14 -08001036 if not fdt_fname:
1037 raise ValueError('Please provide an FDT filename')
1038 fdt = Fdt(self._tools, fdt_fname)
Simon Glass290a1802011-07-17 13:54:32 -07001039 self._fdt_fname = fdt_fname
Simon Glassc3e42c32012-12-17 15:00:04 -08001040
1041 # For upstream, select the correct architecture .dtsi manually.
1042 if self._board == 'link' or 'x86' in self._board:
1043 arch_dts = 'coreboot.dtsi'
1044 elif self._board == 'daisy':
1045 arch_dts = 'exynos5250.dtsi'
1046 else:
1047 arch_dts = 'tegra20.dtsi'
1048
1049 fdt.Compile(arch_dts)
Simon Glass290a1802011-07-17 13:54:32 -07001050 self.fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Simon Glass32abe2e2013-07-18 18:00:55 -06001051 return self.fdt
Simon Glass290a1802011-07-17 13:54:32 -07001052
Simon Glassc90cf582012-03-13 15:40:47 -07001053 def Start(self, hardware_id, output_fname, show_map):
Simon Glass290a1802011-07-17 13:54:32 -07001054 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -07001055
1056 - Checks options, tools, output directory, fdt.
1057 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -07001058
1059 Args:
Simon Glass56577572011-07-19 11:08:06 +12001060 hardware_id: Hardware ID to use for this board. If None, then the
1061 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -07001062 output_fname: Output filename for the image. If this is not None, then
1063 the final image will be copied here.
Simon Glassc90cf582012-03-13 15:40:47 -07001064 show_map: Show a flash map, with each area's name and position
Simon Glass290a1802011-07-17 13:54:32 -07001065
1066 Returns:
1067 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -07001068 """
Vadim Bendebury5baeec12013-04-02 13:01:22 -07001069 if self._small or self.fdt.GetProp('/config', 'nogbb', 'any') != 'any':
1070 gbb = '' # Building a small image or `nogbb' is requested in device tree.
1071 else:
Simon Glass56577572011-07-19 11:08:06 +12001072 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -07001073
1074 # This creates the actual image.
Simon Glassc90cf582012-03-13 15:40:47 -07001075 image, pack = self._CreateImage(gbb, self.fdt)
1076 if show_map:
1077 pack.ShowMap()
Simon Glass290a1802011-07-17 13:54:32 -07001078 if output_fname:
1079 shutil.copyfile(image, output_fname)
1080 self._out.Notice("Output image '%s'" % output_fname)
Simon Glass794217e2012-06-07 11:40:37 -07001081 return image, pack.props