Antoine Labour | d1cfe32 | 2010-03-26 13:41:05 -0700 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # |
| 3 | # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | from optparse import OptionParser |
| 8 | import binascii |
| 9 | import struct |
| 10 | import sys |
| 11 | |
| 12 | # This script allows listing, reading and writing environment variables for |
| 13 | # u-boot, that usually live in an area of a block device (NVRAM, e.g. NAND or |
| 14 | # NOR flash). |
| 15 | # The u-boot environment variable area is a crc (4 bytes) followed by all |
| 16 | # environment variables as "key=value" strings (\0-terminated) with \0\0 |
| 17 | # (empty string) to indicate the end. |
| 18 | |
| 19 | |
| 20 | class SizeError(Exception): |
| 21 | pass |
| 22 | |
| 23 | |
| 24 | def ReadEnviron(file, size=0, offset=0): |
| 25 | """Reads the u-boot environment variables from a file into a dict.""" |
| 26 | f = open(file, "rb") |
| 27 | f.seek(offset) |
| 28 | if size: |
| 29 | data = f.read(size) |
| 30 | else: |
| 31 | data = f.read() |
| 32 | f.close() |
| 33 | |
| 34 | (crc,) = struct.unpack("I", data[0:4]) |
| 35 | real_data = data[4:] |
| 36 | real_crc = binascii.crc32(real_data) & 0xffffffff |
| 37 | environ = {} |
| 38 | for s in real_data.split('\0'): |
| 39 | if not s: |
| 40 | break |
| 41 | key, value = s.split('=', 1) |
| 42 | environ[key] = value |
| 43 | |
| 44 | return (environ, len(data), crc == real_crc) |
| 45 | |
| 46 | def WriteEnviron(file, environ, size, offset=0): |
| 47 | """Writes the u-boot environment variables from a dict into a file.""" |
| 48 | strings = ['%s=%s' % (k, environ[k]) for k in environ] |
| 49 | data = '\0'.join(strings + ['']) |
| 50 | |
| 51 | # pad with \0 |
| 52 | if len(data) <= size-4: |
| 53 | data = data + '\0'*(size-len(data)-4) |
| 54 | else: |
| 55 | raise SizeError |
| 56 | |
| 57 | crc = binascii.crc32(data) & 0xffffffff |
| 58 | |
| 59 | f = open(file, "r+b") |
| 60 | f.seek(offset) |
| 61 | f.write(struct.pack("I", crc)[0:4]) |
| 62 | f.write(data) |
| 63 | f.close() |
| 64 | |
| 65 | |
| 66 | def main(argv): |
| 67 | parser = OptionParser() |
| 68 | parser.add_option('-f', '--file', type='string', dest='filename') |
| 69 | parser.add_option('-o', '--offset', type='int', dest='offset', default=0) |
| 70 | parser.add_option('-s', '--size', type='int', dest='size', default=0) |
| 71 | parser.add_option('--out', type='string', dest='out_filename') |
| 72 | parser.add_option('--out-offset', type='string', dest='out_offset') |
| 73 | parser.add_option('--out-size', type='string', dest='out_size') |
| 74 | parser.add_option('--list', action='store_true', dest='list') |
| 75 | parser.add_option('--force', action='store_true', dest='force') |
| 76 | parser.add_option('--get', type='string', action='append', dest='get', |
| 77 | default=[]) |
| 78 | parser.add_option('--set', type='string', action='append', dest='set', |
| 79 | default=[]) |
| 80 | (options, args) = parser.parse_args() |
| 81 | (environ, size, crc) = ReadEnviron(options.filename, options.size, |
| 82 | options.offset) |
| 83 | if not crc: |
| 84 | sys.stderr.write('Bad CRC\n') |
| 85 | if not options.force: |
| 86 | sys.exit(1) |
| 87 | |
| 88 | if options.list: |
| 89 | for key in environ: |
| 90 | print "%s=%s" % (key, environ[key]) |
| 91 | |
| 92 | for key in options.get: |
| 93 | try: |
| 94 | print environ[key] |
| 95 | except KeyError: |
| 96 | print '' |
| 97 | |
| 98 | do_write = False |
| 99 | for key_value in options.set: |
| 100 | key, value = key_value.split('=', 1) |
| 101 | environ[key] = value |
| 102 | do_write = True |
| 103 | |
| 104 | if do_write: |
| 105 | out_filename = options.out_filename |
| 106 | out_offset = options.out_offset |
| 107 | out_size = options.out_size |
| 108 | if not out_filename: |
| 109 | out_filename = options.filename |
| 110 | out_offset = options.offset |
| 111 | out_size = size |
| 112 | WriteEnviron(out_filename, environ, out_size, out_offset) |
| 113 | |
| 114 | |
| 115 | if __name__ == '__main__': |
| 116 | main(sys.argv) |