# uncompyle6 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: BLFlashCommand.py
"""
Created on 20221216

@author: Dillon
"""
import os, re, sys, argparse, binascii, threading, configparser
from libs import bflb_utils
from libs.bflb_utils import get_serial_ports
from libs.bflb_interface_eflash_loader import InterfaceEflashLoader

def hex_to_dec(value):
    try:
        value = value.replace('0x', '')
        int(value, 16)
        return True
    except ValueError:
        return False


class ThreadIot(threading.Thread):

    def __init__(self, config, act='download', callback=None):
        threading.Thread.__init__(self)
        self.obj = InterfaceEflashLoader()
        self.config = config
        self.callback = callback
        self.act = act

    def stop(self):
        pass

    def run(self):
        self.obj.run(self.act, self.config, self.callback)


class MainClass:

    def __init__(self):
        self.dict_chip = {
         'BL602': ('bl602', 'bl602'), 
         'BL702': ('bl702', 'bl702'), 
         'BL702L': ('bl702l', 'bl702l'), 
         'BL808': ('bl808', 'bl808'), 
         'BL606P': ('bl606p', 'bl808'), 
         'BL616': ('bl616', 'bl616')}

    def get_addr_from_partition_by_name(self, name, parition_file, index):
        try:
            with open(parition_file, 'rb') as (fp):
                data = bytearray(fp.read())
                fp.close()
                start = data.find(name.encode('utf-8'))
                if start != -1:
                    addr = data[start + 9 + index * 4:start + 9 + 4 + index * 4]
                    addr.reverse()
                    addr = hex(int(binascii.hexlify(addr), 16))
                    return (True, addr)
                print(data)
                print(name.encode('utf-8'))
                return (False, '0')
        except Exception as e:
            try:
                bflb_utils.printf(e)
                return (False, '0')
            finally:
                e = None
                del e

    def get_value(self, args):
        self.config = dict()
        self.config['param'] = dict()
        self.config['check_box'] = dict()
        self.config['input_path'] = dict()
        self.config['param']['interface_type'] = args.interface
        self.config['param']['comport_uart'] = args.port
        self.config['param']['chip'] = args.chipname.lower()
        if args.chipname.upper() not in self.dict_chip:
            bflb_utils.printf('Error: chipname ' + args.chipname + ' is error!')
            return
        chip = self.dict_chip[args.chipname.upper()]
        self.config['param']['chip_name'] = chip[0]
        self.config['param']['chip_type'] = chip[1]
        if args.interface.lower() == 'uart':
            self.config['param']['speed_uart'] = str(args.baudrate)
            self.config['param']['speed_jlink'] = '1000'
        else:
            self.config['param']['speed_uart'] = '2000000'
            if str(args.baudrate) == '2000000':
                self.config['param']['speed_jlink'] = '1000'
            else:
                self.config['param']['speed_jlink'] = str(args.baudrate)
        if args.efuse:
            self.config['check_box']['efuse'] = True
            self.config['input_path']['efuse'] = os.path.abspath(args.efuse)
        else:
            self.config['check_box']['efuse'] = False
            self.config['input_path']['efuse'] = ''
        self.config['input_path']['config'] = args.config
        try:
            try:
                self.erase = 1
                self.skip_mode = '0x0, 0x0'
                self.boot2_isp_mode = 0
                config = configparser.ConfigParser()
                if not os.path.exists(os.path.abspath(args.config)):
                    bflb_utils.printf('Error: Config File Not Found!')
                    return
                config.read((os.path.abspath(args.config)), encoding='utf-8')
                if config:
                    for item in config.sections():
                        if item == 'cfg':
                            self.erase = config.get('cfg', 'erase', fallback=1)
                            self.skip_mode = config.get('cfg', 'skip_mode', fallback='0x0, 0x0')
                            self.boot2_isp_mode = config.get('cfg', 'boot2_isp_mode', fallback=0)

            except Exception as e:
                try:
                    config = None
                    print('ConfigParser Error: ' + str(e))
                finally:
                    e = None
                    del e

        finally:
            self.config['param']['erase'] = self.erase
            self.config['param']['skip_mode'] = self.skip_mode
            self.config['param']['boot2_isp_mode'] = self.boot2_isp_mode

        if args.key:
            self.config['check_box']['encrypt'] = True
            self.config['param']['aes_key'] = args.key
            self.config['param']['aes_iv'] = args.iv
        else:
            self.config['check_box']['encrypt'] = False
            self.config['param']['aes_key'] = ''
            self.config['param']['aes_iv'] = ''
        if args.pk:
            self.config['check_box']['sign'] = True
            self.config['input_path']['publickey'] = args.pk
            self.config['input_path']['privatekey'] = args.sk
        else:
            self.config['check_box']['sign'] = False
            self.config['input_path']['publickey'] = ''
            self.config['input_path']['privatekey'] = ''
        return self.config

    def get_value_file(self, name, path, addr, cpu_id=None):
        name = str(name)
        if os.path.isabs(path):
            path = os.path.abspath(path)
        else:
            config_dir = os.path.dirname(os.path.abspath(self.config['input_path']['config']))
            path = os.path.join(config_dir, path)
        if cpu_id:
            path = path.replace('$(CHIPNAME)', self.config['param']['chip_name'] + '_' + cpu_id)
        else:
            path = path.replace('$(CHIPNAME)', self.config['param']['chip_name'])
        addr = str(addr)
        self.config[name] = {}
        self.config[name]['addr'] = addr
        self.config[name]['path'] = path
        if not os.path.exists(path):
            dir_path = os.path.dirname(path)
            file_name = os.path.basename(path)
            try:
                all_file_list = os.listdir(dir_path)
            except Exception as e:
                try:
                    bflb_utils.printf(e)
                    return False
                finally:
                    e = None
                    del e

            result = []
            if '*' in file_name:
                file_name = file_name.replace('.', '\\.').replace('*', '.*[一-龥]*')
            for one_name in all_file_list:
                pattern = re.compile(file_name)
                temp_list = pattern.findall(one_name)
                if one_name in temp_list:
                    result += temp_list

            if len(result) > 1:
                bflb_utils.printf('Error: ' + name + ' multiple files were matched! ')
                return False
            if len(result) == 0:
                error = 'Error: ' + name + ':' + path + ' image file is not existed'
                bflb_utils.printf(error)
                return False
            self.config[name]['path'] = os.path.join(dir_path, result[0])
        if addr.find('@partition') != -1:
            bflb_utils.printf('{0} get address from partiton file {1}'.format(name, self.config['partition']['path']))
            success, addr_pt = self.get_addr_from_partition_by_name(name, self.config['partition']['path'], 0)
            if not success:
                bflb_utils.printf('Fail, not find ', name, ' in partition')
                return False
            self.config[name]['addr'] = addr_pt
            bflb_utils.printf('Address=', addr_pt)
            addr = addr_pt
        if not hex_to_dec(addr):
            error = 'Error: ' + addr + ' is invalid hexadecimal value'
            bflb_utils.printf(error)
            return False
        return True

    def main(self, argv):
        port = None
        ports = []
        for item in get_serial_ports():
            ports.append(item['port'])

        if ports:
            try:
                port = sorted(ports, key=(lambda x: int(re.match('COM(\\d+)', x).group(1))))[0]
            except Exception:
                port = sorted(ports)[0]

        parser = argparse.ArgumentParser(description='flash-command')
        parser.add_argument('--interface', dest='interface', default='uart', help='interface to use')
        parser.add_argument('--port', dest='port', default=port, help='serial port to use')
        parser.add_argument('--chipname', dest='chipname', default='BL602', help='chip name')
        parser.add_argument('--baudrate', dest='baudrate', default=2000000, type=int, help='the speed at which to communicate')
        parser.add_argument('--config', dest='config', default='', help='run config')
        parser.add_argument('--cpu_id', dest='cpu_id', default='', help='cpu id')
        parser.add_argument('--efuse', dest='efuse', default='', help='efuse options')
        parser.add_argument('--key', dest='key', default='', help='aes key')
        parser.add_argument('--iv', dest='iv', default='', help='aes iv')
        parser.add_argument('--pk', dest='pk', help='ecc public key')
        parser.add_argument('--sk', dest='sk', default='', help='ecc private key')
        args = parser.parse_args(argv)
        if args.port:
            bflb_utils.printf('Serial port is ' + args.port)
        else:
            if port:
                bflb_utils.printf('Serial port is ' + port)
            else:
                bflb_utils.printf('Serial port is not found')
        bflb_utils.printf('==================================================')
        config = self.get_value(args)
        if config:
            self.obj = InterfaceEflashLoader()
            self.obj.run('download', config, None)


if __name__ == '__main__':
    print(sys.argv)
    app = MainClass()
    app.main(sys.argv[1:])
# okay decompiling BLFlashCommand.pyc
