summaryrefslogtreecommitdiff
path: root/tegra-uboot-flasher
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-06-06 23:01:34 -0600
committerStephen Warren <swarren@nvidia.com>2013-06-06 23:01:34 -0600
commitdf4d86c1555bc219981ff2d56dcb75df6e0a7c44 (patch)
tree7a9c4d2b2309770d8d5e0f8e1298289b9bbca628 /tegra-uboot-flasher
downloadtegra-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-xtegra-uboot-flasher243
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)