using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Phihong_EVSE_UI_Tool { public class FirmwareHeaderBuilder { public static void AddFirmwareHeader(string temZipPath, string modelName, string outputFilePath) { var modelNameArray = Encoding.ASCII.GetBytes(modelName); var imageDataArray = File.ReadAllBytes(temZipPath); byte[] dataSegment1 = new byte[16]; byte[] dataSegment2 = new byte[16]; byte[] dataSegment3 = new byte[16]; Array.Clear(dataSegment1, 0, 16); for (int i = 0; i < 16; i++) { dataSegment2[i] = 0xFF; dataSegment3[i] = 0xFF; } var Lcm_Type = new byte[] { 0x10, 0x00, 0x00, 0x0F }; // 0000h Array.Copy(modelNameArray, 0, dataSegment1, 0, modelNameArray.Length); // 0001h byte[] imgLenBytes = GetImgLenBytes(imageDataArray); byte[] timeBytes = GetCreateTimeBytes(); //Array.Copy(imageType.CodeArray, 0, dataSegment2, 0, 4); Array.Copy(Lcm_Type, 0, dataSegment2, 0, 4); Array.Copy(imgLenBytes, 0, dataSegment2, 4, 4); Array.Copy(timeBytes, 0, dataSegment2, 8, 8); // 0002h Array.Copy(timeBytes, 8, dataSegment3, 0, 2); byte[] crcBytes = GetCRC32(dataSegment1, dataSegment2, dataSegment3, imageDataArray); Array.Copy(crcBytes, 0, dataSegment3, 2, 4); List contents = new List(); contents.AddRange(dataSegment1); contents.AddRange(dataSegment2); contents.AddRange(dataSegment3); contents.AddRange(imageDataArray); File.WriteAllBytes(outputFilePath, contents.ToArray()); } private static byte[] GetImgLenBytes(byte[] imageArray) { // Big Endian byte[] imgLenBytes = BitConverter.GetBytes(imageArray.Length); Array.Reverse(imgLenBytes); return imgLenBytes; } private static byte[] GetCreateTimeBytes() { string strTime = DateTime.Now.ToString("yyyyMMddHH"); return Encoding.ASCII.GetBytes(strTime); } private static byte[] GetCRC32(byte[] segment1, byte[] segment2, byte[] segment3, byte[] imageArray) { var crc32Handler = CRC32.GetInatance(); List crcData = new List(); crcData.AddRange(segment1); crcData.AddRange(segment2); crcData.AddRange(new byte[] { segment3[0], segment3[1] }); crcData.AddRange(imageArray); ulong crc32 = crc32Handler.Calculate(crcData.ToArray(), crcData.Count); // Big Endian byte[] outcome = new byte[4]; outcome[0] = (byte)((crc32 & 0xFF000000) >> 24); outcome[1] = (byte)((crc32 & 0x00FF0000) >> 16); outcome[2] = (byte)((crc32 & 0x0000FF00) >> 8); outcome[3] = (byte)(crc32 & 0x000000FF); return outcome; } } class CRC32 { private static CRC32 inatance; /// 取得實體。 /// public static CRC32 GetInatance() { if (inatance == null) { inatance = new CRC32(); } return inatance; } private ulong[] crc32Table; /// 初始化 CRC32 類別的新執行個體。 private CRC32() { crc32Table = new ulong[256]; GetCRC32Table(); } /// 計算。 /// /// /// public ulong Calculate(byte[] dataArray, int length) { ulong crc = 0xFFFFFFFF; for (int i = 0; i < length; i++) { crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ dataArray[i]]; } return crc ^ 0xFFFFFFFF; } private void GetCRC32Table() { ulong crc; int i, j; for (i = 0; i < 256; i++) { crc = (ulong)i; for (j = 8; j > 0; j--) { if ((crc & 1) == 1) { crc = (crc >> 1) ^ 0xEDB88320; } else { crc >>= 1; } } crc32Table[i] = crc; } } } }