/// <summary> /// genAIS command. Always use section-by-section CRC checks /// </summary> /// <param name="mainObjectFileName"></param> /// <param name="bootMode"></param> /// <returns>Bytes of the binary or text AIS command</returns> public static Byte[] GenAIS( AISGen devAISGen, List<String> inputFileNames, IniFile iniFile ) { UInt32 numWords; // Setup the binary writer to generate the temp AIS file devAISGen.devAISStream = new MemoryStream(); using ( devAISGen.writer = new EndianBinaryWriter( devAISGen.devAISStream, devAISGen.devEndian) ) { // List to keep track of loadable sections and their occupied memory ranges devAISGen.sectionMemory = new List<MemoryRange>(); // Initiate list to keep track of the input files devAISGen.objectFiles = new List<ObjectFile>(); // Get data from the GENERAL INI Section GeneralIniSectionParse(devAISGen, iniFile); #region Main AIS Generation // --------------------------------------------------------- // ****************** BEGIN AIS GENERATION ***************** // --------------------------------------------------------- Console.WriteLine("Begining the AIS file generation."); // Diaplay currently selected boot mode Console.WriteLine("AIS file being generated for bootmode: {0}.",Enum.GetName(typeof(AisBootModes),devAISGen.bootMode)); // Write the premilinary header and fields (everything before first AIS command) devAISGen.InsertAISPreamble(); Debug.DebugMSG("Preamble Complete"); // Parse the INI sections in order, inserting needed AIS commands if (iniFile != null) { foreach(IniSection sec in iniFile.Sections) { InsertAISCommandViaINI(devAISGen, sec); } Debug.DebugMSG("INI parsing complete"); } // Insert the object file passed in on the top-level (if it exists) if (inputFileNames != null) { foreach (String fn in inputFileNames) { String[] nameAndAddr = fn.Split('@'); Debug.DebugMSG("Inserting file " + nameAndAddr[0]); if (!File.Exists(nameAndAddr[0])) { Console.WriteLine("ERROR: {0} does not exist. Aborting...", nameAndAddr[0]); return null; } if (nameAndAddr.Length == 2) { UInt32 loadAddr; nameAndAddr[1] = nameAndAddr[1].ToLower(); if (nameAndAddr[1].StartsWith("0x")) { if (!UInt32.TryParse(nameAndAddr[1].Replace("0x", ""), NumberStyles.HexNumber, null, out loadAddr)) { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } else { devAISGen.InsertAISObjectFile(nameAndAddr[0], loadAddr); } } else if (UInt32.TryParse(nameAndAddr[1], out loadAddr)) { devAISGen.InsertAISObjectFile(nameAndAddr[0], loadAddr); } else { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } } else if (nameAndAddr.Length == 1) { // If we still have not had a valid entry point set, then use entry point from // first encountered non-binary file in the inputFileNames list if (devAISGen.entryPoint == 0xFFFFFFFF) { devAISGen.InsertAISObjectFile(nameAndAddr[0], true); } else { devAISGen.InsertAISObjectFile(nameAndAddr[0], false); } } else { Console.WriteLine("WARNING: Invalid filename format, {0}. Ignoring...", fn); } } Debug.DebugMSG("Main input file insertion complete."); } // If CRC type is for single CRC, send Request CRC now if (devAISGen.aisCRCType == AisCRCCheckType.SINGLE_CRC) { devAISGen.InsertAISRequestCRC(); } // Insert closing JumpClose AIS command (issue warning) if (devAISGen.entryPoint == 0xFFFFFFFF) { // No valid entry point was ever set (issue warning) Console.WriteLine("WARNING: Entry point set to null pointer!"); devAISGen.InsertAISJumpClose(0x00000000); } else { devAISGen.InsertAISJumpClose(devAISGen.entryPoint); } // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); Console.WriteLine("AIS file generation was successful."); // --------------------------------------------------------- // ******************* END AIS GENERATION ****************** // --------------------------------------------------------- #endregion // Now create return Byte array based on tempAIS file and the bootmode EndianBinaryReader tempAIS_br = new EndianBinaryReader(devAISGen.devAISStream, Endian.LittleEndian); // Setup the binary reader object numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 2]; //Each word converts to 4 binary bytes Debug.DebugMSG("Number of words in the AIS output is {0}", numWords); // Copy the data to the output Byte array for (UInt32 i = 0; i < numWords; i++) { BitConverter.GetBytes(tempAIS_br.ReadUInt32()).CopyTo(devAISGen.AISData, i * 4); } // Close the binary reader tempAIS_br.Close(); } // Dispose of all object files foreach (ObjectFile file in devAISGen.objectFiles) { try { file.Dispose(); } catch (Exception e) { Console.WriteLine(e.Message); } } // Clean up any embedded file resources that may have been extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); // Return Byte Array return devAISGen.AISData; }
public static retType InsertAISCommandViaINI(AISGen devAISGen, IniSection sec) { #region Handle Input Binary and Object Files if (sec.sectionName.Equals("INPUTFILE", StringComparison.OrdinalIgnoreCase)) { String fileName = null; Boolean useEntryPoint = false; UInt32 loadAddr = 0xFFFFFFFF; UInt32 entryPointAddr = 0xFFFFFFFF; foreach (DictionaryEntry de in sec.sectionValues) { // File name for binary section data if (((String)de.Key).Equals("FILENAME", StringComparison.OrdinalIgnoreCase)) { fileName = (String) sec.sectionValues["FILENAME"]; } // Binary section's load address in the memory map if (((String)de.Key).Equals("LOADADDRESS", StringComparison.OrdinalIgnoreCase)) { loadAddr = (UInt32) sec.sectionValues["LOADADDRESS"]; } // Binary section's entry point address in the memory map if (((String)de.Key).Equals("ENTRYPOINTADDRESS", StringComparison.OrdinalIgnoreCase)) { entryPointAddr = (UInt32) sec.sectionValues["ENTRYPOINTADDRESS"]; } // Option to specify that this entry point should be used for AIS if (((String)de.Key).Equals("USEENTRYPOINT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) { useEntryPoint = true; } else if (((String)sec.sectionValues["USEENTRYPOINT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) { useEntryPoint = true; } } } if (fileName == null) { Console.WriteLine("ERROR: File name must be provided in INPUTFILE section."); return retType.FAIL; } // Insert the file into the AIS image if ( loadAddr != 0xFFFFFFFF ) { // binary image if ( entryPointAddr != 0xFFFFFFFF ) { devAISGen.InsertAISObjectFile(fileName, loadAddr, entryPointAddr); } else { devAISGen.InsertAISObjectFile(fileName, loadAddr); } } else { if ( entryPointAddr != 0xFFFFFFFF ) { devAISGen.InsertAISObjectFile(fileName,true); } else { devAISGen.InsertAISObjectFile(fileName,useEntryPoint); } } return retType.SUCCESS; } #endregion #region Handle ROM and AIS Extra Functions // Handle ROM functions if (devAISGen.ROMFunc != null) { for (UInt32 j = 0; j < devAISGen.ROMFunc.Length; j++) { if (sec.sectionName.Equals(devAISGen.ROMFunc[j].iniSectionName, StringComparison.OrdinalIgnoreCase)) { UInt32 funcIndex = j; UInt32[] args = new UInt32[ (UInt32)devAISGen.ROMFunc[funcIndex].numParams ]; for (Int32 k = 0; k < devAISGen.ROMFunc[funcIndex].numParams; k++) { Debug.DebugMSG("\tParam name: {0}, Param num: {1}, Value: {2}\n", devAISGen.ROMFunc[funcIndex].paramNames[k], k, sec.sectionValues[devAISGen.ROMFunc[funcIndex].paramNames[k].ToUpper()]); try { args[k] = (UInt32) sec.sectionValues[devAISGen.ROMFunc[funcIndex].paramNames[k].ToUpper()]; } catch { Console.WriteLine("WARNING: INI Section {0} is malformed - {1} parameter not provided. Ignoring section contens.",sec.sectionName, devAISGen.ROMFunc[funcIndex].paramNames[k].ToUpper()); return retType.SUCCESS; } } devAISGen.InsertAISFunctionExecute((UInt16) funcIndex, (UInt16) devAISGen.ROMFunc[funcIndex].numParams, args); return retType.SUCCESS; } } } // Handle AISExtras functions if (devAISGen.AISExtraFunc != null) { for (UInt32 j = 0; j < devAISGen.AISExtraFunc.Length; j++) { if (sec.sectionName.Equals(devAISGen.AISExtraFunc[j].iniSectionName, StringComparison.OrdinalIgnoreCase)) { UInt32 funcIndex = j; UInt32[] args = new UInt32[ (UInt32)devAISGen.AISExtraFunc[j].numParams ]; // Load the AIS extras file if needed { IniSection tempSec = new IniSection(); tempSec.sectionName = "INPUTFILE"; tempSec.sectionValues = new Hashtable(); tempSec.sectionValues["FILENAME"] = devAISGen.AISExtraFunc[funcIndex].aisExtraFileName; EmbeddedFileIO.ExtractFile(Assembly.GetExecutingAssembly(), devAISGen.AISExtraFunc[funcIndex].aisExtraFileName, true); InsertAISCommandViaINI(devAISGen, tempSec); Debug.DebugMSG("AISExtras file loaded.\n"); // Use symbols to get address for AISExtra functions and parameters for (Int32 k = 0; k < devAISGen.AISExtraFunc.Length; k++) { ObjectFile tempFile = FindFileWithSymbol(devAISGen, devAISGen.AISExtraFunc[funcIndex].funcName); if (tempFile == null) { // Try looking for underscore version tempFile = FindFileWithSymbol(devAISGen, "_" + devAISGen.AISExtraFunc[funcIndex].funcName); } if (tempFile != null) { ObjectSymbol tempSym = tempFile.symFind(devAISGen.AISExtraFunc[funcIndex].funcName); if (tempSym == null) { // Try looking for underscore version tempSym = tempFile.symFind("_"+devAISGen.AISExtraFunc[funcIndex].funcName); } if (tempSym != null) { devAISGen.AISExtraFunc[funcIndex].funcAddr = (UInt32) tempSym.value; ObjectSection tempObjSec = tempFile.secFind(".params"); if (tempObjSec == null) { Console.WriteLine(".params section not found in file {0}.", devAISGen.AISExtraFunc[funcIndex].aisExtraFileName); return retType.FAIL; } else { devAISGen.AISExtraFunc[funcIndex].paramAddr = (UInt32) tempObjSec.runAddr; } } else { Console.WriteLine("AIS extra function, {0}, not found in file {1}.", devAISGen.AISExtraFunc[funcIndex].funcName, devAISGen.AISExtraFunc[funcIndex].aisExtraFileName); return retType.FAIL; } } else { // The function name was not found - that's a big problem with our // device specific AISGen class. Console.WriteLine("AIS extra function, {0}, not found in file {1}.", devAISGen.AISExtraFunc[funcIndex].funcName, devAISGen.AISExtraFunc[funcIndex].aisExtraFileName); return retType.FAIL; } } } Debug.DebugMSG("Found required sections and symbols in AISExtras file.\n"); // Validate input parameters for (Int32 k = 0; k < devAISGen.AISExtraFunc[funcIndex].numParams; k++) { try { args[k] = (UInt32) sec.sectionValues[devAISGen.AISExtraFunc[funcIndex].paramNames[k].ToUpper()]; } catch { Console.WriteLine("WARNING: INI Section {0} is malformed - {1} parameter not provided. Ignoring section contens.",sec.sectionName, devAISGen.ROMFunc[funcIndex].paramNames[k].ToUpper()); return retType.SUCCESS; } } Debug.DebugMSG("Input parameter validation for AISExtras function is complete.\n"); // Write SET command for each input parameter for (Int32 k = 0; k < devAISGen.AISExtraFunc[funcIndex].numParams; k++) { devAISGen.InsertAISSet( (UInt32)AisSetType.INT, // Write type field (32-bit only) (UInt32) (devAISGen.AISExtraFunc[funcIndex].paramAddr + (k * 4)), args[k], (UInt32)0x0 ); // Write Sleep value (should always be zero) } // Now that params are set, Jump to function devAISGen.InsertAISJump(devAISGen.AISExtraFunc[funcIndex].funcAddr); return retType.SUCCESS; } } } #endregion #region Handle AIS Command Sections if (sec.sectionName.Equals("AIS_EnableCRC", StringComparison.OrdinalIgnoreCase)) { devAISGen.InsertAISEnableCRC(); } else if (sec.sectionName.Equals("AIS_DisableCRC", StringComparison.OrdinalIgnoreCase)) { devAISGen.InsertAISDisableCRC(); } else if (sec.sectionName.Equals("AIS_RequestCRC", StringComparison.OrdinalIgnoreCase)) { UInt32 crcValue = 0x00000000; Int32 seekValue = -12; foreach (DictionaryEntry de in sec.sectionValues) { if (((String)de.Key).Equals("CRCValue", StringComparison.OrdinalIgnoreCase)) { crcValue = (UInt32)sec.sectionValues["CRCVALUE"]; } if (((String)de.Key).Equals("SEEKValue", StringComparison.OrdinalIgnoreCase)) { seekValue = (Int32)sec.sectionValues["SEEKVALUE"]; } } if (devAISGen.InsertAISRequestCRC(crcValue, seekValue) != retType.SUCCESS) { Console.WriteLine("WARNING: Final function register AIS command failed."); } } else if (sec.sectionName.Equals("AIS_Jump", StringComparison.OrdinalIgnoreCase)) { String symbolName = ""; UInt32 address = 0x00000000; foreach (DictionaryEntry de in sec.sectionValues) { if (((String)de.Key).Equals("LOCATION", StringComparison.OrdinalIgnoreCase)) { symbolName = sec.sectionValues["LOCATION"].ToString(); } } // See if string is number (address) if (UInt32.TryParse(symbolName, out address)) { if (devAISGen.InsertAISJump(address) != retType.SUCCESS) { Console.WriteLine("WARNING: AIS Jump to {0} was not inserted.",symbolName); } } else { if (devAISGen.InsertAISJump(symbolName) != retType.SUCCESS) { Console.WriteLine("WARNING: AIS Jump to {0} was not inserted.",symbolName); } } } else if (sec.sectionName.Equals("AIS_JumpClose", StringComparison.OrdinalIgnoreCase)) { String symbolName = ""; UInt32 address = 0x00000000; foreach (DictionaryEntry de in sec.sectionValues) { if (((String)de.Key).Equals("ENTRYPOINT", StringComparison.OrdinalIgnoreCase)) { symbolName = (String)sec.sectionValues["ENTRYPOINT"]; } } if (symbolName == "") { devAISGen.InsertAISJumpClose(devAISGen.entryPoint); } else { // See if string is number (address) if (UInt32.TryParse(symbolName, out address)) { if (devAISGen.InsertAISJumpClose(address) != retType.SUCCESS) { Console.WriteLine("WARNING: AIS Jump to {0} was not inserted.",symbolName); } } else { if (devAISGen.InsertAISJumpClose(symbolName) != retType.SUCCESS) { Console.WriteLine("WARNING: AIS Jump to {0} was not inserted.",symbolName); } } } } else if (sec.sectionName.Equals("AIS_Set", StringComparison.OrdinalIgnoreCase)) { UInt32 type = 0x00000000; UInt32 address = 0x00000000; UInt32 data = 0x00000000; UInt32 sleep = 0x00000000; foreach (DictionaryEntry de in sec.sectionValues) { if (sec.sectionValues["TYPE"].GetType() == typeof(String)) { if (((String)de.Key).Equals("TYPE", StringComparison.OrdinalIgnoreCase)) { if (! UInt32.TryParse((String)sec.sectionValues["TYPE"], out type)) { try { type = (UInt32)Enum.Parse(typeof(AisSetType),(String)sec.sectionValues["TYPE"]); } catch (ArgumentException e) { Console.WriteLine((String)sec.sectionValues["TYPE"] + " is not allowed specifier for SET type."); Console.WriteLine(e.Message); return retType.FAIL; } } } } else { type = (UInt32)sec.sectionValues["TYPE"]; } if (((String)de.Key).Equals("ADDRESS", StringComparison.OrdinalIgnoreCase)) { address = (UInt32)sec.sectionValues["ADDRESS"]; } if (((String)de.Key).Equals("DATA", StringComparison.OrdinalIgnoreCase)) { data = (UInt32)sec.sectionValues["DATA"]; } if (((String)de.Key).Equals("SLEEP", StringComparison.OrdinalIgnoreCase)) { sleep = (UInt32)sec.sectionValues["SLEEP"]; } } devAISGen.InsertAISSet(type, address, data, sleep); } else if (sec.sectionName.Equals("AIS_SectionFill", StringComparison.OrdinalIgnoreCase)) { UInt32 address = 0x00000000; UInt32 size = 0x00000000; UInt32 type = 0x00000000; UInt32 pattern = 0x00000000; foreach (DictionaryEntry de in sec.sectionValues) { if (((String)de.Key).Equals("ADDRESS", StringComparison.OrdinalIgnoreCase)) { address = (UInt32)sec.sectionValues["ADDRESS"]; } if (((String)de.Key).Equals("SIZE", StringComparison.OrdinalIgnoreCase)) { size = (UInt32)sec.sectionValues["SIZE"]; } if (((String)de.Key).Equals("TYPE", StringComparison.OrdinalIgnoreCase)) { type = (UInt32)sec.sectionValues["TYPE"]; } if (((String)de.Key).Equals("PATTERN", StringComparison.OrdinalIgnoreCase)) { pattern = (UInt32)sec.sectionValues["PATTERN"]; } } devAISGen.InsertAISSectionFill( address, size, type, pattern); } else if (sec.sectionName.Equals("AIS_FastBoot", StringComparison.OrdinalIgnoreCase)) { devAISGen.InsertAISFastBoot(); } else if (sec.sectionName.Equals("AIS_ReadWait", StringComparison.OrdinalIgnoreCase)) { UInt32 address = 0x00000000; UInt32 mask = 0xFFFFFFFF; UInt32 data = 0xFFFFFFFF; foreach (DictionaryEntry de in sec.sectionValues) { if (((String)de.Key).Equals("ADDRESS", StringComparison.OrdinalIgnoreCase)) { address = (UInt32)sec.sectionValues["ADDRESS"]; } if (((String)de.Key).Equals("MASK", StringComparison.OrdinalIgnoreCase)) { mask = (UInt32)sec.sectionValues["MASK"]; } if (((String)de.Key).Equals("DATA", StringComparison.OrdinalIgnoreCase)) { data = (UInt32)sec.sectionValues["DATA"]; } } devAISGen.InsertAISReadWait(address, mask, data); } else if (sec.sectionName.Equals("AIS_SeqReadEnable", StringComparison.OrdinalIgnoreCase)) { devAISGen.InsertAISSeqReadEnable(); } else if (sec.sectionName.Equals("AIS_FinalFunctionReg", StringComparison.OrdinalIgnoreCase)) { String finalFxnName = ""; foreach (DictionaryEntry de in sec.sectionValues) { if (((String)de.Key).Equals("FINALFXNSYMBOLNAME", StringComparison.OrdinalIgnoreCase)) { finalFxnName = (String)sec.sectionValues["FINALFXNSYMBOLNAME"]; } } if (devAISGen.InsertAISFinalFxnReg(finalFxnName) != retType.SUCCESS) { Console.WriteLine("WARNING: Final function register AIS command failed."); } } else if ( (sec.sectionName.Equals("GENERAL", StringComparison.OrdinalIgnoreCase)) || (sec.sectionName.Equals("SECURITY", StringComparison.OrdinalIgnoreCase)) ) { // Ignore General/Security section here since it should have already been processed } else { // Any other sections names should be ignored with warning Console.WriteLine("WARNING: Unrecognized INI section, {0}. Ignoring...", sec.sectionName ); } #endregion return retType.SUCCESS; }
/// <summary> /// SecureGenAIS command. /// </summary> /// <param name="inputFileNames">File name of input .out file</param> /// <param name="bootMode">AISGen Object for the particular device</param> /// <returns>Bytes of the binary or AIS boot image</returns> public static Byte[] SecureGenAIS(AISGen devAISGen, List<String> inputFileNames, IniFile iniFile) { UInt32 numWords; // Set defaults devAISGen.bootLoaderExitType = BootLoaderExitType.NONE; devAISGen.currHashAlgorithmValue = SHA_Algorithm.SHA1; devAISGen.sectionsToEncrypt = null; devAISGen.rsaObject = null; devAISGen.customerEncryptionKey = null; devAISGen.keyEncryptionKey = null; devAISGen.genericKeyHeaderData = null; devAISGen.currHashAlgorithm = null; // Setup the binary writer to generate the temp AIS file devAISGen.sigStream = new MemoryStream(); devAISGen.devAISStream = new MemoryStream(); devAISGen.sigWriter = new EndianBinaryWriter( devAISGen.sigStream, devAISGen.devEndian); using ( devAISGen.writer = new EndianBinaryWriter( devAISGen.devAISStream, devAISGen.devEndian) ) { // List to keep track of loadable sections and their occupied memory ranges devAISGen.sectionMemory = new List<MemoryRange>(); // Initiate list to keep track of the input files devAISGen.objectFiles = new List<ObjectFile>(); // Get data from the GENERAL INI Section GeneralIniSectionParse(devAISGen, iniFile); // Get data from the SECURITY INI Section if (SecurityIniSectionParse(devAISGen, iniFile) != retType.SUCCESS) { Console.WriteLine("Aborting..."); return null; } #region Handle the case of Legacy boot mode if (devAISGen.bootMode == AisBootModes.LEGACY) { UInt32 fileSize = 0, secureDataSize = 0, totalImgSize = 0, paddingSize = 0; UInt32 loadAddr = 0, fileCount = 0; Byte[] fileData; String fileName = null; Boolean encryptSections = false; UInt32 entryPointAddr = 0x00000000; // Check for legacy input file foreach( IniSection sec in iniFile.Sections) { if (sec.sectionName.Equals("LEGACYINPUTFILE", StringComparison.OrdinalIgnoreCase)) { fileCount++; foreach (DictionaryEntry de in sec.sectionValues) { // File name for binary section data if (((String)de.Key).Equals("FILENAME", StringComparison.OrdinalIgnoreCase)) { fileName = (String) sec.sectionValues["FILENAME"]; } // Binary section's load address in the memory map if (((String)de.Key).Equals("LOADADDRESS", StringComparison.OrdinalIgnoreCase)) { loadAddr = (UInt32) sec.sectionValues["LOADADDRESS"]; } // Binary section's entry point address in the memory map if (((String)de.Key).Equals("ENTRYPOINTADDRESS", StringComparison.OrdinalIgnoreCase)) { entryPointAddr = (UInt32) sec.sectionValues["ENTRYPOINTADDRESS"]; } // Binary section's entry point address in the memory map if (((String)de.Key).Equals("ENCRYPT", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["ENCRYPT"]).Equals("YES", StringComparison.OrdinalIgnoreCase)) encryptSections = true; if (((String)sec.sectionValues["ENCRYPT"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) encryptSections = true; } } if (fileName == null) { Console.WriteLine("ERROR: File name must be provided in INPUTFILE section."); return null; } // Insert the file into the AIS image if (( entryPointAddr == 0x00000000)) { Console.WriteLine("Entrypoint Address = {0} is not valid.", entryPointAddr); return null; } } } // Validate an input binary file was given in the INI file if (fileCount == 0) { Console.WriteLine("ERROR: You did not supply a binary file section in the INI file!"); return null; } if (fileCount > 1) { Console.WriteLine("WARNING: You supplied too many binary file sections in the INI file."); Console.WriteLine(" Only using the first one."); } // Figure out the size of the secure data region (signature + keystruct) if (devAISGen.SecureType == AisSecureType.CUSTOM) { // On custom secure we have rsa keySize bits for signature and modulus of key struct, // plus eight additional bytes from key struct secureDataSize = (UInt32) (8 + (devAISGen.rsaObject.KeySize >> 3) + (devAISGen.rsaObject.KeySize >> 3)); } else if (devAISGen.SecureType == AisSecureType.GENERIC) { // On generic secure we have 32 for key and HashSize bits rounded up to nearst 16 bytes // for signature data. secureDataSize = (UInt32) (32 + ((((devAISGen.currHashAlgorithm.HashSize >> 3)+15)>>4)<<4)); } // Verify legacy input binary file exists, and get data if it does if (File.Exists(fileName)) { Byte[] tempFileData = FileIO.GetFileData(fileName); fileSize = (UInt32) tempFileData.Length; totalImgSize = 16 + fileSize + secureDataSize; if (totalImgSize > 16*1024) { Console.WriteLine("WARNING: The input image is too large for the ROM boot loader."); Console.WriteLine("Reduce its size by {0} bytes.", (totalImgSize - (16*1024))); } // Figure out how much to pad input file region to acheive complete image ending on 1K boundary paddingSize = (((totalImgSize+1023) >> 10) << 10) - totalImgSize; // Copy to final data array of fileSize fileSize = fileSize + paddingSize; fileData = new Byte[fileSize]; tempFileData.CopyTo(fileData,0); // Adjust total image size to final amount totalImgSize = 16 + fileSize + secureDataSize; } else { Console.WriteLine("Error: Binary file was not found!"); return null; } if ( ((entryPointAddr & 0x00FFFFFF) < loadAddr) || ((entryPointAddr & 0x00FFFFFF) > (loadAddr+fileSize)) ) { Console.WriteLine("ERROR: Entry point falls outside load image region."); return null; } // Place header // Config Word - indicates total image size, nor width (if applicable) if (devAISGen.busWidth == 16) { devAISGen.writer.Write ((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x1 << 0)|(0x0 << 4))); devAISGen.sigWriter.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x1 << 0)|(0x0 << 4))); } else { devAISGen.writer.Write ((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x0 << 0)|(0x0 << 4))); devAISGen.sigWriter.Write((UInt32)(((((totalImgSize >> 10)-1) & 0xFFFF) << 8)|(0x0 << 0)|(0x0 << 4))); } // Magic Number - indicates signed or encrypted if (encryptSections) { devAISGen.writer.Write((UInt32)SecureLegacyMagic.ENCMOD_MAGIC); devAISGen.sigWriter.Write((UInt32)SecureLegacyMagic.ENCMOD_MAGIC); } else { devAISGen.writer.Write((UInt32)SecureLegacyMagic.SIGNMOD_MAGIC); devAISGen.sigWriter.Write((UInt32)SecureLegacyMagic.SIGNMOD_MAGIC); } // Entry Point - where to jump within the image upon load devAISGen.writer.Write( entryPointAddr ); devAISGen.sigWriter.Write( entryPointAddr ); // SecureDataSize - size of data following image for key struct & signature devAISGen.writer.Write( (UInt32)secureDataSize ); devAISGen.sigWriter.Write( (UInt32)secureDataSize ); // Now place padded binary contents if (!encryptSections) { // Non-encrypted section devAISGen.writer.Write(fileData); devAISGen.sigWriter.Write(fileData); } else { // Encrypted section // Write unencrypted data to the signature buffer devAISGen.sigWriter.Write(fileData); // Encrypt data using CBC algorithm try { Byte[] encData = AesManagedUtil.AesCTSEncrypt(fileData,devAISGen.customerEncryptionKey,devAISGen.CEKInitialValue); // Write encrypted section data out to AIS data stream devAISGen.writer.Write(encData); } catch(Exception e) { Console.WriteLine("Exception during encryption operation: {0}",e.Message); } } // Now place the key data devAISGen.writer.Write(devAISGen.secureKeyData); devAISGen.sigWriter.Write(devAISGen.secureKeyData); // Finally place the signature which covers the entire image InsertAISSecureSignature( devAISGen ); // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); devAISGen.sigStream.Close(); } #endregion #region AIS Generation else { // --------------------------------------------------------- // ****************** BEGIN AIS GENERATION ***************** // --------------------------------------------------------- Console.WriteLine("Begining the Secure AIS file generation."); // Diaplay currently selected boot mode Console.WriteLine("AIS file being generated for bootmode: {0}.",Enum.GetName(typeof(AisBootModes),devAISGen.bootMode)); // Write the premilinary header and fields (everything before first AIS command) devAISGen.InsertAISPreamble(); Debug.DebugMSG("Preamble Complete"); // Write the Secure Key command and key data devAISGen.InsertAISSecureKeyLoad(devAISGen.secureKeyData); Debug.DebugMSG("Secure Key Insertion Complete"); // Insert Exit Mode type devAISGen.InsertAISSetExitMode(devAISGen.bootLoaderExitType); Debug.DebugMSG("Set Exit Mode complete"); // Parse the INI sections in order, inserting needed AIS commands foreach(IniSection sec in iniFile.Sections) { InsertSecureAISCommandViaINI(devAISGen, sec); } Debug.DebugMSG("INI parsing complete"); // Insert the object file(s) passed in on the top-level (if it exists) foreach (String fn in inputFileNames) { String[] nameAndAddr = fn.Split('@'); Debug.DebugMSG("Inserting file " + nameAndAddr[0]); if (!File.Exists(nameAndAddr[0])) { Console.WriteLine("ERROR: {0} does not exist. Aborting...", nameAndAddr[0]); return null; } // Handle binary files provided with a load address if (nameAndAddr.Length == 2) { UInt32 loadAddr; nameAndAddr[1] = nameAndAddr[1].ToLower(); if (nameAndAddr[1].StartsWith("0x")) { if (!UInt32.TryParse(nameAndAddr[1].Replace("0x", ""), NumberStyles.HexNumber, null, out loadAddr)) { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } else { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], loadAddr, false); } } else if (UInt32.TryParse(nameAndAddr[1], out loadAddr)) { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], loadAddr, false); } else { Console.WriteLine("WARNING: Invalid address format, {0}. Ignoring...", nameAndAddr[1]); } } // Handle Object files (ones provided without load address) else if (nameAndAddr.Length == 1) { // If we still have not had a valid entry point set, then use entry point from // first encountered non-binary file in the inputFileNames list if (devAISGen.entryPoint == 0xFFFFFFFF) { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], true, false); } else { devAISGen.InsertAISSecureObjectFile(nameAndAddr[0], false, false); } } else { Console.WriteLine("WARNING: Invalid filename format, {0}. Ignoring...", fn); } } Debug.DebugMSG("Main input file insertion complete."); // Insert closing JumpClose AIS command (issue warning) if (devAISGen.entryPoint == 0x00000000) { Console.WriteLine("WARNING: Entry point set to null pointer!"); } devAISGen.InsertAISJumpClose(devAISGen.entryPoint); // Insert final Signature InsertAISSecureSignature(devAISGen); // Flush the data and then return to start devAISGen.devAISStream.Flush(); devAISGen.devAISStream.Seek(0,SeekOrigin.Begin); Console.WriteLine("AIS file generation was successful."); // --------------------------------------------------------- // ******************* END AIS GENERATION ****************** // --------------------------------------------------------- } #endregion // Now create return byte array based on AIS Stream data EndianBinaryReader tempAIS_br = new EndianBinaryReader(devAISGen.devAISStream,Endian.LittleEndian); numWords = ((UInt32)tempAIS_br.BaseStream.Length) >> 2; devAISGen.AISData = new Byte[numWords << 2]; //Each word converts to 4 binary bytes Debug.DebugMSG("Number of words in the stream is {0}", numWords); // Copy the data to the output Byte array for (UInt32 i = 0; i < numWords; i++) { BitConverter.GetBytes(tempAIS_br.ReadUInt32()).CopyTo(devAISGen.AISData, i * 4); } // Close the binary reader tempAIS_br.Close(); } // Dispose of all object files foreach (ObjectFile file in devAISGen.objectFiles) { try { file.Dispose(); } catch (Exception e) { Console.WriteLine(e.Message); } } // Clean up any embedded file resources that may have been extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); // Return Byte Array return devAISGen.AISData; }