rjw | 2e8229f | 2022-02-15 21:08:12 +0800 | [diff] [blame] | 1 | # SPDX-License-Identifier: BSD-3-Clause |
| 2 | # |
| 3 | # Copyright (C) MediaTek Inc. |
| 4 | # Author: Joe Yang <joe.yang@mediatek.com> |
| 5 | # |
| 6 | |
xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 7 | #!/usr/bin/env python |
rjw | 2e8229f | 2022-02-15 21:08:12 +0800 | [diff] [blame] | 8 | # -*- coding: utf-8 -*- |
| 9 | import serial |
| 10 | import serial.tools.list_ports as ser_tools |
xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 11 | import sys, time, struct, logging |
| 12 | from optparse import OptionParser |
| 13 | try: |
| 14 | # python2 |
| 15 | import ConfigParser as configparser |
| 16 | except ImportError: |
| 17 | # python3 |
| 18 | import configparser |
| 19 | |
| 20 | class Fbtool: |
| 21 | def __init__(self, config_file, meid=False): |
| 22 | self.TGT_CFG_SBC_EN = 0x00000001 |
| 23 | self.TGT_CFG_SLA_EN = 0x00000002 |
| 24 | self.TGT_CFG_DAA_EN = 0x00000004 |
| 25 | self.E_ERROR = 0x1000 |
| 26 | self.__ser = None |
| 27 | self.__connect_type = 'UNKNOWN' |
| 28 | self.__meid = meid |
| 29 | cfg = configparser.ConfigParser() |
| 30 | cfg.read(config_file) |
| 31 | self.__da1_path = cfg.get('DA1', 'da1_path') |
| 32 | self.__da1_addr = int(cfg.get('DA1', 'da1_addr'), 16) |
| 33 | self.__da1_jump_64 = int(cfg.get('DA1', 'da1_jump_64'), 16) |
| 34 | self.__da2_path = cfg.get('DA2', 'da2_path') |
| 35 | self.__da2_addr = int(cfg.get('DA2', 'da2_addr'), 16) |
| 36 | self.__auth_path = cfg.get('Auth', 'auth_path') |
| 37 | self.__cert_path = cfg.get('Cert', 'cert_path') |
| 38 | self.__fall_thru_to_fb = int(cfg.get('FALL_THRU_TO_FB', 'fall_thru_to_fb')) |
| 39 | logging.debug('da1_path: %s' %(self.__da1_path)) |
| 40 | logging.debug('da1_addr: 0x%x' %(self.__da1_addr)) |
| 41 | logging.debug('da1_jump_64: 0x%x' %(self.__da1_jump_64)) |
| 42 | logging.debug('da2_path: %s' %(self.__da2_path)) |
| 43 | logging.debug('ad2_addr: 0x%x' %(self.__da2_addr)) |
| 44 | logging.debug('auth_path: %s' %(self.__auth_path)) |
| 45 | logging.debug('cert_path: %s' %(self.__cert_path)) |
| 46 | |
| 47 | def __del__(self): |
| 48 | # compatible with pySerial 2.6. |
| 49 | # isOpen() is deprecated since version 3.0, 3.0 uses is_open |
| 50 | if self.__ser and self.__ser.isOpen(): |
| 51 | self.__ser.close() |
| 52 | |
| 53 | def __match_usb_br(self, vid, pid): |
| 54 | if vid == 0x0e8d and pid == 0x0003: |
| 55 | self.__connect_type = 'BROM' |
| 56 | return True |
| 57 | return False |
| 58 | |
| 59 | def __match_usb_bl(self, vid, pid): |
| 60 | if ((vid == 0x0e8d and pid == 0x2000) or (vid == 0x0e8d and pid == 0x3000)): |
| 61 | self.__connect_type = 'BOOTLOADER' |
| 62 | return True |
| 63 | return False |
| 64 | |
| 65 | def __match_usb_auto(self, vid, pid): |
| 66 | if self.__match_usb_br(vid, pid): |
| 67 | return True |
| 68 | if self.__match_usb_bl(vid, pid): |
| 69 | return True |
| 70 | return False |
| 71 | |
| 72 | def __open_usb_device(self, match_usb_func, comport, vid, pid): |
| 73 | if match_usb_func(vid, pid): |
| 74 | time.sleep(0.1) |
| 75 | try: |
| 76 | self.__ser = serial.Serial(comport, 115200) |
| 77 | except serial.SerialException as e: |
rjw | 2e8229f | 2022-02-15 21:08:12 +0800 | [diff] [blame] | 78 | logging.info('%s, retry...' %(str(e))) |
xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 79 | else: |
| 80 | logging.info('Got %s' %(comport)) |
| 81 | return True |
| 82 | return False |
| 83 | |
| 84 | def __find_usb_device(self, match_usb_func): |
| 85 | while True: |
| 86 | ports = ser_tools.comports() |
| 87 | if serial.VERSION < '3': |
| 88 | ports_list = list(ports) |
| 89 | for port in ports_list: |
| 90 | if 'USB' in port[2]: |
| 91 | if sys.platform.startswith('win'): |
| 92 | idx = port[2].index('VID_')+4 |
| 93 | vid = int(port[2][idx : idx + 4], 16) |
| 94 | idx = port[2].index('PID_')+4 |
| 95 | pid = int(port[2][idx : idx + 4], 16) |
| 96 | elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): |
| 97 | idx = port[2].index('VID:PID=') + 8 |
| 98 | vid = int(port[2][idx : idx + 4], 16) |
| 99 | pid = int(port[2][idx + 5 : idx + 13], 16) |
| 100 | elif sys.platform.startswith('darwin'): |
| 101 | raise EnvironmentError('Unsupport macOS') |
| 102 | else: |
| 103 | raise EnvironmentError('Unsupported platform') |
| 104 | if self.__open_usb_device(match_usb_func, port[0], vid, pid): |
| 105 | return |
| 106 | else: |
| 107 | for port in ports: |
| 108 | if self.__open_usb_device(match_usb_func, port.device, port.vid, port.pid): |
| 109 | return |
| 110 | |
| 111 | def __read8(self): |
| 112 | data = struct.unpack('!B', self.__ser.read())[0] |
| 113 | logging.debug("RECV 0x%X" %data) |
| 114 | return data |
| 115 | |
| 116 | def __read16(self): |
| 117 | data = struct.unpack('!H', self.__ser.read(2))[0] |
| 118 | logging.debug("RECV 0x%X" %data) |
| 119 | return data |
| 120 | |
| 121 | def __read32(self): |
| 122 | data = struct.unpack('!I', self.__ser.read(4))[0] |
| 123 | logging.debug("RECV 0x%X" %data) |
| 124 | return data |
| 125 | |
| 126 | def __write8(self, data, echo): |
| 127 | logging.debug("SEND 0x%X" %data) |
| 128 | self.__ser.write(struct.pack('!B', data)) |
| 129 | if echo: |
| 130 | val = struct.unpack('!B', self.__ser.read())[0] |
| 131 | logging.debug("RECV 0x%X" %val) |
| 132 | return val == data |
| 133 | return True |
| 134 | |
| 135 | def __write16(self, data, echo): |
| 136 | logging.debug("SEND 0x%X" %data) |
| 137 | self.__ser.write(struct.pack('!H', data)) |
| 138 | if echo: |
| 139 | val = struct.unpack('!H', self.__ser.read(2))[0] |
| 140 | logging.debug("RECV 0x%X" %val) |
| 141 | return val == data |
| 142 | return True |
| 143 | |
| 144 | def __write32(self, data, echo): |
| 145 | logging.debug("SEND 0x%X" %data) |
| 146 | self.__ser.write(struct.pack('!I', data)) |
| 147 | if echo: |
| 148 | val = struct.unpack('!I', self.__ser.read(4))[0] |
| 149 | logging.debug("RECV 0x%X" %val) |
| 150 | return val == data |
| 151 | return True |
| 152 | |
| 153 | def __start_cmd(self): |
| 154 | cmd = (0xa0, 0x0a, 0x50, 0x05) |
| 155 | echo_cmd = (0x5f, 0xf5, 0xaf, 0xfa) |
| 156 | |
| 157 | i = 0 |
| 158 | while (i < len(cmd)): |
| 159 | self.__write8(cmd[i], False) |
| 160 | if self.__read8() != echo_cmd[i]: |
| 161 | i = 0 |
| 162 | self.__ser.flushInput() |
| 163 | else: |
| 164 | i = i + 1 |
| 165 | time.sleep(0.1) |
| 166 | # self.__ser.flush() |
| 167 | self.__ser.flushInput() |
| 168 | self.__ser.flushOutput() |
| 169 | if self.__connect_type == 'BROM': |
| 170 | logging.info('Connect brom') |
| 171 | elif self.__connect_type == 'BOOTLOADER': |
| 172 | logging.info('Connect bootloader') |
| 173 | |
| 174 | def __load_binary(self, path): |
| 175 | logging.info("Loading file: %s" %path) |
| 176 | with open(path, 'rb') as f: |
| 177 | return f.read() |
| 178 | |
| 179 | def __checksum(self, data, length): |
| 180 | checksum = 0 |
| 181 | for i in range(0, length, 2): |
| 182 | checksum ^= struct.unpack('<H', data[i:i+2])[0] |
| 183 | checksum &= 0xFFFF |
| 184 | return checksum |
| 185 | |
| 186 | def __get_target_config(self): |
| 187 | if not self.__write8(0xd8, True): |
| 188 | return -1, None |
| 189 | cfg = self.__read32() |
| 190 | status = self.__read16() |
| 191 | |
| 192 | if status >= self.E_ERROR: |
| 193 | return status, None |
| 194 | return 0, cfg |
| 195 | |
| 196 | def __send_auth(self, cfg): |
| 197 | if self.TGT_CFG_DAA_EN & cfg == 0: |
| 198 | return 0 |
| 199 | else: |
| 200 | if self.TGT_CFG_SBC_EN & cfg == 0: |
| 201 | logging.error('daa=1, sbc=0') |
| 202 | return -2 |
| 203 | if self.__auth_path == '': |
| 204 | logging.error('no auth file') |
| 205 | return -3 |
| 206 | auth = self.__load_binary(self.__auth_path) |
| 207 | auth_len = len(auth) |
| 208 | logging.debug("auth file size: 0x%x" %(auth_len)) |
| 209 | |
| 210 | if not self.__write8(0xe2, True): |
| 211 | return -4 |
| 212 | if not self.__write32(len(auth), True): |
| 213 | return -5 |
| 214 | |
| 215 | status = self.__read16() |
| 216 | if status >= self.E_ERROR: |
| 217 | return status |
| 218 | self.__ser.write(auth) |
| 219 | |
| 220 | # compare checksum |
| 221 | if self.__read16() != self.__checksum(auth, auth_len): |
| 222 | return -6 |
| 223 | |
| 224 | status = self.__read16() |
| 225 | if status >= self.E_ERROR: |
| 226 | return status |
| 227 | return 0 |
| 228 | |
| 229 | def __strip_pl_hdr(self, pl, pl_len): |
| 230 | # EMMC_HEADER_V1 |
| 231 | identifier, ver, dev_rw_unit = struct.unpack('12s2I', pl[:20]) |
| 232 | # GFH_FILE_INFO_V1 |
| 233 | gfh = pl[:56] |
| 234 | gfh_offset = 0 |
| 235 | |
| 236 | if identifier.strip(b'\0') == b'EMMC_BOOT' and ver == 1: |
| 237 | logging.debug('emmc_hdr: identifier:%s, ver:0x%08x, dev_rw_unit:0x%08x' %(identifier, ver, dev_rw_unit)) |
| 238 | # BR_Layout_v1 size: 40 |
| 239 | if dev_rw_unit + 40 > pl_len: |
| 240 | logging.error('EMMC HDR error. dev_rw_unit=0x%x, brlyt_size=0x%x, pl_len=0x%x' |
| 241 | %(dev_rw_unit, brlyt_size, pl_len)) |
| 242 | return False, None, None |
| 243 | |
| 244 | brlyt_identifier, brlyt_ver = struct.unpack('8sI', pl[dev_rw_unit:dev_rw_unit + 12]) |
| 245 | logging.debug('brlyt_identifier: %s, brlyt_ver=0x%x' %(brlyt_identifier, brlyt_ver)) |
| 246 | if brlyt_identifier.strip(b'\0') != b'BRLYT' or brlyt_ver != 1: |
| 247 | logging.error('BRLYT error. ver=0x%x, identifier=%s' %(brlyt_ver, brlyt_identifier)) |
| 248 | return False, None, None |
| 249 | # BL_Descriptor |
| 250 | bl_begin_dev_addr = struct.unpack('I', pl[dev_rw_unit + 28 : dev_rw_unit + 32])[0] |
| 251 | if bl_begin_dev_addr + 56 > pl_len: |
| 252 | logging.error('BRLYT error. bl_begin_dev_addr=0x%x' %bl_begin_dev_addr) |
| 253 | return False, None, None |
| 254 | # GFH_FILE_INFO_v1 |
| 255 | gfh = pl[bl_begin_dev_addr:bl_begin_dev_addr + 56] |
| 256 | gfh_offset = bl_begin_dev_addr |
| 257 | |
| 258 | gfh_struct =struct.unpack('I2H12sIH2B7I', gfh) |
| 259 | |
| 260 | gfh_magic_ver = gfh_struct[0] |
| 261 | gfh_type = gfh_struct[2] |
| 262 | gfh_identifier = gfh_struct[3] |
| 263 | gfh_file_len = gfh_struct[9] |
| 264 | gfh_jump_offset = gfh_struct[13] |
| 265 | gfh_sig_len = gfh_struct[12] |
| 266 | if (gfh_magic_ver & 0x00FFFFFF) == 0x004D4D4D and gfh_type == 0 and gfh_identifier.strip(b'\0') == b'FILE_INFO': |
| 267 | if gfh_file_len < gfh_jump_offset + gfh_sig_len: |
| 268 | logging.error('GFH error. pl_len=0x%x, file_len=0x%x, jump_offset=0x%x, sig_len=0x%x' |
| 269 | %(pl_len, gfh_file_len, gfh_jump_offset, gfh_sig_len)) |
| 270 | return False, None, None |
| 271 | logging.debug('gfh: magic_ver: 0x%08x' %gfh_struct[0]) |
| 272 | logging.debug('gfh: size: 0x%04x' %gfh_struct[1]) |
| 273 | logging.debug('gfh: type: 0x%04x' %gfh_struct[2]) |
| 274 | logging.debug('gfh: identifier: %s' %gfh_struct[3]) |
| 275 | logging.debug('gfh: file_ver: 0x%08x' %gfh_struct[4]) |
| 276 | logging.debug('gfh: file_type: 0x%04x' %gfh_struct[5]) |
| 277 | logging.debug('gfh: flash_dev: 0x%02x' %gfh_struct[6]) |
| 278 | logging.debug('gfh: sig_type: 0x%02x' %gfh_struct[7]) |
| 279 | logging.debug('gfh: load_addr: 0x%08x' %gfh_struct[8]) |
| 280 | logging.debug('gfh: file_len: 0x%08x' %gfh_struct[9]) |
| 281 | logging.debug('gfh: max_size: 0x%08x' %gfh_struct[10]) |
| 282 | logging.debug('gfh: content_offset: 0x%08x' %gfh_struct[11]) |
| 283 | logging.debug('gfh: sig_len: 0x%08x' %gfh_struct[12]) |
| 284 | logging.debug('gfh: jump_offset: 0x%08x' %gfh_struct[13]) |
| 285 | logging.debug('gfh: attr: 0x%08x' %gfh_struct[14]) |
| 286 | strip_pl_len = gfh_file_len - gfh_jump_offset - gfh_sig_len |
| 287 | start = gfh_offset + gfh_jump_offset |
| 288 | strip_pl = pl[start:start + strip_pl_len] |
| 289 | return (True, strip_pl, strip_pl_len) |
| 290 | else: |
| 291 | return (True, pl, pl_len) |
| 292 | |
| 293 | def __send_da(self, addr, da, da_len, sig, sig_len): |
| 294 | if not self.__write8(0xd7, True): |
| 295 | return -1 |
| 296 | if not self.__write32(addr, True): |
| 297 | return -2 |
| 298 | logging.debug('len: 0x%x' %(da_len + sig_len)) |
| 299 | if not self.__write32(da_len + sig_len, True): |
| 300 | return -3 |
| 301 | if not self.__write32(sig_len, True): |
| 302 | return -4 |
| 303 | status = self.__read16() |
| 304 | if status >= self.E_ERROR: |
| 305 | return status |
| 306 | |
| 307 | if da_len > 0: |
| 308 | logging.debug("Send DA") |
| 309 | self.__ser.write(da) |
| 310 | if sig_len > 0: |
| 311 | logging.debug("Send SIG") |
| 312 | self.__ser.write(sig) |
| 313 | |
| 314 | logging.debug('Calc checksum') |
| 315 | checksum = self.__checksum(da, da_len) ^ self.__checksum(sig, sig_len) |
| 316 | data = self.__read16() |
| 317 | logging.debug('checksum: 0x%x - 0x%x' %(checksum, data)) |
| 318 | if data != checksum: |
| 319 | return -5 |
| 320 | status = self.__read16() |
| 321 | if status >= self.E_ERROR: |
| 322 | return status |
| 323 | |
| 324 | return 0 |
| 325 | |
| 326 | def __jump_da(self, addr): |
| 327 | if not self.__write8(0xd5, True): |
| 328 | return -1 |
| 329 | if not self.__write32(addr, True): |
| 330 | return -2 |
| 331 | status = self.__read16() |
| 332 | if status >= self.E_ERROR: |
| 333 | return status |
| 334 | return 0 |
| 335 | |
| 336 | def __jump_da_ex(self, addr): |
| 337 | if not self.__write8(0xde, True): |
| 338 | return -1 |
| 339 | if not self.__write32(addr, True): |
| 340 | return -2 |
| 341 | if not self.__write8(0x1, True): |
| 342 | return -3 |
| 343 | status = self.__read16() |
| 344 | if status >= self.E_ERROR: |
| 345 | return status |
| 346 | if not self.__write8(0x64, True): |
| 347 | return -4 |
| 348 | status = self.__read16() |
| 349 | if status >= self.E_ERROR: |
| 350 | return status |
| 351 | return 0 |
| 352 | |
| 353 | def __get_meid(self): |
| 354 | if not self.__write8(0xe1, True): |
| 355 | return -1 |
| 356 | len = self.__read32() |
| 357 | logging.debug('meid len: 0x%x' %len) |
| 358 | data = struct.unpack('!'+str(len)+'B', self.__ser.read(len)) |
| 359 | meid_str = lambda s: ''.join(map(lambda c: '%02x' %c, s)) |
| 360 | status = self.__read16() |
| 361 | if status >= self.E_ERROR: |
| 362 | return status |
| 363 | logging.info(meid_str(data)); |
| 364 | return 0 |
| 365 | |
| 366 | def __send_cert(self, data, len): |
| 367 | if not self.__write8(0xe0, True): |
| 368 | return -1 |
| 369 | if not self.__write32(len, True): |
| 370 | return -2 |
| 371 | status = self.__read16() |
| 372 | if status >= self.E_ERROR: |
| 373 | return status |
| 374 | self.__ser.write(data) |
| 375 | checksum = self.__checksum(data, len) |
| 376 | data = self.__read16() |
| 377 | if checksum != data: |
| 378 | logging.error("checksum: 0x%x - 0x%x" %(checksum, data)) |
| 379 | return -3 |
| 380 | status = self.__read16() |
| 381 | if status >= self.E_ERROR: |
| 382 | return status |
| 383 | return 0 |
| 384 | |
| 385 | def __reboot_platform(self): |
| 386 | if not self.__write8(0xd4, True): |
| 387 | return -1 |
| 388 | if not self.__write32(0x10007000, True): |
| 389 | return -2 |
| 390 | if not self.__write32(0x1, True): |
| 391 | return -3 |
| 392 | status = self.__read16() |
| 393 | if status >= self.E_ERROR: |
| 394 | return status |
| 395 | if not self.__write32(0x22000004, True): |
| 396 | return -4 |
| 397 | status = self.__read16() |
| 398 | if status >= self.E_ERROR: |
| 399 | return status |
| 400 | if not self.__write8(0xd4, True): |
| 401 | return -5 |
| 402 | if not self.__write32(0x10007014, True): |
| 403 | return -6 |
| 404 | if not self.__write32(0x1, True): |
| 405 | return -7 |
| 406 | status = self.__read16() |
| 407 | if status >= self.E_ERROR: |
| 408 | return status |
| 409 | if not self.__write32(0x1209, True): |
| 410 | return -8 |
| 411 | return 0 |
| 412 | |
| 413 | def __fall_through_to_fastboot(self): |
| 414 | if not self.__write8(0xd9, True): |
| 415 | return -1 |
| 416 | status = self.__read16() |
| 417 | if status >= self.E_ERROR: |
| 418 | return status |
| 419 | return 0 |
| 420 | |
| 421 | def start(self): |
| 422 | self.__find_usb_device(self.__match_usb_auto) |
| 423 | self.__start_cmd() |
| 424 | |
| 425 | # get meid |
| 426 | if self.__meid: |
| 427 | status = self.__get_meid() |
| 428 | if status != 0: |
| 429 | logging.error('get meid (%d)' %status) |
| 430 | return -1 |
| 431 | return 0 |
| 432 | |
| 433 | # send cert |
| 434 | if self.__cert_path != '': |
| 435 | cert = self.__load_binary(self.__cert_path) |
| 436 | cert_len = len(cert) |
| 437 | logging.debug('cert_len: 0x%x' %cert_len) |
| 438 | status = self.__send_cert(cert, cert_len) |
| 439 | if status != 0: |
| 440 | logging.error('send cert (%d)' %status) |
| 441 | return -1 |
| 442 | logging.info('Reboot...') |
| 443 | status = self.__reboot_platform() |
| 444 | if status != 0: |
| 445 | logging.error('reboot platform (%d)' %status) |
| 446 | return -1 |
| 447 | return 0 |
| 448 | |
| 449 | if self.__connect_type == 'BROM': |
| 450 | status, cfg = self.__get_target_config() |
| 451 | if status != 0: |
| 452 | logging.error('get target config (%s)' %status) |
| 453 | return -1 |
| 454 | logging.debug('cfg=0x%x' %cfg) |
| 455 | |
| 456 | status = self.__send_auth(cfg) |
| 457 | if status != 0: |
| 458 | logging.error('send auth (%d)' %status) |
| 459 | return -1 |
| 460 | |
| 461 | da1 = self.__load_binary(self.__da1_path) |
| 462 | da1_len = len(da1) |
| 463 | logging.debug('da1 length: 0x%x' %da1_len) |
| 464 | status, strip_pl, strip_pl_len = self.__strip_pl_hdr(da1, da1_len) |
| 465 | if not status: |
| 466 | logging.error('strip pl hdr') |
| 467 | return -1 |
| 468 | |
| 469 | sig_da1 = None |
| 470 | sig_da1_len = 0 |
| 471 | if self.TGT_CFG_DAA_EN & cfg: |
| 472 | sig_da1 = self.__load_binary(self.__da1_path + '.sign') |
| 473 | sig_da1_len = len(sig_da1) |
| 474 | |
| 475 | logging.debug('strip_pl_len: 0x%x' %strip_pl_len) |
| 476 | logging.info('Send %s' %self.__da1_path) |
| 477 | status = self.__send_da(self.__da1_addr, strip_pl, strip_pl_len, sig_da1, sig_da1_len) |
| 478 | if status != 0: |
| 479 | logging.error('send da1 (%d)' %status) |
| 480 | return -1 |
| 481 | logging.info('Jump da') |
| 482 | if self.__da1_jump_64 == 0: |
| 483 | status = self.__jump_da(self.__da1_addr) |
| 484 | else: |
| 485 | status = self.__jump_da_ex(self.__da1_addr) |
| 486 | if status != 0: |
| 487 | logging.error('jump da1 (%d)' %status) |
| 488 | return -1 |
| 489 | |
| 490 | self.__ser.close() |
| 491 | if self.__da2_path == '': |
| 492 | return 0 |
| 493 | |
| 494 | # handshake to bootloader |
| 495 | self.__find_usb_device(self.__match_usb_bl) |
| 496 | self.__start_cmd() |
| 497 | |
| 498 | if self.__fall_thru_to_fb == 1: |
| 499 | logging.info("fall through to fastboot") |
| 500 | status = self.__fall_through_to_fastboot() |
| 501 | self.__ser.close() |
| 502 | if status != 0: |
| 503 | logging.error("fall through to fastboot failed(%d)" %(status)) |
| 504 | return -1 |
| 505 | else: |
| 506 | return 0 |
| 507 | |
| 508 | # load da2 (lk) |
| 509 | da2 = self.__load_binary(self.__da2_path) |
| 510 | da2_len = len(da2) |
| 511 | sig_da2 = self.__load_binary(self.__da2_path + '.sign') |
| 512 | sig_da2_len = len(sig_da2) |
| 513 | logging.info('Send %s' %self.__da2_path) |
| 514 | status = self.__send_da(self.__da2_addr, da2, da2_len, sig_da2, sig_da2_len) |
| 515 | if status != 0: |
| 516 | logging.error('send da2 (%d)' %status) |
| 517 | return -1 |
| 518 | logging.info('Jump da2') |
| 519 | status = self.__jump_da(self.__da2_addr) |
| 520 | if status != 0: |
| 521 | logging.error('jump da2 (%d)' %status) |
| 522 | return -1 |
| 523 | |
| 524 | self.__ser.close() |
| 525 | return 0 |
| 526 | |
| 527 | |
| 528 | if __name__ == '__main__': |
| 529 | parser = OptionParser() |
| 530 | parser.add_option('-f', '--file', dest='configfile', help='read config file', |
| 531 | metavar='FILE', default='dl_addr.ini') |
| 532 | parser.add_option('-d', '--debug', action='store_true', dest='debuglog', |
| 533 | default=False, help='enable debug log') |
| 534 | parser.add_option('-m', '--meid', action='store_true', dest='meid', |
| 535 | default=False, help='get meid') |
| 536 | options, args = parser.parse_args() |
| 537 | config_file = options.configfile |
| 538 | meid = options.meid |
| 539 | debug = options.debuglog |
| 540 | if debug: |
| 541 | logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s] %(levelname)s: %(message)s') |
| 542 | else: |
| 543 | logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s: %(message)s') |
| 544 | |
rjw | 2e8229f | 2022-02-15 21:08:12 +0800 | [diff] [blame] | 545 | if sys.version_info < (3, 0): |
| 546 | reload(sys) |
| 547 | sys.setdefaultencoding('utf-8') |
| 548 | |
| 549 | logging.info('python version: %s' %sys.version) |
| 550 | logging.info('pySerial version: %s' %serial.VERSION) |
xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 551 | if serial.VERSION < '2.6': |
| 552 | logging.error('pySerial version(%s) is lower than 2.6, please upgrade!' %serial.VERSION) |
| 553 | logging.info('Use config file: %s' %(config_file)) |
| 554 | logging.info('Waiting to connect platform...') |
| 555 | fbtool = Fbtool(config_file, meid) |
| 556 | fbtool.start() |