Skip to content

Commit

Permalink
fix bootloader packets structure; add beacon for bootloader 5.00.01
Browse files Browse the repository at this point in the history
  • Loading branch information
qrp73 committed Jul 22, 2024
1 parent 86feb41 commit ddb712a
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 91 deletions.
4 changes: 2 additions & 2 deletions AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.5.2.0")]
[assembly: AssemblyFileVersion("1.5.2.0")]
[assembly: AssemblyVersion("1.6.0.0")]
[assembly: AssemblyFileVersion("1.6.0.0")]
46 changes: 36 additions & 10 deletions CommandHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,21 +236,29 @@ public static bool WriteFlashUnpacked(Device device, string version, string file
return CommandHelper.WriteFlash(device, version, data);
}

private static uint GenerateId()
{
var random = new Random();
return (uint)random.Next(1, int.MaxValue);
}

public static bool WriteFlash(Device device, string version, byte[] data)
{
if (data.Length > 0x10000)
throw new ArgumentOutOfRangeException("data.Length");
var offsetFinal = (ushort)data.Length;
if ((offsetFinal & 0xff) != 0)
offsetFinal = (ushort)((offsetFinal + 0x100) & 0xff00);
const int chunkSize = 0x100;
var chunkCount = (ushort)(data.Length / chunkSize);
if ((data.Length % chunkSize) != 0)
chunkCount++;
var offsetFinal = chunkCount * chunkSize;
if (offsetFinal > FirmwareConstraints.MaxFlashAddr + 1)
throw new InvalidOperationException(
string.Format(
"DANGEROUS FLASH ADDRESS WRITE! size=0x{0:x4}, offsetFinal=0x{1:x4}",
data.Length,
offsetFinal));

Console.WriteLine("Write FLASH size=0x{0:x4}, offsetFinal=0x{1:x4}", data.Length, offsetFinal);
Console.WriteLine("Write FLASH size=0x{0:x4}", data.Length);
Console.WriteLine("Waiting for bootloader beacon...");
var packet = device.Recv();
var pktBeacon = packet as PacketFlashBeaconAck;
Expand All @@ -260,6 +268,11 @@ public static bool WriteFlash(Device device, string version, byte[] data)
return false;
}
Console.WriteLine(" Bootloader: {0}", pktBeacon.Version);
if (pktBeacon.HdrId != PacketFlashBeaconAck.ID)
{
Logger.Error("Sorry, this bootloader is not supported yet");
return false;
}
var pktVersion = version != null ?
new PacketFlashVersionReq(version) :
new PacketFlashVersionReq();
Expand All @@ -274,35 +287,48 @@ public static bool WriteFlash(Device device, string version, byte[] data)
}
Console.WriteLine(" Bootloader: {0}", pktBeacon.Version);

