Пример #1
0
        /// <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;
        }
Пример #2
0
        /// <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;
        }