blob: ede3e2aa46c969fc70c5feac7507c29bc35aad3b [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
19import os
20import re
21
22import cros_output
23from fdt import Fdt
24from pack_firmware import PackFirmware
25import shutil
Simon Glass7c2d5572011-11-15 14:47:08 -080026import struct
Simon Glass89b86b82011-07-17 23:49:49 -070027import tempfile
28from tools import Tools
29from write_firmware import WriteFirmware
30
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
57class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070058 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070059
Simon Glass290a1802011-07-17 13:54:32 -070060 Sequence of events:
61 bundle = Bundle(tools.Tools(), cros_output.Output())
62 bundle.SetDirs(...)
63 bundle.SetFiles(...)
64 bundle.SetOptions(...)
65 bundle.SelectFdt(fdt.Fdt('filename.dtb')
66 .. can call bundle.AddConfigList() if required
67 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070068
Simon Glass290a1802011-07-17 13:54:32 -070069 Public properties:
70 fdt: The fdt object that we use for building our image. This wil be the
71 one specified by the user, except that we might add config options
72 to it. This is set up by SelectFdt() which must be called before
73 bundling starts.
74 uboot_fname: Full filename of the U-Boot binary we use.
75 bct_fname: Full filename of the BCT file we use.
76 """
Simon Glass89b86b82011-07-17 23:49:49 -070077
Simon Glass290a1802011-07-17 13:54:32 -070078 def __init__(self, tools, output):
79 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -070080
Simon Glass290a1802011-07-17 13:54:32 -070081 Args:
82 tools: A tools.Tools object to use for external tools.
83 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -070084 """
Simon Glass290a1802011-07-17 13:54:32 -070085 self._tools = tools
86 self._out = output
87
88 # Set up the things we need to know in order to operate.
89 self._board = None # Board name, e.g. tegra2_seaboard.
90 self._fdt_fname = None # Filename of our FDT.
91 self.uboot_fname = None # Filename of our U-Boot binary.
92 self.bct_fname = None # Filename of our BCT file.
93 self.fdt = None # Our Fdt object.
Hung-Te Lin5b649382011-08-03 15:01:16 +080094 self.bmpblk_fname = None # Filename of our Bitmap Block
Stefan Reinauer8d79d362011-08-16 14:20:43 -070095 self.coreboot_fname = None # Filename of our coreboot binary.
Vincent Palatinf7286772011-10-12 14:31:53 -070096 self.seabios_fname = None # Filename of our SeaBIOS payload.
Simon Glass290a1802011-07-17 13:54:32 -070097
98 def SetDirs(self, keydir):
99 """Set up directories required for Bundle.
100
101 Args:
102 keydir: Directory containing keys to use for signing firmware.
103 """
104 self._keydir = keydir
105
Simon Glass6dcc2f22011-07-28 15:26:49 +1200106 def SetFiles(self, board, bct, uboot=None, bmpblk=None, coreboot=None,
Vincent Palatinf7286772011-10-12 14:31:53 -0700107 postload=None, seabios=None):
Simon Glass290a1802011-07-17 13:54:32 -0700108 """Set up files required for Bundle.
109
110 Args:
111 board: The name of the board to target (e.g. tegra2_seaboard).
112 uboot: The filename of the u-boot.bin image to use.
113 bct: The filename of the binary BCT file to use.
Hung-Te Lin5b649382011-08-03 15:01:16 +0800114 bmpblk: The filename of bitmap block file to use.
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700115 coreboot: The filename of the coreboot image to use (on x86)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200116 postload: The filename of the u-boot-post.bin image to use.
Vincent Palatinf7286772011-10-12 14:31:53 -0700117 seabios: The filename of the SeaBIOS payload to use if any.
Simon Glass290a1802011-07-17 13:54:32 -0700118 """
119 self._board = board
120 self.uboot_fname = uboot
121 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800122 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700123 self.coreboot_fname = coreboot
Simon Glass6dcc2f22011-07-28 15:26:49 +1200124 self.postload_fname = postload
Vincent Palatinf7286772011-10-12 14:31:53 -0700125 self.seabios_fname = seabios
Simon Glass290a1802011-07-17 13:54:32 -0700126
127 def SetOptions(self, small):
128 """Set up options supported by Bundle.
129
130 Args:
131 small: Only create a signed U-Boot - don't produce the full packed
132 firmware image. This is useful for devs who want to replace just the
133 U-Boot part while keeping the keys, gbb, etc. the same.
134 """
135 self._small = small
136
137 def CheckOptions(self):
138 """Check provided options and select defaults."""
139 if not self._board:
140 raise ValueError('No board defined - please define a board to use')
Simon Glass493163b2011-09-14 11:19:57 -0700141 build_root = os.path.join('##', 'build', self._board, 'firmware')
Simon Glass290a1802011-07-17 13:54:32 -0700142 if not self._fdt_fname:
143 self._fdt_fname = os.path.join(build_root, 'dtb', '%s.dtb' %
144 re.sub('_', '-', self._board))
145 if not self.uboot_fname:
146 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
147 if not self.bct_fname:
148 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700149 if not self.bmpblk_fname:
150 self.bmpblk_fname = os.path.join(build_root, 'default.bmpblk')
Simon Glass89b86b82011-07-17 23:49:49 -0700151
Simon Glass56577572011-07-19 11:08:06 +1200152 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700153 """Create a GBB for the image.
154
Simon Glass56577572011-07-19 11:08:06 +1200155 Args:
156 hardware_id: Hardware ID to use for this board. If None, then the
157 default from the Fdt will be used
158
Simon Glass89b86b82011-07-17 23:49:49 -0700159 Returns:
160 Path of the created GBB file.
161
162 Raises:
163 CmdError if a command fails.
164 """
Simon Glass56577572011-07-19 11:08:06 +1200165 if not hardware_id:
166 hardware_id = self.fdt.GetString('/config/hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700167 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700168 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700169
Simon Glass89b86b82011-07-17 23:49:49 -0700170 self._out.Progress('Creating GBB')
171 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
172 sizes = ['%#x' % size for size in sizes]
173 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700174 keydir = self._tools.Filename(self._keydir)
175 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700176 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200177 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700178 '--rootkey=%s/root_key.vbpubk' % keydir,
179 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700180 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Simon Glass89b86b82011-07-17 23:49:49 -0700181 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700182 cwd=odir)
183 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700184
Simon Glasse13ee2c2011-07-28 08:12:28 +1200185 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700186 """Sign an image so that the Tegra SOC will boot it.
187
188 Args:
189 bct: BCT file to use.
190 bootstub: Boot stub (U-Boot + fdt) file to sign.
191 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700192
193 Returns:
194 filename of signed image.
195
196 Raises:
197 CmdError if a command fails.
198 """
199 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200200 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700201 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200202 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700203 fd = open(config, 'w')
204 fd.write('Version = 1;\n')
205 fd.write('Redundancy = 1;\n')
206 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700207
208 # TODO(dianders): Right now, we don't have enough space in our flash map
209 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
210 # sure what this does for reliability, but at least things will fit...
211 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
212 if is_nand:
213 fd.write('Bctcopy = 1;\n')
214
Simon Glass89b86b82011-07-17 23:49:49 -0700215 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
216 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700217
Simon Glass89b86b82011-07-17 23:49:49 -0700218 fd.close()
219
220 self._tools.Run('cbootimage', [config, signed])
221 self._tools.OutputSize('BCT', bct)
222 self._tools.OutputSize('Signed image', signed)
223 return signed
224
Doug Anderson86ce5f42011-07-27 10:40:18 -0700225 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700226 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700227
228 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700229 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700230 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700231 """
Simon Glass290a1802011-07-17 13:54:32 -0700232 if bootcmd:
Simon Glassb4447fd2011-07-26 11:18:25 +1200233 self.fdt.PutString('/config/bootcmd', bootcmd)
Doug Anderson86ce5f42011-07-27 10:40:18 -0700234 self.fdt.PutInteger('/config/bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700235 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700236
Simon Glass290a1802011-07-17 13:54:32 -0700237 def AddConfigList(self, config_list, use_int=False):
238 """Add a list of config items to the fdt.
239
240 Normally these values are written to the fdt as strings, but integers
241 are also supported, in which case the values will be converted to integers
242 (if necessary) before being stored.
243
244 Args:
245 config_list: List of (config, value) tuples to add to the fdt. For each
246 tuple:
247 config: The fdt node to write to will be /config/<config>.
248 value: An integer or string value to write.
249 use_int: True to only write integer values.
250
251 Raises:
252 CmdError: if a value is required to be converted to integer but can't be.
253 """
254 if config_list:
255 for config in config_list:
256 value = config[1]
257 if use_int:
258 try:
259 value = int(value)
260 except ValueError as str:
261 raise CmdError("Cannot convert config option '%s' to integer" %
262 value)
263 if type(value) == type(1):
264 self.fdt.PutInteger('/config/%s' % config[0], value)
265 else:
266 self.fdt.PutString('/config/%s' % config[0], value)
267
Simon Glass7c2d5572011-11-15 14:47:08 -0800268 def DecodeTextBase(self, data):
269 """Look at a U-Boot image and try to decode its TEXT_BASE.
270
271 This works because U-Boot has a header with the value 0x12345678
272 immediately followed by the TEXT_BASE value. We can therefore read this
273 from the image with some certainty. We check only the first 40 words
274 since the header should be within that region.
275
276 Args:
277 data: U-Boot binary data
278
279 Returns:
280 Text base (integer) or None if none was found
281 """
282 found = False
283 for i in range(0, 160, 4):
284 word = data[i:i + 4]
285
286 # TODO(sjg): This does not cope with a big-endian target
287 value = struct.unpack('<I', word)[0]
288 if found:
289 return value
290 if value == 0x12345678:
291 found = True
292
293 return None
294
295 def CalcTextBase(self, name, fdt, fname):
296 """Calculate the TEXT_BASE to use for U-Boot.
297
298 Normally this value is in the fdt, so we just read it from there. But as
299 a second check we look at the image itself in case this is different, and
300 switch to that if it is.
301
302 This allows us to flash any U-Boot even if its TEXT_BASE is different.
303 This is particularly useful with upstream U-Boot which uses a different
304 value (which we will move to).
305 """
306 data = self._tools.ReadFile(fname)
307 fdt_text_base = fdt.GetInt('/chromeos-config/textbase')
308 text_base = self.DecodeTextBase(data)
309
310 # If they are different, issue a warning and switch over.
311 if text_base and text_base != fdt_text_base:
312 self._out.Warning("TEXT_BASE %x in %sU-Boot doesn't match "
313 "fdt value of %x. Using %x" % (text_base, name,
314 fdt_text_base, text_base))
315 fdt_text_base = text_base
316 return fdt_text_base
317
Simon Glass6dcc2f22011-07-28 15:26:49 +1200318 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700319 """Create a boot stub and a signed boot stub.
320
Simon Glass6dcc2f22011-07-28 15:26:49 +1200321 For postload:
322 We add a /config/postload-text-offset entry to the signed bootstub's
323 fdt so that U-Boot can find the postload code.
324
325 The raw (unsigned) bootstub will have a value of -1 for this since we will
326 simply append the postload code to the bootstub and it can find it there.
327 This will be used for RW A/B firmware.
328
329 For the signed case this value will specify where in the flash to find
330 the postload code. This will be used for RO firmware.
331
Simon Glass89b86b82011-07-17 23:49:49 -0700332 Args:
333 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200334 fdt: Fdt object containing the flat device tree.
335 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700336
337 Returns:
338 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200339 Full path to bootstub (uboot + fdt(-1) + postload).
340 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700341
342 Raises:
343 CmdError if a command fails.
344 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200345 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass7c2d5572011-11-15 14:47:08 -0800346 text_base = self.CalcTextBase('', self.fdt, uboot)
Simon Glass89b86b82011-07-17 23:49:49 -0700347 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200348
349 # Make a copy of the fdt for the bootstub
350 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
351 fdt.PutInteger('/config/postload-text-offset', 0xffffffff);
Simon Glass290a1802011-07-17 13:54:32 -0700352 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200353
Simon Glass89b86b82011-07-17 23:49:49 -0700354 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700355 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
356 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700357 self._tools.OutputSize('Combined binary', bootstub)
358
Simon Glasse13ee2c2011-07-28 08:12:28 +1200359 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700360 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700361 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200362 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200363
364 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
365 data = self._tools.ReadFile(signed)
366
367 if postload:
368 # We must add postload to the bootstub since A and B will need to
369 # be able to find it without the /config/postload-text-offset mechanism.
370 bs_data = self._tools.ReadFile(bootstub)
371 bs_data += self._tools.ReadFile(postload)
372 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
373 self._tools.WriteFile(bootstub, bs_data)
374 self._tools.OutputSize('Combined binary with postload', bootstub)
375
376 # Now that we know the file size, adjust the fdt and re-sign
377 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
378 fdt.PutInteger('/config/postload-text-offset', len(data))
379 fdt_data = self._tools.ReadFile(fdt.fname)
380 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
381 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
382 postload_bootstub, text_base)
383 if len(data) != os.path.getsize(signed):
384 raise CmdError('Signed file size changed from %d to %d after updating '
385 'fdt' % (len(data), os.path.getsize(signed)))
386
387 # Re-read the signed image, and add the post-load binary.
388 data = self._tools.ReadFile(signed)
389 data += self._tools.ReadFile(postload)
390 self._tools.OutputSize('Post-load binary', postload)
391
392 self._tools.WriteFile(signed_postload, data)
393 self._tools.OutputSize('Final bootstub with postload', signed_postload)
394
395 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700396
Vincent Palatinf7286772011-10-12 14:31:53 -0700397 def _CreateCorebootStub(self, uboot, coreboot, fdt, seabios):
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700398 """Create a coreboot boot stub.
399
400 Args:
401 uboot: Path to u-boot.bin (may be chroot-relative)
402 coreboot: Path to coreboot.rom
403 fdt: Device Tree
Vincent Palatinf7286772011-10-12 14:31:53 -0700404 seabios: Path to SeaBIOS payload binary or None
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700405
406 Returns:
407 Full path to bootstub (coreboot + uboot + fdt).
408
409 Raises:
410 CmdError if a command fails.
411 """
412 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Stefan Reinauer17c19622011-09-16 12:47:41 -0700413 cbfstool = "/usr/bin/cbfstool"
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700414 uboot_elf = uboot.replace(".bin", ".elf")
415 shutil.copyfile(coreboot, bootstub)
Vincent Palatinf7286772011-10-12 14:31:53 -0700416 if seabios:
417 self._tools.Run(cbfstool, [bootstub, 'add-payload', seabios,
418 'fallback/payload', 'lzma'])
419 self._tools.Run(cbfstool, [bootstub, 'add-payload', uboot_elf,
420 'img/U-Boot', 'lzma'])
421 else:
422 self._tools.Run(cbfstool, [bootstub, 'add-payload', uboot_elf,
423 'fallback/payload', 'lzma'])
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700424 self._tools.Run(cbfstool, [bootstub, 'add', fdt.fname, 'u-boot.dtb',
425 '0xac'])
426 return bootstub
427
Simon Glass89b86b82011-07-17 23:49:49 -0700428 def _PackOutput(self, msg):
429 """Helper function to write output from PackFirmware (verbose level 2).
430
431 This is passed to PackFirmware for it to use to write output.
432
433 Args:
434 msg: Message to display.
435 """
436 self._out.Notice(msg)
437
Simon Glass290a1802011-07-17 13:54:32 -0700438 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700439 """Create a full firmware image, along with various by-products.
440
441 This uses the provided u-boot.bin, fdt and bct to create a firmware
442 image containing all the required parts. If the GBB is not supplied
443 then this will just return a signed U-Boot as the image.
444
445 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +1200446 gbb: Full path to the GBB file, or empty if a GBB is not required.
447 fdt: Fdt object containing required information.
448
449 Returns:
450 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700451
452 Raises:
453 CmdError if a command fails.
454 """
Simon Glass290a1802011-07-17 13:54:32 -0700455 self._out.Notice("Model: %s" % fdt.GetString('/model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700456
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700457 if self.coreboot_fname:
458 # FIXME(reinauer) the names are not too great choices.
459 # signed gets packed into the bootstub, and bootstub gets
460 # packed into the RW sections.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700461 signed = self._CreateCorebootStub(self.uboot_fname,
Vincent Palatinf7286772011-10-12 14:31:53 -0700462 self.coreboot_fname, fdt, self.seabios_fname)
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700463 bootstub = self.uboot_fname
464 else:
465 # Create the boot stub, which is U-Boot plus an fdt and bct
Simon Glass6dcc2f22011-07-28 15:26:49 +1200466 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
467 self.postload_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700468
469 if gbb:
470 pack = PackFirmware(self._tools, self._out)
471 image = os.path.join(self._tools.outdir, 'image.bin')
Hung-Te Lina7462e72011-07-27 19:17:10 +0800472 fwid = '.'.join([
473 re.sub('[ ,]+', '_', fdt.GetString('/model')),
474 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700475 self._out.Notice('Firmware ID: %s' % fwid)
476 pack.SetupFiles(boot=bootstub, signed=signed, gbb=gbb,
Simon Glass290a1802011-07-17 13:54:32 -0700477 fwid=fwid, keydir=self._keydir)
478 pack.SelectFdt(fdt)
Simon Glass89b86b82011-07-17 23:49:49 -0700479 pack.PackImage(self._tools.outdir, image)
480 else:
481 image = signed
482
483 self._tools.OutputSize('Final image', image)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200484 return image
Simon Glass89b86b82011-07-17 23:49:49 -0700485
Simon Glass290a1802011-07-17 13:54:32 -0700486 def SelectFdt(self, fdt_fname):
487 """Select an FDT to control the firmware bundling
488
489 Args:
490 fdt_fname: The filename of the fdt to use.
491
Simon Glassc0f3dc62011-08-09 14:19:05 -0700492 Returns:
493 The Fdt object of the original fdt file, which we will not modify.
494
Simon Glass290a1802011-07-17 13:54:32 -0700495 We make a copy of this which will include any on-the-fly changes we want
496 to make.
497 """
498 self._fdt_fname = fdt_fname
499 self.CheckOptions()
500 fdt = Fdt(self._tools, self._fdt_fname)
501 self.fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Simon Glassc0f3dc62011-08-09 14:19:05 -0700502 return fdt
Simon Glass290a1802011-07-17 13:54:32 -0700503
Simon Glass56577572011-07-19 11:08:06 +1200504 def Start(self, hardware_id, output_fname):
Simon Glass290a1802011-07-17 13:54:32 -0700505 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -0700506
507 - Checks options, tools, output directory, fdt.
508 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -0700509
510 Args:
Simon Glass56577572011-07-19 11:08:06 +1200511 hardware_id: Hardware ID to use for this board. If None, then the
512 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -0700513 output_fname: Output filename for the image. If this is not None, then
514 the final image will be copied here.
515
516 Returns:
517 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -0700518 """
Simon Glass89b86b82011-07-17 23:49:49 -0700519 gbb = ''
Simon Glass290a1802011-07-17 13:54:32 -0700520 if not self._small:
Simon Glass56577572011-07-19 11:08:06 +1200521 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -0700522
523 # This creates the actual image.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200524 image = self._CreateImage(gbb, self.fdt)
Simon Glass290a1802011-07-17 13:54:32 -0700525 if output_fname:
526 shutil.copyfile(image, output_fname)
527 self._out.Notice("Output image '%s'" % output_fname)
528 return image