return ProcessAddressSpace(0x0000, data.Length, 0x100, FirmwareConstraints.MinFlashAddr, FirmwareConstraints.MaxFlashAddr, MaxFlashBlock,
var seqId = GenerateId();

return ProcessAddressSpace(0x0000, data.Length, chunkSize, FirmwareConstraints.MinFlashAddr, FirmwareConstraints.MaxFlashAddr, MaxFlashBlock,
(absOffset, blockOffset, blockLength) => {
Console.Write(" Write {0:x4}...{1:x4}: ", absOffset, absOffset + blockLength);
var subData = new byte[blockLength];
Array.Copy(data, blockOffset, subData, 0, subData.Length);
device.Send(new PacketFlashWriteReq((ushort)absOffset, offsetFinal, subData));
var chunkNumber = (ushort)(absOffset / chunkSize);
device.Send(new PacketFlashWriteReq(chunkNumber, chunkCount, subData, seqId));
//Packet packet;
for (; ; )
for (var counter=0; ; counter++)
{
packet = device.Recv();
if (packet is PacketFlashBeaconAck)
Console.Write("[beacon]");
else
break;
if (counter > 10)
{
Logger.Error("No response");
return false;
}
}
var wrpacket = packet as PacketFlashWriteAck;
if (wrpacket == null)
{
Logger.Error("Unexpected response {0}", packet);
return false;
}
if (wrpacket.Offset != absOffset)
if (wrpacket.Result != 0)
{
Logger.Error("Write failed with error code {0}", wrpacket.Result);
return false;
}
if (wrpacket.ChunkNumber != chunkNumber)
{
Logger.Warn("Unexpected offset in response {0}", packet);
Logger.Warn("Unexpected ChunkNumber in response {0}", packet);
return false;
}
//if (wrpacket.Id != id)
//{
// Logger.Warn("Unexpected response Id (0x{0:x8}!=0x{1:x8})", wrpacket.Id, id);
// Logger.Warn("Unexpected response Id (0x{0:x8}!=0x{1:x8})", wrpacket.SequenceId, id);
//}
Console.WriteLine("OK");
return true;
Expand Down
4 changes: 3 additions & 1 deletion Packets/Packet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ public static Packet Deserialize(byte[] data)
case PacketFlashVersionReq.ID: return new PacketFlashVersionReq(data);
case PacketFlashWriteAck.ID: return new PacketFlashWriteAck(data);
case PacketFlashWriteReq.ID: return new PacketFlashWriteReq(data);

// bootloader 5.00.01
case PacketFlashBeaconAck.ID2: return new PacketFlashBeaconAck(data);

// firmware
case PacketHelloAck.ID: return new PacketHelloAck(data);
case PacketHelloReq.ID: return new PacketHelloReq(data);
Expand Down
58 changes: 47 additions & 11 deletions Packets/PacketFlashBeaconAck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@ You should have received a copy of the GNU General Public License

namespace K5TOOL.Packets
{
// bootloader 2:
// can be 20 bytes or 36 bytes
// for 20 bytes there is no version
//
public class PacketFlashBeaconAck : Packet
{
public const ushort ID = 0x0518;
public const ushort ID2 = 0x057a;

public PacketFlashBeaconAck(byte[] rawData)
: base(rawData)
{
if (base.HdrId != ID)
if (base.HdrId != ID && base.HdrId != ID2)
throw new InvalidOperationException();
if (base.HdrSize < 18 || base.HdrSize > 50)
{
Expand All @@ -46,17 +51,40 @@ public PacketFlashBeaconAck(byte[] rawData)
}
}

// bootloader 2.00.06
// 18 05 20 00
// 01 02 02 0B 0C 53 46 34 52 59 FF 08 8C 00 32 00
// 32 2E 30 30 2E 30 36 00 34 0A 00 00 00 00 00 20
public PacketFlashBeaconAck()
: this(new byte[] {
0x18,0x05,0x20,0x00,0x01,0x02,0x02,0x0b,0x0c,0x53,0x46,0x34,0x52,0x59,0xff,0x08,
0x8c,0x00,0x32,0x00,0x32,0x2e,0x30,0x30,0x2e,0x30,0x36,0x00,0x34,0x0a,0x00,0x00,
0x00,0x00,0x00,0x20 })
// bootloader 5.00.01
// 7a 05 20 00
// 01 02 02 06 1c 53 50 4a 37 47 ff 10 93 00 89 00
// 35 2e 30 30 2e 30 31 00 28 0c 00 00 00 00 00 20
public PacketFlashBeaconAck(bool isBL5=false)
: this(isBL5 ?
Utils.FromHex("7a052000010202061c53504a3747ff1093008900352e30302e303100280c000000000020") :
Utils.FromHex("180520000102020b0c5346345259ff088c003200322e30302e303600340a000000000020"))
{
}

// TODO: what means first 16 bytes?
// These keys are used to encrypt data for packet id=0x0516 (CMD_NVR_PUT)
// It happens during AgencyId activation, it get 4 letter and encrypt it to 104 bytes
public uint K0
{
get { return (uint)(_rawData[4] | (_rawData[5] << 8) | (_rawData[6] << 16) | (_rawData[7] << 24)); }
}
public uint K1
{
get { return (uint)(_rawData[8] | (_rawData[9] << 8) | (_rawData[10] << 16) | (_rawData[11] << 24)); }
}
public uint K2
{
get { return (uint)(_rawData[12] | (_rawData[13] << 8) | (_rawData[14] << 16) | (_rawData[15] << 24)); }
}
public uint K3
{
get { return (uint)(_rawData[16] | (_rawData[17] << 8) | (_rawData[18] << 16) | (_rawData[19] << 24)); }
}


public string Version
{
Expand All @@ -79,14 +107,22 @@ public override string ToString()
{
return string.Format(
"{0} {{\n" +
" HdrSize={1}\n" +
" Version=\"{2}\"\n"+
" Data={3}\n" +
" HdrId=0x{1:x4}\n" +
" HdrSize={2}\n" +
" Version=\"{3}\"\n"+
" K0=0x{4:x8}\n" +
" K1=0x{5:x8}\n" +
" K2=0x{6:x8}\n" +
" K3=0x{7:x8}\n" +
"}}",
this.GetType().Name,
HdrId,
HdrSize,
Version,
Utils.ToHex(_rawData.Skip(4).Take(0x10)));
K0,
K1,
K2,
K3);
}
}
}
57 changes: 34 additions & 23 deletions Packets/PacketFlashWriteAck.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ You should have received a copy of the GNU General Public License
using System;
namespace K5TOOL.Packets
{
// ?? 1a050800 8a8d9f1d 0000 0000
// OK: 1a0508008a8d9f1d00000000
// bad id: 1a0508000000000000000100
// bad ver: 1a0508000000000000000100
public class PacketFlashWriteAck : Packet
{
public const ushort ID = 0x051a;
Expand All @@ -35,59 +37,68 @@ public PacketFlashWriteAck(byte[] rawData)
}
}

public PacketFlashWriteAck(ushort offset, uint id = 0x1d9f8d8a)
: this(MakePacketBuffer(id, offset, 0x0000))
public PacketFlashWriteAck(ushort chunkNumber, uint sequenceId = 0x1d9f8d8a)
: this(MakePacketBuffer(sequenceId, chunkNumber, 0x0000))
{
}

private static byte[] MakePacketBuffer(uint id, ushort offset, ushort padding)
private static byte[] MakePacketBuffer(uint sequenceId, ushort chunkNumber, ushort padding)
{
var hdrSize = 8;
var buf = new byte[12];
buf[0] = 0x1a;
buf[1] = 0x05;
buf[2] = (byte)hdrSize;
buf[3] = (byte)(hdrSize >> 8);
buf[4] = (byte)id;
buf[5] = (byte)(id >> 8);
buf[6] = (byte)(id >> 16);
buf[7] = (byte)(id >> 24);
buf[8] = (byte)(offset >> 8);
buf[9] = (byte)offset;
buf[10] = (byte)(padding >> 8);
buf[11] = (byte)padding;
buf[4] = (byte)sequenceId;
buf[5] = (byte)(sequenceId >> 8);
buf[6] = (byte)(sequenceId >> 16);
buf[7] = (byte)(sequenceId >> 24);
buf[8] = (byte)chunkNumber;
buf[9] = (byte)(chunkNumber >> 8);
buf[10] = (byte)padding;
buf[11] = (byte)(padding >> 8);
return buf;
}

public uint Id
public uint SequenceId
{
get { return (uint)(_rawData[4] | (_rawData[5] << 8) | (_rawData[6] << 16) | (_rawData[7] << 24)); }
}

public ushort Offset
public ushort ChunkNumber
{
get { return (ushort)((_rawData[8] << 8) | _rawData[9]); }
get { return (ushort)(_rawData[8] | (_rawData[9] << 8)); }
}

public ushort Padding
// 0=OK
// 1=Error
public byte Result
{
get { return (ushort)((_rawData[10] << 8) | _rawData[11]); }
get { return _rawData[10]; }
}
// What is this?
public byte V0
{
get { return _rawData[11]; }
}

public override string ToString()
{
return string.Format(
"{0} {{\n" +
" HdrSize={1}\n" +
" Id=0x{2:x8}\n" +
" Offset=0x{3:x4}\n" +
" Padding=0x{4:x4}\n" +
" SequenceId=0x{2:x8}\n" +
" ChunkNumber=0x{3:x4}\n" +
" Result={4}\n" +
" V0={5}\n" +
"}}",
this.GetType().Name,
HdrSize,
Id,
Offset,
Padding);
SequenceId,
ChunkNumber,
Result,
V0);
}
}
}
Loading

0 comments on commit ddb712a

Please sign in to comment.