| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872 |
- import binascii
- import os.path
- import sys
- from xml.dom import minidom
- import argparse
- import re
- import base64
- import subprocess
- import os
- import hashlib
- import logging
- log_file_path = ""
- def convert_to_int_value(val, tag_name, attr_name=None) :
- if (val == "") or (val == 0) or (val == "0") :
- return 0
- if (val == 1) or (val == "1") :
- return 1
- if isinstance(val, basestring) : #check if "val" is string type (only string has lower() method)
- if val.lower() == "true" :
- return 1
- if val.lower() == "false" :
- return 0
- if attr_name : #has Atribute
- PrintError_RaiseException_StopBuild("Attribute Name: " + attr_name + " => I got value: \"" + str(val) + "\". The value should be: \"1\" or \"0\" or \"true\" or \"false\" or empty(=false)")
- else :
- PrintError_RaiseException_StopBuild("Tag Name: " + tag_name + " => I got value: \"" + str(val) + "\". The value should be: \"1\" or \"0\" or \"true\" or \"false\" or empty(=false)")
- def isReverseEndianEnabled(val) :
- if isinstance(val, basestring) : #check if "val" is string type (only string has lower() method)
- if val.lower() == "true" :
- return True
- if val.lower() == "false" :
- return False
- PrintError_RaiseException_StopBuild("[definition] \"reverse_endian\" should be in value \"true\" or \"false\".")
- else :
- PrintError_RaiseException_StopBuild("[definition] \"reverse_endian\" should be in String(\"true\" or \"false\") format.")
- def reverseEndian(val, enableReverse=False) :
- if enableReverse :
- if not isinstance(val, basestring) :
- PrintError_RaiseException_StopBuild("The type of input value of \"reverseEndian\" should be String")
- if (len(val) == 4) :
- return val[2:4] + val[0:2]
- elif (len(val) == 8) :
- return val[6:8] + val[4:6] + val[2:4] + val[0:2]
- else :
- return val
- PrintError_RaiseException_StopBuild("The input value of \"reverseEndian\" should be the multiply of 4")
- def writeBitValueAndOneHexStringToFile(fstream, lstBitValue, hexString) :
- """
- Notice: The priority of bit input(lstBitValue) is higher than hex input(hexString) if hexString overlaps lstBitValue
- """
- result = 0;
- priority_mask = 0xFFFFFFFF
- for bit_number, value in lstBitValue :
- if value == 1 :
- result = result + (2 ** bit_number) #transform bit to decimal
- priority_mask = priority_mask & ~(2 ** bit_number)
- hexString2Decimal = int(hexString, 16) #transform hex to decimal
- result = (hexString2Decimal & priority_mask) | result #merge
- plain_hex_string = str(hex(result))[2:] #result is decimal, transform to hex
- plain_hex_string = plain_hex_string.zfill(8) #padding 0 at right to 8 digits
- lstHexArr = re.findall('..', plain_hex_string)
- fstream.write(chr(int(lstHexArr[3], 16)))
- fstream.write(chr(int(lstHexArr[2], 16)))
- fstream.write(chr(int(lstHexArr[1], 16)))
- fstream.write(chr(int(lstHexArr[0], 16)))
- def getBitValueAndOneHexString(lstBitValue, hexString) :
- """
- Notice: The priority of bit input(lstBitValue) is higher than hex input(hexString) if hexString overlaps lstBitValue
- This function is the same as function "writeBitValueAndOneHexStringToFile" except it return the merged value rather than writing to file
- """
- result = 0;
- priority_mask = 0xFFFFFFFF
- for bit_number, value in lstBitValue :
- if value == 1 :
- result = result + (2 ** bit_number) #transform bit to decimal
- priority_mask = priority_mask & ~(2 ** bit_number)
- hexString2Decimal = int(hexString, 16) #transform hex to decimal
- result = (hexString2Decimal & priority_mask) | result #merge
- plain_hex_string = str(hex(result))[2:] #result is decimal, transform to hex
- plain_hex_string = plain_hex_string.zfill(len(hexString)) #padding 0 at right to 8 digits
- return plain_hex_string.upper()
- def writeBitValueToFile(fstream, lstBitValue) :
- result = 0;
- for bit_number, value in lstBitValue :
- if value == 1 :
- result = result + (2 ** bit_number)
- plain_hex_string = str(hex(result))[2:] #result is decimal
- plain_hex_string = plain_hex_string.zfill(8)
- lstHexArr = re.findall('..', plain_hex_string)
- fstream.write(chr(int(lstHexArr[3], 16)))
- fstream.write(chr(int(lstHexArr[2], 16)))
- fstream.write(chr(int(lstHexArr[1], 16)))
- fstream.write(chr(int(lstHexArr[0], 16)))
- def get_file_sha256hexdigest(file_name):
- hash_result = ""
- with open(file_name) as f:
- m = hashlib.sha256()
- m.update(f.read())
- hash_result = m.hexdigest()
- return hash_result.upper()
- def writeHexStringToFile(fstream, hexString) :
- plain_hex_string = hexString.ljust(8, '0') #padding 0 at right to 8 digits
- lstHexArr = re.findall('..', plain_hex_string)
- fstream.write(chr(int(lstHexArr[0], 16)))
- fstream.write(chr(int(lstHexArr[1], 16)))
- fstream.write(chr(int(lstHexArr[2], 16)))
- fstream.write(chr(int(lstHexArr[3], 16)))
- def checkLessThan32BitsHexStringLength(tag_name, hexString, min_index, max_index, attribute_name="") :
- if (max_index <= min_index) :
- PrintError_RaiseException_StopBuild("[Coding Error] Maximum index should be bigger than minimum index!")
- plain_hex_string = hexString.ljust(8, '0') #padding 0 at right to 8 digits
- lstHexArr = re.findall('..', plain_hex_string)
- result = 0;
- mask = 0xFFFFFFFF
- for bit_number in range(0, 32) :
- if (min_index <= bit_number <= max_index) :
- mask = mask & ~(2 ** bit_number)
- input_length_mask = int(lstHexArr[3] + lstHexArr[2] + lstHexArr[1] + lstHexArr[0], 16)
- forbidden_field_mask = mask
- # print(hex(input_length_mask))
- # print(hex(forbidden_field_mask))
- if (input_length_mask & forbidden_field_mask) != 0 :
- if attribute_name == "" :
- PrintError_RaiseException_StopBuild("Tag Name: " + tag_name + " (Wrong value length. The length of value should be \"" + tag_name + "[" + str(max_index) + ":" + str(min_index) + "]\")")
- else :
- PrintError_RaiseException_StopBuild("Tag Name: " + tag_name + " (Wrong value length. The length of value should be \"" + attribute_name + "[" + str(max_index) + ":" + str(min_index) + "]\")")
- def parseXmlTagAndAttribute(xml_file, tag_name, attr_name, inputValueLengthLimit=1, inputIsStringType=False) :
- if inputIsStringType :
- retVal = '0' * inputValueLengthLimit
- else :
- retVal = 0
- try:
- if not xml_file.getElementsByTagName(tag_name) :
- raise KeyError
- tag_number = len(xml_file.getElementsByTagName(tag_name))
- if tag_number > 1 :
- raise ValueError("Duplicated tag name. It appears " + str(tag_number) + " times!!")
- tmp_parse_value = xml_file.getElementsByTagName(tag_name)[0].attributes[attr_name].value
- if inputIsStringType :
- if (tmp_parse_value == "") :
- return retVal
- if (inputValueLengthLimit <> len(tmp_parse_value)) :
- raise ValueError("Wrong value length. The length of value should be: " + str(inputValueLengthLimit))
- if isinstance(tmp_parse_value, basestring) : #check if "tmp_parse_value" is string type (only string has upper() method)
- if not isValidHexString(tmp_parse_value) : #only string can be processed by regex
- raise ValueError("Wrong hex value type! The value should be within [0-9|A-F]")
- return tmp_parse_value.upper()
- return tmp_parse_value
- else : #not string
- return convert_to_int_value(tmp_parse_value, tag_name, attr_name)
- except IndexError:
- #Tag or Attribute not exist
- #printAndLog("[Warning][Not Exist] Tag Name: " + tag_name + ", Attribute Name: " + attr_name + " => Set to default value: " + str(retVal))
- return retVal
- except KeyError:
- #Tag or Attribute not exist
- #printAndLog("[Warning][Not Exist] Tag Name: " + tag_name + ", Attribute Name: " + attr_name + " => Set to default value: " + str(retVal))
- return retVal
- except ValueError as err:
- PrintError_RaiseException_StopBuild("Tag Name: " + tag_name + ", Attribute Name: " + attr_name + " (" + str(err) + ")")
- def parseXmlTagInnerValue(xml_file, tag_name, inputValueLengthLimit=1, inputIsStringType=False) :
- if inputIsStringType :
- retVal = '0' * inputValueLengthLimit
- else :
- retVal = 0
- try:
- if not xml_file.getElementsByTagName(tag_name) :
- raise KeyError
- tag_number = len(xml_file.getElementsByTagName(tag_name))
- if tag_number > 1 :
- raise ValueError("Duplicated tag name. It appears " + str(tag_number) + " times!!")
- tmp_parse_value = xml_file.getElementsByTagName(tag_name)[0].childNodes[0].data
- if inputIsStringType :
- if (tmp_parse_value == "") :
- return retVal
- if (inputValueLengthLimit <> len(tmp_parse_value)) :
- raise ValueError("Wrong value length. The length of value should be: " + str(inputValueLengthLimit))
- if isinstance(tmp_parse_value, basestring) : #check if "tmp_parse_value" is string type (only string has upper() method)
- if not isValidHexString(tmp_parse_value) : #only string can be processed by regex
- raise ValueError("Wrong hex value type! The value should be within [0-9|A-F]")
- return tmp_parse_value.upper()
- return tmp_parse_value
- else : #not string
- return convert_to_int_value(tmp_parse_value, tag_name)
- except IndexError:
- #Tag or Attribute not exist
- #printAndLog("[Warning][Not Exist] Tag Name: " + tag_name + " => Set to default value: " + str(retVal))
- return retVal
- except KeyError:
- #Tag or Attribute not exist
- #printAndLog("[Warning][Not Exist] Tag Name: " + tag_name + " => Set to default value: " + str(retVal))
- return retVal
- except ValueError as err:
- PrintError_RaiseException_StopBuild("Tag Name: " + tag_name + " (" + str(err) + ")")
- def isValidHexString(hex_input) :
- if re.match(r"^[0-9A-F]*$", hex_input, re.IGNORECASE) :
- return True
- return False
- def isValidNumberString(number_input) :
- if re.match(r"^[0-9]*$", number_input, re.IGNORECASE) :
- return True
- return False
- def isValidRegisterLengthString(number_input) :
- if re.match(r"^[0-9]*$", number_input, re.IGNORECASE) :
- if 1 <= int(number_input) <= 32 :
- return True
- return False
- def isValidRegisterIndexString(index_input) :
- if re.match(r"^[0-9]*$", index_input, re.IGNORECASE) :
- if 0 <= int(index_input) <= 31 :
- return True
- return False
- def printAndLog(msg, criticalLevel=False):
- print(msg)
- global log_file_path
- if (log_file_path) :
- logging.basicConfig(format='[%(asctime)s] %(message)s', filename=log_file_path, level=logging.DEBUG)
- if criticalLevel :
- logging.critical(msg)
- else :
- logging.info(msg)
- def PrintError_RaiseException_StopBuild(err) :
- printAndLog("[Error] " + err, criticalLevel=True)
- raise Exception("[Error] " + err)
- def main():
- WRITE_TYPE_BIT = 1
- WRITE_TYPE_STRING = 2
- WRITE_TYPE_BIT_AND_STRING = 3
- parser = argparse.ArgumentParser(description='MediaTek EFUSE XML Parser')
- parser.add_argument('--file', '-f',
- required=True,
- help='Provide the EFUSE blowing xml file')
- parser.add_argument('--definition_file', '-d',
- required=True,
- help='Provide the EFUSE definition file')
- parser.add_argument('--output_bin_name', '-o',
- required=False,
- default='xml_output.bin',
- help='Provide output file name')
- parser.add_argument('--key_hash', '-k',
- required=False,
- help='Provide the file name path of key hash')
- parser.add_argument('--log_output_file', '-l',
- required=False,
- help='Provide the log output file name')
- args = parser.parse_args()
- if (args.log_output_file) :
- if os.path.isfile(args.log_output_file) :
- try :
- os.remove(args.log_output_file)
- except :
- pass
- global log_file_path
- log_file_path = args.log_output_file
- printAndLog("***************************************************************************")
- printAndLog("**************** MediaTek EFUSE XML Parser ([MTK_XML2BIN]) ****************")
- printAndLog("****************************** version 2.0.2 ******************************")
- printAndLog("***************************************************************************")
- printAndLog("Loading XML file: " + os.path.abspath(args.file))
- if os.path.isfile(args.output_bin_name) :
- os.remove(args.output_bin_name)
- printAndLog("Remove old image file: " + os.path.abspath(args.output_bin_name))
- printAndLog("-----------------------------------------------")
- if not os.path.isfile(args.file) :
- PrintError_RaiseException_StopBuild("XML file not exist!!")
- if not os.path.isfile(args.definition_file) :
- PrintError_RaiseException_StopBuild("EFUSE definition file not exist!!")
- try :
- xml_file = minidom.parse(args.file)
- except Exception:
- printAndLog("[Error] ***** XML format is NOT CORRECT. Please check your XML input file. *****")
- printAndLog("[Error] ***** XML format is NOT CORRECT. Please check your XML input file. *****")
- PrintError_RaiseException_StopBuild("***** XML format is NOT CORRECT. Please check your XML input file. *****")
- try :
- definition_file = minidom.parse(args.definition_file)
- except Exception:
- printAndLog("[Error] ***** EFUSE Definition XML format is NOT CORRECT. Please check your XML input file. *****")
- printAndLog("[Error] ***** EFUSE Definition XML format is NOT CORRECT. Please check your XML input file. *****")
- PrintError_RaiseException_StopBuild("***** EFUSE Definition XML format is NOT CORRECT. Please check your XML input file. *****")
- efuse_writer_tag = definition_file.getElementsByTagName("efuse_writer")[0]
- if len(definition_file.getElementsByTagName("efuse_writer")) > 1 :
- PrintError_RaiseException_StopBuild("[definitions] Should only have one \"efuse_writer\" tag.")
- efuse_writer_chip = efuse_writer_tag.getAttribute("chip").strip()
- if (efuse_writer_chip == "") :
- PrintError_RaiseException_StopBuild("[definitions] chip name should not be empty in definition file.")
- printAndLog("Definition Target Platform: " + efuse_writer_chip)
- efuse_writer_output_binary_size = efuse_writer_tag.getAttribute("output_bin_size").strip()
- if (efuse_writer_output_binary_size == "") :
- PrintError_RaiseException_StopBuild("[definitions] output_bin_size should not be empty in definition file.")
- if not isValidNumberString(efuse_writer_output_binary_size) :
- PrintError_RaiseException_StopBuild("[definitions] output_bin_size is not a valid number.")
- try :
- MAX_OUTPUT_OFFSET_DECIMAL = int(efuse_writer_output_binary_size) - 32
- except ValueError :
- PrintError_RaiseException_StopBuild("[definitions] " + efuse_writer_output_binary_size + " is not a valid type of number.")
- printAndLog("Definition Expected Output Binary Size: " + efuse_writer_output_binary_size + " bytes")
- #Parsing XML to variable
- printAndLog("Parsing XML file ...")
- dict_definition_inner_value = {}
- dict_definition_inner_text = {}
- dict_definition_boolean = {}
- dict_definition_external = {}
- printAndLog("-----------------------------------------------")
- if not definition_file.getElementsByTagName("definitions") :
- PrintError_RaiseException_StopBuild("[definitions] No \"definitions\" tag found in EFUSE definition file.")
- if len(definition_file.getElementsByTagName("definitions")) > 1 :
- PrintError_RaiseException_StopBuild("[definitions] Should only have one \"definitions\" tag.")
- definition_alllist = definition_file.getElementsByTagName("definitions")[0]
- definition_inner_value_list = definition_alllist.getElementsByTagName("inner_value")
- definition_inner_text_list = definition_alllist.getElementsByTagName("inner_text")
- definition_boolean_list = definition_alllist.getElementsByTagName("boolean")
- definition_merge_inner_text_and_value_list = definition_inner_value_list + definition_inner_text_list
- for tag in definition_merge_inner_text_and_value_list :
- tag_type = tag.tagName
- tag_name = tag.getAttribute("tag").strip()
- tag_attribute = ""
- if tag_name == "" :
- PrintError_RaiseException_StopBuild("[definitions] Type: " + tag_type + ", \"tag\" value should not be null.")
- if tag_type == "inner_value" :
- tag_attribute = tag.getAttribute("attribute").strip()
- if tag_attribute == "" :
- PrintError_RaiseException_StopBuild("[definitions] Type: " + tag_type + ", \"attribute\" value should not be null.")
- suppress_log = tag.getElementsByTagName("suppress_log")
- log_display = True
- if suppress_log :
- log_display = False
- if tag_type == "inner_value" :
- prepared_error_msg = "Type: " + tag_type + " => tag: " + tag_name + ", attribute: " + tag_attribute
- if tag_name not in dict_definition_inner_value :
- dict_definition_inner_value[tag_name] = {}
- if tag_attribute in dict_definition_inner_value[tag_name] :
- PrintError_RaiseException_StopBuild("[definitions] Duplicated attribute name for the same tag name. (" + prepared_error_msg + ")")
- else : # tag_type == "inner_text"
- prepared_error_msg = "Type: " + tag_type + " => tag: " + tag_name
- if tag_name in dict_definition_inner_text :
- PrintError_RaiseException_StopBuild("[definitions] Duplicated tag name. (" + prepared_error_msg + ")")
- require_conditions = tag.getElementsByTagName("require")
- dict_tmp_require_conditions = {"length": None,
- "valid_start_bit": None,
- "valid_end_bit": None}
- for condition in require_conditions :
- for condition_name in dict_tmp_require_conditions :
- tmp_condition_value = condition.getAttribute(condition_name).strip()
- if (tmp_condition_value != "") :
- if (dict_tmp_require_conditions[condition_name] is not None) :
- PrintError_RaiseException_StopBuild("[definitions] Duplicated \"" + condition_name + "\" declaration. (" + prepared_error_msg + ")")
- dict_tmp_require_conditions[condition_name] = tmp_condition_value
- if dict_tmp_require_conditions["length"] == None :
- PrintError_RaiseException_StopBuild("[definitions] Length is required. (" + prepared_error_msg + ")")
- #value check and transform string to integer
- if not isValidRegisterLengthString(dict_tmp_require_conditions["length"]) :
- PrintError_RaiseException_StopBuild("[definitions] Length is not a valid number(should be 1-32). (" + prepared_error_msg + ")")
- dict_tmp_require_conditions["length"] = int(dict_tmp_require_conditions["length"])
- if tag_type == "inner_value" :
- tag_value = parseXmlTagAndAttribute(xml_file, tag_name, tag_attribute, dict_tmp_require_conditions["length"], True)
- else : # tag_type == "inner_text"
- tag_value = parseXmlTagInnerValue(xml_file, tag_name, dict_tmp_require_conditions["length"], True)
- if (dict_tmp_require_conditions["valid_start_bit"] != None) or (dict_tmp_require_conditions["valid_end_bit"] != None) :
- if (dict_tmp_require_conditions["valid_start_bit"] == None) or (dict_tmp_require_conditions["valid_end_bit"] == None) :
- PrintError_RaiseException_StopBuild("[definitions] valid_start_bit and valid_end_bit should appear at the same time or not. (" + prepared_error_msg + ")")
- #value check and transform string to integer
- if (not isValidRegisterIndexString(dict_tmp_require_conditions["valid_start_bit"])) :
- PrintError_RaiseException_StopBuild("[definitions] valid_start_bit is not a valid index(should be 0-31). (" + prepared_error_msg + ")")
- if (not isValidRegisterIndexString(dict_tmp_require_conditions["valid_end_bit"])) :
- PrintError_RaiseException_StopBuild("[definitions] valid_end_bit is not a valid index(should be 0-31). (" + prepared_error_msg + ")")
- dict_tmp_require_conditions["valid_start_bit"] = int(dict_tmp_require_conditions["valid_start_bit"])
- dict_tmp_require_conditions["valid_end_bit"] = int(dict_tmp_require_conditions["valid_end_bit"])
- checkLessThan32BitsHexStringLength(tag_name, tag_value, dict_tmp_require_conditions["valid_start_bit"], dict_tmp_require_conditions["valid_end_bit"], tag_attribute);
- if tag_type == "inner_value" :
- dict_definition_inner_value[tag_name][tag_attribute] = tag_value
- else : # tag_type == "inner_text"
- dict_definition_inner_text[tag_name] = tag_value
- if log_display :
- printAndLog("EFUSE_" + tag_name + " = " + tag_value)
- #print(dict_definition_inner_text)
- #print(dict_definition_inner_value)
- for tag in definition_boolean_list :
- tag_name = tag.getAttribute("tag").strip()
- tag_attribute = tag.getAttribute("attribute").strip()
- if (tag_name == "") or (tag_attribute == "") :
- PrintError_RaiseException_StopBuild("[definitions] boolean type, tag or attribute value should not be null.")
- suppress_log = tag.getElementsByTagName("suppress_log")
- log_display = True
- if suppress_log :
- log_display = False
- if tag_name not in dict_definition_boolean :
- dict_definition_boolean[tag_name] = {}
- if tag_attribute in dict_definition_boolean[tag_name] :
- PrintError_RaiseException_StopBuild("[definitions] Duplicated attribute name. (boolean type, tag: " + tag_name + ", attribute: " + tag_attribute + ")")
- tag_value = parseXmlTagAndAttribute(xml_file, tag_name, tag_attribute)
- dict_definition_boolean[tag_name][tag_attribute] = tag_value
- if log_display :
- printAndLog("EFUSE_" + tag_attribute + " = " + str(tag_value))
- #print(dict_definition_boolean)
- printAndLog("-----------------------------------------------")
- EFUSE_SBC_PUBK_HASH = '0' * 64
- if args.key_hash :
- printAndLog("[Info] Loading SBC_PUBK_HASH from key hash file: " + os.path.abspath(args.key_hash))
- if os.path.isfile(args.key_hash) :
- try:
- with open(args.key_hash, 'r') as f:
- EFUSE_SBC_PUBK_HASH = f.read()
- except Exception:
- PrintError_RaiseException_StopBuild("***** Error while reading key hash file *****")
- EFUSE_SBC_PUBK_HASH = EFUSE_SBC_PUBK_HASH.strip()
- if EFUSE_SBC_PUBK_HASH == "" :
- PrintError_RaiseException_StopBuild("SBC_PUBK_HASH is empty and not generated")
- if len(EFUSE_SBC_PUBK_HASH) <> 64 :
- PrintError_RaiseException_StopBuild("SBC_PUBK_HASH is not in length 64. Current length of SBC_PUBK_HASH is: " + str(len(EFUSE_SBC_PUBK_HASH)))
- EFUSE_SBC_PUBK_HASH = EFUSE_SBC_PUBK_HASH.upper()
- if not isValidHexString(EFUSE_SBC_PUBK_HASH) :
- PrintError_RaiseException_StopBuild("SBC_PUBK_HASH contains invalid hex string(s)! The value should be within [0-9|A-F]")
- else :
- PrintError_RaiseException_StopBuild(args.key_hash + " is not generated from getKeyHash.sh for SBC_Key_Hash!!")
- else :
- printAndLog("[Info] SBC_PUBK_HASH is not loaded from key hash file.")
- EFUSE_SBC_PUBK_HASH = '0' * 64
- dict_definition_external["SBC_PUBK_HASH"] = EFUSE_SBC_PUBK_HASH
- printAndLog("EFUSE_SBC_PUBK_HASH = " + EFUSE_SBC_PUBK_HASH)
- printAndLog("-----------------------------------------------")
- dict_definition_output = {}
- lst_supported_output_type = ["inner_value", "inner_text", "external", "boolean", "mix_type"]
- lst_supported_output_mix_type = ["inner_value", "inner_text", "external", "boolean"]
- if not definition_file.getElementsByTagName("blow_list") :
- PrintError_RaiseException_StopBuild("[definitions] No \"blow_list\" tag found in EFUSE definition file.")
- if len(definition_file.getElementsByTagName("blow_list")) > 1 :
- PrintError_RaiseException_StopBuild("[definitions] Should only have one \"blow_list\" tag.")
- definition_blow_list = definition_file.getElementsByTagName("blow_list")[0]
- definition_blow_efuse_items = definition_blow_list.getElementsByTagName("efuse")
- for tag in definition_blow_efuse_items :
- tag_type = tag.getAttribute("type").strip()
- tag_offset = tag.getAttribute("offset").strip()
- offset_int_decimal = 0
- if (tag_offset == "") :
- PrintError_RaiseException_StopBuild("[definitions] \"efuse\" tag => \"tag_offset\" should not be null.")
- if (tag_type == "") :
- PrintError_RaiseException_StopBuild("[definitions] \"efuse\" tag => \"tag_type\" should not be null.")
- if tag_type not in lst_supported_output_type :
- PrintError_RaiseException_StopBuild("[definitions] Output type \"" + tag_type + "\" is not supported.")
- try :
- offset_int_decimal = int(tag_offset, 16)
- if (offset_int_decimal % 4) != 0 :
- PrintError_RaiseException_StopBuild("[definitions] offset \"" + tag_offset + "\" should be 4bytes align.")
- except ValueError :
- PrintError_RaiseException_StopBuild("[definitions] offset \"" + tag_offset + "\" is not a valid hex.")
- if offset_int_decimal in dict_definition_output :
- PrintError_RaiseException_StopBuild("[definitions] offset \"" + tag_offset + "\" is duplicated.")
- if (offset_int_decimal >= MAX_OUTPUT_OFFSET_DECIMAL) :
- PrintError_RaiseException_StopBuild("[definitions] Since the biggest size of output binary file is 512 bytes, the offset \"" + str(offset_int_decimal) + "\" in decimal should not exceeds " + str(MAX_OUTPUT_OFFSET_DECIMAL) + ".")
- dict_definition_output[offset_int_decimal] = {}
- input_data_items = tag.getElementsByTagName("input")
- #value checking
- if input_data_items.length == 0 :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => No input declaration")
- if (tag_type not in ["mix_type", "boolean"]) :
- if input_data_items.length > 1 :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => This type only allows one declaration")
- if (tag_type == "mix_type") :
- dict_definition_output[offset_int_decimal]["write_data"] = "" #set the default empty string value because it will append the string for this kind of type
- tmp_dict_input_bit_duplicated_counter = {}
- for input_field in input_data_items :
- dict_tmp_input_fields = {"key": None,
- "tag": None,
- "attribute": None,
- "bit": None,
- "start_index": None,
- "end_index": None,
- "reverse_endian": None,
- "type": None}
- for attribute_name_in_input_tag in input_field.attributes.keys() : #loop attribute and attribute value
- if (attribute_name_in_input_tag != "") :
- attribute_value_in_input_tag = input_field.getAttribute(attribute_name_in_input_tag).strip()
- if attribute_name_in_input_tag not in dict_tmp_input_fields :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => The input attribute \"" + attribute_name_in_input_tag + "\" is not supported.")
- if (dict_tmp_input_fields[attribute_name_in_input_tag] is not None) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => Duplicated attribute: \"" + attribute_name_in_input_tag + "\".")
- if attribute_value_in_input_tag == "" :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => Attribute: \"" + attribute_name_in_input_tag + "\" value cannot be null.")
- if attribute_name_in_input_tag == "key" :
- if attribute_value_in_input_tag not in dict_definition_external :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => Key: \"" + attribute_value_in_input_tag + "\" cannot be found in external storage (current external storage: " + str(dict_definition_external) + ").")
- dict_tmp_input_fields[attribute_name_in_input_tag] = attribute_value_in_input_tag
- elif attribute_name_in_input_tag == "type" :
- if tag_type != "mix_type" :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You must set the overall \"type\" to \"mix_type\" first if you want to specify the \"type\" attribute in each input field.")
- if attribute_value_in_input_tag not in lst_supported_output_mix_type :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => input type: \"" + attribute_value_in_input_tag + "\" is not supported.")
- dict_tmp_input_fields[attribute_name_in_input_tag] = attribute_value_in_input_tag
- elif attribute_name_in_input_tag == "bit" :
- if not isValidRegisterIndexString(attribute_value_in_input_tag) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => Attribute: \"" + attribute_name_in_input_tag + "\" should be in valid index range(0-31).")
- dict_tmp_input_fields["bit"] = int(attribute_value_in_input_tag)
- elif attribute_name_in_input_tag == "reverse_endian" :
- if (isReverseEndianEnabled(attribute_value_in_input_tag)) :
- dict_tmp_input_fields["reverse_endian"] = reverseEndian(attribute_value_in_input_tag)
- elif (attribute_name_in_input_tag == "start_index") or (attribute_name_in_input_tag == "end_index") :
- if not isValidNumberString(attribute_value_in_input_tag) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => Attribute: \"" + attribute_name_in_input_tag + "\" should be a valid number.")
- if (attribute_name_in_input_tag == "start_index") :
- dict_tmp_input_fields["start_index"] = int(attribute_value_in_input_tag)
- elif (attribute_name_in_input_tag == "end_index") :
- dict_tmp_input_fields["end_index"] = int(attribute_value_in_input_tag)
- else :
- dict_tmp_input_fields[attribute_name_in_input_tag] = attribute_value_in_input_tag
- #print(dict_tmp_input_fields)
- need_slice_string = False
- query_tag = dict_tmp_input_fields["tag"]
- query_attribute = dict_tmp_input_fields["attribute"]
- query_key = dict_tmp_input_fields["key"]
- query_start_index = dict_tmp_input_fields["start_index"]
- query_end_index = dict_tmp_input_fields["end_index"]
- query_reverse_endian = dict_tmp_input_fields["reverse_endian"]
- query_tag_type = dict_tmp_input_fields["type"]
- if (query_tag_type == None) :
- query_tag_type = tag_type
- if (query_start_index != None) or (query_end_index != None) :
- if (query_start_index is None) or (query_end_index is None) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"start_index\" and \"end_index\" should appear at the same time or not.")
- if (query_end_index <= query_start_index) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"end_index\" should be bigger than \"start_index\".")
- if (query_end_index - query_start_index) > 7 :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"start_index\" or \"end_index\" is not within the correct range.")
- need_slice_string = True
- #check: (1)start_index and end_index (2)end_index-start_index<=7 (3)xxx_index should be valid
- if (query_tag_type == "inner_value") :
- if (dict_tmp_input_fields["tag"] is None) or (dict_tmp_input_fields["attribute"] is None) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"tag\" and \"attribute\" are necessary for this type.")
- if query_tag not in dict_definition_inner_value :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You must declare the tag \"" + query_tag + "\" first.")
- if query_attribute not in dict_definition_inner_value[query_tag] :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You must declare the attribute \"" + query_attribute + "\" in tag \"" + query_tag + "\" first.")
- dict_definition_output[offset_int_decimal]["write_type"] = WRITE_TYPE_STRING
- if need_slice_string :
- tmp_length = len(dict_definition_inner_value[query_tag][query_attribute])
- if (tmp_length < (query_end_index + 1)) or (tmp_length < (query_start_index + 1)) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"end_index\" exceeds the maximum length \"" + str(tmp_length) + "\" defined in declaration area.")
- tmp_write_data = reverseEndian(dict_definition_inner_value[query_tag][query_attribute][query_start_index:query_end_index + 1], query_reverse_endian)
- else :
- tmp_write_data = reverseEndian(dict_definition_inner_value[query_tag][query_attribute], query_reverse_endian)
- if (tag_type == "mix_type") :
- dict_definition_output[offset_int_decimal]["write_data"] = dict_definition_output[offset_int_decimal]["write_data"] + tmp_write_data
- else :
- dict_definition_output[offset_int_decimal]["write_data"] = tmp_write_data
- # dict_definition_output[offset_int_decimal]["write_data"]
- elif (query_tag_type == "inner_text") :
- if (dict_tmp_input_fields["tag"] is None) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"tag\" is necessary for this type.")
- if query_tag not in dict_definition_inner_text :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You must declare the tag \"" + query_tag + "\" first.")
- dict_definition_output[offset_int_decimal]["write_type"] = WRITE_TYPE_STRING
- if need_slice_string :
- tmp_length = len(dict_definition_inner_text[query_tag])
- if (tmp_length < (query_end_index + 1)) or (tmp_length < (query_start_index + 1)) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"end_index\" exceeds the maximum length \"" + str(tmp_length) + "\" defined in declaration area.")
- tmp_write_data = reverseEndian(dict_definition_inner_text[query_tag][query_start_index:query_end_index + 1], query_reverse_endian)
- else :
- tmp_write_data = reverseEndian(dict_definition_inner_text[query_tag], query_reverse_endian)
- if (tag_type == "mix_type") :
- dict_definition_output[offset_int_decimal]["write_data"] = dict_definition_output[offset_int_decimal]["write_data"] + tmp_write_data
- else :
- dict_definition_output[offset_int_decimal]["write_data"] = tmp_write_data
- elif (query_tag_type == "external") :
- if (dict_tmp_input_fields["key"] is None) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"key\" is necessary for this type.")
- dict_definition_output[offset_int_decimal]["write_type"] = WRITE_TYPE_STRING
- if query_key not in dict_definition_external :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You must declare the external key \"" + query_key + "\" in Python code first.")
- dict_definition_output[offset_int_decimal]["write_type"] = WRITE_TYPE_STRING
- if need_slice_string :
- tmp_length = len(dict_definition_external[query_key])
- if (tmp_length < (query_end_index + 1)) or (tmp_length < (query_start_index + 1)) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"end_index\" exceeds the maximum length \"" + str(tmp_length) + "\" defined in declaration area.")
- tmp_write_data = reverseEndian(dict_definition_external[query_key][query_start_index:query_end_index + 1], query_reverse_endian)
- else :
- tmp_write_data = reverseEndian(dict_definition_external[query_key], query_reverse_endian)
- if (tag_type == "mix_type") :
- dict_definition_output[offset_int_decimal]["write_data"] = dict_definition_output[offset_int_decimal]["write_data"] + tmp_write_data
- else :
- dict_definition_output[offset_int_decimal]["write_data"] = tmp_write_data
- elif (query_tag_type == "boolean") :
- if (dict_tmp_input_fields["tag"] is None) or (dict_tmp_input_fields["attribute"] is None) or (dict_tmp_input_fields["bit"] is None) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => \"tag\" and \"attribute\" and \"bit\" are necessary for this type.")
- tmp_current_bit = dict_tmp_input_fields["bit"]
- if tmp_current_bit in tmp_dict_input_bit_duplicated_counter :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => Duplicated \"bit\" index value \"" + str(tmp_current_bit) + "\" for the same efuse field.")
- if query_tag not in dict_definition_boolean :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You must declare the tag \"" + query_tag + "\" first.")
- if query_attribute not in dict_definition_boolean[query_tag] :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You must declare the attribute \"" + query_attribute + "\" in tag \"" + query_tag + "\" first.")
- tmp_dict_input_bit_duplicated_counter[tmp_current_bit] = dict_definition_boolean[query_tag][query_attribute]
- #later summarize in outer loop
- else :
- if (tag_type == "mix_type") :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => The \"type\" of the input field should not be empty if you use mix_type.")
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => This type is not supported.")
- if (tag_type == "boolean") :
- tmp_lst_all_input_bits_in_this_efuse_field = []
- for idx in tmp_dict_input_bit_duplicated_counter :
- tmp_lst_all_input_bits_in_this_efuse_field.append( (idx, tmp_dict_input_bit_duplicated_counter[idx]) )
- dict_definition_output[offset_int_decimal]["write_data"] = tmp_lst_all_input_bits_in_this_efuse_field
- dict_definition_output[offset_int_decimal]["write_type"] = WRITE_TYPE_BIT
- elif (tag_type == "mix_type") :
- if not tmp_dict_input_bit_duplicated_counter :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => You should not use \"mix_type\" type because you do not set the type of any input field to \"boolean\".")
- tmp_lst_all_input_bits_in_this_efuse_field = []
- for idx in tmp_dict_input_bit_duplicated_counter :
- tmp_lst_all_input_bits_in_this_efuse_field.append( (idx, tmp_dict_input_bit_duplicated_counter[idx]) )
- if (len(dict_definition_output[offset_int_decimal]["write_data"]) > 8) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => If you want to use \"mix_type\" type, the total length of \"inner_value\" and \"inner_text\" input type of field should not exceed 8.")
- if (len(dict_definition_output[offset_int_decimal]["write_data"]) == 0) :
- PrintError_RaiseException_StopBuild("[definitions] Output offset at \"" + tag_offset + "\", type \"" + tag_type + "\" => If you want to use \"mix_type\" type, you should add at least one \"inner_value\" or one \"inner_text\" input type of field.")
- dict_definition_output[offset_int_decimal]["write_data2"] = tmp_lst_all_input_bits_in_this_efuse_field
- dict_definition_output[offset_int_decimal]["write_type"] = WRITE_TYPE_BIT_AND_STRING
- #print(dict_definition_output)
- #dic key: offset
- #dic value: type, final_value
- current_offset = 0
- with open(args.output_bin_name, "wb") as f :
- while (current_offset < MAX_OUTPUT_OFFSET_DECIMAL) :
- if current_offset in dict_definition_output :
- write_data = dict_definition_output[current_offset]["write_data"]
- write_type = dict_definition_output[current_offset]["write_type"]
- if write_type == WRITE_TYPE_BIT :
- writeBitValueToFile(f, write_data)
- elif write_type == WRITE_TYPE_STRING :
- writeHexStringToFile(f, write_data)
- elif write_type == WRITE_TYPE_BIT_AND_STRING :
- write_data_bits = dict_definition_output[current_offset]["write_data2"]
- writeBitValueAndOneHexStringToFile(f, write_data_bits, write_data)
- else :
- writeBitValueToFile(f, [(0, 0)])
- printAndLog("[definition] Unsupported write type in offset decimal: " + str(current_offset) + ".")
- else :
- writeBitValueToFile(f, [(0, 0)])
- current_offset = current_offset + 4
- bin_file_size_before_hash = os.path.getsize(args.output_bin_name)
- printAndLog("")
- sha256_hash = get_file_sha256hexdigest(args.output_bin_name)
- printAndLog("Image file(" + str(bin_file_size_before_hash) + " bytes) sha256 hash: " + sha256_hash)
- with open(args.output_bin_name, "ab") as f :
- writeHexStringToFile(f, sha256_hash[0:8]) #0x1E0 if 512bytes in size
- writeHexStringToFile(f, sha256_hash[8:16])
- writeHexStringToFile(f, sha256_hash[16:24])
- writeHexStringToFile(f, sha256_hash[24:32])
- writeHexStringToFile(f, sha256_hash[32:40])
- writeHexStringToFile(f, sha256_hash[40:48])
- writeHexStringToFile(f, sha256_hash[48:56])
- writeHexStringToFile(f, sha256_hash[56:64])
- printAndLog("Append sha256 hash to bin: Done!")
- bin_file_size = os.path.getsize(args.output_bin_name)
- printAndLog("")
- printAndLog("[Success] Write to bin: " + os.path.abspath(args.output_bin_name) + " (size: " + str(bin_file_size) + " bytes)")
- printAndLog("")
- if __name__ == '__main__':
- main()
|