/// <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; }
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; }