mirror of
https://github.com/pine64/bl_iot_sdk.git
synced 2024-10-04 14:00:01 +00:00
3bc544d9f3
image_conf, make_scripts_riscv - Delete trailing spaces. Change tabs to 4 space multiples. .c and .h get tabs expanded to four spaces for consistency, traliing whitespace whacked. Makefiles do NOT get tabs changed.
1459 lines
57 KiB
Python
Executable File
1459 lines
57 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
# -*- 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, "customer_app", 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")
|
|
|