efuse: Add support coding scheme to script

Added support using BLK1 and BLK2 in custom table.
Added change size key in BLK1 and BLK2 if coding scheme was changed.
This commit is contained in:
Konstantin Kondrashov
2018-11-21 16:09:36 +08:00
committed by bot
parent 693a5c209b
commit 9822055851
9 changed files with 250 additions and 112 deletions

View File

@@ -30,6 +30,16 @@ import ntpath
__version__ = '1.0'
quiet = False
coding_scheme = 0
custom_table_use_BLK1 = False
custom_table_use_BLK2 = False
common_table_fix_size = False
CODE_SCHEME = {
"NONE" : 0,
"3/4" : 1,
"REPEAT" : 2,
}
copyright = '''// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
//
@@ -59,12 +69,11 @@ def critical(msg):
class FuseTable(list):
def __init__(self):
super(FuseTable, self).__init__(self)
self.md5_digest = ""
self.md5_digest_table = ""
@classmethod
def from_csv(cls, csv_contents):
def from_csv(cls, csv_contents, type_table):
res = FuseTable()
res.md5_digest = res.calc_md5(csv_contents)
lines = csv_contents.splitlines()
def expand_vars(f):
f = os.path.expandvars(f)
@@ -120,6 +129,16 @@ class FuseTable(list):
i_count = 0
res.verify_duplicate_name()
# fix size due to coding scheme
if type_table == "common_table":
if common_table_fix_size == True and (custom_table_use_BLK1 == False or custom_table_use_BLK2 == False):
res.fix_size_fields_from_blk1_blk2();
if custom_table_use_BLK1 == True or custom_table_use_BLK2 == True:
res.keys_from_blk1_blk2_make_empty();
# clac md5 for table
res.calc_md5()
return res
def verify_duplicate_name(self):
@@ -139,11 +158,9 @@ class FuseTable(list):
if fl_error == True:
raise InputError("Field names must be unique")
def verify(self):
'''list_field_names = []'''
def verify(self, type_table = None):
for p in self:
p.verify()
p.verify(type_table)
self.verify_duplicate_name()
@@ -156,8 +173,25 @@ class FuseTable(list):
last.field_name, last.efuse_block, last.bit_start, last.bit_count))
last = p
def calc_md5(self, csv_contents):
return hashlib.md5(csv_contents).hexdigest()
def fix_size_fields_from_blk1_blk2(self):
for p in self:
if (p.efuse_block == "EFUSE_BLK1" and custom_table_use_BLK1 == False) or (p.efuse_block == "EFUSE_BLK2" and custom_table_use_BLK2 == False):
max_bits = p.get_max_bits_of_block()
if p.bit_start == 0 and p.bit_count > max_bits:
print("Fix size `%s` field from %d to %d" %(p.field_name, p.bit_count, max_bits))
p.bit_count = max_bits
def keys_from_blk1_blk2_make_empty(self):
for p in self:
if (p.efuse_block == "EFUSE_BLK1" and custom_table_use_BLK1 == True) or (p.efuse_block == "EFUSE_BLK2" and custom_table_use_BLK2 == True):
p.bit_count = 0
print("efuse: `%s` field was changed from %d to 0" %(p.field_name, p.bit_count))
def calc_md5(self):
txt_table = ''
for p in self:
txt_table += "%s %s %d %d %s" % (p.field_name, p.efuse_block, p.bit_start, p.bit_count, p.comment) + "\n"
self.md5_digest_table = hashlib.md5(txt_table).hexdigest()
def show_range_used_bits(self):
# print used and free bits
@@ -190,7 +224,7 @@ class FuseTable(list):
"#endif",
"",
"",
"// md5_digest " + self.md5_digest,
"// md5_digest_table " + self.md5_digest_table,
"// This file was generated automatically from the file " + file_name + ".csv. DO NOT CHANGE THIS FILE MANUALLY.",
"// If you want to change some fields, you need to change " + file_name + ".csv file then build system will generate this header file",
"// To show efuse_table run the command 'make show_efuse_table'.",
@@ -215,7 +249,7 @@ class FuseTable(list):
rows += [ '#include "esp_efuse.h"',
'#include "' + file_name + '.h"',
"",
"// md5_digest " + self.md5_digest,
"// md5_digest_table " + self.md5_digest_table,
"// This file was generated automatically from the file " + file_name + ".csv. DO NOT CHANGE THIS FILE MANUALLY.",
"// If you want to change some fields, you need to change " + file_name + ".csv file then build system will generate this header file",
"// To show efuse_table run the command 'make show_efuse_table'.",
@@ -293,18 +327,36 @@ class FuseDefinition(object):
raise InputError("Field 'efuse_block' should consist from EFUSE_BLK0..EFUSE_BLK3")
return strval
def verify(self):
'''if self.field_name is None:
raise ValidationError(self, "field_name field is not set")'''
def get_max_bits_of_block(self):
'''common_table: EFUSE_BLK0, EFUSE_BLK1, EFUSE_BLK2, EFUSE_BLK3
custom_table: ----------, ----------, ----------, EFUSE_BLK3(some reserved in common_table)
'''
max_bits = 0
if coding_scheme == CODE_SCHEME["NONE"] or self.efuse_block == "EFUSE_BLK0":
max_bits = 256
elif coding_scheme == CODE_SCHEME["3/4"]:
max_bits = 192
elif coding_scheme == CODE_SCHEME["REPEAT"]:
max_bits = 128
else:
ValidationError(self, "Unknown coding scheme")
return max_bits
def verify(self, type_table):
if self.efuse_block is None:
raise ValidationError(self, "efuse_block field is not set")
if self.bit_count is None:
raise ValidationError(self, "bit_count field is not set")
max_bits = 256
if self.efuse_block == "EFUSE_BLK0":
max_bits = 224
if type_table is not None:
if type_table == "custom_table":
if self.efuse_block != "EFUSE_BLK3":
ValidationError(self, "custom_table should use only EFUSE_BLK3")
max_bits = self.get_max_bits_of_block()
if self.bit_start + self.bit_count > max_bits:
print("(%d + %d) > %d" % (self.bit_start, self.bit_count, max_bits))
raise ValidationError(self, "The field is outside the boundaries of the %s block" % (self.efuse_block))
def get_full_name(self):
@@ -324,15 +376,26 @@ class FuseDefinition(object):
str(self.bit_start),
str(self.bit_count) + "}, \t // " + self.comment])
def process_input_file(file):
def process_input_file(file, type_table):
status("Parsing efuse CSV input file " + file.name + " ...")
input = file.read()
table = FuseTable.from_csv(input)
table = FuseTable.from_csv(input, type_table)
status("Verifying efuse table...")
table.verify()
table.verify(type_table)
return table
def ckeck_md5_in_file(md5, filename):
if os.path.exists(filename):
with open(filename,'r') as f:
for line in f:
if md5 in line:
return True
return False
def touch(fname, times=None):
with open(fname, 'a'):
os.utime(fname, times)
def create_output_files(name, output_table, debug):
file_name = os.path.splitext(os.path.basename(name))[0]
gen_dir = os.path.dirname(name)
@@ -346,55 +409,74 @@ def create_output_files(name, output_table, debug):
file_h_path = os.path.join(dir_for_file_h, file_name + ".h")
file_c_path = os.path.join(gen_dir, file_name + ".c")
status("Creating efuse *.h file " + file_h_path + " ...")
output = output_table.to_header(file_name)
with open(file_h_path, 'w') as f:
f.write(output)
f.close()
status("Creating efuse *.c file " + file_c_path + " ...")
output = output_table.to_c_file(file_name, debug)
with open(file_c_path, 'w') as f:
f.write(output)
f.close()
# src files are the same
if ckeck_md5_in_file(output_table.md5_digest_table, file_c_path) == False:
status("Creating efuse *.h file " + file_h_path + " ...")
output = output_table.to_header(file_name)
with open(file_h_path, 'w') as f:
f.write(output)
f.close()
status("Creating efuse *.c file " + file_c_path + " ...")
output = output_table.to_c_file(file_name, debug)
with open(file_c_path, 'w') as f:
f.write(output)
f.close()
else:
print("touch: %s.c" % (file_name))
touch(file_c_path)
def main():
global quiet
global coding_scheme
global custom_table_use_BLK1
global custom_table_use_BLK2
global common_table_fix_size
parser = argparse.ArgumentParser(description='ESP32 eFuse Manager')
parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true')
parser.add_argument('--debug', help='Create header file with debug info', default=False, action="store_false")
parser.add_argument('--info', help='Print info about range of used bits', default=False, action="store_true")
parser.add_argument('--custom_table_use_BLK1', help='BLK1 is used for custom purpose', default=False, action="store_true")
parser.add_argument('--custom_table_use_BLK2', help='BLK2 is used for custom purpose', default=False, action="store_true")
parser.add_argument('--common_table_fix_size_secure_key_and_encrypt_key', help='Size of secure_key and encrypt_key will limit to coding scheme', default=False, action="store_true")
parser.add_argument('--coding_scheme', help='Coding scheme', type=int, default=None)
parser.add_argument('common_input', help='Path to common CSV file to parse.', type=argparse.FileType('rb'))
parser.add_argument('custom_input', help='Path to custom CSV file to parse.', type=argparse.FileType('rb'), nargs='?', default=None)
args = parser.parse_args()
coding_scheme = args.coding_scheme
if CODE_SCHEME["NONE"] == coding_scheme:
print("eFuse coding scheme: NONE")
elif CODE_SCHEME["3/4"] == coding_scheme:
print("eFuse coding scheme: 3/4")
elif CODE_SCHEME["REPEAT"] == coding_scheme:
print("eFuse coding scheme: REPEAT")
custom_table_use_BLK1 = args.custom_table_use_BLK1
custom_table_use_BLK2 = args.custom_table_use_BLK2
common_table_fix_size = args.common_table_fix_size_secure_key_and_encrypt_key
quiet = args.quiet
debug = args.debug
info = args.info
common_table = process_input_file(args.common_input)
common_table = process_input_file(args.common_input, "common_table")
two_table = common_table
if args.custom_input is not None:
custom_table = process_input_file(args.custom_input)
common_table += custom_table
common_table.verify()
if info == True:
output_table = common_table
else:
output_table = custom_table
name = args.custom_input.name
else:
output_table = common_table
name = args.common_input.name
output_table.verify()
custom_table = process_input_file(args.custom_input, "custom_table")
two_table += custom_table
two_table.verify()
# save files.
if info == False:
create_output_files(name, output_table, debug)
if args.custom_input is None:
create_output_files(args.common_input.name, common_table, debug)
else:
create_output_files(args.custom_input.name, custom_table, debug)
else:
print(output_table.show_range_used_bits())
print(two_table.show_range_used_bits())
return 0