| 1 | #!/usr/bin/env python |
|---|
| 2 | |
|---|
| 3 | from __future__ import division |
|---|
| 4 | import sys |
|---|
| 5 | import os.path |
|---|
| 6 | import struct |
|---|
| 7 | |
|---|
| 8 | nxt_path = os.path.join( |
|---|
| 9 | os.path.split(os.path.abspath(__file__))[0], '..', 'pynxt') |
|---|
| 10 | sys.path = [nxt_path]+sys.path |
|---|
| 11 | |
|---|
| 12 | import nxt |
|---|
| 13 | import nxt.samba |
|---|
| 14 | import nxt.flash |
|---|
| 15 | |
|---|
| 16 | USAGE = ''' |
|---|
| 17 | Syntax: %(n)s <kernel binary file> |
|---|
| 18 | %(n)s <kernel name> <boot type> |
|---|
| 19 | |
|---|
| 20 | Examples: |
|---|
| 21 | %(n)s systems/tests/tests_samba.bin |
|---|
| 22 | %(n)s tests rom |
|---|
| 23 | '''.strip() |
|---|
| 24 | |
|---|
| 25 | STATUS_REPORT = ''' |
|---|
| 26 | Kernel %s: |
|---|
| 27 | * In-RAM size: %s |
|---|
| 28 | * In-ROM size: %s |
|---|
| 29 | * Wasted RAM: %s |
|---|
| 30 | * Load address: 0x%x |
|---|
| 31 | * Boot method: %s |
|---|
| 32 | '''.strip() |
|---|
| 33 | |
|---|
| 34 | def kernel_path_from_name(name, variant): |
|---|
| 35 | return 'systems/%s/%s_%s.bin' % (name, name, variant) |
|---|
| 36 | |
|---|
| 37 | def get_kernel(): |
|---|
| 38 | if len(sys.argv) not in (2,3): |
|---|
| 39 | print USAGE % {'n': sys.argv[0]} |
|---|
| 40 | return (None, None, None) |
|---|
| 41 | if len(sys.argv) == 3: |
|---|
| 42 | kernel_file = kernel_path_from_name(sys.argv[1], sys.argv[2]) |
|---|
| 43 | else: |
|---|
| 44 | kernel_file = sys.argv[1] |
|---|
| 45 | |
|---|
| 46 | if not os.path.isfile(kernel_file): |
|---|
| 47 | print 'Kernel image %s not found.' % kernel_file |
|---|
| 48 | return (None, None, None) |
|---|
| 49 | |
|---|
| 50 | # Load the firmware image, and separate the header from the actual |
|---|
| 51 | # image. |
|---|
| 52 | f = open(kernel_file) |
|---|
| 53 | fw_and_header = f.read() |
|---|
| 54 | f.close() |
|---|
| 55 | header = fw_and_header[-21:] |
|---|
| 56 | fw = fw_and_header[:-21] |
|---|
| 57 | |
|---|
| 58 | header = struct.unpack('<5LB', header) |
|---|
| 59 | if header[0] != 0xDEADBEEF: |
|---|
| 60 | print 'Invalid magic on kernel image, cannot process.' |
|---|
| 61 | return (None, None, None) |
|---|
| 62 | return (kernel_file, header, fw) |
|---|
| 63 | |
|---|
| 64 | def format_number(size): |
|---|
| 65 | if size < 1024: |
|---|
| 66 | return '%dB' % size |
|---|
| 67 | else: |
|---|
| 68 | return '%.2fkB' % (size/1024) |
|---|
| 69 | |
|---|
| 70 | def main(): |
|---|
| 71 | filename, header, fw = get_kernel() |
|---|
| 72 | if fw is None: |
|---|
| 73 | return 1 |
|---|
| 74 | (_, ramsize, ramwaste, romsize, loadaddr, samba) = header |
|---|
| 75 | print STATUS_REPORT % (filename, format_number(ramsize), |
|---|
| 76 | format_number(romsize), format_number(ramwaste), |
|---|
| 77 | loadaddr, {0:'Flash Boot', 1:'SAM-BA Boot'}[samba]) |
|---|
| 78 | print |
|---|
| 79 | a = raw_input('Boot? [Y/n] ').lower() |
|---|
| 80 | while a not in ('', 'y', 'n', 'yes', 'no'): |
|---|
| 81 | a = raw_input('Boot? [Y/n] ').lower() |
|---|
| 82 | if a in ('no', 'n'): |
|---|
| 83 | return 0 |
|---|
| 84 | |
|---|
| 85 | s = nxt.samba.SambaBrick() |
|---|
| 86 | try: |
|---|
| 87 | print 'Looking for the NXT in SAM-BA mode...' |
|---|
| 88 | s.open(timeout=60) |
|---|
| 89 | print 'Brick found!' |
|---|
| 90 | except nxt.samba.SambaOpenError, e: |
|---|
| 91 | print 'Error: %s.' % str(e) |
|---|
| 92 | return 1 |
|---|
| 93 | except KeyboardInterrupt: |
|---|
| 94 | print 'Cancelled.' |
|---|
| 95 | return 0 |
|---|
| 96 | |
|---|
| 97 | if samba: |
|---|
| 98 | print 'Uploading firmware...', |
|---|
| 99 | s.write_buffer(loadaddr, fw) |
|---|
| 100 | print 'Ok' |
|---|
| 101 | else: |
|---|
| 102 | print 'Flashing firmware...', |
|---|
| 103 | f = nxt.flash.FlashController(s) |
|---|
| 104 | f.flash(fw) |
|---|
| 105 | print 'Ok' |
|---|
| 106 | |
|---|
| 107 | print 'Jumping to 0x%x...' % loadaddr, |
|---|
| 108 | s.jump(loadaddr) |
|---|
| 109 | print 'Ok' |
|---|
| 110 | s.close() |
|---|
| 111 | return 0 |
|---|
| 112 | |
|---|
| 113 | if __name__ == '__main__': |
|---|
| 114 | sys.exit(main()) |
|---|