diff options
author | Stephen Warren <swarren@nvidia.com> | 2013-06-06 23:01:34 -0600 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2013-06-06 23:01:34 -0600 |
commit | df4d86c1555bc219981ff2d56dcb75df6e0a7c44 (patch) | |
tree | 7a9c4d2b2309770d8d5e0f8e1298289b9bbca628 /tegra-uboot-flasher | |
download | tegra-uboot-flasher-scripts-df4d86c1555bc219981ff2d56dcb75df6e0a7c44.tar.gz |
Initial version of Tegra U-Boot flasher scripts
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'tegra-uboot-flasher')
-rwxr-xr-x | tegra-uboot-flasher | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/tegra-uboot-flasher b/tegra-uboot-flasher new file mode 100755 index 0000000..ecc7ac8 --- /dev/null +++ b/tegra-uboot-flasher @@ -0,0 +1,243 @@ +#!/usr/bin/env python + +# Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +import argparse +import os +import os.path +import shutil +import stat +import sys +import tempfile +from tegraboardconfigs import * + +parser = argparse.ArgumentParser(description='Write an image to a Tegra board\'s flash') +parser.add_argument('--debug', action='store_true', + help='Turn on debugging prints') +parser.add_argument('--data-dir', type=str, + help='The directory containing board data') +parser.add_argument('--work-dir', type=str, + help='The temporary directory used during operation') +parser.add_argument('--save-work-dir', action='store_true', + help='Don\'t delete the work-dir after execution') +parser.add_argument('--flash-image', type=str, + help='The flash image to write, instead of U-Boot itself') +parser.add_argument('--gen-only', action='store_true', + help='Just create the work-dir; don\'t actually flash the image') +parser.add_argument('--force-no-out-dir', action='store_true', + help='Don\'t check for ../_out* directories used in source tree') +group = parser.add_mutually_exclusive_group(required=True) +group.add_argument('--list-confignames', action='store_true', + help='List known configuration names, and exit') +group.add_argument('configname', type=str, nargs='?', + help='The configuration name of the board') +args = parser.parse_args() +if args.debug: print args + +scripts_dir = os.path.dirname(os.path.abspath(__file__)) +scripts_parent_dir = os.path.dirname(scripts_dir) + +if not args.force_no_out_dir: + out_tools_dir = os.path.abspath(os.path.join(scripts_parent_dir, '_out_tools')) + if os.path.exists(out_tools_dir): + if args.debug: print 'Detected build tree; adding ' + out_tools_dir + ' to $PATH' + os.environ['PATH'] = out_tools_dir + ':' + os.environ['PATH'] + +if not args.data_dir and not args.force_no_out_dir: + out_data_dir = os.path.abspath(os.path.join(scripts_parent_dir, '_out')) + if os.path.exists(out_data_dir): + if args.debug: print 'Detected build tree; using ' + out_data_dir + ' as data dir' + args.data_dir = out_data_dir +if not args.data_dir: + data_dir = '/usr/share/tegra_uboot_flasher' + +load_configs(os.path.join(args.data_dir, 'configs')) + +if args.list_confignames: + for configname in sorted(configs.keys()): + print configname + sys.exit(0) + +if not configs.has_key(args.configname): + print 'Unknown config "%s"' % args.configname + sys.exit(1) + +boardname = configs[args.configname]['board'] +socname = boards[boardname]['soc'] + +out_board_dir = os.path.join(args.data_dir, boardname) + +u_boot_no_dtb = os.path.join(out_board_dir, 'u-boot-nodtb-tegra.bin') +u_boot_no_dtb_size = os.path.getsize(u_boot_no_dtb) +if args.debug: + print 'u_boot_no_dtb_size %d 0x%x' % (u_boot_no_dtb_size, u_boot_no_dtb_size) + +u_boot_dtb = os.path.join(out_board_dir, 'u-boot.dtb') +u_boot_dtb_size = os.path.getsize(u_boot_dtb) +if args.debug: + print 'u_boot_dtb_size %d 0x%x' % (u_boot_dtb_size, u_boot_dtb_size) + +if args.flash_image: + flash_img = args.flash_img +else: + flash_img = os.path.join(out_board_dir, configs[args.configname]['flash-image']) +flash_img_size = os.path.getsize(flash_img) +if args.debug: + print 'flash_img_size %d 0x%x' % (flash_img_size, flash_img_size) + +bct = os.path.join(out_board_dir, configs[args.configname]['bct']) + +u_boot_plus_dtb_size = u_boot_no_dtb_size + u_boot_dtb_size +if args.debug: + print 'u_boot_plus_dtb_size %d 0x%x' % (u_boot_plus_dtb_size, u_boot_plus_dtb_size) + +# Add 32k in case size changes due to fdtput +# Align to 4k, so flash writes don't need a bounce buffer for DMA +padded_size = (u_boot_plus_dtb_size + (32 * 1024) + (4 * 1024) - 1) & ~((4 * 1024) - 1) +if args.debug: + print 'padded_size %d 0x%x' % (padded_size, padded_size) + +pad_size = padded_size - u_boot_plus_dtb_size +if args.debug: + print 'pad_size %d 0x%x' % (pad_size, pad_size) + +# 0x00108000 is CONFIG_SYS_TEXT_BASE in U-Boot, minus RAM base +loadaddr = socs[socname]['ram-base'] + 0x00108000 +flash_image_addr = loadaddr + padded_size +if args.debug: + print 'flash_image_addr %d 0x%x' % (flash_image_addr, flash_image_addr) + +def mkdir(path): + if not os.path.isdir(path): + os.makedirs(path) + +def cp(src, dst): + print '+ cp', src, dst + shutil.copy(src, dst) + +def rmtree(path): + if os.path.exists(path): + shutil.rmtree(path) + +def run(dir, cmd): + oldcwd = os.getcwd() + print '+ cd', dir + os.chdir(dir) + print '+', cmd + ret = os.system(cmd) + if ret: + raise Exception('Command failed: %d' % ret) + os.chdir(oldcwd) + +def gen_flashcmd_mmc(): + flash_id = configs[args.configname]['flash-id-uboot'] + flash_img_size_sectors = flash_img_size / 512 + flashcmd = 'mmc dev %d 1 ; ' % flash_id + flashcmd += 'mmc write 0x%08x 0 0x%x ; ' % (flash_image_addr, flash_img_size_sectors) + return flashcmd + +def gen_flashcmd_nand(): + flashcmd = 'nand erase.chip ; ' + flashcmd += 'nand write 0x%08x 0 0x%08x ; ' % (flash_image_addr, flash_img_size) + return flashcmd + +def gen_flashcmd_spi(): + flashcmd = 'sf probe 0 ; ' + flashcmd += 'sf erase 0 0x%08x ; ' % configs[args.configname]['flash-erase-size'] + flashcmd += 'sf write 0x%08x 0 0x%08x ; ' % (flash_image_addr, flash_img_size) + return flashcmd + +gen_flashcmds = { + 'emmc': gen_flashcmd_mmc, + 'nand': gen_flashcmd_nand, + 'spi': gen_flashcmd_spi, +} + +flash_type = configs[args.configname]['flash-type'] +if not gen_flashcmds.has_key(flash_type): + print 'flash-type "%s" not yet supported' % flash_type + sys.exit(1) +gen_flashcmd = gen_flashcmds[flash_type] + +if args.work_dir: + workdir = os.path.abspath(args.work_dir) + mkdir(workdir) +else: + workdir = tempfile.mkdtemp() +try: + u_boot_dtb_runflash = os.path.join(workdir, 'u-boot-runflash.dtb') + cp(u_boot_dtb, u_boot_dtb_runflash) + + # -2; never delay or interrupt + cmd = 'fdtput -p -t i ' + u_boot_dtb_runflash + ' /config bootdelay 0xfffffffe' + run(workdir, cmd) + + bootcmd = '' + if args.debug: + bootcmd = 'crc32 0x%08x 0x%08x ; ' % (flash_image_addr, flash_img_size) + bootcmd += gen_flashcmd() + bootcmd += 'env default -f -a ; ' + # Perhaps U-Boot should set $boardname based on the ID EEPROM; then we wouldn't need this + if configs[args.configname]['dtbfn-extra'] != '': + bootcmd += 'setenv board ' + boardname + configs[args.configname]['dtbfn-extra'] + ' ; ' + bootcmd += 'saveenv ; ' + # To update the bootloader, reset. + # If wanting to run installer, set installer_args.configname in environment, 'run bootcmd' + bootcmd += 'reset' + print 'bootcmd:', bootcmd + cmd = 'fdtput -p -t s ' + u_boot_dtb_runflash + ' /config bootcmd "' + bootcmd + '"' + run(workdir, cmd) + + u_boot_dtb_runflash_size = os.path.getsize(u_boot_dtb_runflash) + if args.debug: + print 'u_boot_dtb_runflash_size %d 0x%x' % (u_boot_dtb_runflash_size, u_boot_dtb_runflash_size) + pad_size -= (u_boot_dtb_runflash_size - u_boot_dtb_size) + if args.debug: + print 'pad_size %d 0x%x' % (pad_size, pad_size) + + uboot_flasher = os.path.join(workdir, 'u-boot-flasher.bin') + f = open(uboot_flasher, 'wb') + shutil.copyfileobj(open(u_boot_no_dtb, 'rb'), f) + shutil.copyfileobj(open(u_boot_dtb_runflash, 'rb'), f) + f.write(chr(0) * pad_size) + shutil.copyfileobj(open(flash_img, 'rb'), f) + f.close() + + cmd = 'tegrarcm --bct=' + bct + ' --bootloader=' + uboot_flasher + ' --loadaddr=0x%08x' % loadaddr + + flasher_sh = os.path.join(workdir, 'flasher.sh') + f = open(flasher_sh, 'wt') + os.fchmod(f.fileno(), stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) + f.write("#!/bin/sh\n") + f.write("\n") + f.write(cmd) + f.write("\n") + f.close() + + if not args.gen_only: + run(workdir, flasher_sh) +except: + raise +finally: + if args.save_work_dir: + print 'Not removing work directory:', workdir + else: + rmtree(workdir) |