text: # -*- coding:utf-8 -*-
  
  import os
  import sys
  import fdt
  import struct
  import shutil
  import binascii
  import hashlib
  import lzma
  import toml
  import itertools
  import bootheader_cfg_keys as B_CFG_KEYS
  import efuse_cfg_keys as E_CFG_KEYS
  from configobj import ConfigObj
  from Cryptodome.Hash import SHA256
  
  app_path = ""
  chip_name = ""
  
  bl_factory_params_file_prefix = 'bl_factory_params_'
  bin_build_out_path = "build_out"
  default_conf_path = ""
  efuse_mask_file = ""
  efuse_file = ""
  
  eflash_loader_cfg_org = ""
  eflash_loader_cfg = ""
  
  dict_xtal = {"24M": 1, "32M": "2", "38.4M": "3", "40M": "4", "26M": "5", "RC32M": "6"}
  
  
  def bl_find_file_list(key_val, endswith):
      file_path_list = []
      conf_path = os.path.join(app_path, "img_conf")
      if os.path.exists(conf_path):
          files = os.listdir(conf_path)
          for f in files:
              if key_val in f and f.endswith(endswith):
                  find_file = os.path.join(conf_path, f)
                  file_path_list.append(find_file)
                  # return find_file
      if file_path_list != []:
          return file_path_list
      conf_path = os.path.join(os.path.abspath('..'), "image_conf",  default_conf_path)
      files = os.listdir(conf_path)
      for f in files:
          if key_val in f and f.endswith(endswith):
              find_file = os.path.join(conf_path, f)
              file_path_list.append(find_file)
              # return find_file
      return file_path_list
  
  
  def bl_find_file(key_val, endswith):
      conf_path = os.path.join(app_path, "img_conf") 
      if os.path.exists(conf_path):
          files = os.listdir(conf_path)
          for f in files:
              if key_val in f and f.endswith(endswith):
                  find_file = os.path.join(conf_path, f)
                  return find_file
      conf_path = os.path.join(os.path.abspath('..'), "image_conf",  default_conf_path)
      files = os.listdir(conf_path)
      for f in files:
          if key_val in f and f.endswith(endswith):
              find_file = os.path.join(conf_path, f)
              return find_file
  
  class bl_efuse_boothd_gen():
  
      def __init__(self):
          self.utils = bl_utils()
  
      def bootheader_update_flash_pll_crc(self, bootheader_data):
          flash_cfg_start = 8
          flash_cfg_len = 4 + 84 + 4
          # magic+......+CRC32
          flash_cfg = bootheader_data[flash_cfg_start + 4:flash_cfg_start + flash_cfg_len - 4]
          crcarray = self.utils.get_crc32_bytearray(flash_cfg)
          bootheader_data[flash_cfg_start + flash_cfg_len - 4:flash_cfg_start + flash_cfg_len] = crcarray
          pll_cfg_start = flash_cfg_start + flash_cfg_len
          pll_cfg_len = 4 + 8 + 4
          # magic+......+CRC32
          pll_cfg = bootheader_data[pll_cfg_start + 4:pll_cfg_start + pll_cfg_len - 4]
          crcarray = self.utils.get_crc32_bytearray(pll_cfg)
          bootheader_data[pll_cfg_start + pll_cfg_len - 4:pll_cfg_start + pll_cfg_len] = crcarray
          return bootheader_data
      
      
      def get_int_mask(self, pos, length):
          ones = "1" * 32
          zeros = "0" * 32
          mask = ones[0:32 - pos - length] + zeros[0:length] + ones[0:pos]
          return int(mask, 2)
      
      
      def update_data_from_cfg(self, config_keys, config_file, section):
          cfg = BFConfigParser()
          cfg.read(config_file)
          # get finally data len
          filelen = 0
          for key in config_keys:
              offset = int(config_keys.get(key)["offset"], 10)
              if offset > filelen:
                  filelen = offset
          filelen += 4
          data = bytearray(filelen)
          data_mask = bytearray(filelen)
          for key in cfg.options(section):
              if config_keys.get(key) == None:
                  print(key + " not exist")
                  continue
              val = cfg.get(section, key)
              if val.startswith("0x"):
                  val = int(val, 16)
              else:
                  val = int(val, 10)
              offset = int(config_keys.get(key)["offset"], 10)
              pos = int(config_keys.get(key)["pos"], 10)
              bitlen = int(config_keys.get(key)["bitlen"], 10)
      
              oldval = self.utils.bytearray_to_int(self.utils.bytearray_reverse(data[offset:offset + 4]))
              oldval_mask = self.utils.bytearray_to_int(self.utils.bytearray_reverse(data_mask[offset:offset + 4]))
              newval = (oldval & self.get_int_mask(pos, bitlen)) + (val << pos)
              if val != 0:
                  newval_mask = (oldval_mask | (~self.get_int_mask(pos, bitlen)))
              else:
                  newval_mask = oldval_mask
              data[offset:offset + 4] = self.utils.int_to_4bytearray_l(newval)
              data_mask[offset:offset + 4] = self.utils.int_to_4bytearray_l(newval_mask)
          return data, data_mask
      
      
      def bootheader_create_do(self, chipname, chiptype, config_file, section, output_file=None, if_img=False):
          efuse_bootheader_path = os.path.join(app_path, bin_build_out_path)
          try:
              # sub_module = __import__("bootheader_cfg_keys", fromlist=[chiptype])
              bh_data, tmp = self.update_data_from_cfg(B_CFG_KEYS.bootheader_cfg_keys, config_file, section)
              # bh_data, tmp = self.update_data_from_cfg(sub_module.bootheader_cfg_keys, config_file, section)
              bh_data = self.bootheader_update_flash_pll_crc(bh_data)
              if output_file == None:
                  fp = open(efuse_bootheader_path + "/" + section.lower().replace("_cfg", ".bin"), 'wb+')
              else:
                  fp = open(output_file, 'wb+')
              if section == "BOOTHEADER_CFG" and chiptype == "bl60x":
                  final_data = bytearray(8 * 1024)
                  # add sp core feature
                  # halt
                  bh_data[118] = (bh_data[118] | (1 << 2))
                  final_data[0:176] = bh_data
                  final_data[4096 + 0:4096 + 176] = bh_data
                  # change magic
                  final_data[4096 + 2] = 65
                  # change waydis to 0xf
                  final_data[117] = (final_data[117] | (15 << 4))
                  # change crc and hash ignore
                  final_data[4096 + 118] = final_data[4096 + 118] | 0x03
                  bh_data = final_data
              if if_img == True:
                  # clear flash magic
                  bh_data[8:12] = bytearray(4)
                  # clear clock magic
                  bh_data[100:104] = bytearray(4)
                  fp.write(bh_data[0:176])
              else:
                  fp.write(bh_data)
              fp.close()
              fp = open(efuse_bootheader_path + "/flash_para.bin", 'wb+')
              fp.write(bh_data[12:12 + 84])
              fp.close()
          except Exception as err:
              print("bootheader_create_do  fail!!")
              print(err)
              traceback.print_exc(limit=5, file=sys.stdout)
      
      def bootheader_create_process(self, chipname, chiptype, config_file, output_file1=None, output_file2=None, if_img=False):
          fp = open(config_file, 'r')
          data = fp.read()
          fp.close()
          if "BOOTHEADER_CFG" in data:
              self.bootheader_create_do(chipname, chiptype, config_file, "BOOTHEADER_CFG", output_file1, if_img)
          if "BOOTHEADER_CPU0_CFG" in data:
              self.bootheader_create_do(chipname, chiptype, config_file, "BOOTHEADER_CPU0_CFG", output_file1, if_img)
          if "BOOTHEADER_CPU1_CFG" in data:
              self.bootheader_create_do(chipname, chiptype, config_file, "BOOTHEADER_CPU1_CFG", output_file2, if_img)
      
      
      def efuse_create_process(self, chipname, chiptype, config_file, output_file=None):
          efuse_file = os.path.join(app_path, bin_build_out_path, "efusedata.bin")
          # sub_module = __import__("efuse_cfg_keys.py", fromlist=[chiptype])
          efuse_data, mask = self.update_data_from_cfg(E_CFG_KEYS.efuse_cfg_keys, config_file, "EFUSE_CFG")
          # efuse_data, mask = self.update_data_from_cfg(sub_module.efuse_cfg_keys, config_file, "EFUSE_CFG")
          if output_file == None:
              fp = open(efuse_file, 'wb+')
          else:
              fp = open(output_file, 'wb+')
          fp.write(efuse_data)
          fp.close()
          efuse_mask_file = os.path.join(app_path, bin_build_out_path, "efusedata_mask.bin")
          if output_file == None:
              fp = open(efuse_mask_file, 'wb+')
          else:
              fp = open(output_file.replace(".bin", "_mask.bin"), 'wb+')
          fp.write(mask)
          fp.close()
      
      def efuse_boothd_create_process(self, chipname, chiptype, config_file):
          self.bootheader_create_process(chipname, chiptype, config_file)
          self.efuse_create_process(chipname, chiptype, config_file)
  
  class bl_utils():
      
      #12345678->0x12,0x34,0x56,0x78
      def hexstr_to_bytearray_b(self, hexstring):
          return bytearray.fromhex(hexstring)
      
      
      def hexstr_to_bytearray(self, hexstring):
          return bytearray.fromhex(hexstring)
      
      
      def hexstr_to_bytearray_l(self, hexstring):
          b = bytearray.fromhex(hexstring)
          b.reverse()
          return b
      
      
      def int_to_2bytearray_l(self, intvalue):
          return struct.pack("<H", intvalue)
      
      
      def int_to_2bytearray_b(self, intvalue):
          return struct.pack(">H", intvalue)
      
      
      def int_to_4bytearray_l(self, intvalue):
          src = bytearray(4)
          src[3] = ((intvalue >> 24) & 0xFF)
          src[2] = ((intvalue >> 16) & 0xFF)
          src[1] = ((intvalue >> 8) & 0xFF)
          src[0] = ((intvalue >> 0) & 0xFF)
          return src
      
      
      def int_to_4bytearray_b(self, intvalue):
          val = int_to_4bytearray_l(intvalue)
          val.reverse()
          return val
      
      
      def bytearray_reverse(self, a):
          l = len(a)
          b = bytearray(l)
          i = 0
          while i < l:
              b[i] = a[l - i - 1]
              i = i + 1
          return b
      
      
      def bytearray_to_int(self, b):
          return int(binascii.hexlify(b), 16)
      
      
      def string_to_bytearray(self, string):
          return bytes(string, encoding="utf8")
      
      
      def bytearray_to_str(self, bytesarray):
          return str(bytesarray)
      
      
      def get_random_hexstr(self, n_bytes):
          hextring = ""
          i = 0
          while i < n_bytes:
              hextring = hextring + str(binascii.hexlify(random.randint(0, 255)))
              i = i + 1
          return hextring
      
      
      def get_crc32_bytearray(self, data):
          crc = binascii.crc32(data)
          return self.int_to_4bytearray_l(crc)
      
      
      def copyfile(self, srcfile, dstfile):
          if os.path.isfile(srcfile):
              fpath, fname = os.path.split(dstfile)
              if not os.path.exists(fpath):
                  os.makedirs(fpath)
              shutil.copyfile(srcfile, dstfile)
          else:
              print("Src file not exists")
              sys.exit()
      
      def enable_udp_send_log(self, server,local_echo):
          global udp_send_log,udp_socket_server,upd_log_local_echo
          udp_send_log=True
          upd_log_local_echo=local_echo
          udp_socket_server=server
          
      def add_udp_client(self, tid,upd_client):
          udp_clinet_dict[tid]=upd_client
      
      def remove_udp_client(self, tid):
          del udp_clinet_dict[tid]
      
      def Update_Cfg(self, cfg, section, key, value):
          if cfg.has_option(section, key):
              cfg.set(section, key, str(value))
          else:
              #print key," not found,adding it"
              cfg.set(section, key, str(value))
      
      
      def get_byte_array(self, str):
          return str.encode("utf-8")
      
  #class BFConfigParser(configparser.ConfigParser):
  #    def __init__(self, defaults=None):
  #        configparser.ConfigParser.__init__(self, defaults=defaults)
  #
  #    def optionxform(self, optionstr):
  #        return optionstr
  
  
  class BFConfigParser():
      cfg_infile = None
      cfg_obj = ConfigObj()
  
      def __init__(self, file=None):
          self.cfg_infile = file
          self.cfg_obj = ConfigObj(self.cfg_infile)
  
      def read(self, file=None):
          self.cfg_infile = file
          self.cfg_obj = ConfigObj(self.cfg_infile, encoding='UTF8')
          return self.cfg_obj
  
      def get(self, section, key):
          ret = self.cfg_obj[section][key]
          if ret == "\"\"":
              return ""
          else:
              return ret
  
      def set(self, section, key, value):
          self.cfg_obj[section][key] = str(value)
  
      def sections(self,):
          return self.cfg_obj.keys()
  
      def delete_section(self, section):
          del self.cfg_obj[section]
  
      def update_section_name(self, oldsection, newsection):
          _sections = self.cfg_obj.keys()
          for _section in _sections:
              print(_section)
              if _section == oldsection:
                  print(self.cfg_obj[_section])
                  self.cfg_obj[newsection] = self.cfg_obj[oldsection]
          self.delete_section(oldsection)
  
      def options(self, section):
          return self.cfg_obj[section]
  
      def has_option(self, section, key):
          _sections = self.cfg_obj.keys()
          for _section in _sections:
              if _section == section:
                  for _key in self.cfg_obj[_section]:
                      if _key == key:
                          return True
                      else:
                          continue
              else:
                  continue
          return False
  
      def write(self, outfile=None, flag=None):
          if outfile == None:
              self.cfg_obj.filename = self.cfg_infile
          else:
              self.cfg_obj.filename = outfile
          self.cfg_obj.write()
  
  class PtCreater(bl_utils):
  
      def __init__(self, config_file):
          #if not os.path.exists(config_file):
          #    config_file = os.path.join(default_conf_path, "partition_cfg_2M.toml")
          #config_file = bl_find_file("partition_cfg_", ".toml")
          self.parsed_toml = toml.load(config_file)
          self.entry_max = 16
          self.pt_new = False
  
      def __create_pt_table_do(self, lists, file):
          entry_table = bytearray(36 * self.entry_max)
          entry_cnt = 0
          for item in lists:
              entry_type = item["type"]
              entry_name = item["name"]
              entry_device = item["device"]
              entry_addr0 = item["address0"]
              entry_addr1 = item["address1"]
              entry_maxlen0 = item["size0"]
              entry_maxlen1 = item["size1"]
              entry_len = item["len"]
  
              entry_table[36 * entry_cnt + 0] = self.int_to_2bytearray_l(entry_type)[0]
              if len(entry_name) >= 8:
                  print("Entry name is too long!")
                  return False
              entry_table[36 * entry_cnt + 3:36 * entry_cnt + 3 + len(entry_name)] = bytearray(entry_name, "utf-8") + bytearray(0)
              entry_table[36 * entry_cnt + 12:36 * entry_cnt + 16] = self.int_to_4bytearray_l(entry_addr0)
              entry_table[36 * entry_cnt + 16:36 * entry_cnt + 20] = self.int_to_4bytearray_l(entry_addr1)
              entry_table[36 * entry_cnt + 20:36 * entry_cnt + 24] = self.int_to_4bytearray_l(entry_maxlen0)
              entry_table[36 * entry_cnt + 24:36 * entry_cnt + 28] = self.int_to_4bytearray_l(entry_maxlen1)
              entry_cnt += 1
          #partition table header
          #0x54504642
          pt_table = bytearray(16)
          pt_table[0] = 0x42
          pt_table[1] = 0x46
          pt_table[2] = 0x50
          pt_table[3] = 0x54
          pt_table[6:8] = self.int_to_2bytearray_l(int(entry_cnt))
          pt_table[12:16] = self.get_crc32_bytearray(pt_table[0:12])
          entry_table[36 * entry_cnt:36 * entry_cnt + 4] = self.get_crc32_bytearray(entry_table[0:36 * entry_cnt])
          data = pt_table + entry_table[0:36 * entry_cnt + 4]
          fp = open(file, 'wb+')
          fp.write(data)
          fp.close()
          return True
  
      def create_pt_table(self, file):
          self.pt_new = True
          return self.__create_pt_table_do(self.parsed_toml["pt_entry"], file)
  
      def get_pt_table_addr(self):
          addr0 = self.parsed_toml["pt_table"]["address0"]
          addr1 = self.parsed_toml["pt_table"]["address1"]
          return addr0, addr1
  
      def construct_table(self):
          parcel = {}
          if self.pt_new == True:
              parcel['pt_new'] = True
          else:
              parcel['pt_new'] = False
          parcel['pt_addr0'] = self.parsed_toml["pt_table"]["address0"]
          parcel['pt_addr1'] = self.parsed_toml["pt_table"]["address1"]
          for tbl_item in self.parsed_toml["pt_entry"]:
              if tbl_item['name'] == 'factory':
                  parcel['conf_addr'] = tbl_item['address0']
              if tbl_item['name'] == 'FW_CPU0':
                  parcel['fw_cpu0_addr'] = tbl_item['address0']
              if tbl_item['name'] == 'FW':
                  parcel['fw_addr'] = tbl_item['address0']
              if tbl_item['name'] == 'media':
                  parcel['media_addr'] = tbl_item['address0']
              if tbl_item['name'] == 'mfg':
                  parcel['mfg_addr'] = tbl_item['address0']
          return parcel
  
  class bl_img_create_do(bl_utils):
  
      def __init__(self):
  
          cfg = BFConfigParser()
  
          keyslot0 = 28
          keyslot1 = keyslot0 + 16
          keyslot2 = keyslot1 + 16
          keyslot3 = keyslot2 + 16
          keyslot4 = keyslot3 + 16
          keyslot5 = keyslot4 + 16
          keyslot6 = keyslot5 + 16
  
          wr_lock_key_slot_4_l = 13
          wr_lock_key_slot_5_l = 14
          wr_lock_boot_mode = 15
          wr_lock_dbg_pwd = 16
          wr_lock_sw_usage_0 = 17
          wr_lock_wifi_mac = 18
          wr_lock_key_slot_0 = 19
          wr_lock_key_slot_1 = 20
          wr_lock_key_slot_2 = 21
          wr_lock_key_slot_3 = 22
          wr_lock_key_slot_4_h = 23
          wr_lock_key_slot_5_h = 24
          rd_lock_dbg_pwd = 25
          rd_lock_key_slot_0 = 26
          rd_lock_key_slot_1 = 27
          rd_lock_key_slot_2 = 28
          rd_lock_key_slot_3 = 29
          rd_lock_key_slot_4 = 30
          rd_lock_key_slot_5 = 31
  
      #####################update efuse info##########################################
      def img_update_efuse(self, sign, pk_hash, flash_encryp_type, flash_key, sec_eng_key_sel, sec_eng_key):
          fp = open(cfg.get("Img_Cfg", "efuse_file"), 'rb')
          efuse_data = bytearray(fp.read()) + bytearray(0)
          fp.close()
          fp = open(cfg.get("Img_Cfg", "efuse_mask_file"), 'rb')
          efuse_mask_data = bytearray(fp.read()) + bytearray(0)
          fp.close()
  
          mask_4bytes = bytearray.fromhex("FFFFFFFF")
  
          efuse_data[0] |= flash_encryp_type
          efuse_data[0] |= (sign << 2)
          if flash_encryp_type > 0:
              efuse_data[0] |= 0x80
          efuse_mask_data[0] |= 0xff
          rw_lock = 0
          if pk_hash != None:
              efuse_data[keyslot0:keyslot2] = pk_hash
              efuse_mask_data[keyslot0:keyslot2] = mask_4bytes * 8
              rw_lock |= (1 << wr_lock_key_slot_0)
              rw_lock |= (1 << wr_lock_key_slot_1)
          if flash_key != None:
              if flash_encryp_type == 1:
                  # aes 128
                  efuse_data[keyslot2:keyslot4] = flash_key
                  efuse_mask_data[keyslot2:keyslot4] = mask_4bytes * 8
              elif flash_encryp_type == 2:
                  # aes 192
                  efuse_data[keyslot2:keyslot4] = flash_key
                  efuse_mask_data[keyslot2:keyslot4] = mask_4bytes * 8
              elif flash_encryp_type == 3:
                  # aes 256
                  efuse_data[keyslot2:keyslot4] = flash_key
                  efuse_mask_data[keyslot2:keyslot4] = mask_4bytes * 8
  
              rw_lock |= (1 << wr_lock_key_slot_2)
              rw_lock |= (1 << wr_lock_key_slot_3)
              rw_lock |= (1 << rd_lock_key_slot_2)
              rw_lock |= (1 << rd_lock_key_slot_3)
  
          if sec_eng_key != None:
              if flash_encryp_type == 0:
                  if sec_eng_key_sel == 0:
                      efuse_data[keyslot2:keyslot3] = sec_eng_key[16:32]
                      efuse_data[keyslot3:keyslot4] = sec_eng_key[0:16]
                      efuse_mask_data[keyslot2:keyslot4] = mask_4bytes * 8
                      rw_lock |= (1 << wr_lock_key_slot_2)
                      rw_lock |= (1 << wr_lock_key_slot_3)
                      rw_lock |= (1 << rd_lock_key_slot_2)
                      rw_lock |= (1 << rd_lock_key_slot_3)
                  if sec_eng_key_sel == 1:
                      efuse_data[keyslot3:keyslot4] = sec_eng_key[16:32]
                      efuse_data[keyslot2:keyslot3] = sec_eng_key[0:16]
                      efuse_mask_data[keyslot2:keyslot4] = mask_4bytes * 8
                      rw_lock |= (1 << wr_lock_key_slot_2)
                      rw_lock |= (1 << wr_lock_key_slot_3)
                      rw_lock |= (1 << rd_lock_key_slot_2)
                      rw_lock |= (1 << rd_lock_key_slot_3)
              if flash_encryp_type == 1:
                  if sec_eng_key_sel == 0:
                      efuse_data[keyslot4:keyslot5] = sec_eng_key[0:16]
                      efuse_mask_data[keyslot4:keyslot5] = mask_4bytes * 4
                      rw_lock |= (1 << wr_lock_key_slot_4_l)
                      rw_lock |= (1 << wr_lock_key_slot_4_h)
                      rw_lock |= (1 << rd_lock_key_slot_4)
                  if sec_eng_key_sel == 1:
                      efuse_data[keyslot4:keyslot5] = sec_eng_key[0:16]
                      efuse_mask_data[keyslot4:keyslot5] = mask_4bytes * 4
                      rw_lock |= (1 << wr_lock_key_slot_4_l)
                      rw_lock |= (1 << wr_lock_key_slot_4_h)
                      rw_lock |= (1 << rd_lock_key_slot_4)
          # set read write lock key
          efuse_data[124:128] = self.int_to_4bytearray_l(rw_lock)
          efuse_mask_data[124:128] = self.int_to_4bytearray_l(rw_lock)
          fp = open(cfg.get("Img_Cfg", "efuse_file"), 'wb+')
          fp.write(efuse_data)
          fp.close()
          fp = open(cfg.get("Img_Cfg", "efuse_mask_file"), 'wb+')
          fp.write(efuse_mask_data)
          fp.close()
  
  
      ####################get sign and encrypt info##########################################
  
  
      def img_create_get_sign_encrypt_info(self, bootheader_data):
          sign = bootheader_data[116] & 0x3
          encrypt = ((bootheader_data[116] >> 2) & 0x3)
          key_sel = ((bootheader_data[116] >> 4) & 0x3)
          return sign, encrypt, key_sel
  
  
      ####################get hash ignore ignore##########################################
  
  
      def img_create_get_hash_ignore(self, bootheader_data):
          return (bootheader_data[118] >> 1) & 0x1
  
  
      ####################get crc ignore ignore##########################################
  
  
      def img_create_get_crc_ignore(self, bootheader_data):
          return bootheader_data[118] & 0x1
  
  
      #####################update boot header info##########################################
  
  
      def img_create_update_bootheader(self, bootheader_data, hash, seg_cnt):
          # update segment count
          bootheader_data[120:124] = self.int_to_4bytearray_l(seg_cnt)
  
          # update hash
          sign, encrypt, key_sel = self.img_create_get_sign_encrypt_info(bootheader_data)
          if self.img_create_get_hash_ignore(bootheader_data) == 1 and sign == 0:
              # do nothing
              pass
          else:
              bootheader_data[132:164] = hash
  
          # update header crc
          if self.img_create_get_crc_ignore(bootheader_data) == 1:
              # do nothing
              pass
          else:
              hd_crcarray = self.get_crc32_bytearray(bootheader_data[0:176 - 4])
              bootheader_data[176 - 4:176] = hd_crcarray
              print("Header crc: ", binascii.hexlify(hd_crcarray))
          return bootheader_data[0:176]
  
  
      #####################update segment header according segdata#########################
  
  
      def img_create_update_segheader(self, segheader, segdatalen, segdatacrc):
          segheader[4:8] = segdatalen
          segheader[8:12] = segdatacrc
          return segheader
  
  
      #####################do hash of image################################################
  
  
      def img_create_sha256_data(self, data_bytearray):
          hashfun = SHA256.new()
          hashfun.update(data_bytearray)
          return self.hexstr_to_bytearray(hashfun.hexdigest())
  
  
      #####################encrypt image, mainly segdata#####################################
  
  
      def img_create_encrypt_data(self, data_bytearray, key_bytearray, iv_bytearray, flash_img):
          if flash_img == 0:
              cryptor = AES.new(key_bytearray, AES.MODE_CBC, iv_bytearray)
              ciphertext = cryptor.encrypt(data_bytearray)
          else:
              #iv = Crypto.Util.Counter.new(128, initial_value = long(binascii.hexlify(iv_bytearray),16))
              iv = Counter.new(128, initial_value=int(binascii.hexlify(iv_bytearray), 16))
              cryptor = AES.new(key_bytearray, AES.MODE_CTR, counter=iv)
              ciphertext = cryptor.encrypt(data_bytearray)
          return ciphertext
  
  
      #####################sign image(hash code)#####################################
  
  
      def img_create_sign_data(self, data_bytearray, privatekey_file_uecc, publickey_file):
          sk = ecdsa.SigningKey.from_pem(open(privatekey_file_uecc).read())
          vk = ecdsa.VerifyingKey.from_pem(open(publickey_file).read())
          pk_data = vk.to_string()
          pk_hash = self.img_create_sha256_data(pk_data)
  
          signature = sk.sign(data_bytearray, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_string)
  
          # return len+signature+crc
          len_array = self.int_to_4bytearray_l(len(signature))
          sig_field = len_array + signature
          crcarray = self.get_crc32_bytearray(sig_field)
          return pk_data, pk_hash, sig_field + crcarray
  
  
      ######################## read one file and append crc if needed#####################
  
  
      def img_create_read_file_append_crc(self, file, crc):
          fp = open(file, 'rb')
          read_data = bytearray(fp.read())
          crcarray = bytearray(0)
          if crc:
              crcarray = self.get_crc32_bytearray(read_data)
          fp.close()
          return read_data + crcarray
  
  
      def img_creat_process(self, flash_img):
          encrypt_blk_size = 16
          padding = bytearray(encrypt_blk_size)
          data_tohash = bytearray(0)
          ret = 'OK'
          cfg_section = "Img_Cfg"
  
          # get segdata to deal with
          segheader_file = []
          if flash_img == 0:
              for files in cfg.get(cfg_section, "segheader_file").split(" "):
                  segheader_file.append(str(files))
          segdata_file = []
          for files in cfg.get(cfg_section, "segdata_file").split(" "):
              segdata_file.append(str(files))
              if flash_img == 1:
                  break
  
          # get bootheader
          boot_header_file = cfg.get(cfg_section, "boot_header_file")
          bootheader_data = self.img_create_read_file_append_crc(boot_header_file, 0)
          # decide encrypt and sign
          encrypt = 0
          sign, encrypt, key_sel = self.img_create_get_sign_encrypt_info(bootheader_data)
          aesiv_data = bytearray(0)
          pk_data = bytearray(0)
          if sign != 0:
              publickey_file = cfg.get(cfg_section, "publickey_file")
              privatekey_file_uecc = cfg.get(cfg_section, "privatekey_file_uecc")
  
          if encrypt != 0:
              encrypt_key_org = self.hexstr_to_bytearray(cfg.get(cfg_section, "aes_key_org"))
              global encrypt_key
              if encrypt == 1:
                  encrypt_key = encrypt_key_org[0:16]
              elif encrypt == 2:
                  encrypt_key = encrypt_key_org[0:32]
              elif encrypt == 3:
                  encrypt_key = encrypt_key_org[0:24]
              encrypt_iv = self.hexstr_to_bytearray(cfg.get(cfg_section, "aes_iv"))
              iv_crcarray = self.get_crc32_bytearray(encrypt_iv)
              aesiv_data = encrypt_iv + iv_crcarray
              data_tohash = data_tohash + aesiv_data
  
          # decide seg_cnt values
          seg_cnt = len(segheader_file)
          if flash_img == 0 and seg_cnt != len(segdata_file):
              print("Segheader count and segdata count not match")
              return "FAIL", data_tohash
  
          data_toencrypt = bytearray(0)
          if flash_img == 0:
              i = 0
              seg_header_list = []
              seg_data_list = []
              while i < seg_cnt:
                  # read seg data and calculate crcdata
                  seg_data = self.img_create_read_file_append_crc(segdata_file[i], 0)
                  padding_size = 0
                  if len(seg_data) % encrypt_blk_size != 0:
                      padding_size = encrypt_blk_size - \
                          len(seg_data) % encrypt_blk_size
                      seg_data += padding[0:padding_size]
                  segdata_crcarray = self.get_crc32_bytearray(seg_data)
                  seg_data_list.append(seg_data)
  
                  # read seg header and replace segdata's CRC
                  seg_header = self.img_create_read_file_append_crc(segheader_file[i], 0)
                  seg_header = img_create_update_segheader(seg_header, self.int_to_4bytearray_l(len(seg_data)), segdata_crcarray)
                  segheader_crcarray = self.get_crc32_bytearray(seg_header)
                  seg_header = seg_header + segheader_crcarray
                  seg_header_list.append(seg_header)
                  i = i + 1
  
              # get all data to encrypt
              i = 0
              while i < seg_cnt:
                  # ,now changed to encrypted since download tool's segdata len is from bootrom
                  data_toencrypt += seg_header_list[i]
                  data_toencrypt += seg_data_list[i]
                  i += 1
          else:
              seg_data = self.img_create_read_file_append_crc(segdata_file[0], 0)
              padding_size = 0
              if len(seg_data) % encrypt_blk_size != 0:
                  padding_size = encrypt_blk_size - len(seg_data) % encrypt_blk_size
                  seg_data += padding[0:padding_size]
              data_toencrypt += seg_data
              seg_cnt = len(data_toencrypt)
  
          # do encrypt
          if encrypt != 0:
              data_toencrypt = img_create_encrypt_data(data_toencrypt, encrypt_key, encrypt_iv, flash_img)
  
          # get fw data
          fw_data = bytearray(0)
          data_tohash += data_toencrypt
          fw_data = data_toencrypt
  
          # hash fw img
          hash = self.img_create_sha256_data(data_tohash)
          # update boot header and recalculate crc
          bootheader_data = self.img_create_update_bootheader(bootheader_data, hash, seg_cnt)
  
          # add signautre
          signature = bytearray(0)
          pk_hash = None
          if sign == 1:
              pk_data, pk_hash, signature = img_create_sign_data(data_tohash, privatekey_file_uecc, publickey_file)
              pk_data = pk_data + self.get_crc32_bytearray(pk_data)
  
          # write whole image
          if flash_img == 1:
              bootinfo_file_name = cfg.get(cfg_section, "bootinfo_file")
              fp = open(bootinfo_file_name, 'wb+')
              bootinfo = bootheader_data + pk_data + signature + aesiv_data
              fp.write(bootinfo)
              fp.close()
              fw_file_name = cfg.get(cfg_section, "img_file")
              fp = open(fw_file_name, 'wb+')
              fp.write(fw_data)
              fp.close()
              # update efuse
              if encrypt != 0:
                  if encrypt == 1:
                      # AES 128
                      img_update_efuse(sign, pk_hash, 1, encrypt_key + bytearray(32 - len(encrypt_key)), key_sel, None)
                  if encrypt == 2:
                      # AES 256
                      img_update_efuse(sign, pk_hash, 3, encrypt_key + bytearray(32 - len(encrypt_key)), key_sel, None)
                  if encrypt == 3:
                      # AES 192
                      img_update_efuse(sign, pk_hash, 2, encrypt_key + bytearray(32 - len(encrypt_key)), key_sel, None)
              else:
                  self.img_update_efuse(sign, pk_hash, encrypt, None, key_sel, None)
          else:
              whole_img_file_name = cfg.get(cfg_section, "whole_img_file")
              fp = open(whole_img_file_name, 'wb+')
              img_data = bootheader_data + pk_data + signature + aesiv_data + fw_data
              fp.write(img_data)
              fp.close()
              # update efuse
              if encrypt != 0:
                  if encrypt == 1:
                      # AES 128
                      img_update_efuse(sign, pk_hash, 1, None, key_sel, encrypt_key + bytearray(32 - len(encrypt_key)))
                  if encrypt == 2:
                      # AES 256
                      img_update_efuse(sign, pk_hash, 3, None, key_sel, encrypt_key + bytearray(32 - len(encrypt_key)))
                  if encrypt == 3:
                      # AES 192
                      img_update_efuse(sign, pk_hash, 2, None, key_sel, encrypt_key + bytearray(32 - len(encrypt_key)))
              else:
                  img_update_efuse(sign, pk_hash, 0, None, key_sel, bytearray(32))
          return "OK", data_tohash
  
  
      def usage():
          print(sys.argv[0], "\n")
          print("-i/--img_type=  :image type:media or if")
          print("-h/--help       :helper")
  
  
      #######################################################################
  
  
      def img_create_do(self, options, img_dir_path=None, config_file=None):
  
          print("Image create path: ", img_dir_path)
  
          if config_file == None:
              config_file = img_dir_path + "/img_create_cfg.ini"
          cfg.read(config_file)
          print("Config file: ", config_file)
  
          img_type = "media"
          signer = "none"
          ret = "OK"
          data_tohash = bytearray(0)
  
          try:
              opts, args = getopt.getopt(options, 'i:s:Hh', ["img_type=", "signer=", "help"])
              for option, value in opts:
                  if option in ["-h", "-H"]:
                      usage()
                  if option in ["-i", "--img_type"]:
                      img_type = value
                  if option in ["-s", "--signer"]:
                      signer = value
          except getopt.GetoptError as err:
              # will  something like "option -a not recognized")
              print(err)
              usage()
              
  
          if img_type == "media":
              flash_img = 1
          else:
              flash_img = 0
  
          # deal image creation
          ret, data_tohash = self.img_creat_process(flash_img)
  
          if ret != "OK":
              print("Fail to create images!")
              return
  
      def create_sp_media_image(self, config, cpu_type=None):
          global cfg
          cfg = BFConfigParser()
          cfg.read(config)
          self.img_creat_process(1)
  
  class bl_img_create(bl_img_create_do):
      def img_create(self, options, chipname="bl60x", chiptype="bl60x", img_dir=None, config_file=None):
          img_dir_path = os.path.join(app_path, chipname, "img_create")
          if img_dir is None:
              self.img_create_do(options, img_dir_path, config_file)
          else:
              self.img_create_do(options, img_dir, config_file)
  
      def create_sp_media_image_file(self, config, chiptype="bl60x", cpu_type=None):
          self.create_sp_media_image(config, cpu_type)
  
  class bl_device_tree():
      def bl_dts2dtb(self, src_addr="", dest_addr=""):
          if "" == src_addr or "" == dest_addr:
              print("bl_dts2dtb please check arg.")
              return
          with open(src_addr, "r") as f:
              tmp1_dts = f.read()
  
          tmp2_dtb = fdt.parse_dts(tmp1_dts)
  
          dest_addr = os.path.join(app_path, bin_build_out_path, dest_addr)
          with open(dest_addr, "wb") as f:
              f.write(tmp2_dtb.to_dtb(version=17))
  
      def bl_ro_params_device_tree(self, in_dts_config, out_bin_file):
          dts_config = in_dts_config
          bin_file = out_bin_file
          self.bl_dts2dtb(dts_config, bin_file)
  
  class bl_whole_img_generate():
      def bl_create_flash_default_data(self, length):
          datas = bytearray(length)
          for i in range(length):
              datas[i] = 0xff
          return datas
  
      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)
                  datalen = os.path.getsize(files[i])
          return maxlen + datalen
  
      def bl_get_file_data(self, files):
          datas = []
          for file in files:
              with open(file, 'rb') as fp:
                  data = fp.read()
              datas.append(data)
          return datas
  
      def bl_write_flash_img(self, d_addrs, d_files, flash_size):
          whole_img_len = self.bl_get_largest_addr(d_addrs, d_files)
          whole_img_data = self.bl_create_flash_default_data(whole_img_len)
          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]
          # dst_file = os.path.join(app_path, bin_build_out_path, "whole_flash_data.bin")
          dst_file = os.path.join(app_path, bin_build_out_path, "whole_{}.bin".format(file_finally_name))
          fp = open(dst_file, 'wb+')
          fp.write(whole_img_data)
          print("Generating BIN File to %s" %(dst_file))
          fp.close()
  
      def bl_image_gen_cfg(self, raw_bin_name, bintype, key=None, iv=None, cfg_ini=None, cpu_type=None):
          cfg = BFConfigParser()
          if cfg_ini in [None, '']:
              f_org = bl_find_file("img_create_cfg", ".conf")
              f = os.path.join(app_path, bin_build_out_path, "img_create_cfg.ini")
              #if os.path.isfile(f) == False:
              shutil.copy(f_org, f)
          else:
              f = cfg_ini
          cfg.read(f)
          if bintype == "fw":
              if cpu_type == None:
                  bootinfo_file = os.path.join(app_path, bin_build_out_path, "bootinfo.bin")
                  img_file = os.path.join(app_path, bin_build_out_path, "img.bin")
              else:
                  bootinfo_file = os.path.join(app_path, bin_build_out_path, "bootinfo_{0}.bin".format(cpu_type.lower()))
                  img_file = os.path.join(app_path, bin_build_out_path, "img_{0}.bin".format(cpu_type.lower()))
          else:
              bootinfo_file = os.path.join(app_path, bin_build_out_path, "bootinfo_{0}.bin".format(bintype))
              img_file = os.path.join(app_path, bin_build_out_path, "img_{0}.bin".format(bintype))
  
          if cpu_type != None:
              img_section_name = "Img_" + cpu_type + "_Cfg"
          else:
              if "Img_CPU0_Cfg" in cfg.sections():
                  img_section_name = "Img_CPU0_Cfg"
              else:
                  img_section_name = "Img_Cfg"
  
          bh_file = os.path.join(app_path, bin_build_out_path, "bootheader.bin")
          efuse_file = os.path.join(app_path, bin_build_out_path, "efusedata.bin")
          efuse_mask_file = os.path.join(app_path, bin_build_out_path, "efusedata_mask.bin")
          cfg.set(img_section_name, 'boot_header_file', bh_file)
          cfg.set(img_section_name, 'efuse_file', efuse_file)
          cfg.set(img_section_name, 'efuse_mask_file', efuse_mask_file)
          cfg.set(img_section_name, 'segdata_file', raw_bin_name)
          cfg.set(img_section_name, 'bootinfo_file', bootinfo_file)
          cfg.set(img_section_name, 'img_file', img_file)
          if key:
              cfg.set(img_section_name, 'aes_key_org', key)
          if iv:
              cfg.set(img_section_name, 'aes_iv', iv)
          cfg.write(f, 'w')
          return f
  
      def bl_image_gen(self, bintype, raw_bin_name, key=None, iv=None, cfg_ini=None):
          # python bflb_img_create.py -c np -i media -s none
          f = self.bl_image_gen_cfg(raw_bin_name, bintype)
          #exe_genitor(['bflb_img_create.exe', '-c', 'np', '-i', 'media', '-s', 'none'])
          img_create = bl_img_create() 
          img_create.create_sp_media_image_file(f)
  
      def bl_fw_boot_head_gen(self, boot2, xtal, config, encrypt=False, chipname="bl60x", chiptype="bl60x", cpu_type=None):
          cfg = BFConfigParser()
          cfg.read(config)
  
          if cpu_type != None:
              bootheader_section_name = "BOOTHEADER_" + cpu_type + "_CFG"
          else:
              if "BOOTHEADER_CPU0_CFG" in cfg.sections():
                  bootheader_section_name = "BOOTHEADER_CPU0_CFG"
              else:
                  bootheader_section_name = "BOOTHEADER_CFG"
  
          if boot2 == True:
              cfg.set(bootheader_section_name, 'img_start', '0x2000')
              cfg.set(bootheader_section_name, 'cache_enable', '1')
              cfg.set(bootheader_section_name, 'crc_ignore', '1')
              cfg.set(bootheader_section_name, 'hash_ignore', '1')
              #cfg.set(bootheader_section_name,'sfctrl_clk_delay', '0')
              if cpu_type != None:
                  cfg.set(bootheader_section_name, 'halt_cpu1', '1')
              cfg.set(bootheader_section_name, 'key_sel', '0')
  
          if encrypt:
              cfg.set(bootheader_section_name, 'encrypt_type', '1')
          else:
              cfg.set(bootheader_section_name, 'encrypt_type', '0')
  
          cfg.set(bootheader_section_name, 'xtal_type', dict_xtal[xtal])
  
          cfg.write(config)
          create = bl_efuse_boothd_gen()
          create.efuse_boothd_create_process(chipname, chiptype, config)
  
      def bl_whole_flash_bin_create(self, bin_file, boot2, ro_params, pt_parcel, media, mfg, flash_opt="1M"):
         
          d_files = []
          d_addrs = []
  
          if pt_parcel == None:
              return False
          
          if boot2 == True:
              d_files.append(os.path.join(app_path, bin_build_out_path, "bootinfo_boot2.bin"))
              d_addrs.append("00000000")
              d_files.append(os.path.join(app_path, bin_build_out_path, "img_boot2.bin"))
              d_addrs.append("00002000")
  
          if pt_parcel != None and len(pt_parcel) > 0 and pt_parcel['pt_new'] == True:
              d_files.append(os.path.join(app_path, bin_build_out_path, "partition.bin"))
              d_addrs.append(hex(pt_parcel['pt_addr0'])[2:])
              d_files.append(os.path.join(app_path, bin_build_out_path, "partition.bin"))
              d_addrs.append(hex(pt_parcel['pt_addr1'])[2:])
  
          if bin_file == True and 'fw_addr' in pt_parcel:
              d_files.append(os.path.join(app_path, bin_build_out_path, "bootinfo.bin"))
              d_addrs.append(hex(pt_parcel['fw_addr'])[2:])
              d_files.append(os.path.join(app_path, bin_build_out_path, "img.bin"))
              d_addrs.append(hex(pt_parcel['fw_addr'] + 0x1000)[2:])
  
          if ro_params != None and len(ro_params) > 0 and pt_parcel['conf_addr'] != None:
              bl_ro_device_tree = bl_device_tree()
              dtb_file = os.path.join(app_path, bin_build_out_path, "ro_params.dtb")
              bl_ro_device_tree.bl_ro_params_device_tree(ro_params, dtb_file)
              d_files.append(os.path.join(app_path, bin_build_out_path, "ro_params.dtb"))
              d_addrs.append(hex(pt_parcel['conf_addr'])[2:])
  
          if media == True and pt_parcel['media_addr'] != None:
              d_files.append(os.path.join(app_path, bin_build_out_path, "media.bin"))
              d_addrs.append(hex(pt_parcel['media_addr'])[2:])
  
          if mfg == True:
              d_files.append(os.path.join(app_path, bin_build_out_path, "bootinfo_mfg.bin"))
              d_addrs.append(hex(pt_parcel['mfg_addr'])[2:])
              d_files.append(os.path.join(app_path, bin_build_out_path, "img_mfg.bin"))
              d_addrs.append(hex(pt_parcel['mfg_addr'] + 0x1000)[2:])
  
          if len(d_files) > 0 and len(d_addrs) > 0:
              cfg = BFConfigParser()
              cfg.read(eflash_loader_cfg)
              self.bl_write_flash_img(d_addrs, d_files, flash_opt)
              files_str = " ".join(d_files)
              addrs_str = " ".join(d_addrs)
              cfg.set('FLASH_CFG', 'file', files_str)
              cfg.set('FLASH_CFG', 'address', addrs_str)
              cfg.write(eflash_loader_cfg, 'w')
              return True
          else:
              return False
  
  class bl_img_ota():
      def bl_mfg_ota_header(self, file_bytearray, use_xz):
          ota_conf = bl_find_file("ota", ".toml")
          parsed_toml = toml.load(ota_conf)
          header_len = 512
          header = bytearray()
          file_len = len(file_bytearray)
          m = hashlib.sha256()
  
          # 16 Bytes header
          data = b'BL60X_OTA_Ver1.0'
          for b in data:
              header.append(b)
          # 4 Byte ota file type
          if use_xz:
              data = b'XZ  '
          else:
              data = b'RAW '
          for b in data:
              header.append(b)
  
          # 4 Bytes file length
          file_len_bytes = file_len.to_bytes(4, byteorder='little')
          for b in file_len_bytes:
              header.append(b)
  
          # 8 Bytes pad
          header.append(0x01)
          header.append(0x02)
          header.append(0x03)
          header.append(0x04)
          header.append(0x05)
          header.append(0x06)
          header.append(0x07)
          header.append(0x08)
  
          # 16 Bytes Hardware version
          data = bytearray(parsed_toml["ota"]["version_hardware"].encode())
          data_len = 16 - len(data)
          for b in data:
              header.append(b)
          while data_len > 0:
              header.append(0x00)
              data_len = data_len - 1
  
          # 16 Bytes firmware version
          data = bytearray(parsed_toml["ota"]["version_software"].encode())
          data_len = 16 - len(data)
          for b in data:
              header.append(b)
          while data_len > 0:
              header.append(0x00)
              data_len = data_len - 1
  
          # 32 Bytes SHA256
          m.update(file_bytearray)
          hash_bytes = m.digest()
          for b in hash_bytes:
              header.append(b)
          header_len = header_len - len(header)
          while header_len > 0:
              header.append(0xFF)
              header_len = header_len - 1
          return header
  
      def bl_mfg_ota_xz_gen(self, chipname="bl60x", chiptype="bl60x", cpu_type=None):
          bl60x_xz_filters = [
              {
                  "id": lzma.FILTER_LZMA2,
                  "dict_size": 32768
              },
          ]
  
          fw_ota_bin = bytearray()
          fw_ota_bin_xz = bytearray()
          if cpu_type == None:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/FW_OTA.bin".format(file_finally_name))
          else:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/".format(file_finally_name) + cpu_type + "_OTA.bin")
          with open(FW_OTA_path, mode="rb") as bin_f:
              file_bytes = bin_f.read()
              for b in file_bytes:
                  fw_ota_bin.append(b)
          if cpu_type == None:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/FW_OTA.bin.xz".format(file_finally_name))
          else:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/".format(file_finally_name) + cpu_type + "_OTA.bin.xz")
          with lzma.open(FW_OTA_path, mode="wb", check=lzma.CHECK_CRC32, filters=bl60x_xz_filters) as xz_f:
              xz_f.write(fw_ota_bin)
          print("Generating BIN File to %s" %(FW_OTA_path))
          with open(FW_OTA_path, mode="rb") as f:
              file_bytes = f.read()
              for b in file_bytes:
                  fw_ota_bin_xz.append(b)
          fw_ota_bin_xz_ota = self.bl_mfg_ota_header(fw_ota_bin_xz, use_xz=1)
          for b in fw_ota_bin_xz:
              fw_ota_bin_xz_ota.append(b)
          if cpu_type == None:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/FW_OTA.bin.xz.ota".format(file_finally_name))
          else:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/".format(file_finally_name) + cpu_type + "_OTA.bin.xz.ota")
          with open(FW_OTA_path, mode="wb") as f:
              f.write(fw_ota_bin_xz_ota)
          print("Generating BIN File to %s" %(FW_OTA_path))
  
  
      def bl_mfg_ota_bin_gen(self, chipname="bl60x", chiptype="bl60x", cpu_type=None):
          fw_header_len = 4096
          fw_ota_bin = bytearray()
  
          ota_path = os.path.join(app_path, bin_build_out_path)
          if os.path.isdir(ota_path)==False:
              os.mkdir(ota_path)
  
          if cpu_type == None:
              bootinfo_fw_path = os.path.join(app_path, bin_build_out_path, "bootinfo.bin")
          else:
              bootinfo_fw_path = os.path.join(app_path, bin_build_out_path, "bootinfo_" + cpu_type.lower() + ".bin")
          with open(bootinfo_fw_path, mode="rb") as f:
              file_bytes = f.read(4096)
              for b in file_bytes:
                  fw_ota_bin.append(b)
          i = fw_header_len - len(fw_ota_bin)
          while i > 0:
              fw_ota_bin.append(0xFF)
              i = i - 1
          if cpu_type == None:
              img_fw_path = os.path.join(app_path, bin_build_out_path, "img.bin")
          else:
              img_fw_path = os.path.join(app_path, bin_build_out_path, "img_" + cpu_type.lower() + ".bin")
          with open(img_fw_path, mode="rb") as f:
              file_bytes = f.read()
              for b in file_bytes:
                  fw_ota_bin.append(b)
          fw_ota_bin_header = self.bl_mfg_ota_header(fw_ota_bin, use_xz=0)
          
          FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota")
          if not os.path.exists(FW_OTA_path):
              os.makedirs(FW_OTA_path)
          FW_OTA_path = os.path.join(FW_OTA_path, file_finally_name)
          if not os.path.exists(FW_OTA_path):
              os.makedirs(FW_OTA_path)
          if cpu_type == None:
              FW_OTA_path = os.path.join(FW_OTA_path, "FW_OTA.bin")
          else:
              FW_OTA_path = os.path.join(FW_OTA_path, cpu_type + "_OTA.bin")
          with open(FW_OTA_path, mode="wb") as f:
              f.write(fw_ota_bin)
          print("Generating BIN File to %s" %(FW_OTA_path))
          for b in fw_ota_bin:
              fw_ota_bin_header.append(b)
          if cpu_type == None:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/FW_OTA.bin.ota".format(file_finally_name))
          else:
              FW_OTA_path = os.path.join(app_path, bin_build_out_path, "ota/{}/".format(file_finally_name) + cpu_type + "_OTA.bin.ota")
          with open(FW_OTA_path, mode="wb") as f:
              f.write(fw_ota_bin_header)
          print("Generating BIN File to %s" %(FW_OTA_path))
          self.bl_mfg_ota_xz_gen(chipname, chiptype, cpu_type)
  
  class bl_flash_select():
      def get_suitable_file_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:
              for i in range(len(conf_files)):
                  tmp = conf_files[i].split('.')[0]
                  print("%d:%s" % (i + 1, tmp))
              return conf_files[i]
          elif len(conf_files) == 1:
              return conf_files[0]
          else:
              return ""
  
      def update_flash_cfg_do(self, chipname, chiptype, flash_id, file=None, create=False, section=None):
          cfg_dir = os.path.join(os.getcwd(), chiptype, "flash_select")
          conf_name = self.get_suitable_file_name(cfg_dir, flash_id)
          print(os.path.join(cfg_dir, conf_name))
          value_key = []
          if os.path.isfile(os.path.join(cfg_dir, conf_name)) == False:
              return False
          fp = open(os.path.join(cfg_dir, conf_name), 'r')
          for line in fp.readlines():
              value = line.split("=")[0].strip()
              if value == "[FLASH_CFG]":
                  continue
              value_key.append(value)
  
          cfg1 = BFConfigParser()
          cfg1.read(os.path.join(cfg_dir, conf_name))
          cfg2 = BFConfigParser()
          cfg2.read(file)
          for i in range(len(value_key)):
              if cfg1.has_option("FLASH_CFG", value_key[i]) and cfg2.has_option(section, value_key[i]) :
                  tmp_value = cfg1.get("FLASH_CFG", value_key[i])
                  bflb_utils = bl_utils()
                  bflb_utils.Update_Cfg(cfg2, section, value_key[i], tmp_value)
  
          cfg2.write(file, "w+")
  
      def bl_flash_loader_list(self, chipname, chiptype, bh_cfg_file):
          eflash_loader_cfg = os.path.join(app_path, bin_build_out_path, "eflash_loader_cfg.ini")
          cfg = BFConfigParser()
          cfg.read(eflash_loader_cfg)
  
          if cfg.has_option("FLASH_CFG", "flash_id"):
              flash_id_str = cfg.get("FLASH_CFG", "flash_id")
              if type(flash_id_str) is str:
                  flash_id_list = flash_id_str.split(',')
                  return flash_id_list
              elif type(flash_id_str) is list:
                  return flash_id_str
              # for flash_id in flash_id_list:
              #     print("========= chip flash id: %s =========" % flash_id)
              #     if chiptype == "bl602":
              #         if self.update_flash_cfg_do(chipname, chiptype, flash_id, bh_cfg_file, False, "BOOTHEADER_CFG") == False:
              #             error = "flash_id:" + flash_id + " do not support"
              #             return error
              #     elif chiptype == "bl60x":
              #         if self.update_flash_cfg_do(chipname, chiptype, flash_id, bh_cfg_file, False, "BOOTHEADER_CPU0_CFG") == False:
              #             error = "flash_id:" + flash_id + " do not support"
              #             return error
          else:
              error = "Do not find flash_id in eflash_loader_cfg.ini"
              return error
  
      def bl_flash_update(self, chipname, chiptype, bh_cfg_file, flash_id):
          print("========= chip flash id: %s =========" % flash_id)
          if chiptype == "bl602":
              if self.update_flash_cfg_do(chipname, chiptype, flash_id, bh_cfg_file, False, "BOOTHEADER_CFG") == False:
                  error = "flash_id:" + flash_id + " do not support"
                  return error
          elif chiptype == "bl60x":
              if self.update_flash_cfg_do(chipname, chiptype, flash_id, bh_cfg_file, False,
                                          "BOOTHEADER_CPU0_CFG") == False:
                  error = "flash_id:" + flash_id + " do not support"
                  return error
  
      def bl_flash_loader(self, chipname, chiptype, bh_cfg_file):
          eflash_loader_cfg = os.path.join(app_path, bin_build_out_path, "eflash_loader_cfg.ini")
          cfg = BFConfigParser()
          cfg.read(eflash_loader_cfg)
          if cfg.has_option("FLASH_CFG", "flash_id"):
              flash_id_str = cfg.get("FLASH_CFG", "flash_id")
              flash_id_list = flash_id_str.split(',')
              print('++++++++')
              print(flash_id_list, type(flash_id_list))
              for flash_id in flash_id_list:
                  print(flash_id)
                  print("========= chip flash id: %s =========" % flash_id)
                  if chiptype == "bl602":
                      if self.update_flash_cfg_do(chipname, chiptype, flash_id, bh_cfg_file, False, "BOOTHEADER_CFG") == False:
                          error = "flash_id:" +  flash_id + " do not support"
                          return error
                  elif chiptype == "bl60x":
                      if self.update_flash_cfg_do(chipname, chiptype, flash_id, bh_cfg_file, False, "BOOTHEADER_CPU0_CFG") == False:
                          error = "flash_id:" +  flash_id + " do not support"
                          return error
          else:
              error = "Do not find flash_id in eflash_loader_cfg.ini"
              return error
  
  if __name__ == '__main__':
      abs_path = os.path.abspath('..')
      app_path = os.path.join(abs_path, "examples", sys.argv[1])
      demo_name = sys.argv[1]
      chip_name = sys.argv[2].lower()
      default_conf_path = chip_name
      eflash_loader_cfg_org = bl_find_file("eflash_loader_cfg", ".conf")
      eflash_loader_cfg = os.path.join(app_path, bin_build_out_path, "eflash_loader_cfg.ini")
      shutil.copy(eflash_loader_cfg_org, eflash_loader_cfg)
  
      # 找到efuse_bootheader_cfg
      f_org = bl_find_file("efuse_bootheader_cfg", ".conf")
      f = os.path.join(app_path, bin_build_out_path, "efuse_bootheader_cfg.ini")
      # if os.path.isfile(f) == False:
      shutil.copy(f_org, f)
      # 选择flash型号
      flash_sele = bl_flash_select()
  
      flashid_list = flash_sele.bl_flash_loader_list(chip_name, chip_name, f)
  
      pt_file_list = bl_find_file_list("partition_cfg_", ".toml")
      ro_list = bl_find_file_list(bl_factory_params_file_prefix, ".dts")
      img_boot2_file_list = bl_find_file_list("blsp_boot2_", ".bin")
  
      arrange_group_list = list(itertools.product(pt_file_list, ro_list, img_boot2_file_list, flashid_list))
  
      for group in arrange_group_list:
          # 找到partition
          # pt_file = bl_find_file("partition_cfg_", ".toml")
          pt_file = group[0]
          pt_name = pt_file.split("partition_cfg_")
          pt_name = pt_name[1].split('.toml')
          pt_name = 'pt{}'.format(pt_name[0])
  
          pt_helper = PtCreater(pt_file)
          pt_helper.create_pt_table(os.path.join(app_path, bin_build_out_path, "partition.bin"))
          pt_parcel = pt_helper.construct_table()
  
          # flashid
          flash_sele.bl_flash_update(chip_name, chip_name, f, group[3])
          flash_id_name = group[3]
  
          #找到device_tree
          # ro = bl_find_file(bl_factory_params_file_prefix, ".dts")
          ro = group[1]
          xtal = ro.split("IoTKitA_")
          xtal = xtal[1].split(".dts")
          xtal = xtal[0]
          dts_name = 'dts{}'.format(xtal)
  
          img_gen = bl_whole_img_generate()
          img_gen.bl_fw_boot_head_gen(True, xtal, f, False, chip_name, chip_name)
  
          #找到boot2
          # img_boot2_file = bl_find_file("blsp_boot2_", ".bin")
          img_boot2_file = group[2]
          boot2_name = img_boot2_file.split("blsp_boot2_")
          boot2_name = boot2_name[1].split('.bin')
          boot2_name = 'boot2{}'.format(boot2_name[0])
  
          file_finally_name = '{}_{}_{}_{}'.format(dts_name, pt_name, boot2_name, flash_id_name)
  
          img_gen.bl_image_gen("boot2", img_boot2_file)
  
          img_gen.bl_fw_boot_head_gen(False, xtal, f, False, chip_name, chip_name)
          img_gen.bl_image_gen("fw", os.path.join(app_path, "build_out", demo_name + ".bin"))
          img_ota = bl_img_ota()
          img_ota.bl_mfg_ota_bin_gen(chip_name, chip_name, None)
          img_gen.bl_whole_flash_bin_create(True, True, ro, pt_parcel, None, None, "2M")
  
  