using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace hex2img { class hex2img { private const UInt16 HEX_FILE_SIGN = 0x08AA; private const byte FILL_CHAR = 0xFF; private const byte ADDR_SIZE = sizeof(UInt16); private class SectionInfo { private UInt32 addr; private UInt16 len; public UInt32 Addr { get { return addr; } } public UInt16 Len { get { return len; } } public SectionInfo(UInt32 addr, UInt16 len) { this.addr = addr; this.len = len; } } private static UInt32 SwapUInt32(UInt32 dword) { return ((dword & 0x0000FFFF) << 16) | ((dword & 0xFFFF0000) >> 16); } static void Main(string[] args) { if (args.Length >= 2) { try { BinaryReader rd = new BinaryReader(File.Open(args[0], FileMode.Open)); UInt16 signature = rd.ReadUInt16(); if (signature == HEX_FILE_SIGN) { // skip 16 reserved double words rd.BaseStream.Seek(16, SeekOrigin.Current); // read enpty point UInt32 entryPt = rd.ReadUInt32(); UInt32 minAddr = UInt32.MaxValue; UInt32 maxAddr = UInt32.MinValue; UInt16 secLen; List secInfoList = new List(); do { // read section length secLen = (UInt16)(rd.ReadUInt16() * ADDR_SIZE); if (secLen > 0) { // read section start address UInt32 secAddr = SwapUInt32(rd.ReadUInt32()); secInfoList.Add(new SectionInfo(secAddr, secLen)); Console.WriteLine("Found section: addr 0x" + secAddr.ToString("X") + " size " + secLen.ToString() + " bytes"); rd.BaseStream.Seek(secLen, SeekOrigin.Current); if (minAddr > secAddr) { minAddr = secAddr; } if (maxAddr < secAddr + secLen) { maxAddr = secAddr + secLen; } } } while (secLen > 0); if (minAddr < maxAddr) { BinaryWriter wr = new BinaryWriter(File.Open(args[1], FileMode.Create)); // fill in output file with fill character UInt32 memSize = (maxAddr - minAddr) * ADDR_SIZE; for (UInt32 bt = 0; bt < memSize; ++bt) { wr.Write(FILL_CHAR); } // goto beginning of the section data (skip file signarute, reserved bytes, and entry point) rd.BaseStream.Seek(22, SeekOrigin.Begin); foreach (SectionInfo sectionInfo in secInfoList) { // skip section size and address rd.BaseStream.Seek(6, SeekOrigin.Current); // position output file pointer wr.BaseStream.Seek((sectionInfo.Addr - minAddr) * ADDR_SIZE, SeekOrigin.Begin); // copy data from input into output file byte[] arr = new byte[sectionInfo.Len]; rd.Read(arr, 0, sectionInfo.Len); wr.Write(arr, 0, sectionInfo.Len); } wr.Close(); Console.WriteLine("Image start address = 0x" + minAddr.ToString("X")); Console.WriteLine("Image end address = 0x" + maxAddr.ToString("X")); } else { Console.WriteLine("Invalid input file format"); } } else { Console.WriteLine("Invalid input file format"); } rd.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } else { Console.WriteLine("Invalid number of parameters! Usage: hex2img "); } } } }