summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Hanna Sedlak Grinbaum <asedla@codeaurora.org>2017-06-25 16:07:25 +0300
committerNicolas Dechesne <nicolas.dechesne@linaro.org>2017-11-27 14:44:49 +0100
commitbad05b88cb0359877387187d7a15986ac595b0ef (patch)
treebf1dd109dc95aaf58eab0f2ebe2b670ce274d310
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.py1378
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