summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorWei-Han Chen <stimim@google.com>2018-02-14 18:39:29 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-03-27 18:22:28 +0000
commitd71bef7c868c7add1ff27a01ad389bd1f9ea3e1a (patch)
tree9b34e6aadb256823f5b6086046f24e865d19d4a4 /util
parent8f4f5389ee1fe8ebaf290a1217bc5ab7a678441c (diff)
downloadchrome-ec-d71bef7c868c7add1ff27a01ad389bd1f9ea3e1a.tar.gz
util/unpack_ftb.py: a script to convert FTB file into bin file
ST firmwares are released in FTB format, which can't be written to flash directly. This python script can convert a file in FTB format into bin file. Currently, we only support FTB files of whiskers touchpad firmware. BRANCH=none BUG=none TEST=manual Signed-off-by: Wei-Han Chen <stimim@chromium.org> Change-Id: I179de12663580881347a31f11b5b10659e00b879 Reviewed-on: https://chromium-review.googlesource.com/918603 Commit-Ready: Wei-Han Chen <stimim@chromium.org> Tested-by: Wei-Han Chen <stimim@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/982319 Reviewed-by: Furquan Shaikh <furquan@chromium.org> Commit-Queue: Furquan Shaikh <furquan@chromium.org> Tested-by: Furquan Shaikh <furquan@chromium.org> Trybot-Ready: Furquan Shaikh <furquan@chromium.org>
Diffstat (limited to 'util')
-rwxr-xr-xutil/unpack_ftb.py105
1 files changed, 105 insertions, 0 deletions
diff --git a/util/unpack_ftb.py b/util/unpack_ftb.py
new file mode 100755
index 0000000000..49f4d0ab5b
--- /dev/null
+++ b/util/unpack_ftb.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+import argparse
+import ctypes
+import os
+
+
+class Header(ctypes.Structure):
+ _pack_ = 1
+ _fields_ = [
+ ('signature', ctypes.c_uint32),
+ ('ftb_ver', ctypes.c_uint32),
+ ('chip_id', ctypes.c_uint32),
+ ('svn_ver', ctypes.c_uint32),
+ ('fw_ver', ctypes.c_uint32),
+ ('config_id', ctypes.c_uint32),
+ ('config_ver', ctypes.c_uint32),
+ ('reserved', ctypes.c_uint8 * 8),
+ ('release_info', ctypes.c_ulonglong),
+ ('sec_size', ctypes.c_uint32 * 4),
+ ('crc', ctypes.c_uint32),
+ ]
+
+FW_HEADER_SIZE = 64
+FW_HEADER_SIGNATURE = 0xAA55AA55
+FW_FTB_VER = 0x00000001
+FW_CHIP_ID = 0x3936
+FW_BYTES_ALIGN = 4
+FW_BIN_VER_OFFSET = 16
+FW_BIN_CONFIG_ID_OFFSET = 20
+
+# Starting address in flash for each section
+FLASH_SEC_ADDR = [
+ 0x0000 * 4, # CODE
+ 0x7C00 * 4, # CONFIG
+ 0x7000 * 4, # CX
+ None # This section shouldn't exist
+]
+
+OUTPUT_FILE_SIZE = 128 * 1024 # 128KB
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--input', '-i', required=True)
+ parser.add_argument('--output', '-o', required=True)
+ args = parser.parse_args()
+
+ with open(args.input) as f:
+ bs = f.read()
+
+ size = len(bs)
+ if size < FW_HEADER_SIZE + FW_BYTES_ALIGN:
+ raise Exception('FW size too small')
+
+ print('FTB file size:', size)
+
+ header = Header()
+ assert ctypes.sizeof(header) == FW_HEADER_SIZE
+
+ ctypes.memmove(ctypes.addressof(header), bs, ctypes.sizeof(header))
+ if (header.signature != FW_HEADER_SIGNATURE or
+ header.ftb_ver != FW_FTB_VER or
+ header.chip_id != FW_CHIP_ID):
+ raise Exception('Invalid header')
+
+ for key, _ in header._fields_:
+ v = getattr(header, key)
+ if isinstance(v, ctypes.Array):
+ print(key, map(hex, v))
+ else:
+ print(key, hex(v))
+
+ dimension = sum(header.sec_size)
+
+ assert dimension + FW_HEADER_SIZE + FW_BYTES_ALIGN == size
+ data = bs[FW_HEADER_SIZE:FW_HEADER_SIZE + dimension]
+
+ with open(args.output, 'wb') as f:
+ # ensure the file size
+ f.seek(OUTPUT_FILE_SIZE - 1, os.SEEK_SET)
+ f.write('\x00')
+
+ offset = 0
+ # write each sections
+ for i, addr in enumerate(FLASH_SEC_ADDR):
+ size = header.sec_size[i]
+ assert addr is not None or size == 0
+
+ if size == 0:
+ continue
+
+ f.seek(addr, os.SEEK_SET)
+ f.write(data[offset : offset + size])
+ offset += size
+
+ f.flush()
+
+
+if __name__ == '__main__':
+ main()