# decompyle3 version 3.9.0
# Python bytecode version base 3.7.0 (3394)
# Decompiled from: Python 3.7.16 (default, Mar 30 2023, 01:25:49) 
# [GCC 12.2.1 20220924]
# Embedded file name: libs/base/bflb_base_eflash_loader.py
__doc__ = '\nCreated on 20220908\n\n@author: Dillon\n'
import os, lzma, ecdsa, config as gol
from libs.bflb_utils import *
from libs.bflb_configobj import BFConfigParser
from libs import bflb_ecdh
from libs import bflb_interface_jlink
from libs import bflb_interface_cklink
from libs import bflb_interface_openocd
from libs.base import bflb_img_loader
from libs.base import bflb_flash_select
from libs.base import bflb_efuse_boothd_create
from libs.base import bflb_img_create as img_create
from pickle import NONE
FLASH_LOAD_SHAKE_HAND = 'Flash load shake hand'
FLASH_ERASE_SHAKE_HAND = 'Flash erase shake hand'

class BaseEflashLoader(object):
    __doc__ = '\n    Load the flash base execution file.\n    '

    def __init__(self, chip_type, args, config, callback, macaddr_callback, create_simple_callback, create_img_callback, task_num):
        self.chip_type = chip_type
        self.chip_name = ''
        self.args = args
        self.config = config
        self.callback = callback
        self.macaddr_callback = macaddr_callback
        self.create_simple_callback = create_simple_callback
        self.create_img_callback = create_img_callback
        self.temp_task_num = task_num
        self.task_num = None
        self.device = ''
        self.speed = 0
        self.boot_speed = 0
        self.bflb_serial_object = None
        self.start = ''
        self.end = ''
        self.file = ''
        self.address = ''
        self.macaddr = ''
        self.bootinfo = None
        self.flash_set = 0
        self.read_flash_id = 0
        self.id_valid_flag = '80'
        self.read_flash2_id = 0
        self.id2_valid_flag = '80'
        self.do_reset = True
        self.reset_hold_time = 100
        self.shake_hand_delay = 100
        self.reset_revert = True
        self.cutoff_time = 0
        self.shake_hand_retry = 2
        self.flash_burn_retry = 1
        self.ram_load = False
        self.load_function = 1
        self.macaddr_check = False
        self.NUM_ERR = 5
        self.cfg = ''
        self.eflash_loader_file = ''
        self.cpu_reset = False
        self.retry_delay_after_cpu_reset = 0
        self.input_macaddr = ''
        self.isp_mode_sign = False
        self.create_cfg = None
        self._skip_addr = []
        self._skip_len = []
        self.address_list = []
        self.flash_file_list = []
        self.encrypt_key = None
        self.encrypt_iv = None
        self.public_key = None
        self.private_key = None
        self.load_file = ''
        self._mac_addr = bytearray(0)
        self._need_shake_hand = True
        self._isp_shakehand_timeout = 0
        self._macaddr_check = bytearray(0)
        self._default_time_out = 2.0
        self._flash2_en = False
        self._flash1_size = 0
        self._flash2_size = 0
        self._flash2_select = False
        self._efuse_bootheader_file = ''
        self._img_create_file = ''
        self._com_cmds = {'change_rate':{'cmd_id':'20', 
          'data_len':'0008', 
          'callback':None}, 
         'reset':{'cmd_id':'21', 
          'data_len':'0000', 
          'callback':None}, 
         'clk_set':{'cmd_id':'22', 
          'data_len':'0000', 
          'callback':None}, 
         'opt_finish':{'cmd_id':'23', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_erase':{'cmd_id':'30', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_write':{'cmd_id':'31', 
          'data_len':'0100', 
          'callback':None}, 
         'flash_read':{'cmd_id':'32', 
          'data_len':'0100', 
          'callback':None}, 
         'flash_boot':{'cmd_id':'33', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_xip_read':{'cmd_id':'34', 
          'data_len':'0100', 
          'callback':None}, 
         'flash_switch_bank':{'cmd_id':'35', 
          'data_len':'0100', 
          'callback':None}, 
         'flash_read_jid':{'cmd_id':'36', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_read_status_reg':{'cmd_id':'37', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_write_status_reg':{'cmd_id':'38', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_write_check':{'cmd_id':'3a', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_set_para':{'cmd_id':'3b', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_chiperase':{'cmd_id':'3c', 
          'data_len':'0000', 
          'callback':None}, 
         'flash_readSha':{'cmd_id':'3d', 
          'data_len':'0100', 
          'callback':None}, 
         'flash_xip_readSha':{'cmd_id':'3e', 
          'data_len':'0100', 
          'callback':None}, 
         'flash_decompress_write':{'cmd_id':'3f', 
          'data_len':'0100', 
          'callback':None}, 
         'efuse_write':{'cmd_id':'40', 
          'data_len':'0080', 
          'callback':None}, 
         'efuse_read':{'cmd_id':'41', 
          'data_len':'0000', 
          'callback':None}, 
         'efuse_read_mac':{'cmd_id':'42', 
          'data_len':'0000', 
          'callback':None}, 
         'efuse_write_mac':{'cmd_id':'43', 
          'data_len':'0006', 
          'callback':None}, 
         'flash_xip_read_start':{'cmd_id':'60', 
          'data_len':'0080', 
          'callback':None}, 
         'flash_xip_read_finish':{'cmd_id':'61', 
          'data_len':'0000', 
          'callback':None}, 
         'log_read':{'cmd_id':'71', 
          'data_len':'0000', 
          'callback':None}, 
         'efuse_security_write':{'cmd_id':'80', 
          'data_len':'0080', 
          'callback':None}, 
         'efuse_security_read':{'cmd_id':'81', 
          'data_len':'0000', 
          'callback':None}, 
         'ecdh_get_pk':{'cmd_id':'90', 
          'data_len':'0000', 
          'callback':None}, 
         'ecdh_chanllenge':{'cmd_id':'91', 
          'data_len':'0000', 
          'callback':None}}
        self._resp_cmds = [
         'flash_read','flash_xip_read','efuse_read','efuse_read_mac','flash_readSha','flash_xip_readSha','flash_read_jid',
         'flash_read_status_reg','log_read','ecdh_get_pk','ecdh_chanllenge','efuse_security_read']

    def first_run_step_load_parameter(self):
        """
        First step: init.
        """
        if self.temp_task_num == None:
            local_log_enable(True)
        if self.temp_task_num != None:
            if self.temp_task_num > 256:
                self.task_num = self.temp_task_num - 256
            else:
                self.task_num = self.temp_task_num
        else:
            self.task_num = None
        printf('========= eflash loader cmd arguments =========')
        self.interface = self.config['param']['interface_type'].lower()
        self.chip_name = self.config['param']['chip_name']
        self.config_file = os.path.join(app_path, 'chips', self.chip_name.lower(), 'eflash_loader', 'eflash_loader_cfg.ini')
        if not os.path.exists(self.config_file):
            conf_file = self.config_file.replace('.ini', '.conf')
            if os.path.exists(conf_file):
                shutil.copy(conf_file, self.config_file)
        if os.path.exists(self.config_file):
            self.cfg = BFConfigParser()
            self.cfg.read(self.config_file)
        else:
            printf('Config file "' + self.config_file + '" not found')
            self.error_code_print('000B')
            return (False, 0)
        if self.interface == 'openocd':
            self.device = self.cfg.get('LOAD_CFG', 'openocd_config')
            self._bflb_sn_device = self.config['param']['comport_uart']
        else:
            if self.interface == 'cklink':
                self.device = self.cfg.get('LOAD_CFG', 'cklink_vidpid')
                self._bflb_sn_device = self.cfg.get('LOAD_CFG', 'cklink_type') + ' ' + self.config['param']['comport_uart']
            else:
                self.device = self.config['param']['comport_uart']
        if 'aes_key' in self.config['param']:
            if self.config['check_box']['encrypt']:
                self.encrypt_key = self.config['param']['aes_key']
        if 'aes_iv' in self.config['param']:
            if self.config['check_box']['sign']:
                self.encrypt_iv = self.config['param']['aes_iv']
        if 'input_path' in self.config:
            if 'publickey' in self.config['input_path']['publickey']:
                self.public_key = self.config['input_path']['publickey']
        if 'input_path' in self.config:
            if 'privatekey' in self.config['input_path']['privatekey']:
                self.private_key = self.config['input_path']['privatekey']
        xtal_type = self.config['param']['chip_xtal']
        if self.interface == 'uart':
            temp_speed = int(self.config['param']['speed_uart'])
        else:
            temp_speed = int(self.config['param']['speed_jlink'])
        printf('serial port is ', self.device)
        printf('chiptype: ', self.chip_type)
        try:
            if self.args.start:
                self.start = self.args.start
            if self.args.end:
                self.end = self.args.end
            if self.args.file:
                self.file = self.args.file
            if self.args.addr:
                self.address = self.args.addr
            if self.args.mac:
                self.macaddr = self.args.mac
            if self.args.createcfg:
                self.create_cfg = self.args.createcfg
            if self.args.loadfile:
                self.load_file = self.args.loadfile
            if self.args.usage:
                printf('-e --start=00000000 --end=0000FFFF -c config.ini')
                printf('-w --flash -c config.ini')
                printf('-w --flash --file=1.bin,2.bin --addr=00000000,00001000 -c config.ini')
                printf('-r --flash --start=00000000 --end=0000FFFF --file=flash.bin -c config.ini')
        except Exception as e:
            try:
                printf(e)
                self.error_code_print('0002')
                return (False, 0)
            finally:
                e = None
                del e

        if self.cfg.has_option('LOAD_CFG', 'verify'):
            if self.cfg.get('LOAD_CFG', 'verify') == '1':
                self.verify = 1
            else:
                self.verify = 0
        else:
            self.verify = 0
        try:
            self.erase = int(self.config['param']['erase'])
        except:
            self.erase = 1

        try:
            boot2_isp_mode = int(self.config['param']['boot2_isp_mode'])
            if int(boot2_isp_mode) == 1:
                self.isp_mode_sign = True
        except:
            pass

        if not 'skip_mode' in self.config['param'] or self.config['param']['skip_mode']:
            skip_para = self.config['param']['skip_mode'].replace(' ', '')
            if skip_para[-1] == ';':
                skip_para = skip_para[:-1]
            skip_para_list = skip_para.split(';')
            for temp_value in skip_para_list:
                temp_list = temp_value.split(',')
                if temp_list[0][0:2] == '0x':
                    self._skip_addr.append(int(temp_list[0][2:], 16))
                else:
                    self._skip_addr.append(int(temp_list[0], 10))
                if temp_list[1][0:2] == '0x':
                    self._skip_len.append(int(temp_list[1][2:], 16))
                else:
                    self._skip_len.append(int(temp_list[1], 10))

            if len(self._skip_len) > 1 or len(self._skip_len) == 1 and self._skip_len[0] > 0:
                if self.erase == 2:
                    printf('Error: skip mode can not set flash chiperase!')
                    self.error_code_print('0044')
                    return (False, 0)
            if self.cfg.has_option('LOAD_CFG', 'local_log'):
                if self.cfg.get('LOAD_CFG', 'local_log') == 'true':
                    printf('local log enable')
                    local_log_enable(True)
                    self.input_macaddr = self.macaddr
                else:
                    local_log_enable(False)
                    self.input_macaddr = ''
            if self.interface == 'cklink':
                self._bflb_com_tx_size = 14344
            else:
                self._bflb_com_tx_size = int(self.cfg.get('LOAD_CFG', 'tx_size'))
            if self.cfg.has_option('LOAD_CFG', 'erase_time_out'):
                self._erase_time_out = int(self.cfg.get('LOAD_CFG', 'erase_time_out'))
            if self.cfg.has_option('LOAD_CFG', 'shake_hand_retry'):
                self.shake_hand_retry = int(self.cfg.get('LOAD_CFG', 'shake_hand_retry'))
            if self.cfg.has_option('LOAD_CFG', 'flash_burn_retry'):
                self.flash_burn_retry = int(self.cfg.get('LOAD_CFG', 'flash_burn_retry'))
            if self.cfg.has_option('LOAD_CFG', 'checksum_err_retry'):
                self._checksum_err_retry_limit = int(self.cfg.get('LOAD_CFG', 'checksum_err_retry'))
            if self.cfg.has_option('LOAD_CFG', 'cpu_reset_after_load'):
                self.cpu_reset = self.cfg.get('LOAD_CFG', 'cpu_reset_after_load') == 'true'
            if self.cfg.has_option('LOAD_CFG', 'retry_delay_after_cpu_reset'):
                self.retry_delay_after_cpu_reset = int(self.cfg.get('LOAD_CFG', 'retry_delay_after_cpu_reset'))
                printf('retry delay: ', self.retry_delay_after_cpu_reset)
            if self.cfg.has_option('LOAD_CFG', 'eflash_loader_file'):
                if self.eflash_loader_file is None:
                    self.eflash_loader_file = self.cfg.get('LOAD_CFG', 'eflash_loader_file')
            printf('cpu_reset=', self.cpu_reset)
            if xtal_type != '':
                self.eflash_loader_file = 'chips/' + self.chip_name.lower() + '/eflash_loader/eflash_loader_' + xtal_type.replace('.', 'p').lower() + '.bin'
            if self.load_file and not self.eflash_loader_file:
                self.eflash_loader_file = self.load_file
            else:
                if self.eflash_loader_file is not None:
                    self.eflash_loader_file = os.path.join(app_path, self.eflash_loader_file)
            self.load_function = 1
            if self.cfg.has_option('LOAD_CFG', 'isp_shakehand_timeout'):
                self._isp_shakehand_timeout = int(self.cfg.get('LOAD_CFG', 'isp_shakehand_timeout'))
            result, address, flash_file = self.get_flash_file_and_address()
            if not result:
                return (False, self.flash_burn_retry)
            temp_file_list = []
            for one in flash_file:
                if os.path.join(chip_path, self.chip_name) in one:
                    temp_file_list.append(one.replace(app_path, '')[1:])
                else:
                    temp_file_list.append(os.path.join('chips', self.chip_name, 'img_create', os.path.basename(one)))

            if 'erase' in self.config['param']:
                if self.config['param']['erase']:
                    update_cfg(self.cfg, 'LOAD_CFG', 'erase', str(self.erase))
            if 'skip_mode' in self.config['param']:
                if self.config['param']['skip_mode']:
                    update_cfg(self.cfg, 'LOAD_CFG', 'skip_mode', self.config['param']['skip_mode'])
            if 'boot2_isp_mode' in self.config['param']:
                if self.config['param']['boot2_isp_mode']:
                    update_cfg(self.cfg, 'LOAD_CFG', 'boot2_isp_mode', self.config['param']['boot2_isp_mode'])
            update_cfg(self.cfg, 'FLASH_CFG', 'file', ' '.join(temp_file_list))
            update_cfg(self.cfg, 'FLASH_CFG', 'address', ' '.join(address))
            self.cfg.write(self.config_file, 'w+')
            with open((self.config_file), 'r', encoding='utf-8') as cf_file:
                cf_context = cf_file.read().replace('"', '')
            with open((self.config_file), 'w', encoding='utf-8') as cf_file:
                cf_file.write(cf_context)
            self.bl_write_flash_img(address, flash_file)
            self.address_list = address[:]
            self.flash_file_list = flash_file[:]
            if self.args.efuse:
                try:
                    if self.config['input_path']['efuse']:
                        if self.config['check_box']['efuse']:
                            efusefile = self.config['input_path']['efuse']
                except:
                    efusefile = ''

                if efusefile:
                    efuse_file = efusefile
                    mask_file = efuse_file.replace('.bin', '_mask.bin')
                    relpath_efuse_file = os.path.relpath(os.path.join('chips', self.chip_name, 'img_create', os.path.basename(efuse_file)))
                    relpath_mask_file = os.path.relpath(os.path.join('chips', self.chip_name, 'img_create', os.path.basename(mask_file)))
                    if self.cfg.has_option('EFUSE_CFG', 'file'):
                        update_cfg(self.cfg, 'EFUSE_CFG', 'file', relpath_efuse_file)
                        update_cfg(self.cfg, 'EFUSE_CFG', 'maskfile', relpath_mask_file)
                        self.cfg.write(self.config_file, 'w+')
                        with open((self.config_file), 'r', encoding='utf-8') as cf_file:
                            cf_context = cf_file.read().replace('"', '')
                        with open((self.config_file), 'w', encoding='utf-8') as cf_file:
                            cf_file.write(cf_context)
                else:
                    efuse_file = self.cfg.get('EFUSE_CFG', 'file')
                    mask_file = self.cfg.get('EFUSE_CFG', 'maskfile')
                if self.temp_task_num != None:
                    efuse_file = 'task' + str(self.temp_task_num) + '/' + efuse_file
                ret = img_create.compress_dir(self.chip_name, 'img_create', self.args.efuse, address, flash_file, efuse_file, mask_file)
                if ret is not True:
                    return errorcode_msg()
            else:
                ret = img_create.compress_dir(self.chip_name, 'img_create', False, address, flash_file)
                if ret is not True:
                    return errorcode_msg()
            if self.interface == 'uart' or self.interface == 'sdio':
                if temp_speed:
                    self.speed = temp_speed
                self.boot_speed = int(self.cfg.get('LOAD_CFG', 'speed_uart_boot'))
                self.set_boot_speed()
                if self.cfg.has_option('LOAD_CFG', 'reset_hold_time'):
                    self.reset_hold_time = int(self.cfg.get('LOAD_CFG', 'reset_hold_time'))
                if self.cfg.has_option('LOAD_CFG', 'shake_hand_delay'):
                    self.shake_hand_delay = int(self.cfg.get('LOAD_CFG', 'shake_hand_delay'))
                if self.cfg.has_option('LOAD_CFG', 'do_reset'):
                    self.do_reset = self.cfg.get('LOAD_CFG', 'do_reset') == 'true'
                if self.cfg.has_option('LOAD_CFG', 'reset_revert'):
                    self.reset_revert = self.cfg.get('LOAD_CFG', 'reset_revert') == 'true'
                if self.cfg.has_option('LOAD_CFG', 'cutoff_time'):
                    self.cutoff_time = int(self.cfg.get('LOAD_CFG', 'cutoff_time'))
                printf('========= Interface is %s =========' % self.interface)
                self._bflb_com_img_loader = bflb_img_loader.BflbImgLoader(self.device, self.speed, self.boot_speed, self.interface, self.chip_type, self.chip_name, self.eflash_loader_file, '', self.callback, self.do_reset, self.reset_hold_time, self.shake_hand_delay, self.reset_revert, self.cutoff_time, self.shake_hand_retry, self.isp_mode_sign, self._isp_shakehand_timeout, self.encrypt_key, self.encrypt_iv, self.public_key, self.private_key)
                self.bflb_serial_object = self._bflb_com_img_loader.bflb_serial_object
                if not self.cfg.has_option('LOAD_CFG', 'isp_mode_speed') or self.isp_mode_sign is True:
                    isp_mode_speed = int(self.cfg.get('LOAD_CFG', 'isp_mode_speed'))
                    self._bflb_com_img_loader.set_isp_baudrate(isp_mode_speed)
            else:
                if self.interface == 'jlink':
                    printf('========= Interface is JLink =========')
                    self.bflb_serial_object = bflb_interface_jlink.BflbJLinkPort()
                    if temp_speed:
                        self.speed = temp_speed
                        printf('com speed: %dk' % self.speed)
                    else:
                        self.speed = int(self.cfg.get('LOAD_CFG', 'speed_jlink'))
                    self.boot_speed = self.speed
                else:
                    if self.interface == 'openocd':
                        printf('========= Interface is Openocd =========')
                        self.bflb_serial_object = bflb_interface_openocd.BflbOpenocdPort()
                        if temp_speed:
                            self.speed = temp_speed
                            printf('com speed: %dk' % self.speed)
                        else:
                            self.speed = int(self.cfg.get('LOAD_CFG', 'speed_jlink'))
                        self.boot_speed = self.speed
                    else:
                        if self.interface == 'cklink':
                            printf('========= Interface is CKLink =========')
                            self.bflb_serial_object = bflb_interface_cklink.BflbCKLinkPort()
                            if temp_speed:
                                self.speed = temp_speed
                                printf('com speed: %dk' % self.speed)
                            else:
                                self.speed = int(self.cfg.get('LOAD_CFG', 'speed_jlink'))
                            self.boot_speed = self.speed
                        else:
                            printf(self.interface + ' is not supported ')
                            return (
                             False, self.flash_burn_retry)
            if self.args.chipid:
                ret, self.bootinfo, res = self.get_boot_info()
                if ret is False:
                    self.error_code_print('0003')
                    return (
                     False, self.flash_burn_retry)
                return (
                 True, self.flash_burn_retry)
            if self.cfg.has_option('LOAD_CFG', 'load_function'):
                self.load_function = int(self.cfg.get('LOAD_CFG', 'load_function'))
            if self.isp_mode_sign is True:
                if self._isp_shakehand_timeout == 0:
                    self._isp_shakehand_timeout = 5
                self.set_load_function()
            return (True, 'continue')

    def second_run_step_shake_hand(self):
        """
        Second step: shake hand and load eflash_loader.bin.
        """
        try:
            if self.load_function == 0:
                printf('No need load eflash_loader.bin')
            else:
                if self.load_function == 1:
                    load_bin_pass = False
                    printf('Eflash load bin file: ', self.eflash_loader_file)
                    ret, self.bootinfo, res = self.load_eflash_loader_bin()
                    if res == 'shake hand fail':
                        self.error_code_print('0050')
                    if res.startswith('repeat_burn') is True:
                        return ('repeat_burn', self.flash_burn_retry)
                    if res.startswith('error_shakehand') is True:
                        if self.cpu_reset is True:
                            self.error_code_print('0003')
                            return (
                             False, self.flash_burn_retry)
                        load_bin_pass = True
                        time.sleep(4.5)
                    if ret is False:
                        if load_bin_pass == False:
                            self.error_code_print('0003')
                            return (
                             False, self.flash_burn_retry)
                    if self.ram_load:
                        return (True, self.flash_burn_retry)
                else:
                    if self.load_function == 2:
                        load_bin_pass = False
                        printf('Bootrom load')
                        ret, self.bootinfo, res = self.get_boot_info()
                        if res == 'shake hand fail':
                            self.error_code_print('0050')
                        if res.startswith('repeat_burn') is True:
                            self.error_code_print('000A')
                            return (
                             'repeat_burn', self.flash_burn_retry)
                        if res.startswith('error_shakehand') is True:
                            if self.cpu_reset is True:
                                self.error_code_print('0003')
                                return (
                                 False, self.flash_burn_retry)
                            load_bin_pass = True
                            time.sleep(4.5)
                        if ret is False:
                            if load_bin_pass == False:
                                self.error_code_print('0050')
                                return (
                                 False, self.flash_burn_retry)
                        self._need_shake_hand = False
                        clock_para = bytearray(0)
                        if self.cfg.has_option('LOAD_CFG', 'clock_para'):
                            clock_para_str = self.cfg.get('LOAD_CFG', 'clock_para')
                            if clock_para_str != '':
                                clock_para_file = os.path.join(app_path, clock_para_str)
                                printf('clock para file: ', clock_para_file)
                                clock_para = self.clock_para_update(clock_para_file)
                        printf('change bdrate: ', self.speed)
                        ret = self.clock_pll_set(self._need_shake_hand, True, clock_para)
                        if ret is False:
                            printf('pll set fail!!')
                            return (
                             False, self.flash_burn_retry)
            return (True, 'continue')
        except Exception as e:
            try:
                printf(e)
                self.error_code_print('0003')
                return (
                 False, self.flash_burn_retry)
            finally:
                e = None
                del e

    def third_run_step_read_mac_address(self):
        """
        Third step: read mac address.
        """
        time.sleep(0.1)
        if self.isp_mode_sign is True:
            if self.cpu_reset is True:
                self.set_clear_boot_status(self._need_shake_hand)
        if self.cfg.has_option('LOAD_CFG', 'check_mac'):
            self.macaddr_check = self.cfg.get('LOAD_CFG', 'check_mac') == 'true'
        if self.macaddr_check:
            if self.isp_mode_sign is False:
                ret, self._mac_addr = self.efuse_read_mac_addr_process()
                if ret is False:
                    printf('read mac addr fail!!')
                    return (
                     False, self.flash_burn_retry)
                if self._mac_addr == self._macaddr_check:
                    self.error_code_print('000A')
                    return (
                     False, self.flash_burn_retry)
                self._need_shake_hand = False
                self._macaddr_check_status = True
        if self.macaddr_callback is not None:
            ret, self._efuse_data, self._efuse_mask_data, macaddr = self.macaddr_callback(binascii.hexlify(self._mac_addr).decode('utf-8'))
            if ret is False:
                return (False, self.flash_burn_retry)
            if self._efuse_data != bytearray(0) and self._efuse_mask_data != bytearray(0) or macaddr != '':
                self.args.efuse = True
        if self.callback:
            self.callback(0, 100, 'running', 'blue')
        return (True, 'continue')

    def fourth_run_step_interact_chip(self):
        """
        Fourth step: Interact with chip, read chip ID and update flash parameter.
        """
        if self.args.flash:
            flash_pin = 0
            flash_clock_cfg = 0
            flash_io_mode = 0
            flash_clk_delay = 0
            if self.cfg.has_option('FLASH_CFG', 'decompress_write'):
                self.decompress_write = self.cfg.get('FLASH_CFG', 'decompress_write') == 'true'
            self.set_decompress_write()
            printf('flash set para')
            if self.cfg.get('FLASH_CFG', 'flash_pin'):
                flash_pin_cfg = self.cfg.get('FLASH_CFG', 'flash_pin')
                if flash_pin_cfg.startswith('0x'):
                    flash_pin = int(flash_pin_cfg, 16)
                else:
                    flash_pin = int(flash_pin_cfg, 10)
                if flash_pin == 128:
                    flash_pin = self.get_flash_pin_from_bootinfo(self.chip_type, self.bootinfo)
                    printf('get flash pin cfg from bootinfo: 0x%02X' % flash_pin)
            else:
                flash_pin = self.get_flash_pin()
            if self.cfg.has_option('FLASH_CFG', 'flash_clock_cfg'):
                clock_div_cfg = self.cfg.get('FLASH_CFG', 'flash_clock_cfg')
                if clock_div_cfg.startswith('0x'):
                    flash_clock_cfg = int(clock_div_cfg, 16)
                else:
                    flash_clock_cfg = int(clock_div_cfg, 10)
            if self.cfg.has_option('FLASH_CFG', 'flash_io_mode'):
                io_mode_cfg = self.cfg.get('FLASH_CFG', 'flash_io_mode')
                if io_mode_cfg.startswith('0x'):
                    flash_io_mode = int(io_mode_cfg, 16)
                else:
                    flash_io_mode = int(io_mode_cfg, 10)
            if self.cfg.has_option('FLASH_CFG', 'flash_clock_delay'):
                clk_delay_cfg = self.cfg.get('FLASH_CFG', 'flash_clock_delay')
                if clk_delay_cfg.startswith('0x'):
                    flash_clk_delay = int(clk_delay_cfg, 16)
                else:
                    flash_clk_delay = int(clk_delay_cfg, 10)
            self.flash_set = (flash_pin << 0) + (flash_clock_cfg << 8) + (flash_io_mode << 16) + (flash_clk_delay << 24)
            if self.flash_set != 66047 or self.load_function == 2:
                printf('set flash cfg: %X' % self.flash_set)
                ret = self.flash_set_para_main_process(self.flash_set, bytearray(0))
                self._need_shake_hand = False
                if ret is False:
                    return (False, self.flash_burn_retry)
            ret, data = self.flash_read_jedec_id_process()
            if ret:
                self._need_shake_hand = False
                data = binascii.hexlify(data).decode('utf-8')
                self.id_valid_flag = data[6:]
                read_id = data[0:6]
                self.read_flash_id = read_id
                if self.cfg.has_option('FLASH_CFG', 'flash_para'):
                    flash_para_file = os.path.join(app_path, self.cfg.get('FLASH_CFG', 'flash_para'))
                    self.flash_para_update(flash_para_file, read_id)
                if self.id_valid_flag != '80':
                    if not self.show_identify_fail():
                        return (False, self.flash_burn_retry)
                if self.is_conf_exist(self.read_flash_id) is False:
                    self.error_code_print('003D')
                    return (
                     False, self.flash_burn_retry)
            else:
                self.error_code_print('0030')
                return (
                 False, self.flash_burn_retry)
            result, content = self.run_flash2()
            return (
             result, content)
        return (True, 'continue')

    def fifth_run_step_write_flash_and_check(self):
        """
        Fifth step: write flash and check.
        """
        if self.args.none:
            return (True, self.flash_burn_retry)
        if self.args.write:
            if not self.args.flash:
                if not self.args.efuse:
                    printf('No target select')
                    return (
                     False, self.flash_burn_retry)
            printf('Program operation')
            if self.args.flash:
                flash_para_file = ''
                flash2_para_file = ''
                if self.cfg.has_option('FLASH_CFG', 'flash_para'):
                    flash_para_file = os.path.join(app_path, self.cfg.get('FLASH_CFG', 'flash_para'))
                if self.cfg.has_option('FLASH2_CFG', 'flash2_para'):
                    flash2_para_file = os.path.join(app_path, self.cfg.get('FLASH2_CFG', 'flash2_para'))
                address = self.address_list
                flash_file = self.flash_file_list
                if self.erase == 2:
                    ret = self.flash_chiperase_main_process()
                    if ret is False:
                        return (False, self.flash_burn_retry)
                    self._need_shake_hand = False
                    self.erase = 0
                if len(flash_file) > 0:
                    size_before = 0
                    size_all = 0
                    i = 0
                    for item in flash_file:
                        if self.temp_task_num != None:
                            size_all += os.path.getsize(os.path.join(app_path, convert_path('task' + str(self.temp_task_num) + '/' + item)))
                        else:
                            size_all += os.path.getsize(os.path.join(app_path, convert_path(item)))

                    try:
                        ret = False
                        while i < len(flash_file):
                            if self.temp_task_num != None:
                                flash_file[i] = 'task' + str(self.temp_task_num) + '/' + flash_file[i]
                                size_current = os.path.getsize(os.path.join(app_path, convert_path(flash_file[i])))
                            else:
                                size_current = os.path.getsize(os.path.join(app_path, convert_path(flash_file[i])))
                            if self.callback:
                                self.callback(size_before, size_all, 'program1')
                            else:
                                if self.callback:
                                    self.callback(size_current, size_all, 'program2')
                                printf('Dealing Index ', i)
                                if self.isp_mode_sign is True:
                                    printf('========= programming ', convert_path(flash_file[i]))
                                else:
                                    printf('========= programming ', convert_path(flash_file[i]), ' to 0x', address[i])
                                flash1_bin = ''
                                flash1_bin_len = 0
                                flash2_bin = ''
                                flash2_bin_len = 0
                                flash1_bin, flash1_bin_len, flash2_bin, flash2_bin_len = self.get_flash1_and_flash2(flash_file, address, size_current, i)
                                if flash1_bin != '' and flash2_bin != '':
                                    ret = self.flash_cfg_option(self.read_flash_id, flash_para_file, self.flash_set, self.id_valid_flag, flash1_bin, self.config_file, self.cfg, self.create_img_callback, self.create_simple_callback)
                                    if ret is False:
                                        return (False, self.flash_burn_retry)
                                    printf('========= programming ', convert_path(flash1_bin), ' to 0x', address[i])
                                    ret = self.flash_load_specified(convert_path(flash1_bin), int(address[i], 16), self.callback)
                                    if ret is False:
                                        return (False, self.flash_burn_retry)
                                    ret = self.flash_switch_bank_process(1)
                                    self._need_shake_hand = False
                                    if ret is False:
                                        return (False, self.flash_burn_retry)
                                    ret = self.flash_cfg_option(self.read_flash2_id, flash2_para_file, self.flash2_set, self.id2_valid_flag, flash_file[i], self.config_file, self.cfg, self.create_img_callback, self.create_simple_callback)
                                    if ret is False:
                                        return (False, self.flash_burn_retry)
                                    printf('========= programming ', convert_path(flash2_bin), ' to 0x%08X' % (int(address[i], 16) + flash1_bin_len))
                                    ret = self.flash_load_specified(convert_path(flash2_bin), int(address[i], 16) + flash1_bin_len, self.callback)
                                    if ret is False:
                                        return (False, self.flash_burn_retry)
                                else:
                                    if not (self._flash2_en is False or self._flash2_select) is False or int(address[i], 16) < self._flash1_size:
                                        ret = self.flash_cfg_option(self.read_flash_id, flash_para_file, self.flash_set, self.id_valid_flag, flash_file[i], self.config_file, self.cfg, self.create_img_callback, self.create_simple_callback)
                                        if ret is False:
                                            return (False, self.flash_burn_retry)
                                    else:
                                        if self._flash2_select is False:
                                            if int(address[i], 16) >= self._flash1_size:
                                                ret = self.flash_switch_bank_process(1)
                                                self._need_shake_hand = False
                                                if ret is False:
                                                    return (False, self.flash_burn_retry)
                                        ret = self.flash_cfg_option(self.read_flash2_id, flash2_para_file, self.flash2_set, self.id2_valid_flag, flash_file[i], self.config_file, self.cfg, self.create_img_callback, self.create_simple_callback)
                                        if ret is False:
                                            return (False, self.flash_burn_retry)
                                    if 'eflash_loader_cfg.ini' in flash_file[i]:
                                        print('11111')
                                    ret = self.flash_load_specified(convert_path(flash_file[i]), int(address[i], 16), self.callback)
                                    if ret is False:
                                        return (False, self.flash_burn_retry)
                                size_before += os.path.getsize(os.path.join(app_path, convert_path(flash_file[i])))
                                i += 1
                                if self.callback:
                                    self.callback(i, len(flash_file), 'program')
                                self._need_shake_hand = False

                        if self._flash2_select is True:
                            ret = self.flash_switch_bank_process(0)
                            self._need_shake_hand = False
                            if ret is False:
                                return (False, self.flash_burn_retry)
                        printf('Program Finished')
                    except Exception as e:
                        try:
                            printf(e)
                            traceback.print_exc(limit=(self.NUM_ERR), file=(sys.stdout))
                            return (
                             False, self.flash_burn_retry)
                        finally:
                            e = None
                            del e

                else:
                    printf('Warning: No input file to program to flash')
        return (True, 'continue')

    def sixth_run_step_write_efuse(self):
        """
        Sixth step: write efuse.
        """
        if self.args.efuse:
            try:
                if self.config['input_path']['efuse']:
                    efusefile = self.config['input_path']['efuse']
            except:
                efusefile = ''

            if efusefile:
                efuse_file = efusefile
                mask_file = efuse_file.replace('.bin', '_mask.bin')
            else:
                efuse_file = self.cfg.get('EFUSE_CFG', 'file')
                mask_file = self.cfg.get('EFUSE_CFG', 'maskfile')
            if self.temp_task_num != None:
                efuse_file = 'task' + str(self.temp_task_num) + '/' + efuse_file
            efuse_load = True
            efuse_verify = 0
            if self.cfg.has_option('EFUSE_CFG', 'burn_en'):
                efuse_load = self.cfg.get('EFUSE_CFG', 'burn_en') == 'true'
            if self.cfg.has_option('EFUSE_CFG', 'factory_mode'):
                if self.cfg.get('EFUSE_CFG', 'factory_mode') == 'true':
                    efuse_verify = 1
            security_write = self.cfg.get('EFUSE_CFG', 'security_write') == 'true'
            if efuse_load and self.isp_mode_sign is False:
                ret = self.efuse_load_specified(efuse_file, mask_file, bytearray(0), bytearray(0), efuse_verify, security_write)
                if self.callback:
                    self.callback(1, 1, 'APP_WR')
                if ret is False:
                    return (False, self.flash_burn_retry)
            else:
                printf('efuse load disalbe')
            self._need_shake_hand = False
        return (True, 'continue')

    def seventh_run_step_erase(self):
        """
        Seventh step: erase.
        """
        if self.args.erase:
            printf('Erase flash operation')
            if self.end == '0':
                ret = self.flash_chiperase_main_process()
                if ret is False:
                    return (False, self.flash_burn_retry)
            else:
                ret = self.flash_erase_main_process(int(self.start, 16), int(self.end, 16), self._need_shake_hand)
                if ret is False:
                    return (False, self.flash_burn_retry)
            printf('Erase flash OK')
        return (True, 'continue')

    def eighth_run_step_read(self):
        """
        Eighth step: read.
        """
        if self.args.read:
            printf('Read operation')
            if not self.args.flash:
                if not self.args.efuse:
                    printf('No target select')
                    return (
                     False, self.flash_burn_retry)
            if not (self.args.flash and self.start and self.end):
                self.flash_read_jedec_id_process(self.callback)
            else:
                start_addr = int(self.start, 16)
                end_addr = int(self.end, 16)
                ret, readdata = self.flash_read_main_process(start_addr, end_addr - start_addr + 1, self._need_shake_hand, self.file, self.callback)
                if ret is False:
                    return (False, self.flash_burn_retry)
            if self.args.efuse:
                start_addr = int(self.start, 16)
                end_addr = int(self.end, 16)
                if self.efuse_read_main_process(start_addr, end_addr - start_addr + 1, self._need_shake_hand, self.file) is False:
                    return (False, self.flash_burn_retry)
        return (True, 'continue')

    def ninth_run_step_end(self):
        """
        Ninth step: run end.
        """
        self.run_reset_cpu()
        if self.macaddr_check is True:
            self._bootinfo = self.bootinfo
        self._macaddr_check = self._mac_addr
        self._macaddr_check_status = False
        return (
         True, self.flash_burn_retry)

    def set_clear_boot_status(self, shakehand=0):
        pass

    def set_boot_speed(self):
        pass

    def set_load_function(self):
        self.load_function = 2

    def set_decompress_write(self):
        pass

    def get_flash_pin(self):
        return 0

    def show_identify_fail(self):
        return True

    def run_flash2(self):
        return (True, 'continue')

    def get_flash1_and_flash2(self, flash_file, address, size_current, i):
        return ('', 0, '', 0)

    def run_reset_cpu(self):
        pass

    def get_mac_len(self):
        return 6

    def get_isp_sh_time(self):
        return 0

    def write_flash_data(self, file, start_addr, callback):
        pass

    def clear_boot_status(self, shakehand=0):
        printf('Clear boot status at hbn rsvd register')
        if shakehand != 0:
            printf(FLASH_ERASE_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return False
        data = bytearray(12)
        data[0] = 80
        data[1] = 0
        data[2] = 8
        data[3] = 0
        data[4] = 8
        data[5] = 241
        data[6] = 0
        data[7] = 32
        data[8] = 0
        data[9] = 0
        data[10] = 0
        data[11] = 0
        self.bflb_serial_object.write(data)
        self.bflb_serial_object.deal_ack(dmy_data=False)
        return True

    def set_config_file(self, bootheaderFile, imgCreateFile):
        self._efuse_bootheader_file = bootheaderFile
        self._img_create_file = imgCreateFile

    def load_eflash_loader_bin(self):
        """
        This function is used to load eflash loader bin file.
        """
        printf('========= load eflash_loader.bin =========')
        bootinfo = None
        if self.interface == 'jlink':
            printf('Load eflash_loader.bin via jlink')
            self.bflb_serial_object.if_init(self.device, self.speed, self.chip_type, self.chip_name)
            self.bflb_serial_object.reset_cpu()
            imge_fp = open_file(self.eflash_loader_file, 'rb')
            fw_data = bytearray(imge_fp.read())[192:] + bytearray(0)
            imge_fp.close()
            sub_module = __import__(('libs.base.' + self.chip_type), fromlist=[self.chip_type])
            load_addr = sub_module.jlink_load_cfg.jlink_load_addr
            self.bflb_serial_object.if_raw_write(load_addr, fw_data)
            pc = fw_data[4:8]
            pc = bytes([pc[3], pc[2], pc[1], pc[0]])
            msp = fw_data[0:4]
            msp = bytes([msp[3], msp[2], msp[1], msp[0]])
            self.bflb_serial_object.set_pc_msp(binascii.hexlify(pc), binascii.hexlify(msp).decode('utf-8'))
            time.sleep(0.01)
            self.bflb_serial_object.if_close()
            return (
             True, bootinfo, '')
        if self.interface == 'openocd':
            printf('Load eflash_loader.bin via openocd')
            self.bflb_serial_object.if_init(self.device, self._bflb_sn_device, self.speed, self.chip_type, self.chip_name)
            self.bflb_serial_object.halt_cpu()
            imge_fp = open_file(self.eflash_loader_file, 'rb')
            fw_data = bytearray(imge_fp.read())[192:] + bytearray(0)
            imge_fp.close()
            sub_module = __import__(('libs.base.' + self.chip_type), fromlist=[self.chip_type])
            load_addr = sub_module.openocd_load_cfg.openocd_load_addr
            self.bflb_serial_object.if_raw_write(load_addr, fw_data)
            pc = fw_data[4:8]
            pc = bytes([pc[3], pc[2], pc[1], pc[0]])
            msp = fw_data[0:4]
            msp = bytes([msp[3], msp[2], msp[1], msp[0]])
            self.bflb_serial_object.set_pc_msp(binascii.hexlify(pc), binascii.hexlify(msp).decode('utf-8'))
            return (
             True, bootinfo, '')
        if self.interface == 'cklink':
            printf('Load eflash_loader.bin via cklink')
            self.bflb_serial_object.if_init(self.device, self._bflb_sn_device, self.speed, self.chip_type, self.chip_name)
            self.bflb_serial_object.halt_cpu()
            imge_fp = open_file(self.eflash_loader_file, 'rb')
            fw_data = bytearray(imge_fp.read())[192:] + bytearray(0)
            imge_fp.close()
            sub_module = __import__(('libs.base.' + self.chip_type), fromlist=[self.chip_type])
            load_addr = sub_module.openocd_load_cfg.openocd_load_addr
            self.bflb_serial_object.if_raw_write(load_addr, fw_data)
            pc = fw_data[4:8]
            pc = bytes([pc[3], pc[2], pc[1], pc[0]])
            msp = fw_data[0:4]
            msp = bytes([msp[3], msp[2], msp[1], msp[0]])
            self.bflb_serial_object.set_pc_msp(binascii.hexlify(pc), binascii.hexlify(msp).decode('utf-8'))
            self.bflb_serial_object.resume_cpu()
            return (
             True, bootinfo, '')
        if self.interface.lower() == 'uart' or self.interface == 'sdio':
            ret = True
            printf('Load eflash_loader.bin via %s' % self.interface)
            start_time = time.time() * 1000
            ret, bootinfo, res = self._bflb_com_img_loader.img_load_process(self.boot_speed, self.boot_speed, None, self.do_reset, self.reset_hold_time, self.shake_hand_delay, self.reset_revert, self.cutoff_time, self.shake_hand_retry, self.isp_mode_sign, self._isp_shakehand_timeout, True, bootinfo)
            printf('Load helper bin time cost(ms): ', time.time() * 1000 - start_time)
            return (
             ret, bootinfo, res)

    def set_temp_timeout(self):
        self.bflb_serial_object.set_timeout(self._erase_time_out / 1000)

    def get_new_bh_data(self, section, bh_data, fp):
        return b''

    def get_chip_id(self, bootinfo):
        chip_id = bootinfo[34:36] + bootinfo[32:34] + bootinfo[30:32] + bootinfo[28:30] + bootinfo[26:28] + bootinfo[24:26]
        return chip_id

    def get_flash_file_and_address(self):
        result = True
        temp_files = []
        temp_addrs = []
        temp_dict = {}
        temp_set_addrs = []
        for key, value_dict in self.config.items():
            if isinstance(value_dict, dict):
                if 'addr' in value_dict:
                    if value_dict['addr'] in temp_set_addrs:
                        printf('Error: %s has duplicate addresse %s!' % (key, value_dict['addr']))
                        return (
                         False, temp_addrs, temp_files)
                    else:
                        temp_dict[value_dict['addr']] = value_dict['path']
                        temp_set_addrs.append(value_dict['addr'])

        if temp_dict:
            temp_list = sorted((temp_dict.items()), key=(lambda x: int(x[0], 16)
), reverse=False)
            for i in range(len(temp_list)):
                temp_addrs.append(temp_list[i][0].replace('0x', ''))
                temp_files.append(temp_list[i][1])
                if i != 0:
                    temp_length = int(temp_list[i][0], 16) - int(temp_list[i - 1][0], 16)
                    file_length = os.path.getsize(temp_list[i - 1][1])
                    if temp_length < file_length:
                        result = False
                        printf('Error: path: %s  size: %s  range: %s' % (temp_list[i - 1][1], str(file_length), str(temp_length)))
                        printf('Error: The file size exceeds the address space size!')

        return (
         result, temp_addrs, temp_files)

    def get_boot_info(self):
        """
        This function is used to get boot information from chips. At the same time, it can get chip ID.
        """
        printf('========= get_boot_info =========')
        bootinfo = None
        if self.interface == 'uart':
            ret = True
            start_time = time.time() * 1000
            ret, bootinfo = self._bflb_com_img_loader.img_get_bootinfo(self.boot_speed, self.boot_speed, None, self.do_reset, self.reset_hold_time, self.shake_hand_delay, self.reset_revert, self.cutoff_time, self.shake_hand_retry, self.isp_mode_sign, self._isp_shakehand_timeout)
            bootinfo = bootinfo.decode('utf-8')
            chipid = ''
            chipid = self.get_chip_id(bootinfo)
            printf('========= ChipID: ', chipid, ' =========')
            printf('Get bootinfo time cost(ms): ', time.time() * 1000 - start_time)
            return (
             ret, bootinfo, 'OK')
        printf('interface not fit')
        return (
         False, bootinfo, '')

    def error_code_print(self, code):
        set_error_code(code, self.task_num)
        printf('{"ErrorCode": "' + code + '","ErrorMsg":"' + eflash_loader_error_code[code] + '"}')

    def clock_para_update(self, file):
        if os.path.isfile(file) is False:
            efuse_bootheader_path = os.path.join(chip_path, self.chip_name, 'efuse_bootheader')
            efuse_bh_cfg = efuse_bootheader_path + '/efuse_bootheader_cfg.conf'
            sub_module = __import__(('libs.base.' + self.chip_type), fromlist=[self.chip_type])
            section = 'BOOTHEADER_GROUP0_CFG'
            fp = open(efuse_bh_cfg, 'r')
            data = fp.read()
            fp.close()
            if 'BOOTHEADER_CFG' in data:
                section = 'BOOTHEADER_CFG'
            else:
                if 'BOOTHEADER_CPU0_CFG' in data:
                    section = 'BOOTHEADER_CPU0_CFG'
                else:
                    if 'BOOTHEADER_GROUP0_CFG' in data:
                        section = 'BOOTHEADER_GROUP0_CFG'
            bh_data, tmp = bflb_efuse_boothd_create.update_data_from_cfg(sub_module.bootheader_cfg_keys.bootheader_cfg_keys, efuse_bh_cfg, section)
            bh_data = bflb_efuse_boothd_create.bootheader_update_flash_pll_crc(bh_data, self.chip_type)
            fp = open(file, 'wb+')
            self.get_new_bh_data(section, bh_data, fp)
            fp.close()
        fp = open_file(file, 'rb')
        clock_para = bytearray(fp.read())
        fp.close()
        return clock_para

    def clock_pll_set(self, shakehand, irq_en, clk_para):
        printf('Clock PLL set')
        if shakehand != 0:
            printf('clock set shake hand')
            if self.img_load_shake_hand() is False:
                return False
        start_time = time.time() * 1000
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('clk_set')['cmd_id'])
        irq_enable = bytearray(4)
        load_speed = bytearray(4)
        if irq_en:
            irq_enable = b'\x01\x00\x00\x00'
        load_speed = int_to_4bytearray_l(int(self.speed))
        data_send = irq_enable + load_speed + clk_para
        try_cnt = 0
        while True:
            ret, dmy = self.com_process_one_cmd('clk_set', cmd_id, data_send)
            if ret.startswith('OK'):
                break
            if try_cnt < self._checksum_err_retry_limit:
                printf('Retry')
                try_cnt += 1
            else:
                self.error_code_print('000C')
                return False

        printf('Set clock time cost(ms): ', time.time() * 1000 - start_time)
        self.bflb_serial_object.repeat_init(self.device, self.speed, self.chip_type, self.chip_name)
        self.bflb_serial_object.clear_buf()
        time.sleep(0.01)
        return True

    def efuse_read_mac_addr_process(self, callback=None):
        readdata = bytearray(0)
        macLen = self.get_mac_len()
        if self._need_shake_hand != 0:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, None)
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('efuse_read_mac')['cmd_id'])
        printf('Read mac addr ')
        ret, data_read = self.com_process_one_cmd('efuse_read_mac', cmd_id, bytearray(0))
        if ret.startswith('OK') is False:
            self.error_code_print('0023')
            return (False, None)
        readdata += data_read
        crcarray = get_crc32_bytearray(readdata[:macLen])
        if crcarray != readdata[macLen:macLen + 4]:
            printf(binascii.hexlify(crcarray))
            printf(binascii.hexlify(readdata[macLen:macLen + 4]))
            self.error_code_print('0025')
            return (False, None)
        return (True, readdata[:macLen])

    def flash_set_para_main_process(self, flash_pin, flash_para):
        printf('Set flash config ')
        if flash_para != bytearray(0):
            if flash_para[13:14] == b'\xff':
                printf('Skip set flash para due to flash id is 0xFF')
                return True
        if self._need_shake_hand != 0:
            printf('Flash set para shake hand')
            if self.img_load_shake_hand() is False:
                return False
        start_time = time.time() * 1000
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_set_para')['cmd_id'])
        data_send = int_to_4bytearray_l(flash_pin) + flash_para
        try_cnt = 0
        while True:
            ret, dmy = self.com_process_one_cmd('flash_set_para', cmd_id, data_send)
            if ret.startswith('OK'):
                break
            if try_cnt < self._checksum_err_retry_limit:
                printf('Retry')
                try_cnt += 1
            else:
                self.error_code_print('003B')
                return False

        printf('Set para time cost(ms): ', time.time() * 1000 - start_time)
        return True

    def flash_read_jedec_id_process(self, callback=None):
        printf('========= flash read jedec ID =========')
        readdata = bytearray(0)
        if self._need_shake_hand is not False:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, None)
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_read_jid')['cmd_id'])
        ret, data_read = self.com_process_one_cmd('flash_read_jid', cmd_id, bytearray(0))
        printf('Read flash jedec ID ')
        if ret.startswith('OK') is False:
            self.error_code_print('0030')
            return (False, None)
        readdata += data_read
        printf('readdata: ')
        printf(binascii.hexlify(readdata))
        printf('Finished')
        return (
         True, readdata[:4])

    def flash_para_update(self, file, jedec_id):
        flash_para = bytearray(0)
        if self.is_conf_exist(jedec_id) is True:
            sub_module = __import__(('libs.base.' + self.chip_type), fromlist=[self.chip_type])
            cfg_dir = app_path + '/utils/flash/' + self.chip_type + '/'
            conf_name = sub_module.flash_select_do.get_suitable_file_name(cfg_dir, jedec_id)
            offset, flashCfgLen, flash_para, flashCrcOffset, crcOffset = bflb_flash_select.update_flash_para_from_cfg(sub_module.bootheader_cfg_keys.bootheader_cfg_keys, cfg_dir + conf_name)
            fp = open(os.path.join(app_path, file), 'wb+')
            fp.write(flash_para)
            fp.close()
        return flash_para

    def is_conf_exist(self, flash_id):
        cfg_dir = app_path + '/utils/flash/' + self.chip_type + '/'
        conf_name = self.get_suitable_conf_name(cfg_dir, flash_id)
        if os.path.isfile(cfg_dir + conf_name) is False:
            return False
        return True

    def flash_chiperase_main_process(self):
        printf('Flash Chip Erase All')
        if self._need_shake_hand != 0:
            printf(FLASH_ERASE_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                printf('Shake hand fail')
                return False
        start_time = time.time() * 1000
        self.set_temp_timeout()
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_chiperase')['cmd_id'])
        try_cnt = 0
        while True:
            ret, dmy = self.com_process_one_cmd('flash_chiperase', cmd_id, bytearray(0))
            if ret.startswith('OK'):
                break
            else:
                if ret.startswith('PD'):
                    printf('erase pending')
                    while True:
                        ret = self.bflb_serial_object.deal_ack()
                        if ret.startswith('PD'):
                            printf('erase pending')
                        else:
                            self.bflb_serial_object.set_timeout(0.02)
                            self.bflb_serial_object.read(1000)
                            break
                        if time.time() * 1000 - start_time > self._erase_time_out:
                            printf('erase timeout')
                            break

                    if ret.startswith('OK'):
                        break
                    if try_cnt < self._checksum_err_retry_limit:
                        printf('Retry')
                        try_cnt += 1
                    else:
                        printf('Erase Fail')
                        self.bflb_serial_object.set_timeout(self._default_time_out)
                        self.error_code_print('0033')
                        return False

        printf('Chip erase time cost(ms): ', time.time() * 1000 - start_time)
        self.bflb_serial_object.set_timeout(self._default_time_out)
        return True

    def flash_cfg_option(self, read_flash_id, flash_para_file, flash_set, id_valid_flag, binfile, cfgfile, cfg, create_img_callback=None, create_simple_callback=None):
        ret = bflb_flash_select.flash_bootheader_config_check(self.chip_type, read_flash_id, convert_path(binfile), flash_para_file)
        if ret is False:
            printf('flashcfg not match first')
            if self.is_conf_exist(read_flash_id) is True:
                update_cfg(cfg, 'FLASH_CFG', 'flash_id', read_flash_id)
                if isinstance(cfgfile, BFConfigParser) == False:
                    cfg.write(cfgfile, 'w+')
                if create_img_callback is not None:
                    create_img_callback()
                else:
                    if create_simple_callback is not None:
                        create_simple_callback()
            else:
                self.error_code_print('003D')
                return False
            ret = bflb_flash_select.flash_bootheader_config_check(self.chip_name, read_flash_id, convert_path(binfile), flash_para_file)
            if ret is False:
                printf('flashcfg not match again')
                self.error_code_print('0040')
                return False
        if flash_para_file:
            if id_valid_flag != '80':
                printf('flash para file: ', flash_para_file)
                fp = open_file(flash_para_file, 'rb')
                flash_para = bytearray(fp.read())
                fp.close()
                ret = self.flash_set_para_main_process(flash_set, flash_para)
                self._need_shake_hand = False
                if ret is False:
                    return False

    def flash_switch_bank_process(self, bank):
        """When the chip has two flashes, switch the flashes according to bank."""
        printf('Flash Switch Bank')
        if self._need_shake_hand != 0:
            printf('Flash switch bank shake hand')
            if self.img_load_shake_hand() is False:
                printf('Shake hand fail')
                return False
        start_time = time.time() * 1000
        self.bflb_serial_object.set_timeout(self._erase_time_out / 1000)
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_switch_bank')['cmd_id'])
        data_send = int_to_4bytearray_l(bank)
        ret, dmy = self.com_process_one_cmd('flash_switch_bank', cmd_id, data_send)
        if ret.startswith('OK') is False:
            printf('Switch Fail')
            self.bflb_serial_object.set_timeout(self._default_time_out)
            self.error_code_print('0042')
            return False
        printf('Switch bank time cost(ms): ', time.time() * 1000 - start_time)
        self.bflb_serial_object.set_timeout(self._default_time_out)
        if bank == 0:
            self._flash2_select = False
        else:
            self._flash2_select = True
        return True

    def flash_load_opt(self, file, start_addr, callback=None):
        printf('========= flash load =========')
        if self._need_shake_hand != 0:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return False
        if self._flash2_select is True:
            start_addr -= self._flash1_size
        self.write_flash_data(file, start_addr, callback)
        ret = self.flash_load_main_process(file, start_addr, callback)
        if ret is False:
            printf('Flash load fail')
            return ret
        fw_sha256 = ''
        fp = open_file(file, 'rb')
        flash_data = fp.read()
        fp.close()
        flash_data_len = len(flash_data)
        if flash_data_len > 2097152:
            self.bflb_serial_object.set_timeout(2.0 * (flash_data_len / 2097152 + 1))
        sh = hashlib.sha256()
        sh.update(flash_data)
        fw_sha256 = sh.hexdigest()
        fw_sha256 = hexstr_to_bytearray(fw_sha256)
        printf('Sha caled by host: ', binascii.hexlify(fw_sha256).decode('utf-8'))
        del sh
        printf('xip mode Verify')
        ret, read_data = self.flash_xip_read_sha_main_process(start_addr, flash_data_len, 0, None, callback)
        try:
            printf('Sha caled by dev: ', binascii.hexlify(read_data).decode('utf-8'))
        except:
            printf('Sha caled by dev: ', binascii.hexlify(read_data))

        if ret is True and read_data == fw_sha256:
            printf('Verify success')
        else:
            printf('Verify fail')
            self.flash_load_tips()
            self.error_code_print('003E')
            ret = False
        if self.verify > 0:
            fp = open_file(file, 'rb')
            flash_data = bytearray(fp.read())
            fp.close()
            flash_data_len = len(flash_data)
            ret, read_data = self.flash_read_main_process(start_addr, flash_data_len, 0, None, callback)
            if ret is True and read_data == flash_data:
                printf('Verify success')
            else:
                printf('Verify fail')
                self.flash_load_tips()
                self.error_code_print('003E')
                ret = False
            printf('sbus mode Verify')
            ret, read_data = self.flash_read_sha_main_process(start_addr, flash_data_len, 0, None, callback)
            printf('Sha caled by dev: ', binascii.hexlify(read_data).decode('utf-8'))
            if ret is True and read_data == fw_sha256:
                printf('Verify success')
            else:
                printf('Verify fail')
                self.flash_load_tips()
                self.error_code_print('003E')
                ret = False
        self.bflb_serial_object.set_timeout(self._default_time_out)
        return ret

    def flash_load_specified(self, file, start_addr, callback=None):
        ret = False
        run_state = 0
        temp_start_addr = start_addr
        if len(self._skip_len) > 0 and self._skip_len[0] > 0:
            fp = open_file(file, 'rb')
            flash_data = fp.read()
            fp.close()
            flash_data_len = len(flash_data)
            if self._skip_addr[0] > temp_start_addr + flash_data_len or self._skip_addr[-1] + self._skip_len[-1] < temp_start_addr:
                ret = self.flash_load_opt(file, start_addr, callback)
                return ret
            for i in range(len(self._skip_addr)):
                if self._skip_addr[i] <= start_addr:
                    if self._skip_addr[i] + self._skip_len[i] > start_addr and self._skip_addr[i] + self._skip_len[i] < temp_start_addr + flash_data_len:
                        addr = self._skip_addr[i] + self._skip_len[i]
                        start_addr = self._skip_addr[i] + self._skip_len[i]
                    else:
                        if self._skip_addr[i] > start_addr and self._skip_addr[i] + self._skip_len[i] < temp_start_addr + flash_data_len:
                            printf('skip flash file, skip addr 0x%08X, skip len 0x%08X' % (
                             self._skip_addr[i], self._skip_len[i]))
                            addr = start_addr
                            data = flash_data[start_addr - temp_start_addr:self._skip_addr[i] - temp_start_addr]
                            filename, ext = os.path.splitext(file)
                            file_temp = os.path.join(app_path, filename + '_skip' + str(i) + ext)
                            fp = open(file_temp, 'wb')
                            fp.write(data)
                            fp.close()
                            ret = self.flash_load_opt(file_temp, addr, callback)
                            start_addr = self._skip_addr[i] + self._skip_len[i]
                        else:
                            if self._skip_addr[i] > start_addr:
                                if self._skip_addr[i] < temp_start_addr + flash_data_len and self._skip_addr[i] + self._skip_len[i] >= temp_start_addr + flash_data_len:
                                    printf('skip flash file, skip addr 0x%08X, skip len 0x%08X' % (
                                     self._skip_addr[i], self._skip_len[i]))
                                    addr = start_addr
                                    data = flash_data[start_addr - temp_start_addr:self._skip_addr[i] - temp_start_addr]
                                    filename, ext = os.path.splitext(file)
                                    file_temp = os.path.join(app_path, filename + '_skip' + str(i) + ext)
                                    fp = open(file_temp, 'wb')
                                    fp.write(data)
                                    fp.close()
                                    ret = self.flash_load_opt(file_temp, addr, callback)
                                    start_addr = temp_start_addr + flash_data_len
                                else:
                                    if self._skip_addr[i] <= start_addr:
                                        if self._skip_addr[i] + self._skip_len[i] >= temp_start_addr + flash_data_len:
                                            printf('skip flash file, skip addr 0x%08X, skip len 0x%08X' % (
                                             self._skip_addr[i], self._skip_len[i]))
                                            start_addr = temp_start_addr + flash_data_len
                                            return True

            if start_addr < temp_start_addr + flash_data_len:
                addr = start_addr
                data = flash_data[start_addr - temp_start_addr:]
                filename, ext = os.path.splitext(file)
                file_temp = os.path.join(app_path, filename + '_skip' + str(i + 1) + ext)
                fp = open(file_temp, 'wb')
                fp.write(data)
                fp.close()
                ret = self.flash_load_opt(file_temp, addr, callback)
        else:
            ret = self.flash_load_opt(file, start_addr, callback)
        return ret

    def flash_load_main_process(self, file, start_addr, callback=None):
        fp = open_file(file, 'rb')
        flash_data = bytearray(fp.read())
        fp.close()
        flash_data_len = len(flash_data)
        i = 0
        cur_len = 0
        if self.erase == 1:
            ret = self.flash_erase_main_process(start_addr, start_addr + flash_data_len - 1)
            if ret is False:
                return False
        start_time = time.time() * 1000
        log = ''
        if self.decompress_write and flash_data_len > 4096:
            self.bflb_serial_object.set_timeout(30.0)
            start_addr |= 2147483648
            cmd_name = 'flash_decompress_write'
            ret, flash_data, flash_data_len = self.flash_load_xz_compress(file)
            if ret is False:
                printf('Flash write data xz fail')
                self.bflb_serial_object.set_timeout(self._default_time_out)
                return False
            if time.time() * 1000 - start_time > 2200:
                printf(FLASH_LOAD_SHAKE_HAND)
                if self.img_load_shake_hand() is False:
                    return False
            else:
                if time.time() * 1000 - start_time > 1800:
                    time.sleep(0.5)
                    printf(FLASH_LOAD_SHAKE_HAND)
                    if self.img_load_shake_hand() is False:
                        return False
            printf('decompress flash load ', flash_data_len)
        else:
            cmd_name = 'flash_write'
        while i < flash_data_len:
            cur_len = flash_data_len - i
            if cur_len > self._bflb_com_tx_size - 8:
                cur_len = self._bflb_com_tx_size - 8
            cmd_id = hexstr_to_bytearray(self._com_cmds.get(cmd_name)['cmd_id'])
            data_send = int_to_4bytearray_l(i + start_addr) + flash_data[i:i + cur_len]
            start_addr &= 2147483647
            try_cnt = 0
            while True:
                ret, dmy = self.com_process_one_cmd(cmd_name, cmd_id, data_send)
                if ret.startswith('OK'):
                    break
                if try_cnt < self._checksum_err_retry_limit:
                    printf('Retry')
                    try_cnt += 1
                else:
                    self.error_code_print('0036')
                    self.bflb_serial_object.set_timeout(self._default_time_out)
                    return False

            i += cur_len
            log = 'Load ' + str(i) + '/' + str(flash_data_len) + ' {"progress":' + str(i * 100 // flash_data_len) + '}'
            printf(log)
            if callback is not None:
                if flash_data_len > 200:
                    callback(i, flash_data_len, 'APP_WR')

        printf(log)
        if self.flash_write_check_main_process() is False:
            printf('Flash write check fail')
            self.bflb_serial_object.set_timeout(self._default_time_out)
            return False
        self.bflb_serial_object.set_timeout(self._default_time_out)
        printf('Flash load time cost(ms): ', time.time() * 1000 - start_time)
        printf('Finished')
        return True

    def flash_xip_read_sha_main_process(self, start_addr, flash_data_len, shakehand=0, file=None, callback=None):
        readdata = bytearray(0)
        if shakehand != 0:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, None)
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_xip_read_start')['cmd_id'])
        ret, dmy = self.com_process_one_cmd('flash_xip_read_start', cmd_id, bytearray(0))
        if ret.startswith('OK') is False:
            self.error_code_print('0039')
            return (False, None)
        start_time = time.time() * 1000
        log = ''
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_xip_readSha')['cmd_id'])
        data_send = int_to_4bytearray_l(start_addr) + int_to_4bytearray_l(flash_data_len)
        try_cnt = 0
        while True:
            ret, data_read = self.com_process_one_cmd('flash_xip_readSha', cmd_id, data_send)
            if ret.startswith('OK'):
                break
            if try_cnt < self._checksum_err_retry_limit:
                printf('Retry')
                try_cnt += 1
            else:
                printf('Read Fail')
                cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_xip_read_finish')['cmd_id'])
                ret, dmy = self.com_process_one_cmd('flash_xip_read_finish', cmd_id, bytearray(0))
                if ret.startswith('OK') is False:
                    self.error_code_print('0039')
                    return (False, None)
                return (False, None)

        log += 'Read Sha256/' + str(flash_data_len)
        if callback is not None:
            callback(flash_data_len, flash_data_len, 'APP_VR')
        readdata += data_read
        printf(log)
        printf('Flash xip readsha time cost(ms): ', time.time() * 1000 - start_time)
        printf('Finished')
        if file is not None:
            fp = open_file(file, 'wb+')
            fp.write(readdata)
            fp.close()
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_xip_read_finish')['cmd_id'])
        ret, dmy = self.com_process_one_cmd('flash_xip_read_finish', cmd_id, bytearray(0))
        if ret.startswith('OK') is False:
            self.error_code_print('0039')
            return (False, None)
        return (True, readdata)

    def flash_read_sha_main_process(self, start_addr, flash_data_len, shakehand=0, file=None, callback=None):
        readdata = bytearray(0)
        if shakehand != 0:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, None)
        start_time = time.time() * 1000
        log = ''
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_readSha')['cmd_id'])
        data_send = int_to_4bytearray_l(start_addr) + int_to_4bytearray_l(flash_data_len)
        try_cnt = 0
        while True:
            ret, data_read = self.com_process_one_cmd('flash_readSha', cmd_id, data_send)
            if ret.startswith('OK'):
                break
            if try_cnt < self._checksum_err_retry_limit:
                printf('Retry')
                try_cnt += 1
            else:
                self.error_code_print('0038')
                return (False, None)

        log += 'Read Sha256/' + str(flash_data_len)
        if callback is not None:
            callback(flash_data_len, flash_data_len, 'APP_VR')
        readdata += data_read
        printf(log)
        printf('Flash readsha time cost(ms): ', time.time() * 1000 - start_time)
        printf('Finished')
        if file is not None:
            fp = open_file(file, 'wb+')
            fp.write(readdata)
            fp.close()
        return (True, readdata)

    def flash_load_xz_compress(self, file):
        try:
            xz_filters = [
             {'id':lzma.FILTER_LZMA2, 
              'dict_size':32768}]
            fp = open_file(file, 'rb')
            data = bytearray(fp.read())
            fp.close()
            flash_data = lzma.compress(data, check=(lzma.CHECK_CRC32), filters=xz_filters)
            flash_data_len = len(flash_data)
        except Exception as e:
            try:
                printf(e)
                return (False, None, None)
            finally:
                e = None
                del e

        return (
         True, flash_data, flash_data_len)

    def flash_load_tips(self):
        printf('########################################################################')
        printf('请按照以下描述排查问题：')
        printf('是否降低烧录波特率到500K测试过')
        printf('烧写文件的大小是否超过Flash所能存储的最大空间')
        printf('Flash是否被写保护')
        printf('########################################################################')

    def flash_erase_main_process(self, start_addr, end_addr, shakehand=0):
        printf('========= flash erase =========')
        printf('Erase flash  from ', hex(start_addr), ' to ', hex(end_addr))
        if shakehand != 0:
            printf(FLASH_ERASE_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                printf('Shake hand fail')
                return False
        start_time = time.time() * 1000
        self.set_temp_timeout()
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_erase')['cmd_id'])
        data_send = int_to_4bytearray_l(start_addr) + int_to_4bytearray_l(end_addr)
        try_cnt = 0
        while True:
            ret, dmy = self.com_process_one_cmd('flash_erase', cmd_id, data_send)
            if ret.startswith('OK'):
                break
            else:
                if ret.startswith('PD'):
                    printf('erase pending')
                    while True:
                        ret = self.bflb_serial_object.deal_ack()
                        if ret.startswith('PD'):
                            printf('erase pending')
                        else:
                            self.bflb_serial_object.set_timeout(0.02)
                            self.bflb_serial_object.read(1000)
                            break
                        if time.time() * 1000 - start_time > self._erase_time_out:
                            printf('erase timeout')
                            break

                    if ret.startswith('OK'):
                        break
                    if try_cnt < self._checksum_err_retry_limit:
                        printf('Retry')
                        try_cnt += 1
                    else:
                        printf('Erase Fail')
                        self.bflb_serial_object.set_timeout(self._default_time_out)
                        self.error_code_print('0034')
                        return False

        printf('Erase time cost(ms): ', time.time() * 1000 - start_time)
        self.bflb_serial_object.set_timeout(self._default_time_out)
        return True

    def flash_read_main_process(self, start_addr, flash_data_len, shakehand=0, file=None, callback=None):
        printf('========= flash read =========')
        i = 0
        cur_len = 0
        readdata = bytearray(0)
        if shakehand != 0:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, None)
        start_time = time.time() * 1000
        log = ''
        while i < flash_data_len:
            cur_len = flash_data_len - i
            if cur_len > self._bflb_com_tx_size - 8:
                cur_len = self._bflb_com_tx_size - 8
            else:
                cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_read')['cmd_id'])
                data_send = int_to_4bytearray_l(i + start_addr) + int_to_4bytearray_l(cur_len)
                try_cnt = 0
                while True:
                    ret, data_read = self.com_process_one_cmd('flash_read', cmd_id, data_send)
                    if ret.startswith('OK'):
                        break
                    if try_cnt < self._checksum_err_retry_limit:
                        printf('Retry')
                        try_cnt += 1
                    else:
                        self.error_code_print('0035')
                        return (False, None)

                i += cur_len
                log += 'Read ' + str(i) + '/' + str(flash_data_len)
                if len(log) > 50:
                    printf(log)
                    log = ''
                else:
                    log += '\n'
                if callback is not None:
                    callback(i, flash_data_len, 'APP_VR')
                readdata += data_read

        printf(log)
        printf('Flash read time cost(ms): ', time.time() * 1000 - start_time)
        printf('Finished')
        if file is not None:
            fp = open_file(file, 'wb+')
            fp.write(readdata)
            fp.close()
        return (True, readdata)

    def flash_write_check_main_process(self, shakehand=0):
        printf('Write check')
        if shakehand != 0:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return False
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_write_check')['cmd_id'])
        try_cnt = 0
        while True:
            retry = 0
            if self.decompress_write:
                retry = 10
            ret, dmy = self.com_process_one_cmd('flash_write_check', cmd_id, bytearray(0))
            if ret.startswith('OK'):
                break
            if try_cnt < self._checksum_err_retry_limit + retry:
                printf('Retry')
                try_cnt += 1
            else:
                self.error_code_print('0037')
                return False

        return True

    def efuse_load_specified(self, file, maskfile, efusedata, efusedatamask, verify=0, security_write=False):
        printf('========= efuse load =========')
        if self._need_shake_hand != 0:
            printf('Efuse load shake hand')
            ret = self.img_load_shake_hand()
            if ret is False:
                return False
        ret = self.efuse_load_main_process(file, maskfile, efusedata, efusedatamask, verify, security_write)
        return ret

    def efuse_load_main_process(self, file, maskfile, efusedata, efusedatamask, verify=0, security_write=False):
        if efusedata != bytearray(0):
            printf('Load data')
            efuse_data = efusedata
            mask_data = efusedatamask
        else:
            if file is not None:
                printf('Load file: ', file)
                fp = open_file(file, 'rb')
                efuse_data = bytearray(fp.read()) + bytearray(0)
                fp.close()
                if verify:
                    fp = open_file(maskfile, 'rb')
                    mask_data = bytearray(fp.read()) + bytearray(0)
                    fp.close()
                else:
                    mask_data = bytearray(0)
                if len(efuse_data) > 4096:
                    printf('Decrypt efuse data')
                    efuse_data = efuse_data[4096:]
                    security_key, security_iv = get_security_key()
                    efuse_data = aes_decrypt_data(efuse_data, security_key, security_iv, 0)
            else:
                efuse_data = self._efuse_data
                if verify:
                    mask_data = self._efuse_mask_data
                else:
                    mask_data = bytearray(0)
        if security_write:
            if self.get_ecdh_shared_key() is not True:
                return False
        printf('Load efuse 0')
        if security_write:
            cmd_name = 'efuse_security_write'
        else:
            cmd_name = 'efuse_write'
        cmd_id = hexstr_to_bytearray(self._com_cmds.get(cmd_name)['cmd_id'])
        data_send = efuse_data[0:124] + bytearray(4)
        if security_write:
            data_send = self.ecdh_encrypt_data(data_send)
        data_send = int_to_4bytearray_l(0) + data_send
        ret, dmy = self.com_process_one_cmd(cmd_name, cmd_id, data_send)
        if ret.startswith('OK') is False:
            printf('Write Fail')
            self.error_code_print('0021')
            return False
        if verify >= 1:
            ret, read_data = self.efuse_read_main_process(0, 128, shakehand=0, file=None, security_read=security_write)
            if ret is True and self.efuse_compare(read_data, mask_data[0:124] + bytearray(4), efuse_data[0:124] + bytearray(4)):
                printf('Verify success')
            else:
                printf('Read: ')
                printf(binascii.hexlify(read_data[0:124]).decode('utf-8'))
                printf('Expected: ')
                printf(binascii.hexlify(efuse_data[0:124]).decode('utf-8'))
                printf('Verify fail')
                self.error_code_print('0022')
                return False
        data_send = bytearray(12) + efuse_data[124:128]
        if security_write:
            data_send = self.ecdh_encrypt_data(data_send)
        data_send = int_to_4bytearray_l(112) + data_send
        ret, dmy = self.com_process_one_cmd(cmd_name, cmd_id, data_send)
        if ret.startswith('OK') is False:
            printf('Write Fail')
            self.error_code_print('0021')
            return False
        if verify >= 1:
            ret, read_data = self.efuse_read_main_process(112, 16, shakehand=0, file=None, security_read=security_write)
            if ret is True and self.efuse_compare(read_data, bytearray(12) + mask_data[124:128], bytearray(12) + efuse_data[124:128]):
                printf('Verify success')
            else:
                printf('Read: ')
                printf(binascii.hexlify(read_data[12:16]))
                printf('Expected: ')
                printf(binascii.hexlify(efuse_data[124:128]))
                printf('Verify fail')
                self.error_code_print('0022')
                return False
        if len(efuse_data) > 128:
            printf('Load efuse 1')
            if security_write:
                cmd_name = 'efuse_security_write'
            else:
                cmd_name = 'efuse_write'
            cmd_id = hexstr_to_bytearray(self._com_cmds.get(cmd_name)['cmd_id'])
            data_send = efuse_data[128:252] + bytearray(4)
            if security_write:
                data_send = self.ecdh_encrypt_data(data_send)
            data_send = int_to_4bytearray_l(128) + data_send
            ret, dmy = self.com_process_one_cmd(cmd_name, cmd_id, data_send)
            if ret.startswith('OK') is False:
                printf('Write Fail')
                self.error_code_print('0021')
                return False
            if verify >= 1:
                ret, read_data = self.efuse_read_main_process(128, 128, shakehand=0, file=None, security_read=security_write)
                if ret is True and self.efuse_compare(read_data, mask_data[128:252] + bytearray(4), efuse_data[128:252] + bytearray(4)):
                    printf('Verify success')
                else:
                    printf('Verify fail')
                    self.error_code_print('0022')
                    return False
            data_send = bytearray(12) + efuse_data[252:256]
            if security_write:
                data_send = self.ecdh_encrypt_data(data_send)
            data_send = int_to_4bytearray_l(240) + data_send
            ret, dmy = self.com_process_one_cmd(cmd_name, cmd_id, data_send)
            if ret.startswith('OK') is False:
                printf('Write Fail')
                self.error_code_print('0021')
                return False
            if verify >= 1:
                ret, read_data = self.efuse_read_main_process(240, 16, shakehand=0, file=None, security_read=security_write)
                if ret is True and self.efuse_compare(read_data, bytearray(12) + mask_data[252:256], bytearray(12) + efuse_data[252:256]):
                    printf('Verify success')
                else:
                    printf('Verify fail')
                    self.error_code_print('0022')
        printf('Finished')
        return True

    def efuse_read_main_process(self, start_addr, data_len, shakehand=0, file=None, security_read=False):
        readdata = bytearray(0)
        if shakehand != 0:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, None)
        if security_read:
            cmd_name = 'efuse_security_read'
        else:
            cmd_name = 'efuse_read'
        cmd_id = hexstr_to_bytearray(self._com_cmds.get(cmd_name)['cmd_id'])
        data_send = int_to_4bytearray_l(start_addr) + int_to_4bytearray_l(data_len)
        ret, data_read = self.com_process_one_cmd(cmd_name, cmd_id, data_send)
        printf('Read efuse ')
        if ret.startswith('OK') is False:
            self.error_code_print('0020')
            return (False, None)
        readdata += data_read
        if security_read:
            readdata = self.ecdh_decrypt_data(readdata)
        printf('Finished')
        if file is not None:
            fp = open_file(file, 'wb+')
            fp.write(readdata)
            fp.close()
        return (True, readdata)

    def efuse_compare(self, read_data, maskdata, write_data):
        i = 0
        for i in range(len(read_data)):
            compare_data = read_data[i] & maskdata[i]
            if compare_data & write_data[i] != write_data[i]:
                printf('compare fail: ', i)
                printf(read_data[i], write_data[i])
                return False

        return True

    def img_load_shake_hand(self):
        isp_sh_time = self.get_isp_sh_time()
        if self.interface.lower() == 'uart':
            self.bflb_serial_object.repeat_init(self.device, self.speed, self.chip_type, self.chip_name)
            if self._bflb_com_img_loader.toggle_boot_or_shake_hand(2, do_reset=False,
              reset_hold_time=100,
              shake_hand_delay=100,
              reset_revert=True,
              cutoff_time=0,
              isp_mode_sign=(self.isp_mode_sign),
              isp_timeout=isp_sh_time,
              boot_load=False,
              shake_hand_retry=2) != 'OK':
                self.error_code_print('0001')
                return False
        else:
            self.bflb_serial_object.if_init(self.device, self.speed, self.chip_type, self.chip_name)
            if self.bflb_serial_object.if_shakehand(do_reset=False, reset_hold_time=100,
              shake_hand_delay=100,
              reset_revert=True,
              cutoff_time=0,
              shake_hand_retry=2,
              isp_timeout=isp_sh_time,
              boot_load=False) != 'OK':
                self.error_code_print('0001')
                return False
        self._need_shake_hand = False
        return True

    def com_process_one_cmd(self, section, cmd_id, data_send):
        data_read = bytearray(0)
        data_len = int_to_2bytearray_l(len(data_send))
        checksum = 0
        checksum += bytearray_to_int(data_len[0:1]) + bytearray_to_int(data_len[1:2])
        for char in data_send:
            checksum += char

        data = cmd_id + int_to_2bytearray_l(checksum & 255)[0:1] + data_len + data_send
        if self.interface.lower() == 'uart':
            self.bflb_serial_object.write(data)
            if section in self._resp_cmds:
                res, data_read = self.bflb_serial_object.deal_response()
            else:
                res = self.bflb_serial_object.deal_ack()
        else:
            self.bflb_serial_object.if_write(data)
            if section in self._resp_cmds:
                res, data_read = self.bflb_serial_object.if_deal_response()
            else:
                res = self.bflb_serial_object.if_deal_ack()
        return (
         res, data_read)

    def get_suitable_conf_name(self, cfg_dir, flash_id):
        conf_files = []
        for home, dirs, files in os.walk(cfg_dir):
            for filename in files:
                if filename.split('_')[-1] == flash_id + '.conf':
                    conf_files.append(filename)

        if len(conf_files) > 1:
            printf('Flash id duplicate and alternative is:')
            for i in range(len(conf_files)):
                tmp = conf_files[i].split('.')[0]
                printf('%d:%s' % (i + 1, tmp))

            return conf_files[i]
        if len(conf_files) == 1:
            return conf_files[0]
        return ''

    def get_ecdh_shared_key(self, shakehand=0):
        printf('========= get ecdh shared key =========')
        publickey_file = 'utils/pem/publickey_uecc.pem'
        if shakehand != 0:
            printf('Shake hand')
            ret = self.img_load_shake_hand()
            if ret is False:
                return
        tmp_ecdh = bflb_ecdh.BflbEcdh()
        self._ecdh_public_key = tmp_ecdh.create_public_key()
        self._ecdh_private_key = binascii.hexlify(tmp_ecdh.ecdh.private_key.to_string()).decode('utf-8')
        printf('ecdh public key')
        printf(self._ecdh_public_key)
        printf('ecdh private key')
        printf(self._ecdh_private_key)
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('ecdh_get_pk')['cmd_id'])
        data_send = bytearray.fromhex(self._ecdh_public_key)
        ret, data_read = self.com_process_one_cmd('ecdh_get_pk', cmd_id, data_send)
        if ret.startswith('OK') is True:
            self._ecdh_peer_public_key = binascii.hexlify(data_read).decode('utf-8')
            printf('ecdh peer key')
            printf(self._ecdh_peer_public_key)
            self._ecdh_shared_key = tmp_ecdh.create_shared_key(self._ecdh_peer_public_key[0:128])
            printf('ecdh shared key')
            printf(self._ecdh_shared_key)
            cmd_id = hexstr_to_bytearray(self._com_cmds.get('ecdh_chanllenge')['cmd_id'])
            data_send = bytearray(0)
            ret, data_read = self.com_process_one_cmd('ecdh_chanllenge', cmd_id, data_send)
            if ret.startswith('OK') is True:
                printf('challenge data')
                printf(binascii.hexlify(data_read).decode('utf-8'))
                encrypted_data = data_read[0:32]
                signature = data_read[32:96]
                signature_r = data_read[32:64]
                signature_s = data_read[64:96]
                vk = ecdsa.VerifyingKey.from_pem(open_file('utils\\pem\\room_root_publickey_ecc.pem').read())
                try:
                    ret = vk.verify(signature, (self.ecdh_decrypt_data(encrypted_data)),
                      hashfunc=(hashlib.sha256),
                      sigdecode=(ecdsa.util.sigdecode_string))
                except Exception as err:
                    try:
                        printf(err)
                    finally:
                        err = None
                        del err

                if ret is True:
                    return True
                printf('Challenge verify fail')
                return False
            else:
                printf('Challenge ack fail')
                return False
        else:
            printf('Get shared key fail')
            return False

    def ecdh_encrypt_data(self, data):
        cryptor = AES.new(bytearray.fromhex(self._ecdh_shared_key[0:32]), AES.MODE_CBC, bytearray(16))
        ciphertext = cryptor.encrypt(data)
        return ciphertext

    def ecdh_decrypt_data(self, data):
        cryptor = AES.new(bytearray.fromhex(self._ecdh_shared_key[0:32]), AES.MODE_CBC, bytearray(16))
        plaintext = cryptor.decrypt(data)
        return plaintext

    def close_serial(self):
        if self.bflb_serial_object:
            try:
                self.bflb_serial_object.close()
            except Exception as e:
                try:
                    printf(e)
                finally:
                    e = None
                    del e

    def clear_all_data(self):
        if self.bflb_serial_object:
            try:
                self.bflb_serial_object.clear_buf()
            except Exception as e:
                try:
                    printf(e)
                finally:
                    e = None
                    del e

    def base_reset_cpu(self):
        if self.bflb_serial_object:
            self.bflb_serial_object.reset_cpu()

    def object_status_clear(self):
        self.bootinfo = None
        self._macaddr_check = bytearray(0)
        self._macaddr_check_status = False

    def flash_read_status_reg_process(self, cmd, len, callback=None):
        printf('========= flash read status register =========')
        readdata = bytearray(0)
        if self._need_shake_hand is not False:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, None)
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_read_status_reg')['cmd_id'])
        data_send = int_to_4bytearray_l(int(cmd, 16)) + int_to_4bytearray_l(len)
        ret, data_read = self.com_process_one_cmd('flash_read_status_reg', cmd_id, data_send)
        printf('Read flash status register ')
        if ret.startswith('OK') is False:
            self.error_code_print('0031')
            return (False, None)
        readdata += data_read
        printf('readdata: ')
        printf(binascii.hexlify(readdata))
        printf('Finished')
        return (
         True, readdata)

    def flash_write_status_reg_process(self, cmd, len, write_data, callback=None):
        printf('========= flash write status register =========')
        if self._need_shake_hand is not False:
            printf(FLASH_LOAD_SHAKE_HAND)
            if self.img_load_shake_hand() is False:
                return (False, 'Flash load shake hand fail')
        printf('write_data ', write_data)
        cmd_id = hexstr_to_bytearray(self._com_cmds.get('flash_write_status_reg')['cmd_id'])
        data_send = int_to_4bytearray_l(int(cmd, 16)) + int_to_4bytearray_l(len) + int_to_4bytearray_l(int(write_data, 16))
        ret, data_read = self.com_process_one_cmd('flash_write_status_reg', cmd_id, data_send)
        printf('Write flash status register ')
        if ret.startswith('OK') is False:
            self.error_code_print('0032')
            return (False, 'Write fail')
        printf('Finished')
        return (True, None)

    def bl_get_largest_addr(self, addrs, files):
        maxlen = 0
        datalen = 0
        for i in range(len(addrs)):
            if int(addrs[i], 16) > maxlen:
                maxlen = int(addrs[i], 16)
                if os.path.exists(files[i]):
                    datalen = os.path.getsize(files[i])
                else:
                    datalen = os.path.getsize(os.path.join(app_path, files[i]))

        return maxlen + datalen

    def bl_get_file_data(self, files):
        datas = []
        for file in files:
            if os.path.exists(file):
                temp_path = file
            else:
                temp_path = os.path.join(app_path, file)
            with open(temp_path, 'rb') as fp:
                data = fp.read()
            datas.append(data)

        return datas

    def bl_create_flash_default_data(self, length):
        datas = bytearray(length)
        for i in range(length):
            datas[i] = 255

        return datas

    def bl_write_flash_img(self, d_addrs, d_files, flash_size='1M'):
        whole_img_len = self.bl_get_largest_addr(d_addrs, d_files)
        whole_img_data = self.bl_create_flash_default_data(whole_img_len)
        whole_img_file = os.path.join(chip_path, self.chip_name, 'img_create', 'whole_flash_data.bin')
        if os.path.exists(whole_img_file):
            os.remove(whole_img_file)
        filedatas = self.bl_get_file_data(d_files)
        for i in range(len(d_addrs)):
            start_addr = int(d_addrs[i], 16)
            whole_img_data[start_addr:start_addr + len(filedatas[i])] = filedatas[i]

        if not os.path.exists(os.path.dirname(whole_img_file)):
            os.makedirs(os.path.dirname(whole_img_file))
        fp = open(whole_img_file, 'wb+')
        fp.write(whole_img_data)
        fp.close()

    def get_flash_pin_from_bootinfo(self, chiptype, bootinfo):
        return 128
# okay decompiling ./libs/base/bflb_base_eflash_loader.pyc
