Skip to content
Permalink
Browse files

Initial commit

  • Loading branch information...
Tim Horemans
Tim Horemans committed Dec 15, 2015
0 parents commit f777c7d1cc02441bcb9a66fcea960eddd7a2d40d
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HuaweiUpdateLibrary", "HuaweiUpdateLibrary\HuaweiUpdateLibrary.csproj", "{A34AA259-4277-41C9-8E21-700972DE46A6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{6EAC0262-14FC-4DDB-BD93-386339B10CD7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A34AA259-4277-41C9-8E21-700972DE46A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A34AA259-4277-41C9-8E21-700972DE46A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A34AA259-4277-41C9-8E21-700972DE46A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A34AA259-4277-41C9-8E21-700972DE46A6}.Release|Any CPU.Build.0 = Release|Any CPU
{6EAC0262-14FC-4DDB-BD93-386339B10CD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6EAC0262-14FC-4DDB-BD93-386339B10CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EAC0262-14FC-4DDB-BD93-386339B10CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EAC0262-14FC-4DDB-BD93-386339B10CD7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,73 @@
using System;
using System.Security.Cryptography;

namespace HuaweiUpdateLibrary.Algorithms
{
public class Crc16 : HashAlgorithm
{
private readonly ushort[] _table = new ushort[256];
private const ushort InitialSum = 0xFFFF;
private const ushort Polynomial = 0x8408;
private const ushort XorValue = 0xFFFF;

public override void Initialize()
{
for (ushort i = 0; i < _table.Length; ++i)
{
ushort value = 0;
var temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ Polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
_table[i] = value;
}
}

protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
var sum = InitialSum;
var i = ibStart;
var size = (cbSize - ibStart) * 8;

while (size >= 8)
{
var v = array[i++];
sum = (ushort)((_table[(v ^ sum) & 0xff] ^ (sum >> 8)) & 0xffff);
size -= 8;
}

if (size == 0)
{
HashValue = new [] {(byte) ((sum ^ XorValue) & 0xffff)};
HashSizeValue = 1;
return;
}

for (var n = array[i] << 8; ; n >>= 1)
{
if (size == 0) break;
size -= 1;
var flag = ((sum ^ n) & 1) == 0;
sum >>= 1;
if (flag) sum ^= Polynomial;
}

HashValue = new[] { (byte)((sum ^ XorValue) & 0xffff) };
HashSizeValue = 1;
}

protected override byte[] HashFinal()
{
return HashValue;
}
}
}
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace HuaweiUpdateLibrary
{
public class Class1
{
}
}
@@ -0,0 +1,31 @@
using System;
using System.Runtime.InteropServices;

namespace HuaweiUpdateLibrary.Core
{
// Credits: ZeBadger (zebadger@hotmail.com)
// For some stuff ripped from split_updata.pl

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct FileHeader
{
public UInt32 HeaderId;
public UInt32 HeaderSize;
public UInt32 Unknown1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] HardwareId;
public UInt32 FileSequence;
public UInt32 FileSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string FileDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string FileTime;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string FileType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public char[] Blank1;
public UInt16 HeaderChecksum;
public UInt16 BlockSize;
public UInt16 Blank2;
}
}
@@ -0,0 +1,247 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using HuaweiUpdateLibrary.Streams;

