| from __future__ import print_function | |
| import sys | |
| import platform | |
| import os | |
| import os.path | |
| import time | |
| import re | |
| import argparse | |
| import subprocess | |
| try: | |
| input = raw_input | |
| except NameError: | |
| pass | |
| arguments = None | |
| fastboot_name = "fastboot" | |
| fbtool_name = "fbtool.py" | |
| prod_out_path = os.path.abspath(".") | |
| def initialize_env(): | |
| global fastboot_name | |
| # check python version | |
| if sys.version_info[:2] == (2, 7) or sys.version_info[:2][0] == 3: | |
| pass | |
| else: | |
| print("Python 2.7.x / Python 3.x.x required") | |
| exit(1) | |
| # set fastboot | |
| if "Windows" in platform.system(): | |
| fastboot_name += ".exe" | |
| elif "CYGWIN" in platform.system(): | |
| fastboot_name += ".exe" | |
| elif "Linux" in platform.system(): | |
| if "arm" in platform.machine(): | |
| fastboot_name += "-linux-arm" | |
| elif "aarch64" in platform.machine(): | |
| fastboot_name += "-linux-arm" | |
| elif "x86_64" in platform.machine(): | |
| fastboot_name += "-linux-x86_64" | |
| elif "Darwin" in platform.system(): | |
| fastboot_name += "-darwin" | |
| def set_arguments(): | |
| global arguments | |
| parser = argparse.ArgumentParser( | |
| description=''' | |
| Auto device flasher, Python 2.7.x / Python 3.x.x required | |
| ''', | |
| formatter_class=argparse.RawTextHelpFormatter) | |
| parser.add_argument("--productdir", default=None, | |
| help=''' | |
| The product out dir is where to find images. | |
| The Following is the path priority order: | |
| 1. --productdir specified | |
| 2. current directory | |
| ''') | |
| parser.add_argument("--toolsdir", default=None, | |
| help=''' | |
| The tools dir is where to find fbtool and fastboot. | |
| The Following is the path priority order: | |
| 1. --toolsdir specified | |
| 2. current directory | |
| 3. $PATH | |
| ''') | |
| parser.add_argument("partition", nargs="?", default="all", | |
| help="partition to flash (default: all) \ | |
| , not include the test partition") | |
| parser.add_argument("-b", "--boot", action="store_true", default=False, | |
| help="Flash boot partition") | |
| parser.add_argument("-d", "--dryrun", action="store_true", default=False, | |
| help="No image would be flashed, for debug") | |
| parser.add_argument("-s", "--userdefined", | |
| action="store_true", default=False, | |
| help="Flash user-defined partitions \ | |
| and run user-defined actions") | |
| parser.add_argument("-t", "--test", action="store_true", default=False, | |
| help="Flash test partition") | |
| parser.add_argument("-u", "--user", action="store_true", default=False, | |
| help="Flash user data partition") | |
| parser.add_argument("-v", "--verbose", action="store_true", default=False, | |
| help="print more information") | |
| arguments = parser.parse_args() | |
| def show_info(case): | |
| def print_platform(): | |
| print("".center(60, "=")) | |
| print("") | |
| print(("Running flasher on " + platform.platform()).center(60)) | |
| print("") | |
| print("".center(60, "=")) | |
| def print_imagepath(): | |
| global prod_out_path | |
| print("".center(60, "=")) | |
| print("= flash images under:".ljust(58), "=") | |
| print("= ", prod_out_path.ljust(52), "=") | |
| print("".center(60, "=")) | |
| def print_success(): | |
| if platform.system() == "Windows": | |
| input("Success! press enter to exit: ") | |
| else: | |
| print("Success!") | |
| def print_default(): | |
| print("No information about %s." % case) | |
| information = { | |
| "platform": print_platform, | |
| "imagepath": print_imagepath, | |
| "success": print_success | |
| } | |
| information.get(case, print_default)() | |
| def check_flash_tools(): | |
| global arguments, fbtool_name, fastboot_name | |
| toolsdir = "" | |
| if arguments.toolsdir: | |
| try: | |
| toolsdir = os.path.abspath(arguments.toolsdir) | |
| fastboot_name = os.path.join(toolsdir, fastboot_name) | |
| fbtool_name = os.path.join(toolsdir, fbtool_name) | |
| if not os.path.exists(fbtool_name): | |
| raise Exception("Cannot find " + str(fbtool_name) + " in \ | |
| " + str(toolsdir)) | |
| if not os.path.exists(fastboot_name): | |
| raise Exception("Cannot find " + str(fastboot_name) + " in \ | |
| " + str(toolsdir)) | |
| except Exception as err: | |
| print(str(err)) | |
| exit(1) | |
| else: | |
| toolsdir = os.path.abspath(".") | |
| if os.path.exists(os.path.join(toolsdir, fbtool_name)): | |
| if os.path.exists(os.path.join(toolsdir, fastboot_name)): | |
| fastboot_name = os.path.join(toolsdir, fastboot_name) | |
| fbtool_name = os.path.join(toolsdir, fbtool_name) | |
| def get_flashprocs(): | |
| global arguments | |
| devProduct = "DEFAULT" | |
| try: | |
| from flashproc import getFlashProc | |
| except ImportError as err: | |
| print("ImportError: ", err) | |
| exit(1) | |
| flashprocs = getFlashProc(devProduct) | |
| if arguments.userdefined: | |
| try: | |
| from flashproc import getFlashUserdefinedProc | |
| flashprocs = getFlashUserdefinedProc(devProduct) | |
| except: | |
| flashprocs = getFlashProc(devProduct) | |
| if arguments.user: | |
| try: | |
| from flashproc import getFlashUserProc | |
| flashprocs = getFlashUserProc(devProduct) | |
| except: | |
| flashprocs = getFlashProc(devProduct) | |
| if arguments.boot: | |
| try: | |
| from flashproc import getFlashBootProc | |
| flashprocs = getFlashBootProc(devProduct) | |
| except: | |
| flashprocs = getFlashProc(devProduct) | |
| if arguments.test: | |
| try: | |
| from flashproc import getFlashTestProc | |
| flashprocs = getFlashTestProc(devProduct) | |
| except: | |
| flashprocs = getFlashProc(devProduct) | |
| if flashprocs is None: | |
| print("Cannot retrieve flash procedure according \ | |
| to product type of", devProduct) | |
| print("Terminate program !") | |
| exit(1) | |
| if arguments.verbose: | |
| print("Flash procedure".center(60)) | |
| print("".center(60, "-")) | |
| for p in flashprocs: | |
| print("fastboot", " ".join(p)) | |
| return flashprocs | |
| def get_img_list(): | |
| flashprocs = get_flashprocs() | |
| imgs = [] | |
| try: | |
| for proc in flashprocs: | |
| if proc[0] == "fastboot": | |
| if proc[1] == "flash": | |
| if proc[3] not in imgs: | |
| imgs.append(proc[3]) | |
| except Exception as err: | |
| print(err) | |
| return imgs | |
| def check_img(filename, _needreboot=True, _showdetail=False): | |
| global fastboot_name, prod_out_path | |
| if _showdetail: | |
| print((filename).rjust(28), ": ", end="") | |
| path = os.path.join(prod_out_path, filename) | |
| if os.path.exists(path): | |
| if _showdetail: | |
| print("PASS!") | |
| return path | |
| if _needreboot: | |
| print("FAIL!\n Rebooting...") | |
| call([fastboot_name, "reboot"]) | |
| exit(1) | |
| return None | |
| def call(cmd): | |
| global arguments | |
| if arguments.verbose: | |
| print("call:", " ".join(cmd)) | |
| return subprocess.call(cmd) | |
| def check_output(cmd): | |
| global arguments | |
| if arguments.verbose: | |
| print("check_output:", " ".join(cmd)) | |
| return subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) | |
| def check_img_path(): | |
| global arguments, prod_out_path | |
| if arguments.productdir: | |
| prod_out_path = os.path.abspath(arguments.productdir) | |
| else: | |
| prod_out_path = os.path.abspath(".") | |
| for img in get_img_list(): | |
| if check_img(img, _needreboot=False, _showdetail=False) is None: | |
| prod_out_path = None | |
| break | |
| if prod_out_path is None: | |
| prod_out_path = os.getenv("PRODUCT_OUT", ".") | |
| prod_out_path = os.path.abspath(prod_out_path) | |
| def da_mode_wait(wait_secs=30): | |
| global fbtool_name | |
| print("\nWaiting for DA mode:") | |
| ret_code = None | |
| for i in range(wait_secs): | |
| time.sleep(1) | |
| print("# ", end="") | |
| sys.stdout.flush() | |
| ret_code = check_output("python %s " % fbtool_name) | |
| if ret_code is not None and len(ret_code) != 0: | |
| print("datool - device detected: ") | |
| break | |
| if ret_code is None: | |
| print("No device detected.") | |
| print("Please ensure that datool is running.\n") | |
| exit(1) | |
| def fastboot_wait(wait_secs=30): | |
| global fastboot_name | |
| print("\nWaiting for fastboot mode:") | |
| ret_code = None | |
| for i in range(wait_secs): | |
| time.sleep(1) | |
| print("# ", end="") | |
| sys.stdout.flush() | |
| ret_code = check_output("%s devices" % fastboot_name).decode() | |
| if ret_code is not None and len(ret_code) != 0: | |
| print("Fastboot - device detected: ", (ret_code.split())[0]) | |
| break | |
| if ret_code is None: | |
| print("No device detected. ") | |
| exit(1) | |
| def command_reboot(_tobootloader=True): | |
| global fastboot_name | |
| if _tobootloader: | |
| call([fastboot_name, "reboot-bootloader"]) | |
| fastboot_wait() | |
| else: | |
| call([fastboot_name, "reboot"]) | |
| def reboot_device(): | |
| time.sleep(3) | |
| command_reboot(_tobootloader=False) | |
| def check_all_imgs(): | |
| images = get_img_list() | |
| print("".center(60, "-")) | |
| print("Checking image".center(60)) | |
| print("".center(60, "-")) | |
| try: | |
| for img in images: | |
| check_img(img, _needreboot=True, _showdetail=True) | |
| except Exception as err: | |
| print(err) | |
| time.sleep(3) | |
| command_reboot(_tobootloader=False) | |
| input("Fail, press enter to exit: ") | |
| exit(1) | |
| def reboot_bootloader(tries=3): | |
| check_output("adb devices") | |
| for i in range(tries): | |
| print(". ", end="") | |
| time.sleep(2) | |
| sys.stdout.flush() | |
| try: | |
| device_id = check_output("adb get-serialno") | |
| except subprocess.CalledProcessError as err: | |
| print("command '{}' return with error (code {}): {}".format( | |
| err.cmd, err.returncode, err.output)) | |
| continue | |
| print("\nAdb - device detected: ", (device_id.split())[0]) | |
| check_output("adb -s %s reboot bootloader" % (device_id.split())[0]) | |
| return | |
| print("adb is not ready!") | |
| print("Please check whether the usb cable is plugged or adb is supported.") | |
| exit(1) | |
| def command_run(cmd, dryrun=False): | |
| ret_code = 1 | |
| raw_cmd = [] | |
| if cmd[0] == "fastboot": | |
| cmd[0] = fastboot_name | |
| if cmd[1] == "flash": | |
| path = check_img(cmd[3], _needreboot=False, _showdetail=False) | |
| if path is not None: | |
| if "CYGWIN" in platform.system(): | |
| p = subprocess.check_output( | |
| "cygpath --absolute --mixed %s" % path, shell=True) | |
| if p: | |
| path = p.strip() | |
| raw_cmd += [cmd[0], cmd[1], cmd[2], path] | |
| else: | |
| raw_cmd += cmd | |
| elif cmd[0] == "fbWait": | |
| fastboot_wait() | |
| return 0 | |
| elif cmd[0] == "daWait": | |
| da_mode_wait() | |
| return 0 | |
| elif cmd[0] == "reboottobl": | |
| reboot_bootloader() | |
| return 0 | |
| else: | |
| print("FAIL: Unknown command!\n") | |
| return -1 | |
| if dryrun: | |
| print(" ".join(raw_cmd)) | |
| ret_code = 0 | |
| else: | |
| ret_code = call(raw_cmd) | |
| if ret_code == 0: | |
| if cmd[0] == "fastboot": | |
| if cmd[1] == "reboot-bootloader": | |
| fastboot_wait() | |
| return ret_code | |
| def flash_imgs(): | |
| print("\nStart flashing".center(60)) | |
| print("".center(60, "-")) | |
| try: | |
| for p in get_flashprocs(): | |
| if command_run(p, arguments.dryrun) != 0: | |
| raise Exception("<FAILED> %s" % " ".join(proc)) | |
| except Exception as err: | |
| print(err) | |
| time.sleep(3) | |
| command_reboot(_tobootloader=False) | |
| exit(1) | |
| if __name__ == "__main__": | |
| initialize_env() | |
| set_arguments() | |
| show_info("platform") | |
| check_flash_tools() | |
| check_img_path() | |
| show_info("imagepath") | |
| check_all_imgs() | |
| flash_imgs() | |
| reboot_device() | |
| show_info("success") | |
| exit(0) |