/// <summary> /// Secondary genAIS that calls the first /// </summary> /// <param name="mainObjectFileName">File name of .out file</param> /// <param name="bootmode">String containing desired boot mode</param> /// <returns>an Array of bytes to write to create an AIS file</returns> public static Byte[] GenAIS( AISGen devAISGen, List<String> inputFileNames, String bootmode, String iniData ) { devAISGen.bootMode = (AisBootModes)Enum.Parse(typeof(AisBootModes), bootmode, true); Console.WriteLine("Chosen bootmode is {0}.", devAISGen.bootMode.ToString()); return GenAIS(devAISGen, inputFileNames, iniData); }
/// <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; }
/// <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, String iniData ) { return GenAIS(devAISGen, inputFileNames, new IniFile(iniData)); }
public static ObjectFile FindObjectFile(AISGen devAISGen, String fileName) { foreach (ObjectFile file in devAISGen.objectFiles) { if (file.FileName.Equals(fileName)) { return file; } } return null; }
public static ObjectSymbol FindSymbol(AISGen devAISGen, String symbolName) { ObjectSymbol sym = null; foreach (ObjectFile file in devAISGen.objectFiles) { sym = file.symFind(symbolName); if (sym != null) break; } return sym; }
/// <summary> /// AIS COFF file Load command generation (loads all sections) /// </summary> /// <param name="cf">The COFFfile object that the section comes from.</param> /// <param name="devAISGen">The specific device AIS generator object.</param> /// <returns>retType enumerator indicating success or failure.</returns> private static retType AISSecureObjectFileLoad( AISGen devAISGen, ObjectFile file ) { UInt32 loadedSectionCount = 0; // Check if object file already loaded if (FindObjectFile(devAISGen,file.FileName) != null) { return retType.FAIL; } // Ii this is a new file, let's add it to our list devAISGen.objectFiles.Add(file); // Make sure we have an endianness match be // FIXME - Is this a good idea, what about binary files? if (!devAISGen.devEndian.ToString().Equals(file.Endianness)) { Console.WriteLine("Endianness mismatch. Device is {0} endian, Object file is {1} endian", devAISGen.devEndian.ToString(), file.Endianness); return retType.FAIL; } // Make sure the .TIBoot section is first (if it exists) ObjectSection firstSection = file.LoadableSections[0]; for (int i = 1; i < file.LoadableSectionCount; i++) { if ((file.LoadableSections[i].name).Equals(".TIBoot")) { file.LoadableSections[0] = file.LoadableSections[i]; file.LoadableSections[i] = firstSection; break; } } // Do all SECTION_LOAD commands for (Int32 i = 0; i < file.LoadableSectionCount; i++) { Boolean encryptSection = false; // Determine section encryption status if (devAISGen.sectionsToEncrypt != null) { if ( (devAISGen.sectionsToEncrypt.Length == 1) && devAISGen.sectionsToEncrypt[0].Equals("ALL")) { encryptSection = true; Console.WriteLine("Encrypting section {0}, since ALL was specified for encryptSections in ini file.",file.LoadableSections[i].name); } else { if ( Array.IndexOf(devAISGen.sectionsToEncrypt,file.LoadableSections[i].name) >= 0 ) { encryptSection = true; Console.WriteLine("Encrypting section {0}, since it was explicitly specified in encryptSections in ini file.",file.LoadableSections[i].name); } } } // Perform secure section load if (AISSecureSectionLoad(devAISGen, file, file.LoadableSections[i], encryptSection) != retType.SUCCESS) { return retType.FAIL; } // Check for need to do TIBoot initialization if ( (loadedSectionCount == 0) && ((file.LoadableSections[i].name).Equals(".TIBoot")) ) { devAISGen.InsertAISJump("_TIBootSetup"); InsertAISSecureSignature(devAISGen); } loadedSectionCount++; } // End of SECTION_LOAD commands // Now that we are done with file contents, we can close it file.Close(); return retType.SUCCESS; }
public static ObjectFile FindFileWithSymbol(AISGen devAISGen, String symbolName) { foreach (ObjectFile file in devAISGen.objectFiles) { if (file.symFind(symbolName) != null) { return file; } } return null; }
private static retType AISObjectFileLoad( AISGen devAISGen, ObjectFile file ) { UInt32 loadedSectionCount = 0; // Check if object file already loaded if (FindObjectFile(devAISGen,file.FileName) != null) { return retType.FAIL; } // If this is a new file, let's add it to our list devAISGen.objectFiles.Add(file); if (!devAISGen.devEndian.ToString().Equals(file.Endianness)) { Console.WriteLine("Endianness mismatch. Device is {0} endian, Object file is {1} endian", devAISGen.devEndian.ToString(), file.Endianness); return retType.FAIL; } // Make sure the .TIBoot section is first (if it exists) ObjectSection firstSection = file.LoadableSections[0]; for (Int32 i = 1; i < file.LoadableSectionCount; i++) { if ((file.LoadableSections[i].name).Equals(".TIBoot")) { file.LoadableSections[0] = file.LoadableSections[i]; file.LoadableSections[i] = firstSection; break; } } // Enable CRC if needed devAISGen.InsertAISEnableCRC(); // Do all SECTION_LOAD commands for (Int32 i = 0; i < file.LoadableSectionCount; i++) { if (AISSectionLoad(devAISGen, file, file.LoadableSections[i]) != retType.SUCCESS) { return retType.FAIL; } // Check for need to do TIBoot initialization if (loadedSectionCount == 0) { devAISGen.InsertAISJump("_TIBootSetup"); } loadedSectionCount++; } // End of SECTION_LOAD commands // Now that we are done with file contents, we can close it file.Close(); return retType.SUCCESS; }
private static retType AISSectionLoad( AISGen devAISGen, ObjectFile file, ObjectSection section) { Byte[] secData = file.secRead(section); Byte[] srcCRCData = new Byte[section.size + 8]; Debug.DebugMSG("AISSectionLoad for section " + section.name + " from file " + file.FileName + "."); // If we are doing section-by-section CRC, then zero out the CRC value if (devAISGen.aisCRCType == AisCRCCheckType.SECTION_CRC) { devAISGen.devCRC.ResetCRC(); } // Add section load to the output devAISGen.InsertAISSectionLoad((UInt32) section.loadAddr, (UInt32) section.size, secData); // Copy bytes to CRC byte array for future CRC calculation if (devAISGen.aisCRCType != AisCRCCheckType.NO_CRC) { if (devAISGen.devEndian != devAISGen.devAISEndian) { Endian.swapEndian(BitConverter.GetBytes(section.loadAddr)).CopyTo(srcCRCData, 0); Endian.swapEndian(BitConverter.GetBytes(section.size)).CopyTo(srcCRCData, 4); } else { BitConverter.GetBytes(section.loadAddr).CopyTo(srcCRCData, 0); BitConverter.GetBytes(section.size).CopyTo(srcCRCData, 4); } } // Now write contents to CRC array for (UInt32 k = 0; k < section.size; k+=4) { // Copy bytes to array for future CRC calculation if (devAISGen.aisCRCType != AisCRCCheckType.NO_CRC) { Byte[] temp = new Byte[4]; Array.Copy(secData,k,temp,0,4); if (devAISGen.devEndian != devAISGen.devAISEndian) { Endian.swapEndian(temp).CopyTo(srcCRCData, (8 + k)); } else { temp.CopyTo(srcCRCData, (8 + k)); } } } // Add this section's memory range, checking for overlap AddMemoryRange(devAISGen, (UInt32) section.loadAddr, (UInt32) (section.loadAddr+section.size-1)); // Perform CRC calculation of the section's contents if (devAISGen.aisCRCType != AisCRCCheckType.NO_CRC) { devAISGen.devCRC.CalculateCRC(srcCRCData); if (devAISGen.aisCRCType == AisCRCCheckType.SECTION_CRC) { // Write CRC request command, value, and jump value to temp AIS file devAISGen.InsertAISRequestCRC(((Int32)(-1) * (Int32)(section.size + 12 + 12))); } } 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; }
private static void AddMemoryRange(AISGen devAISGen, UInt32 startAddr, UInt32 endAddr) { // Cycle through entire list looking for overlaps foreach (MemoryRange m in devAISGen.sectionMemory) { // Three issues: // 1) Both fall in occupied memory // 2) Input startAddr falls in occuppied memory, input endAddr does not // 3) Input endAddr falls in occuppied memory if ( ( (startAddr >= m.startAddr) && (startAddr <= m.endAddr) ) && ( (endAddr >= m.startAddr) && (endAddr <= m.endAddr) ) ) { Console.WriteLine("WARNING: Memory overlap from 0x{0:X8} to 0x{1:X8}.",startAddr, endAddr); continue; } if ( (startAddr >= m.startAddr) && (startAddr <= m.endAddr) && (endAddr > m.endAddr) ) { Console.WriteLine("WARNING: Memory overlap from 0x{0:X8} to 0x{1:X8}.",startAddr, m.endAddr); continue; } if ( (startAddr < m.startAddr) && (endAddr >= m.startAddr) && (endAddr <= m.endAddr) ) { Console.WriteLine("WARNING: Memory overlap from 0x{0:X8} to 0x{1:X8}.",m.startAddr, endAddr); continue; } } // Add the MemoryRange for this section to the list devAISGen.sectionMemory.Add(new MemoryRange(startAddr,endAddr)); }
private static retType SecurityIniSectionParse(AISGen devAISGen, IniFile iniFile) { String currHashAlgorithmString = "SHA1"; // Default hash algorithm // Get data from the GENERAL INI Section IniSection sec = iniFile.GetSectionByName("Security"); #region INI Section parsing if (sec != null) { foreach (DictionaryEntry de in sec.sectionValues) { // Security Type if (((String)de.Key).Equals("SECURITYTYPE", StringComparison.OrdinalIgnoreCase)) { devAISGen.SecureType = (AisSecureType) Enum.Parse(typeof(AisSecureType), (String)sec.sectionValues["SECURITYTYPE"], true); } // Boot exit type if (((String)de.Key).Equals("BOOTEXITTYPE", StringComparison.OrdinalIgnoreCase)) { devAISGen.bootLoaderExitType = (BootLoaderExitType) Enum.Parse(typeof(BootLoaderExitType), (String)sec.sectionValues["BOOTEXITTYPE"], true); } // Encrypted section settings if (((String)de.Key).Equals("ENCRYPTSECTIONS", StringComparison.OrdinalIgnoreCase)) { Char[] separators = new Char[]{','}; String encryptSections = (String)sec.sectionValues["ENCRYPTSECTIONS"]; devAISGen.sectionsToEncrypt = encryptSections.Split(separators,StringSplitOptions.RemoveEmptyEntries); for( int k = 0; k<devAISGen.sectionsToEncrypt.Length; k++) { devAISGen.sectionsToEncrypt[k] = devAISGen.sectionsToEncrypt[k].Trim(); } } // AES Encryption Key (CEK) if (((String)de.Key).Equals("ENCRYPTIONKEY", StringComparison.OrdinalIgnoreCase)) { devAISGen.customerEncryptionKey = new Byte[16]; devAISGen.rootCustomerEncryptionKey = null; devAISGen.CEKInitialValue = new Byte[16]; devAISGen.rootCEKInitialValue = null; String keyString = (String)sec.sectionValues["ENCRYPTIONKEY"]; if (keyString.Length != 32) { Console.WriteLine("AES Encryption Key is wrong length!"); return retType.FAIL; } for (int j=0; j<keyString.Length; j+=2) { devAISGen.customerEncryptionKey[(j>>1)] = Convert.ToByte(keyString.Substring(j,2),16); } // Save base CEK key for restoring after delegate key removal devAISGen.rootCustomerEncryptionKey = devAISGen.customerEncryptionKey; // Generate IV as encrypted version of AES Key using (MemoryStream ms = new MemoryStream(devAISGen.CEKInitialValue)) { Aes myAES = new AesManaged(); myAES.KeySize = 128; myAES.Mode = CipherMode.ECB; myAES.Padding = PaddingMode.None; ICryptoTransform encryptor = myAES.CreateEncryptor(devAISGen.customerEncryptionKey, new Byte[16]); CryptoStream cs = new CryptoStream(ms,encryptor,CryptoStreamMode.Write); cs.Write(devAISGen.customerEncryptionKey,0,devAISGen.customerEncryptionKey.Length); } devAISGen.rootCEKInitialValue = devAISGen.CEKInitialValue; } // Key Encryption Key (not normally known, here for debug/testing purposes) if (((String)de.Key).Equals("KEYENCRYPTIONKEY", StringComparison.OrdinalIgnoreCase)) { devAISGen.keyEncryptionKey = new Byte[16]; String keyString = (String)sec.sectionValues["KEYENCRYPTIONKEY"]; if (keyString.Length != 32) { Console.WriteLine("Key Encryption Key is wrong length!"); return retType.FAIL; } for (int j=0; j<keyString.Length; j+=2) { devAISGen.keyEncryptionKey[(j>>1)] = Convert.ToByte(keyString.Substring(j,2),16); } } // Generic Secure Option to force JTAG off as part of the key loading if (((String)de.Key).Equals("GENERICJTAGFORCEOFF", StringComparison.OrdinalIgnoreCase)) { if (((String)sec.sectionValues["GENERICJTAGFORCEOFF"]).Equals("TRUE", StringComparison.OrdinalIgnoreCase)) devAISGen.genericJTAGForceOff = true; else devAISGen.genericJTAGForceOff = false; } // Generic Secure Option to select the hash algorithm for signatures if (((String)de.Key).Equals("GENERICSHASELECTION", StringComparison.OrdinalIgnoreCase)) { currHashAlgorithmString = (String)sec.sectionValues["GENERICSHASELECTION"]; devAISGen.currHashAlgorithmValue = (SHA_Algorithm) Enum.Parse(typeof(SHA_Algorithm), currHashAlgorithmString, true); } // Generic Key Header file if (((String)de.Key).Equals("GENKEYHEADERFILENAME", StringComparison.OrdinalIgnoreCase)) { String genKeyHeaderFileName = (String)sec.sectionValues["GENKEYHEADERFILENAME"]; devAISGen.genericKeyHeaderData = new Byte[32]; // Open file, read contents, copy to our AIS array using (FileStream tempFS = new FileStream(genKeyHeaderFileName, FileMode.Open, FileAccess.Read)) { tempFS.Read(devAISGen.genericKeyHeaderData,0,32); } } // Custom Secure RSA Key File if (((String)de.Key).Equals("RSAKEYFILENAME", StringComparison.OrdinalIgnoreCase)) { String rsaKeyFileName = (String)sec.sectionValues["RSAKEYFILENAME"]; devAISGen.rsaObject = RSAKey.LoadFromFile(rsaKeyFileName); devAISGen.rootRsaObject = null; if (devAISGen.rsaObject == null) { Console.WriteLine("RSA key loading failed!"); return retType.FAIL; } // Update the hash algo string if RSA key size is 2048 bits if (devAISGen.rsaObject.KeySize == 2048) { currHashAlgorithmString = "SHA256"; devAISGen.currHashAlgorithmValue = SHA_Algorithm.SHA256; } // Save root public key reference for use after delegate key removal devAISGen.rootRsaObject = devAISGen.rsaObject; } } } else { sec = iniFile.GetSectionByName("SecureLegacy"); if (sec != null) { devAISGen.bootMode = AisBootModes.LEGACY; } else { Console.WriteLine("INI file is missing a SECURITY or SECURELEGACY section."); return retType.FAIL; } } #endregion #region Security INI Input Validation // 2) Make sure a secure type has been specified if (devAISGen.SecureType == AisSecureType.NONE) { Console.WriteLine("ERROR: The device's security type was not specified!"); return retType.FAIL; } else { Console.WriteLine("Creating boot image for a {0} secure device.",devAISGen.SecureType.ToString().ToLower()); // 3) Make sure we have a CEK and IV if (devAISGen.customerEncryptionKey == null) { Console.WriteLine("ERROR: No encryption key was specified!"); return retType.FAIL; } // 4) If custom secure, make sure we have an rsaObject if ((devAISGen.SecureType == AisSecureType.CUSTOM) && (devAISGen.rsaObject == null)) { Console.WriteLine("ERROR: No RSA key file was specified!"); return retType.FAIL; } // 5) Make sure RSA key size is supported if ((devAISGen.SecureType == AisSecureType.CUSTOM) && (devAISGen.rsaObject != null)) { if ( (devAISGen.rsaObject.KeySize != 1024) && (devAISGen.rsaObject.KeySize != 2048) ) { Console.WriteLine("ERROR: No RSA key size is invalid!"); return retType.FAIL; } else { Console.WriteLine("INFO: RSA key is {0} bits.",devAISGen.rsaObject.KeySize); } } // 6) Specify Boot Exit type (if not legacy boot) if (devAISGen.bootMode != AisBootModes.LEGACY) { if (devAISGen.bootLoaderExitType == BootLoaderExitType.NONE) { Console.WriteLine("ERROR: No boot loader exit type was specified!"); return retType.FAIL; } else { Console.WriteLine("INFO: Boot exit type has been selected as {0}.",devAISGen.bootLoaderExitType); } } // 7) If generic secure, make sure we have the CEK header info (or KEK though that's not typical use-case) if ( (devAISGen.SecureType == AisSecureType.GENERIC) && (devAISGen.genericKeyHeaderData == null) && (devAISGen.keyEncryptionKey == null) ) { Console.WriteLine("WARNING: Encrypted Key Header data is absent - generating plaintext version. "); Console.WriteLine(" The Customer Encryption Key will be transferred in plaintext! "); } // 8) Give warning if generic device and no sections are specified for encryption if (devAISGen.bootMode != AisBootModes.LEGACY) { if ((devAISGen.SecureType == AisSecureType.GENERIC) && (devAISGen.sectionsToEncrypt == null)) { Console.WriteLine("WARNING: Generic Secure device was specified, but no input sections were indicated for encryption."); Console.WriteLine(" Only boot image signing will take place."); } } } // 9) Make sure valid hash algorithm was selected try { devAISGen.currHashAlgorithm = HashAlgorithm.Create(currHashAlgorithmString); Console.WriteLine("INFO: Current SHA algorithm is {0}.",devAISGen.currHashAlgorithmValue); } catch (Exception e) { Console.WriteLine("Invalid Hash Algorithm Selected. Exception message: {0}.",e.Message); return retType.FAIL; } #endregion #region Secure data/structure creation if ( devAISGen.SecureType == AisSecureType.GENERIC ) { // Create our own key header devAISGen.secureKeyData = new Byte[32]; Byte[] tempHeaderData = new Byte[32]; // Init with Random Data (new Random()).NextBytes(tempHeaderData); // Copy in the magic word for the generic key header structure BitConverter.GetBytes((UInt32)SecureLoadMagic.GENKEY_MAGIC).CopyTo(tempHeaderData, 0); // Insert JTAGForceOff word BitConverter.GetBytes( (UInt32) (devAISGen.genericJTAGForceOff ? 0x00000001 : 0x00000000) ).CopyTo(tempHeaderData, 4); // Insert Hash algorithm selection word BitConverter.GetBytes( (UInt32)devAISGen.currHashAlgorithmValue ).CopyTo(tempHeaderData, 8); // Insert key Data (at offset 16) devAISGen.customerEncryptionKey.CopyTo(tempHeaderData, 16); // If KEK is provided, use it to generate the header for the boot image if (devAISGen.keyEncryptionKey != null) { Byte[] iv = new Byte[16]; using (MemoryStream ms = new MemoryStream(iv)) { Aes myAES = new AesManaged(); myAES.KeySize = 128; myAES.Mode = CipherMode.ECB; myAES.Padding = PaddingMode.None; ICryptoTransform encryptor = myAES.CreateEncryptor(devAISGen.keyEncryptionKey, new Byte[16]); CryptoStream cs = new CryptoStream(ms,encryptor,CryptoStreamMode.Write); cs.Write(devAISGen.keyEncryptionKey,0,devAISGen.keyEncryptionKey.Length); } Byte[] encSecureKeyData = new Byte[32]; using (MemoryStream ms = new MemoryStream(encSecureKeyData)) { Aes myAES = new AesManaged(); myAES.KeySize = 128; myAES.Mode = CipherMode.CBC; myAES.Padding = PaddingMode.None; ICryptoTransform encryptor = myAES.CreateEncryptor(devAISGen.keyEncryptionKey, iv); CryptoStream cs = new CryptoStream(ms,encryptor,CryptoStreamMode.Write); cs.Write(tempHeaderData,0,32); } //#if (DEBUG) // For debug write the data out to file FileIO.SetFileData("gen_keyhdr_unencrypted.bin",tempHeaderData,true); FileIO.SetFileData("gen_keyhdr_encrypted.bin",encSecureKeyData,true); //#endif Array.Copy(encSecureKeyData,0,devAISGen.secureKeyData,0,32); } // We have a file being provided - use first 32 bytes of it else if ((devAISGen.genericKeyHeaderData != null) && (devAISGen.genericKeyHeaderData.Length >= 32)) { Array.Copy(devAISGen.genericKeyHeaderData,0,devAISGen.secureKeyData,0,32); } // There is no KEK to create an encrypted header and no file is provided with key data // so let's just use our own unencrypted data else { Array.Copy(tempHeaderData,0,devAISGen.secureKeyData,0,32); } } else if ( devAISGen.SecureType == AisSecureType.CUSTOM ) { // Create RPK Verify Struct devAISGen.secureKeyData = RSAKey.CreateCustomSecureKeyVerifyStruct(devAISGen.rsaObject); #if (DEBUG) // For debug write the data out to file FileIO.SetFileData("rpk_struct.bin",devAISGen.secureKeyData,true); // Calculate the SHA hash of the Root Public Key Byte[] digest = devAISGen.currHashAlgorithm.ComputeHash(devAISGen.secureKeyData); // Write the full hash of the RPK struct // For debug write the data out to file FileIO.SetFileData("rpk_hash_full.bin",digest,true); for (int i=16;i<digest.Length;i++) { digest[i-16] ^= digest[i]; } // Write the expected MPK (hash of RPK structure truncated to 128 bits) in binary format to file mpk.bin Byte[] mpk = new Byte[16]; Array.Copy(digest,0,mpk,0,16); // For debug write the data out to file FileIO.SetFileData("mpk.bin",mpk,true); #endif } #endregion return retType.SUCCESS; }
/// <summary> /// Signature insertion creation and insertion routine /// </summary> public static retType InsertAISSecureSignature( AISGen devAISGen ) { EndianBinaryWriter ebw = new EndianBinaryWriter( devAISGen.devAISStream, devAISGen.devEndian); // Make sure all data is present for signature calculation devAISGen.sigStream.Flush(); // Reset stream to start devAISGen.sigStream.Position = 0; #if (DEBUG) // For debug write the data out to file Byte[] sigData = null; sigData = ((MemoryStream) devAISGen.sigStream).ToArray(); FileIO.SetFileData("sig_data.bin",sigData,true); #endif // Calculate hash of data Byte[] hash = devAISGen.currHashAlgorithm.ComputeHash(devAISGen.sigStream); Console.WriteLine("\tSignature Hash: {0}", BitConverter.ToString(hash)); Console.WriteLine("\tSignature Byte Count = {0}", devAISGen.sigStream.Length); Byte[] signatureData = null; // Generate signature via encryption if ( devAISGen.SecureType == AisSecureType.GENERIC ) { signatureData = new Byte[32]; // Fill signature data buffer with random bytes (new Random()).NextBytes(signatureData); // Copy calculated SHA hash into signature data buffer hash.CopyTo(signatureData,0); using (MemoryStream ms = new MemoryStream()) { Aes myAES = new AesManaged(); myAES.KeySize = 128; myAES.Mode = CipherMode.CBC; myAES.Padding = PaddingMode.None; ICryptoTransform encryptor = myAES.CreateEncryptor(devAISGen.customerEncryptionKey, devAISGen.CEKInitialValue); CryptoStream cs = new CryptoStream(ms,encryptor,CryptoStreamMode.Write); cs.Write(signatureData,0,signatureData.Length); cs.FlushFinalBlock(); ms.ToArray().CopyTo(signatureData,0); } } else if ( devAISGen.SecureType == AisSecureType.CUSTOM ) { RSAPKCS1SignatureFormatter rsaFormatter = new RSAPKCS1SignatureFormatter(devAISGen.rsaObject); // Create a signature for HashValue and return it. signatureData = rsaFormatter.CreateSignature(devAISGen.currHashAlgorithm); // Signature info needs to be revered to work with RSA functionality in ROM Array.Reverse(signatureData); } // Write the signature data to the output AIS binary writer ebw.Write(signatureData); // Clear the signature stream now that we have used the data for signature generation devAISGen.sigStream.SetLength(0); devAISGen.sigStream.Position = 0; return retType.SUCCESS; }
/// <summary> /// AIS Section Load command generation /// </summary> /// <param name="cf">The COFFfile object that the section comes from.</param> /// <param name="secHeader">The Hashtable object of the section header to load.</param> /// <param name="devAISGen">The specific device AIS generator object.</param> /// <returns>retType enumerator indicating success or failure.</returns> private static retType AISSecureSectionLoad( AISGen devAISGen, ObjectFile file, ObjectSection section, Boolean encryptSection) { Byte[] secData = file.secRead(section); // Write Section_Load AIS command, load address, and size if (encryptSection) { Byte[] encData = null; // Encrypt data using CTS algorithm try { encData = AesManagedUtil.AesCTSEncrypt(secData,devAISGen.customerEncryptionKey,devAISGen.CEKInitialValue); } catch(Exception e) { Console.WriteLine("Exception during encryption operation: {0}",e.Message); return retType.FAIL; } if (encData != null) { devAISGen.InsertAISEncSectionLoad((UInt32) section.loadAddr, (UInt32) section.size, secData, encData); } else { Console.WriteLine("Section encryption failed."); return retType.FAIL; } } else { devAISGen.InsertAISSectionLoad((UInt32) section.loadAddr, (UInt32) section.size, secData); } // Add this section's memory range, checking for overlap AddMemoryRange(devAISGen, (UInt32) section.loadAddr, (UInt32) (section.loadAddr+section.size-1)); return retType.SUCCESS; }
/// <summary> /// Secondary genAIS that calls the first /// </summary> /// <param name="mainObjectFileName">File name of .out file</param> /// <param name="bootmode">AISGen.AisBootModes Enum value containing desired boot mode</param> /// <returns>an Array of bytes to write to create an AIS file</returns> public static Byte[] GenAIS( AISGen devAISGen, List<String> inputFileNames, AisBootModes bootmode, String iniData ) { devAISGen.bootMode = bootmode; Console.WriteLine("Chosen bootmode is {0}.", devAISGen.bootMode.ToString()); return GenAIS(devAISGen, inputFileNames, iniData); }
private static void GeneralIniSectionParse(AISGen devAISGen, IniFile iniFile) { // Get data from the GENERAL INI Section IniSection genSec = iniFile.GetSectionByName("General"); foreach (DictionaryEntry de in genSec.sectionValues) { // Read buswidth if (((String)de.Key).Equals("BUSWIDTH", StringComparison.OrdinalIgnoreCase)) devAISGen.busWidth = (UInt32)genSec.sectionValues["BUSWIDTH"]; // Read BootMode (unless already set) if ((((String)de.Key).Equals("BOOTMODE", StringComparison.OrdinalIgnoreCase)) && (devAISGen.bootMode == AisBootModes.NONE)) devAISGen.bootMode = (AisBootModes) Enum.Parse(typeof(AisBootModes), (String)genSec.sectionValues["BOOTMODE"], true); // Read Addr width (for I2C/SPI) if (((String)de.Key).Equals("ADDRWIDTH", StringComparison.OrdinalIgnoreCase)) { devAISGen.addrWidth = (UInt32)genSec.sectionValues["ADDRWIDTH"]; } // CRC Type override if (((String)de.Key).Equals("CRCCheckType", StringComparison.OrdinalIgnoreCase)) { devAISGen.AISCRCType = (AisCRCCheckType) Enum.Parse(typeof(AisCRCCheckType), (String)genSec.sectionValues["CRCCHECKTYPE"], true); } // Read global entry point if (((String)de.Key).Equals("ENTRYPOINT", StringComparison.OrdinalIgnoreCase)) { devAISGen.entryPoint = (UInt32)genSec.sectionValues["ENTRYPOINT"]; } } }
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> /// Secondary genAIS thats calls the first /// </summary> /// <param name="inputFileNames">File name of .out file</param> /// <param name="bootmode">AISGen.AisBootModes Enum value containing desired boot mode</param> /// <returns>an Array of bytes to write to create an AIS file</returns> public static Byte[] SecureGenAIS(AISGen devAISGen, List<String> inputFileNames, AisBootModes bootmode, String iniData) { return SecureGenAIS(devAISGen, inputFileNames, bootmode, new IniFile(iniData)); }