2021-12-18 14:20:30 +02:00
|
|
|
# Command interface for Unisoc chipsets
|
|
|
|
|
# Created by Luxferre in 2021
|
|
|
|
|
|
|
|
|
|
from struct import pack, unpack
|
|
|
|
|
|
|
|
|
|
UNICMD_CRC_MISMATCH = 0xd00b
|
|
|
|
|
|
|
|
|
|
# HDLC frame encoding/decoding (Unisoc modification)
|
|
|
|
|
|
|
|
|
|
def crc16_xmodem(data: bytes): # xmodem used in boot mode
|
|
|
|
|
crc = 0
|
|
|
|
|
data = bytearray(data)
|
|
|
|
|
msb = crc >> 8
|
|
|
|
|
lsb = crc & 255
|
|
|
|
|
for c in data:
|
|
|
|
|
x = (0xFF & c) ^ msb
|
|
|
|
|
x ^= (x >> 4)
|
|
|
|
|
msb = (lsb ^ (x >> 3) ^ (x << 4)) & 255
|
|
|
|
|
lsb = (x ^ (x << 5)) & 255
|
|
|
|
|
return (msb << 8) + lsb
|
|
|
|
|
|
|
|
|
|
def crc16_fdl(data: bytes): # used in FDL1/2 mode
|
|
|
|
|
crc = 0
|
|
|
|
|
data = bytearray(data)
|
|
|
|
|
l = len(data)
|
|
|
|
|
for i in range(0,l,2):
|
|
|
|
|
if i+1 == l:
|
|
|
|
|
crc += data[i]
|
|
|
|
|
else:
|
|
|
|
|
crc += (data[i]<<8)|data[i+1]
|
|
|
|
|
crc = (crc >> 16) + (crc & 0xffff)
|
|
|
|
|
crc += (crc >> 16)
|
|
|
|
|
return ~crc & 0xffff
|
|
|
|
|
|
|
|
|
|
def hdlc_encode(data, fdl = False, nocrc = False):
|
|
|
|
|
if nocrc:
|
|
|
|
|
crc = 0
|
|
|
|
|
else:
|
|
|
|
|
if fdl:
|
|
|
|
|
crc = crc16_fdl(data)
|
|
|
|
|
else:
|
|
|
|
|
crc = crc16_xmodem(data)
|
|
|
|
|
out = []
|
2021-12-20 01:16:41 +02:00
|
|
|
rdata = bytearray(data + pack('>H', crc))
|
|
|
|
|
for c in rdata:
|
2021-12-18 14:20:30 +02:00
|
|
|
if c == 0x7e or c == 0x7d:
|
|
|
|
|
out.append(0x7d)
|
|
|
|
|
out.append(c ^ 0x20)
|
|
|
|
|
else:
|
|
|
|
|
out.append(c)
|
|
|
|
|
out = bytes(out)
|
2021-12-20 01:16:41 +02:00
|
|
|
return b'\x7e' + out + b'\x7e'
|
2021-12-18 14:20:30 +02:00
|
|
|
|
|
|
|
|
def hdlc_decode(data, fdl = False, ignoreCrc = False): # HDLC bug in Unisoc: CRC is also encoded!!!
|
|
|
|
|
rawdata = bytearray(data[1:-1])
|
|
|
|
|
out = []
|
|
|
|
|
esc = False
|
|
|
|
|
for c in rawdata:
|
|
|
|
|
if esc:
|
|
|
|
|
if c == 0x5e or c == 0x5d:
|
|
|
|
|
out.append(c ^ 0x20)
|
|
|
|
|
esc = False
|
|
|
|
|
else:
|
|
|
|
|
raise Exception("Invalid escape sequence while decoding HDLC frame")
|
|
|
|
|
elif c == 0x7d:
|
|
|
|
|
esc = True
|
|
|
|
|
else:
|
|
|
|
|
out.append(c)
|
|
|
|
|
decoded = bytes(out)
|
|
|
|
|
rawcrc = unpack('>H', decoded[-2:])[0]
|
|
|
|
|
decoded = decoded[:-2]
|
|
|
|
|
if fdl:
|
|
|
|
|
calc_crc = crc16_fdl(decoded)
|
|
|
|
|
else:
|
|
|
|
|
calc_crc = crc16_xmodem(decoded)
|
|
|
|
|
if ignoreCrc: # don't hard assert but return a special error code on CRC mismatch
|
|
|
|
|
if rawcrc != calc_crc:
|
|
|
|
|
return UNICMD_CRC_MISMATCH
|
|
|
|
|
else:
|
|
|
|
|
assert rawcrc == calc_crc, "Actual CRC16 value %04x does not match calculated value %04x after decoding HDLC frame" % (rawcrc, calc_crc)
|
|
|
|
|
return decoded
|
|
|
|
|
|
|
|
|
|
def resp_decode(data, fdl = False, ignoreCrc = False):
|
|
|
|
|
rawdata = hdlc_decode(data, fdl, ignoreCrc)
|
|
|
|
|
if rawdata != UNICMD_CRC_MISMATCH:
|
|
|
|
|
respcode, resplen = unpack('>HH', rawdata[:4])
|
|
|
|
|
content = rawdata[4:4+resplen]
|
|
|
|
|
return respcode, resplen, content
|
|
|
|
|
else:
|
|
|
|
|
return UNICMD_CRC_MISMATCH, 0, None
|
|
|
|
|
|
|
|
|
|
# Unisoc command set constants
|
|
|
|
|
|
|
|
|
|
FLAG_BYTE = 0x7E
|
|
|
|
|
|
|
|
|
|
BSL_PKT_TYPE_MIN = 0
|
|
|
|
|
|
|
|
|
|
# PC -> phone commands
|
|
|
|
|
|
|
|
|
|
BSL_CMD_CONNECT = BSL_PKT_TYPE_MIN
|
|
|
|
|
|
|
|
|
|
BSL_CMD_START_DATA = 1
|
|
|
|
|
BSL_CMD_MIDST_DATA = 2
|
|
|
|
|
BSL_CMD_END_DATA = 3
|
|
|
|
|
BSL_CMD_EXEC_DATA = 4
|
|
|
|
|
|
|
|
|
|
BSL_CMD_NORMAL_RESET = 5
|
|
|
|
|
BSL_CMD_READ_FLASH = 6
|
|
|
|
|
BSL_CMD_READ_CHIP_TYPE = 7
|
|
|
|
|
BSL_CMD_READ_NVITEM = 8
|
|
|
|
|
BSL_CMD_CHANGE_BAUD = 9
|
|
|
|
|
BSL_CMD_ERASE_FLASH = 0xa
|
|
|
|
|
BSL_CMD_REPARTITION = 0xb
|
|
|
|
|
BSL_CMD_READ_FLASH_TYPE = 0xc
|
|
|
|
|
BSL_CMD_READ_FLASH_INFO = 0xd
|
|
|
|
|
BSL_CMD_READ_SECTOR_SIZE = 0xf
|
|
|
|
|
|
|
|
|
|
BSL_CMD_READ_START = 0x10
|
|
|
|
|
BSL_CMD_READ_MIDST = 0x11
|
|
|
|
|
BSL_CMD_READ_END = 0x12
|
|
|
|
|
|
|
|
|
|
BSL_CMD_KEEP_CHARGE = 0x13
|
|
|
|
|
BSL_CMD_EXTTABLE = 0x14
|
|
|
|
|
BSL_CMD_READ_FLASH_UID = 0x15
|
|
|
|
|
BSL_CMD_READ_SOFTSIM_EID = 0x16
|
|
|
|
|
BSL_CMD_POWER_OFF = 0x17
|
|
|
|
|
BSL_CMD_CHECK_ROOT = 0x19
|
|
|
|
|
BSL_CMD_READ_CHIP_UID = 0x1a
|
|
|
|
|
BSL_CMD_ENABLE_WRITE_FLASH = 0x1b
|
|
|
|
|
BSL_CMD_ENABLE_SECUREBOOT = 0x1c
|
|
|
|
|
BSL_CMD_READ_RF_TRANSCEIVER_TYPE = 0x24
|
|
|
|
|
BSL_CMD_CHECK_BAUD = FLAG_BYTE
|
|
|
|
|
|
|
|
|
|
BSL_DDR_VERIFY = 0x26
|
|
|
|
|
|
|
|
|
|
BSL_CMD_END_PROCESS = 0x7F
|
|
|
|
|
|
|
|
|
|
# Phone -> PC responses
|
|
|
|
|
|
|
|
|
|
BSL_REP_TYPE_MIN = 0x80
|
|
|
|
|
BSL_REP_ACK = BSL_REP_TYPE_MIN
|
|
|
|
|
BSL_REP_VER = 0x81
|
|
|
|
|
BSL_REP_INVALID_CMD = 0x82
|
|
|
|
|
BSL_REP_UNKNOWN_CMD = 0x83
|
|
|
|
|
BSL_REP_OPERATION_FAILED = 0x84
|
|
|
|
|
BSL_REP_NOT_SUPPORT_BAUDRATE = 0x85
|
|
|
|
|
|
|
|
|
|
BSL_REP_DOWN_NOT_START = 0x86
|
|
|
|
|
BSL_REP_DOWN_MULTI_START = 0x87
|
|
|
|
|
BSL_REP_DOWN_EARLY_END = 0x88
|
|
|
|
|
BSL_REP_DOWN_DEST_ERROR = 0x89
|
|
|
|
|
BSL_REP_DOWN_SIZE_ERROR = 0x8A
|
|
|
|
|
BSL_REP_VERIFY_ERROR = 0x8B
|
|
|
|
|
BSL_REP_NOT_VERIFY = 0x8C
|
|
|
|
|
|
|
|
|
|
BSL_PHONE_NOT_ENOUGH_MEMORY = 0x8D
|
|
|
|
|
BSL_PHONE_WAIT_INPUT_TIMEOUT = 0x8E
|
|
|
|
|
|
|
|
|
|
BSL_PHONE_SUCCEED = 0x8F
|
|
|
|
|
BSL_PHONE_VALID_BAUDRATE = 0x90
|
|
|
|
|
BSL_PHONE_REPEAT_CONTINUE = 0x91
|
|
|
|
|
BSL_PHONE_REPEAT_BREAK = 0x92
|
|
|
|
|
|
|
|
|
|
BSL_REP_READ_FLASH = 0x93
|
|
|
|
|
BSL_REP_READ_CHIP_TYPE = 0x94
|
|
|
|
|
BSL_REP_READ_NVITEM = 0x95
|
|
|
|
|
|
|
|
|
|
BSL_REP_INCOMPATIBLE_PARTITION = 0x96
|
|
|
|
|
BSL_REP_UNKNOWN_DEVICE = 0x97
|
|
|
|
|
BSL_REP_INVALID_DEVICE_SIZE = 0x98
|
|
|
|
|
BSL_REP_ILLEGAL_SDRAM = 0x99
|
|
|
|
|
BSL_WRONG_SDRAM_PARAMETER = 0x9A
|
|
|
|
|
BSL_REP_READ_FLASH_INFO = 0x9B
|
|
|
|
|
BSL_REP_READ_SECTOR_SIZE = 0x9C
|
|
|
|
|
BSL_REP_READ_FLASH_TYPE = 0x9D
|
|
|
|
|
BSL_REP_READ_FLASH_UID = 0x9E
|
|
|
|
|
BSL_REP_READ_SOFTSIM_EID = 0x9F
|
|
|
|
|
|
|
|
|
|
BSL_ERROR_CHECKSUM = 0xA0
|
|
|
|
|
BSL_CHECKSUM_DIFF = 0xA1
|
|
|
|
|
BSL_WRITE_ERROR = 0xA2
|
|
|
|
|
BSL_CHIPID_NOT_MATCH = 0xA3
|
|
|
|
|
BSL_FLASH_CFG_ERROR = 0xA4
|
|
|
|
|
BSL_REP_DOWN_STL_SIZE_ERROR = 0xA5
|
2021-12-20 12:53:02 +02:00
|
|
|
BSL_REP_SECURITY_VERIFICATION_FAIL = 0xA6
|
2021-12-18 14:20:30 +02:00
|
|
|
BSL_REP_PHONE_IS_ROOTED = 0xA7
|
|
|
|
|
BSL_REP_SEC_VERIFY_ERROR = 0xAA
|
|
|
|
|
BSL_REP_READ_CHIP_UID = 0xAB
|
|
|
|
|
BSL_REP_NOT_ENABLE_WRITE_FLASH = 0xAC
|
|
|
|
|
BSL_REP_ENABLE_SECUREBOOT_ERROR = 0xAD
|
|
|
|
|
BSL_REP_FLASH_WRITTEN_PROTECTION = 0xB3
|
|
|
|
|
BSL_REP_FLASH_INITIALIZING_FAIL = 0xB4
|
|
|
|
|
BSL_REP_RF_TRANSCEIVER_TYPE = 0xB5
|
|
|
|
|
|
|
|
|
|
BSL_REP_UNSUPPORTED_COMMAND = 0xFE
|
|
|
|
|
BSL_REP_LOG = 0xFF
|
|
|
|
|
BSL_PKT_TYPE_MAX = 0x100
|
|
|
|
|
|
|
|
|
|
BSL_UART_SEND_ERROR = 0x101
|
|
|
|
|
BSL_REP_DECODE_ERROR = 0x102
|
|
|
|
|
BSL_REP_INCOMPLETE_DATA = 0x103
|
|
|
|
|
BSL_REP_READ_ERROR = 0x104
|
|
|
|
|
BSL_REP_TOO_MUCH_DATA = 0x105
|
|
|
|
|
BSL_USER_CANCEL = 0x106
|
|
|
|
|
BSL_REP_SIZE_ZERO = 0x107
|
|
|
|
|
BSL_REP_PORT_ERROR = 0x108
|
|
|
|
|
|
|
|
|
|
# Unisoc command packet interface
|
|
|
|
|
|
|
|
|
|
def shape_cmd_packet(command):
|
|
|
|
|
return pack('>HH', command, 0)
|
|
|
|
|
|
|
|
|
|
def shape_data_packet(dtype, data, dlen = 0):
|
|
|
|
|
if dlen == 0:
|
|
|
|
|
dlen = len(data)
|
|
|
|
|
#if dlen&1:
|
|
|
|
|
# dlen += 1
|
|
|
|
|
packethdr = pack('>HH', dtype, dlen)
|
|
|
|
|
return packethdr + data
|
|
|
|
|
|
|
|
|
|
def cmd_data_start(targetAddr, targetLen):
|
|
|
|
|
datahdr = pack('>LL', targetAddr, targetLen)
|
|
|
|
|
return shape_data_packet(BSL_CMD_START_DATA, datahdr)
|
|
|
|
|
|
|
|
|
|
def cmd_data_send(data):
|
|
|
|
|
return shape_data_packet(BSL_CMD_MIDST_DATA, data)
|
|
|
|
|
|
|
|
|
|
def cmd_data_end():
|
|
|
|
|
return shape_cmd_packet(BSL_CMD_END_DATA)
|
|
|
|
|
|
|
|
|
|
def cmd_data_exec(targetAddr):
|
|
|
|
|
datahdr = pack('>L', targetAddr)
|
|
|
|
|
return shape_data_packet(BSL_CMD_EXEC_DATA, datahdr)
|
|
|
|
|
|
|
|
|
|
def cmd_connect():
|
|
|
|
|
return shape_cmd_packet(BSL_CMD_CONNECT)
|
|
|
|
|
|
|
|
|
|
def cmd_reset():
|
|
|
|
|
return shape_cmd_packet(BSL_CMD_NORMAL_RESET)
|
|
|
|
|
|
|
|
|
|
def cmd_sync():
|
|
|
|
|
return pack('>H', BSL_CMD_CHECK_BAUD)
|
|
|
|
|
|
|
|
|
|
def cmd_sync_full(baudrate = 921600):
|
|
|
|
|
datahdr = pack('>L', baudrate)
|
|
|
|
|
return shape_data_packet(BSL_CMD_CHANGE_BAUD, datahdr)
|
|
|
|
|
|
|
|
|
|
def cmd_read_chip_type():
|
|
|
|
|
return shape_cmd_packet(BSL_CMD_READ_CHIP_TYPE)
|
|
|
|
|
|
|
|
|
|
def cmd_read_sector_size():
|
|
|
|
|
return shape_cmd_packet(BSL_CMD_READ_SECTOR_SIZE)
|
|
|
|
|
|
|
|
|
|
def cmd_read_flash_info():
|
|
|
|
|
return shape_cmd_packet(BSL_CMD_READ_FLASH_INFO)
|
|
|
|
|
|
|
|
|
|
def cmd_read_flash(targetAddr, targetLen, offset):
|
|
|
|
|
return pack('>HHLLL', BSL_CMD_READ_FLASH, 12, targetAddr, targetLen, offset)
|
2021-12-20 12:53:02 +02:00
|
|
|
|
|
|
|
|
def cmd_erase_flash(targetAddr, targetLen):
|
|
|
|
|
datahdr = pack('>LL', targetAddr, targetLen)
|
|
|
|
|
return shape_data_packet(BSL_CMD_ERASE_FLASH, datahdr)
|
|
|
|
|
|
|
|
|
|
def cmd_end_flash_process():
|
|
|
|
|
return shape_cmd_packet(BSL_CMD_END_PROCESS)
|