blob: 09b064822c25edc25a3229833bd43866af89638a [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
26import tempfile
27from tools import Tools
28from write_firmware import WriteFirmware
29
30# This data is required by bmpblk_utility. Does it ever change?
31# It was stored with the chromeos-bootimage ebuild, but we want
32# this utility to work outside the chroot.
33yaml_data = '''
34bmpblock: 1.0
35
36images:
37 devmode: DeveloperBmp/DeveloperBmp.bmp
38 recovery: RecoveryBmp/RecoveryBmp.bmp
39 rec_yuck: RecoveryNoOSBmp/RecoveryNoOSBmp.bmp
40 rec_insert: RecoveryMissingOSBmp/RecoveryMissingOSBmp.bmp
41
42screens:
43 dev_en:
44 - [0, 0, devmode]
45 rec_en:
46 - [0, 0, recovery]
47 yuck_en:
48 - [0, 0, rec_yuck]
49 ins_en:
50 - [0, 0, rec_insert]
51
52localizations:
53 - [ dev_en, rec_en, yuck_en, ins_en ]
54'''
55
56class Bundle:
Simon Glass290a1802011-07-17 13:54:32 -070057 """This class encapsulates the entire bundle firmware logic.
Simon Glass89b86b82011-07-17 23:49:49 -070058
Simon Glass290a1802011-07-17 13:54:32 -070059 Sequence of events:
60 bundle = Bundle(tools.Tools(), cros_output.Output())
61 bundle.SetDirs(...)
62 bundle.SetFiles(...)
63 bundle.SetOptions(...)
64 bundle.SelectFdt(fdt.Fdt('filename.dtb')
65 .. can call bundle.AddConfigList() if required
66 bundle.Start(...)
Simon Glass89b86b82011-07-17 23:49:49 -070067
Simon Glass290a1802011-07-17 13:54:32 -070068 Public properties:
69 fdt: The fdt object that we use for building our image. This wil be the
70 one specified by the user, except that we might add config options
71 to it. This is set up by SelectFdt() which must be called before
72 bundling starts.
73 uboot_fname: Full filename of the U-Boot binary we use.
74 bct_fname: Full filename of the BCT file we use.
75 """
Simon Glass89b86b82011-07-17 23:49:49 -070076
Simon Glass290a1802011-07-17 13:54:32 -070077 def __init__(self, tools, output):
78 """Set up a new Bundle object.
Simon Glass89b86b82011-07-17 23:49:49 -070079
Simon Glass290a1802011-07-17 13:54:32 -070080 Args:
81 tools: A tools.Tools object to use for external tools.
82 output: A cros_output.Output object to use for program output.
Simon Glass89b86b82011-07-17 23:49:49 -070083 """
Simon Glass290a1802011-07-17 13:54:32 -070084 self.text_base = None # Base of U-Boot image in memory
85
86 self._tools = tools
87 self._out = output
88
89 # Set up the things we need to know in order to operate.
90 self._board = None # Board name, e.g. tegra2_seaboard.
91 self._fdt_fname = None # Filename of our FDT.
92 self.uboot_fname = None # Filename of our U-Boot binary.
93 self.bct_fname = None # Filename of our BCT file.
94 self.fdt = None # Our Fdt object.
Hung-Te Lin5b649382011-08-03 15:01:16 +080095 self.bmpblk_fname = None # Filename of our Bitmap Block
Stefan Reinauer8d79d362011-08-16 14:20:43 -070096 self.coreboot_fname = None # Filename of our coreboot binary.
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,
107 postload=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.
Simon Glass290a1802011-07-17 13:54:32 -0700117 """
118 self._board = board
119 self.uboot_fname = uboot
120 self.bct_fname = bct
Hung-Te Lin5b649382011-08-03 15:01:16 +0800121 self.bmpblk_fname = bmpblk
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700122 self.coreboot_fname = coreboot
Simon Glass6dcc2f22011-07-28 15:26:49 +1200123 self.postload_fname = postload
Simon Glass290a1802011-07-17 13:54:32 -0700124
125 def SetOptions(self, small):
126 """Set up options supported by Bundle.
127
128 Args:
129 small: Only create a signed U-Boot - don't produce the full packed
130 firmware image. This is useful for devs who want to replace just the
131 U-Boot part while keeping the keys, gbb, etc. the same.
132 """
133 self._small = small
134
135 def CheckOptions(self):
136 """Check provided options and select defaults."""
137 if not self._board:
138 raise ValueError('No board defined - please define a board to use')
Simon Glass493163b2011-09-14 11:19:57 -0700139 build_root = os.path.join('##', 'build', self._board, 'firmware')
Simon Glass290a1802011-07-17 13:54:32 -0700140 if not self._fdt_fname:
141 self._fdt_fname = os.path.join(build_root, 'dtb', '%s.dtb' %
142 re.sub('_', '-', self._board))
143 if not self.uboot_fname:
144 self.uboot_fname = os.path.join(build_root, 'u-boot.bin')
145 if not self.bct_fname:
146 self.bct_fname = os.path.join(build_root, 'bct', 'board.bct')
Simon Glass2a7f0b32011-08-26 11:25:17 -0700147 if not self.bmpblk_fname:
148 self.bmpblk_fname = os.path.join(build_root, 'default.bmpblk')
Simon Glass89b86b82011-07-17 23:49:49 -0700149
Simon Glass56577572011-07-19 11:08:06 +1200150 def _CreateGoogleBinaryBlock(self, hardware_id):
Simon Glass89b86b82011-07-17 23:49:49 -0700151 """Create a GBB for the image.
152
Simon Glass56577572011-07-19 11:08:06 +1200153 Args:
154 hardware_id: Hardware ID to use for this board. If None, then the
155 default from the Fdt will be used
156
Simon Glass89b86b82011-07-17 23:49:49 -0700157 Returns:
158 Path of the created GBB file.
159
160 Raises:
161 CmdError if a command fails.
162 """
Simon Glass56577572011-07-19 11:08:06 +1200163 if not hardware_id:
164 hardware_id = self.fdt.GetString('/config/hwid')
Simon Glass89b86b82011-07-17 23:49:49 -0700165 gbb_size = self.fdt.GetFlashPartSize('ro', 'gbb')
Simon Glass290a1802011-07-17 13:54:32 -0700166 odir = self._tools.outdir
Simon Glass89b86b82011-07-17 23:49:49 -0700167
Simon Glass89b86b82011-07-17 23:49:49 -0700168 self._out.Progress('Creating GBB')
169 sizes = [0x100, 0x1000, gbb_size - 0x2180, 0x1000]
170 sizes = ['%#x' % size for size in sizes]
171 gbb = 'gbb.bin'
Simon Glass290a1802011-07-17 13:54:32 -0700172 keydir = self._tools.Filename(self._keydir)
173 self._tools.Run('gbb_utility', ['-c', ','.join(sizes), gbb], cwd=odir)
Simon Glass89b86b82011-07-17 23:49:49 -0700174 self._tools.Run('gbb_utility', ['-s',
Simon Glass56577572011-07-19 11:08:06 +1200175 '--hwid=%s' % hardware_id,
Simon Glass89b86b82011-07-17 23:49:49 -0700176 '--rootkey=%s/root_key.vbpubk' % keydir,
177 '--recoverykey=%s/recovery_key.vbpubk' % keydir,
Simon Glass2a7f0b32011-08-26 11:25:17 -0700178 '--bmpfv=%s' % self._tools.Filename(self.bmpblk_fname),
Simon Glass89b86b82011-07-17 23:49:49 -0700179 gbb],
Simon Glass290a1802011-07-17 13:54:32 -0700180 cwd=odir)
181 return os.path.join(odir, gbb)
Simon Glass89b86b82011-07-17 23:49:49 -0700182
Simon Glasse13ee2c2011-07-28 08:12:28 +1200183 def _SignBootstub(self, bct, bootstub, text_base):
Simon Glass89b86b82011-07-17 23:49:49 -0700184 """Sign an image so that the Tegra SOC will boot it.
185
186 Args:
187 bct: BCT file to use.
188 bootstub: Boot stub (U-Boot + fdt) file to sign.
189 text_base: Address of text base for image.
Simon Glass89b86b82011-07-17 23:49:49 -0700190
191 Returns:
192 filename of signed image.
193
194 Raises:
195 CmdError if a command fails.
196 """
197 # First create a config file - this is how we instruct cbootimage
Simon Glasse13ee2c2011-07-28 08:12:28 +1200198 signed = os.path.join(self._tools.outdir, 'signed.bin')
Simon Glass89b86b82011-07-17 23:49:49 -0700199 self._out.Progress('Signing Bootstub')
Simon Glasse13ee2c2011-07-28 08:12:28 +1200200 config = os.path.join(self._tools.outdir, 'boot.cfg')
Simon Glass89b86b82011-07-17 23:49:49 -0700201 fd = open(config, 'w')
202 fd.write('Version = 1;\n')
203 fd.write('Redundancy = 1;\n')
204 fd.write('Bctfile = %s;\n' % bct)
Doug Anderson0eeb0742011-09-15 18:11:40 -0700205
206 # TODO(dianders): Right now, we don't have enough space in our flash map
207 # for two copies of the BCT when we're using NAND, so hack it to 1. Not
208 # sure what this does for reliability, but at least things will fit...
209 is_nand = "NvBootDevType_Nand" in self._tools.Run('bct_dump', [bct])
210 if is_nand:
211 fd.write('Bctcopy = 1;\n')
212
Simon Glass89b86b82011-07-17 23:49:49 -0700213 fd.write('BootLoader = %s,%#x,%#x,Complete;\n' % (bootstub, text_base,
214 text_base))
Doug Anderson0eeb0742011-09-15 18:11:40 -0700215
Simon Glass89b86b82011-07-17 23:49:49 -0700216 fd.close()
217
218 self._tools.Run('cbootimage', [config, signed])
219 self._tools.OutputSize('BCT', bct)
220 self._tools.OutputSize('Signed image', signed)
221 return signed
222
Doug Anderson86ce5f42011-07-27 10:40:18 -0700223 def SetBootcmd(self, bootcmd, bootsecure):
Simon Glass290a1802011-07-17 13:54:32 -0700224 """Set the boot command for U-Boot.
Simon Glass89b86b82011-07-17 23:49:49 -0700225
226 Args:
Simon Glass290a1802011-07-17 13:54:32 -0700227 bootcmd: Boot command to use, as a string (if None this this is a nop).
Doug Anderson86ce5f42011-07-27 10:40:18 -0700228 bootsecure: We'll set '/config/bootsecure' to 1 if True and 0 if False.
Simon Glass89b86b82011-07-17 23:49:49 -0700229 """
Simon Glass290a1802011-07-17 13:54:32 -0700230 if bootcmd:
Simon Glassb4447fd2011-07-26 11:18:25 +1200231 self.fdt.PutString('/config/bootcmd', bootcmd)
Doug Anderson86ce5f42011-07-27 10:40:18 -0700232 self.fdt.PutInteger('/config/bootsecure', int(bootsecure))
Simon Glass290a1802011-07-17 13:54:32 -0700233 self._out.Info('Boot command: %s' % bootcmd)
Simon Glass89b86b82011-07-17 23:49:49 -0700234
Simon Glass290a1802011-07-17 13:54:32 -0700235 def AddConfigList(self, config_list, use_int=False):
236 """Add a list of config items to the fdt.
237
238 Normally these values are written to the fdt as strings, but integers
239 are also supported, in which case the values will be converted to integers
240 (if necessary) before being stored.
241
242 Args:
243 config_list: List of (config, value) tuples to add to the fdt. For each
244 tuple:
245 config: The fdt node to write to will be /config/<config>.
246 value: An integer or string value to write.
247 use_int: True to only write integer values.
248
249 Raises:
250 CmdError: if a value is required to be converted to integer but can't be.
251 """
252 if config_list:
253 for config in config_list:
254 value = config[1]
255 if use_int:
256 try:
257 value = int(value)
258 except ValueError as str:
259 raise CmdError("Cannot convert config option '%s' to integer" %
260 value)
261 if type(value) == type(1):
262 self.fdt.PutInteger('/config/%s' % config[0], value)
263 else:
264 self.fdt.PutString('/config/%s' % config[0], value)
265
Simon Glass6dcc2f22011-07-28 15:26:49 +1200266 def _CreateBootStub(self, uboot, base_fdt, postload):
Simon Glass89b86b82011-07-17 23:49:49 -0700267 """Create a boot stub and a signed boot stub.
268
Simon Glass6dcc2f22011-07-28 15:26:49 +1200269 For postload:
270 We add a /config/postload-text-offset entry to the signed bootstub's
271 fdt so that U-Boot can find the postload code.
272
273 The raw (unsigned) bootstub will have a value of -1 for this since we will
274 simply append the postload code to the bootstub and it can find it there.
275 This will be used for RW A/B firmware.
276
277 For the signed case this value will specify where in the flash to find
278 the postload code. This will be used for RO firmware.
279
Simon Glass89b86b82011-07-17 23:49:49 -0700280 Args:
281 uboot: Path to u-boot.bin (may be chroot-relative)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200282 fdt: Fdt object containing the flat device tree.
283 postload: Path to u-boot-post.bin, or None if none.
Simon Glass89b86b82011-07-17 23:49:49 -0700284
285 Returns:
286 Tuple containing:
Simon Glass6dcc2f22011-07-28 15:26:49 +1200287 Full path to bootstub (uboot + fdt(-1) + postload).
288 Full path to signed (uboot + fdt(flash pos) + bct) + postload.
Simon Glass89b86b82011-07-17 23:49:49 -0700289
290 Raises:
291 CmdError if a command fails.
292 """
Simon Glasse13ee2c2011-07-28 08:12:28 +1200293 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt.bin')
Simon Glass290a1802011-07-17 13:54:32 -0700294 text_base = self.fdt.GetInt('/chromeos-config/textbase');
Simon Glass89b86b82011-07-17 23:49:49 -0700295 uboot_data = self._tools.ReadFile(uboot)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200296
297 # Make a copy of the fdt for the bootstub
298 fdt = base_fdt.Copy(os.path.join(self._tools.outdir, 'bootstub.dtb'))
299 fdt.PutInteger('/config/postload-text-offset', 0xffffffff);
Simon Glass290a1802011-07-17 13:54:32 -0700300 fdt_data = self._tools.ReadFile(fdt.fname)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200301
Simon Glass89b86b82011-07-17 23:49:49 -0700302 self._tools.WriteFile(bootstub, uboot_data + fdt_data)
Simon Glass290a1802011-07-17 13:54:32 -0700303 self._tools.OutputSize('U-Boot binary', self.uboot_fname)
304 self._tools.OutputSize('U-Boot fdt', self._fdt_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700305 self._tools.OutputSize('Combined binary', bootstub)
306
Simon Glasse13ee2c2011-07-28 08:12:28 +1200307 # Sign the bootstub; this is a combination of the board specific
Simon Glass89b86b82011-07-17 23:49:49 -0700308 # bct and the stub u-boot image.
Simon Glass290a1802011-07-17 13:54:32 -0700309 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
Simon Glasse13ee2c2011-07-28 08:12:28 +1200310 bootstub, text_base)
Simon Glass6dcc2f22011-07-28 15:26:49 +1200311
312 signed_postload = os.path.join(self._tools.outdir, 'signed-postload.bin')
313 data = self._tools.ReadFile(signed)
314
315 if postload:
316 # We must add postload to the bootstub since A and B will need to
317 # be able to find it without the /config/postload-text-offset mechanism.
318 bs_data = self._tools.ReadFile(bootstub)
319 bs_data += self._tools.ReadFile(postload)
320 bootstub = os.path.join(self._tools.outdir, 'u-boot-fdt-postload.bin')
321 self._tools.WriteFile(bootstub, bs_data)
322 self._tools.OutputSize('Combined binary with postload', bootstub)
323
324 # Now that we know the file size, adjust the fdt and re-sign
325 postload_bootstub = os.path.join(self._tools.outdir, 'postload.bin')
326 fdt.PutInteger('/config/postload-text-offset', len(data))
327 fdt_data = self._tools.ReadFile(fdt.fname)
328 self._tools.WriteFile(postload_bootstub, uboot_data + fdt_data)
329 signed = self._SignBootstub(self._tools.Filename(self.bct_fname),
330 postload_bootstub, text_base)
331 if len(data) != os.path.getsize(signed):
332 raise CmdError('Signed file size changed from %d to %d after updating '
333 'fdt' % (len(data), os.path.getsize(signed)))
334
335 # Re-read the signed image, and add the post-load binary.
336 data = self._tools.ReadFile(signed)
337 data += self._tools.ReadFile(postload)
338 self._tools.OutputSize('Post-load binary', postload)
339
340 self._tools.WriteFile(signed_postload, data)
341 self._tools.OutputSize('Final bootstub with postload', signed_postload)
342
343 return bootstub, signed_postload
Simon Glass89b86b82011-07-17 23:49:49 -0700344
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700345 def _CreateCorebootStub(self, uboot, coreboot, fdt):
346 """Create a coreboot boot stub.
347
348 Args:
349 uboot: Path to u-boot.bin (may be chroot-relative)
350 coreboot: Path to coreboot.rom
351 fdt: Device Tree
352
353 Returns:
354 Full path to bootstub (coreboot + uboot + fdt).
355
356 Raises:
357 CmdError if a command fails.
358 """
359 bootstub = os.path.join(self._tools.outdir, 'coreboot-full.rom')
Stefan Reinauer17c19622011-09-16 12:47:41 -0700360 cbfstool = "/usr/bin/cbfstool"
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700361 uboot_elf = uboot.replace(".bin", ".elf")
362 shutil.copyfile(coreboot, bootstub)
363 self._tools.Run(cbfstool, [bootstub, 'add-payload', uboot_elf,
364 'fallback/payload', 'lzma'])
365 self._tools.Run(cbfstool, [bootstub, 'add', fdt.fname, 'u-boot.dtb',
366 '0xac'])
367 return bootstub
368
Simon Glass89b86b82011-07-17 23:49:49 -0700369 def _PackOutput(self, msg):
370 """Helper function to write output from PackFirmware (verbose level 2).
371
372 This is passed to PackFirmware for it to use to write output.
373
374 Args:
375 msg: Message to display.
376 """
377 self._out.Notice(msg)
378
Simon Glass290a1802011-07-17 13:54:32 -0700379 def _CreateImage(self, gbb, fdt):
Simon Glass89b86b82011-07-17 23:49:49 -0700380 """Create a full firmware image, along with various by-products.
381
382 This uses the provided u-boot.bin, fdt and bct to create a firmware
383 image containing all the required parts. If the GBB is not supplied
384 then this will just return a signed U-Boot as the image.
385
386 Args:
Simon Glasse13ee2c2011-07-28 08:12:28 +1200387 gbb: Full path to the GBB file, or empty if a GBB is not required.
388 fdt: Fdt object containing required information.
389
390 Returns:
391 Path to image file
Simon Glass89b86b82011-07-17 23:49:49 -0700392
393 Raises:
394 CmdError if a command fails.
395 """
Simon Glass290a1802011-07-17 13:54:32 -0700396 self._out.Notice("Model: %s" % fdt.GetString('/model'))
Simon Glass89b86b82011-07-17 23:49:49 -0700397
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700398 if self.coreboot_fname:
399 # FIXME(reinauer) the names are not too great choices.
400 # signed gets packed into the bootstub, and bootstub gets
401 # packed into the RW sections.
Stefan Reinauerc2e1e4d2011-08-23 14:50:59 -0700402 signed = self._CreateCorebootStub(self.uboot_fname,
403 self.coreboot_fname, fdt)
Stefan Reinauer8d79d362011-08-16 14:20:43 -0700404 bootstub = self.uboot_fname
405 else:
406 # Create the boot stub, which is U-Boot plus an fdt and bct
Simon Glass6dcc2f22011-07-28 15:26:49 +1200407 bootstub, signed = self._CreateBootStub(self.uboot_fname, fdt,
408 self.postload_fname)
Simon Glass89b86b82011-07-17 23:49:49 -0700409
410 if gbb:
411 pack = PackFirmware(self._tools, self._out)
412 image = os.path.join(self._tools.outdir, 'image.bin')
Hung-Te Lina7462e72011-07-27 19:17:10 +0800413 fwid = '.'.join([
414 re.sub('[ ,]+', '_', fdt.GetString('/model')),
415 self._tools.GetChromeosVersion()])
Simon Glass89b86b82011-07-17 23:49:49 -0700416 self._out.Notice('Firmware ID: %s' % fwid)
417 pack.SetupFiles(boot=bootstub, signed=signed, gbb=gbb,
Simon Glass290a1802011-07-17 13:54:32 -0700418 fwid=fwid, keydir=self._keydir)
419 pack.SelectFdt(fdt)
Simon Glass89b86b82011-07-17 23:49:49 -0700420 pack.PackImage(self._tools.outdir, image)
421 else:
422 image = signed
423
424 self._tools.OutputSize('Final image', image)
Simon Glasse13ee2c2011-07-28 08:12:28 +1200425 return image
Simon Glass89b86b82011-07-17 23:49:49 -0700426
Simon Glass290a1802011-07-17 13:54:32 -0700427 def SelectFdt(self, fdt_fname):
428 """Select an FDT to control the firmware bundling
429
430 Args:
431 fdt_fname: The filename of the fdt to use.
432
Simon Glassc0f3dc62011-08-09 14:19:05 -0700433 Returns:
434 The Fdt object of the original fdt file, which we will not modify.
435
Simon Glass290a1802011-07-17 13:54:32 -0700436 We make a copy of this which will include any on-the-fly changes we want
437 to make.
438 """
439 self._fdt_fname = fdt_fname
440 self.CheckOptions()
441 fdt = Fdt(self._tools, self._fdt_fname)
442 self.fdt = fdt.Copy(os.path.join(self._tools.outdir, 'updated.dtb'))
Simon Glassc0f3dc62011-08-09 14:19:05 -0700443 return fdt
Simon Glass290a1802011-07-17 13:54:32 -0700444
Simon Glass56577572011-07-19 11:08:06 +1200445 def Start(self, hardware_id, output_fname):
Simon Glass290a1802011-07-17 13:54:32 -0700446 """This creates a firmware bundle according to settings provided.
Simon Glass89b86b82011-07-17 23:49:49 -0700447
448 - Checks options, tools, output directory, fdt.
449 - Creates GBB and image.
Simon Glass290a1802011-07-17 13:54:32 -0700450
451 Args:
Simon Glass56577572011-07-19 11:08:06 +1200452 hardware_id: Hardware ID to use for this board. If None, then the
453 default from the Fdt will be used
Simon Glass290a1802011-07-17 13:54:32 -0700454 output_fname: Output filename for the image. If this is not None, then
455 the final image will be copied here.
456
457 Returns:
458 Filename of the resulting image (not the output_fname copy).
Simon Glass89b86b82011-07-17 23:49:49 -0700459 """
Simon Glass89b86b82011-07-17 23:49:49 -0700460 gbb = ''
Simon Glass290a1802011-07-17 13:54:32 -0700461 if not self._small:
Simon Glass56577572011-07-19 11:08:06 +1200462 gbb = self._CreateGoogleBinaryBlock(hardware_id)
Simon Glass89b86b82011-07-17 23:49:49 -0700463
464 # This creates the actual image.
Simon Glasse13ee2c2011-07-28 08:12:28 +1200465 image = self._CreateImage(gbb, self.fdt)
Simon Glass290a1802011-07-17 13:54:32 -0700466 if output_fname:
467 shutil.copyfile(image, output_fname)
468 self._out.Notice("Output image '%s'" % output_fname)
469 return image