def generateOTADescriptorImage(inputImagePath, hardwarePlatform): """ :param inputImagePath: valid input image path :param hardwarePlatform: :return: path of generated ota image, which as OTA descriptor appended """ rootPath = os.path.dirname(__file__) userConfigFolder = 'user-config' userConfigFileName = 'ota-descriptor.config' userConfigFilePath = os.path.join(rootPath, userConfigFolder, userConfigFileName) validateFilePath(userConfigFilePath) ruleFolder = "config-validation-rules" ruleFolderPath = os.path.join(rootPath, ruleFolder) otaDescriptor = getOTADescriptor(userConfigFilePath, inputImagePath, ruleFolderPath, hardwarePlatform) print("\nAdding OTA descriptors to image " + inputImagePath + " ...") if inputImagePath.endswith(".bin"): otaImagePath = inputImagePath.replace(".bin", ".ota.bin") else: otaImagePath = inputImagePath + ".ota.bin" addOTADescriptorToImage(inputImagePath, otaDescriptor, otaImagePath) print("OTA descriptors added! OTA image generated at : " + otaImagePath) return otaImagePath
userConfigFolder = 'user-config' userConfigFileName = 'ota-descriptor.config' userConfigFilePath = os.path.join(rootPath, userConfigFolder, userConfigFileName) validateFilePath(userConfigFilePath) ruleFolder = "config-validation-rules" ruleFolderPath = os.path.join(rootPath, ruleFolder) otaDescriptor = getOTADescriptor(userConfigFilePath, inputImagePath, ruleFolderPath, hardwarePlatform) print("\nAdding OTA descriptors to image " + inputImagePath + " ...") if inputImagePath.endswith(".bin"): otaImagePath = inputImagePath.replace(".bin", ".ota.bin") else: otaImagePath = inputImagePath + ".ota.bin" addOTADescriptorToImage(inputImagePath, otaDescriptor, otaImagePath) print("OTA descriptors added! OTA image generated at : " + otaImagePath) return otaImagePath if __name__ == "__main__": inputImagePath, hardwarePlatform = parseParamFromCMD() validateFilePath(inputImagePath) otaImagePath = generateOTADescriptorImage(inputImagePath, hardwarePlatform) print("\nResult of adding OTA descriptor: \n") printOTADescriptorImageStruct(processedImagePath=otaImagePath, imageLines=10, offset=0)
def getOTADescriptor(userConfigFilePath, inputImagePath, ruleFolderPath, hardwarePlatform): """ parse and validate the parameters defined by user. calculate the end address If all parameters are valid, return them as ota descriptor. Otherwise, raise exeception. :param userConfigFilePath: path of the user config file :param inputImagePath: path of the input image, which will be used to calculate the end address :param ruleFolderPath: path of the folder which contains the validation rule file for the user config :param hardwarePlatform: hardware platform name :return: parameters to be used to generate the OTA descriptor. Each parameter will be formatted as a 10-character string to represent a 32-bit hexadecimal number, where the first two character is a prefix "0x". """ parsedParams = parseConfigFile(userConfigFilePath) # 1. validate the hardware platform is valid and corresponding rule file can be found validHardwarePlatforms = os.listdir(ruleFolderPath) if hardwarePlatform not in validHardwarePlatforms: raise Exception( "Invalid hardware platform! \nExpected hardware platforms: " + str( validHardwarePlatforms) + ". \nFound: " + hardwarePlatform) # 2. Make sure the rule file and the parameters defined in it are valid validationFileLocation = os.path.join(ruleFolderPath, hardwarePlatform) validateFilePath(validationFileLocation) ruleParams = parseConfigFile(validationFileLocation) if len(ruleParams.keys()) != 2: raise Exception("Invalid validation rule file : " + validationFileLocation + "\nExpected 2 parameters in this file. " + "\nFound: " + str(len(ruleParams.keys()))) if "MIN_ADDRESS" not in ruleParams: raise Exception("Error! parameter \"MIN_ADDRESS\" is not defined in " + validationFileLocation) minAddrHardwarePlatform = ruleParams["MIN_ADDRESS"] validate32BitHexParam(minAddrHardwarePlatform, "MIN_ADDRESS", validationFileLocation) minAddrHardwarePlatform = format32BitHexStr(minAddrHardwarePlatform) if "MAX_ADDRESS" not in ruleParams: raise Exception("Error! parameter \"MAX_ADDRESS\" is not defined in " + validationFileLocation) maxAddrHardwarePlatform = ruleParams["MAX_ADDRESS"] validate32BitHexParam(maxAddrHardwarePlatform, "MAX_ADDRESS", validationFileLocation) maxAddrHardwarePlatform = format32BitHexStr(maxAddrHardwarePlatform) if (int(maxAddrHardwarePlatform, 16) <= int(minAddrHardwarePlatform, 16)): raise Exception( "MAX_ADDRESS must be greater than the MIN_ADDRESS !" + " File location " + validationFileLocation) # 3. validate sequence number if "SEQUENCE_NUMBER" not in parsedParams: raise Exception("Error! parameter \"SEQUENCE_NUMBER\" is not defined in " + userConfigFilePath) sequenceNumber = parsedParams["SEQUENCE_NUMBER"] validate32BitUIntParam(sequenceNumber, "SEQUENCE_NUMBER", userConfigFilePath) # convert from string of 32-bit unsigned integer to string of 32-bit hexadecimal sequenceNumber = hex(int(sequenceNumber, 10)) sequenceNumber = format32BitHexStr(sequenceNumber) # 4. validate hardware id if "HARDWARE_ID" not in parsedParams: raise Exception("Error! parameter \"HARDWARE_ID\" is not defined in " + userConfigFilePath) hardwareID = parsedParams["HARDWARE_ID"] hardwareID = formatHardwareID(hardwareID, userConfigFilePath) hardwareID = format32BitHexStr(hardwareID) # 5. validate reserved bytes if "RESERVED_BYTES" not in parsedParams: raise Exception("Error! parameter \"RESERVED_BYTES\" is not defined in " + userConfigFilePath) reserves = parsedParams["RESERVED_BYTES"] validate32BitHexParam(reserves, "RESERVED_BYTES", userConfigFilePath) reserves = format32BitHexStr(reserves) # 6. validate start address if "START_ADDRESS" not in parsedParams: raise Exception("Error! parameter \"START_ADDRESS\" is not defined in " + userConfigFilePath) startAddress = parsedParams["START_ADDRESS"] validate32BitHexParam(startAddress, "START_ADDRESS", userConfigFilePath) startAddress = format32BitHexStr(startAddress) # make sure minAddrHardwarePlatform <= startAddress < maxAddressHardwarePlatform startMin = minAddrHardwarePlatform startMax = format32BitHexStr(hex(int(maxAddrHardwarePlatform, 16) - 1)) validate32BitHexParamRange(startAddress, "START_ADDRESS", startMin, startMax, userConfigFilePath) # 7. calculate and validate the end address fileSize = getFileSize(inputImagePath) endAddress = getEndAddress(fileSize, int(startAddress, 16)) # get end address in decimal format endAddress = hex(endAddress).upper() # convert to hexadecimal format # make sure minAddrHardwarePlatform < endAddress <= maxAddressHardwarePlatform endMin = format32BitHexStr(hex(int(minAddrHardwarePlatform, 16) + 1)) endMax = maxAddrHardwarePlatform if int(endAddress, 16) < int(endMin, 16) or int(endAddress, 16) > int(endMax, 16): raise Exception( "Invalid value of \"END_ADDRESS\"! Expected range : [" + endMin + "," + endMax + "]. Calculated Result : " + endAddress + "\nPossible reasons: START_ADDRESS is too large or image size is too large (END_ADDRESS = START_ADDRESS + 24 bytes + size of input image)" + "\n\nDebug Info: " + "\nImage size: " + str(fileSize) + "\nSTART_ADDRESS: " + startAddress + ". Config file location" + userConfigFilePath) endAddress = format32BitHexStr(endAddress) # 8. validate the execution address if "EXECUTION_ADDRESS" not in parsedParams: raise Exception("Error! parameter \"EXECUTION_ADDRESS\" is not defined in " + userConfigFilePath) executionAddress = parsedParams["EXECUTION_ADDRESS"] validate32BitHexParam(executionAddress, "EXECUTION_ADDRESS", userConfigFilePath) # make sure startAddress <= executionAddress <= endAddress execMin = startAddress execMax = endAddress validate32BitHexParamRange(executionAddress, "EXECUTION_ADDRESS", execMin, execMax, userConfigFilePath) executionAddress = format32BitHexStr(executionAddress) return OTADescriptor(sequenceNumber, startAddress, endAddress, executionAddress, hardwareID, reserves)
print("\nConverting factory image " + factoryImagePath + " into hex format ....\n") hexFilePath = factoryImagePath.replace("initial.bin", "factory.unified.hex") convertToUnifiedHex(inputImagePath=factoryImagePath, outputPath=hexFilePath, bootLoaderHexPath=bootloaderHexPath) print("\nHex file is generated at " + hexFilePath) print("\nHex file info:") os.system("srec_info " + hexFilePath + " -Intel ") if __name__ == "__main__": inputImagePath, hardwarePlatform, privateKeyPath, bootloaderHexPath = parseCMDParam( ) # verify parameter validateFilePath(inputImagePath) validateFilePath(privateKeyPath) validateFilePath(bootloaderHexPath) # get ota image otaImagePath = generateOTADescriptorImage(inputImagePath, hardwarePlatform) # sign the ota image digestMethod = "sha256" # use "sha256" method signature = getSignitureLocally(otaImagePath, privateKeyPath, digestMethod) generateFactoryImage(signature, otaImagePath, bootloaderHexPath)