namespace HuaweiUpdateLibrary.Core
{
public class UpdateEntry
{
private const UInt32 FileMagic = 0xA55AAA55;

private FileHeader _fileHeader;
private readonly long _dataOffset;
private readonly ushort[] _checkSumTable;

private UpdateEntry(Stream stream, bool checksum = true)
{
var reader = new BinaryReader(stream);

// Read header
if (!Utilities.ByteToType(reader, out _fileHeader))
throw new Exception("ByteToType() failed @" + reader.BaseStream.Position);

// Check header magic
if (_fileHeader.HeaderId != FileMagic)
throw new Exception("Invalid file.");

// Validate checksum
if (checksum)
{

}

// Calculate checksum table size
var checksumTableSize = _fileHeader.HeaderSize - Marshal.SizeOf(typeof(FileHeader));

// Allocate checksum table
_checkSumTable = new ushort[checksumTableSize / sizeof(ushort)];

// Read checksum table
for (var count = 0; count < _checkSumTable.Length; count++) { _checkSumTable[count] = reader.ReadUInt16(); }

// Save position of file data
_dataOffset = stream.Position;
}

/// <summary>
/// Header Id
/// </summary>
public UInt32 HeaderId
{
get { return _fileHeader.HeaderId; }
}

/// <summary>
/// Header size
/// </summary>
public UInt32 HeaderSize
{
get { return _fileHeader.HeaderSize; }
}

/// <summary>
/// Hardware id
/// </summary>
public string HardwareId
{
get { return new string(_fileHeader.HardwareId);}
}

/// <summary>
/// File sequence
/// </summary>
public UInt32 FileSequence
{
get { return _fileHeader.FileSequence; }
}

/// <summary>
/// File size
/// </summary>
public UInt32 FileSize
{
get { return _fileHeader.FileSize; }
}

/// <summary>
/// File date
/// </summary>
public string FileDate
{
get { return _fileHeader.FileDate; }
}

/// <summary>
/// File time
/// </summary>
public string FileTime
{
get { return _fileHeader.FileTime; }
}

/// <summary>
/// File type
/// </summary>
public string FileType
{
get { return _fileHeader.FileType; }
}

/// <summary>
/// Header checksum
/// </summary>
public UInt16 HeaderChecksum
{
get { return _fileHeader.HeaderChecksum; }
}

/// <summary>
/// Block size
/// </summary>
public UInt16 BlockSize
{
get { return _fileHeader.BlockSize; }
}

/// <summary>
/// Read an <see cref="UpdateEntry"/> from a given <see cref="Stream"/>
/// </summary>
/// <param name="stream"><see cref="Stream"/> to read from</param>
/// <param name="checksum">Verify header checksum</param>
/// <returns><see cref="UpdateEntry"/></returns>
public static UpdateEntry Read(Stream stream, bool checksum = true)
{
return new UpdateEntry(stream, checksum);
}

/// <summary>
/// Get a <see cref="Stream"/> to the file data in the given <see cref="Stream"/>
/// </summary>
/// <param name="stream"><see cref="Stream"/> to read from</param>
/// <returns><see cref="Stream"/></returns>
public Stream GetDataStream(Stream stream)
{
// Seek to offset
stream.Seek(_dataOffset, SeekOrigin.Begin);

// Return stream
return new PartialStream(stream, FileSize);
}

/// <summary>
/// Get a <see cref="Stream"/> to the file data in the given file
/// </summary>
/// <param name="fileName">File to read from</param>
/// <returns><see cref="Stream"/></returns>
public Stream GetDataStream(string fileName)
{
var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

// Seek to offset
stream.Seek(_dataOffset, SeekOrigin.Begin);

// Return stream
return new PartialStream(stream, FileSize);
}

/// <summary>
/// Extract the current <see cref="UpdateEntry"/> from an input <see cref="Stream"/> to an output <see cref="Stream"/>
/// </summary>
/// <param name="input">Input <see cref="Stream"/></param>
/// <param name="output">Output <see cref="Stream"/></param>
/// <param name="checksum">Verify file data checksum</param>
public void Extract(Stream input, Stream output, bool checksum = true)
{
// Get stream to file data
var reader = GetDataStream(input);
var buffer = new byte[BlockSize];
var blockNumber = 0;
int size;

// Read file data
while ((size = reader.Read(buffer, 0, BlockSize)) > 0)
{
// Verify crc
if (checksum)
{
var crc = _checkSumTable[blockNumber];
}

// Write to output file
output.Write(buffer, 0, size);

// Increase block
blockNumber++;
}
}

/// <summary>
/// Extract the current <see cref="UpdateEntry"/> from an input <see cref="Stream"/> to an output file
/// </summary>
/// <param name="input">Input <see cref="Stream"/></param>
/// <param name="output">Output file</param>
/// <param name="checksum">Verify file data checksum</param>
public void Extract(Stream input, string output, bool checksum = true)
{
using (var outputStream = new FileStream(output, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Extract
Extract(input, outputStream, checksum);
}
}

/// <summary>
/// Extract the current <see cref="UpdateEntry"/> from an input file to an output <see cref="Stream"/>
/// </summary>
/// <param name="input">Input file</param>
/// <param name="output">Output <see cref="Stream"/></param>
/// <param name="checksum">Verify file data checksum</param>
public void Extract(string input, Stream output, bool checksum = true)
{
using (var inputStream = new FileStream(input, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Extract
Extract(inputStream, output, checksum);
}
}

/// <summary>
/// Extract the current <see cref="UpdateEntry"/> from an input file to an output file
/// </summary>
/// <param name="input">Input file</param>
/// <param name="output">Output file</param>
/// <param name="checksum">Verify file data checksum</param>
public void Extract(string input, string output, bool checksum = true)
{
using (var inputStream = new FileStream(input, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var outputStream = new FileStream(output, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Extract
Extract(inputStream, outputStream, checksum);
}
}
}
}
}

0 comments on commit f777c7d

Please sign in to comment.
You can’t perform that action at this time.