diff options
author | Anna Hanna Sedlak Grinbaum <asedla@codeaurora.org> | 2017-06-25 16:07:25 +0300 |
---|---|---|
committer | Nicolas Dechesne <nicolas.dechesne@linaro.org> | 2017-11-27 14:44:49 +0100 |
commit | bad05b88cb0359877387187d7a15986ac595b0ef (patch) | |
tree | bf1dd109dc95aaf58eab0f2ebe2b670ce274d310 |
Add db600c_flasher tool
The purpose of db600_flasher is to rescue a bricked DB600c device, and put it into fastboot mode.
Change-Id: I56495d928dcabe6594624bbed659a2c6318c494d
-rw-r--r-- | db600c_flasher.py | 1378 |
1 files changed, 1378 insertions, 0 deletions
diff --git a/db600c_flasher.py b/db600c_flasher.py new file mode 100644 index 0000000..be09c50 --- /dev/null +++ b/db600c_flasher.py @@ -0,0 +1,1378 @@ +#!/usr/bin/python + +#============================================================================# +# Copyright (c) 2016, The Linux Foundation. All rights reserved. # +# # +# Redistribution and use in source and binary forms, with or without # +# modification, are permitted provided that the following conditions are # +# met: # +# * Redistributions of source code must retain the above copyright # +# notice, this list of conditions and the following disclaimer. # +# * Redistributions in binary form must reproduce the above # +# copyright notice, this list of conditions and the following # +# disclaimer in the documentation and/or other materials provided # +# with the distribution. # +# * Neither the name of The Linux Foundation nor the names of its # +# contributors may be used to endorse or promote products derived # +# from this software without specific prior written permission. # +# # +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED # +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT # +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS # +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +#============================================================================# + +import struct, os, sys, getopt +from xml.etree import ElementTree as ET +#from elementtree.ElementTree import ElementTree +from xml.etree.ElementTree import Element, SubElement, Comment, tostring +from xml.dom import minidom +from datetime import date, timedelta, datetime +import subprocess as sub +from inspect import getargspec +from os.path import getsize +try: + import serial +except: + print "\nERROR: This program makes use of PySerial to talk to COM ports" + print "Please install this from here http://pyserial.sourceforge.net/ for Python 2.x\n" + sys.exit() +import inspect, re +from types import * +from time import strftime, localtime, sleep, time + +# Defines +MAX_READ_RETRIES_STREAM = 4 +MODE_IS_STREAMING = 0 + +## These defines are to verify we are in the mode we think we are +DLOAD_ACK = 2 +DLOAD_NAK = 3 + +AHDLC_FLAG = 0x7e +AHDLC_ESCAPE = 0x7d +AHDLC_ESC_M = 0x20 + +CRC_16_L_SEED = 0xFFFF + +CMD_NOOP = 0x06 +CMD_GO = 0x05 +CMD_PARAMREQ = 0x07 +CMD_PARAMREQ_RESP = 0x08 +CMD_WRITE_32BIT = 0x0F + +EHOST_HELLO_REQ = 0x01 # Hello request +EHOST_HELLO_RSP = 0x02 # Hello response +EHOST_STREAM_WRITE_REQ = 0x07 # Streaming write command +EHOST_STREAM_WRITE_RSP = 0x08 # Response to stream write +EHOST_SECURITY_REQ = 0x17 # Send Security mode to use for programming images +EHOST_SECURITY_RSP = 0x18 # Response to Send Security mode +EHOST_OPEN_MULTI_REQ = 0x1B # Open for writing image (Multi-image mode only) +EHOST_OPEN_MULTI_RSP = 0x1C # Response to open for writing image +EHOST_CLOSE_REQ = 0x15 # Close and flush last partial write to Flash +EHOST_CLOSE_RSP = 0x16 # Response to close and flush last partial write to Flash +EHOST_RESET_REQ = 0x0B # Reset target +EHOST_RESET_ACK = 0x0C # Response to reset +EHOST_LOG = 0x0E +EHOST_ERROR_RSP = 0x0D + +FEATURE_UNCOMPRESSED_DLOAD = 0x00000001 +FEATURE_SECTOR_ADDRESSES = 0x00000010 + +PRTN_EMMCUSER = 0x21 # For programming eMMC chip (singleimage.bin) +DLOAD_MAX_WRITE_SIZE= 1536 + +COM_PORT = None + +SEARCH_CWD_LAST = False + +# Global variables +port_trace = True +RX_Buffer = [] +device_handle = "Aaron" +max_block_size = 256 +max_window_size = 1 +flash_base_address = 0 +SECTOR_SIZE = 512 +device_handle = None +version_num = None +compatible_ver = None +partition_sizes_cache = {} +current_open_partition = None +search_paths = [] +sector_addresses = False +max_write_size = 1536 +hex_transfer_address = None +hex_file_line_count = None +verbose = False +hex_filename = None +DoDLOAD = False +DoStreaming = False +streaming_erase = [] +temp_patch_filename = "temppatchfile.bin" +DidStuff = False + +DloadCommand = [ + "0x00 = illegal command", + "0x01 = Write", + "0x02 = ACK", + "0x03 = NAK", + "0x04 = Erase", + "0x05 = Go", + "0x06 = NO-OP", + "0x07 = Param Request", + "0x08 = Param Response", + "0x09 = Mem Dump", + "0x0A = Reset", + "0x0B = Unlock", + "0x0C = SW Ver Request", + "0x0D = SW Ver Response", + "0x0E = Powerdown", + "0x0F = Write with 32 bit addr", + "0x10 = Mem Debug query", + "0x11 = Mem Debug info", + "0x12 = Mem Read Request", + "0x13 = Mem Read Response", + "0x14 = Command Failed", + "0x15 = No Response" +] + +StreamingCommand = [ + "0x00 = Illegal command", + "0x01 = Hello", + "0x02 = Hello response", + "0x03 = Read", + "0x04 = Read response", + "0x05 = Simple write", + "0x06 = Wrote okay", + "0x07 = Stream write", + "0x08 = Block written", + "0x09 = NOP", + "0x0A = NOP response", + "0x0B = Reset", + "0x0C = Reset ACK", + "0x0D = Error", + "0x0E = Log", + "0x0F = Unlock", + "0x10 = Unlocked", + "0x11 = Power off", + "0x12 = Powering down", + "0x13 = Open", + "0x14 = Opened", + "0x15 = Close", + "0x16 = Closed", + "0x17 = Security mode", + "0x18 = Security mode received", + "0x19 = Partition table", + "0x1A = Partition table received", + "0x1B = Open multi-image", + "0x1C = Opened multi-image", + "0x1D = Erase Flash", + "0x1E = Flash erased", + "0x1F = Get ECC state", + "0x20 = Current ECC state", + "0x21 = Set ECC", + "0x22 = Set ECC response" +] + +EHOST_ERROR_CODES = [ + "Illegal reason (do not use)", + "Reserved", + "Invalid destination address", + "Invalid length", + "Unexpected end of packet", + "Invalid command", + "Reserved", + "Operation failed", + "Wrong Flash intelligent ID", + "Bad programming voltage", + "Write-verify failed", + "Reserved", + "Incorrect security code", + "Cannot power down phone", + "NAND Flash programming not supported", + "Command out of sequence", + "Close did not succeed", + "Incompatible feature bits", + "Out of space", + "Invalid Security mode", + "Multi-image NAND not supported", + "Power off command not supported", + "Illegal reason (do not use)", +] + +# Functions + +def port_open(portname): + global device_handle + device_handle = device_open(portname) + +def port_close(): + device_close(device_handle) + +def port_write(data_packet): + return device_write(device_handle, ''.join(hdlc_encode(data_packet))) + +def ReturnSizeInSectors(size): + rem = size % 512 + if rem != 0: + return int(size / 512) + 1 + else: + return int(size / 512) + +def find_file(filename, search_paths): + device_log("\n\n\tLooking for '%s'" % filename, 1) + print "\t" + "-" * 40 + for x in search_paths: + device_log("\tSearching %s" % x, 1) + temp = os.path.join(x, filename) + if os.path.exists(temp): + device_log("\n\t**Found %s (%i bytes) (%i sectors)\n" % ( + temp, os.path.getsize(temp), ReturnSizeInSectors(os.path.getsize(temp))), 1) + return temp + + ## search cwd last + device_log("\tSearching CWD %s" % os.getcwd(), 1) + if os.path.exists(filename): + device_log("\n\t**Found %s (%i bytes)\n" % (filename, os.path.getsize(filename)), 1) + return filename + + device_log("\tCound't find file\n", 1) + return None + +def reset_device_log(): + try: + out_fp = open('port_trace.txt', 'w') + except: + print "\nERROR: Can't create the file port_trace.txt" + print "This might be because the file is open and locked" + print "Or because you are running this from a read-only location\n" + sys.exit() + + out_fp.close() + +def device_log(message, display=0, data=None, GuessPacketAtIndex=-1): + try: + out_fp = open('port_trace.txt', 'a') + except: + print "ERROR: could not open 'port_trace.txt'" + return + + if display == 1: + print message + + ## Remove any extra newlines + try: + out_fp.write("%s %s\n" % (strftime("%H:%M:%S", localtime()), message.replace('\n', ''))) + except: + print "ERROR: could not write to 'port_trace.txt'" + return + + if not data is None: + if GuessPacketAtIndex >= 0: + if len(data) >= (GuessPacketAtIndex + 1): # if guess is 0, then len() must be 1 + try: + command_id = data[ + GuessPacketAtIndex] ## If still HDLC encoded, GuessPacketAtIndex should be 1, else 0 + if command_id < len(DloadCommand): + out_fp.write("\t\tBuffer below could be DLOAD ------> " + DloadCommand[command_id] + "\n") + if command_id < len(StreamingCommand): + out_fp.write("\t\tBuffer below could be STREAMING --> " + StreamingCommand[command_id] + "\n") + except: + print "ERROR: could not write to 'port_trace.txt'" + return + + HexPrint(data, display, out_fp) + out_fp.close() + +def device_open(portname): + try: + ser = serial.Serial(portname, 115200, timeout=0.1) + except: + device_log("ERROR: Could not open '%s'" % portname, 1) + device_log("ERROR: If your device is on this port, try resetting it?\n\n", 1) + sys.exit(1) + + device_log("Port %s opened\n" % portname, 1) + + return ser + +def device_write(ser, data): + ser.write(data) + ser.flush() + if port_trace: + device_log("device_write(%i bytes)" % len(data), 0, data, 1) # guess at 1 since it's encoded + # return x + return len(data) + +def HexPrint(data, tostdout=0, fp=None): + szNum = "" + szAsc = "" + + if len(data) == 0: + szHexDump = "\n\tBuffer holds %d bytes\n\n" % len(data) + else: + szHexDump = "\n\tShowing %d bytes\n\t" % len(data) + for i in range(len(data)): + try: + v = ord(data[i]) ## HACK - if all code is clean, won't need this + except: + v = data[i] + + if i > 0 and i % 16 == 0: + szHexDump += "%-48s\t%s\n\t" % (szNum, szAsc) + szNum = "" + szAsc = "" + + szNum += "%.2X " % v + if v >= 0x20 and v <= 0x7E: + szAsc += "%c" % v + else: + szAsc += "." + + szHexDump += "%-48s\t%s\n\n" % (szNum, szAsc) + + if fp != None: + try: + fp.write(szHexDump) + except: + print "ERROR: could not write to 'port_trace.txt'" + return + + if tostdout == 1 or fp == None: + print szHexDump + +def device_close(ser): + ser.close() + ser = None + device_log("Port closed device_close()\n\n") + +def PrintYouAreNotInStreamingMode(QuitOnFail=1): + global MODE_IS_STREAMING + device_log("\n\n" + "=" * 78, 1) + device_log("WARNING: You are *NOT* in STREAMING DOWNLOAD MODE\n", 1) + device_log("WARNING: You are *NOT* in STREAMING DOWNLOAD MODE\n", 1) + device_log("WARNING: You are *NOT* in STREAMING DOWNLOAD MODE", 1) + device_log("\nNOTE: Your device is not in the state expected", 1) + MODE_IS_STREAMING = 0 + device_log("=" * 78 + "\n", 1) + if QuitOnFail == 1: + device_log("NOTE: Please reset your device", 1) + sys.exit(1) + +def PrintYouAreNotInDloadMode(QuitOnFail=1): + global MODE_IS_STREAMING + device_log("\n\n" + "=" * 78, 1) + device_log("WARNING: You are *NOT* in DLOAD MODE\n", 1) + device_log("WARNING: You are *NOT* in DLOAD MODE\n", 1) + device_log("WARNING: You are *NOT* in DLOAD MODE\n", 1) + device_log("\nNOTE: Your device is not in the state expected", 1) + MODE_IS_STREAMING = 1 + device_log("=" * 78 + "\n", 1) + if QuitOnFail == 1: + device_log("NOTE: Please reset your device", 1) + sys.exit(1) + +def HDLC_Decode(): + global RX_Buffer, MODE_IS_STREAMING + debugthis = 1 + + ShowPacketToUser = 0 # Overrides if it's an error + + FramingOk = 0 + FrameStart = 0 + FrameEnd = 0 + + for i in range(len(RX_Buffer)): + if RX_Buffer[i] == AHDLC_FLAG: + # Found first 0x7E + FrameStart = i + FramingOk += 1 + break + + if FramingOk == 0: + device_log( + "WARNING: HDLC_Decode(%i bytes), something is wrong with this buffer, could not find start of frame" % len( + RX_Buffer), 0, RX_Buffer) + print "HDLC_Decode() Returning [0]" + return [0] # Nothing to decode + + i = i + 1 # i is where we found the start of the frame, so we throw this away + + RX_Buffer = RX_Buffer[i:] + + for i in range(len(RX_Buffer)): + if RX_Buffer[i] == AHDLC_FLAG: + # Found last 0x7E + FrameEnd = i + FrameStart + FramingOk += 1 + break + + if FramingOk == 1: # should be 2 at this point if we found both + device_log( + "WARNING: HDLC_Decode(%i bytes), something is wrong with this buffer, could not find end of frame" % len( + RX_Buffer), 0, RX_Buffer) + print "HDLC_Decode() Returning [0]" + return [0] # Nothing to decode + + packet = RX_Buffer[:i] # Gets everything else + RX_Buffer = RX_Buffer[i + 1:] # Gets what is left over + + packet_length = len(packet) + i = 0 + while i < packet_length: + if packet[i] == AHDLC_ESCAPE and packet[i + 1] == 0x5e: + packet.pop(i) + packet.pop(i) + # packet.insert(i, chr(AHDLC_FLAG)) + packet.insert(i, AHDLC_FLAG) + packet_length = packet_length - 1 + if packet[i] == AHDLC_ESCAPE and packet[i + 1] == 0x5d: + packet.pop(i) + packet.pop(i) + # packet.insert(i, chr(AHDLC_ESCAPE)) + packet.insert(i, AHDLC_ESCAPE) + packet_length = packet_length - 1 + i = i + 1 + + temp = packet[-2:] + try: # HACK + recv_crc = ((temp[1] << 8) & 0xFF00) | (temp[0] & 0x00FF) + except: + try: + recv_crc = ((ord(temp[1]) << 8) & 0xFF00) | (ord(temp[0]) & 0x00FF) + except: + import pdb; + pdb.set_trace() + a = 5 + b = 6 + + packet = packet[:-2] + calc_crc = 0xffff & calculate_crc(packet, len(packet) * 8) + if recv_crc != calc_crc: + device_log("CRC doesn't match", 1) + device_log("Packet CRC: 0x%.4X" % recv_crc) + device_log("Expect CRC: 0x%.4X\n" % calc_crc) + print "HDLC_Decode() Returning [0]" + return [0] + + return packet + +def hdlc_encode(packet): + write_size = len(packet) + crc_value = calculate_crc(packet, write_size * 8) + encoded_buffer = [] + encoded_buffer.append(chr(AHDLC_FLAG)) + + # Add data, escaping when necessary + decodeIndex = 0 + while decodeIndex < write_size: + try: + value = ord(packet[decodeIndex]) # HACK shouldn't be needed if data is all clean + except: + value = packet[decodeIndex] + decodeIndex = decodeIndex + 1 + if value == AHDLC_FLAG or value == AHDLC_ESCAPE: + value ^= AHDLC_ESC_M + encoded_buffer.append(chr(AHDLC_ESCAPE)) + encoded_buffer.append(chr(value)) + + # Byte order crc + byteOrderedCRC = [(crc_value & 0x00ff), ((crc_value >> 8) & 0x00ff)] + + # Add crc + c = 0 + while c < 2: + value = byteOrderedCRC[c] + c = c + 1 + if value == AHDLC_FLAG or value == AHDLC_ESCAPE: + value ^= AHDLC_ESC_M + encoded_buffer.append(chr(AHDLC_ESCAPE)) + + encoded_buffer.append(chr(value)) + + # Add trailing flag + encoded_buffer.append(chr(AHDLC_FLAG)) + return encoded_buffer + +crc_table = [ + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +] + +def calculate_crc(buffer, bitLen): + pBuf = 0 + crc_value = CRC_16_L_SEED + while bitLen >= 8: + try: + crc_value = crc_table[(crc_value ^ ord(buffer[pBuf])) & 0x00ff] ^ (crc_value >> 8) + except: + crc_value = crc_table[(crc_value ^ buffer[pBuf]) & 0x00ff] ^ (crc_value >> 8) + bitLen = bitLen - 8 + pBuf = pBuf + 1 + return (0xFFFF & (~crc_value)) + +def ReadCOMPort(read_length=1024): + global RX_Buffer + + device_log("ReadCOMPort(read_length=%d) Attempting to read %i bytes from COM port" % (read_length, read_length)) + retries = 0 + data_read = [] + while retries < MAX_READ_RETRIES_STREAM and len(data_read) == 0: + data_read = [ord(x) for x in + device_handle.read(read_length)] ## Orig treated as chars, as in 't','i','m','m','y' + ## now it will be [116,105,109,109,121] + if len(data_read) == 0: + retries = retries + 1 + device_log("0 bytes received - Retry %i of %i" % (retries, MAX_READ_RETRIES_STREAM)) + sleep(0.1) + if retries == MAX_READ_RETRIES_STREAM: + device_log("ReadCOMPort(read_length=%d) 0 bytes received, Max read retries reached (TIMEOUT)" % read_length, 0) + return 0 + + if len(data_read) > 0: + device_log("%i new bytes read from COM port" % len(data_read), 0, data_read) + + RX_Buffer = RX_Buffer + data_read ## append the data + + return len(data_read) + +def GetNextPacket(): + global RX_Buffer + + device_log("Entering GetNextPacket()") + + AttemptsAtGettingFullPacket = 10 + NumAttemptsAtFullPacket = 0 + FoundCompletePacket = 0 + NumBytesRead = 0 + + while (NumAttemptsAtFullPacket < AttemptsAtGettingFullPacket): + ## First, does buffer hold at least 5 bytes, i.e. 7E XX crc crc 7E, where XX is some command + if len(RX_Buffer) > 4: + device_log("len(RX_Buffer)>4") + ## To be this far means we have enough data to satisfy HDLC encoding + if RX_Buffer[0] != AHDLC_FLAG: + device_log( + "WARNING: RX_Buffer is most likely holding garbage since it doesn't begin with 0x%X" % AHDLC_FLAG, + 0, RX_Buffer) + ## Now begin hunting for the first AHDLC_FLAG byte + Found = 0 + for i in range(len(RX_Buffer)): + if RX_Buffer[i] == AHDLC_FLAG: + Found = 1 + break + if Found == 1: + device_log("Found the beginning AHDLC_FLAG") + RX_Buffer = RX_Buffer[i:] + else: + device_log("WARNING: RX_Buffer only held garbage. It is now empty") + RX_Buffer = [] + + device_log("Continuing in loop") + next ## continue on in either case, doesn't change NumAttemptsAtFullPacket + ## want the above checks to happen again + + else: + device_log("RX_Buffer[0] begins with AHDLC_FLAG") + ## To be this far means we have len(RX_Buffer)>4 and RX_Buffer[0] == AHDLC_FLAG: + if RX_Buffer[-1] == AHDLC_FLAG: + ## buffer holds one complete packet OR multiple complete packets + device_log("FoundCompletePacket = 1") + FoundCompletePacket = 1 + break + else: + ## Buffer does *not* hold enough data + if NumAttemptsAtFullPacket == 0: + device_log( + "RX_Buffer only has %d bytes, this is not enough to form a complete packet, will attempt to collect more" % len( + RX_Buffer), 0, RX_Buffer) + else: + device_log( + "RX_Buffer only has %d bytes, this is not enough to form a complete packet, will attempt to collect more" % len( + RX_Buffer)) + NumBytesRead = ReadCOMPort() # appends to RX_Buffer + NumAttemptsAtFullPacket += 1 + + if FoundCompletePacket == 1: + temp = HDLC_Decode() + return temp # works on RX_Buffer + else: + # didn't find a complete packet. Must me something is wrong + device_log("\nERROR? GetNextPacket() Didn't find a complete packet?? Returning [0]") + return [0] + +def SendCommand(command_id, **kwargs): + packet_buf = [chr(command_id)] + + if MODE_IS_STREAMING == 0: + if command_id < len(DloadCommand): + device_log("DLOAD: SendCommand(0x%.2X) (%s)" % (command_id, DloadCommand[command_id])) + else: + device_log("DLOAD: SendCommand(0x%.2X) (%s)" % (command_id, "command not in DloadCommand string table?")) + else: + if command_id < len(StreamingCommand): + device_log("STREAMING: SendCommand(0x%.2X) (%s)" % (command_id, StreamingCommand[command_id])) + else: + device_log( + "STREAMING: SendCommand(0x%.2X) (%s)" % (command_id, "command not in StreamingCommand string table?")) + + if 'packet_data' in kwargs: + packet_buf.extend(kwargs['packet_data']) + + port_write(packet_buf) + +def int_to_hex_list(some_int, list_length=None): + if some_int < 0: + print "In int_to_hex_list(some_int=", some_int, "list_length=", list_length + print "In int_to_hex_list(some_int=", type(some_int), "list_length=", type(list_length) + print "Logic is probably wrong, please double check this" + sys.exit(1) + temp = hex(some_int)[2:] + if temp[-1] == 'L': + temp = temp[:-1] + if len(temp) % 2 == 1: + temp = '0' + temp + temp_list = [chr(int(temp[x:x + 2], 16)) for x in range(0, len(temp), 2)] + if not list_length is None: + temp_len = len(temp_list) + while list_length != temp_len: + temp_list.insert(0, '\x00') + temp_len = temp_len + 1 + return temp_list + +def hex_list_to_int(some_list): + new_list = [] + for i in range(len(some_list)): + try: + x = hex(ord(some_list[i]))[2:] # HACK shouldn't be needed if all data is clean + except: + x = hex(some_list[i])[2:] + if len(x) == 1: + x = '0' + x + new_list.append(x) + return int(''.join(new_list), 16) + +def check_for_target(): + device_log("DLOAD: check_for_target()", 0) + SendCommand(CMD_NOOP) + Attempts = 0 + while True: + sleep(1) + data_read = GetNextPacket() + # print "Read",data_read,"of type",type(data_read) + # print "="*50 + + if len(data_read) >= 1: # could have returned [0] + if data_read[0] == DLOAD_ACK: + device_log("DLOAD: Device responded", 0) + return True + else: + device_log("DLOAD: Not the correct response, re-pinging device...", 1, data_read, 0) + else: + device_log('DLOAD: Nothing received back, re-pinging device...', 1) + + Attempts += 1 + if Attempts > 5: + DisplayResetDeviceErrorMessage(inspect.currentframe(), __file__) + sys.exit() + SendCommand(CMD_NOOP) + + return False + +def DidNotRespondCorrectly(szMessage, data_read): + device_log("\nData received was:", 1, data_read) + device_log("%s" % szMessage, 1) + device_log("ERROR: Device is alive but not in the state this program expects", 1) + device_log("ERROR: Device is most likely in STREAMING MODE, reset it to move to DLOAD mode", 1) + device_log("ERROR: Please RESET device", 1) + print "\n\nSee port_trace.txt for a more detailed log\n\n" + sys.exit(1) + +def get_max_write(): + global max_write_size + SendCommand(CMD_PARAMREQ) + data_read = GetNextPacket() + device_log("DLOAD: In get_max_write() call to GetNextPacket() returned %i bytes" % len(data_read)) + if len(data_read) > 0: + if data_read[0] == CMD_PARAMREQ_RESP: + max_write_size = ((data_read[3] << 8) & 0xFF00) | (data_read[4] & 0x00FF) + device_log("DLOAD: ** max_write_size is set to %d **" % max_write_size, 1) + else: + DidNotRespondCorrectly( + "ERROR: Device did *not* respond correctly, expected CMD_PARAMREQ_RESP of 0x%X but got 0x%X" % ( + CMD_PARAMREQ_RESP, data_read[0]), data_read) + else: + DidNotRespondCorrectly("ERROR: Device did *not* respond correctly", data_read) + +def set_max_write_size(value): + global max_write_size + max_write_size = value + +def DisplayResetDeviceErrorMessage(c, f): + print "\n" + "-" * 78 + device_log("ERROR: Seems the device is *not* responding\n", 1) + device_log("\t** Try resetting the device AND unplug the USB cable\n", 1) + device_log("\t\tQualcomm HS-USB QDLoader 9008 <-- or something like this", 1) + + device_log("\n\tLINE:" + str(c.f_lineno) + "\t" + f, 1) + + print "-" * 78 + "\n" + +def send_go_command(hex_filename): + SendCommand(CMD_GO, packet_data=hex_transfer_address) + data_read = GetNextPacket() + if len(data_read) == 0: + device_log("DLOAD: send_go_command(): Nothing received from target", 1) + device_log("DLOAD: ERROR: This probably means the HEX file does not work for this target/revision", 1) + DisplayResetDeviceErrorMessage(inspect.currentframe(), __file__) + sys.exit(1) + if not data_read[0] == DLOAD_ACK: + device_log("DLOAD: ERROR: ACK *not* received after sending GO command", 1) + device_log("DLOAD: ERROR: This probably means the HEX file does not work for this target/revision", 1) + sys.exit(1) + else: + device_log("DLOAD: GO command was ACCEPTED by the device\n", 1) + device_log("DLOAD: The phone is now running this HEX file\n", 1) + device_log("\nDLOAD: If the phone HANGS here it means the HEX file is bad OR not meant for this device\n", 1) + +def transfer_hex(filename, operation=1): + global hex_transfer_address + global hex_file_line_count + + device_log("Inside transfer_hex with operation=%d" % operation, 1) + + try: + fp = open(filename, 'r') + except: + device_log("ERROR: Could not open '%s'\n" % filename, 1) + sys.exit() + + device_log("DLOAD: Opened '%s'\n" % filename, 1) + + line_count = 0 + if operation == 1: + transfer_address_value = hex_list_to_int(hex_transfer_address) + total_data = [] + total_data_sent = 0 + progress = 1 + progress_max = 10 + for line in fp: + line_count = line_count + 1 + line = line.strip('\n\r') + + ## Is this really a HEX file? :020000042A00D0 + m = re.search(":[\da-fA-F]", line) + if type(m) is NoneType: + device_log("\nDLOAD ERROR:\n'%s'\ndoes not appear to be a valid HEX file" % filename, 1) + device_log("\nDLOAD ERROR:\n'%s'\ndoes not appear to be a valid HEX file" % filename, 1) + device_log("\nDLOAD ERROR:\n'%s'\ndoes not appear to be a valid HEX file\n" % filename, 1) + sys.exit(1) + + start_code = line[0:1] + byte_count = int(line[1:3], 16) + address = int(line[3:7], 16) + record_type = int(line[7:9], 16) + checksum = int(line[-2:], 16) + temp = line[9:-2] + data = [chr(int(temp[x:x + 2], 16)) for x in range(0, len(temp), 2)] + + if record_type == 0x00 and operation == 1: + # if line_count != 1 and operation == 1: + if len(data) >= 8: + total_data.extend(data) + if len(total_data) >= max_write_size: + # if (line_count-1)%16 == 0: + packet = [] + packet.extend(int_to_hex_list(transfer_address_value, 4)) + packet.extend(int_to_hex_list(len(total_data), 2)) + packet.extend(total_data) + SendCommand(CMD_WRITE_32BIT, packet_data=packet) + data_read = GetNextPacket() + if len(data_read) == 0: + device_log("DLOAD: transfer_hex(operation=%i): Nothing received from target" % operation, 1) + DisplayResetDeviceErrorMessage(inspect.currentframe(), __file__) + sys.exit(1) + elif not data_read[0] == DLOAD_ACK: + DidNotRespondCorrectly("ERROR: ACK *not* received", data_read) + else: + device_log("DLOAD: received ACK\n") + transfer_address_value = transfer_address_value + len(total_data) + total_data_sent = total_data_sent + len(total_data) + 7 + device_log("DLOAD: sent %i bytes\n" % total_data_sent) + + total_data = [] + if ((1.0 * line_count) / hex_file_line_count) >= ((1.0 * progress) / progress_max): + device_log("-" * 78) + device_log("%i %%" % (progress * progress_max), 1) + device_log("-" * 78) + progress = progress + 1 + + if record_type == 0x05 and byte_count == 0x04 and address == 0 and operation == 0: + if type(data[0]) is str: ## HACK - if all data is clean, won't need this + hex_transfer_address = [ord(x) for x in data] + else: + hex_transfer_address = data + + if operation == 0: + hex_file_line_count = line_count + device_log("DLOAD: hex_transfer_address = 0x%.4X" % hex_list_to_int(hex_transfer_address), 1) + + if operation == 1: + if len(total_data) > 0: + packet = [] + packet.extend(int_to_hex_list(transfer_address_value, 4)) + packet.extend(int_to_hex_list(len(total_data), 2)) + packet.extend(total_data) + SendCommand(CMD_WRITE_32BIT, packet_data=packet) + data_read = GetNextPacket() + if len(data_read) == 0: + device_log("ERROR: transfer_hex(operation==1): Nothing received from target", 1) + DisplayResetDeviceErrorMessage(inspect.currentframe(), __file__) + sys.exit(1) + if not data_read[0] == DLOAD_ACK: + device_log("ERROR: ACK not received", 0, data_read) + sys.exit(1) + else: + device_log("DLOAD: received ACK\n") + transfer_address_value = transfer_address_value + len(total_data) + total_data_sent = total_data_sent + len(total_data) + 7 + # print "sent", total_data_sent + total_data = [] + ##print (progress*progress_max), "% " + fp.close() + +def ReturnSizeString(size): + if size > (1024 * 1024 * 1024): + return "%.2f GB" % (size / (1024.0 * 1024.0 * 1024.0)) + elif size > (1024 * 1024): + return "%.2f MB" % (size / (1024.0 * 1024.0)) + elif size > (1024): + return "%.2f KB" % (size / (1024.0)) + else: + return "%i B" % (size) + +class StateMachine: + def __init__(self): + self.StateHandler = [] + self.StateKwargs = [] + + def num_states(self): + return len(self.StateHandler) + + def show_states(self): + device_log("Streaming Operations:", 1) + for i in range(len(self.StateHandler)): + device_log("%i)\t%-50s\tkwargs: %s" % (i, self.StateHandler[i], self.StateKwargs[i]), 0) + + def add_state(self, handler, **kwargs): + self.StateHandler.append(handler) ## streaming.FSM.add_state(streaming.Hello) + if len(kwargs) > 0: + self.StateKwargs.append( + kwargs) ## streaming.FSM.add_state(streaming.GetPartitionInfo,set_active_boot=False) + else: + self.StateKwargs.append({}) # append an empty dictionary + + def move_to_state(self, handler, **kwargs): + handler(**kwargs) + + def run(self): + for i in range(len(self.StateHandler)): + handler = self.StateHandler[i] + kwargs = self.StateKwargs[i] + + handler(**kwargs) ## note this is passing **kwargs + print "-" * 78 + +def Hello(**kwargs): + device_log("STREAMING: Sending HELLO", 1) + packet = [] + packet.extend([x for x in 'QCOM fast download protocol host']) + packet.append('\x02') + packet.append('\x02') + + requested_feature_bits = FEATURE_UNCOMPRESSED_DLOAD + if sector_addresses: + requested_feature_bits = requested_feature_bits | FEATURE_SECTOR_ADDRESSES + requested_feature_bits = struct.pack("<L", requested_feature_bits) + # Currently emmcbld only deals with the first byte of feature bits + requested_feature_bits = requested_feature_bits[0] + packet.append(requested_feature_bits) + + SendCommand(EHOST_HELLO_REQ, packet_data=packet) + + data_read = BlockForResponse(EHOST_HELLO_RSP) + device_log("STREAMING: Device responded to Streaming HELLO", 0) + + print "\n" + "*" * 78 + device_log("Device responded", 1) + device_log("Device responded", 1) + device_log("Device responded", 1) + print "*" * 78 + "\n" + device_log("\nDevice is running the HEX code (i.e. it's responding to STREAMING PROTOCOL commands)\n\n", 1) + + global version_num, compatible_ver, max_block_size, flash_base_address, max_window_size + version_num = hex_list_to_int(data_read[33:34][::-1]) + compatible_ver = hex_list_to_int(data_read[34:35][::-1]) + max_block_size = hex_list_to_int(data_read[35:39][::-1]) + flash_base_address = hex_list_to_int(data_read[39:43][::-1]) + flash_name_length = hex_list_to_int(data_read[43:44][::-1]) + flash_name = data_read[44:44 + flash_name_length] + max_window_size = hex_list_to_int(data_read[44 + flash_name_length:44 + flash_name_length + 2][::-1]) + max_window_size = max_window_size - 1 if max_window_size > 1 else max_window_size + + num_of_sectors = hex_list_to_int(data_read[44 + flash_name_length + 2:44 + flash_name_length + 2 + 2][::-1]) + sector_sizes = hex_list_to_int( + data_read[44 + flash_name_length + 2 + 2:44 + flash_name_length + 2 + 2 + (num_of_sectors * 4)][::-1]) + active_feature_bits = hex_list_to_int(data_read[44 + flash_name_length + 2 + 2 + ( + num_of_sectors * 4):44 + flash_name_length + 2 + 2 + (num_of_sectors * 4) + 1][::-1]) + + if active_feature_bits & FEATURE_SECTOR_ADDRESSES: + device_log("Sector addresses enabled", 1) + else: + device_log("Sector addresses not supported", 1) + global sector_addresses + sector_addresses = False + + device_log("version_num\t\t= %i" % version_num, 1) + device_log("compatible_ver\t\t= %i" % compatible_ver, 1) + device_log("max_block_size\t\t= %i" % max_block_size, 1) + device_log("flash_base_address\t= %i" % flash_base_address, 1) + device_log("flash_name\t\t= %s" % ''.join([chr(x) for x in flash_name]), 1) + device_log("window_size\t\t= %i\n" % max_window_size, 1) + +def SecurityMode(**kwargs): + device_log("STREAMING: Attempting to UNLOCK the device", 1) + packet = ['\x00'] + SendCommand(EHOST_SECURITY_REQ, packet_data=packet) + + data_read = BlockForResponse(EHOST_SECURITY_RSP) + device_log("STREAMING: Device responded. It is now unlocked", 0) + +def OpenMultiImage(**kwargs): + global current_open_partition + if not 'partition' in kwargs: + device_log("Don't know which partition to open in OpenMultiImage. Ex: partition=PRTN_EMMCUSER", 1) + sys.exit(1) + + # for key in kwargs: + # print "another keyword arg: %s: %s" % (key, kwargs[key]) + + device_log("STREAMING: Calling send_open_multi_image(%i)" % kwargs['partition'], 1) + SendCommand(EHOST_OPEN_MULTI_REQ, packet_data=[chr(kwargs['partition'])]) + + data_read = BlockForResponse(EHOST_OPEN_MULTI_RSP) + device_log("STREAMING: Device responded. Partition %i is now open" % kwargs['partition'], 0) + current_open_partition = kwargs['partition'] + +def CloseMultiImage(**kwargs): + global current_open_partition + device_log("STREAMING: closing partition", 0) + SendCommand(EHOST_CLOSE_REQ) + + data_read = BlockForResponse(EHOST_CLOSE_RSP) + device_log("STREAMING: Device responded. Partition %d is now closed" % current_open_partition, 0) + current_open_partition = None + +def Reset(**kwargs): + device_log("STREAMING: Send Reset", 1) + SendCommand(EHOST_RESET_REQ) + + data_read = BlockForResponse(EHOST_RESET_ACK) + device_log("-" * 78, 1) + device_log("Device reset", 1) + device_log("-" * 78 + "\n", 1) + device_log("=" * 78, 1) + device_log("Your device should now come up as a MASS STORAGE device", 1) + device_log("It should be accessible just like a USB FLASH drive", 1) + device_log("OR your device should be accessible as a FASTBOOT device", 1) + device_log("=" * 78 + "\n", 1) + +def Write(**kwargs): + start_sector = 0 + num_partition_sectors = 0 + EndSector = 0 + file_sector_offset = 0 + num_file_sectors = 0 + check_card_length = 0 + PayloadSize = max_block_size # most likely 1024 + NumWindows = 30 + NumPartitionSectors = 0 + + if 'partition' in kwargs: + OpenMultiImage(partition=kwargs['partition']) + if 'filename' in kwargs: + filename = kwargs['filename'] + else: + device_log("\nERROR: No filename (image) specified for writing to eMMC", 1) + sys.exit(1) + if 'start_sector' in kwargs: + start_sector = kwargs['start_sector'] + if 'num_file_sectors' in kwargs: + num_file_sectors = kwargs['num_file_sectors'] ## This is the number of sectors user wants to write + if 'file_sector_offset' in kwargs: + file_sector_offset = kwargs['file_sector_offset'] + if 'check_card_length' in kwargs: + check_card_length = kwargs['check_card_length'] + + ## HACK what is current_open_partition here? + + if current_open_partition is None: + device_log("=" * 78, 1) + device_log("ERROR: No partition is opened, can't continue", 1) + device_log("=" * 78, 1) + sys.exit(1) + + device_log("Current open partition is %d" % (current_open_partition), 1) + if current_open_partition in partition_sizes_cache: + NumPartitionSectors = partition_sizes_cache[current_open_partition] + else: + device_log("=" * 78, 1) + device_log( + "WARNING: Current partition size is unknown. Please run command 0x23 (PartitionOperations) on it first.", 1) + device_log("WARNING: Assuming partition is of size 64GB in order to continue!!.", 1) + device_log("=" * 78, 1) + # sys.exit(1) + partition_sizes_cache[current_open_partition] = 137438953472 ## this is 64GB in sectors + NumPartitionSectors = partition_sizes_cache[current_open_partition] + + device_log("NumPartitionSectors %d" % (NumPartitionSectors), 1) + device_log("start_sector '%d'" % start_sector, 1) + + if start_sector < 0: + start_sector = NumPartitionSectors + start_sector + device_log("start_sector was negative, assuming it's an offset from the end, set to '%d'" % start_sector, 1) + + if NumPartitionSectors <= 0: + device_log("=" * 78, 1) + device_log("ERROR: Current partition open has size 0. Can't continue", 1) + device_log("=" * 78, 1) + sys.exit(1) + + filename = find_file(filename, search_paths) + if filename == None: + device_log("ERROR: File not found. Can't continue", 1) + sys.exit(1) + + file_disk_size = getsize(filename) ## file size in terms of bytes + device_log("Filename: '%s' (%s)" % (filename, ReturnSizeString(file_disk_size)), 1) + + FileSizeInSectors = int(file_disk_size / SECTOR_SIZE) ## file size in terms of sectors + if file_disk_size % SECTOR_SIZE > 0: + FileSizeInSectors += 1 + + device_log("FileSizeInSectors %d" % (FileSizeInSectors), 1) + device_log("file_sector_offset %d" % (file_sector_offset), 1) + device_log("num_file_sectors %d" % (num_file_sectors), 1) + device_log("NumPartitionSectors %d" % (NumPartitionSectors), 1) + device_log("start_sector %d" % (start_sector), 1) + + if num_file_sectors == 0: + num_file_sectors = FileSizeInSectors - file_sector_offset ## whole file then + device_log("num_file_sectors %d" % (num_file_sectors), 1) + + if NumPartitionSectors - start_sector < num_file_sectors: ## has user specified a file too big for this partition + device_log("=" * 78, 1) + device_log( + "ERROR: The partition offsets you provided OR the num_file_sectors (FILE) is too big for this PHY partition", + 1) + device_log("=" * 78, 1) + sys.exit(1) + + fp = None + try: + fp = open(filename, 'rb') + except: + device_log("\nERROR: Could not open '%s' for writing" % filename, 1) + sys.exit(1) + + try: + fp.seek(int(file_sector_offset * SECTOR_SIZE)) + except: + device_log("\nERROR: Could not seek to sector %d in '%s'" % (file_sector_offset, filename), 1) + sys.exit(1) + + # max_window_size = 1 + NumWindows = max_window_size + TotalFileSectors = num_file_sectors + + while num_file_sectors > 0: + device_log("In WHILE: num_file_sectors=%d" % num_file_sectors, 0) + + ## Phase 1: Prepare NumWindows worth of packets to send + for i in range(NumWindows): + if i % 9 == 0: + device_log("-" * 78) + device_log("Progress: %i %%" % (100 * (TotalFileSectors - num_file_sectors) / TotalFileSectors), 1) + device_log("-" * 78) + + if num_file_sectors < int(PayloadSize / SECTOR_SIZE): + PayloadSize = int(num_file_sectors * SECTOR_SIZE) ## i.e. could be only 1 sector left + try: + data = fp.read(PayloadSize) + except: + device_log("ERROR: Could not read %d bytes from '%s'" % (PayloadSize, filename), 1) + sys.exit(1) + + if len(data) == 0: + device_log("Reached end of file, num_file_sectors = 0", 0) + num_file_sectors = 0 + break + else: + device_log("len(data)=%d bytes, PayloadSize=%d bytes" % (len(data), PayloadSize), 0) + + device_log("Building packet to send", 0) + packet = [] + if sector_addresses is True: + packet.extend(int_to_hex_list(start_sector, 4)[::-1]) + device_log("(%.2d:%d) STREAMING: Sending %4d bytes for address 0x%08X (%d)" % ( + i + 1, NumWindows, len(data), start_sector, start_sector), 0) + else: + packet.extend(int_to_hex_list(start_sector * SECTOR_SIZE, 4)[::-1]) + device_log("(%.2d:%d) STREAMING: Sending %4d bytes for address 0x%08X (%d)" % ( + i + 1, NumWindows, len(data), start_sector * SECTOR_SIZE, start_sector * SECTOR_SIZE), 0) + + packet.extend(data) + + SendCommand(EHOST_STREAM_WRITE_REQ, packet_data=packet) + + start_sector += int(PayloadSize / SECTOR_SIZE) + num_file_sectors -= int(PayloadSize / SECTOR_SIZE) ## sectors remaining + + device_log("-" * 78) + device_log("Progress: %i %%" % (100 * (TotalFileSectors - num_file_sectors) / TotalFileSectors), 1) + device_log("-" * 78) + + device_log("STREAMING: After the for i in range(NumWindows) loop, i=%d, NumWindows=%d " % (1, NumWindows), 0) + + if num_file_sectors == 0: + device_log("STREAMING: Reached end of file, now setting NumWindows to %d" % (i), 0) + NumWindows = i ## In case it broke out early above due to hitting the end of the file + + ## Phase 2: Look for ACKs + device_log("STREAMING: Begin looking for ACKs ", 0) + ## Phase 2: Look for ACKs from previous writes + AcksReceived = 0 + while AcksReceived < NumWindows: + data_read = BlockForResponse(EHOST_STREAM_WRITE_RSP) + address = hex_list_to_int(data_read[1:4][::-1]) + device_log("STREAMING: Device responded to the write for address 0x%08X (%d)" % (address, address), 0) + AcksReceived += 1 + + # end of while start_sector < EndSector: + + try: + fp.close() + except: + pass + + if 'partition' in kwargs: + CloseMultiImage(partition=kwargs['partition']) + +def BlockForResponse(CmdCode): + while True: + data_read = GetNextPacket() + if data_read[0] == 0: + device_log('STREAMING: Something went wrong, please see port_trace.txt', 1) + sys.exit(1) + elif data_read[0] == CmdCode: + return data_read + elif data_read[0] == EHOST_LOG and MODE_IS_STREAMING == 1: + sz = ''.join([chr(b) for b in data_read[1:]]) + device_log('\nSTREAMING: LOG MESSAGE: "%s"' % sz.rstrip(), 1) + elif data_read[0] == EHOST_ERROR_RSP and MODE_IS_STREAMING == 1: + # import pdb; pdb.set_trace() + sz = ''.join([chr(b) for b in data_read[5:]]) + reason = hex_list_to_int(data_read[1:5][::-1]) + + if reason < len(EHOST_ERROR_CODES): + szReason = EHOST_ERROR_CODES[reason] + else: + szReason = "Uknown Reason Code" + + device_log('\nSTREAMING: ERROR: "%s", Reason %d "%s"' % (sz.rstrip(), reason, szReason), 1) + sys.exit(1) + +FSM = StateMachine() +FSM.add_state(Hello) ## All streaming operations begin +FSM.add_state(SecurityMode) ## with these two commands + +def do_dload(COM_PORT, hex_filename): + + MODE_IS_STREAMING = 0 + + port_open(COM_PORT) + if True == check_for_target(): + get_max_write() + device_log("Need to parse 'hex_transfer_address' from HEX file",1) + transfer_hex(hex_filename, 0) + set_max_write_size(DLOAD_MAX_WRITE_SIZE) + print "\n" + size = os.path.getsize(hex_filename) + device_log("Starting DLOAD transfer of '%s' (%i bytes)\n" % (hex_filename,size),1) + transfer_hex(hex_filename) + device_log("="*78,1) + device_log("100%% '%s' transfer complete" % hex_filename,1) + device_log("="*78+"\n",1) + + device_log("DLOAD: sending GO command to begin running HEX file",1) + + send_go_command(hex_filename) + port_close() + +def usage(): + print """ +Usage: python db600c_flasher.py [OPTION...] +Emulates QPST Emergency download. + + Options: + -p, --port COM/serial Port + -d, --dload HEX file to transfer over DLOAD (MPRG8064.hex) + -i, --image image to (singleimage.bin) + + Example: + For Windows machine: + python db600c_flasher.py -p COM26 -d MPRG8064.hex -i singleimage.bin + For Linux machine: + sudo python db600c_flasher.py -p /dev/ttyUSB0 -d MPRG8064.hex -i singleimage.bin """ + +def ParseCommandLineOptions(): + global COM_PORT,verbose,hex_filename,DoDLOAD,DoStreaming,SEARCH_CWD_LAST,search_paths,streaming_erase,temp_patch_filename + + try: + opts, args = getopt.getopt(sys.argv[1:], "p:d:i:v?k:f:s:ewx:ngqz:", ["port=", "dload=", "image=", "verbose", "help", "disk=", "files=", "search_path=", "erase", "wipe", "xml=", "new", "gpp", "quick", "send_data="]) + except getopt.GetoptError, err: + # print help information and exit: + print str(err) # will print something like "option -a not recognized" + usage() + sys.exit(1) + + ## Command line will over ride anything in the XML file + for o, a in opts: + if o in ("-p", "--port"): + COM_PORT = a + print "COM_PORT=",COM_PORT + if COM_PORT.lower().startswith('com'): + COM_PORT = '\\\\.\\' + COM_PORT.upper() + print "COM_PORT=",COM_PORT + elif o in ("-d", "--dload"): + hex_filename= a + DoDLOAD = True + elif o in ("-i", "--image"): + FSM.add_state(OpenMultiImage,partition=PRTN_EMMCUSER) + FSM.add_state(Write, filename=a) + FSM.add_state(CloseMultiImage) + else: + assert False, "unhandled option" + + if SEARCH_CWD_LAST: + search_paths.append(os.getcwd()) ## Put CWD at the end of search paths + else: + search_paths.insert(0, os.getcwd()) ## put CWD at the beginning of search paths + + if FSM.num_states()>2: + DoStreaming = True # if more than the default 2 states then there must have been streaming commands added + +def main(): + global DidStuff,hex_filename,search_paths + + #if (date(2011, 11, 17)-date.today()).days < 0: + # device_log("EXITING. Upgrade to a newer version.\n", 1) + + if len(sys.argv)<=1: + usage() + sys.exit(1) + + ParseCommandLineOptions() + + reset_device_log() + + if verbose: + enable_full_dump() + + ## Test for DLOAD + if DoDLOAD: + MODE_IS_STREAMING = 0 + if hex_filename is None: + print "\nERROR: No HEX file specified for DLOAD. i.e. for 8960 it's called MPRG8960.hex" + sys.exit() + + DidStuff = True + hex_filename = find_file(hex_filename,search_paths) + if hex_filename is None: + print "\nERROR: Could not find HEX file you listed" + sys.exit() + if not os.path.exists(hex_filename): + device_log("ERROR: Could not open '%s'\n" % hex_filename,1) + sys.exit(1) + size = os.path.getsize(hex_filename) + device_log("Starting DLOAD transfer",1) + do_dload(COM_PORT, hex_filename) + sleep(4) + + if DoStreaming: + MODE_IS_STREAMING = 1 + search_paths = search_paths + FSM.show_states() ## in log only + + DidStuff = True + + port_open(COM_PORT) + + FSM.add_state(Reset) + FSM.run() + + port_close() + sleep(4) + + sys.exit(1) + + if DidStuff == False: + print "=" * 78 + print "ERROR: Nothing to do. - Nothing to do - Nothing to do - Nothing to do" + print "=" * 78 + print "\nPlease specify a HEX file to send -d, or IMAGE to send -i\n" + print "Or run \"python db600c_flasher.py\" to see usage\n" + +if __name__ == "__main__": + start_time = time() + main() + end_time = time() + print "\nTime taken: %0.2f seconds\n" % (end_time-start_time)
\ No newline at end of file |