unit UnitE1; interface uses Windows, SysUtils, Graphics, Controls, Classes, Forms, UsbMain, HexUtils, UnitMisc, Masks, Boots, UnitAndrey, UnitPavel, Unit1, uTokens; function ISIHeaderTransId():byte; function ISIHeaderMsgBody():byte; function USBControlPacket(_Class: LongWord; Length: longword; Expected:Integer):Boolean; function BB5_USB_BootRom_GetFirstBlock:integer; function GetRAPInfo():boolean; function BB5_NormalFlashing():boolean; function BB5_Flashing():boolean; function BB5_DeadFlashing():boolean; procedure BB5_ExtractCertData (core:string; needSert:string; CertData:TMemoryStream; Result:boolean; ape : boolean); procedure BB5_ExtractBlockOfRAWLoader(core: string;RAWBlock:TMemoryStream; var Result:boolean); procedure BB5_ExtractRAWLoader(RAWBlock, RAWLoader:TMemoryStream; Result:boolean); function BB5_SendADLLoader(UAgent:TMemoryStream):Boolean; function CheckADLLoader:boolean; function GetLoaderCRC(Buf:Pointer; BufLen: integer): Word;//Функция расчета CHK UPDAPP function BB5restart2ndproto():boolean; function BB5_ADL_RestartMCU(mode: byte):boolean; function BB5_EraseFile(core: string):boolean; function BB5_EraseArea(Start, Stop: LongInt; FlashCfg, Byte1, Byte2, Byte3:byte):boolean; function BB5_EraseAreaSmallBlock(Start, Stop: LongInt; FlashCfg,Byte1,Byte2,Byte3:byte):boolean; function BB5_EraseSegment(startSegment, stopSegment:LongInt; FlashCfg, Byte1, Byte2, Byte3:byte):boolean; function BB5_EraseSector (startSector,EraseSectorSize:LongInt; FlashCfg, Byte1, Byte2, Byte3:byte):boolean; function BB5_WriteFile(core: string):boolean; function s40prep04 ():Boolean; // $04 byte adl flashing ( normal s40 ) function s40prep80():Boolean; function extractloader(core:string ; mode : integer):Boolean; function BB5_FlashingXSR15():boolean; function RebuildPartition(F:TMemoryStream; PLen: integer):boolean; function s60checkadl():Byte; function ADLBootInFlash():Boolean; function ADL06auth ():Boolean; function AdlRestart06 (rb:byte):Boolean; function ADL80auth ():Boolean; function OMAP1710boot () : boolean; function XSR6RAWBoot (core:string):Boolean; function OMAPFlash():Boolean; function Omap1610extrboot(ASIC:string):boolean; function OMAP1610boot () : boolean; function OMAP2420boot () : boolean; function ADLAPErestart(rb:Byte):Boolean; type E = class(exception); TRAPInfoRecord = record SYSTEM_ASIC_ID : array[0..$13] of byte; EMx_ID : array[0..$03] of byte; PUBLIC_ID : array[0..$13] of byte; //5800 - 1FF0001841158B52064E64D3C3E9A7F38DC47E29 ASIC_MODE : byte; ROOT_KEY_HASH : array[0..$0f] of byte; //5800 - CAEEBB65D3C48E6DC73B49DC5063A2EE ROM_ID : array[0..$07] of byte; //5800 - 4B9B75103E691FF8 //Old version ASICID : array[0..$14] of byte; //5800 - 000000010000022600010006400C192101031103 [RAPIDO3G ver: 1.x] ROMID : array[0..$07] of byte; //5800 - 4B9B75103E691FF8 PublicID : array[0..$13] of byte; //5800 - 1FF0001841158B52064E64D3C3E9A7F38DC47E29 //for CMT BootID : array[0..$07] of byte; //6233 - 0803000002010000 PAPUBKEYSID : array[0..$13] of byte; //6233 - 2F36DDC4990FD844712A61A80C033211BD9602E3 FlashID : array[0..$0A] of byte; //6233 - 00EC2208012100000100 //for APE PAPUBKEYSHashCMT : array[0..$13] of byte; //5800 - 76A20187051C30162EE91C77AE5E6011F5F1BA61 EM1ID : DWord; //5800 - 00000295 EM2ID : DWord; //5800 - 00000B22 MODEID : Byte; //00 APErootkey : array[0..$0f] of Byte; APEFlashID : array [0..$0A] of byte; end; TBlockRec = record Block : Byte; OffSet : Dword; Size : Word; end; const BB5_EraseSectorSize: LongInt = $10000; var TransId : byte; MsgBody : byte; msgid : Byte; RAPInfo : TRAPInfoRecord; partition : Boolean; partitionstream : TMemoryStream; implementation function ISIHeaderTransId():byte; begin inc(TransId); //if TransId=0 then inc(TransId); Result:=TransId; end; function ISIHeaderMsgBody():byte; begin inc(MsgBody); //if MsgBody=0 then inc(MsgBody); Result:=MsgBody; end; //Get RAP Info function GetRAPInfo():boolean; var i,j : integer; Key : Byte; KeyLen : Byte; begin FillMemory(@RAPInfo.ROOT_KEY_HASH,$10,$00); FillMemory(@RAPInfo.APErootkey,$10,$00); FillMemory(@RAPInfo.FlashID,$A,$00); FillMemory(@RAPInfo.APEFlashID,$A,$00); FillMemory(@RAPInfo.PublicID,$14,$00); FillMemory(@RAPInfo.BootID,$8,$00); FillMemory(@RAPInfo.PAPUBKEYSID,$14,$00); Result:=false; i:=$10; USBBulkWritePort(@GETRoot, Length(GETRoot)); if Not USBBulkReadPort($FFFF) then exit; while i < Length(rxbuf) do begin Key :=rxbuf[i]; KeyLen:=rxbuf[i+1]-2; inc(i, 2); case Key of $01: begin for j:=$0 to $9 do RAPInfo.FlashID[j]:= rxbuf[i+j]; inc(i, KeyLen); end; $03: begin for j:=$0 to $9 do RAPInfo.APEFlashID[j]:= rxbuf[i+j]; inc(i, KeyLen); end; $04: begin // 0803000002010000 for j:=$0 to $7 do RAPInfo.BootID[j]:= rxbuf[i+j]; inc(i,$10); for j:=0 to $0F do RAPInfo.APErootkey[j]:= rxBuf[i+j]; inc(i, KeyLen-$10); end; $05: begin // 0A900018A8B54650B9C89AA40EEC5059B5762F38 inc(i, $0A); for j:=0 to $13 do RAPInfo.PublicID[j]:= rxbuf[i+j]; // BAF3A9C3DBFA8454937DB77F2B8852B1 inc(i, $14); for j:=0 to $0F do RAPInfo.ROOT_KEY_HASH[j]:= rxbuf[i+j]; inc(i, $10); // 2F36DDC4990FD844712A61A80C033211BD9602E3 for j:=0 to $13 do RAPInfo.PAPUBKEYSID[j]:= rxbuf[i+j]; inc(i, $14); Result:=True; inc(i, KeyLen-$42); end else inc(i, KeyLen); end;//End Of Case end; { ASICID : array[0..$14] of byte; //5800 - 000000010000022600010006400C192101031103 [RAPIDO3G ver: 1.x] ROMID : array[0..$07] of byte; //5800 - 4B9B75103E691FF8 PublicID : array[0..$13] of byte; //5800 - 1FF0001841158B52064E64D3C3E9A7F38DC47E29 //for CMT BootID : array[0..$07] of byte; //6233 - 0803000002010000 RootKeyHash : array[0..$0f] of byte; //5800 - CAEEBB65D3C48E6DC73B49DC5063A2EE PAPUBKEYSID : array[0..$14] of byte; //6233 - 2F36DDC4990FD844712A61A80C033211BD9602E3 //for APE PAPUBKEYSHashCMT : array[0..$13] of byte; //5800 - 76A20187051C30162EE91C77AE5E6011F5F1BA61 EM1ID : DWord; //5800 - 00000295 EM2ID : DWord; //5800 - 00000B22 MODEID : Byte; //00} {Processing file: RM-356_31.0.101_prd.core.C00 --- Press phone's POWER button or connect a CHARGER ! --- warning: Some new phones consume more power, please connect cable to USB host instead of USB hub. [ADL] Pooling for ADL device [ADL] Device found : nmwcdnsuc\Nokia USB Flashing Generic-2c024cda RAP SYSTEM ASIC ID: 000000010000022600010006400C192101031103 [RAPIDO3G ver: 1.x] RAP EM1 ID: 00000295 RAP EM2 ID: 00000B22 RAP PUBLIC ID: 1FF0001841158B52064E64D3C3E9A7F38DC47E29 RAP ASIC MODE ID: 00 RAP ROOT KEY HASH: CAEEBB65D3C48E6DC73B49DC5063A2EE RAP ROM ID: 4B9B75103E691FF8 [ADL] Flashing CMT Update Server Data, ULO: 0x3B80 bytes [ADL] Update Server code succesfully sent to phone [ADL] Flashing CMT Update Server Data, XSR: 0x2A3F45 bytes [ADL] RAP3NAND sent. [ADL] PASUBTOC sent. [ADL] UPDAPP sent. [ADL] Update Server code succesfully sent to phone [ADL] Pooling for ADL device} end; procedure BB5_ExtractCertData(core:string;needSert:string;CertData:TMemoryStream;Result:boolean; ape:boolean); var HdrLen, i, good : Integer; buf : array[0..$3FFFF] of byte; DataLen, CertLen, CertOffSet, tmp : LongInt; CertName : String; CertDone, NewCertBegin, NeedCertFound, CertDataBricked : Boolean; fs : TFileStream; Begin Result:=False; // Form1._msg('Processing '+ExtractFileName(core)); try fs:=TFileStream.Create(core,fmOpenRead); fs.Seek(0, sofromBeginning); fs.Read(i,1); if i<>$B2 then begin Form1._msg('Invalid Image File'); USBClosePort; fs.Free; exit; end; fs.ReadBuffer(buf[0], 4);//Длина Flash Header HdrLen := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); fs.Seek(HdrLen,soFromCurrent); CertDone:=False;//Признак концовки текущей части сертификата CertDataBricked:=False;//Признак того, что в данных сертификата присутствует разметка Flash-token NewCertBegin:=False;//Признак начала нового сертификата NeedCertFound:=False;//Признак того, что искомый серт найден while ((fs.Position+$13)=fs.Size then break; fs.ReadBuffer(buf[0], $1); //если следующий байт не является началом разметки Cert-token, //значит данные искомого блока поделены на кусочки разметкой Flash-token if buf[0]<>$5D then begin //Warning: Data is splitted into bricks! CertDataBricked:=True; fs.Seek(fs.Position-1, sofromBeginning); continue; end; break;//найдено начало нового серта -> стоп end; if CertDataBricked and not NewCertBegin then CertData.CopyFrom(fs, DataLen) else //копирование при условии, что это кусочек искомого блока fs.Seek(DataLen, sofromCurrent); //пропуск, если левый кусочек end; $5D://Разметка Cert-token case ape of false: // CMT mode begin fs.ReadBuffer(buf[0], $3); fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[37], 2)+IntToHex(buf[38], 2)+IntToHex(buf[39], 2)+IntToHex(buf[40], 2)); good:=0; for i:=$0 to $0F do if RAPInfo.ROOT_KEY_HASH[i]=buf[i] then inc(good); if good<$10 then begin //Начало сертификата не совпадает с Root-Hash, пропускаем fs.Seek(DataLen, sofromCurrent); continue; end; //Найдено начало нового сертификата, который совпадает с Root-Hash CertName:=''; for i:=$14 to $23 do if buf[i]=$00 then break else CertName:=CertName+Chr(buf[i]); tmp:=CertData.Size; //Сравнение имени найденного сертификата с искомым if not MatchesMask(CertName, '*'+needSert+'*') then //Имя текущего сертификата не совпадает с искомым begin //Если искомый серт уже был найден, то перед началом текущего находится концовка искомого if NeedCertFound then NewCertBegin:=True; fs.Seek(DataLen, sofromCurrent);//пропускаем найденный блок сертификата continue; end else //Найдено начало искомого серта begin NeedCertFound:=true; // Form1._msg('Cert: '+CertName+' Match with Root'); if Not NewCertBegin then //Если после найденного начала искомого серта не было найдено начало следующего, то begin CertData.CopyFrom(fs, DataLen);//копируем текущий блок CertDone:=True;// end; end; end; True : //APE mode begin fs.ReadBuffer(buf[0], $3); fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[37], 2)+IntToHex(buf[38], 2)+IntToHex(buf[39], 2)+IntToHex(buf[40], 2)); good:=0; for i:=$0 to $0F do if RAPInfo.APERootkey[i]=buf[i] then inc(good); if good<$10 then begin //Начало сертификата не совпадает с Root-Hash, пропускаем fs.Seek(DataLen, sofromCurrent); continue; end; //Найдено начало нового сертификата, который совпадает с Root-Hash CertName:=''; for i:=$14 to $23 do if buf[i]=$00 then break else CertName:=CertName+Chr(buf[i]); tmp:=CertData.Size; //Сравнение имени найденного сертификата с искомым if not MatchesMask(CertName, '*'+needSert+'*') then //Имя текущего сертификата не совпадает с искомым begin //Если искомый серт уже был найден, то перед началом текущего находится концовка искомого if NeedCertFound then NewCertBegin:=True; fs.Seek(DataLen, sofromCurrent);//пропускаем найденный блок сертификата continue; end else //Найдено начало искомого серта begin NeedCertFound:=true; // Form1._msg('APE Cert: '+CertName+' Match with Root'); if Not NewCertBegin then //Если после найденного начала искомого серта не было найдено начало следующего, то begin CertData.CopyFrom(fs, DataLen);//копируем текущий блок CertDone:=True;// end; end; end; end; end;//end of case end;//end while fs.free; CertData.Seek(0, soFromBeginning); Result:=True; except begin fs.free; Result:=False; exit; end; end; end; procedure BB5_ExtractBlockOfRAWLoader(core: string;RAWBlock:TMemoryStream; var Result:boolean); var buf : array[0..$3] of byte; HdrLen, //Длина Flash-заголовка SeemCount : Dword; //Кол-во блоков в Flash-заголовке CurrSeem : Byte; //Текущий блок CurrSeemLen : Word; //Длина данных текущего блока fs : TFileStream; begin Result:=false; //Form1.lst1.items.add('RawLoaderExtract: Processing '+ExtractFileName(core)); try fs:=TFileStream.Create(core,fmOpenRead); fs.Read(buf[0] ,1); if buf[0]<>$B2 then //Заголовок / идентификатор begin Form1.lst1.items.add('RawLoaderExtract: Error extracting RAW-loader from '+ExtractFileName(core)); 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)); fs.ReadBuffer(buf[0], 4);//Кол-во блоков в Flash-заголовке SeemCount := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); while (fs.Position$B0 then begin Form1._msg('RawLoader: Damaged data :('); fs.free; exit; end else begin fs.Seek(fs.Position-1, sofromBeginning); RAWBlock.CopyFrom(fs, CurrSeemLen); fs.free; Result:=True; exit; end; end;//End of Block F3 else begin fs.ReadBuffer(buf[0], 1); CurrSeemLen:=buf[0]; fs.Seek(CurrSeemLen, sofromcurrent); end; end;//end of Case end; fs.free; except begin fs.free; Form1._msg('RawLoader: Error extracting RAW-loader'); exit; end; end; end; procedure BB5_ExtractRAWLoader(RAWBlock, RAWLoader:TMemoryStream; Result:boolean); var b : Boolean; i, j, k, good : Integer; buf : array[0..$3] of byte; RootInBlock : array[0..$F] of byte; RAWLoaderBuf : array[0..$ffff] of byte; RAWHdrLen, BlockCount : DWord; PatchOffset, PatchLen : Word; BlockRec : array of TBlockRec; RAWLoaderLen, RAWLoaderOffset : Dword; SubstBlock : byte;//Блок подстановки begin Result:=false; RAWBlock.Seek(1, sofromBeginning);//Пропускаем идентификатор $B0, т.к. мы его проверили при извлечении RAWBlock.ReadBuffer(buf[0], 4);//Длина RAWBlock-header'a RAWHdrLen := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); RAWBlock.ReadBuffer(buf[0], 4);//Кол-во блоков в RAWBlock'е BlockCount := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); if (RAWBlock.Size$E4) and (buf[0]<>$E5) and (buf[0]<>$EA) then begin RAWBlock.ReadBuffer(buf[0], 1);//Длина блока BlockRec[i].Size:=buf[0]; BlockRec[i].OffSet:=RAWBlock.Position;//Начало данных блока end else begin RAWBlock.ReadBuffer(buf[0], 2);//Длина блока BlockRec[i].Size:=(buf[0]*$100)+buf[1]; BlockRec[i].OffSet:=RAWBlock.Position;//Начало данных блока end; RAWBlock.Seek(BlockRec[i].Size, sofromCurrent);//Пропускаем данные текущего блока inc(i); end; RAWLoaderOffSet:=RAWBlock.Position; RAWLoaderLen:=RAWBlock.Size-RAWLoaderOffSet; if RAWLoaderLen<=0 then //Проверка на наличие RAW-loader'а в RAW-Block'е begin Form1._msg('RawLoader not found...'); exit; end; //Копируем RAW-loader RAWLoader.CopyFrom(RAWBlock, RAWLoaderLen); // RAWLoader.SaveToFile('C:\Extract_RAW_Loader_extr_'+ExtractFileName(core)+'.bin'); //Патчинг RAW-loader'a i:=0; SubstBlock:=0; while i$10 then begin //Соответствие блоков длин/смещений и патчинговых блоков ($E4, $E5, $EA) if BlockRec[i].Block=$E2 then SubstBlock:=$E4; if BlockRec[i].Block=$E3 then SubstBlock:=$E5; if BlockRec[i].Block=$E9 then SubstBlock:=$EA; //Чтение данных из текущего блока длин/смещений //Данные о длине и смещении всегда располагаются в конце блока (последние 4 байта) RAWBlock.Seek((BlockRec[i].OffSet+BlockRec[i].Size-4), sofromBeginning); RAWBlock.ReadBuffer(PatchOffset, 2);//Чтение смещения PatchOffset:=Swap(PatchOffset); RAWBlock.ReadBuffer(PatchLen, 2);//Чтение длины патча PatchLen:=Swap(PatchLen); //Поиск патчинг-блока с RootHash, который совпадает с RAP-RootHash k:=0; b:=true; while (k Sending loader...'); Application.ProcessMessages; //Get Block - Х.з. зачем... Запрос 256 блока PM ???? //При прошивке 6233 и 7900 //запрос 6233 1B 00 10 23 00 06 00 15 54 42 01 00 //запрос 7390 1B 00 10 23 00 06 00 16 63 42 01 00 //ответ 6233 1B 10 00 23 00 16 15 36 54 43 00 01 07 10 00 00 00 00 00 00 00 02 00 00 00 00 00 00 //ответ 7390 1B 10 00 23 00 16 16 32 63 43 00 01 07 10 00 00 00 00 00 00 00 02 00 00 00 00 00 00 GetBlock[7]:=msgid; GetBlock[8]:=ISIHeaderTransId; GetBlock[9]:=$42; GetBlock[10]:=$01; GetBlock[11]:=$00; USBBulkWritePort(@GetBlock, Length(GetBlock)); USBBulkReadPort($FFFF); //Передача данных о размере и контрольной сумме ADL-loader'а //При прошивке 6233 и 7900 //запрос 6233 1B 00 10 6F 00 0F 00 15 55 02 00 1E 00 03 6E C0 F9 63 FF 00 00 --> Loader len: 224960, CHK: 0xF963 //запрос 6270 1B 00 10 6F 00 0F 00 15 1C 02 00 1E 00 03 B1 40 A4 C9 FF 00 00 --> Loader len: 241984, CHK: 0xA4C9 //запрос 7390 1B 00 10 6F 00 0F 00 16 64 02 00 1E 00 03 6E C0 FE 0F FF 00 00 //ответ 6233 1B 10 00 6F 00 06 15 48 55 22 00 00 //ответ 6270 1B 10 00 6F 00 06 15 48 1C 22 00 00 //ответ 7390 1B 10 00 6F 00 06 16 44 64 22 00 00 //SendADLCRC : array[0..20] of Byte = //($1B, $00, $10, $6F, $00, $0F, $00, $16, $64, $02, $00, $1E, $00, $03, $6E, $C0, $FE, $0F, $FF, $00, $00); SendADLCRC[7]:=msgid; MsgBody:=$01; SendADLCRC[8]:=ISIHeaderTransId; SendADLCRC[9]:=ISIHeaderMsgBody; //Длина UPDAPP SendADLCRC[12]:=UAgent.Size div $1000000; SendADLCRC[13]:=UAgent.Size div $10000; SendADLCRC[14]:=UAgent.Size div $100; SendADLCRC[15]:=UAgent.Size mod $100; //Чек UPDAPP SendADLCRC[16]:=CHK div $100; SendADLCRC[17]:=CHK mod $100; USBBulkWritePort(@SendADLCRC, Length(SendADLCRC)); USBBulkReadPort($FFFF); //Отправка агента по кусочкам b:=true; i:=1;//номер сообщения MsgBody:=2;//номер сообщения PktLen:=$0780;//длина отправляемого кусочка лоадера (длина как в Фениксе) Form1.pb1.Progress:=0; //ms:=TMemoryStream.Create;//для теста и сохранения текущего отправленного кусочка BufCopy(@SendADL[0], @txBuf[0], Length(SendADL)); //SendADL : array[0..15] of Byte = //($1B, $00, $10, $6F, $07, $8A, $00, $15, $56, $03, $00, $01, $00, $00, $07, $80); txBuf[6] := $00; txBuf[7] :=msgid; txBuf[9] := ISIHeaderMsgBody; Form1.pb1.maxvalue:=100; UAgent.Seek(0, sofromBeginning); Application.ProcessMessages; while (UAgent.Position+PktLen)<=UAgent.Size do begin UAgent.ReadBuffer(txBuf[16], PktLen); Word((@txBuf[4])^):=Swap(PktLen+$0A); txBuf[8] := ISIHeaderTransId; txBuf[11] := i; Word((@txBuf[14])^):=Swap(PktLen); //Только для сохранения отправляемых кусочков агента {ms.Seek(0, soFromBeginning); ms.WriteBuffer(txBuf[0], 16); ms.WriteBuffer(txBuf[16], PktLen); ms.SaveToFile('C:\ADL_Send\'+Int2Digs(i,4)+'.bin'); ms.Clear;} k:=USBBulkWritePort(@txbuf[0], (PktLen+$10)); if k<>(PktLen+$10) then begin USBClosePort; exit; end; if i=$0D then begin //данная команда присутствует в Phoenix'е - "включение подсветки дисплея" //Display3: array[0..11] of Byte = //($1B, $00, $10, $15, $00, $06, $00, $0C, $A4, $0E, $00, $00); USBBulkWritePort(@Display3, Length(Display3)); USBBulkReadPort($FFFF); end; USBBulkReadPort(16); if ((UAgent.Size-UAgent.position)$01 then begin USBClosePort; exit; end; TransId:=$5E; MsgBody:=$0A; Application.ProcessMessages; preflashread; b:=true; //RootHash for i := 0 to $0F do b:=b and (RAPInfo.ROOT_KEY_HASH[i]<>0); if Not b then begin Form1._msg('No RootKey Asic! Unable to continue flashing...'); exit; end; Application.ProcessMessages; Form1._msg('RAP_BOOT: ' + BufToHexStr(@RAPInfo.BootID[0], Length(RAPInfo.BootID))); Form1._msg('RAP_PUBLIC: ' + BufToHexStr(@RAPInfo.PublicID[0], Length(RAPInfo.PublicID))); Form1._msg('CMT_ROOTKEY: ' + BufToHexStr(@RAPInfo.ROOT_KEY_HASH[0], Length(RAPInfo.ROOT_KEY_HASH))); Form1._msg('RAP_PAPUBKEY: ' + BufToHexStr(@RAPInfo.PAPUBKEYSID[0], Length(RAPInfo.PAPUBKEYSID))); Application.ProcessMessages; // Тут будет чек и репак контента if (not Smart) and (image<>'') then begin Form1._msg('Checking CNT sector PN<>FL'); cmtflash:=Swap(Word((@rxBuf[20])^)); cmtflash:=cmtflash Shl 16; cmtflash:=cmtflash+Swap(Word((@rxBuf[18])^)); phsec:=getcntsize(cmtflash); Form1._msg('PN CNT sector : '+inttostr(phsec)+' kb'); if phsec=64 then Application.ProcessMessages else begin if not convertcnt(image) then begin Application.ProcessMessages; end else begin image:=image+'_128'; end; end; end; Application.ProcessMessages; if not Form1.chkDEADMODE.Checked then begin if Form1.chkDOWNGRADE.Checked=true then begin if not downgradeprep then begin Form1._msg('Error on flash prepare! break, Uncheck DOWNGRADE'); Form1.SetReady; Form1._msg(''); exit; end; end; end; Application.ProcessMessages; //Извлечение Update Agent UAgent:=TmemoryStream.Create; BB5_ExtractCertData(core, 'UPDAPP', UAgent, b, false); if Not b then begin UAgent.Free; Form1._msg('Error extracting Update Agent... ((('); Form1.SetReady; exit; end; if Not BB5_SendADLLoader(UAgent) then begin UAgent.Free; Form1.pb1.Progress:=0; Form1._msg('Sending UAgent Error... ((('); Form1.SetReady; exit; end else Form1._msg('Update Server code succesfully sent to phone!'); UAgent.Free; Application.ProcessMessages; i:=0; repeat begin Sleep(100); Application.ProcessMessages; Inc(i) end; until (DevPresent=False) or ( i=200 ); if i=200 then begin b:=False; Form1._msg('Error while restart phone - repower it and try again...'); Exit; end; Application.ProcessMessages; b:=BB5_Flashing; Result:=b; end; function BB5_Flashing():boolean; var b, proto : Boolean; i : integer; rb : Byte; begin rb:=$04; Application.ProcessMessages; Form1._msg('Reopening the connection...'); i:=30; while i>0 do begin Form1._msg('Waiting for response: '+inttostr(i)); Application.ProcessMessages; if catchdevice<>$02 then begin Application.ProcessMessages; sleep (1000); Application.ProcessMessages; sleep (1000); Application.ProcessMessages; end else i:=0; dec(i); end; if not DevPresent then begin Form1._msg('Phone not found... :('); Form1.SetBuzy; Form1.StatusBar.Panels[4].Text:=''; USBClosePort; exit; end; //Phone in Flash Mode??? CheckADLUpload[7]:=msgid; CheckADLUpload[8]:=ISIHeaderTransId; CheckADLUpload[9]:=$00; i:=USBBulkWritePort(@CheckADLUpload, Length(CheckADLUpload)); if i<>12 then begin Form1._msg('Bootcode start in CMT fail ! Need flash via programming device :('); Form1.TimConChk.Interval:=2000; result:=False; exit; end; USBBulkReadPort(12); if rxBuf[11]<>$04 then begin if rxBuf[11]<>$80 then begin Form1._msg('ADL Server not confirmed flashmode!'); Form1.SetReady; USBClosePort; exit; end else begin Form1._msg('ADL server [2nd] changing...'); rb:=rxBuf[11]; end; end else rb:=rxBuf[11]; // Form1._msg(Byte2Str(rb)); case rb of $04: begin s40prep04; end; $80: begin s40prep80; end; else begin Form1._msg('Error while prepare!'); Form1.setready; Exit; end; end; Form1._msg('ADL Server confirm flashmode!'); //Добавил для удобства кастом-прошивки Form1.statusbar.Panels[4].Text:='FLASHING'; Form1.statusbar.Panels[3].Text:='Connected'; Form1.TimConChk.Interval:=100; Application.ProcessMessages; if Form1.chkMCUen.Checked=true then begin Form1._msg(' ===Flashing [MCU]==='); Form1.pb1.ForeColor:=clRed; if not BB5_EraseFile(core) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Form1.pb1.progress:=0; Form1.pb1.ForeColor:=clGreen; if not BB5_WriteFile(core) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkPPMe.Checked=true then begin Form1._msg(' ===Flashing [PPM]==='); Form1.pb1.ForeColor:=clRed; if not BB5_EraseFile(ppm) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Form1.pb1.progress:=0; Form1.pb1.ForeColor:=clGreen; if not BB5_WriteFile(ppm) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkCNTe.Checked=true then begin Form1._msg(' ===Flashing [CNT]==='); Form1.pb1.ForeColor:=clRed; if not BB5_EraseFile(image) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Form1.pb1.progress:=0; if not BB5_WriteFile(image) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; Form1._msg(''); Form1._msg('Flashing done... Reboot phone now...'); Form1._msg(''); Application.ProcessMessages; Form1.statusbar.Panels[0].Text:=''; Form1.pb1.ForeColor:=clNavy; Form1.pbsm1.ForeColor:=clNavy; Form1.pb1.MaxValue:=100; Form1.pb1.progress:=0; Form1.statusbar.Panels[1].Text:=''; Form1.TimConChk.Interval:=2000; BB5_ADL_RestartMCU(rb); // режим рестарта Form1.pb1.color:=clActiveBorder; Application.ProcessMessages; Sleep(1000); Application.ProcessMessages; Sleep(1000); Application.ProcessMessages; i:=0; if catchdevice<>$01 then begin repeat Application.ProcessMessages; Sleep(1000); Inc(i); Application.ProcessMessages; until (catchdevice=$01) or (i=50); end; if (i=50) and (catchdevice<>$01) then begin Application.ProcessMessages; Sleep(200); Form1.SetReady; Form1.TimConChk.Enabled:=true; Form1._msg('Flashing Failed! :( Maybee HW error, or Downgrade try???!'); Form1._msg(''); Form1.DisconnectFill; Result:=false; exit; end; Form1.statusbar.Panels[6].Text:='BUSY'; //Form1.statusbar.Panels[0].Text:=USBReadPhName; //Form1.statusbar.Panels[1].Text:=UsbReadIMEIPl; Form1.afterFlashdo; Application.ProcessMessages; Sleep(200); Form1.TimConChk.Enabled:=true; Form1._msg('Done!'); Result:=true; end;//End of Normal Mode Flashing function BB5_DeadFlashing():boolean; var i,j,n,k,PktLen : integer; UAgent, ms, RAWBlock, RAWLoader, PASUB : TmemoryStream; s, needSert : String; Key, KeyLen : Byte; PacketLen : Byte; BlockCount : Byte; CurrBlock : Byte; CurrBlockLen : Word; b, proto : Boolean; begin Result:=false; Form1._msg('Dead Mode is Selected'); Form1._msg('Waiting for USB device...'); Form1._msg('--- Press phone'+#39+'s power button! ---'); Application.ProcessMessages; //Захват Nokia USB ROM устройства b:=false; i:=0; repeat if (i=1500) and (b=false) then begin Form1._msg('Phone not found.. :('); Form1.SetReady; form1.BtnDisable; Exit; end; Application.ProcessMessages; if catchdevice=$02 then begin b:=true; Form1._msg('Connection opened successfully'); end; inc(i); Application.ProcessMessages; until b ; Application.ProcessMessages; Form1._msg('Waiting for communication response.'); //Sleep(50); Application.ProcessMessages; if BB5_USB_BootRom_GetFirstBlock<>$60 then begin Form1.setready; Form1._msg('Error answer from BootRom'); result:=False; form1.BtnDisable; exit; end; //Парсинг Root Hash Application.ProcessMessages; FillMemory(@RAPInfo.Root_Key_Hash,$10,$00); FillMemory(@RAPInfo.APErootkey,$10,$00); FillMemory(@RAPInfo.FlashID,$A,$00); FillMemory(@RAPInfo.APEFlashID,$A,$00); FillMemory(@RAPInfo.PublicID,$14,$00); FillMemory(@RAPInfo.BootID,$8,$00); Application.ProcessMessages; //================================================================================================================================================================================================================================================================================ // Парсинг ответа 5800 (RM-356) на запрос BB5_USB_BootRom_GetFirstBlock // Лог MX-кея // RAP Data : // SYSTEM ASIC ID: 000000010000022600010006400C192101031103 [RAPIDO3G ver: 1.x] // EM1 ID: 00000295 // EM2 ID: 00000B22 // PUBLIC ID: 1FF0001841158B52064E64D3C3E9A7F38DC47E29 // ASIC MODE ID: 00 // ROOT KEY HASH: CAEEBB65D3C48E6DC73B49DC5063A2EE // ROM ID: 4B9B75103E691FF8 // RAPIDOv11_2nd.fg: [BB5] version: 1.30.0 revision: 0.0 size: 0x3AC0 // Supported RAP Ids: 0003192101002003, 000C192101002003, 4003192101002003, 400C192101002003, 4003192101011103, 400C192101011103, 4003192101021103, 400C192101021103, 4003192101031103, 400C192101031103, 4003192101011105, 400C192101011105, 400C192101021105, 400C192101031105 // FlashID0: 00EC 0040 - 0040 0121 [Samsung 2Gb DDP OneNAND,2 Gbits] type: ONENAND,RAP // ExtBUSC: 0000 0000 0000 0000 0000 0000 0000 0000 // ExtDEVC: FFFF 0000 - 0000 0000 // RAPIDOv11_algo.fg: [XSR 1.5] version: 1.35.0 revision: 0.0 size: 0x272B0 // Supported RAP Ids: 0003192101002003, 000C192101002003, 4003192101002003, 400C192101002003, 4003192101011103, 400C192101011103, 4003192101021103, 400C192101021103, 4003192101031103, 400C192101031103, 4003192101011105, 400C192101011105, 400C192101021105, 400C192101031105 // RAP PAPUBKEYS ID: 76A20187051C30162EE91C77AE5E6011F5F1BA61 // // Ответ на запрос B5_USB_BootRom_GetFirstBlock приходит в таком виде: // 6007011500000000010000022600010006400C1921010311030205000000029502050000000B221215001FF0 // 001841158B52064E64D3C3E9A7F38DC47E2913020000141100CAEEBB65D3C48E6DC73B49DC5063A2EE150900 // 4B9B75103E691FF8 // // Разбираем: // 60 - общая длина принятых данных ответа (переданных телефоном данных на запрос RootHash'a) // 07 - количество блоков данных в ответе // 0115 00 000000010000022600010006400C192101031103 - блок №1 ($01), его длина $15 - RAP SYSTEM ASIC ID // 0205 00 00000295 - блок №2 ($02), его длина $05 - RAP EM0 ID (ну или RAP EM1 ID - кто как считает с нуля или с единицы) // 0205 00 00000B22 - блок №3 ($02), его длина $05 - RAP EM1 ID (ну или RAP EM2 ID - кто как считает с нуля или с единицы) // 1215 00 1FF0001841158B52064E64D3C3E9A7F38DC47E29 - блок №4 ($12), его длина $15 - RAP PUBLIC ID // 1302 00 00 - блок №5 ($13), его длина $02 - RAP ASIC MODE ID // 1411 00 CAEEBB65D3C48E6DC73B49DC5063A2EE - блок №6 ($14), его длина $11 - RAP ROOT KEY HASH // 1509 00 4B9B75103E691FF8 - блок №7 ($15), его длина $09 - RAP ROM ID //================================================================================================================================================================================================================================================================================ i:=2; while i < Length(rxbuf) do begin Key :=rxbuf[i]; KeyLen:=rxbuf[i+1]; inc(i, 2); case Key of $01: begin for j:=$0 to KeyLen-1 do RAPInfo.FlashID[j]:= rxbuf[i+j]; inc(i, KeyLen); end; $12: begin // 0A900018A8B54650B9C89AA40EEC5059B5762F38 inc(i); for j:=0 to $13 do RAPInfo.PublicID[j]:= rxbuf[i+j]; inc(i, $14); end; $14: //Root Hash begin // BAF3A9C3DBFA8454937DB77F2B8852B1 inc(i); for j:=0 to $0F do RAPInfo.ROOT_KEY_HASH[j]:= rxbuf[i+j]; inc(i, $0F); end else inc(i, KeyLen); end;//End Of Case end; { Application.ProcessMessages; PacketLen :=rxbuf[0];//длина принятого пакета данных BlockCount :=rxbuf[1];//количество блоков i:=2;//текущий байт в пакете данных j:=0;//текущий номер блока while (i$B2 then begin Form1._msg('Erase: Invalid Image File'); USBClosePort; fs.Free; exit; end; fs.ReadBuffer(buf[0], 4);//Длина Flash Header HdrLen := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); fs.Seek(4,soFromCurrent); try while fs.Position<(HdrLen) do begin fs.ReadBuffer(CurrSeem, 1); case CurrSeem of $E4: begin // Form1._msg('SEEM: E4'); fs.ReadBuffer(buf[0], 2); CurrSeemLen:=(buf[0]*$100)+buf[1]; fs.Seek(CurrSeemLen, sofromCurrent); end; $E5: begin // Form1._msg('SEEM: E5'); fs.ReadBuffer(buf[0], 2); CurrSeemLen:=(buf[0]*$100)+buf[1]; fs.Seek(CurrSeemLen, sofromCurrent); end; $EA: begin // Form1._msg('SEEM: EA'); fs.ReadBuffer(buf[0], 2); CurrSeemLen:=(buf[0]*$100)+buf[1]; fs.Seek(CurrSeemLen, sofromCurrent); end; $EE: begin partition:=True; partitionstream:=TmemoryStream.Create; // Form1._msg('SEEM: EE'); fs.ReadBuffer(buf[0], 2); CurrSeemLen:=(buf[0]*$100)+buf[1]; partLen:=currseemlen; //fs.Seek(CurrSeemLen, sofromCurrent); partitionstream.copyFrom(fs,CurrSeemlen); /// ms.SaveToFile('C:\partition.bin'); Application.ProcessMessages; if partition=True then begin RebuildPartition(partitionstream,partLen); partitionstream.Free; partition:=false; Application.ProcessMessages; end; end; $F3: begin // Form1._msg('SEEM: F3'); fs.ReadBuffer(buf[0], 2); CurrSeemLen:=(buf[0]*$100)+buf[1]; fs.Seek(CurrSeemLen, sofromCurrent); end; $FA: begin // Form1._msg('SEEM: FA'); streamlen:=TmemoryStream.Create; streamlen.CopyFrom(fs,$E); // создавал поток, потому что иначе пока не умею streamlen.Seek(1, sofromBeginning); // пропускаем один байт streamlen.ReadBuffer(loaderlen,4); // читаем длину - это длина всего адресного пространства блока FA, которое занимает апдейт апп, сразу после блока длины. dwordswap(@loaderlen); // разворачиваем fs.seek(loaderlen-9,sofromcurrent); // меняем позицию - после идут старые добрые С8 Application.ProcessMessages; streamlen.Free; end; $C8: begin fs.ReadBuffer(buf[0], 1); CurrSeemLen:=buf[0]; fs.ReadBuffer(CurSeemcount, 1); //Form1._msg(''); // Form1._msg('Found '+IntToStr(CurrSeemLen)+' flash chips to erase'); for n:=1 to CurSeemcount do begin fs.ReadBuffer(currseem,1); case currseem of $12: begin FlashCfg:=$12; fs.ReadBuffer(CurrEraseLen, 1); Dec(CurrEraseLen, 3); fs.ReadBuffer(Byte1, 1); fs.ReadBuffer(Byte2, 1); fs.ReadBuffer(Byte3, 1); EraseCnt:=CurrEraseLen div 8; Form1._msg('Found '+IntToStr(EraseCnt)+' areas to erase'); fs.ReadBuffer(buf[0], CurrEraseLen); if byte2=$00 then begin Application.ProcessMessages; fullerase:=0; for j:=0 to EraseCnt-1 do begin EraseStart[n] := HexToInt(IntToHex(buf[j*8], 2)+IntToHex(buf[j*8+1], 2)+IntToHex(buf[j*8+2], 2)+IntToHex(buf[j*8+3], 2)); EraseStop[n] := HexToInt(IntToHex(buf[j*8+4], 2)+IntToHex(buf[j*8+5], 2)+IntToHex(buf[j*8+6], 2)+IntToHex(buf[j*8+7], 2)); fullErase:=fullerase+(EraseStop[n]-EraseStart[n]); end; Form1.pb1.MaxValue:=fullerase div $54000; Application.ProcessMessages; end; for j:=0 to EraseCnt-1 do begin Form1.statusbar.Panels[0].Text:=''; Form1.statusbar.Panels[1].Text:=''; EraseStart[n] := HexToInt(IntToHex(buf[j*8], 2)+IntToHex(buf[j*8+1], 2)+IntToHex(buf[j*8+2], 2)+IntToHex(buf[j*8+3], 2)); EraseStop[n] := HexToInt(IntToHex(buf[j*8+4], 2)+IntToHex(buf[j*8+5], 2)+IntToHex(buf[j*8+6], 2)+IntToHex(buf[j*8+7], 2)); Form1.statusbar.Panels[0].Text:='Erase Area: '+ IntToStr(j+1); // Form1._msg('Erase Area: '+ IntToStr(j+1) + ' EraseStart: ' + inttohex(EraseStart[n],8) + ' EraseStop: ' + inttohex(EraseStop[n], 8)); //if not BB5_EraseSegment(EraseStart[n], EraseStop[n], FlashCfg, Byte1, Byte2, Byte3) then //raise E.Create('Erasure error, Area: '+IntToStr(n)); case byte2 of $00: begin if not BB5_EraseAreaSmallBlock(EraseStart[n], EraseStop[n], FlashCfg, Byte1, Byte2, Byte3) then raise E.Create('Erasure error, Area: '+IntToStr(n)); end; $01: begin if not BB5_EraseArea(EraseStart[n], EraseStop[n], FlashCfg, Byte1, Byte2, Byte3) then raise E.Create('Erasure error, Area: '+IntToStr(n)); Form1.pb1.progress:=Form1.pb1.progress+10; end; $03: begin if not BB5_EraseArea(EraseStart[n], EraseStop[n], FlashCfg, Byte1, Byte2, Byte3) then raise E.Create('Erasure error, Area: '+IntToStr(n)); Form1.pb1.progress:=Form1.pb1.progress+10; end; end; Application.ProcessMessages; end; Form1.statusbar.Panels[0].Text:=''; Form1.statusbar.Panels[1].Text:=''; // Form1._msg(''); end; $19: begin fs.ReadBuffer(partitionlen,1); fs.readbuffer(pcfg,1); ////1B 00 10 6F 00 2E 00 14 06 92 txBuf[0]:=$1B; txBuf[1]:=$00; txBuf[2]:=$10; txBuf[3]:=$6F; txBuf[4]:=$00; txBuf[5]:=partitionlen-1; txBuf[6]:=$00; txBuf[7]:=$15; txBuf[8]:=ISIHeaderTransId; txBuf[9]:=$92; fs.ReadBuffer(txBuf[10], partitionlen-4); usbbulkWriteport(@txbuf[0], partitionlen+5); if usbbulkreadport($ffff) then begin //form1._msg(buftohexstr(@rxbuf[0], length(rxbuf))); if (rxBuf[9]=$93) and (rxBuf[10]=0) and (rxBuf[11]=0 ) then begin Form1._msg('Partition erase Ok'); end else begin Form1._msg('Partition erase Error :('); end; end; Application.ProcessMessages; end; end; end; Result:=True; Application.ProcessMessages; Form1.pbsm1.Progress:=0; fs.Free; exit; // fs.Seek(HdrLen, sofromBeginning); end else begin //Form1._msg('SEEM : '+byte2str(currseem)); fs.ReadBuffer(buf[0], 1); CurrSeemLen:=buf[0]; fs.readbuffer(buf[0],CurrSeemLen); // form1._msg(buftohexstr(@buf[0], currseemlen)); // if CurrSeemLen<1 then fs.ReadBuffer(CurrSeemLen, 1); application.ProcessMessages; end; end; end; fs.Free; except on E:Exception do begin fs.Free; Form1._msg('EraseFile: Error: '+E.Message); end; end; Application.ProcessMessages; fullerase:=0; Form1.pb1.MaxValue:=100; Form1.pb1.Progress:=0; end; function BB5_EraseArea(Start, Stop: LongInt; FlashCfg,Byte1,Byte2,Byte3:byte):boolean; var n : Integer; FlashType, Subsystem : String; begin Result:=False; case Byte1 of $00: Subsystem:='CMT'; $01: Subsystem:='APE'; else Subsystem:='Unknown ('+IntToStr(Byte1)+')'; end; case Byte2 of $00: FlashType:='NOR'; $03: FlashType:='NAND'; $01: FlashType:='NAND'; else FlashType:='Unknown ('+IntToStr(Byte2)+')'; end; case byte1 of 0: begin //Transanc.Id Erase[3] := $6F; Erase[7] := msgid; Erase[8] := ISIHeaderTransId; Erase[9] := $42; //Config Erase[10] := Byte1; Erase[11] := $01; Erase[12] := FlashCFG; Erase[13] := $0c; Erase[14] := Byte2; Erase[15] := Byte3; end; 1: begin //APE try Erase[3] := $21; Erase[7] := msgid; Erase[8] := ISIHeaderTransId; Erase[9] := $42; //Config Erase[10] := $00; Erase[11] := $01; Erase[12] := FlashCFG; Erase[13] := $0c; Erase[14] := Byte2; Erase[15] := Byte3; end; end; //Begin Block Erase[16] := Start div $1000000; Erase[17] := Start div $10000; Erase[18] := Start div $100; Erase[19] := Start mod $100; //End Block Erase[20] := Stop div $1000000; Erase[21] := Stop div $10000; Erase[22] := Stop div $100; Erase[23] := Stop mod $100; Form1._msg('Erasing area 0x'+IntToHex(Start,8)+' - 0x'+IntToHex(Stop, 8)+ ', '+FlashType+', '+Subsystem); Application.processmessages; n:=USBBulkWritePort(@Erase[0], Length(Erase)); if n<>24 then exit; if Not USBBulkReadPort(16) or (Length(rxBuf)<16) then exit; Application.processmessages; if rxBuf[8]<>Erase[8] then exit; //целостность транзанкций if Word((@rxBuf[14])^)=$00 then Form1._msg('Result: '+IntToHex(Word((@rxBuf[14])^), 4)); Result:=True; end; function BB5_EraseAreaSmallBlock(Start, Stop: LongInt; FlashCfg,Byte1,Byte2,Byte3:byte):boolean; var n, PktLen : Integer; FlashType, Subsystem : String; b, k : Boolean; begin Result:=False; b:=true; k:=true; PktLen:=$54000; case Byte1 of $00: Subsystem:='CMT'; $01: Subsystem:='APE'; else Subsystem:='Unknown ('+IntToStr(Byte1)+')'; end; case Byte2 of $00: FlashType:='NOR'; $03: FlashType:='NAND'; $01: FlashType:='NAND'; else FlashType:='Unknown ('+IntToStr(Byte2)+')'; end; case byte1 of 0: begin //Transanc.Id Erase[3] := $6F; Erase[7] := msgid; Erase[8] := ISIHeaderTransId; Erase[9] := $42; //Config Erase[10] := Byte1; Erase[11] := $01; Erase[12] := FlashCFG; Erase[13] := $0c; Erase[14] := Byte2; Erase[15] := Byte3; end; 1: begin //APE try Erase[3] := $21; Erase[7] := msgid; Erase[8] := ISIHeaderTransId; Erase[9] := $42; //Config Erase[10] := $00; Erase[11] := $01; Erase[12] := FlashCFG; Erase[13] := $0c; Erase[14] := Byte2; Erase[15] := Byte3; end; end; Form1._msg('Erasing area 0x'+IntToHex(Start,8)+' - 0x'+IntToHex(Stop, 8)+ ', '+FlashType+', '+Subsystem); while (Start24 then exit; if Not USBBulkReadPort(16) or (Length(rxBuf)<16) then exit; Application.processmessages; if rxBuf[8]<>Erase[8] then exit; //целостность транзанкций if Word((@rxBuf[14])^)<>$00 then begin k:=false; b:=false; continue; end; Application.ProcessMessages; Form1.pb1.Progress:=Form1.pb1.progress+1; Start:=Start+PktLen; end; if k then Form1._msg('Result: '+IntToHex(Word((@rxBuf[14])^), 4)) else Form1._msg('Error Eraising Area: 0x'+IntToHex(Start, 4)+' - 0x'+IntToHex(Stop, 4)); Result:=k; end; function BB5_EraseSegment(startSegment, stopSegment: LongInt; FlashCfg,Byte1,Byte2,Byte3:byte):boolean; var SectorsToErase,i : integer; CurrentSector : LongInt; CurrEraseSize : LongInt; FlashType,Subsystem : string; begin Result:=False; SectorsToErase:=(StopSegment-StartSegment) div BB5_EraseSectorSize; if ((StopSegment-StartSegment) mod BB5_EraseSectorSize) > 0 then inc(SectorsToErase); case Byte1 of $00: Subsystem:='CMT'; $01: Subsystem:='APE'; else Subsystem:='Unknown ('+IntToStr(Byte1)+')'; end; case Byte2 of $00: FlashType:='NOR'; $03: FlashType:='NAND'; $01: FlashType:='NAND'; else FlashType:='Unknown ('+IntToStr(Byte2)+')'; end; //Form1._msg('Erasing area 0x'+IntToHex(StartSegment,8)+' - 0x'+IntToHex(StopSegment,8)+', Type: '+FlashType+', Subsystem: '+Subsystem); Application.processmessages; StopSegment :=StopSegment+1; CurrentSector :=StartSegment; CurrEraseSize :=BB5_EraseSectorSize; for i:=0 to SectorsToErase-1 do begin if ((i=SectorsToErase-1) and (((StopSegment-StartSegment) mod BB5_EraseSectorSize) > 0)) then CurrEraseSize:=((StopSegment-StartSegment) mod BB5_EraseSectorSize); if not BB5_EraseSector(CurrentSector, CurrEraseSize, FlashCfg, Byte1, Byte2, Byte3) then exit; CurrentSector:=CurrentSector+CurrEraseSize; Application.ProcessMessages; end; Result:=True; end; function BB5_EraseSector(startSector,EraseSectorSize:LongInt; FlashCfg,Byte1,Byte2,Byte3:byte):boolean; var n: integer; str:string; begin Result:=False; Application.ProcessMessages; {Erase : array[0..23] of Byte = ($1B, $00, $10, $6F, $00, $12, $00, $16, $00, $42, $00, $01, $00, $0C, $00, $00, $00, $00, $00, $C0, $00, $00, $00, $00);} case byte1 of 0: begin //Transanc.Id Erase[3] := $6F; Erase[7] := msgid; Erase[8] := ISIHeaderTransId; Erase[9] := $42; //Config Erase[10] := Byte1; Erase[11] := $01; Erase[12] := FlashCFG; Erase[13] := $0c; Erase[14] := Byte2; Erase[15] := Byte3; end; 1: begin //APE try Erase[3] := $21; Erase[7] := msgid; Erase[8] := ISIHeaderTransId; Erase[9] := $42; //Config Erase[10] := $00; Erase[11] := $01; Erase[12] := FlashCFG; Erase[13] := $0c; Erase[14] := Byte2; Erase[15] := Byte3; end; end; //Begin Block Erase[16] := StartSector div $1000000; Erase[17] := StartSector div $10000; Erase[18] := StartSector div $100; Erase[19] := StartSector mod $100; StartSector:=StartSector+(EraseSectorSize-1); //End Block Erase[20] := StartSector div $1000000; Erase[21] := StartSector div $10000; Erase[22] := StartSector div $100; Erase[23] := StartSector mod $100; n:=USBBulkWritePort(@Erase[0], Length(Erase)); if n<>24 then exit; if Not USBBulkReadPort(16) or (Length(rxBuf)<16) then exit; if rxBuf[8]<>txBuf[8] then exit; //целостность транзанкций if rxBuf[15]<>$00 then exit; str:=BufToHex_Str(@Erase, Length(Erase)); Form1._msg(str); Result:=True; end; function BB5_WriteFile(core: string):boolean; const Write_Split : word = $8000; var buf :array[0..$3FFFF] of byte; EntryPoint, DataLen, TargetOffset, CRCTmp : LongInt; i, n, Blocks, Packets,icl, CurrPacketSize : Integer; cf1,cf2,cf3,apeb : byte; good : Integer; CertName,AsicType : String; PAPUB_Already, APE_PAPUB : boolean; fs : TFileStream; writen : Dword; cmtcount,cmtdin,apedin, apecount,TokenType, unk : integer; begin Result:=False; Form1._msg('Write : Processing '+ExtractFileName(core)); fs:=TFileStream.Create(core,fmOpenRead); fs.Seek(0, sofromBeginning); Blocks:=0; cmtcount:=0; cmtdin:=0; apecount:=0; apedin:=0; unk:=0; Form1.pb1.ForeColor:=clGreen; Form1.pb1.progress:=0; Application.ProcessMessages; try fs.Read(i,1); if i<>$B2 then raise E.Create('Write : Bad image file'); fs.ReadBuffer(buf[0], 4);//Длина Flash Header DataLen := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); fs.Seek(DataLen,soFromCurrent); EntryPoint := fs.Position; //Form1._msg('Counting data+cert blocks...'); while fs.Position$54) and (buf[0]<>$5D) then raise E.Create('Write : Bad image file, Corrupted Data/Cert blocks!' ); case buf[0] of $54://Phoenix-token begin fs.ReadBuffer(buf[0], $3); case buf[1] of $17 : begin fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[6], 2)+IntToHex(buf[7], 2)+IntToHex(buf[8], 2)+IntToHex(buf[9], 2)); TokenType := buf[0]; case tokentype of 0:Inc(cmtcount); 1:Inc(apecount); else inc(unk); end; //Form1._msg(inttohex(buf[0],2)+inttohex(buf[1],2)); fs.Seek(DataLen,soFromCurrent); inc(blocks); continue; end; $2E : begin fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[17], 2)+IntToHex(buf[18], 2)+IntToHex(buf[19], 2)+IntToHex(buf[20], 2)); TokenType := buf[0]; case tokentype of 0:Inc(cmtcount); 1:Inc(apecount); else inc(unk); end; // Form1._msg(inttohex(buf[0],2)+inttohex(buf[1],2)); fs.Seek(DataLen,soFromCurrent); inc(blocks); continue; end; else begin fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[6], 2)+IntToHex(buf[7], 2)+IntToHex(buf[8], 2)+IntToHex(buf[9], 2)); fs.Seek(DataLen,soFromCurrent); inc(blocks); continue; end; end; end; $5D://Phoenix-segment begin fs.ReadBuffer(buf[0], $3); fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[37], 2)+IntToHex(buf[38], 2)+IntToHex(buf[39], 2)+IntToHex(buf[40], 2)); TokenType := buf[32]; case tokentype of 0:Inc(cmtcount); 1:Inc(apecount); else inc(unk); end; //Form1._msg(inttohex(buf[32],2)+inttohex(buf[33],2)); //Form1._msg(inttohex(buf[32],2)+inttohex(buf[33],2)+inttohex(buf[34],2)+inttohex(buf[35],2)); fs.Seek(DataLen,soFromCurrent); inc(blocks); continue; end; end; end; writen:=0; if Blocks=0 then begin Form1._msg('No any data for write, skip write'); fs.Free; result:=True; Exit; end; Form1._msg('Total '+IntToStr(blocks)+' ['+inttostr(cmtcount)+'/'+inttostr(apecount)+'/'+inttostr(unk)+'] blocks to write, writing... '); Application.ProcessMessages; Form1.statusbar.Panels[0].text:='Write Data....'; //Form1.statusbar.panels[1].text:='Time : '+inttostr(blocks div 10)+' sec...'; Form1.pb1.progress:=0; Form1.pb1.MaxValue:=Blocks; fs.Seek(EntryPoint, soFromBeginning); Application.ProcessMessages; Form1.statusbar.Panels[1].text:='0/'+inttostr(cmtcount); while fs.Position$54) and (buf[0]<>$5D) then raise E.Create('Bad image file! Write terminated!'); case buf[0] of $54://Phoenix-token begin fs.ReadBuffer(buf[0], $3); case buf[1] of $17: begin fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[6], 2)+IntToHex(buf[7], 2)+IntToHex(buf[8], 2)+IntToHex(buf[9], 2)); TargetOffset := HexToInt(IntToHex(buf[10], 2)+IntToHex(buf[11], 2)+IntToHex(buf[12], 2)+IntToHex(buf[13], 2)); Application.ProcessMessages; WriteData[6] := buf[0]; WriteData[7] := msgid; WriteData[8] := ISIHeaderTransId; WriteData[9] := $4C; WriteData[10] := buf[1]; WriteData[11] := buf[2]; cf1:=buf[0]; cf2:=buf[1]; cf3:=buf[2]; apeb:=buf[0]; WriteData[12] := buf[6]; WriteData[13] := buf[7]; WriteData[14] := buf[8]; WriteData[15] := buf[9]; WriteData[16] := buf[10]; WriteData[17] := buf[11]; WriteData[18] := buf[12]; WriteData[19] := buf[13]; case apeb of 0: begin WriteData[3]:=$6F; WriteData[6]:=$00; cmtdin:=cmtdin+1; Form1.statusbar.Panels[1].text:='CMT : '+inttostr(cmtdin)+'/'+inttostr(cmtcount); Application.ProcessMessages; end; 1: begin WriteData[3]:=$21; WriteData[6]:=$00; apedin:=apedin+1; Form1.statusbar.Panels[1].text:='APE : '+inttostr(apedin)+'/'+inttostr(apecount); Application.ProcessMessages; end; else begin WriteData[3]:=$6F; WriteData[6]:=$00; end; end; {=============================================================================================================================================================} n:=USBBulkWritePort(@WriteData, 36); if n<>36 then raise E.Create('Write Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if Not USBBulkReadPort(12) or (Length(rxBuf)<12) then raise E.Create('Write Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if rxBuf[8]<>WriteData[8] then raise E.Create('Write Failed, (trans-err), at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8));//целостность транзанкций if rxBuf[11]<>$00 then raise E.Create('Write Failed, err4, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); {--------------------------------------------------------------------------------------------------------------------------------------------------------------} //Form1._msg('Send : '+BufToHex_Str(@WriteData, 36)); //Form1._msg('Receiv: '+BufToHex_Str(@rxBuf, n)); {=============================================================================================================================================================} Application.ProcessMessages; end; $2E: begin fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[17], 2)+IntToHex(buf[18], 2)+IntToHex(buf[19], 2)+IntToHex(buf[20], 2)); TargetOffset := HexToInt(IntToHex(buf[21], 2)+IntToHex(buf[22], 2)+IntToHex(buf[23], 2)+IntToHex(buf[24], 2)); //form1._msg(byte2str(buf[21])+byte2str(buf[22])+byte2str(buf[23])+byte2str(buf[24])); Application.ProcessMessages; WriteData[6] := buf[0]; WriteData[7] := msgid; WriteData[8] := ISIHeaderTransId; WriteData[9] := $4C; WriteData[10] := buf[1]; WriteData[11] := buf[2]; cf1:=buf[0]; cf2:=buf[1]; cf3:=buf[2]; apeb:=buf[0]; dword((@writedata[12])^):=datalen; dwordswap(@writedata[12]); WriteData[16] := buf[21]; WriteData[17] := buf[22]; WriteData[18] := buf[23]; WriteData[19] := buf[24]; WriteData[20] := buf[5]; WriteData[21] := buf[6]; WriteData[22] := buf[7]; WriteData[23] := buf[8]; WriteData[24] := buf[9]; WriteData[25] := buf[10]; WriteData[26] := buf[11]; WriteData[27] := buf[12]; WriteData[28] := buf[13]; WriteData[29] := buf[14]; WriteData[30] := buf[15]; WriteData[31] := buf[16]; case apeb of 0: begin WriteData[3]:=$6F; WriteData[6]:=$00; cmtdin:=cmtdin+1; Form1.statusbar.Panels[1].text:='CMT : '+inttostr(cmtdin)+'/'+inttostr(cmtcount); Application.ProcessMessages; end; 1: begin WriteData[3]:=$21; WriteData[6]:=$00; apedin:=apedin+1; Form1.statusbar.Panels[1].text:='APE : '+inttostr(apedin)+'/'+inttostr(apecount); Application.ProcessMessages; end; else begin WriteData[3]:=$6F; WriteData[6]:=$00; end; end; {=============================================================================================================================================================} n:=USBBulkWritePort(@WriteData, 36); if n<>36 then raise E.Create('Write Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if Not USBBulkReadPort(12) or (Length(rxBuf)<12) then raise E.Create('Write Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if rxBuf[8]<>WriteData[8] then raise E.Create('Write Failed, (trans-err), at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8));//целостность транзанкций if rxBuf[11]<>$00 then raise E.Create('Write Failed, err4, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); {--------------------------------------------------------------------------------------------------------------------------------------------------------------} //Form1._msg('Send : '+BufToHex_Str(@WriteData, 36)); //Form1._msg('Receiv: '+BufToHex_Str(@rxBuf, n)); {=============================================================================================================================================================} for icl:=20 to 31 do WriteData[icl]:=$00; Application.ProcessMessages; end; else begin fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[6], 2)+IntToHex(buf[7], 2)+IntToHex(buf[8], 2)+IntToHex(buf[9], 2)); TargetOffset := HexToInt(IntToHex(buf[10], 2)+IntToHex(buf[11], 2)+IntToHex(buf[12], 2)+IntToHex(buf[13], 2)); WriteData[6] := buf[0]; WriteData[7] := msgid; WriteData[8] := ISIHeaderTransId; WriteData[9] := $4C; WriteData[10] := buf[1]; WriteData[11] := buf[2]; cf1:=buf[0]; cf2:=buf[1]; cf3:=buf[2]; apeb:=buf[0]; WriteData[12] := buf[6]; WriteData[13] := buf[7]; WriteData[14] := buf[8]; WriteData[15] := buf[9]; WriteData[16] := buf[10]; WriteData[17] := buf[11]; WriteData[18] := buf[12]; WriteData[19] := buf[13]; case apeb of 0: begin WriteData[3]:=$6F; WriteData[6]:=$00; cmtdin:=cmtdin+1; Form1.statusbar.Panels[1].text:='CMT : '+inttostr(cmtdin)+'/'+inttostr(cmtcount); Application.ProcessMessages; end; 1: begin WriteData[3]:=$21; WriteData[6]:=$00; apedin:=apedin+1; Form1.statusbar.Panels[1].text:='APE : '+inttostr(apedin)+'/'+inttostr(apecount); Application.ProcessMessages; end; else begin WriteData[3]:=$6F; WriteData[6]:=$00; end; end; {=============================================================================================================================================================} n:=USBBulkWritePort(@WriteData, 36); if n<>36 then raise E.Create('Write Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if Not USBBulkReadPort(12) or (Length(rxBuf)<12) then raise E.Create('Write Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if rxBuf[8]<>WriteData[8] then raise E.Create('Write Failed, (trans-err), at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8));//целостность транзанкций if rxBuf[11]<>$00 then raise E.Create('Write Failed, err4, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); {--------------------------------------------------------------------------------------------------------------------------------------------------------------} //Form1._msg('Send : '+BufToHex_Str(@WriteData, 36)); //Form1._msg('Receiv: '+BufToHex_Str(@rxBuf, n)); {=============================================================================================================================================================} Application.ProcessMessages; end; end; Application.ProcessMessages; Form1.pb1.progress:=Form1.pb1.progress+1; // Header written... now Rock'n'Roll! fs.ReadBuffer(buf[0], DataLen); Packets:=1; CurrPacketSize:=DataLen; if DataLen>Write_Split then begin Packets:=DataLen div Write_Split; if (DataLen mod Write_Split) > 0 then inc(Packets); CurrPacketSize:=Write_Split; end; for i:=0 to Packets-1 do begin if (i=Packets-1) and (Packets>1) then begin if (DataLen mod Write_Split)>0 then CurrPacketSize:=(DataLen mod Write_Split) else CurrPacketSize:=Write_Split; end; txBuf[0] := $1B; txBuf[1] := $00; txBuf[2] := $10; txBuf[3] := $6F; txBuf[4] := ((CurrPacketSize+8) div $100); txBuf[5] := ((CurrPacketSize+8) mod $100); txBuf[6] := cf1; txBuf[7] := msgid; txBuf[8] := ISIHeaderTransId; txBuf[9] := $4B; txBuf[10] := (CurrPacketSize div $100); txBuf[11] := (CurrPacketSize mod $100); txBuf[12] := $00; txBuf[13] := $00; for n:=0 to CurrPacketSize-1 do begin txBuf[14+n] := buf[(i*Write_Split)+n]; end; CrcTmp:=$0000; for n:=0 to CurrPacketSize-1 do begin if (n mod 2)=0 then CrcTmp:=CrcTmp xor ( (txBuf[14+n]*$100) + (txBuf[14+n+1])); end; CrcTmp := CrcTmp AND $FFFF; txBuf[12] := CrcTmp div $100; txBuf[13] := CrcTmp mod $100; case apeb of 0: begin txbuf[3]:=$6F; txbuf[6]:=$00; end; 1: begin txbuf[3]:=$21; txbuf[6]:=$00; end; else begin txbuf[3]:=$6F; txbuf[6]:=$00; end; end; {=============================================================================================================================================================} n:=USBBulkWritePort(@txBuf, 14+CurrPacketSize); if n<>14+CurrPacketSize then raise E.Create('Write Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if Not USBBulkReadPort(16) or (Length(rxBuf)<16) then raise E.Create('Write Failed, err2, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if rxBuf[8]<>txBuf[8] then raise E.Create('Write Failed,(trans-err), at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8));//целостность транзанкций if rxBuf[15]<>$00 then raise E.Create('Write Failed, err3, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); {--------------------------------------------------------------------------------------------------------------------------------------------------------------} //Form1._msg('Send : '+BufToHex_Str(@WriteData, 36)); //Form1._msg('Receiv: '+BufToHex_Str(@rxBuf, n)); {=============================================================================================================================================================} end; continue; end;//end of case $54 - write Data $5D://Phoenix-segment begin fs.ReadBuffer(buf[0], 3); fs.ReadBuffer(buf[0], buf[2]+1); DataLen := HexToInt(IntToHex(buf[37], 2)+IntToHex(buf[38], 2)+IntToHex(buf[39], 2)+IntToHex(buf[40], 2)); TargetOffset := HexToInt(IntToHex(buf[41], 2)+IntToHex(buf[42], 2)+IntToHex(buf[43], 2)+IntToHex(buf[44], 2)); apeb:=buf[32]; //form1._msg(byte2str(buf[32])); Application.ProcessMessages; case apeb of 0: begin good:=0; for i:=$0 to $0F do if RAPInfo.Root_Key_Hash[i]=buf[i] then inc(good); if good<$10 then begin fs.Seek(DataLen, sofromCurrent); continue; end; AsicType:='CMT : '; end; 1: begin good:=0; for i:=$0 to $0F do if RAPInfo.APErootkey[i]=buf[i] then inc(good); if good<$10 then begin fs.Seek(DataLen, sofromCurrent); continue; end; AsicType:='APE : '; end; else begin good:=0; for i:=$0 to $0F do if RAPInfo.Root_Key_Hash[i]=buf[i] then inc(good); if good<$10 then begin fs.Seek(DataLen, sofromCurrent); continue; end; AsicType:='CMT : '; end; end; CertName:=''; for i:=20 to 31 do if buf[i]=$00 then break else CertName:=CertName+Chr(buf[i]); Form1._msg(AsicType+'Writing Hash CERT ['+CertName+']'); Application.ProcessMessages; txBuf[0] := $1B; txBuf[1] := $00; txBuf[2] := $10; txBuf[3] := $6F; txBuf[4] := $00; txBuf[5] := $1E; txBuf[6] := $00; txBuf[7] := msgid; txBuf[8] := ISIHeaderTransId; txBuf[9] := $4C; txBuf[10] := buf[33]; txBuf[11] := buf[34]; cf1:=buf[32]; cf2:=buf[33]; cf3:=buf[34]; txBuf[12] := buf[37]; txBuf[13] := buf[38]; txBuf[14] := buf[39]; txBuf[15] := buf[40]; txBuf[16] := buf[41]; txBuf[17] := buf[42]; txBuf[18] := buf[43]; txBuf[19] := buf[44]; for i:=20 to 35 do txBuf[i]:=$00; case apeb of 0: begin if CertName='PAPUBKEYS' then begin if not PAPUB_Already then begin Form1._msg('CMT : Patch '+CertName); txBuf[16] := $00; txBuf[17] := $00; txBuf[18] := $00; txBuf[19] := $00; for i:=20 to 31 do txBuf[i]:=buf[i]; PAPUB_Already:=True; end else begin Form1._msg('CMT : PAPUBKEYS'+' Skip'); end; end; end; 1: begin if CertName='PAPUBKEYS' then begin if not APE_PAPUB then begin Form1._msg('APE : Patch '+CertName); txBuf[16] := $00; txBuf[17] := $00; txBuf[18] := $00; txBuf[19] := $00; for i:=20 to 31 do txBuf[i]:=buf[i]; APE_PAPUB:=True; end else begin Form1._msg('APE : PAPUBKEYS'+' Skip'); end; end; end; end; case apeb of 0: begin txbuf[3]:=$6F; cmtdin:=cmtdin+1; Form1.statusbar.Panels[1].text:='CMT : '+inttostr(cmtdin)+'/'+inttostr(cmtcount); Application.ProcessMessages; end; 1: begin txbuf[3]:=$21; apedin:=apedin+1; Form1.statusbar.Panels[1].text:='APE : '+inttostr(apedin)+'/'+inttostr(apecount); Application.ProcessMessages; end; else begin txbuf[3]:=$6F; end; end; // form1._msg(BufToHexStr(@txbuf[1],36)); // Form1._msg(''); Application.ProcessMessages; {=============================================================================================================================================================} n:=USBBulkWritePort(@txBuf, 36); if n<>36 then raise E.Create('Write CERT Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if Not USBBulkReadPort(12) or (Length(rxBuf)<12) then raise E.Create('Write CERT Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if rxBuf[8]<>txBuf[8] then raise E.Create('Write CERT Failed, (trans-err), at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8));//целостность транзанкций if rxBuf[11]<>$00 then raise E.Create('Write CERT Failed, err4, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); {--------------------------------------------------------------------------------------------------------------------------------------------------------------} //Form1._msg('SendPrologiSert: '+BufToHex_Str(@txBuf, 36)); //Form1._msg('RecPrologiSert : '+BufToHex_Str(@rxBuf, n)); {=============================================================================================================================================================} // Шапка записана - Зажигаем! =) fs.ReadBuffer(buf[0], DataLen); Packets:=1; CurrPacketSize:=DataLen; if DataLen>Write_Split then begin Packets:=DataLen div Write_Split; if (DataLen mod Write_Split) > 0 then inc(Packets); CurrPacketSize:=Write_Split; end; for i:=0 to Packets-1 do begin if (i=Packets-1) and (Packets>1) then begin if (DataLen mod Write_Split)>0 then CurrPacketSize:=(DataLen mod Write_Split) else CurrPacketSize:=Write_Split; end; txBuf[0] := $1B; txBuf[1] := $00; txBuf[2] := $10; case ApeB of 0:txBuf[3] := $6F; 1:txBuf[3] := $21; else txBuf[3]:= $6F; end; txBuf[4] := ((CurrPacketSize+8) div $100); txBuf[5] := ((CurrPacketSize+8) mod $100); txBuf[6] := $00; txBuf[7] := msgid; txBuf[8] := ISIHeaderTransId; txBuf[9] := $4B; txBuf[10] := (CurrPacketSize div $100); txBuf[11] := (CurrPacketSize mod $100); for n:=0 to CurrPacketSize-1 do begin txBuf[14+n] := buf[(i*Write_Split)+n]; end; CrcTmp:=$0000; for n:=0 to CurrPacketSize-1 do begin if (n mod 2)=0 then CrcTmp:=CrcTmp xor ( (txBuf[14+n]*$100) + (txBuf[14+n+1])); end; CrcTmp := CrcTmp AND $FFFF; txBuf[12] := CrcTmp div $100; txBuf[13] := CrcTmp mod $100; {=============================================================================================================================================================} n:=USBBulkWritePort(@txBuf, 14+CurrPacketSize); if n<>14+CurrPacketSize then raise E.Create('Write CERT Failed, err1, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if Not USBBulkReadPort(16) or (Length(rxBuf)<16) then raise E.Create('Write CERT Failed, err2, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); if rxBuf[8]<>txBuf[8] then raise E.Create('Write CERT Failed, (trans-err), at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8));//целостность транзанкций if rxBuf[11]<>$00 then raise E.Create('Write CERT Failed, err2, at '+IntToHex(TargetOffset, 8)+':'+IntToHex(DataLen,8)); {--------------------------------------------------------------------------------------------------------------------------------------------------------------} //Form1._msg(BufToHex_Str(@txBuf, 14+CurrPacketSize)); //Form1._msg(BufToHex_Str(@rxBuf, n); {=============================================================================================================================================================} end; continue; form1.pb1.progress:=form1.pb1.progress+1; Application.ProcessMessages; end;//end of case $5D - write Sert end; end; Result:=True; fs.Free; except on E:Exception do begin fs.Free; Form1._msg('Error: '+E.Message); Form1.pb1.Progress:=0; USBClosePort; exit; end; end; Form1.pb1.Progress:=0; end; function USBControlPacket(_Class: LongWord; Length: longword; Expected:Integer):Boolean; var i : integer; Count : LongWord; Buffer : array[0..$FFFE] of byte; begin Result:=False; rxBuf:=nil; SetLength(rxBuf, 1); if hDevice = INVALID_HANDLE_VALUE then exit; if not DeviceIOControl(hDevice, _Class, @txBuf, Length, @Buffer, Expected, Count, nil) then exit; SetLength(rxBuf, Count); for i := 0 to Count - 1 do rxBuf[i]:=Buffer[i]; Result:=(Count=Expected); end; function BB5_USB_BootRom_GetFirstBlock:integer; begin Result:=0; txBuf[0]:=$40; txBuf[1]:=$59; txBuf[2]:=$00; txBuf[3]:=$00; txBuf[4]:=$00; txBuf[5]:=$00; txBuf[6]:=$00; txBuf[7]:=$00; try if USBControlPacket($222040, $8, 0) then begin Application.ProcessMessages; Form1._msg('[BB5 FLASH]: Bootrom Ok!'); end else begin Form1._msg('[BB5 FLASH]: Can'+#39+'t verify Bootrom :( Try again...'); USBClosePort; exit; end; Application.ProcessMessages; txBuf[0]:=$C0; txBuf[1]:=$56; txBuf[2]:=$00; txBuf[3]:=$00; txBuf[4]:=$00; txBuf[5]:=$00; txBuf[6]:=$00; txBuf[7]:=$03; USBControlPacket($222040, $8, $300); //Form1._msg('rxbuf: '+BufToHexStr(@rxBuf[0], Length(rxBuf))); if rxBuf[0]<1 then begin Application.ProcessMessages; Form1._msg('[BB5 FLASH]: GetFirstBlock Failed, Aborting'); USBClosePort; exit; end; Result:=rxBuf[0]; except Result:=0; end; end; function BB5_ADL_RestartMCU(mode: byte):boolean; var n: integer; begin case mode of $04: begin case oldsmart of false: begin Result:=False; txBuf[0] := $1B; txBuf[1] := $00; txBuf[2] := $10; txBuf[3] := $6f; txBuf[4] := $00; txBuf[5] := $06; txBuf[6] := $00; txBuf[7] := msgid; txBuf[8] := ISIHeaderTransId; txBuf[9] := $04; txBuf[10] := $00; txBuf[11] := $00; n:=USBBulkWritePort(@txBuf, 12); if n<>12 then exit; Result:=True; end; true: begin Result:=False; txBuf[0] := $1B; txBuf[1] := $00; txBuf[2] := $10; txBuf[3] := $6f; txBuf[4] := $00; txBuf[5] := $06; txBuf[6] := $00; txBuf[7] := msgid; txBuf[8] := ISIHeaderTransId; txBuf[9] := $04; txBuf[10] := $00; txBuf[11] := $00; n:=USBBulkWritePort(@txBuf, 12); if n<>12 then exit; Result:=True; end; end; end; $80: begin result:=False; txBuf[0] := $1B; txBuf[1] := $00; txBuf[2] := $10; txBuf[3] := $6f; txBuf[4] := $00; txBuf[5] := $06; txBuf[6] := $00; txBuf[7] := msgid; txBuf[8] := ISIHeaderTransId; txBuf[9] := $09; txBuf[10] := $02; txBuf[11] := $00; n:=USBBulkWritePort(@txBuf, 12); USBBulkReadPort($FF); if n<>12 then exit; txBuf[0] := $1B; txBuf[1] := $00; txBuf[2] := $10; txBuf[3] := $6f; txBuf[4] := $00; txBuf[5] := $06; txBuf[6] := $00; txBuf[7] := msgid; txBuf[8] := ISIHeaderTransId; txBuf[9] := $04; txBuf[10] := $02; txBuf[11] := $00; n:=USBBulkWritePort(@txBuf, 12); if n<>12 then exit; Result:=True; end; end; end; function BB5restart2ndproto():boolean; var n:integer; begin //1B 00 10 6F 00 06 00 18 7D 09 02 00 //1B 00 10 6F 00 06 00 18 2E 09 02 00 //1B 00 10 6F 00 06 00 18 2F 04 02 00 end; function CheckADLLoader:boolean; var n: integer; begin Result:=False; n:=USBBulkWritePort(@CheckADLUpload[0], Length(CheckADLUpload)); if n<>12 then exit; n:=ReadUBUSData; if n<6 then exit; if rxBuf[5]<>$04 then begin Form1._msg('ADL Server not confirmed flashmode!'); USBClosePort; exit; end else begin Form1._msg('ADL Server has confirmed its flashmode'); Result:=True; end; end; //Функция расчета CHK UPDAPP function GetLoaderCRC(Buf:Pointer; BufLen: integer): Word; begin Result:=0; while BufLen > 0 do begin Result:=Result+Byte(Buf^); inc(Integer(Buf)); dec(BufLen); end; Result:=Result xor $FFFF; end; function s40prep04 ():Boolean; var i:integer; begin CheckADLUpload[7]:=msgid; CheckADLUpload[8]:=ISIHeaderTransId; CheckADLUpload[9]:=$00; i:=USBBulkWritePort(@CheckADLUpload, Length(CheckADLUpload)); if i<>12 then exit; USBBulkReadPort(12); if rxBuf[11]<>$04 then // проверяем если старый байт - то пропускаем. result:=false else begin case oldsmart of false: begin; GetRoot[7]:=msgid; GetRoot[8]:=ISIHeaderTransId; USBBulkWritePort(@GetRoot, Length(GetRoot)); USBBulkReadPort($FFFF); //GetRoot GetRoot[7]:=msgid; GetRoot[8]:=ISIHeaderTransId; GETRoot[9]:=$07; USBBulkWritePort(@GetRoot, Length(GetRoot)); USBBulkReadPort($FFFF); //PreErase PreErase[7]:=msgid; PreErase[8]:=ISIHeaderTransId; USBBulkWritePort(@PreErase, Length(PreErase)); result:=True; end; true: begin //oldsmgetroot USBBulkWritePort(@oldsmGetRoot, Length(oldsmGetRoot)); USBBulkReadPort($FFFF); selectAsicCMT[3]:=$6F; selectAsicCMT[8]:=ISIHeaderTransId; USBBulkWritePort(@selectAsicCMT, Length(selectAsicCMT)); if USBBulkReadPort($FFFF) then Form1._msg('ASIC CMT select Ok'); Application.ProcessMessages; end; end; end; end; function s40prep80():Boolean; begin //1st recheck adl80checkst[7]:=msgid; adl80checkst[8]:=ISIHeaderTransId; USBBulkWritePort(@adl80checkst, Length(adl80checkst)); UsbBulkReadport($FFFF); adl80checkst[3]:=$21; USBBulkWritePort(@adl80checkst, Length(adl80checkst)); adl80checkst[3]:=$6F; //2nd - repeat check adl, send bytes adl80precheck[7]:=msgid; adl80precheck[8]:=ISIHeaderTransID; USBBulkWritePort(@adl80precheck, Length(adl80precheck)); UsbBulkReadport($FFFF); adl80checkst[7]:=msgid; adl80checkst[8]:=ISIHeaderTransId; USBBulkWritePort(@adl80checkst, Length(adl80checkst)); UsbBulkReadport($FFFF); adl80checkst[3]:=$21; USBBulkWritePort(@adl80checkst, Length(adl80checkst)); adl80checkst[3]:=$6F; //3rd - getroot adl80getroot[7]:=msgid; adl80getroot[8]:=ISIHeaderTransId; USBBulkWritePort(@adl80getroot, Length(adl80getroot)); UsbBulkReadport($FFFF); //PRECRTDATA - хз как ее ваять... =/ //Select ASIC adl80preasic[7]:=msgid; adl80preasic[8]:=ISIHeaderTransId; USBBulkWritePort(@adl80preasic, Length(adl80preasic)); UsbBulkReadport($FFFF); adl80selASIC[7]:=msgid; adl80selASIC[8]:=ISIHeaderTransId; USBBulkWritePort(@adl80selASIC, Length(adl80selASIC)); UsbBulkReadport($FFFF); if rxbuf[9]=$28 then result:=True else result:=False; end; function Extractloader(core:string ; mode : integer):Boolean; var fs : TfileStream; currcert, currtoken, streamlen : TMemoryStream; data : string; hdrlen,seemcount, CurrSeemLen,i : Integer; currseem : Byte; a : string; blklen,loaderlen : DWORD; dcr : Boolean; RootInBlock : array[0..$F] of byte; j,good,i2 : Integer; n,k,l,m,PktLen : integer; ms, RAWBlock, RAWLoader : TmemoryStream; s, needSert : String; Key, KeyLen : Byte; PacketLen : Byte; BlockCount : Byte; CurrBlock : Byte; CurrBlockLen : Word; b, proto : Boolean; begin Form1.setbuzy; if mode=1 then begin Form1._msg('Dead Mode is Selected'); Form1._msg('Waiting for USB device...'); Form1._msg('--- Press phone'+#39+'s power button! ---'); Application.ProcessMessages; end; //?????? Nokia USB ROM ?????????? b:=false; i:=0; repeat form1.setbuzy; if (i=2500) and (b=false) then begin Form1._msg('Phone not found.. :('); result:=False; Form1.SetReady; Exit; end; Application.ProcessMessages; //if BB5_USB_ScanAndOpenConnection('BB5', '*VID_0421&PID_0106&IF_OTH*', false) then if catchdevice=$02 then begin b:=true; Form1._msg('Connection opened successfully'); end; Application.ProcessMessages; Sleep(10); inc(i); Application.ProcessMessages; until b ; Application.ProcessMessages; Form1._msg('Waiting for communication response...'); Application.ProcessMessages; if BB5_USB_BootRom_GetFirstBlock<2 then begin Form1.setready; Form1._msg('Error answer from BootRom'); result:=False; exit; end; Application.ProcessMessages; Form1.statusbar.Panels[3].Text:='Connected'; Application.ProcessMessages; // Root Hash Application.ProcessMessages; FillMemory(@RAPInfo.ROOT_KEY_HASH,$10,$00); FillMemory(@RAPInfo.APErootkey,$10,$00); FillMemory(@RAPInfo.FlashID,$A,$00); FillMemory(@RAPInfo.APEFlashID,$A,$00); FillMemory(@RAPInfo.PublicID,$14,$00); FillMemory(@RAPInfo.BootID,$8,$00); Application.ProcessMessages; Application.ProcessMessages; PacketLen :=rxbuf[0]; BlockCount :=rxbuf[1]; i:=2; j:=0; m:=0; while (i$B2 then //Заголовок / идентификатор begin Form1.lst1.items.add('File damaged or Unknow format... :('); 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)); //form1._msg('HeaderLen: '+inttostr(HdrLen)); fs.ReadBuffer(buf[0], 4);//Кол-во блоков в Flash-заголовке SeemCount := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); //form1._msg('BlockCount: '+inttostr(SeemCount)); Application.ProcessMessages; dcr:=false; currcert:=TMemoryStream.Create; currtoken:=TmemoryStream.Create; streamlen:=TMemoryStream.Create; good:=0; i2:=0; loaderlen:=0; try Form1.statusbar.Panels[4].Text:='Sending Boot'; while (fs.Position0 do begin Form1._msg('Waiting for response: '+inttostr(i)); Application.ProcessMessages; if catchdevice<>$02 then begin Application.ProcessMessages; sleep (1000); Application.ProcessMessages; end else i:=0; dec(i); end; if not DevPresent then begin Form1._msg('Phone not found... :('); Form1.SetBuzy; Form1.StatusBar.Panels[4].Text:=''; result:=False; USBClosePort; exit; end; //Phone in Flash Mode??? CheckADLUpload[7]:=msgid; CheckADLUpload[8]:=ISIHeaderTransId; CheckADLUpload[9]:=$00; i:=USBBulkWritePort(@CheckADLUpload, Length(CheckADLUpload)); if i<>12 then exit; USBBulkReadPort(12); if rxBuf[11]<>$06 then begin if rxBuf[11]<>$80 then begin Form1._msg('ADL Server not confirmed flashmode!'); Form1._msg('ADL ReqPh : '+byte2str(rxbuf[11])); Form1.SetReady; result:=False; USBClosePort; exit; end else begin Form1._msg('ADL server [2nd] changing...'); rb:=rxBuf[11]; end; end else rb:=rxBuf[11]; Form1._msg('ADL Server confirm flashmode!'); case rb of $06: ADL06auth; // 6120, n76........ $80: ADL80auth; // 5800, n86........ end; selectAsicCMT[3]:=$6F; selectAsicCMT[8]:=ISIHeaderTransId; USBBulkWritePort(@selectAsicCMT, Length(selectAsicCMT)); if USBBulkReadPort($FFFF) then Form1._msg('ASIC CMT select Ok'); Application.ProcessMessages; //Добавил для удобства кастом-прошивки Form1.statusbar.Panels[0].Text:=''; Form1.statusbar.Panels[1].Text:=''; Form1.statusbar.Panels[2].Text:=''; Form1.statusbar.Panels[4].Text:='FLASHING'; Form1.statusbar.Panels[3].Text:='Connected'; Form1.TimConChk.Interval:=100; Application.ProcessMessages; if Form1.chkMCUen.Checked=true then begin Form1._msg(' ===Flashing [MCU]==='); if not BB5_EraseFile(core) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(core) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkPPMe.Checked=true then begin Form1._msg(' ===Flashing [PPM]==='); if not BB5_EraseFile(ppm) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(ppm) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkPPM1e.Checked=true then begin Form1._msg(' ===Flashing [PPM2]==='); if not BB5_EraseFile(ppm1) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(ppm1) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkCNTe.Checked=true then begin Form1._msg(' ===Flashing [CNT]==='); if not BB5_EraseFile(image) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(image) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkAPEe.Checked=true then begin Form1._msg(' ===Flashing [APE]==='); if not BB5_EraseFile(ape) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(ape) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; // режим рестарта AdlRestart06(rb); Application.ProcessMessages; Form1._msg(''); Form1._msg('Flashing done... Reboot phone now...'); Form1._msg(''); Application.ProcessMessages; Form1.statusbar.Panels[0].Text:=''; Form1.pb1.ForeColor:=clNavy; Form1.pbsm1.ForeColor:=clNavy; Form1.pb1.MaxValue:=100; Form1.pb1.progress:=0; Form1.statusbar.Panels[1].Text:=''; Form1.TimConChk.Interval:=2000; Form1.pb1.color:=clActiveBorder; Application.ProcessMessages; Sleep(1000); Application.ProcessMessages; Sleep(1000); Application.ProcessMessages; i:=0; if catchdevice<>$01 then begin repeat Application.ProcessMessages; Sleep(1000); Inc(i); Application.ProcessMessages; until (catchdevice=$01) or (i=50); end; if (i=50) and (catchdevice<>$01) then begin Application.ProcessMessages; Sleep(200); Form1.SetReady; Form1.TimConChk.Enabled:=true; Form1._msg('Flashing Failed! :( Maybee HW error, or Downgrade try???!'); Form1._msg(''); Form1.DisconnectFill; Result:=false; exit; end; Form1.statusbar.Panels[6].Text:='BUSY'; //Form1.statusbar.Panels[0].Text:=USBReadPhName; //Form1.statusbar.Panels[1].Text:=UsbReadIMEIPl; Form1.afterFlashdo; Application.ProcessMessages; Sleep(200); Form1.SetReady; Form1.TimConChk.Enabled:=true; Form1._msg('Done!'); //Form1.DisconnectFill; Result:=true; end;//End of Normal Mode Flashing function RebuildPartition(F:TMemoryStream; PLen: integer):boolean; var Outstream:TmemoryStream; i:Integer; buf1:array [0..3] of Byte ; buf2:array [0..2] of Byte; cf : byte; len : Int64; blkcnt:DWORD; begin blkcnt:=0; len:=0; case PLen of $32: begin buf2[0]:=$02; buf2[1]:=$06; buf2[2]:=$00; end; $42: begin buf2[0]:=$03; buf2[1]:=$06; buf2[2]:=$00; end; $52: begin buf2[0]:=$04; buf2[1]:=$06; buf2[2]:=$00; end; $72: begin buf2[0]:=$06; buf2[1]:=$06; buf2[2]:=$00; end; end; ////////=////////// buf1[0]:=$06; buf1[1]:=$14; buf1[2]:=$00; buf1[3]:=$00; Outstream:=TmemoryStream.Create; F.Seek(3, soFromBeginning); F.readbuffer(cf,1); F.Seek(3, soFromBeginning); Outstream.copyFrom(F,3); Outstream.Writebuffer(buf2[0],3); Outstream.copyfrom(F,8); F.ReadBuffer(blkcnt,4); DWordSwap(@blkcnt); for i:=1 to blkcnt do begin Outstream.Writebuffer(buf1[0],4); Outstream.copyfrom(F,16); end; ////1B 00 10 6F 00 62 00 15 75 10 ////1B 00 10 21 00 4E 00 12 11 10 txBuf[0]:=$1B; txBuf[1]:=$00; txBuf[2]:=$10; case cf of 0:txBuf[3]:=$6F; 1:txBuf[3]:=$21; else txBuf[3]:=$6F; end; txBuf[6]:=$00; txBuf[7]:=$0F; txBuf[8]:=ISIHeaderTransId; txBuf[9]:=$10; len:=Outstream.size; outstream.seek(0,soFromBeginning); outstream.ReadBuffer(txBuf[10], len); txBuf[4]:=(len+4) div $100; txBuf[5]:=(len+4) mod $100; USBBulkWritePort(@txbuf[0],len+$A); if USBBulkReadPort($FFFF) then begin if (rxBuf[10]=0) and (rxBuf[11]=0 ) then begin Form1._msg('Partitioning Ok ['+inttostr(blkcnt+1)+']'); result:=true; end else begin Form1._msg('Partitioning Error :('); result:=False; end; end; Application.ProcessMessages; //Outstream.SaveToFile('C:\Data.bin'); Outstream.Free; end; function s60checkadl():Byte; begin ///1B 10 00 6F 00 06 17 37 08 20 00 07 ///1B 00 10 6F 00 06 00 17 08 00 00 00 AdlCheckst[8]:=ISIHeaderTransId; USBBulkWritePort(@AdlCheckst[0], Length(AdlCheckst)); If USBBulkReadPort($FFFF) then begin result:=rxbuf[11]; end; end; function ADLBootInFlash():Boolean; var n:Integer; begin ///1B 00 10 6F 00 06 00 14 09 04 00 00 - reboot in flash mode Application.ProcessMessages; ADLReboot[8]:=ISIHeaderTransId; n:=USBBulkWritePort(@AdlReboot[0], Length(ADLReboot)); if n<>12 then begin result:=False; Exit; end; n:=200; repeat begin Sleep(50); Application.ProcessMessages; dec(n); end; until (DevPresent=False) or (n=0); if n=0 then result:=False else result:=True; end; function ADL06auth ():Boolean; var len:Byte; begin USBBulkWritePort(@GetRootAsic, Length(GetRootAsic)); if USBBulkReadPort($FFFF) then //form1._msg(BufToHexStr(@rxBuf[0], Length(rxBuf))); len:=rxBuf[10]; if len>0 then begin bufcopy(@rxBuf[14],@txbuf[10],len); //1B00106F002E000F0406 txbuf[0]:=$1B; txbuf[1]:=$00; txbuf[2]:=$10; txbuf[3]:=$6F; txbuf[4]:=$00; txbuf[5]:=len+4; txbuf[6]:=$00; txbuf[7]:=$0F; txbuf[8]:=$04; txbuf[9]:=$06; USBBulkWritePort(@txbuf[0], len+$A); if USBBulkReadPort($FFF) then begin if rxBuf[10]<>0 then result:=true else result:=false; end; end; end; function AdlRestart06 (rb:byte):Boolean; var i:integer; begin result:=false; case rb of $80: begin AdlPreBootReq[8]:=ISIHeaderTransId; USBBulkWritePort(@AdlPreBootReq, Length(AdlPreBootReq)); if USBBulkReadPort($FFF) then begin if rxBuf[9]=$29 then Form1._msg('Finalize...'); i:=USBBulkWritePort(@adlrestersxr15, Length(adlrestersxr15)); if i<>12 then form1._msg('Error while rebooting :('); Application.ProcessMessages; end; end; $06: begin AdlPreBootReq[8]:=ISIHeaderTransId; USBBulkWritePort(@AdlPreBootReq, Length(AdlPreBootReq)); if USBBulkReadPort($FFF) then begin if rxBuf[9]=$29 then Form1._msg('Finalize...'); i:=USBBulkWritePort(@adlrestersxr15, Length(adlrestersxr15)); if i<>12 then form1._msg('Error while rebooting :('); Application.ProcessMessages; end; end; end; end; function ADL80auth ():Boolean; var len:Byte; begin result:=False; ReqAdl80[8]:=ISIHeaderTransId; USBBulkWritePort(@ReqAdl80, Length(ReqAdl80)); if USBBulkReadPort($FFF) then begin if rxbuf[11]<>$01 then exit; ADL80RootReq[8]:=ISIHeaderTransId; USBBulkWritePort(@ADL80RootReq, Length(ADL80RootReq)); if USBBulkReadPort($FFF) then begin Application.ProcessMessages; end; Flastartreq[8]:=ISIHeaderTransId; USBBulkWritePort(@Flastartreq, Length(Flastartreq)); if USBBulkReadPort($FFF) then begin if rxbuf[10]<>$01 then Exit; Application.ProcessMessages; end; result:=True; form1._msg('Auth done...'); end; end; function OMAP2420boot () : boolean; var CMTadl, APEadl:TMemoryStream; b :Boolean; tmp :array of Byte; CHK, pktlen :Word; k :Integer; i :Word; begin // mdstart adlstartmode[8]:=ISIHeaderTransId; adlstartmode[7]:= $14; USBBulkWritePort(@adlstartmode, Length(adlstartmode)); If USBBulkReadPort($FFFF) then begin Application.ProcessMessages; Form1._msg(BufToHexStr(@rxBuf[0], Length(rxBuf))); end; CMTadl:=TMemoryStream.Create; BB5_ExtractCertData(core,'UPDAPP', CMTAdl, b, false); //CMTAdl.SaveToFile('C:\ADL.bin'); CMTAdl.Seek(0, soFromBeginning); SetLength(tmp, CMTAdl.Size); if CMTAdl.size=0 then begin result:=False; Exit; end; CMTAdl.ReadBuffer(tmp[0], CMTAdl.Size); CHK:=GetLoaderCRC(@tmp[0], CMTAdl.Size); Form1._msg('CMT Loader len: '+inttostr(CMTAdl.Size)+', CHK: '+inttohex(CHK, 4)); Application.ProcessMessages; Form1._msg('Sending CMT boot....'); // sending CRC and len of loader Sendomapcrcadl[7]:= $14; Sendomapcrcadl[8]:=ISIHeaderTransId; Sendomapcrcadl[12]:=CMTAdl.Size div $1000000; Sendomapcrcadl[13]:=CMTAdl.Size div $10000; Sendomapcrcadl[14]:=CMTAdl.Size div $100; Sendomapcrcadl[15]:=CMTAdl.Size mod $100; Sendomapcrcadl[16]:=CHK div $100; Sendomapcrcadl[17]:=CHK mod $100; USBBulkWritePort(@sendomapcrcadl, Length(Sendomapcrcadl)); If USBBulkReadPort($FFFF) then begin //Form1._msg(buftohexstr(@rxBuf[0],Length(rxBuf))); if rxBuf[11]<>0 then Form1._msg('Accept error, skip'); end; //Отправка агента по кусочкам b:=true; i:=1;//номер сообщения MsgBody:=2;//номер сообщения PktLen:=$0780;//длина отправляемого кусочка лоадера (длина как в Фениксе) Form1.pb1.Progress:=0; //ms:=TMemoryStream.Create;//для теста и сохранения текущего отправленного кусочка BufCopy(@Sendomapadl[0], @txBuf[0], Length(Sendomapadl)); //SendADL : array[0..15] of Byte = //($1B, $00, $10, $6F, $07, $8A, $00, $15, $56, $03, $00, $01, $00, $00, $07, $80); txBuf[8] := ISIHeaderTransId; CMTAdl.Seek(0, sofromBeginning); Application.ProcessMessages; while (CMTAdl.Position+PktLen)<=CMTAdl.Size do begin CMTAdl.ReadBuffer(txBuf[16], PktLen); Word((@txBuf[4])^):=Swap(PktLen+$0A); txBuf[3] :=$6F; txBuf[7] := $14; txBuf[8] := ISIHeaderTransId; Word((@txBuf[10])^):=Swap(i); Word((@txBuf[14])^):=Swap(PktLen); //Только для сохранения отправляемых кусочков агента {ms.Seek(0, soFromBeginning); ms.WriteBuffer(txBuf[0], 16); ms.WriteBuffer(txBuf[16], PktLen); ms.SaveToFile('C:\ADL_Send\'+Int2Digs(i,4)+'.bin'); ms.Clear;} k:=USBBulkWritePort(@txbuf[0], (PktLen+$10)); if k<>(PktLen+$10) then begin USBClosePort; exit; end; USBBulkReadPort(16); if ((CMTAdl.Size-CMTAdl.position)0 then Form1._msg('Accept error, skip'); end; Application.ProcessMessages; Form1._msg('Sending APE boot....'); //Отправка агента по кусочкам b:=true; i:=1;//номер сообщения MsgBody:=2;//номер сообщения PktLen:=$0780;//длина отправляемого кусочка лоадера (длина как в Фениксе) Form1.pb1.Progress:=0; //ms:=TMemoryStream.Create;//для теста и сохранения текущего отправленного кусочка BufCopy(@Sendomapadl[0], @txBuf[0], Length(Sendomapadl)); //SendADL : array[0..15] of Byte = //($1B, $00, $10, $6F, $07, $8A, $00, $15, $56, $03, $00, $01, $00, $00, $07, $80); txBuf[8] := ISIHeaderTransId; APEAdl.Seek(0, sofromBeginning); Application.ProcessMessages; while (APEAdl.Position+PktLen)<=APEAdl.Size do begin APEAdl.ReadBuffer(txBuf[16], PktLen); Word((@txBuf[4])^):=Swap(PktLen+$0A); txBuf[3] := $21; txBuf[7] := $14; txBuf[8] := ISIHeaderTransId; Word((@txBuf[10])^):=Swap(i); Word((@txBuf[14])^):=Swap(PktLen); k:=USBBulkWritePort(@txbuf[0], (PktLen+$10)); if k<>(PktLen+$10) then begin USBClosePort; exit; end; USBBulkReadPort(16); if ((APEAdl.Size-APEAdl.position)0 then Form1._msg('Accept error, skip'); end; //Отправка агента по кусочкам b:=true; i:=1;//номер сообщения MsgBody:=2;//номер сообщения PktLen:=$0780;//длина отправляемого кусочка лоадера (длина как в Фениксе) Form1.pb1.Progress:=0; //ms:=TMemoryStream.Create;//для теста и сохранения текущего отправленного кусочка BufCopy(@Sendomapadl[0], @txBuf[0], Length(Sendomapadl)); //SendADL : array[0..15] of Byte = //($1B, $00, $10, $6F, $07, $8A, $00, $15, $56, $03, $00, $01, $00, $00, $07, $80); txBuf[8] := ISIHeaderTransId; CMTAdl.Seek(0, sofromBeginning); Application.ProcessMessages; while (CMTAdl.Position+PktLen)<=CMTAdl.Size do begin CMTAdl.ReadBuffer(txBuf[16], PktLen); Word((@txBuf[4])^):=Swap(PktLen+$0A); txBuf[3] :=$6F; txBuf[7] := $18; txBuf[8] := ISIHeaderTransId; Word((@txBuf[10])^):=Swap(i); Word((@txBuf[14])^):=Swap(PktLen); //Только для сохранения отправляемых кусочков агента {ms.Seek(0, soFromBeginning); ms.WriteBuffer(txBuf[0], 16); ms.WriteBuffer(txBuf[16], PktLen); ms.SaveToFile('C:\ADL_Send\'+Int2Digs(i,4)+'.bin'); ms.Clear;} k:=USBBulkWritePort(@txbuf[0], (PktLen+$10)); if k<>(PktLen+$10) then begin USBClosePort; exit; end; USBBulkReadPort(16); if ((CMTAdl.Size-CMTAdl.position)0 then Form1._msg('Accept error, skip'); end; Application.ProcessMessages; Form1._msg('Sending APE boot....'); //Отправка агента по кусочкам b:=true; i:=1;//номер сообщения MsgBody:=2;//номер сообщения PktLen:=$0780;//длина отправляемого кусочка лоадера (длина как в Фениксе) Form1.pb1.Progress:=0; //ms:=TMemoryStream.Create;//для теста и сохранения текущего отправленного кусочка BufCopy(@Sendomapadl[0], @txBuf[0], Length(Sendomapadl)); //SendADL : array[0..15] of Byte = //($1B, $00, $10, $6F, $07, $8A, $00, $15, $56, $03, $00, $01, $00, $00, $07, $80); txBuf[8] := ISIHeaderTransId; APEAdl.Seek(0, sofromBeginning); Application.ProcessMessages; while (APEAdl.Position+PktLen)<=APEAdl.Size do begin APEAdl.ReadBuffer(txBuf[16], PktLen); Word((@txBuf[4])^):=Swap(PktLen+$0A); txBuf[3] := $21; txBuf[7] := $18; txBuf[8] := ISIHeaderTransId; Word((@txBuf[10])^):=Swap(i); Word((@txBuf[14])^):=Swap(PktLen); k:=USBBulkWritePort(@txbuf[0], (PktLen+$10)); if k<>(PktLen+$10) then begin USBClosePort; exit; end; USBBulkReadPort(16); if ((APEAdl.Size-APEAdl.position)0 then Form1._msg('Accept error, skip'); end; //Отправка агента по кусочкам b:=true; i:=1;//номер сообщения MsgBody:=2;//номер сообщения PktLen:=$0780;//длина отправляемого кусочка лоадера (длина как в Фениксе) Form1.pb1.Progress:=0; //ms:=TMemoryStream.Create;//для теста и сохранения текущего отправленного кусочка BufCopy(@Sendomapadl[0], @txBuf[0], Length(Sendomapadl)); //SendADL : array[0..15] of Byte = //($1B, $00, $10, $6F, $07, $8A, $00, $15, $56, $03, $00, $01, $00, $00, $07, $80); txBuf[8] := ISIHeaderTransId; CMTAdl.Seek(0, sofromBeginning); Application.ProcessMessages; while (CMTAdl.Position+PktLen)<=CMTAdl.Size do begin CMTAdl.ReadBuffer(txBuf[16], PktLen); Word((@txBuf[4])^):=Swap(PktLen+$0A); txBuf[3] :=$6F; txBuf[7] := $18; txBuf[8] := ISIHeaderTransId; Word((@txBuf[10])^):=Swap(i); Word((@txBuf[14])^):=Swap(PktLen); //Только для сохранения отправляемых кусочков агента {ms.Seek(0, soFromBeginning); ms.WriteBuffer(txBuf[0], 16); ms.WriteBuffer(txBuf[16], PktLen); ms.SaveToFile('C:\ADL_Send\'+Int2Digs(i,4)+'.bin'); ms.Clear;} k:=USBBulkWritePort(@txbuf[0], (PktLen+$10)); if k<>(PktLen+$10) then begin USBClosePort; exit; end; USBBulkReadPort(16); if ((CMTAdl.Size-CMTAdl.position)0 then Form1._msg('Accept error, skip'); end; Application.ProcessMessages; Form1._msg('Sending APE boot....'); //Отправка агента по кусочкам b:=true; i:=1;//номер сообщения MsgBody:=2;//номер сообщения PktLen:=$0780;//длина отправляемого кусочка лоадера (длина как в Фениксе) Form1.pb1.Progress:=0; //ms:=TMemoryStream.Create;//для теста и сохранения текущего отправленного кусочка BufCopy(@Sendomapadl[0], @txBuf[0], Length(Sendomapadl)); //SendADL : array[0..15] of Byte = //($1B, $00, $10, $6F, $07, $8A, $00, $15, $56, $03, $00, $01, $00, $00, $07, $80); txBuf[8] := ISIHeaderTransId; APEAdl.Seek(0, sofromBeginning); Application.ProcessMessages; while (APEAdl.Position+PktLen)<=APEAdl.Size do begin APEAdl.ReadBuffer(txBuf[16], PktLen); Word((@txBuf[4])^):=Swap(PktLen+$0A); txBuf[3] := $21; txBuf[7] := $18; txBuf[8] := ISIHeaderTransId; Word((@txBuf[10])^):=Swap(i); Word((@txBuf[14])^):=Swap(PktLen); k:=USBBulkWritePort(@txbuf[0], (PktLen+$10)); if k<>(PktLen+$10) then begin USBClosePort; exit; end; USBBulkReadPort(16); if ((APEAdl.Size-APEAdl.position)$60 then begin Form1.setready; Form1._msg('Error answer from BootRom'); result:=False; exit; end; Application.ProcessMessages; Form1.statusbar.Panels[3].Text:='Connected'; Application.ProcessMessages; //Парсинг Root Hash Application.ProcessMessages; FillMemory(@RAPInfo.Root_Key_Hash,$10,$00); FillMemory(@RAPInfo.APErootkey,$10,$00); FillMemory(@RAPInfo.FlashID,$A,$00); FillMemory(@RAPInfo.APEFlashID,$A,$00); FillMemory(@RAPInfo.PublicID,$14,$00); FillMemory(@RAPInfo.BootID,$8,$00); Application.ProcessMessages; i:=2; while i < Length(rxbuf) do begin Key :=rxbuf[i]; KeyLen:=rxbuf[i+1]; inc(i, 2); case Key of $01: begin for j:=$0 to KeyLen-1 do RAPInfo.FlashID[j]:= rxbuf[i+j]; inc(i, KeyLen); end; $12: begin // 0A900018A8B54650B9C89AA40EEC5059B5762F38 inc(i); for j:=0 to $13 do RAPInfo.PublicID[j]:= rxbuf[i+j]; inc(i, $14); end; $14: //Root Hash begin // BAF3A9C3DBFA8454937DB77F2B8852B1 inc(i); for j:=0 to $0F do RAPInfo.Root_Key_Hash[j]:= rxbuf[i+j]; inc(i, $0F); end else inc(i, KeyLen); end;//End Of Case end; j:=0; //Проверка на пустой RootHash for i := 0 to $0F do inc(j, RAPInfo.Root_Key_Hash[i]); if j=0 then begin Form1.setready; Form1._msg('No RootKeyHash Asic CMT. Unable to find flash CmtAlgorithm'); exit; end; Application.ProcessMessages; //Form1._msg('RAP_BOOT: '+ BufToHexStr(@RAPInfo.BootID[0], Length(RAPInfo.BootID))); Form1._msg('RAP_PUB: '+ BufToHexStr(@RAPInfo.PublicID[0], Length(RAPInfo.PublicID))); Form1._msg('CMT_ROOT: '+ BufToHexStr(@RAPInfo.Root_Key_Hash[0], Length(RAPInfo.ROOT_KEY_HASH))); //Form1._msg('RAP_PAPUB: '+ BufToHexStr(@RAPInfo.PAPUBKEYSID[0], Length(RAPInfo.PAPUBKEYSID))); Application.ProcessMessages; //Извлечение RAW-Block RAWBlock:=TmemoryStream.Create; BB5_ExtractBlockOfRAWLoader(core, RAWBlock, b); if Not b then begin Form1.setready; Form1._msg('Error extracting RAW-loader'); RAWBlock.Free; exit; end; RAWBlock.SaveToFile('C:\Extract_RAW_Loader_from_'+ExtractFileName(core)+'.bin'); //Извлечение и патчинг RAW-loader'a RAWLoader:=TmemoryStream.Create; BB5_ExtractRAWLoader(RAWBlock, RAWLoader, b); if Not b then begin Form1.setready; Form1._msg('Error Patching RAW-loader'); RAWLoader.Free; RAWBlock.Free; exit; end; Form1._msg('PatchRAWLoader: Patched OK'); RAWLoader.SaveToFile('C:\RAW_Cert_Patch.bin'); //RAWLoader.Clear; {================================== SEND RAW LOADER ===================================} Application.processmessages; RAWLoader.Seek(0, sofrombeginning); b:=true; PktLen:=$1000; k:=1; txBuf[0]:=$40; txBuf[1]:=$57; txBuf[2]:=$01; txBuf[3]:=$00; txBuf[4]:=$00; txBuf[5]:=$00; Form1._msg('Processing RAWLOADER...'); while (RAWLoader.position0 do begin Form1._msg('Waiting for response: '+inttostr(i)); Application.ProcessMessages; if catchdevice<>$02 then begin Application.ProcessMessages; sleep (1500); Application.ProcessMessages; sleep (1500); Application.ProcessMessages; end else i:=0; dec(i); end; if not DevPresent then begin Form1._msg('Phone not found... :('); Form1.SetBuzy; Form1.StatusBar.Panels[4].Text:=''; result:=False; USBClosePort; exit; end; //Phone in Flash Mode??? CheckADLUpload[3]:=$6F; CheckADLUpload[7]:=msgid; CheckADLUpload[8]:=ISIHeaderTransId; CheckADLUpload[9]:=$00; i:=USBBulkWritePort(@CheckADLUpload, Length(CheckADLUpload)); if i<>12 then exit; USBBulkReadPort(12); if rxBuf[11]<>$03 then begin if rxBuf[11]<>$80 then begin Form1._msg('ADL Server (CMT) not confirmed flashmode!'); Form1._msg('ADL ReqPh : '+byte2str(rxbuf[11])); Form1.SetReady; result:=False; USBClosePort; exit; end else begin //1B 00 10 6F 00 06 00 14 A9 80 00 00 end; end; //Phone in Flash Mode??? CheckADLUpload[3]:=$21; CheckADLUpload[7]:=msgid; CheckADLUpload[8]:=ISIHeaderTransId; CheckADLUpload[9]:=$00; i:=USBBulkWritePort(@CheckADLUpload, Length(CheckADLUpload)); if i<>12 then exit; USBBulkReadPort(12); CheckADLUpload[3]:=$6F; // чистим, на всякий if rxBuf[11]<>$03 then begin if rxBuf[11]<>$80 then begin Form1._msg('ADL Server (APE) not confirmed flashmode!'); Form1._msg('ADL ReqPh : '+byte2str(rxbuf[11])); Form1.SetReady; result:=False; USBClosePort; exit; end; end; rb:=rxbuf[11]; Form1._msg('ADL Server confirm flashmode!'); case rb of $80 : begin get2420root[8]:=ISIHeaderTransID; UsbBulkWriteport(@get2420root, Length(get2420root)); if usbbulkreadport($FFFF) then begin form1._msg('Auth Ok'); Application.ProcessMessages; end; end; $03 : begin Application.Processmessages; form1._msg('Auth skip'); //sentroot+pc+hash-> conf APE //send crc& end; end; selectAsicCMT[3]:=$6F; selectAsicCMT[8]:=ISIHeaderTransId; USBBulkWritePort(@selectAsicCMT, Length(selectAsicCMT)); if USBBulkReadPort($FFFF) then begin if rxbuf[10]<>$00 then begin Form1._msg('ADL Select CMT failed!'); Exit; end; Form1._msg('ASIC CMT select Ok'); Application.ProcessMessages; end; selectAsicCMT[3]:=$21; SelectAsicCMT[8]:=ISIHeaderTransId; USBBulkWritePort(@selectAsicCMT, Length(selectAsicCMT)); if USBBulkReadPort($FFFF) then begin if rxbuf[10]<>$00 then begin Form1._msg('ADL Select APE failed!'); Exit; end; Form1._msg('ASIC APE select Ok'); selectAsicCMT[3]:=$6F; Application.ProcessMessages; end; //Добавил для удобства кастом-прошивки Form1.statusbar.Panels[0].Text:=''; Form1.statusbar.Panels[1].Text:=''; Form1.statusbar.Panels[2].Text:=''; Form1.statusbar.Panels[4].Text:='FLASHING'; Form1.statusbar.Panels[3].Text:='Connected'; Form1.TimConChk.Interval:=100; Application.ProcessMessages; if Form1.chkMCUen.Checked=true then begin Form1._msg(' ===Flashing [MCU]==='); if not BB5_EraseFile(core) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(core) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkPPMe.Checked=true then begin Form1._msg(' ===Flashing [PPM]==='); if not BB5_EraseFile(ppm) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(ppm) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkPPM1e.Checked=true then begin Form1._msg(' ===Flashing [PPM2]==='); if not BB5_EraseFile(ppm1) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(ppm1) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkCNTe.Checked=true then begin Form1._msg(' ===Flashing [CNT]==='); if not BB5_EraseFile(image) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(image) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; Application.ProcessMessages; if Form1.chkAPEe.Checked=true then begin Form1._msg(' ===Flashing [APE]==='); if not BB5_EraseFile(ape) then begin Form1.pb1.progress:=0; result:=False; Exit; end; Application.ProcessMessages; if not BB5_WriteFile(ape) then begin Form1.pb1.progress:=0; result:=False; Exit; end; end; if not ADLAPErestart(rb) then begin Application.ProcessMessages; Sleep(200); Form1.SetReady; Form1.TimConChk.Enabled:=true; Form1._msg('Flashing Failed! :( Maybee HW error, or Downgrade try???!'); Form1._msg(''); Form1.DisconnectFill; Result:=false; exit; end; Application.ProcessMessages; Form1._msg(''); Form1._msg('Flashing done... Reboot phone now...'); Form1._msg(''); Application.ProcessMessages; Form1.statusbar.Panels[0].Text:=''; Form1.pb1.ForeColor:=clNavy; Form1.pbsm1.ForeColor:=clNavy; Form1.pb1.MaxValue:=100; Form1.pb1.progress:=0; Form1.statusbar.Panels[1].Text:=''; Form1.TimConChk.Interval:=2000; Form1.pb1.color:=clActiveBorder; Application.ProcessMessages; Sleep(1000); Application.ProcessMessages; Sleep(1000); Application.ProcessMessages; i:=0; if catchdevice<>$01 then begin repeat Application.ProcessMessages; Sleep(1000); Inc(i); Application.ProcessMessages; until (catchdevice=$01) or (i=50); end; if (i=50) and (catchdevice<>$01) then begin Application.ProcessMessages; Sleep(200); Form1.SetReady; Form1.TimConChk.Enabled:=true; Form1._msg('Flashing Failed! :( Maybee HW error, or Downgrade try???!'); Form1._msg(''); Form1.DisconnectFill; Result:=false; exit; end; Form1.statusbar.Panels[6].Text:='BUSY'; //Form1.statusbar.Panels[0].Text:=USBReadPhName; //Form1.statusbar.Panels[1].Text:=UsbReadIMEIPl; Form1.afterFlashdo; Application.ProcessMessages; Sleep(200); Form1.TimConChk.Enabled:=true; Form1._msg('Done!'); Result:=true; end; function Omap1610extrboot(ASIC:string):boolean; var fs,resstream :TMemoryStream; data :string; hdrlen,seemcount, CurrSeemLen,i :Integer; currseem :Byte; loaderlen :DWORD; copysize :int64; begin result:=False; try fs:=TMemoryStream.Create; if ASIC='CMT' then fs.LoadFromFile(ExtractFilePath(Application.ExeName)+'\Flash\ADLREVC00.adl') else fs.LoadFromFile(ExtractFilePath(Application.ExeName)+'\Flash\ADLREVA00.adl'); fs.Read(buf[0] ,1); if buf[0]<>$B3 then //Заголовок / идентификатор begin Form1.lst1.items.add('File damaged or Unknow format... :('); 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)); fs.ReadBuffer(buf[0], 4);//Кол-во блоков в Flash-заголовке SeemCount := HexToInt(IntToHex(buf[0], 2)+IntToHex(buf[1], 2)+IntToHex(buf[2], 2)+IntToHex(buf[3], 2)); Application.ProcessMessages; while (fs.Position$00 then begin Form1._msg('Close CMT session failed '); result:=false; Exit; end; Form1._msg('Close CMT session...'); Application.ProcessMessages; end; CMTfinish[3]:=$21; CMTfinish[8]:=ISIHeaderTransId; USBBulkWritePort(@CMTfinish, Length(CMTfinish)); if USBBulkReadPort($FFFF) then begin if rxbuf[10]<>$00 then begin Form1._msg('Close APE session failed '); result:=False; Exit; end; Form1._msg('Close APE session...'); Application.ProcessMessages; end; EndOmapFlash[3]:=$6F; EndOmapFlash[8]:=ISIHeaderTransId; USBBulkWritePort(@EndOmapFlash, Length(EndOmapFlash)); EndOmapFlash[3]:=$21; EndOmapFlash[8]:=ISIHeaderTransId; USBBulkWritePort(@EndOmapFlash, Length(EndOmapFlash)); EndOmapFlash[3]:=$6F; EndOmapFlash[8]:=ISIHeaderTransId; USBBulkWritePort(@EndOmapFlash, Length(EndOmapFlash)); result:=True; end; $80: begin CMTfinish[3]:=$6F; CMTfinish[8]:=ISIHeaderTransId; CMTfinish[10]:=$02; USBBulkWritePort(@CMTfinish, Length(CMTfinish)); if USBBulkReadPort($FFFF) then begin if rxbuf[10]<>$00 then begin Form1._msg('Close CMT session failed '); result:=false; Exit; end; Form1._msg('Close CMT session...'); Application.ProcessMessages; end; CMTfinish[3]:=$21; CMTfinish[8]:=ISIHeaderTransId; USBBulkWritePort(@CMTfinish, Length(CMTfinish)); if USBBulkReadPort($FFFF) then begin if rxbuf[10]<>$00 then begin Form1._msg('Close APE session failed '); result:=false; Exit; end; Form1._msg('Close APE session...'); Application.ProcessMessages; end; EndOmapFlash[3]:=$6F; EndOmapFlash[8]:=ISIHeaderTransId; EndOmapFlash[10]:=$02; USBBulkWritePort(@EndOmapFlash, Length(EndOmapFlash)); EndOmapFlash[3]:=$21; EndOmapFlash[8]:=ISIHeaderTransId; EndOmapFlash[10]:=$00; USBBulkWritePort(@EndOmapFlash, Length(EndOmapFlash)); EndOmapFlash[3]:=$6F; EndOmapFlash[10]:=$00; result:=True; end; end; end; end.