unit uTokens; //////////////////////////////////////////////////////////////////////////////// // // Structure of Tokens // //////////////////////////////////////////////////////////////////////////////// {-------------------------------------------------------------------------------------- { BB5 Flash-token: Type 1 54 01 17 0E 00 00 00 0D BA 01 00 00 40 00 01 6E 00 00 62 TH ST ST HL DEVICE DC DC UN LL LL LL LL SS SS SS SS HC Type 2 54 01 30 15 00 03 00 A2 72 00 00 00 08 FF FF FF FF 00 04 00 00 00 00 00 00 9A TH ST ST HL FI FI FI DC DC ?? ?? ?? ?? ?? ?? ?? ?? LL LL LL LL SS SS SS SS HC TH - Token Header ST - SubType (type of token) HL - Header Length FF - Flash ID DC - Data Checksum LL - Length of data between two tokens SS - Start adress in flash HC - Header Checksum --------------------------------------------------------------------------------------- { BB5 Cert-token Type 1 5D 01 27 2D ............... .............. 00 00 00 23 0C 00 00 04 00 00 00 06 C0 AE 5D 01 27 2D ............... .............. 00 00 00 8D B6 00 00 04 00 00 00 06 C0 D6 5D 01 27 2D ............... .............. 01 01 00 C1 26 00 00 04 00 00 07 00 00 48 TH ST ST HL [20 byte SHA1?] [12 byte name] FF FF FF DC DC LL LL LL LL SS SS SS SS HC Type 2 5D 01 28 43 ............... .............. 00 00 00 5A 5A 00 00 03 00 FF FF FF FF ................ 02 00 9D 5D 01 28 43 ............... .............. 01 01 00 BF 2B 00 00 04 00 FF FF FF FF ................ 02 00 48 5D 01 28 43 ............... .............. 00 00 00 8C 2E 00 00 02 80 FF FF FF FF ................ 01 00 25 5D 01 28 43 E9EFF4BFAA5393217CA6B17755FC3E1415658E9A 50415055424B455953000000000000 1D26 00000600 FFFFFFFF 64 3B2F33E3E6EEFC2D6F45213419C8E368FCB9960100 6D TH ST ST HL [20 byte SHA1?] [12 byte name] FF FF FF DC DC LL LL LL LL SS SS SS SS [20 bytes SHA1?] ?? ?? HC TH HLEN NAME/DESC DCHK BLKSZ LAST_BYTE_IS_H_CHECKSUM --------------------------------------------------------------------------------------- { BB5 Image-token allways applied in starting image-token F0F0 0001 FF00 0000 FFF0 FFFF 00000000 [some identifier] [ident?] [ part ] part is starting with 0 every 0x208 bytes (including this 8 bytes): FFF0 FFFF [ part ] every 0x20000 bytes this sequence is starting again but part is still continuing letzter 0x20000 part: F0F0 0001 FFC0 0000 FFF0 FFFF 0000 xxxx yy <- $C0 marks end ---------------------------------------------------------------------------------------} interface uses Classes, SysUtils, Hexutils; procedure DeletePhoenixTokens(var ms: TMemoryStream; var res: Boolean; var FirstTokenType: Word; var SizeOfDataInToken: Cardinal); procedure InsertPhoenixTokens(sc: TMemoryStream; var res: Boolean; var TokenType: Word; var Offset, SizeOfDataInToken: Cardinal); function FlashTokenChekSum(Buf: Pointer; BufLen: integer): Word; function FlashTokenCRC(Buf: Pointer; BufLen: integer): byte; implementation procedure DeletePhoenixTokens(var ms: TMemoryStream; var res: Boolean; var FirstTokenType: Word; var SizeOfDataInToken: Cardinal); var i, HdrLen: integer; TokenBuf: array of byte; Data: Byte; CurrTokenType: Word; CurrTokenSize: Cardinal; dest: TMemoryStream; begin i := 0; res := false; dest := TMemoryStream.Create; {ms.Read(i,1); if i<>$B2 then exit; SetLength(TokenBuf, 4); ms.ReadBuffer(TokenBuf[0], 4);//Длина Flash Header HdrLen := HexToInt(IntToHex(TokenBuf[0], 2)+IntToHex(TokenBuf[1], 2)+IntToHex(TokenBuf[2], 2)+IntToHex(TokenBuf[3], 2)); ms.Seek(0,sofromBeginning); dest.CopyFrom(ms, HdrLen+5);} i := 0; while ms.Position < ms.Size do begin ms.ReadBuffer(Data, 1); if Data = $54 then begin ms.ReadBuffer(CurrTokenType, 2); ms.ReadBuffer(Data, 1); SetLength(TokenBuf, Data + 1); //length of header flash-token ms.ReadBuffer(TokenBuf[0], Data + 1); // на единицу больше с учетом CRC case CurrTokenType of $1701: begin CurrTokenSize := HexToInt(IntToHex(TokenBuf[6], 2) + IntToHex(TokenBuf[7], 2) + IntToHex(TokenBuf[8], 2) + IntToHex(TokenBuf[9], 2)); if i = 0 then begin FirstTokentype := CurrTokenType; //Копирование первого значения о типе применяемого токена для дальнейшей "переразметки" SizeOfDataInToken := CurrTokenSize; //Копирование первого значения размера токен блока для дальнейшей "переразметки" inc(i); end; end; $3001: begin CurrTokenSize := HexToInt(IntToHex(TokenBuf[17], 2) + IntToHex(TokenBuf[18], 2) + IntToHex(TokenBuf[19], 2) + IntToHex(TokenBuf[20], 2)); if i = 0 then begin FirstTokentype := CurrTokenType; //Копирование первого значения о типе применяемого токена для дальнейшей "переразметки" SizeOfDataInToken := CurrTokenSize; //Копирование первого значения размера токен блока для дальнейшей "переразметки" inc(i); end; end else begin //Если текущее значение не равно $54, значит нарушена структурность разметки flash-token, либо новый тип разметки -> Error dest.Free; exit; end; end; //end of case //Если имеются различия между данными о длине блока в токене и реальным значением -> Bad Image File if (ms.size - ms.position) < CurrTokenSize then begin dest.Free; exit; end; dest.CopyFrom(ms, CurrTokenSize); end; end; ms.Clear; dest.Seek(0, soFromBeginning); ms.CopyFrom(dest, dest.Size); dest.free; ms.Seek(0, soFromBeginning); res := true; end; procedure InsertPhoenixTokens(sc: TMemoryStream; var res: Boolean; var TokenType: Word; var Offset, SizeOfDataInToken: Cardinal); var i, HdrLen: integer; b: boolean; TokenBuf: array of byte; DataBuf: array of byte; Data: Byte; CurrTokenType, CurrTokenDataCheck: Word; CurrTokenSize: Cardinal; dest: TMemoryStream; begin res := false; dest := TMemoryStream.Create; sc.Seek(0, sofromBeginning); i := 0; b := true; //признак последнего блока данные меньшего по размерам, чем стандартный if TokenType = $1701 then SetLength(TokenBuf, $13) else if TokenType = $3001 then SetLength(TokenBuf, $19) else begin dest.Free; exit; end; SetLength(DataBuf, SizeOfDataInToken); while (sc.Position < sc.Size) and b do begin //Возможно ли прочитать блок данных длиной SizeOfDataInToken //Необходимо для чтения остатка (для последнего блока данных) if (sc.size - sc.position) < SizeOfDataInToken then begin SizeOfDataInToken := sc.size - sc.position; b := false; end; sc.ReadBuffer(DataBuf[0], SizeOfDataInToken); CurrTokenDataCheck := FlashTokenChekSum(@DataBuf[0], SizeOfDataInToken); case TokenType of $1701: begin TokenBuf[0] := $54; //TH - Token Header //ST - SubType (type of token) TokenBuf[1] := $01; TokenBuf[2] := $17; TokenBuf[3] := $0E; //HL - Header Length //May be Flash ID TokenBuf[4] := $00; TokenBuf[5] := $00; TokenBuf[6] := $00; Word((@TokenBuf[7])^) := CurrTokenDataCheck; //DC - Data Checksum TokenBuf[9] := $01; //Unknow //LL - Length of data between two tokens Word((@TokenBuf[10])^) := Swap((SizeOfDataInToken and $FFFF0000) shr 16); Word((@TokenBuf[12])^) := Swap((SizeOfDataInToken and $0000FFFF)); //SS - Start adress in flash Word((@TokenBuf[14])^) := Swap((Offset and $FFFF0000) shr 16); Word((@TokenBuf[16])^) := Swap(Offset and $0000FFFF); Byte((@TokenBuf[18])^) := FlashTokenCRC(@TokenBuf[1], Length(TokenBuf) - 2); //HC - Header Checksum end; $3001: begin TokenBuf[0] := $54; //TH - Token Header //ST - SubType (type of token) TokenBuf[1] := $01; TokenBuf[2] := $30; TokenBuf[3] := $15; //HL - Header Length //May be Flash ID TokenBuf[4] := $00; TokenBuf[5] := $03; TokenBuf[6] := $00; Word((@TokenBuf[7])^) := CurrTokenDataCheck; //DC - Data Checksum //Unknow TokenBuf[9] := $00; TokenBuf[10] := $00; TokenBuf[11] := $00; TokenBuf[12] := $08; TokenBuf[13] := $FF; TokenBuf[14] := $FF; TokenBuf[15] := $FF; TokenBuf[16] := $FF; //LL - Length of data between two tokens Word((@TokenBuf[17])^) := Swap((SizeOfDataInToken and $FFFF0000) shr 16); Word((@TokenBuf[19])^) := Swap((SizeOfDataInToken and $0000FFFF)); //SS - Start adress in flash Word((@TokenBuf[21])^) := Swap((Offset and $FFFF0000) shr 16); Word((@TokenBuf[23])^) := Swap(Offset and $0000FFFF); Byte((@TokenBuf[25])^) := FlashTokenCRC(@TokenBuf[1], Length(TokenBuf) - 2); //HC - Header Checksum end; end; //end of case Offset := Offset + SizeOfDataInToken; dest.WriteBuffer(TokenBuf[0], Length(TokenBuf)); dest.WriteBuffer(DataBuf[0], SizeOfDataInToken); end; sc.clear; dest.Seek(0, sofrombeginning); sc.CopyFrom(dest, dest.Size); sc.Seek(0, sofrombeginning); dest.Free; res := true; end; //Расчет контрольной суммы блока данных (DC - Data Checksum) function FlashTokenChekSum(Buf: Pointer; BufLen: integer): Word; begin Result := Word(Buf^); inc(Integer(Buf)); dec(BufLen); inc(Integer(Buf)); dec(BufLen); while BufLen > 0 do begin Result := Result xor Word(Buf^); inc(Integer(Buf)); dec(BufLen); inc(Integer(Buf)); dec(BufLen); end; end; //Расчет контрольной суммы flash-tokens (последний байт - HC - Header Checksum) function FlashTokenCRC(Buf: Pointer; BufLen: integer): byte; begin Result := 0; while BufLen > 0 do begin Result := Result + Byte(Buf^); inc(Integer(Buf)); dec(BufLen); end; Result := Result xor $FF; end; end.