unit uContent; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // / // 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 5D 01 27 2D 38F312750F686F9FC9B1B3778774A19550F16CA3 4E4F4C4F0000000000000000000000 55B9 00000400 000402C0 3E Root Key Hash NOLO TH ST ST HL [20 byte SHA1?] [12 byte name] FFFFFF DCDC LLLLLLLL SSSSSSSS HC Type 2 5D 01 28 43 38F312750F686F9FC9B1B3778774A195 50F16CA3 50415055424B455953000000000000 DFD0 00000600 000582C0 3D744C60D026865F8B384F71E83AA7A06FC122770100 99 5D 01 28 43 BAF3A9C3DBFA8454937DB77F2B8852B1 24CD5A6C 50415055424B455953000000000000 1E0C 00000600 000582C0 3D744C60D026865F8B384F71E83AA7A06FC122770100 01 5D 01 28 43 E9EFF4BFAA5393217CA6B17755FC3E14 15658E9A 50415055424B455953000000000000 1D26 00000600 FFFFFFFF 643B2F33E3E6EEFC2D6F45213419C8E368FCB9960100 6D Root Key Hash PAPUBKEYS TH ST ST HL [20 byte SHA1?] [12 byte name] FFFFFF DCDC LLLLLLLL SSSSSSSS [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, Windows, Hexutils; type TEraseArea = record BeginErase : Cardinal; EndErase : Cardinal; FlashingArea : Boolean; end; var buf : array[0..$3FFFF] of byte; EraseArea : array of TEraseArea; procedure GetPageSize(img: string; var PageSize: byte; var res:Boolean); procedure GetFlashArea(img: string; {EraseArea: array of TEraseArea;} var res:Boolean); procedure Image64to128(img: string; dest: TMemoryStream;var Res:boolean); procedure DeletePhoenixTokens(var ms:TMemoryStream; {var EraseArea: array of TEraseArea;}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 GetPageSize(img: string; var PageSize: byte; var res:Boolean); var HdrLen, HdrSeems, Count, BlockCount, CurrBlock, CurrBlockLen : Integer; ConvBlockPresent : Boolean; ImagePageSize : Word; ms : TMemoryStream; begin res:=false; ms:=TMemoryStream.Create; ms.LoadFromFile(img); currblock:=0; CurrBlockLen:=0; ms.Read(buf[0] ,1); if buf[0]<>$B2 then begin ms.Free; exit; end; ms.ReadBuffer(buf[0], 4);//Длина Flash-header'a HdrLen := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); ms.ReadBuffer(buf[0], 4);//Количество блоков в Flash-header'е BlockCount:= HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); HdrSeems := HdrLen+5; Count:=0; ConvBlockPresent:=false; while (ms.Position2 then begin ms.Free; exit; end; ms.ReadBuffer(ImagePageSize, CurrBlockLen); inc(Count); case ImagePageSize of $1100: begin PageSize:=128; res:=true; end; $1000: begin PageSize:=64; res:=true; end; end;//end of case ImagePageSize end; else begin ms.ReadBuffer(CurrBlockLen, 1); ms.Seek(CurrBlockLen, sofromCurrent); inc(Count); end; end;//end of case CurrBlock end;//end of while ms.Free; //Если блок F5 отсутствует, то контент имеет 128K-формат if Not ConvBlockPresent then begin PageSize:=128; res:=true; end; end; procedure GetFlashArea(img: string; {EraseArea: array of TEraseArea;} var res:Boolean); var HdrLen, HdrSeems, CurrSeemLen, CurrEraseLen, Count, i, j, BlockCount, CurrBlock, CurrBlockLen, EraseCnt : Integer; FlashCFG, Byte1, Byte2, Byte3 : Byte; ms : TMemoryStream; begin res:=false; ms:=TMemoryStream.Create; ms.LoadFromFile(img); ms.Read(buf[0] ,1); if buf[0]<>$B2 then begin ms.Free; exit; end; ms.ReadBuffer(buf[0], 4);//Длина Flash-header'a HdrLen := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); ms.ReadBuffer(buf[0], 4);//Количество блоков в Flash-header'е BlockCount:= HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); HdrSeems := HdrLen+5; Count:=0; while (ms.Position$B2 then begin fs.Free; exit; end; fs.ReadBuffer(buf[0], 4);//Длина Flash-header'a HdrLen := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); HdrSeems := HdrLen+5; head:=TMemoryStream.Create; ms:=TMemoryStream.Create; fs.Seek(0, sofrombeginning); head.CopyFrom(fs, HdrSeems); ms.CopyFrom(fs, fs.Size-HdrSeems); fs.Free; ms.Seek(0, sofrombeginning); //убираем flash-tokens DeletePhoenixTokens(ms, {EraseArea,} b, TokenType, SizeDataTok); if Not b then begin ms.free; head.Free; exit; end; //Убираем разметку токенами в 64K dest.CopyFrom(ms, $0FFF8); ms.ReadBuffer(buf[0], $10); b:=true; DataLen:=$0FFF0; while (ms.PositionDataLen then begin ms.WriteBuffer(buf[$11], $10); ms.WriteBuffer(buf[0] , $10); ms.CopyFrom(dest, DataLen); end else begin DataLen:= dest.size-dest.position; buf[12]:=$C0;//это последний токен в данном имаже, его признак - значение $C0 ms.WriteBuffer(buf[$11], $10); ms.WriteBuffer(buf[0] , $10); //Скопируем остаток данных ms.CopyFrom(dest, DataLen); //Пересчет свободного места, необходимо добавить "пустые" данные //необходимо для сохранения структуры/размера данных, входящих в последний токен DataLen:=$1FFF8-DataLen; for i:=0 to DataLen-1 do buf[i]:=$FF; buf[DataLen-2]:=$F0; buf[DataLen-1]:=$F0; ms.WriteBuffer(buf[0], DataLen); b:=false; continue; end; end; dest.clear; //ms.SavetoFile('G:\Coding\My Project\!!!64to128\Image\manual\_my_prog_128_without_header_flash_tokens'); ms.seek(0, sofrombeginning); head.Seek(9, sofrombeginning); while head.Position= EraseArea[i].BeginErase) and (FlashAddress <= EraseArea[i].EndErase) then EraseArea[i].FlashingArea:=true; end; $3001: begin CurrTokenSize:=HexToInt(IntToHex(TokenBuf[17], 2)+IntToHex(TokenBuf[18], 2)+IntToHex(TokenBuf[19], 2)+IntToHex(TokenBuf[20], 2)); FlashAddress :=HexToInt(IntToHex(TokenBuf[21], 2)+IntToHex(TokenBuf[22], 2)+IntToHex(TokenBuf[23], 2)+IntToHex(TokenBuf[24], 2)); if b then begin FirstTokentype:=CurrTokenType;//Копирование первого значения о типе применяемого токена для дальнейшей "переразметки" SizeOfDataInToken:=CurrTokenSize;//Копирование первого значения размера токен блока для дальнейшей "переразметки" b:=false; end; for i:=0 to Length(EraseArea)-1 do if (FlashAddress >= EraseArea[i].BeginErase) and (FlashAddress <= EraseArea[i].EndErase) then EraseArea[i].FlashingArea:=true; end else begin //Если текущее значение не равно $54, значит нарушена структурность разметки flash-token, либо новый тип разметки -> Error dest.Free; exit; end; end;//end of case //Если имеются различия между данными о длине блока в токене и реальным значением -> Bad Image File if (ms.size-ms.position) 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.