unit UnitUFS; interface uses D2XXUnit, HexUtils, FBoots, Windows, Masks, Forms, sysutils, classes, boots, dialogs; function BArmInterface(): boolean; function readData(): boolean; function SwitchBoxMode(Mode: string): boolean; function ChecCMTData(): boolean; procedure FetchBootData; function ufsresetpower(): Boolean; function replyverify(): Boolean; function replyverify2(): Boolean; function SendRaw(Asic: integer; Loader: string): integer; function Freaddata(bytes: byte): Boolean; function Freadflashic(): boolean; function SendAlgorihtm(Asic: integer; algo: string): integer; function CheckVpp(): Boolean; function ReadCert(ASIC: Byte; CERT: string): string; function GetReadLen(): Byte; function ReadDatarequest(bytes: byte): Boolean; function replyend(): Boolean; function PreCertreq(): Boolean; function ufs_cmd(timeout: dword; pCmd: pointer; CmdLen: dword; pDst: Pointer; Expected: dword): dword; function ufsfl_cmd(timeout: dword; pCmd: pointer; CmdLen: dword; pDst: Pointer; Expected: dword): dword; function replyverify3(): byte; function ufx_boot(sn: string): boolean; function ufx_sw_fbus(sn: string; mode: string): boolean; function incheck(bytes: Integer): Boolean; function phoneready(retry: Integer): Boolean; function FlashPrepare(flimage: string): Boolean; function UFSPartitioning(core: string): Boolean; function SendRawID(Asic: integer; Loader: string): integer; function getapepapub(): Boolean; function UFSprepareForFlash(image: string): Boolean; function UFSeraseUni(core: string): Boolean; function ConFigureAsic(ASIC: Byte): Boolean; function AsicComandFur(): Boolean; function checkc7(): Boolean; function UFSfinishsession(): integer; function UFSEBLock(): integer; function buildUFScert(DataStream: widestring; cert: string; asic: byte): Boolean; function UFSeraseCRT(CRT: string; Asic: Byte): Boolean; function UFSEBLockAPE(): boolean; function busreset(): boolean; /// function ufssys_cmd(CmdLen: dword; pDst: Pointer; Expected: dword): dword; //Infineon //Infineon function Boot_infineon({Boot1:TMemoryStream;Boot2:TMemoryStream}): Boolean; function BusCheckInfineon(): Boolean; function InfineonEnd(): Boolean; function FlashInfineonFile(FlasHfile: string): Boolean; function InfineonErase(infcore: string; curreg: string): Boolean; function sendCert(infcore: string): Boolean; function infgetblockcnt(infcore: string; Erlist: Tstringlist): Integer; function InfineonWrite(infcore: string; mode: Integer; dlen: string): Boolean; function checkready(): Boolean; function getchksuminf(): Boolean; function halfboot(): Boolean; procedure dumpregionepp(start, stop: dword; resstr: Tmemorystream); procedure dumpppmcatalog(start, stop: dword; resstr: Tmemorystream); //special function UFSeraseS40(area: string): Boolean; function UFSFormatLow(area: string): Boolean; implementation uses UnitE1, UnitPavel, unit1, FlashBoots, USBmain, FbusMain, unitmisc, Graphics; var if_layer_dir: string; u_id: DWord; u_id_reprezentation: string; u_sn: string; u_g_sn: string; EEProm: string; Atmel_Sn: Integer; RxFrBuf, TxFrBuf: array[0..$8000] of byte; FrameInside: array[0..$FFFF] of byte; Seq: Integer; AckPacket: array[0..9] of byte; // Fbus_Timeout: integer; FR_CNT1: byte; Mode12A4: byte; McuSW_Buf, SWVersion, SWDate, Product, Manufacturer: string; PMWrLen: integer; PMWrBuffer: array[0..$800000] of byte; PMData: array[0..$800000] of byte; FLbyte: Byte; CFltype, AFltype: Byte; const Fbus_Timeout = 3000; function ufsresetpower(): Boolean; var retry, i: integer; InterfaceArmed: boolean; c_buf: string; label dummy_sn_retry; begin try except result := false; end; end; function MakeSeq: integer; begin if Seq = $40 then begin Seq := $41; Result := Seq; exit; end; if Seq = $41 then begin Seq := $42; Result := Seq; exit; end; if Seq = $42 then begin Seq := $43; Result := Seq; exit; end; if Seq = $43 then begin Seq := $44; Result := Seq; exit; end; if Seq = $44 then begin Seq := $45; Result := Seq; exit; end; if Seq = $45 then begin Seq := $46; Result := Seq; exit; end; if Seq = $46 then begin Seq := $47; Result := Seq; exit; end; if Seq = $47 then begin Seq := $40; Result := Seq; exit; end; end; function ufssys_cmd(CmdLen: dword; pDst: Pointer; Expected: dword): dword; begin result := 0; if write_usb_device_buffer(cmdlen) <> cmdlen then exit; if read_usb_device_buffer(expected) <> expected then result := 0; move(ft_in_buffer, pointer(dword(pdst))^, expected); end; function ufs_cmd(timeout: dword; pCmd: pointer; CmdLen: dword; pDst: Pointer; Expected: dword): dword; var tries, totalread, toread, leftover: dword; finished: boolean; cnt, cnt1: longint; begin Application.ProcessMessages; FillMemory(@cmd_buf, 65536, $00); PURGE_USB_DEVICE_IN; result := 0; finished := false; if cmdlen > 0 then begin move(pCmd^, ft_out_buffer, cmdlen); if write_usb_device_buffer(cmdlen) <> cmdlen then exit; end; if expected = 0 then begin result := cmdlen; exit; end; cnt := gettickcount + timeout; Get_USB_Device_QueueStatus; while (ft_q_bytes < expected) do begin if (cnt - gettickcount) <= 0 then break; Get_USB_Device_QueueStatus; end; if read_usb_device_buffer(ft_q_bytes) <> ft_q_bytes then exit else move(ft_in_buffer, pointer(dword(pdst))^, ft_q_bytes); PURGE_USB_DEVICE_OUT; result := ft_q_bytes; end; function ufsfl_cmd(timeout: dword; pCmd: pointer; CmdLen: dword; pDst: Pointer; Expected: dword): dword; var tries, totalread, toread, leftover: dword; finished: boolean; cnt, cnt1: longint; begin Application.ProcessMessages; FillMemory(@cmd_buf, 65536, $00); PURGE_USB_DEVICE_IN; result := 0; finished := false; if cmdlen > 0 then begin move(pCmd^, ft_out_buffer, cmdlen); if write_usb_device_buffer(cmdlen) <> cmdlen then exit; end; if expected = 0 then begin result := cmdlen; exit; end; cnt := gettickcount + timeout; Get_USB_Device_QueueStatus; while (ft_q_bytes < expected) do begin if (cnt - gettickcount) <= 0 then break; Get_USB_Device_QueueStatus; end; if read_usb_device_buffer(ft_q_bytes) <> ft_q_bytes then exit else move(ft_in_buffer, pointer(dword(pdst))^, ft_q_bytes); PURGE_USB_DEVICE_OUT; result := ft_q_bytes; end; function ufx_boot(sn: string): boolean; var cmd_buf: array[0..1024] of byte; i, j: integer; label TryAgain; begin try Reset_USB_Device; Close_USB_Device; except Application.ProcessMessages; end; if (Open_USB_Device_By_Serial_Number(sn) <> FT_OK) then begin form1._msg('Error open UFS #' + sn); Close_USB_Device; Result := False; exit; end; if (Reset_USB_Device <> FT_OK) then begin form1._msg('Error reset UFS #' + sn); Close_USB_Device; Result := False; exit; end; if Set_USB_Device_TimeOuts(100, 2000) <> ft_ok then begin form1._msg('UFS timeout set failed'); Close_USB_Device; Result := False; exit; end; if (Reset_USB_Device <> FT_OK) then begin form1._msg('Error reset UFS'); Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_Out <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_IN <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if Set_USB_Parameters($10000, $10000) <> FT_OK then begin form1._msg('Parameters set error'); Close_USB_Device; Result := False; exit; end; FT_current_DataBits := 8; FT_Current_StopBits := 0; FT_Current_Parity := 0; if Set_USB_Device_DataCharacteristics <> FT_OK then begin form1._msg('Data set error'); Close_USB_Device; Result := False; exit; end; FT_Current_FlowControl := 0; FT_XON_Value := $11; FT_XOFF_Value := $13; if Set_USB_Device_FlowControl <> FT_OK then begin form1._msg('UFS flowcontrol set error'); Close_USB_Device; Result := False; exit; end; if (Set_USB_Device_BaudRate_Divisor(26) <> FT_OK) then begin form1._msg('UFS bd switch failed'); Close_USB_Device; Result := False; exit; end; if (set_usb_Device_dtr <> FT_OK) then begin form1._msg('UFS dtrset error'); Close_USB_Device; Result := False; exit; end; j := 0; TryAgain: FT_out_buffer[0] := $3F; ufs_cmd(1000, @ft_out_buffer, 1, @cmd_buf, $2); j := j + 1; if ((cmd_buf[0] <> $62) or (cmd_buf[1] <> $CF)) and (cmd_buf[0] <> $3F) then begin if j > 5 then begin form1._msg('UFS Boot Enter error (' + IntToHex(cmd_buf[0], 2) + IntToHex(Cmd_Buf[1], 2) + ')'); Close_USB_Device; Result := False; exit; end else begin sleep(500); if (Reset_USB_Device <> FT_OK) then begin form1._msg('Error reset UFS #' + sn); Close_USB_Device; Result := False; exit; end; if Set_USB_Device_TimeOuts(2000, 2000) <> ft_ok then begin form1._msg('UFS timeout set failed'); Close_USB_Device; Result := False; exit; end; if (Reset_USB_Device <> FT_OK) then begin form1._msg('Error reset UFS'); Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_Out <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_IN <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if Set_USB_Parameters($10000, $10000) <> FT_OK then begin form1._msg('Parameters set error'); Close_USB_Device; Result := False; exit; end; FT_current_DataBits := 8; FT_Current_StopBits := 0; FT_Current_Parity := 0; if Set_USB_Device_DataCharacteristics <> FT_OK then begin form1._msg('Data set error'); Close_USB_Device; Result := False; exit; end; FT_Current_FlowControl := 0; FT_XON_Value := $11; FT_XOFF_Value := $13; if Set_USB_Device_FlowControl <> FT_OK then begin form1._msg('UFS flowcontrol set error'); Close_USB_Device; Result := False; exit; end; if (Set_USB_Device_BaudRate_Divisor(16696) <> FT_OK) then begin form1._msg('UFS bd switch failed'); Close_USB_Device; Result := False; exit; end; if (clr_usb_Device_dtr <> FT_OK) then begin form1._msg('UFS clrdtr error'); Close_USB_Device; Result := False; exit; end; if (clr_usb_Device_rts <> FT_OK) then begin form1._msg('UFS clrrts error'); Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_Out <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_IN <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (set_usb_Device_rts <> FT_OK) then begin form1._msg('UFS rtsset error'); Close_USB_Device; Result := False; exit; end; if (clr_usb_Device_rts <> FT_OK) then begin form1._msg('UFS clrrts error'); Close_USB_Device; Result := False; exit; end; if (set_usb_Device_dtr <> FT_OK) then begin form1._msg('UFS dtrset error'); Close_USB_Device; Result := False; exit; end; if (set_usb_Device_rts <> FT_OK) then begin form1._msg('UFS rtsset error'); Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_Out <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_IN <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; goto TryAgain; end; end else result := true; end; function WriteByte(inp: Byte): boolean; begin FT_Out_Buffer[0] := inp; Write_USB_Device_Buffer(1); end; function SwitchBoxMode(Mode: string): boolean; const BoxBoot: array[0..6] of Byte = ($4C, $1D, $1D, $1F, $02, $0D, $98); var PrevStatus: string; ic: Integer; begin Result := False; if Mode = 'FBUS' then begin if (Set_USB_Device_Event_Notification(01) <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; FT_current_DataBits := 8; FT_Current_StopBits := 0; FT_Current_Parity := 0; if Set_USB_Device_DataCharacteristics <> FT_OK then begin Close_USB_Device; Result := False; exit; end; FT_Current_FlowControl := 0; FT_XON_Value := $11; FT_XOFF_Value := $13; if Set_USB_Device_FlowControl <> FT_OK then begin Close_USB_Device; Result := False; exit; end; FT_Out_Buffer[0] := $38; ufs_cmd(50, @ft_out_buffer, 1, @cmd_buf, $05); FT_Out_Buffer[0] := $44; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $08; FT_Out_Buffer[4] := $00; ufs_cmd(250, @ft_out_buffer, 5, @cmd_buf, $05); FT_Out_Buffer[0] := $44; FT_Out_Buffer[1] := $18; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $08; FT_Out_Buffer[4] := $00; ufs_cmd(250, @ft_out_buffer, 5, @cmd_buf, $05); FT_Out_Buffer[0] := $55; FT_Out_Buffer[1] := $05; ufs_cmd(50, @ft_out_buffer, 2, @cmd_buf, $03); if Set_USB_Device_TimeOuts(60000, 60000) <> ft_ok then begin Close_USB_Device; Result := False; exit; end; FT_Out_Buffer[0] := $42; FT_Out_Buffer[1] := $10; ufs_cmd(1, @ft_out_buffer, 2, @cmd_buf, $01); if (Set_USB_Device_BaudRate_Divisor($50001A) <> FT_OK) then begin form1._msg('Baudrate switch failed. This is critical.'); Close_USB_Device; Result := False; exit; end; FT_Out_Buffer[0] := $58; ufs_cmd(1000, @ft_out_buffer, 1, @cmd_buf, 1); FT_Out_Buffer[0] := $32; ufs_cmd(50, @ft_out_buffer, 1, @cmd_buf, 1); if (clr_usb_Device_dtr <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (clr_usb_Device_dtr <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (set_usb_Device_dtr <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_Out <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; if (Purge_USB_Device_IN <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; FT_Out_Buffer[0] := $67; ufs_cmd(500, @ft_out_buffer, 1, @cmd_buf, 1); // FBUS Mode, DTR High, RTS Low, Flow: NO FT_Out_Buffer[0] := $68; FT_Out_Buffer[1] := $00; ufs_cmd(50, @ft_out_buffer, 2, @cmd_buf, $01); FT_Out_Buffer[0] := $66; ufs_cmd(100, @ft_out_buffer, 1, @cmd_buf, $01); FT_Out_Buffer[0] := $A5; ufs_cmd(50, @ft_out_buffer, 1, @cmd_buf, $01); // DTR falling-edge if (clr_usb_Device_dtr <> FT_OK) then begin Close_USB_Device; Result := False; exit; end; Result := True; end; if Mode = 'FlashBus' then begin {FT_Out_Buffer[0]:=$32; ufs_cmd(200,@ft_out_buffer,1,@cmd_buf,$01); FT_Current_FlowControl:=FT_FLOW_NONE; FT_XON_Value:=$11; FT_XOFF_Value:=$13; if Set_USB_Device_FlowControl <> FT_OK then begin form1._msg('UFS flowcontrol set failed'); Close_USB_Device; exit; end; if (set_usb_Device_dtr <> FT_OK) then begin Close_USB_Device; Result:=False; exit; end; if (Purge_USB_Device_IN <> FT_OK) then begin Close_USB_Device; Result:=False; exit; end; if (Set_USB_Device_TimeOuts($10000,$10000)<> FT_OK) then begin Close_USB_Device; Result:=False; exit; end; FT_Out_Buffer[0]:=$78; ufs_cmd(200,@ft_out_buffer,1,@cmd_buf,$01); FT_Out_Buffer[0]:=$42; FT_Out_Buffer[1]:=$00; ufs_cmd(200,@ft_out_buffer,2,@cmd_buf,$01); sleep(100); if (Set_USB_Device_BaudRate_Divisor($1) <> FT_OK) then begin Close_USB_Device; Result:=False; exit; end; FT_Out_Buffer[0]:=$32; ufs_cmd(300,@ft_out_buffer,1,@cmd_buf,$01); FT_Current_FlowControl:=FT_FLOW_DTR_DSR; FT_XON_Value:=$11; FT_XOFF_Value:=$13; if Set_USB_Device_FlowControl <> FT_OK then begin form1._msg('UFS flowcontrol set failed'); Close_USB_Device; exit; end; FT_Out_Buffer[0]:=$67; ufs_cmd(500,@ft_out_buffer,1,@cmd_buf,1); FT_out_Buffer[0] := $62; FT_out_Buffer[1] := $FB; FT_out_Buffer[2] := $01; FT_out_Buffer[3] := $AA; ufs_cmd(2000,@ft_out_buffer,4,@cmd_buf,3); } Reset_USB_Device; Set_USB_Device_FlowControl; Set_USB_Device_DTR; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_TimeOuts(10000, 10000); Purge_USB_Device_Out; Purge_USB_Device_In; Sleep(100); FT_Out_Buffer[0] := $4C; FT_Out_Buffer[1] := $1D; FT_Out_Buffer[2] := $1D; FT_Out_Buffer[3] := $1F; FT_Out_Buffer[4] := $02; FT_Out_Buffer[5] := $0D; FT_Out_Buffer[6] := $98; ufs_cmd(600, @Ft_out_buffer, 7, @cmd_buf, 5); Reset_USB_Device; FT_Out_Buffer[0] := $42; FT_Out_Buffer[1] := $00; ufs_cmd(600, @Ft_out_buffer, 2, @cmd_buf, 0); //Set UFS to Atmel MODE first Reset_USB_Device; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_DTR; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_TimeOuts(500, 8000); FT_Current_FlowControl := 0; Set_USB_Device_FlowControl; Set_USB_Device_TimeOuts(6000, 8000); if Set_USB_Device_BaudRate_Divisor($1) <> FT_Ok then Exit; FT_out_Buffer[0] := $58; ufs_cmd(600, @Ft_out_buffer, 1, @cmd_buf, 1); FT_Out_Buffer[0] := $32; ufs_cmd(600, @Ft_out_buffer, 1, @cmd_buf, 1); FT_out_Buffer[0] := $68; FT_out_Buffer[1] := $01; ufs_cmd(600, @Ft_out_buffer, 2, @cmd_buf, 1); FT_Out_Buffer[0] := $67; ufs_cmd(600, @Ft_out_buffer, 1, @cmd_buf, 1); Set_USB_Device_FlowControl; Set_USB_Device_DTR; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_TimeOuts(10000, 10000); Purge_USB_Device_Out; Purge_USB_Device_In; FT_Out_Buffer[0] := $78; ufs_cmd(600, @Ft_out_buffer, 1, @cmd_buf, 1); Purge_USB_Device_Out; Purge_USB_Device_In; FT_Out_Buffer[0] := $42; FT_Out_Buffer[1] := $00; ufs_cmd(600, @Ft_out_buffer, 2, @cmd_buf, 0); if Set_USB_Device_BaudRate_Divisor($1) <> FT_Ok then Exit; FT_Out_Buffer[0] := $32; ufs_cmd(600, @Ft_out_buffer, 1, @cmd_buf, 1); FT_Current_FlowControl := 512; Set_USB_Device_FlowControl; if Set_USB_Parameters(65536, 65536) <> FT_Ok then Exit; FT_Out_Buffer[0] := $67; ufs_cmd(600, @Ft_out_buffer, 1, @cmd_buf, 1); sleep(100); FT_out_Buffer[0] := $62; FT_out_Buffer[1] := $FB; FT_out_Buffer[2] := $01; FT_out_Buffer[3] := $AA; ufs_cmd(2000, @Ft_out_buffer, 4, @cmd_buf, 3); Form1.statusbar.Panels[4].Text := ''; if {(cmd_buf[0]=$FF) and }(cmd_buf[1] = $FF) or (cmd_buf[2] = $72) then begin form1._msg('FlashMode set Ok'); result := True; end else result := False; end; if Mode = 'FastReset' then begin FT_Out_Buffer[0] := $67; ufs_cmd(500, @ft_out_buffer, 1, @cmd_buf, 1); Result := True; end; if Mode = 'Infineon' then begin if Set_USB_Device_TimeOuts($2710, $2710) <> FT_Ok then Exit; sleep(5); if Set_USB_Device_BaudRate_Divisor($1A) <> FT_Ok then Exit; Form1.statusbar.Panels[4].Text := ''; result := True; end; end; function ufx_sw_fbus(sn: string; mode: string): boolean; var cmd_buf: array[0..1024] of byte; chksum: byte; i: integer; Fuses: array[1..2] of byte; begin FT_Out_Buffer[0] := $4C; FT_Out_Buffer[1] := $4D; FT_Out_Buffer[2] := $54; FT_Out_Buffer[3] := $31; FT_Out_Buffer[4] := $39; FT_Out_Buffer[5] := $06; FT_Out_Buffer[6] := $EF; ufsfl_cmd(1200, @FT_out_buffer, 7, @cmd_buf, 1); //if cmd_buf[0]<>$2A then Form1._msg('Error prepare UFSx / '+byte2str(cmd_buf[0])); // check_licence FT_Out_Buffer[0] := $4C; FT_Out_Buffer[1] := $1D; FT_Out_Buffer[2] := $1D; FT_Out_Buffer[3] := $1F; FT_Out_Buffer[4] := $02; FT_Out_Buffer[5] := $0D; FT_Out_Buffer[6] := $98; ufsfl_cmd(300, @ft_out_buffer, 7, @cmd_buf, $01); //if cmd_buf[0]<>$3E then Form1._msg('Prepare error UFSx / '+byte2str(cmd_buf[0])); // firmware version FT_Out_Buffer[0] := $41; ufsfl_cmd(300, @ft_out_buffer, 1, @cmd_buf, 32); FT_Out_Buffer[0] := $58; ufsfl_cmd(300, @ft_out_buffer, 1, @cmd_buf, $01); //if cmd_buf[0]<>$5A then Form1._msg('Fail init UFSx / '+byte2str(cmd_buf[0])); {// bootloader version FT_Out_Buffer[0]:=$56; ufs_cmd(100,@ft_out_buffer,1,@cmd_buf,32); // firmware version FT_Out_Buffer[0]:=$41; ufs_cmd(100,@ft_out_buffer,1,@cmd_buf,32); // amtel sn FT_Out_Buffer[0]:=$54; ufs_cmd(50,@ft_out_buffer,1,@cmd_buf,$03); if (Purge_USB_Device_Out <> FT_OK) then begin form1._msg('Cannot purge UFSx #'+sn+'. This is critical.'); Close_USB_Device; Result:=False; exit; end; atmel_sn:=HexToInt(IntToHex(cmd_buf[0], 2)+IntToHex(cmd_buf[1], 2)); // read fuses FT_Out_Buffer[0]:=$53; ufs_cmd(50,@ft_out_buffer,1,@cmd_buf,$03); fuses[1]:=cmd_buf[1]; fuses[2]:=cmd_buf[2]; // check_licence FT_Out_Buffer[0]:=$4C; FT_Out_Buffer[1]:=$1D; FT_Out_Buffer[2]:=$1D; FT_Out_Buffer[3]:=$1F; FT_Out_Buffer[4]:=$02; FT_Out_Buffer[5]:=$0D; chksum:=FT_Out_buffer[1]+FT_Out_buffer[2]+FT_Out_buffer[3]+FT_Out_buffer[4]+FT_Out_buffer[5]; FT_Out_Buffer[6]:=-chksum; ufs_cmd(50,@ft_out_buffer,7,@cmd_buf,$03); // download eeprom FT_Out_Buffer[0]:=$39; ufs_cmd(500,@ft_out_buffer,1,@cmd_buf,194); eeprom:=''; for i:=0 to 193 do eeprom:=eeprom+IntToHex(cmd_buf[i], 2); } Result := SwitchBoxMode(mode); end; function NFB_Send55str(): boolean; var i: integer; begin Result := False; for i := 1 to 5 do begin FT_Out_Buffer[0] := $55; FT_Out_Buffer[1] := $55; FT_Out_Buffer[2] := $55; FT_Out_Buffer[3] := $55; FT_Out_Buffer[4] := $55; if (Write_USB_Device_Buffer(5)) <> 5 then exit; end; Result := true; end; function fbus_crc(data: string): string; var crc: byte; i: integer; s_crc: string; begin crc := 0; i := 0; while i < (strlen(pchar(data)) div 2) do begin crc := crc xor HexToInt(data[i * 2 + 1] + data[i * 2 + 2]); inc(i, 2); end; s_crc := inttohex(crc, 2); crc := 0; i := 1; while i < (strlen(pchar(data)) div 2) do begin crc := crc xor HexToInt(data[i * 2 + 1] + data[i * 2 + 2]); inc(i, 2); end; s_crc := s_crc + inttohex(crc, 2); Result := s_crc; end; function Suck_Fbus(timeout: dword; pCmd: pointer; CmdLen: dword; pDst: Pointer; CheckAck: boolean; SendAck: boolean): dword; var tries, totalread, toread, leftover: dword; finished: boolean; cnt, cnt1: longint; cBuf: array[0..$FFFF] of byte; crcBuf: string; CalculatedCRC, PacketCRC: string; ExpectedBuf: integer; i, j, k: integer; LoadCounter: integer; SecondPacketLength: Integer; SeqTmp: integer; BruteForce: Boolean; PrevStatus: string; begin Application.ProcessMessages; if (Purge_USB_Device_IN <> FT_OK) then exit; if (Purge_USB_Device_OUT <> FT_OK) then exit; Finished := False; Move(pCmd^, FT_OUT_BUFFER, CmdLen); if Write_USB_Device_Buffer(CmdLen) <> CmdLen then exit; Cnt := GetTickCount + TimeOut; Get_USB_Device_Queuestatus; if (CheckAck) then begin Cnt := GetTickCount + TimeOut; Get_USB_Device_Queuestatus; while (FT_Q_Bytes < 10) do begin Application.ProcessMessages; // check if Time not exceeded. if (Cnt - GetTickCount) <= 0 then break; Get_USB_Device_Queuestatus; end; if (Cnt - GetTickCount) <= 0 then exit else if Read_USB_Device_Buffer(10) <> 10 then exit; for i := 0 to 10 - 1 do AckPacket[i] := FT_IN_Buffer[i]; for i := 0 to 10 - 1 do FT_In_Buffer[i] := $00; // I think we have now ACK packet! if AckPacket[0] <> $1E then exit; if AckPacket[1] <> $10 then exit; if AckPacket[2] <> $00 then exit; if AckPacket[3] <> $7F then exit; // Now needed to Calculate and Check the ACK packet CRC crcBuf := ''; for i := 0 to 7 do crcBuf := crcBuf + IntToHex(AckPacket[i], 2); CalculatedCRC := Fbus_CRC(crcBuf); PacketCRC := IntToHex(AckPacket[8], 2) + IntToHex(AckPacket[9], 2); if CalculatedCRC <> PacketCRC then exit; end; // If crc is OK we need now to read the rest of packet Cnt := GetTickCount + TimeOut; Get_USB_Device_Queuestatus; while (FT_Q_Bytes < 1) do begin Application.ProcessMessages; // check if Time not exceeded. if (Cnt - GetTickCount) <= 0 then break; Get_USB_Device_Queuestatus; end; if (Cnt - GetTickCount) <= 0 then exit else if Read_USB_Device_Buffer(1) <> 1 then exit; if FT_In_Buffer[0] <> $1E then exit; // Trashed packet Cmd_Buf[0] := FT_In_Buffer[0]; FT_In_Buffer[0] := $00; // 1E i have now to come: 10, 00, TYPE, 00, LEN, in fact, 5 bytes Cnt := GetTickCount + TimeOut; Get_USB_Device_Queuestatus; while (FT_Q_Bytes < 5) do begin Application.ProcessMessages; // check if Time not exceeded. if (Cnt - GetTickCount) <= 0 then break; Get_USB_Device_Queuestatus; end; if (Cnt - GetTickCount) <= 0 then exit else if Read_USB_Device_Buffer(5) <> 5 then exit; for i := 1 to 5 do Cmd_Buf[i] := FT_In_Buffer[i - 1]; for i := 0 to 4 do FT_IN_Buffer[i] := $00; // how many bytes more to come? Cnt := GetTickCount + TimeOut; Get_USB_Device_Queuestatus; while (FT_Q_Bytes < Cmd_Buf[5]) do begin Application.ProcessMessages; // check if Time not exceeded. if (Cnt - GetTickCount) <= 0 then break; Get_USB_Device_Queuestatus; end; if (Cnt - GetTickCount) <= 0 then exit else if Read_USB_Device_Buffer(Cmd_Buf[5]) <> Cmd_Buf[5] then exit; for i := 6 to Cmd_Buf[5] + 6 do Cmd_Buf[i] := FT_In_Buffer[i - 6]; // Download payload Cnt := GetTickCount + TimeOut; Get_USB_Device_Queuestatus; if FT_Q_Bytes > 0 then if Read_USB_Device_Buffer(FT_Q_Bytes) <> FT_Q_Bytes then exit; for i := 6 + Cmd_Buf[5] + 1 to 6 + Cmd_Buf[5] + 1 + FT_Q_Bytes do Cmd_Buf[i] := FT_In_Buffer[i - (6 + Cmd_Buf[5] + 1)]; SecondPacketLength := 6 + Cmd_Buf[5] + FT_Q_Bytes; for i := 0 to FT_Q_Bytes do FT_IN_Buffer[i] := $00; // Calculate and send CRC if (SendAck) then begin AckPacket[1] := $00; AckPacket[2] := $10; AckPacket[6] := Cmd_Buf[3]; //if AckPacket[7]=$07 then AckPacket[7]:=$00 else AckPacket[7]:=AckPacket[7]+1; AckPacket[7] := (Seq + 1) - $40; // Calculate ack packet crc crcBuf := ''; for i := 0 to 7 do crcBuf := crcBuf + IntToHex(AckPacket[i], 2); CalculatedCRC := Fbus_CRC(crcBuf); AckPacket[8] := HexToInt(CalculatedCRC[1] + CalculatedCRC[2]); AckPacket[9] := HexToInt(CalculatedCRC[3] + CalculatedCRC[4]); for i := 0 to 9 do FT_Out_Buffer[i] := AckPacket[i]; // Send ack packet if Write_USB_Device_Buffer(10) <> 10 then exit; end; // When all ok, clear buffers if (Purge_USB_Device_IN <> FT_OK) then exit; if (Purge_USB_Device_OUT <> FT_OK) then exit; // Notify peer process that all is ok Result := SecondPacketLength; end; function SendFBusFrame(var FrameBuf: array of byte; CheckAck: boolean; SendAck: boolean): boolean; var n, len: integer; tstr: string; CRC: word; // UFSx only RxBuf: array[0..$FFFF] of byte; i: integer; begin Application.ProcessMessages; result := false; len := FrameBuf[4] * $100 + FrameBuf[5]; len := (len + 1) and $FFFFFFFE; {Round UP} len := len + 2 + 6; {--- Update Frames counter ------} FR_CNT1 := (FR_CNT1 and $07) or $40; if ((FrameBuf[len - 3] <= $50) or (len <= $0A)) then begin if FrameBuf[3] <> $7F then if len > $0A then if Mode12A4 <> 0 then begin if (FrameBuf[5] and 1) = 1 then FrameBuf[len - 4] := FR_CNT1 else FrameBuf[len - 3] := FR_CNT1; FR_CNT1 := ((FR_CNT1 + 1) and $07) or $40; end; end else begin FR_CNT1 := FrameBuf[len - 3] + 1; end; {- Calculate frame CRC -} CRC := 0; for n := 0 to ((len - 2) div 2) - 1 do CRC := CRC xor ((FrameBuf[n * 2] * $100) + FrameBuf[n * 2 + 1]); FrameBuf[len - 2] := (CRC div $100) and $FF; FrameBuf[len - 1] := CRC and $FF; {---------------------------------} for n := 0 to len - 1 do FT_Out_Buffer[n] := FrameBuf[n]; ///form1._msg('TXbuf: '+buftohexstr(@FT_Out_Buffer[0], len)); n := Suck_FBUS(Fbus_Timeout, @FT_OUT_BUFFER, len, @cmd_buf, CheckAck, SendAck); if (n > 0) and (n < 255) then begin for i := 0 to n do RxFrBuf[i] := Cmd_Buf[i]; Result := True end; end; function SendFrameAndSendAck(Frame: array of byte; IFrameLen: integer; MekeSeq: Boolean; CheckAck: Boolean; SendAck: Boolean): integer; var CurrentBuffer: array[0..$8000] of byte; FrameLen, FrameLenTmp: integer; i, n: integer; rdd: integer; Retry: integer; EndframePointer: integer; MaxRetry: integer; DebugBuf: string; TID: longword; label Start, StartUFSx; begin Application.ProcessMessages; MaxRetry := 8; Result := 0; Retry := 1; // SEND FRAME :: DETECT PHONE for i := 0 to $8000 do RxFrBuf[i] := $00; for i := 0 to IFrameLen do TxFrBuf[i] := Frame[i]; for i := 0 to $8000 do FrameInside[i] := $00; // Check ack is make Seq if (MekeSeq) then begin IFrameLen := IFrameLen + 1; TxFrBuf[IFrameLen] := MakeSeq; // Make sequentional number end; StartUFSx: if Retry > 1 then begin if (NFB_Send55str) = FALSE then begin form1._msg('UFS 0x55 error'); exit; end; end; if (SendFBUSFrame(TxFrBuf, CheckAck, SendAck)) = FALSE then begin Retry := Retry + 1; if Retry >= MaxRetry then begin form1._msg('UFS ack error'); exit; end else begin sleep(2000); goto StartUFSx; end; end; FrameLen := RxFrBuf[5]; for i := 6 to FrameLen + 6 do FrameInside[i - 6] := RxFrBuf[i]; Result := Framelen - 2; end; function BArmInterface(): boolean; var retry, i: integer; InterfaceArmed: boolean; c_buf: string; label dummy_sn_retry; begin USBClosePort; form1._msg('Searching Devices... '); GetFTDeviceCount; form1._msg(IntToStr(FT_Device_Count) + ' devices found.'); if FT_Device_Count < 1 then exit; u_id := 0; retry := 1; dummy_sn_retry: GetFTDeviceDescription(u_id); u_id_reprezentation := FT_Device_String; GetFTDeviceSerialNo(u_id); u_sn := FT_Device_String; Application.ProcessMessages; if (u_sn = '') or (MatchesMask(u_id_reprezentation, '*UFS*') = false) then begin if (FT_Device_Count) > 0 then begin if FT_Device_Count = Retry then begin form1._msg('UFS not found. Try to reconnect it'); exit; end; for i := retry + 1 to FT_Device_Count do begin retry := i; u_id := i - 1; goto dummy_sn_retry; end; end; end else u_g_sn := inttostr(strtoint(u_sn) * 1); // fix the 000* sn form1._msg('Booting UFS #' + u_g_sn); if (ufx_boot(u_sn)) then begin Application.ProcessMessages; ///4C 4D 54 31 39 06 EF //2A //4C 1D 1D 1F 02 0D 98 //3E //41 //58 =>5A //32 =>72 FT_Out_Buffer[0] := $56; ufs_cmd(100, @ft_out_buffer, 1, @cmd_buf, $20); c_buf := ''; for i := 0 to 31 do c_buf := c_buf + Chr(cmd_buf[i]); if (MatchesMask(c_buf, 'UFxBoot V?.? (c) SarasSoft 200?.') = FALSE) then begin form1._msg('UFSBoot is damaged!'); Close_USB_Device; exit; end; form1._msg(c_buf); Application.ProcessMessages; FT_Out_Buffer[0] := $41; ufs_cmd(100, @ft_out_buffer, 1, @cmd_buf, $20); c_buf := ''; for i := 0 to 31 do c_buf := c_buf + chr(cmd_buf[i]); if (MatchesMask(c_buf, 'UFS_USB V2.? (c) SarasSoft 200?.') = FALSE) then begin form1._msg('UFS Firmware is damaged!'); Close_USB_Device; exit; end; form1._msg(c_buf); if (ufx_sw_fbus(u_sn, 'FBUS')) then begin Seq := $40; for i := 0 to 20 do begin Sleep(50); Application.ProcessMessages; end; end; Application.ProcessMessages; end; form1._msg(''); end; function GetPMFieldLength(Field: integer): Integer; var Frame_GetPMFieldLength: array[0..$C] of byte; n, i: integer; Str_Field: string; begin Result := 0; Str_Field := IntToHex(Field, 4); // Build frame Frame_GetPMFieldLength[$0] := $1E; // fbus header Frame_GetPMFieldLength[$1] := $00; // destination - phone Frame_GetPMFieldLength[$2] := $10; // source - PC Frame_GetPMFieldLength[$3] := $23; // Msg TYPE Frame_GetPMFieldLength[$4] := $00; // msg len 0x00 Frame_GetPMFieldLength[$5] := $08; // msg len 0x01 Frame_GetPMFieldLength[$6] := $00; // payload 7bytes Frame_GetPMFieldLength[$7] := $0D; Frame_GetPMFieldLength[$8] := $C2; Frame_GetPMFieldLength[$9] := $0E; Frame_GetPMFieldLength[$A] := HexToInt(Str_Field[1] + Str_Field[2]); // Field_1 Frame_GetPMFieldLength[$B] := HexToInt(Str_Field[3] + Str_Field[4]); // Field_2 Frame_GetPMFieldLength[$C] := $01; // overhead not included n := SendFrameAndSendAck(Frame_GetPMFieldLength, $C, True, True, True); Result := FrameInside[n - 1]; end; function PMWriteCurrentKey(Field: integer; Key: integer; KeyLength: integer): integer; var Frame_WritePM: array[0..$8000] of byte; n, i, j, k, z: integer; HowManyPackets, OverAllPackets: integer; CurrentPacket: integer; SectorSize: integer; tmp: string; ProceedWithAck: Boolean; OverheadpacketsDone, OverHeadPacketsLeft: integer; ConvBuf: string; CurrWriteSectorSize: integer; begin Result := 0; // Build Frame Frame_WritePM[0] := $1E; //header Frame_WritePM[1] := $00; //src Frame_WritePM[2] := $10; //dst Frame_WritePM[3] := $23; //msgtype // [4] length // [5] length // Current payload Frame_WritePM[6] := $00; Frame_WritePM[7] := $08; Frame_WritePM[8] := $01; Frame_WritePM[9] := $02; ConvBuf := IntToHex(Field, 4); Frame_WritePM[10] := HexToInt(ConvBuf[1] + ConvBuf[2]); Frame_WritePM[11] := HexToInt(ConvBuf[3] + ConvBuf[4]); ConvBuf := IntToHex(Key, 4); Frame_WritePM[12] := HexToInt(ConvBuf[1] + ConvBuf[2]); Frame_WritePM[13] := HexToInt(ConvBuf[3] + ConvBuf[4]); Frame_WritePM[14] := 00; Frame_WritePM[15] := 00; Frame_WritePM[16] := 00; // 17 PM Data Length - 1 // 18 PM Data Length - 2 // 19 PM Data Length - 3 CurrWriteSectorSize := 96; if KeyLength <= CurrWriteSectorSize then begin Frame_WritePM[4] := (KeyLength + 16) div $100; Frame_WritePM[5] := (KeyLength + 16) mod $100; Frame_WritePM[17] := $00; Frame_WritePM[18] := KeyLength div $100; Frame_WritePM[19] := KeyLength mod $100; for i := 0 to KeyLength - 1 do begin Frame_WritePM[20 + i] := PMWrBuffer[i]; end; Frame_WritePM[20 + KeyLength] := $01; n := SendFrameAndSendAck(Frame_WritePM, 20 + KeyLength, True, True, True); if FrameInside[5] = $01 then begin Result := KeyLength; end else Result := 0; end else begin // First Sector size is ALWAYS 106 bytes, cause PM_PACKET_TYPE must be MAX 0x7A , so 106+overhead > 7A SectorSize := CurrWriteSectorSize; // 106 + 0xFE * 120 (max_sector_size) = 30586 if KeyLength > $FFA0 then exit; // Here we need to count how many packets will be sent to phone. Algo is // simple. Keylength-106(cause first packet) HowManyPackets := ((KeyLength - CurrWriteSectorSize) div CurrWriteSectorSize) + 3; /// or +3.. have no idea, need to test with FBUS olso // Multi-Packet Flag Frame_WritePM[8] := $02; CurrentPacket := 1; OverAllPackets := HowManyPackets; // Send first packet Frame_WritePM[4] := (SectorSize + 16) div $100; Frame_WritePM[5] := (SectorSize + 16) mod $100; //Result shoudl be 7A! Frame_WritePM[17] := 00; Frame_WritePM[18] := KeyLength div $100; Frame_WritePM[19] := KeyLength mod $100; for i := 0 to SectorSize - 1 do begin Frame_WritePM[20 + i] := PMWrBuffer[i]; end; Frame_WritePM[20 + SectorSize] := OverAllPackets; // Send first packet n := SendFrameAndSendAck(Frame_WritePM, 20 + SectorSize, True, False, False); SectorSize := CurrWriteSectorSize; //Switching to BIG_MODE // One packet sent HowManyPackets := HowManyPackets - 2; CurrentPacket := CurrentPacket + 1; OverHeadPacketsDone := 0; OverHeadPacketsLeft := HowManyPackets; for i := 1 to HowManyPackets do begin if i = HowManyPackets then begin SectorSize := (KeyLength - CurrWriteSectorSize) - (((KeyLength - CurrWriteSectorSize) div CurrWriteSectorSize) * CurrWriteSectorSize); ProceedWithAck := True; end else SectorSize := CurrWriteSectorSize; Frame_WritePM[4] := (SectorSize + 2) div $100; Frame_WritePM[5] := (SectorSize + 2) mod $100; z := 0; for j := CurrWriteSectorSize + ((i - 1) * CurrWriteSectorSize) to (CurrWriteSectorSize + ((i - 1) * CurrWriteSectorSize)) + (SectorSize - 1) do begin // Fill buffer with data Frame_WritePM[6 + z] := PMWrBuffer[j]; z := z + 1; end; Frame_WritePM[6 + SectorSize] := OverHeadPacketsLeft; Frame_WritePM[7 + SectorSize] := MakeSeq - $40; SendFrameAndSendAck(Frame_WritePM, 5 + SectorSize + 1 + 1, False, ProceedWithAck, ProceedWithAck); OverHeadPacketsLeft := OverHeadPacketsLeft - 1; OverHeadPacketsDone := OverHeadPacketsDone + 1; end; if FrameInside[5] = $01 then begin Result := KeyLength; end else Result := 0; end; end; function GetPMKeyLength(Field: integer; Key: integer): Integer; var Frame_GetPMKey: array[0..$10] of byte; n, i: integer; KeyLength: integer; Str_Field: string; Str_Key: string; begin Result := 0; Str_Field := IntToHex(Field, 4); Str_Key := IntToHex(Key, 4); Frame_GetPMKey[$0] := $1E; Frame_GetPMKey[$1] := $00; Frame_GetPMKey[$2] := $10; Frame_GetPMKey[$3] := $23; Frame_GetPMKey[$4] := $00; Frame_GetPMKey[$5] := $0C; Frame_GetPMKey[$6] := $00; Frame_GetPMKey[$7] := $0D; Frame_GetPMKey[$8] := $0F; Frame_GetPMKey[$9] := $0C; Frame_GetPMKey[$A] := HexToInt(Str_Field[1] + Str_Field[2]); Frame_GetPMKey[$B] := HexToInt(Str_Field[3] + Str_Field[4]); Frame_GetPMKey[$C] := HexToInt(Str_Key[1] + Str_Key[2]); Frame_GetPMKey[$D] := HexToInt(Str_Key[3] + Str_Key[4]); Frame_GetPMKey[$E] := $00; Frame_GetPMKey[$F] := $00; Frame_GetPMKey[$10] := $01; n := SendFrameAndSendAck(Frame_GetPMKey, $10, True, True, True); if n = 0 then exit; if FrameInside[5] = $00 then KeyLength := 0; if FrameInside[5] = $01 then begin KeyLength := HexToInt(IntToHex(FrameInside[n - 3], 2) + IntToHex(FrameInside[n - 2], 2) + IntToHex(FrameInside[n - 1], 2)); if KeyLength = 0 then KeyLength := $FFFFFF; end; Result := KeyLength; end; function PMReadCurrentKey(Field: integer; Key: Integer; KeyLength: Integer): Integer; var Frame_GetPMContent: array[0..24] of byte; i, n, j: integer; CurrentSector: integer; SectorLength: integer; PMCount: integer; CurrentBuffer: array[0..$8000] of byte; ExtractedPMSize: integer; ConvBuf: string; MaxGauge, CurrGauge: integer; Str_Field: string; Str_Key: string; OldStatus: string; MaxKeyLen: word; begin Result := 0; PMCount := 0; Str_Field := IntToHex(Field, 4); Str_Key := IntToHex(Key, 4); MaxKeyLen := $64; if KeyLength > MaxKeyLen then begin //OldStatus:=Form1.NStatus.Panels.Items[0].Text; end; for i := 0 to (KeyLength div MaxKeyLen) do // Sector size is $64 begin if KeyLength > MaxKeyLen then begin //Form1.NStatus.Panels.Items[0].Text:='Reading Long PM Field '+IntToStr(Field)+', Key '+IntToStr(Key)+', Len '+IntTOStr(KeyLength)+' bytes, Readen Sectors: '+IntToStr(i)+'/'+IntToStr((KeyLength div $64)); end; CurrentSector := i * MaxKeyLen; if i = (KeyLength div MaxKeyLen) then SectorLength := (KeyLength mod MaxKeyLen) else SectorLength := MaxKeyLen; // if overhead is detected Frame_GetPMContent[0] := $1E; Frame_GetPMContent[1] := $00; Frame_GetPMContent[2] := $10; Frame_GetPMContent[3] := $23; Frame_GetPMContent[4] := $00; Frame_GetPMContent[5] := $14; Frame_GetPMContent[6] := $00; Frame_GetPMContent[7] := $0D; Frame_GetPMContent[8] := $10; Frame_GetPMContent[9] := $04; Frame_GetPMContent[10] := HexToInt(Str_Field[1] + Str_Field[2]); Frame_GetPMContent[11] := HexToInt(Str_Field[3] + Str_Field[4]); Frame_GetPMContent[12] := HexToInt(Str_Key[1] + Str_Key[2]); Frame_GetPMContent[13] := HexToInt(Str_Key[3] + Str_Key[4]); Frame_GetPMContent[14] := $00; Frame_GetPMContent[15] := $00; Frame_GetPMContent[16] := $00; ConvBuf := IntToHex(CurrentSector, 6); Frame_GetPMContent[17] := HexToInt(ConvBuf[1] + ConvBuf[2]); Frame_GetPMContent[18] := HexToInt(ConvBuf[3] + ConvBuf[4]); Frame_GetPMContent[19] := HexToInt(ConvBuf[5] + ConvBuf[6]); Frame_GetPMContent[20] := $00; Frame_GetPMContent[21] := $00; Frame_GetPMContent[22] := SectorLength div $100; Frame_GetPMContent[23] := SectorLength mod $100; Frame_GetPMContent[24] := $01; n := SendFrameAndSendAck(Frame_GetPMContent, 24, True, True, True); if n = 0 then exit; if n < SectorLength + 5 then exit; if FrameInside[0] <> Frame_GetPMContent[7] then exit; ExtractedPMSize := (FrameInside[16] * $100) + FrameInside[17]; if ExtractedPMSize <> SectorLength then exit; for j := PMCount to PMCount + (ExtractedPMSize - 1) do PMData[j] := FrameInside[18 + (j - PMCount)]; // we have so it located into CurrentBuffer what then ? PMCount := PMCount + SectorLength; end; if KeyLength > MaxKeyLen then begin //Form1.NStatus.Panels.Items[0].Text:=OldStatus; end; Result := PMCount - 1; end; function readData(): boolean; const Frame_GetOTPIMEI: array[0..$E] of byte = ($1E, $00, $10, $1B, $00, $0A, $00, $01, $01, $00, $41, $00, $00, $00, $01); Frame_DetectPPM: array[0..$C] of byte = ($1E, $00, $10, $1B, $00, $08, $00, $03, $1F, $07, $01, $00, $01); Frame_GetCodeCount: array[0..$B] of byte = ($1E, $00, $10, $53, $00, $07, $00, $08, $00, $12, $0D, $01); Frame_BB5_GetCP: array[0..$10] of byte = ($1E, $00, $10, $1B, $00, $0C, $00, $06, $06, $07, $00, $00, $00, $00, $04, $00, $01); Frame_BB5_GetAPESW: array[0..$10] of byte = ($1E, $00, $10, $1B, $00, $0C, $00, $06, $06, $07, $00, $00, $00, $00, $00, $02, $01); Frame_BB5_GetAPEVA: array[0..$10] of byte = ($1E, $00, $10, $1B, $00, $0C, $00, $06, $06, $07, $00, $00, $00, $00, $00, $04, $01); Frame_DetectPhone: array[0..$B] of byte = ($1E, $00, $10, $D1, $00, $07, $00, $01, $00, $03, $00, $01); var n, i, x, j: integer; buf: string; DelimiterPos, PointerBuf: integer; PPM, Tmp: string; begin Product := ''; SWVersion := ''; SWDate := ''; Manufacturer := ''; SwitchBoxMode('FBUS'); if (NFB_Send55str) = FALSE then begin form1._msg('0x55 Reset Error'); exit; end; n := SendFrameAndSendAck(Fphonename, Length(fphonename), True, True, True); if n = 0 then begin form1._msg('Phone not found'); exit; end; Form1._msg('Name : ' + hex2chr(BufToHexStr(@FrameInside[10], FrameInside[9]))); n := SendFrameAndSendAck(Frame_DetectPhone, $B, True, True, True); if n = 0 then begin form1._msg('Phone not found'); exit; end; for i := 0 to n - 1 do begin if (FrameInside[i] > $0F) or (FrameInside[i] = $0A) then if FrameInside[i] = $0A then McuSW_Buf := McuSW_BUf + ', ' else McuSW_Buf := McuSW_Buf + Chr(FrameInside[i]); end; // Scan all stuff in McuSW buf for i := 1 to StrLen(PChar(McuSW_Buf)) do begin if McuSW_Buf[i] = ',' then begin PointerBuf := i; break; end; SWVersion := SWVersion + McuSW_Buf[i]; end; for i := PointerBuf + 2 to StrLen(PChar(McuSW_Buf)) do begin if McuSW_Buf[i] = ',' then begin PointerBuf := i; break; end; SWDate := SWDate + McuSW_Buf[i]; end; for i := PointerBuf + 2 to StrLen(PChar(McuSW_Buf)) do begin if McuSW_Buf[i] = ',' then begin PointerBuf := i; break; end; Product := Product + McuSW_Buf[i]; end; for i := PointerBuf + 2 to StrLen(PChar(McuSW_Buf)) do begin if McuSW_Buf[i] = ',' then begin PointerBuf := i; break; end; Manufacturer := Manufacturer + McuSW_Buf[i]; end; // OK we have all needed info, lets roll! form1._msg('SWver : ' + Product + ' , ' + SWVersion + ' , ' + SWDate + ' , ' + Manufacturer); n := SendFrameAndSendAck(Frame_GetOTPIMEI, $E, True, True, True); if n = 0 then begin form1._msg('Extended info, Get OTP IMEI, Transmit error, aborting'); exit; end; Buf := ''; for i := 1 to FrameInside[9] - 1 do Buf := Buf + Chr(FrameInside[9 + i]); form1._msg('IMEI : ' + BUF); n := SendFrameAndSendAck(Frame_DetectPPM, $C, True, True, True); if n = 0 then begin form1._msg('Extended info, PPM Info, Transmit error, aborting'); exit; end; for i := 0 to n do begin Buf := Buf + Chr(FrameInside[i]); end; i := StrLen(PChar(Buf)); repeat i := i - 1; until Buf[i] = ','; DelimiterPos := i; for i := DelimiterPos + 2 to StrLen(PChar(Buf)) do PPM := PPM + Buf[i]; x := 0; for i := 1 to StrLen(PChar(PPM)) do begin if PPM[i] = '.' then x := i; end; Buf := ''; if x <> 0 then begin for i := x + 1 to StrLen(PChar(PPM)) do begin buf := buf + PPM[i]; end; PPM := Buf; end; form1._msg('PPM Variant : ' + PPM); n := SendFrameAndSendAck(Frame_BB5_GetCP, $10, True, True, True); if n = 0 then begin form1._msg('Extended info, Get CP, Transmit error, aborting'); exit; end; Buf := ''; for i := 1 to FrameInside[9] - 1 do begin if FrameInside[9 + i] = $0A then Buf := Buf + ', ' else Buf := Buf + Chr(FrameInside[9 + i]); end; if Buf <> '' then begin Tmp := ''; j := 0; for i := 1 to StrLen(pChar(Buf)) - 2 do begin if j = 50 then begin form1._msg('CNT Version : ' + Tmp); Tmp := ''; j := 0; end else begin j := j + 1; Tmp := Tmp + Buf[i]; if i = StrLen(pChar(Buf)) then j := 50; end; end; end; n := SendFrameAndSendAck(Frame_BB5_GetAPESW, $10, True, True, True); if n = 0 then begin form1._msg('Extended info, Get APESW, Transmit error, aborting'); exit; end; Buf := ''; for i := 1 to FrameInside[9] - 1 do begin if FrameInside[9 + i] = $0A then Buf := Buf + ', ' else Buf := Buf + Chr(FrameInside[9 + i]); end; if Buf <> '' then form1._msg('APE Core : ' + BUF); n := SendFrameAndSendAck(Frame_BB5_GetAPEVA, $10, True, True, True); if n = 0 then begin form1._msg('Extended info, Get APEVA, Transmit error, aborting'); exit; end; Buf := ''; for i := 1 to FrameInside[9] - 1 do begin if FrameInside[9 + i] = $0A then Buf := Buf + ', ' else Buf := Buf + Chr(FrameInside[9 + i]); end; if Buf <> '' then form1._msg('APE Variant : ' + BUF); n := SendFrameAndSendAck(Frame_GetCodeCount, $B, True, True, True); if n = 0 then begin form1._msg('Extended info, Get Simlock_Code_Count, Transmit error, aborting'); exit; end; Buf := ''; form1._msg('SL Key Count : ' + IntToStr(FrameInside[29] mod $10) + '/' + IntToStr(FrameInside[29] div $10)); Buf := ''; n := GetPMFieldLength(4); if n >= (4 div 2) then // 0 is key position begin n := GetPMKeyLength(4, 4); if n >= 7 then begin n := PMReadCurrentKey(4, 4, n); for i := 0 to n do Buf := Buf + Chr(PMData[i]); form1._msg('Product Code : ' + Buf); end; end; n := GetPMFieldLength(120); if n > 1 then begin form1._msg('New Security BB5 Phone'); end; end; function ChecCMTData(): boolean; begin Application.ProcessMessages; //Move(pCmd^, FT_OUT_BUFFER, CmdLen); FillMemory(@FT_IN_BUFFER, $FFFF, $00); FT_OUT_BUFFER[0] := $6E; FT_OUT_BUFFER[1] := $1F; if Write_USB_Device_Buffer(2) <> 2 then exit; Form1._msg('BootData : ' + BufToHexStr(@FT_IN_BUFFER[0], $62)); end; procedure FetchBootData; var Key, KeyLen: Byte; PacketLen: Byte; BlockCount: Byte; CurrBlock: Byte; CurrBlockLen: Word; i, j, k, l, m: integer; ape: Byte; begin apeexist := false; FASICape := ''; FASICcmt := ''; Application.ProcessMessages; FillMemory(@RAPInfo.APEASICID, $4, $00); 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.ROM_ID, $8, $00); Application.ProcessMessages; PacketLen := cmd_buf[1]; BlockCount := cmd_buf[3]; FLbyte := cmd_buf[Packetlen + 2]; i := 4; j := 0; m := 0; form1._msg(''); form1._msg('1st boot Ok, ' + byte2str(cmd_buf[2])); while (i < PacketLen) and (j < BlockCount) do begin Application.ProcessMessages; CurrBlock := cmd_buf[i]; inc(i); CurrBlockLen := (cmd_buf[i]); inc(i); case CurrBlock of $01: //RAP SYSTEM ASIC ID //5800 - 000000010000022600010006400C192101031103 [RAPIDO3G ver: 1.x] begin ape := cmd_buf[i]; inc(i); case ape of $01: begin Form1._msg(''); Form1._msg('APE part info : '); Application.ProcessMessages; for k := 0 to CurrBlockLen do RAPInfo.APEASICID[k] := cmd_buf[i + k]; Form1._msg('APE ASICID : ' + BufToHexStr(@RAPInfo.APEASICID[0], Length(RAPInfo.APEASICID))); inc(i, CurrBlockLen - 1); FASICape := BufToHexStr(@RAPInfo.APEASICID[0], Length(RAPInfo.APEASICID)); inc(j); apeexist := True; Application.ProcessMessages; end; $00: begin Form1._msg(''); Form1._msg('CMT part info : '); Application.ProcessMessages; for k := 0 to CurrBlockLen do RAPInfo.SYSTEM_ASIC_ID[k] := cmd_buf[i + k]; FASICcmt := Copy(BufToHexStr(@RAPInfo.SYSTEM_ASIC_ID[12], 8), 1, 16); Form1._msg('CMT ASICID : ' + BufToHexStr(@RAPInfo.SYSTEM_ASIC_ID[0], Length(RAPInfo.SYSTEM_ASIC_ID))); inc(i, CurrBlockLen - 1); inc(j); Application.ProcessMessages; end; end; end; $02: //RAP EMx ID //00000295 //00000B22 begin ape := FT_IN_BUFFER[i]; inc(i); case ape of $01: begin for k := 0 to CurrBlockLen do RAPInfo.EMx_ID[k] := cmd_buf[i + k]; Form1._msg('APE EM' + inttostr(m) + ' ID : ' + BufToHexStr(@RAPInfo.EMx_ID[0], 4)); inc(i, CurrBlockLen - 1); inc(j); inc(m); Application.ProcessMessages; end; $00: begin for k := 0 to CurrBlockLen do RAPInfo.EMx_ID[k] := cmd_buf[i + k]; Form1._msg('CMT EM' + inttostr(m) + ' ID : ' + BufToHexStr(@RAPInfo.EMx_ID[0], 4)); inc(i, CurrBlockLen - 1); inc(j); inc(m); Application.ProcessMessages; end; end; end; $12: //PUBLIC_ID //1FF0001841158B52064E64D3C3E9A7F38DC47E29 begin ape := FT_IN_BUFFER[i]; inc(i); case ape of $01: begin for k := 0 to CurrBlockLen do RAPInfo.PUBLIC_ID[k] := cmd_buf[i + k]; Form1._msg('APE PUB ID : ' + BufToHexStr(@RAPInfo.PUBLIC_ID[0], Length(RAPInfo.PUBLIC_ID))); inc(i, CurrBlockLen - 1); inc(j); Application.ProcessMessages; end; $00: begin for k := 0 to CurrBlockLen do RAPInfo.PUBLIC_ID[k] := cmd_buf[i + k]; Form1._msg('CMT PUB ID : ' + BufToHexStr(@RAPInfo.PUBLIC_ID[0], Length(RAPInfo.PUBLIC_ID))); inc(i, CurrBlockLen - 1); inc(j); Application.ProcessMessages; end; end; end; $13: //ASIC_MODE //00 begin ape := FT_IN_BUFFER[i]; inc(i); case ape of $01: begin RAPInfo.ASIC_MODE := cmd_buf[i]; Form1._msg('APE MODE ID : ' + BufToHexStr(@RAPInfo.ASIC_MODE, 1)); inc(i, CurrBlockLen - 1); inc(j); Application.ProcessMessages; end; $00: begin RAPInfo.ASIC_MODE := cmd_buf[i]; Form1._msg('CMT MODE ID : ' + BufToHexStr(@RAPInfo.ASIC_MODE, 1)); inc(i, CurrBlockLen - 1); inc(j); Application.ProcessMessages; end; end; end; $14: //ROOT_KEY_HASH //CAEEBB65D3C48E6DC73B49DC5063A2EE begin ape := cmd_buf[i]; inc(i); case ape of $01: begin for k := 0 to CurrBlockLen - 1 do RAPInfo.APErootkey[k] := cmd_buf[i + k]; inc(i, CurrBlockLen - 1); inc(j); Form1._msg('APE R_HASH : ' + BufToHexStr(@RAPInfo.APErootkey[0], Length(RAPInfo.ROOT_KEY_HASH))); Application.ProcessMessages; end; $00: begin for k := 0 to CurrBlockLen - 1 do RAPInfo.ROOT_KEY_HASH[k] := cmd_buf[i + k]; inc(i, CurrBlockLen - 1); inc(j); Form1._msg('CMT R_HASH : ' + BufToHexStr(@RAPInfo.ROOT_KEY_HASH[0], Length(RAPInfo.ROOT_KEY_HASH))); ROOTKEY := BufToHexStr(@RAPInfo.ROOT_KEY_HASH[0], Length(RAPInfo.ROOT_KEY_HASH)); Application.ProcessMessages; end; end; end; $15: //ROM_ID //4B9B75103E691FF8 begin ape := cmd_buf[i]; inc(i); case ape of $01: begin for k := 0 to CurrBlockLen - 1 do RAPInfo.ROM_ID[k] := cmd_buf[i + k]; Form1._msg('APE ROM ID : ' + BufToHexStr(@RAPInfo.ROM_ID[0], Length(RAPInfo.ROM_ID))); inc(i, CurrBlockLen - 1); inc(j); Application.ProcessMessages; end; $00: begin for k := 0 to CurrBlockLen - 1 do RAPInfo.ROM_ID[k] := cmd_buf[i + k]; Form1._msg('CMT ROM ID : ' + BufToHexStr(@RAPInfo.ROM_ID[0], Length(RAPInfo.ROM_ID))); inc(i, CurrBlockLen - 1); inc(j); Application.ProcessMessages; end; end; end; else begin inc(i, CurrBlockLen); inc(j); end; end; //End Of Case end; form1._msg(''); end; function replyverify(): Boolean; begin result := false; ufsfl_cmd(150, @Verifyreply[0], 6, @cmd_buf, 2); if cmd_buf[0] > $F0 then result := True; end; function replyverify2(): Boolean; begin result := false; ufsfl_cmd(50, @Verifyreply[0], 6, @cmd_buf, 2); if cmd_buf[0] > $F0 then Exit; result := True; end; function replyverify3(): byte; begin ufsfl_cmd(50, @Verifyreply[0], 6, @cmd_buf, 2); Result := cmd_buf[0]; end; function CheckVpp(): Boolean; var vpp, dual: string; begin result := false; {if not write_frame(@vppchk[0], Length(vppchk)) then Exit; if not read_frame(2,1000) then exit; } ufsfl_cmd(1500, @vppchk[0], 2, @cmd_buf, 2); if cmd_buf[0] <> $3F then vpp := 'False' else vpp := 'True'; if cmd_buf[1] <> $3F then dual := 'False' else dual := 'True'; //form1._msg('IGNITION : VPP : '+vpp+' , DUAL : '+dual); result := True; end; function GetReadLen(): Byte; begin result := $00; readDataReq[5] := $02; ufsfl_cmd(150, @readDataReq[0], Length(readDataReq), @cmd_buf, 4); result := cmd_buf[1]; readDataReq[5] := $00; end; function ReadDatarequest(bytes: byte): Boolean; var len: integer; begin result := false; readDataReq[5] := bytes; len := hexToInt(Byte2Str(bytes)) + 2; ufsfl_cmd(150, @readDataReq[0], Length(readDataReq), @cmd_buf, len); result := true; readDataReq[5] := $00; end; function Freaddata(bytes: byte): Boolean; var len: integer; begin result := false; readrDta[5] := bytes; len := hexToInt(Byte2Str(bytes)) + 2; ufs_cmd(150, @readrdta[0], Length(readrdta), @cmd_buf, len); result := true; end; function Freadflashic(): boolean; var FLasic, asfltype, s: string; begin flven := 0; Cfltype := $00; FLtype := ''; asfltype := ''; case cmd_buf[0] of $00: FLasic := 'CMT'; $01: FLasic := 'APE'; else FLasic := 'Unknow'; end; case cmd_buf[1] of $00: begin FLtype := 'NOR'; CFltype := $00; end; $01: begin AsFLtype := 'NAND'; Afltype := $01; end; $03: begin FLtype := 'NAND'; Cfltype := $03; end; $04: begin FLtype := 'MMC , EXT'; Cfltype := $04; end; else fltype := 'Unknow'; end; flven := dword((@cmd_buf[3])^); //DWordSwap(@flven); reversedword(@flven); case FT_In_Buffer[0] of 1: begin Form1._msg('FLASHID : ' + IntToHex(flven, 8) + ' , ' + FLasic + ' , NAND'); ReadFlashIc(0, flven); end; 0: begin Form1._msg('FLASHID : ' + IntToHex(flven, 8) + ' , ' + FLasic + ' , ' + fltype); ReadFlashIc(flven, 0); end; end; if Flven <> $0000FFFF then begin result := True; flicven := flven; end; end; function SendRaw(Asic: integer; Loader: string): integer; var rawloader, rawblock: TMemoryStream; b: Boolean; chk: word; tmp: array of Byte; i: integer; flblk: integer; lb: Byte; blkcnt, cblk, cblklen: Byte; flcnt: string; begin result := 9; algo := ''; case asic of $00: begin Form1.statusbar.Panels[0].Text := 'UFS : CMT 2ND boot...'; Form1._msg('CMT : Sending 2nd loader...'); Application.ProcessMessages; RAWblock := TMemoryStream.Create; rawblock.LoadFromFile(loader); form1._msg('Use : ' + extractfilename(Loader)); rawblock.Seek(0, soFromBeginning); RAWloader := TMemoryStream.Create; BB5_ExtractRAWLoader(RAWBlock, RAWLoader, b); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); if rawloader.size = 0 then exit; result := 8; // RAwloader prepare error //form1._msg('STbyte :'+byte2str(flbyte)); if FLbyte > $F0 then begin ufs_cmd(50, @prerawcheck[0], 3, @cmd_buf, 1); //Form1._msg('Set Data ['+Byte2Str(ft_in_buffer[0])+']'); //form1._msg('Set Data ['+Byte2Str(replyverify3)+']'); end; rawloader.ReadBuffer(tmp[0], rawloader.Size); RawLen[6] := rawloader.Size mod $100; RawLen[5] := rawloader.Size div $100; result := 7; // PrebootCheck error - raw len no accepted ufs_cmd(70, @Rawlen[0], 7, @cmd_buf, 2); //Form1._msg('Set data ['+byte2str(FT_In_Buffer[0])+']'); if cmd_buf[1] <> $72 then Exit; Application.ProcessMessages; FT_Out_Buffer[0] := $69; FT_Out_Buffer[1] := $02; FT_Out_Buffer[2] := $0A; FT_Out_Buffer[3] := $00; FT_Out_Buffer[5] := rawloader.Size mod $100; FT_Out_Buffer[4] := rawloader.Size div $100; FT_Out_Buffer[6] := $00; FT_Out_Buffer[7] := $00; Application.ProcessMessages; for i := 0 to rawloader.size + 7 do FT_Out_Buffer[i + 8] := TMP[i]; ufs_cmd(600, @FT_out_buffer, (rawloader.Size + 8), @cmd_buf, 7); result := 6; // rawloader not accepted by phone if cmd_buf[0] <> $00 then exit; if cmd_buf[6] <> $72 then exit; Application.ProcessMessages; Form1._msg('CMT Loader sent, Boot Ok'); Form1._msg('MCU Configuration'); Form1.statusbar.Panels[0].Text := 'UFS : 2ND Boot Ok, wait...'; case apeexist of true: ufs_cmd(75, @APEcrc[0], 16, @cmd_buf, 11); false: ufs_cmd(75, @CMTcrc[0], 16, @cmd_buf, 11); end; result := 5; // Fetch data fail blkcnt := Ft_in_buffer[1]; cblk := ft_in_buffer[2]; cblklen := ft_in_buffer[3]; if cblklen = 0 then Exit; for i := 0 to blkcnt - 1 do begin case cblk of $10: begin FreadData(cblklen + 2); // Flash ID descriptor //form1._msg(buftohexstr(@Ft_in_buffer[0],cblklen+2)); Freadflashic; cblk := ft_in_buffer[cblklen]; cblklen := ft_in_buffer[cblklen + 1]; if cblklen = 0 then Break; end; $15: begin FreadData(cblklen + 4); // FLCNT ( flash content ) //form1._msg(buftohexstr(@Ft_in_buffer[0],cblklen+4)); flcnt := ''; flcnt := buftohexstr(@Ft_in_buffer[0], 19); form1._msg('FLCNT : ' + flcnt); cblk := ft_in_buffer[cblklen + 2]; cblklen := ft_in_buffer[cblklen + 3]; if cblklen = 0 then Break; end; $35: begin FreadData(cblklen + 2); //form1._msg(buftohexstr(@Ft_in_buffer[0],cblklen+2)); algo := Hex2Chr(BufToHexStr(@Ft_in_buffer[1], cblklen - 2)); form1._msg('ReqAlgo : CMT , ' + algo); cblk := ft_in_buffer[cblklen]; cblklen := ft_in_buffer[cblklen + 1]; end; $11: begin FreadData(cblklen + 2); // FLCNT ( flash content ) flcnt := ''; //form1._msg(buftohexstr(@Ft_in_buffer[0],cblklen+2)); flcnt := buftohexstr(@Ft_in_buffer[0], 19); form1._msg('FLCNT : ' + flcnt); cblk := ft_in_buffer[cblklen]; cblklen := ft_in_buffer[cblklen + 1]; if cblklen = 0 then Break; end else begin Form1._msg('ERR : UNK : ' + Byte2Str(cblk)); FreadData(cblklen + 2); //Form1._msg(BufToHexStr(@ft_in_buffer[0],cblklen+4)); end; end; end; {case flblk of $01 : begin Application.ProcessMessages; if not FreadData($0D) then Exit; //CMTMCID Form1._msg('FLMCID : '+buftohexstr(@cmd_buf[3],8)); Application.ProcessMessages; end; $03 : begin Application.ProcessMessages; if not FreadData($0D) then Exit; Freadflashic(0); // check flash ic case flven of $89820089 : FbusSloader:=StartDir+'Flash\UFS\RAP3Gv3_algo_v1331.fg'; else Application.ProcessMessages; end; Application.ProcessMessages; if not FreadData($15) then Exit; Form1._msg('FLCNT : '+buftohexstr(@cmd_buf[3],16)); Application.ProcessMessages; if not FreadData($0D) then Exit; //CMTMCID Form1._msg('FLMCID : '+buftohexstr(@cmd_buf[3],8)); Application.ProcessMessages; end; $04 : begin Application.ProcessMessages; if not FreadData($0D) then Exit; Freadflashic(0); // check flash ic Application.ProcessMessages; if not FreadData($0D) then Exit; Freadflashic(0); // check flash ic Application.ProcessMessages; if not FreadData($15) then Exit; Form1._msg('FLCNT : '+buftohexstr(@cmd_buf[3],16)); Application.ProcessMessages; if not FreadData($0D) then Exit; //CMTMCID Form1._msg('FLMCID : '+buftohexstr(@cmd_buf[3],8)); Application.ProcessMessages; end; $05 : begin Application.ProcessMessages; if not FreadData($0D) then Exit; Freadflashic(0); // check flash ic if not FreadData($0D) then Exit; Freadflashic(0); if not FreadData($11) then Exit; algo:=Hex2Chr(BufTohexStr(@cmd_buf[1],$10)); Form1._msg('ALG : '+algo); Application.ProcessMessages; if not FreadData($15) then Exit; Form1._msg('FLCNT : '+buftohexstr(@cmd_buf[0],16)); Application.ProcessMessages; if not FreadData($0D) then Exit; //CMTMCID Form1._msg('FLMCID : '+buftohexstr(@cmd_buf[3],8)); Application.ProcessMessages; end; else begin form1._msg('Sorry, cant'+#39+'t proceed ['+inttostr(flblk)+']'); exit; end; end; } end; $01: begin result := 8; Form1._msg(''); Application.processMessages; if not replyverify then form1._msg('ready [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; if not replyverify then form1._msg('ready [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; Form1.statusbar.Panels[0].Text := 'UFS : APE 2ND boot...'; Form1._msg('APE : Sending 2nd loader...'); Application.ProcessMessages; RAWblock := TMemoryStream.Create; rawblock.LoadFromFile(loader); form1._msg('Use : ' + extractfilename(Loader)); rawblock.Seek(0, soFromBeginning); RAWloader := TMemoryStream.Create; BB5_ExtractAPERAWLoader(RAWBlock, RAWLoader, b); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); rawloader.ReadBuffer(tmp[0], rawloader.Size); result := 8; if rawloader.size = 0 then Exit; Application.ProcessMessages; FT_Out_Buffer[0] := $65; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $08; FT_Out_Buffer[3] := $09; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := rawloader.Size div $100; FT_Out_Buffer[6] := rawloader.Size mod $100; FT_Out_Buffer[7] := $00; FT_Out_Buffer[8] := $00; FT_Out_Buffer[9] := $5B; FT_Out_Buffer[10] := $01; FT_Out_Buffer[11] := $24; FT_Out_Buffer[12] := $04; FT_Out_Buffer[13] := $00; FT_Out_Buffer[14] := $00; FT_Out_Buffer[15] := rawloader.Size div $100; FT_Out_Buffer[16] := rawloader.Size mod $100; FT_Out_Buffer[17] := framecrc(@ft_out_buffer[10], 7); Application.ProcessMessages; for i := 0 to rawloader.size + 17 do FT_Out_Buffer[i + 18] := TMP[i]; ufs_cmd(700, @FT_out_buffer, (rawloader.Size + 18), @cmd_buf, 7); result := 6; if cmd_buf[0] <> $00 then exit; if cmd_buf[1] <> $10 then form1._msg('Payload message : ' + byte2str(ft_in_buffer[1])); if cmd_buf[5] < $F0 then form1._msg('Payload message : ' + byte2str(ft_in_buffer[5])); if cmd_buf[6] <> $72 then exit; Application.ProcessMessages; Form1._msg('APE Loader sent, Boot Ok'); if not replyverify then form1._msg('ready [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); result := 6; // Boot sent, need collect flash info now and check some stuff Application.processMessages; Form1.statusbar.Panels[0].Text := 'UFS : Running APE...'; Application.processMessages; if not replyverify then form1._msg('ready [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; ufs_cmd(70, @apePredta, 6, @cmd_buf, 3); Application.ProcessMessages; if not replyverify2 then form1._msg('repl2 [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); ufs_cmd(70, @apePredta, 6, @cmd_buf, 3); Application.ProcessMessages; if not replyverify then form1._msg('ready [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; ufs_cmd(70, @aperun, 16, @cmd_buf, 9); Application.ProcessMessages; flblk := cmd_buf[1]; case flblk of $02: begin lb := GetReadLen; ReadDatarequest(lb); Freadflashic(); // check flash ic Application.ProcessMessages; lb := GetReadLen; ReadDatarequest(lb); form1._msg('FLCNT : ' + buftohexstr(@cmd_buf[2], lb - 4)); Application.ProcessMessages; lb := GetReadLen; ReadDatarequest(lb); end; $03: begin lb := GetReadLen; ReadDatarequest(lb); Freadflashic(); // check flash ic Application.ProcessMessages; lb := GetReadLen; ReadDatarequest(lb); algo := ''; for i := 1 to lb - 3 do if cmd_buf[i] <> $00 then algo := algo + chr(cmd_buf[i]); Form1._msg('ALGO : ' + algo); Application.ProcessMessages; lb := GetReadLen; ReadDatarequest(lb); form1._msg('FLMCID : ' + buftohexstr(@cmd_buf[2], lb - 4)); Application.ProcessMessages; lb := GetReadLen; ReadDatarequest(lb); end else begin form1._msg('Sorry, cant' + #39 + 't proceed [' + inttostr(flblk) + ']'); exit; end; end; Application.ProcessMessages; result := 5; if not replyverify then form1._msg('ready [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; if not replyverify then form1._msg('ready [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; end; end; result := 0; end; function SendAlgorihtm(Asic: integer; algo: string): integer; var rawloader, rawblock: TMemoryStream; b: Boolean; chk: word; tmp: array of Byte; ostlen, packets, i2, i: integer; currpacketsize: integer; begin result := 9; case Asic of $00: begin Form1.statusbar.Panels[0].Text := 'UFS : Send CMT algo, wait...'; ufsfl_cmd(300, @Checkalgo[0], Length(checkalgo), @cmd_buf, 14); if ft_in_buffer[0] <> $C3 then exit; if ft_in_buffer[12] < $F0 then form1._msg('reply ' + byte2str(ft_in_buffer[12])); if ft_in_buffer[13] <> $72 then exit; Application.ProcessMessages; result := 8; if not replyverify then form1._msg('prepare for algo send [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; if not replyverify then form1._msg('prepare for algo send [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; form1._msg('Sending ALGO....'); result := 7; RAWblock := TMemoryStream.Create; rawblock.LoadFromFile(algo); form1._msg('Use : ' + extractfilename(algo)); rawblock.Seek(0, soFromBeginning); RAWloader := TMemoryStream.Create; BB5_ExtractRAWLoader(RAWBlock, RAWLoader, b); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); Rawloader.Readbuffer(tmp[0], rawloader.size); FT_Out_Buffer[0] := $69; FT_Out_Buffer[1] := $02; FT_Out_Buffer[2] := $0A; FT_Out_Buffer[3] := rawloader.Size div $10000; FT_Out_Buffer[4] := rawloader.Size div $100; FT_Out_Buffer[5] := (rawloader.Size mod $100) + 4; FT_Out_Buffer[6] := $00; FT_Out_Buffer[7] := $00; FT_Out_Buffer[8] := $00; FT_Out_Buffer[9] := rawloader.Size div $10000; FT_Out_Buffer[10] := rawloader.Size div $100; FT_Out_Buffer[11] := rawloader.Size mod $100; if rawloader.size > $FFF4 then begin for i := 0 to $FFF4 - 1 do FT_Out_Buffer[i + 12] := TMP[i]; ufsfl_cmd(800, @FT_out_buffer, $10000, @cmd_buf, 0); ostlen := rawloader.size - $FFF4; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); Rawloader.Readbuffer(tmp[0], $FFF4); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; Rawloader.Readbuffer(tmp[0], currpacketsize); for i := 0 to currpacketsize - 1 do FT_Out_Buffer[i] := TMP[i]; if currpacketsize < $10000 then ufs_cmd(800, @FT_out_buffer, currpacketsize, @cmd_buf, 7) else ufsfl_cmd(800, @FT_out_buffer, currpacketsize, @cmd_buf, 0); Application.ProcessMessages; //Form1._msg('Packet : '+inttostr(packets)+' Len : '+inttostr(currpacketsize)); end; end; if cmd_buf[0] <> $00 then exit; if cmd_buf[1] <> $00 then exit; if cmd_buf[4] <> $00 then exit; if cmd_buf[5] < $F0 then form1._msg('Payload msg : ' + byte2str((FT_In_Buffer[5]))); if cmd_buf[6] <> $72 then exit; result := 6; Application.ProcessMessages; Form1._msg('CMT Algo sent'); ufsfl_cmd(150, @asicch[0], length(asicch), @cmd_buf, 11); if cmd_buf[0] <> $C5 then Exit; case cmd_buf[1] of 0: form1._msg('PAPUBkeys blank (erased or HW failure)'); 1: begin Application.ProcessMessages; if not FreadData($17) then Exit; form1._msg('CMT PAPUB : ' + buftohexstr(@cmd_buf[2], $15)); end else Form1._msg('Can' + #39 + 't proceed [' + byte2str(ft_in_buffer[1]) + ']'); end; ufsfl_cmd(100, @asicunk[0], length(asicunk), @cmd_buf, 7); Application.ProcessMessages; if not replyverify then form1._msg('reply [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); checkvpp; result := 0; Form1.statusbar.Panels[0].Text := ''; end; $01: begin Form1.statusbar.Panels[0].Text := 'UFS : Send APE algo, wait...'; Application.ProcessMessages; form1._msg('Sending ALGO....'); RAWblock := TMemoryStream.Create; rawblock.LoadFromFile(algo); form1._msg('Use : ' + extractfilename(algo)); rawblock.Seek(0, soFromBeginning); RAWloader := TMemoryStream.Create; BB5_ExtractAPERAWLoader(RAWBlock, RAWLoader, b); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); Rawloader.Readbuffer(tmp[0], rawloader.size); Application.ProcessMessages; FT_Out_Buffer[0] := $65; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $08; FT_Out_Buffer[3] := $09; FT_Out_Buffer[4] := rawloader.Size div $10000; FT_Out_Buffer[5] := rawloader.Size div $100; FT_Out_Buffer[6] := rawloader.Size mod $100; FT_Out_Buffer[7] := $00; FT_Out_Buffer[8] := $00; FT_Out_Buffer[9] := $5B; FT_Out_Buffer[10] := $01; FT_Out_Buffer[11] := $25; FT_Out_Buffer[12] := $04; FT_Out_Buffer[13] := $00; FT_Out_Buffer[14] := rawloader.Size div $10000; FT_Out_Buffer[15] := rawloader.Size div $100; FT_Out_Buffer[16] := rawloader.Size mod $100; FT_Out_Buffer[17] := framecrc(@ft_out_buffer[10], 7); Application.ProcessMessages; if rawloader.size > $FFEE then begin for i := 0 to $FFEE - 1 do FT_Out_Buffer[i + 18] := TMP[i]; ufsfl_cmd(1200, @FT_out_buffer, $10000, @cmd_buf, 0); ostlen := rawloader.size - $FFEE; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); Rawloader.Readbuffer(tmp[0], $FFEE); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if packets - 1 = 0 then CurrPacketSize := (ostLen mod $10000); if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; Rawloader.Readbuffer(tmp[0], currpacketsize); for i := 0 to currpacketsize - 1 do FT_Out_Buffer[i] := TMP[i]; if currpacketsize < $10000 then ufs_cmd(1200, @FT_out_buffer, currpacketsize, @cmd_buf, 7) else ufsfl_cmd(1200, @FT_out_buffer, currpacketsize, @cmd_buf, 0); Application.ProcessMessages; end; end else begin for i := 0 to Rawloader.size - 1 do FT_Out_Buffer[i + 18] := TMP[i]; ufsfl_cmd(1200, @FT_out_buffer, Rawloader.size + 18, @cmd_buf, 7); end; if cmd_buf[0] <> $00 then exit; //if ft_in_buffer[1]<>$00 then form1._msg('Fur msg : '+byte2str((FT_In_Buffer[1]))); if cmd_buf[4] <> $00 then form1._msg('Fur msg : ' + byte2str((FT_In_Buffer[4]))); if cmd_buf[5] < $F0 then form1._msg('Payload msg : ' + byte2str((FT_In_Buffer[5]))); if cmd_buf[6] <> $72 then exit; Application.ProcessMessages; Form1._msg('APE Algo sent'); ufsfl_cmd(500, @asicunk[0], length(asicunk), @cmd_buf, 11); if not replyverify then form1._msg('[' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; CheckVpp; getapepapub; Form1.statusbar.Panels[0].Text := 'UFS : Boot Done'; end; end; result := 0; end; function getapepapub(): Boolean; begin Application.ProcessMessages; ufsfl_cmd(500, @apepapub[0], Length(apepapub), @cmd_buf, 11); if cmd_buf[0] <> $C5 then begin form1._msg('RX : ' + buftohexstr(@ft_in_buffer[0], 10)); Exit; end; case FT_In_Buffer[1] of 0: form1._msg('PAPUBkeys blank (erased or HW failure)'); 1: begin Application.ProcessMessages; if not FreadData($17) then Exit; form1._msg('APE PAPUB : ' + buftohexstr(@cmd_buf[2], $15)); end else Form1._msg('Can' + #39 + 't proceed [' + byte2str(cmd_buf[1]) + ']'); end; PreCertreq; if not replyverify then form1._msg('[' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; result := True; end; function ReadCert(ASIC: Byte; CERT: string): string; var i, rwal: Integer; chkb: Byte; b: Boolean; data, sd: string; cbyte: byte; blkcnt: Integer; certsize: integer; begin data := ''; certsize := 0; if not phoneready(5) then begin form1._msg('Error while prepare, can' + #39 + 't read certificate... :('); result := ''; Exit; end; for i := 12 to 25 do readCertReq[i] := $00; Form1.statusbar.Panels[0].Text := 'UFS : Read ' + CERT + ' cert'; Form1.pb1.Progress := 0; case ASIC of $00: // CMT begin Form1._msg('CMT : Read ' + CERT + ' certificate...'); for i := 0 to Length(CERT) do readCertReq[i + 12] := Ord(CERT[i + 1]); readCertReq[24] := $00; readCertReq[25] := frameCrc(@readCertReq[9], 16); ufs_cmd(1000, @readcertreq[0], Length(readCertReq), @cmd_buf, 9); //Form1._msg('PrecertReq : '+buftohexstr(@Ft_in_buffer[0],9)); if (cmd_buf[7] < $B0) and (cmd_buf[8] <> $72) then begin result := ''; Exit; end; blkcnt := cmd_buf[1]; Form1.pb1.MaxValue := blkcnt; //Form1._msg('BlkCNT : '+inttostr(blkcnt)); Application.ProcessMessages; if blkcnt = 0 then result := ''; repeat readDataReq[5] := $02; ufs_cmd(1000, @readdatareq[0], Length(readdataReq), @cmd_buf, 4); chkb := cmd_buf[1]; cbyte := cmd_buf[0]; //Form1._msg(Byte2Str(chkb)+byte2str(cbyte)); if (chkb > 0) and (cbyte = $2C) then begin Application.ProcessMessages; readDataReq[5] := chkb; certsize := certsize + chkb; ufs_cmd(1000, @readdatareq[0], Length(readdataReq), @cmd_buf, chkb); data := data + BufToHexStr(@cmd_buf[0], chkb); b := True; end else b := False; Application.ProcessMessages; Form1.pb1.Progress := Form1.pb1.Progress + 1; Application.ProcessMessages; until b = false; form1._msg('Cert size : ' + inttostr(certsize) + ' byte(s)'); replyend; if Length(data) > 80 then result := data else result := ''; end; $01: // APE begin Form1._msg('APE : Read ' + CERT + ' certificate...'); for i := 0 to Length(CERT) do readCertReq[i + 12] := Ord(CERT[i + 1]); readCertReq[24] := $01; readCertReq[25] := frameCrc(@readCertReq[9], 16); ufs_cmd(1000, @readcertreq[0], Length(readCertReq), @cmd_buf, 9); //Form1._msg('PrecertReq : '+buftohexstr(@Ft_in_buffer[0],9)); if (cmd_buf[7] < $B0) and (cmd_buf[8] <> $72) then begin result := ''; Exit; end; blkcnt := cmd_buf[1]; Form1.pb1.MaxValue := blkcnt; //Form1._msg('BlkCNT : '+inttostr(blkcnt)); Application.ProcessMessages; if blkcnt = 0 then result := ''; repeat readDataReq[5] := $02; ufs_cmd(1000, @readdatareq[0], Length(readdataReq), @cmd_buf, 4); chkb := cmd_buf[1]; cbyte := cmd_buf[0]; //Form1._msg(Byte2Str(chkb)+byte2str(cbyte)); if (chkb > 0) and (cbyte = $2C) then begin Application.ProcessMessages; readDataReq[5] := chkb; certsize := certsize + chkb; ufs_cmd(1000, @readdatareq[0], Length(readdataReq), @cmd_buf, chkb); data := data + BufToHexStr(@cmd_buf[0], chkb); b := True; end else b := False; Application.ProcessMessages; Form1.pb1.Progress := Form1.pb1.Progress + 1; Application.ProcessMessages; until b = false; form1._msg('Cert size : ' + inttostr(certsize) + ' byte(s)'); replyend; if Length(data) > 80 then result := data else result := ''; end; end; Form1.statusbar.Panels[0].Text := ''; Form1.pb1.MaxValue := 100; Form1.pb1.progress := 0; end; function replyend(): Boolean; begin result := false; Verifyreply[2] := $14; if replyverify then result := True; Verifyreply[2] := $40; end; function PreCertreq(): Boolean; begin result := false; ufsfl_cmd(120, @Precert[0], Length(Precert), @cmd_buf, 14); //form1._msg('PreDta : '+buftohexstr(@FT_in_buffer[0],14)); //C3 01 20 01 04 D9 00 00 00 00 00 00 B1 72 if cmd_buf[0] = $C3 then begin if (cmd_buf[3] = $01) and (cmd_buf[4] = $04) then form1._msg('Transmission mode : Dual (Ddr, TX2) ') else form1._msg('Transmission mode : 16 bit ( Single) '); result := true; end else result := false; Application.ProcessMessages; end; function incheck(bytes: Integer): Boolean; var i, i2: integer; begin result := False; i2 := 0; for i := 1 to bytes do if FT_In_Buffer[i - 1] = $00 then i2 := i2 + 1; if i2 = bytes then Result := True; end; function phoneready(retry: Integer): Boolean; var i: integer; begin if not replyverify then begin i := 0; repeat Application.ProcessMessages; Inc(i); Sleep(20); Application.ProcessMessages; until (replyverify) or (i = retry); if i <> retry then result := True else Result := false; end else result := true; end; function FlashPrepare(flimage: string): Boolean; begin // prepare data here Storecert and trans-proto check if not phoneready(20) then begin result := false; form1._msg('Error while prepare , transrequest error'); Exit; end; // CertStore request ufsfl_cmd(500, @storecert[0], Length(storecert), @cmd_buf, 7); if (ft_in_Buffer[0] <> $00) or (ft_in_Buffer[1] <> $00) then begin result := false; form1._msg('Error while prepare : CertStore error'); form1._msg('ERR : ' + buftohexstr(@ft_in_buffer[0], 7)); Exit; end; if not phoneready(20) then begin result := false; form1._msg('Error while prepare : transrequest error'); form1._msg('ERR : ' + buftohexstr(@ft_in_buffer[0], 3)); Exit; end; if not UFSPartitioning(flimage) then begin Form1._msg('Error on Flash Prepare : Partitioning error!'); exit; end; if not PreCertreq then exit; if not ConFigureAsic($00) then form1._msg('CMT CFG not done'); if apeexist then if not ConFigureAsic($01) then form1._msg('APE CFG not done'); result := True; end; function ConFigureAsic(ASIC: Byte): Boolean; begin case ASIC of $00: //CMT FUR client begin ufs_cmd(500, @setfmcuconfig[0], Length(setfmcuconfig), @cmd_buf, 7); if not AsicComandFur then begin result := false; form1._msg('Error FUR CMT client, MCU cfg not done'); form1._msg('ERR : ' + buftohexstr(@ft_in_buffer[0], 7)); Exit; end else begin //form1._msg('CMT select Ok'); furCMT := $00; end; end; $01: //APE FUR client begin ufs_cmd(500, @setfmcuconfigAPE[0], Length(setfmcuconfig), @cmd_buf, 7); if not AsicComandFur then begin result := false; form1._msg('Error FUR APE client, MCU cfg not done'); form1._msg('ERR : ' + buftohexstr(@ft_in_buffer[0], 7)); Exit; end else begin //form1._msg('APE select Ok'); furCMT := $01; end; end; end; result := True; end; function UFSPartitioning(core: string): Boolean; var fs: TFileStream; buf: array[0..$FFFF] of byte; n, j, buflen: Integer; HdrLen: Integer; HdrPos: LongInt; CurrSeem: Byte; CurrSeemLen, CurSeemcount: Integer; ms: TMemoryStream; loaderlen: DWORD; erase: Boolean; framelen: DWORD; streamlen: TMemoryStream; begin Result := false; partition := false; erase := False; //Form1._msg('Erase : Processing '+ExtractFileName(core)); Application.processmessages; Form1.statusbar.Panels[1].text := ''; Application.ProcessMessages; fs := TFileStream.Create(core, fmOpenRead); fs.Seek(0, sofromBeginning); fs.Read(buf[0], 1); if buf[0] <> $B2 then begin fs.free; raise E.Create('Partition : Bad image file'); Exit; end; Application.ProcessMessages; starttime; Application.ProcessMessages; 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; $F3: begin // Form1._msg('SEEM: F3'); fs.ReadBuffer(buf[0], 2); CurrSeemLen := (buf[0] * $100) + buf[1]; // Form1._msg('Dead mode support : True'); 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); // ????????????? //form1._msg('SEEM: FA:LEN: '+ inttostr(loaderlen)); fs.seek(loaderlen - 9, sofromcurrent); // ?????? ??????? - ????? ???? ?????? ?????? ?8 Application.ProcessMessages; streamlen.Free; end; $EE: begin form1._msg('Partitioning....'); partition := True; partitionstream := TmemoryStream.Create; fs.ReadBuffer(buf[0], 2); CurrSeemLen := (buf[0] * $100) + buf[1]; partitionstream.copyFrom(fs, CurrSeemlen); partitionstream.Seek(0, soFromBeginning); Application.ProcessMessages; if partition = True then begin framelen := CurrSeemLen + 10; FT_Out_Buffer[0] := $69; FT_Out_Buffer[1] := $0A; FT_Out_Buffer[2] := $0A; FT_Out_Buffer[3] := $00; Word((@FT_Out_Buffer[4])^) := currseemlen + 2; WordSwap(@FT_out_buffer[4]); FT_Out_Buffer[6] := $00; FT_Out_Buffer[7] := $00; FT_Out_Buffer[8] := $64; partitionstream.ReadBuffer(FT_out_buffer[9], CurrSeemLen); FT_out_buffer[framelen - 1] := frameCrc(@FT_out_buffer[9], CurrSeemLen); //Form1._msg('txbuf : '+BufToHexStr(@FT_out_buffer[0],framelen)); ufs_cmd(8000, @FT_out_buffer[0], framelen, @cmd_buf, 7); //Form1._msg('Partition result : '+buftohexstr(@cmd_buf[0],7)); if FT_In_Buffer[0] = $00 then form1._msg('Partitioning Ok...') else begin Form1._msg('Partitioning error : ' + buftohexstr(@cmd_buf[0], 7)); form1._msg('Partitioning failed! :('); result := false; end; Application.ProcessMessages; partitionstream.free; fs.free; result := true; Exit; end; end else begin // Form1._msg('SEEM : '+byte2str(currseem)); fs.ReadBuffer(buf[0], 1); CurrSeemLen := buf[0]; fs.readbuffer(buf[0], CurrSeemLen); application.ProcessMessages; end; end; end; if not partition then result := true; fs.Free; except on E: Exception do begin fs.Free; Form1._msg('PartitionFile: Error: ' + E.Message); end; end; Application.ProcessMessages; end; function SendRawID(Asic: integer; Loader: string): integer; var rawloader, rawblock: TMemoryStream; b: Boolean; chk: word; tmp: array of Byte; i: integer; flblk: integer; lb: Byte; filename: string; mmc: System.Text; id: string; idstart: string; idint: integer; begin result := 9; algo := ''; Form1.statusbar.Panels[0].Text := 'UFS : CMT 2ND boot...'; Form1._msg('CMT : Sending 2nd loader...'); Application.ProcessMessages; RAWloader := TMemoryStream.Create; rawloader.LoadFromFile(loader); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); if rawloader.size = 0 then exit; result := 8; // RAwloader prepare error if FLbyte > $F0 then begin ufsfl_cmd(500, @prerawcheck[0], 3, @cmd_buf, 1); //Form1._msg('Set Data ['+Byte2Str(ft_in_buffer[0])+']'); //form1._msg('Set Data ['+Byte2Str(replyverify3)+']'); end; rawloader.ReadBuffer(tmp[0], rawloader.Size); RawLen[6] := rawloader.Size mod $100; RawLen[5] := rawloader.Size div $100; result := 7; // PrebootCheck error - raw len no accepted ufsfl_cmd(500, @Rawlen[0], 7, @cmd_buf, 2); //Form1._msg('Set data ['+byte2str(FT_In_Buffer[0])+']'); devbyte := FT_In_Buffer[0]; if FT_In_Buffer[1] <> $72 then Exit; Application.ProcessMessages; FT_Out_Buffer[0] := $69; FT_Out_Buffer[1] := $02; FT_Out_Buffer[2] := $0A; FT_Out_Buffer[3] := $00; FT_Out_Buffer[5] := rawloader.Size mod $100; FT_Out_Buffer[4] := rawloader.Size div $100; FT_Out_Buffer[6] := $00; FT_Out_Buffer[7] := $00; Application.ProcessMessages; for i := 0 to rawloader.size + 7 do FT_Out_Buffer[i + 8] := TMP[i]; ufs_cmd(3000, @FT_out_buffer, (rawloader.Size + 8), @cmd_buf, 7); result := 6; // rawloader not accepted by phone if ft_in_buffer[0] <> $00 then exit; //if ft_in_buffer[5]<>$F1 then exit; if ft_in_buffer[6] <> $72 then exit; Application.ProcessMessages; Form1._msg('CMT Loader sent, Boot Ok'); Form1.statusbar.Panels[0].Text := 'UFS : 2ND Boot Ok, wait...'; rawloader.Free; { RAWloader:=TMemoryStream.Create; rawloader.LoadFromFile(bof); rawloader.Seek(0,soFromBeginning); SetLength(tmp, rawloader.Size); rawloader.ReadBuffer(tmp[0], rawloader.Size); } Application.ProcessMessages; FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $20; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $02; FT_Out_Buffer[4] := $E4; case bof of 1: for i := 0 to 740 + 4 do FT_Out_Buffer[i + 5] := BOF1rapv2[i]; 2: for i := 0 to 740 + 4 do FT_Out_Buffer[i + 5] := BOF2rapv3[i]; 3: for i := 0 to 740 + 4 do FT_Out_Buffer[i + 5] := BOF3Rapido[i]; end; ufsfl_cmd(5000, @FT_out_buffer, (740 + 5), @cmd_buf, 2); //rawloader.Free; if ft_in_buffer[1] <> $72 then exit; Application.ProcessMessages; ufsfl_cmd(5000, @flow, Length(flow), @cmd_buf, 2); Form1.statusbar.Panels[0].Text := 'UFS : Exploit Ok, wait...'; Application.ProcessMessages; //Form1._msg('OWF : '+byte2str(ft_in_buffer[0])); if ft_in_buffer[1] <> $72 then exit; RAWloader := TMemoryStream.Create; rawloader.LoadFromFile(FbusSloader); rawloader.Seek(0, soFromBeginning); SetLength(tmp, rawloader.Size); rawloader.ReadBuffer(tmp[0], rawloader.Size); Application.ProcessMessages; FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $20; FT_Out_Buffer[2] := $00; FT_Out_Buffer[4] := rawloader.Size mod $100; FT_Out_Buffer[3] := rawloader.Size div $100; for i := 0 to rawloader.size + 4 do FT_Out_Buffer[i + 5] := TMP[i]; dwordswap(@FT_out_buffer[5]); ufsfl_cmd(5000, @FT_out_buffer, (rawloader.Size + 5), @cmd_buf, 2); rawloader.free; if ft_in_buffer[1] <> $72 then exit; Application.ProcessMessages; ufsfl_cmd(5000, @flow, Length(flow), @cmd_buf, 2); Application.ProcessMessages; // Form1._msg('OWF2 : '+byte2str(ft_in_buffer[0])); if ft_in_buffer[1] <> $72 then exit; Application.ProcessMessages; ufsfl_cmd(5000, @overready, 9, @cmd_buf, 11); // Form1._msg('OWF : '+byte2str(ft_in_buffer[9])); //if ft_in_buffer[8]<>$72 then exit; Application.ProcessMessages; ufsfl_cmd(5000, @readdieid, 6, @cmd_buf, $40); Form1.statusbar.Panels[0].Text := 'UFS : Fetching data, wait...'; id := buftohexstr(@ft_in_buffer[0], $40); UkeyData.PID := BufToHexStr(@Rapinfo.PUBLIC_ID[0], Length(Rapinfo.PUBLIC_ID)); UkeyData.Hash := buftohexstr(@Rapinfo.ROOT_KEY_HASH[0], Length(RAPInfo.ROOT_KEY_HASH)); idint := Pos(UkeyData.PID, id); idstart := Copy(id, idint + 40, 40); UkeyData.key := idstart; //form1._msg(id); // Show Data in log // form1._msg('PID : '+UkeyData.PID); // form1._msg('HSH : '+UkeyData.Hash); // form1._msg('KEY : '+UkeyData.key); //id); result := 0; end; function UFSWriteFileUNI(core: string): Boolean; const maxlen: dWORD = $4FFFF; var buf: array[0..$4FFFF] of byte; HdrLen, CurrBlockLen: Cardinal; EntryPoint, DataLen, TargetOffset, CRCTmp: LongInt; i, n, Blocks, Packets, icl, CurrPacketSize, TokenHdrLen: Integer; good: Integer; CertName, AsicType: string; PAPUB_Already, APE_PAPUB: boolean; fs: TFileStream; ms: TMemoryStream; writen, framelen: Dword; cmtcount, cmtdin, TokenSubType, unk: integer; nopbyte: byte; nopword: word; ttxbuf: array[0..$4FFFF] of byte; ape, cmt: Boolean; apebyte: Byte; bulkread: integer; ostlen: DWORD; i2: integer; inslen: integer; fspos: 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; unk := 0; Form1.pb1.ForeColor := clGreen; Form1.pb1.progress := 0; Application.ProcessMessages; PAPUB_Already := False; APE_PAPUB := false; try fs.Read(ttxbuf[0], 1); if ttxbuf[0] <> $B2 then begin fs.free; raise E.Create('Write : Bad image file'); end; Application.ProcessMessages; starttime; Application.ProcessMessages; fs.ReadBuffer(ttxbuf[0], 4); //Длина Flash-header'a HdrLen := HexToInt(IntToHex(ttxbuf[0], 2) + IntToHex(ttxbuf[1], 2) + IntToHex(ttxbuf[2], 2) + IntToHex(ttxbuf[3], 2)); fs.Seek(HdrLen, sofromcurrent); //К началу первого Flash-токена {ms:=TMemoryStream.Create;} form1.pb1.maxvalue := (fs.size - hdrlen); form1.statusbar.Panels.Items[0].Text := 'Writing...'; while fs.Position < fs.Size do begin if stop = True then begin dostop('WRITE'); result := False; fs.Free; Application.ProcessMessages; UFSeblock; SwitchBoxMode('FBUS'); Exit; end; Application.ProcessMessages; fs.ReadBuffer(ttxbuf[8], 1); case ttxbuf[8] of $54: //Flash-token begin //form1._msg('CurrPos : ' +inttostr(fs.position)); Application.ProcessMessages; //54 0117 0E 000300 4D9C 01 00000400 00000000 E8 fs.ReadBuffer(ttxbuf[$09], $3); //Чтение значения подтипа токена и длины его заголовка TokenHdrLen := ttxbuf[$0B]; //Длина заголовка токена TokenSubType := TokenHdrLen; fs.Seek(fs.position - 4, sofrombeginning); //смещение на начало токена inc(TokenHdrLen, 5); //Увеличим длину до общей длины токена с его CRC fs.ReadBuffer(ttxbuf[8], TokenHdrLen); //Чтение значений токена с его CRC apebyte := ttxbuf[12]; fs.Seek(fs.position - TokenHdrLen, sofrombeginning); //смещение на начало токена Application.ProcessMessages; //Длина текущего блока между токенами CurrBlockLen := HexToInt(IntToHex(ttxbuf[TokenHdrLen - 1], 2) + IntToHex(ttxbuf[TokenHdrLen], 2) + IntToHex(ttxbuf[TokenHdrLen + 1], 2) + IntToHex(ttxbuf[TokenHdrLen + 2], 2)); //Form1._msg('CurrLen : '+inttostr(CurrBlockLen)); //fs.ReadBuffer(ttxbuf[0],(tokenhdrlen+currblocklen)); Application.ProcessMessages; case apebyte of $00: begin if furCMT <> $00 then begin if ConFigureAsic($00) then furcmt := $00 else begin form1._msg('CMT select error, impossible continue flashing. Check HW/Cable'); result := false; fs.free; Exit; end; Application.ProcessMessages; end; end; $01: begin if furCMT <> $01 then begin if ConFigureAsic($01) then furcmt := $01 else begin form1._msg('APE select error, impossible continue flashing. Check HW/Cable'); result := false; fs.free; Exit; end; end; Application.ProcessMessages; end; end; application.ProcessMessages; //FillMemory(@cmd_buf[0],9,$00); FT_Out_Buffer[0] := $65; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $0C; //0C FT_Out_Buffer[3] := TokenSubtype + $05; FT_Out_Buffer[4] := CurrBlockLen div $10000; FT_Out_Buffer[5] := CurrBlockLen div $100; FT_Out_Buffer[6] := CurrBlockLen mod $100; FT_Out_Buffer[7] := $07; //07 FT_Out_Buffer[8] := $00; Application.ProcessMessages; currblocklen := currblocklen + tokenhdrlen; //fspos:=fs.Position; if CurrBlockLen > $FFF7 then begin fs.ReadBuffer(FT_Out_Buffer[9], $FFF7); ufsfl_cmd(8000, @FT_out_buffer, $10000, @cmd_buf, 0); ostlen := CurrBlockLen - $FFF7; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets >= 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; Application.ProcessMessages; //form1._msg(inttostr(ostlen mod $10000)); fs.ReadBuffer(FT_Out_Buffer[0], currpacketsize); if currpacketsize < $10000 then ufsfl_cmd(8000, @FT_out_buffer, currpacketsize, @cmd_buf, 14) else ufsfl_cmd(8000, @FT_out_buffer, currpacketsize, @cmd_buf, 0); Application.ProcessMessages; end; end else begin fs.ReadBuffer(FT_Out_Buffer[9], currblocklen); ufsfl_cmd(8000, @FT_out_buffer, CurrBlockLen + 9, @cmd_buf, 14); end; //Form1._msg(BufToHexStr(@cmd_buf[0],7)); Application.ProcessMessages; if not checkc7 then begin form1._msg('Error write block at : ' + IntToStr(blocks)); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 12)); result := False; fs.Free; Exit; end; Application.ProcessMessages; inc(blocks); case apebyte of $00: form1.statusbar.Panels[1].Text := 'CMT : ' + inttostr(Blocks); $01: form1.statusbar.Panels[1].Text := 'APE : ' + inttostr(Blocks); end; Application.ProcessMessages; end; //End of Case $54 $5D: //Phoenix-segment begin //5D 0127 2D 25B977A055BE9B5DEC0C38A2A279C695 8594B99841444100000000000000000000030077E7 00000400 000A0800 BB // Len RootKey Hash Len Flash CRC //5D 0128 43 25B977A055BE9B5DEC0C38A2A279C695 8594B99850415055424B4559530000000003 00A70900 00060000 11F000397DCE210733C335E84BAD369EC893FCA06D1BC3 0100 A5 // Len RootKey Hash Len Flash CRC Application.ProcessMessages; fs.ReadBuffer(ttxbuf[$09], $3); //Чтение значения подтипа токена и длины его заголовка TokenHdrLen := ttxbuf[$0B]; //Длина заголовка токена TokenSubType := TokenHdrLen; fs.Seek(fs.position - 4, sofrombeginning); //смещение на начало токена inc(TokenHdrLen, 5); //Увеличим длину до общей длины токена с его CRC fs.ReadBuffer(ttxbuf[8], TokenHdrLen); //Чтение значений токена с его CRC apebyte := ttxbuf[44]; Application.ProcessMessages; case TokenSubType of $2D: //Длина текущего блока между токенами CurrBlockLen := HexToInt(IntToHex(ttxbuf[TokenHdrLen - 1], 2) + IntToHex(ttxbuf[TokenHdrLen], 2) + IntToHex(ttxbuf[TokenHdrLen + 1], 2) + IntToHex(ttxbuf[TokenHdrLen + 2], 2)); $43: //Длина текущего блока между токенами CurrBlockLen := HexToInt(IntToHex(ttxbuf[TokenHdrLen - $17], 2) + IntToHex(ttxbuf[TokenHdrLen - $16], 2) + IntToHex(ttxbuf[TokenHdrLen - $15], 2) + IntToHex(ttxbuf[TokenHdrLen - $14], 2)); else begin fs.Free; E.Create('Write : Bad image file'); end; end; //End of Case //Сравнение RootKey Hash телефона и RootKey Hash блока сертов good := 0; case apebyte of $00: begin for i := $0 to $0F do if RAPInfo.Root_Key_Hash[i] = ttxbuf[i + $0C] then inc(good); end; $01: begin for i := $0 to $0F do if RAPInfo.APErootkey[i] = ttxbuf[i + $0C] then inc(good); end; end; if good < $10 then begin //RootKey Hash не совпал, пропускаем fs.Seek(CurrBlockLen, soFromCurrent); //Пропускаем токен и его данные continue; end else begin fs.Seek(fs.position - Tokenhdrlen, soFromBeginning); //RootKey Hash серта совпал, копируем case TokenSubType of $2D: begin fs.ReadBuffer(ttxBuf[0], TokenHdrLen); //Копирование данных Application.ProcessMessages; CertName := ''; for i := 24 to 39 do if ttxbuf[i] = $00 then break else CertName := CertName + Chr(ttxbuf[i]); case apebyte of $00: Form1._msg('CMT: Writing Hash CERT [' + CertName + ']'); $01: Form1._msg('APE: Writing Hash CERT [' + CertName + ']'); end; Application.ProcessMessages; //Form1._msg('txbuf : '+BufToHexStr(@txbuf[0],framelen)); Application.ProcessMessages; case apebyte of $00: begin if furCMT <> $00 then begin if ConFigureAsic($00) then furcmt := $00 else begin form1._msg('APE select error, impossible continue flashing. Check HW/Cable'); result := false; fs.free; Exit; end; end; end; $01: begin if furCMT <> $01 then begin if ConFigureAsic($01) then furcmt := $01 else begin form1._msg('APE select error, impossible continue flashing. Check HW/Cable'); result := false; fs.free; Exit; end; end; Application.ProcessMessages; end; end; application.ProcessMessages; fs.Seek(fs.position - Tokenhdrlen, soFromBeginning); application.ProcessMessages; //FillMemory(@cmd_buf[0],9,$00); FT_Out_Buffer[0] := $65; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $0C; FT_Out_Buffer[3] := $32; FT_Out_Buffer[4] := CurrBlockLen div $10000; FT_Out_Buffer[5] := CurrBlockLen div $100; FT_Out_Buffer[6] := CurrBlockLen mod $100; FT_Out_Buffer[7] := $07; FT_Out_Buffer[8] := $00; Application.ProcessMessages; currblocklen := currblocklen + tokenhdrlen; if CurrBlockLen > $FFF7 then begin fs.ReadBuffer(FT_Out_Buffer[9], $FFF7); ufsfl_cmd(6000, @FT_out_buffer, $10000, @cmd_buf, 0); ostlen := CurrBlockLen - $FFF7; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets >= 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; // form1._msg(inttostr(ostlen mod $10000)); fs.ReadBuffer(FT_Out_Buffer[0], currpacketsize); if currpacketsize < $10000 then ufsfl_cmd(6000, @FT_out_buffer, currpacketsize, @cmd_buf, 14) else ufsfl_cmd(6000, @FT_out_buffer, currpacketsize, @cmd_buf, 0); Application.ProcessMessages; end; end else begin fs.ReadBuffer(FT_Out_Buffer[9], currblocklen); ufsfl_cmd(6000, @FT_out_buffer, CurrBlockLen + 9, @cmd_buf, 14); end; //Form1._msg(BufToHexStr(@cmd_buf[0],7)); Application.ProcessMessages; if not checkc7 then begin form1._msg('Error write CERT block at : ' + IntToStr(blocks)); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 12)); result := False; fs.Free; Exit; end; Application.ProcessMessages; inc(blocks); Application.ProcessMessages; case apebyte of $00: form1.statusbar.Panels[1].Text := 'CMT : ' + inttostr(Blocks); $01: form1.statusbar.Panels[1].Text := 'APE : ' + inttostr(Blocks); end; end; $43: begin fs.ReadBuffer(ttxBuf[0], CurrBlockLen + TokenHdrLen); //Копирование данных Application.ProcessMessages; //Form1._msg('txbuf : '+BufToHexStr(@txbuf[0],framelen)); Application.ProcessMessages; case apebyte of $00: begin if furCMT <> $00 then begin if ConFigureAsic($00) then furcmt := $00 else begin form1._msg('APE select error, impossible continue flashing. Check HW/Cable'); result := false; fs.free; Exit; end; end; end; $01: begin if furCMT <> $01 then begin if ConFigureAsic($01) then furcmt := $01 else begin form1._msg('APE select error, impossible continue flashing. Check HW/Cable'); result := false; fs.free; Exit; end; end; Application.ProcessMessages; end; end; case apebyte of $00: begin if PAPUB_Already then Application.ProcessMessages else begin Form1._msg('CMT: Writing Hash CERT [PAPUBKEYS]'); // FillMemory(@cmd_buf[0],9,$00); FT_Out_Buffer[0] := $65; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $0C; FT_Out_Buffer[3] := $48; FT_Out_Buffer[4] := CurrBlockLen div $10000; FT_Out_Buffer[5] := CurrBlockLen div $100; FT_Out_Buffer[6] := CurrBlockLen mod $100; FT_Out_Buffer[7] := $07; FT_Out_Buffer[8] := $00; currblocklen := currblocklen + tokenhdrlen; if CurrBlockLen > $FFF7 then begin for i := 0 to $FFF7 - 1 do FT_Out_Buffer[i + 9] := ttxbuf[i]; ufsfl_cmd(6000, @FT_out_buffer, $10000, @cmd_buf, 0); ostlen := CurrBlockLen - $FFF7; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; for i := 0 to currpacketsize - 1 do FT_Out_Buffer[i] := ttxbuf[i]; if currpacketsize < $10000 then ufsfl_cmd(6000, @FT_out_buffer, currpacketsize, @cmd_buf, 14) else ufsfl_cmd(6000, @FT_out_buffer, currpacketsize, @cmd_buf, 0); Application.ProcessMessages; end; end else begin for i := 0 to CurrBlockLen do FT_Out_Buffer[i + 9] := ttxbuf[i]; ufsfl_cmd(6000, @FT_out_buffer, CurrBlockLen + 9, @cmd_buf, 14); end; //Form1._msg(BufToHexStr(@cmd_buf[0],7)); Application.ProcessMessages; if not checkc7 then begin form1._msg('Error write CERT block at : ' + IntToStr(blocks)); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 12)); result := False; fs.Free; Exit; end; PAPUB_Already := True; end; end; $01: begin if APE_PAPUB then Application.ProcessMessages else begin Form1._msg('APE: Writing Hash CERT [PAPUBKEYS]'); // FillMemory(@cmd_buf[0],9,$00); FT_Out_Buffer[0] := $65; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $0C; FT_Out_Buffer[3] := $48; FT_Out_Buffer[4] := CurrBlockLen div $10000; FT_Out_Buffer[5] := CurrBlockLen div $100; FT_Out_Buffer[6] := CurrBlockLen mod $100; FT_Out_Buffer[7] := $07; FT_Out_Buffer[8] := $00; currblocklen := currblocklen + tokenhdrlen; if CurrBlockLen > $FFF7 then begin for i := 0 to $FFF7 - 1 do FT_Out_Buffer[i + 9] := ttxbuf[i]; ufsfl_cmd(6000, @FT_out_buffer, $10000, @cmd_buf, 0); ostlen := CurrBlockLen - $FFF7; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; for i := 0 to currpacketsize - 1 do FT_Out_Buffer[i] := ttxbuf[i]; if currpacketsize < $10000 then ufsfl_cmd(6000, @FT_out_buffer, currpacketsize, @cmd_buf, 14) else ufsfl_cmd(6000, @FT_out_buffer, currpacketsize, @cmd_buf, 0); Application.ProcessMessages; end; end else begin for i := 0 to CurrBlockLen do FT_Out_Buffer[i + 9] := ttxbuf[i]; ufsfl_cmd(6000, @FT_out_buffer, CurrBlockLen + 9, @cmd_buf, 14); end; //Form1._msg(BufToHexStr(@cmd_buf[0],7)); Application.ProcessMessages; if not checkc7 then begin form1._msg('Error write CERT block at : ' + IntToStr(blocks)); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 12)); result := False; fs.Free; Exit; end; APE_PAPUB := True; end; end; end; Application.ProcessMessages; end; end; end; Application.ProcessMessages; inc(blocks); Application.ProcessMessages; case apebyte of $01: form1.statusbar.Panels[1].Text := 'APE : ' + inttostr(Blocks); $00: form1.statusbar.Panels[1].Text := 'CMT : ' + inttostr(Blocks); end; end //End of Case $5D else begin //Unknow Tokens or Bad File fs.free; E.Create('Write : Bad image file'); end; end; //End of Case form1.pb1.progress := fs.Position; Application.ProcessMessages; end; //End of While fs.free; Form1._msg('Total writen ' + inttostr(blocks) + ' blocks'); Application.ProcessMessages; endtimecount; Form1._msg('TIME : Write time : ' + showtime(tmsres) + ' '); form1.statusbar.Panels[1].Text := ''; form1.statusbar.Panels[0].Text := ''; result := True; //form1._msg('Errors : '+inttostr(GetLastError)); form1.pb1.maxvalue := 100; form1.pb1.progress := 0; Application.ProcessMessages; except on E: Exception do begin Form1._msg('Error: ' + E.Message); Form1.pb1.Progress := 0; //USBClosePort; exit; end; end; Form1.pb1.Progress := 0; end; function UFSeraseUni(core: string): Boolean; var fs: TFileStream; buf: array[0..$FFFF] of byte; n, j: Integer; HdrLen: Integer; HdrPos: LongInt; CurrSeem: Byte; CurrSeemLen, CurrEraseLen, CurSeemcount: Integer; EraseStart, EraseStop: array[0..$FF] of LongInt; EraseCnt: Integer; FlashCFG, Byte1, Byte2, Byte3: Byte; streamlen, ms: TMemoryStream; loaderlen: DWORD; partitionlen, pcfg: Byte; fullerase: Integer; partLen: integer; erase: Boolean; b: Byte; di, i, i2: integer; crc, partbyte: byte; regioncnt: byte; cmt: Boolean; ercrt: string; begin Result := false; partition := false; partLen := 0; erase := False; furcmt := $03; Form1.pb1.Progress := 0; Form1.pbsm1.Progress := 0; Form1._msg('Erase : Processing ' + ExtractFileName(core)); Application.processmessages; Form1.statusbar.Panels[1].text := ''; Form1.pb1.ForeColor := clYellow; Form1.pb1.progress := 0; Application.ProcessMessages; fs := TFileStream.Create(core, fmOpenRead); fs.Seek(0, sofromBeginning); fs.Read(b, 1); if b <> $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); Application.ProcessMessages; starttime; regioncnt := 0; Application.ProcessMessages; 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; 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 erase := True; cmt := True; 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 //form1._msg(IntToStr(fs.Position)); if stop = True then begin dostop('ERASE'); result := False; fs.Free; Application.ProcessMessages; Exit; end; 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); if furCMT <> Byte1 then begin ConFigureAsic(Byte1); furCMT := Byte1; end; FillMemory(@Ft_out_buffer[0], $10000, $00); FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $0A; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $00; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $50; FT_Out_Buffer[6] := $00; di := 7; EraseCnt := CurrEraseLen div 8; Form1._msg('Found ' + IntToStr(EraseCnt) + ' areas to erase, erase group'); Form1._msg('Asic : ' + GetAsic(Byte1) + ' , Sub : ' + GetSub(Byte2)); //fs.ReadBuffer(buf[0], CurrEraseLen); for j := 0 to EraseCnt - 1 do begin FT_Out_Buffer[di] := FlashCFG; Inc(di); FT_Out_Buffer[di] := $0B; Inc(di); FT_Out_Buffer[di] := byte1; Inc(di); FT_Out_Buffer[di] := byte2; Inc(di); FT_Out_Buffer[di] := byte3; Inc(di); fs.ReadBuffer(FT_Out_Buffer[di], 8); Application.ProcessMessages; Form1._msg(GetAsic(Byte1) + ' , ' + GetSub(Byte2) + ' , Area : 0x' + buftohexstr(@FT_out_buffer[di], 4) + ' - 0x' + buftohexstr(@FT_out_buffer[di + 4], 4)); Application.ProcessMessages; Inc(di, 8); Application.ProcessMessages; end; Form1.statusbar.Panels[0].Text := ''; Form1.statusbar.Panels[1].Text := ''; Application.ProcessMessages; Word((@FT_Out_Buffer[3])^) := di - 4; wordswap(@FT_Out_Buffer[3]); FT_Out_Buffer[6] := erasecnt; crc := frameCrc(@Ft_out_buffer[6], di - 6); FT_Out_Buffer[di] := crc; inc(di); application.processMessages; form1.pb1.progress := 0; form1.pb1.maxvalue := 5000; // Form1._msg('Erase : '+buftohexstr(@FT_Out_Buffer[0],di)); if Byte2 = $00 then Form1._msg('Using TimeOut : 5 min ( 300 sec )'); Form1._msg('Erasing, wait.....'); application.processMessages; ufsfl_cmd(1000, @FT_out_buffer, di, @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @rd1byte, length(rd1byte), @cmd_buf, 3); // form1._msg(byte2str(FT_In_Buffer[0])); repeat FillMemory(@cmd_buf[0], 2, $00); ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if (cmd_buf[0] > $F0) or (cmd_buf[0] < $B0) then break; application.processMessages; form1.pb1.progress := form1.pb1.progress + 1; application.processMessages; if stop = True then begin dostop('ERASE'); result := False; fs.Free; Application.ProcessMessages; UFSeblock; SwitchBoxMode('FBUS'); Exit; end; sleep(20); until cmd_buf[0] > $F0; if cmd_buf[0] < $B0 then begin form1._Msg('Erase error! Conection lost :('); result := False; fs.Free; Exit; end; end; ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); if not AsicComandFur then begin form1._msg('Erase ' + GetAsic(furCMT) + ' group error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; form1._msg(GetAsic(furCMT) + ' : Group erase Ok'); Application.ProcessMessages; end else begin ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); // form1._msg(buftohexstr(@ft_In_Buffer[0],9)); if not AsicComandFur then begin form1._msg('Erase ' + GetAsic(furCMT) + ' group error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; form1._msg(GetAsic(furCMT) + ' : Group erase Ok'); Application.ProcessMessages; end; //for i:=0 to di do form1._msg(byte2str(framecrc(@Ft_out_buffer[i],(di-i)))); //Form1._msg('Erase : '+buftohexstr(@FT_Out_Buffer[0],di)); end; $19: begin fs.ReadBuffer(partitionlen, 1); fs.ReadBuffer(byte1, 1); if furCMT <> Byte1 then begin ConFigureAsic(Byte1); furcmt := Byte1; end; Application.ProcessMessages; fs.Seek(fs.position - 2, soFromBeginning); Application.ProcessMessages; FillMemory(@Ft_out_buffer[0], $10000, $00); FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $0A; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $00; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $50; FT_Out_Buffer[6] := $00; di := 7; //regioncnt:=regioncnt+1; FT_Out_Buffer[di] := $19; Inc(di); fs.ReadBuffer(partitionlen, 1); FT_Out_Buffer[di] := partitionlen; Inc(di); fs.ReadBuffer(FT_Out_Buffer[di], partitionlen); byte1 := Ft_out_buffer[di]; byte2 := Ft_out_buffer[di + 1]; partbyte := Ft_out_buffer[di + 14]; Inc(di, partitionlen); form1._msg('Erase Partition 0x' + byte2str(partbyte) + ' , ' + GetAsic(Byte1) + ' , ' + GetSub(Byte2)); Application.ProcessMessages; Word((@FT_Out_Buffer[3])^) := di - 4; wordswap(@FT_Out_Buffer[3]); FT_Out_Buffer[6] := $01; crc := frameCrc(@Ft_out_buffer[6], di - 6); FT_Out_Buffer[di] := crc; inc(di); application.processMessages; form1.pb1.progress := 0; form1.pb1.maxvalue := 1000; //Form1._msg('Erase : '+buftohexstr(@FT_Out_Buffer[0],di)); //Form1._msg('Using TimeOut : 5 min ( 300 sec )'); //Form1._msg('Erasing, wait.....'); application.processMessages; ufsfl_cmd(1000, @FT_out_buffer, di, @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @rd1byte, length(rd1byte), @cmd_buf, 3); //form1._msg(byte2str(FT_In_Buffer[0])); repeat FillMemory(@cmd_buf[0], 2, $00); ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if (cmd_buf[0] > $F0) or (cmd_buf[0] < $B0) then break; application.processMessages; form1.pb1.progress := form1.pb1.progress + 1; application.processMessages; sleep(10); until cmd_buf[0] > $F0; if cmd_buf[0] < $B0 then begin form1._Msg('Erase partition error! Conection lost :('); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; end; ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); if not AsicComandFur then begin form1._msg('Erase ' + GetAsic(furCMT) + ' Partition error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; form1._msg(GetAsic(furCMT) + ' : Partition erase Ok'); Application.ProcessMessages; end else begin ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); if not AsicComandFur then begin form1._msg('Erase ' + GetAsic(furCMT) + ' Partition error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; form1._msg(GetAsic(furCMT) + ': Partition erase Ok'); Application.ProcessMessages; end; // form1._msg('afPos : '+IntToStr(fs.Position)); end; $13: // Erase USRFL begin //regioncnt:=regioncnt+1; //FillMemory(@Ft_out_buffer[0],$10000,$00); ercrt := ''; fs.ReadBuffer(partitionlen, 1); fs.ReadBuffer(Flashcfg, 1); if furCMT <> Flashcfg then ConFigureAsic(FlashCfg); erasecnt := (partitionlen - 1) div $C; for i := 0 to erasecnt - 1 do begin ercrt := ''; Application.ProcessMessages; FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $0A; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $00; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $50; FT_Out_Buffer[6] := $00; di := 7; FT_Out_Buffer[di] := $13; Inc(di); FT_Out_Buffer[di] := $0D; Inc(di); FT_Out_Buffer[di] := FlashCFG; Inc(di); fs.ReadBuffer(FT_Out_Buffer[di], $0C); for i2 := 0 to $0B do if FT_Out_Buffer[di + i2] = $00 then break else ercrt := ercrt + Chr(FT_Out_Buffer[di + i2]); Inc(di, $0C); //inc(di); form1._msg('Erase CRTFL : ' + Ercrt); Application.ProcessMessages; Word((@FT_Out_Buffer[3])^) := di - 4; wordswap(@FT_Out_Buffer[3]); FT_Out_Buffer[6] := $01; crc := frameCrc(@Ft_out_buffer[6], di - 6); FT_Out_Buffer[di] := crc; inc(di); application.processMessages; form1.pb1.progress := 0; form1.pb1.maxvalue := 1000; //Form1._msg('Erase : '+buftohexstr(@FT_Out_Buffer[0],di)); //Form1._msg('Using TimeOut : 5 min ( 300 sec )'); //Form1._msg('Erasing, wait.....'); application.processMessages; ufsfl_cmd(1000, @FT_out_buffer[0], di, @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @rd1byte, length(rd1byte), @cmd_buf, 3); //form1._msg(byte2str(FT_In_Buffer[0])); repeat FillMemory(@cmd_buf[0], 2, $00); ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if (cmd_buf[0] > $F0) or (cmd_buf[0] < $B0) then break; application.processMessages; form1.pb1.progress := form1.pb1.progress + 1; application.processMessages; sleep(10); until cmd_buf[0] > $F0; if cmd_buf[0] < $B0 then begin form1._Msg('Erase CRTFL error! Conection lost :('); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; end; ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); if not AsicComandFur then begin form1._msg(GetAsic(furCMT) + ' : Erase CRTFL error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; form1._msg(GetAsic(furCMT) + ' : CRTFL erase Ok'); Application.ProcessMessages; end else begin ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); // form1._msg(buftohexstr(@ft_In_Buffer[0],9)); if not AsicComandFur then begin form1._msg('Erase ' + GetAsic(furCMT) + ' CRTFL erase error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; fs.Free; Exit; end; form1._msg(GetAsic(furCMT) + ' : CRTFL erase Ok'); Application.ProcessMessages; end; end; end; end; end; form1.pb1.maxvalue := 10000; form1.pb1.progress := 0; Result := True; Application.ProcessMessages; endtimecount; Form1._msg('TIME : Erase time : ' + showtime(tmsres)); Application.ProcessMessages; 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; if erase = False then begin result := True; Form1._msg('Erase : No any region, skip erase'); end; fs.Free; except on E: Exception do begin fs.Free; Form1._msg('EraseFile: Error: ' + E.Message); end; end; Application.ProcessMessages; endtimecount; Form1._msg('TIME : Erase time : ' + showtime(tmsres)); Application.ProcessMessages; fullerase := 0; Form1.pb1.MaxValue := 100; Form1.pb1.Progress := 0; end; function UFSprepareForFlash(image: string): Boolean; begin result := False; {if not UFSPartitioning(image) then begin Form1._msg('Error on Flash Prepare : Partitioning error!'); exit; end; } if stop = True then begin dostop('FLASH'); Application.ProcessMessages; Exit; end; if not FlashPrepare(image) then begin Form1._msg('Error on Flash Prepare!'); exit; end; if stop = True then begin dostop('FLASH'); Application.ProcessMessages; Exit; end; if not UFSeraseUni(image) then begin Form1._msg('Error on Erasing Phone!'); exit; end; UFSfinishsession; if not phoneready(20) then begin Form1._msg('Error on Prepare for Flashing Phone!'); exit; end; if not PreCertreq then exit; if not phoneready(20) then begin Form1._msg('Error on Prepare for Flashing Phone!'); exit; end; if not UFSWriteFileUNI(image) then begin Form1._msg('Error on Flashing Phone!'); exit; end; //form1._msg('All done ;)'); result := True; end; function UFSFormatLow(area: string): Boolean; begin result := False; if not phoneready(20) then begin result := false; form1._msg('Error while prepare , phone not ready'); Exit; end; if not PreCertreq then exit; if not phoneready(20) then begin result := false; form1._msg('Error while prepare , transrequest error'); Exit; end; // CertStore request ufsfl_cmd(500, @storecert[0], Length(storecert), @cmd_buf, 7); if (ft_in_Buffer[0] <> $00) or (ft_in_Buffer[1] <> $00) then begin result := false; form1._msg('Error while prepare : CertStore error'); form1._msg('ERR : ' + buftohexstr(@ft_in_buffer[0], 7)); Exit; end; if not phoneready(20) then begin result := false; form1._msg('Error while prepare : transrequest error'); form1._msg('ERR : ' + buftohexstr(@ft_in_buffer[0], 3)); Exit; end; if not ConFigureAsic($00) then form1._msg('CMT CFG not done'); Application.ProcessMessages; if not UFSeraseS40(area) then begin Form1._msg('Error on Formatting Phone!'); //exit; end; Application.ProcessMessages; if not phoneready(20) then begin Form1._msg('Error on finish format... :( '); //exit; end; Application.ProcessMessages; if UFSfinishsession <> 0 then Exit; UFSfinishsession; result := True; end; function AsicComandFur(): Boolean; begin if cmd_buf[0] <> $C7 then result := False else begin if (cmd_buf[1] = $01) and (cmd_buf[2] = $2D) and (cmd_buf[3] = $01) and (cmd_buf[4] = $00) and (cmd_buf[5] = $D0) then result := true else begin if (cmd_buf[1] = $01) and (cmd_buf[2] = $2D) and (cmd_buf[3] = $01) and (cmd_buf[4] = $01) and (cmd_buf[5] = $CF) then result := true else result := false; end; end; if (cmd_buf[4] = $03) then Form1._msg('Error, 03, DataMissMatch, Check Cable, FlashPack, Firmware'); end; function checkc7(): Boolean; begin result := False; if not AsicComandFur then exit else result := True; end; function UFSfinishsession(): integer; var st, st2: Byte; asic, len: Byte; strasic: string; i: integer; begin result := 5; //if not phoneready(20) then exit; Application.ProcessMessages; ufsfl_cmd(3000, @Flbcloseasic[0], 11, @cmd_buf, 9); if cmd_buf[0] <> $C2 then Exit; repeat Application.ProcessMessages; rdreqdta[5] := $02; ufsfl_cmd(1500, @rdreqdta[0], 6, @cmd_buf, 4); asic := cmd_buf[0]; len := cmd_buf[1]; if len = 0 then Break; rdreqdta[5] := len; ufsfl_cmd(1500, @rdreqdta[0], 6, @cmd_buf, len + 2); //Form1._msg('Asic : '+byte2str(asic)+' data : '+buftohexstr(@cmd_buf[0],len)); if asic = $16 then begin Application.ProcessMessages; strasic := ''; for i := 3 to 12 do if cmd_buf[i] <> $00 then strasic := strasic + chr(cmd_buf[i]) else break; form1._msg('Programming report : Error ' + strasic); Application.ProcessMessages; end; until len = 0; Application.ProcessMessages; if not phoneready(20) then exit; result := 0; furCMT := $03; end; function UFSEBLock(): integer; begin ufsfl_cmd(1200, @EBlock[0], 11, @cmd_buf, 14); //Form1._msg('EngageBootLock : '+buftohexstr(@cmd_buf[0],12)); end; function UFSEBLockAPE(): boolean; begin ufsfl_cmd(1200, @EBlockAPE[0], 14, @cmd_buf, 7); //Form1._msg('EngageBootLock : '+buftohexstr(@cmd_buf[0],12)); if phoneready(50) then result := True; end; function buildUFScert(DataStream: widestring; cert: string; asic: byte): Boolean; var i, framelen: Integer; tmp: array of Byte; chk: word; x, i2, len, flen: Integer; begin result := False; // if cert='HWC' then datastream:=datastream+'FFFFFFFF'; flen := length(datastream) mod 80; if flen <> 0 then begin len := 80 - (length(datastream) mod 80); for i2 := 0 to len - 1 do datastream := datastream + 'F'; // form1._msg('Collect : '+inttostr(len)+'/'+inttostr(flen)); end; // prepare and clear start buffer FillMemory(@Ft_out_buffer[0], 800, $00); FT_Out_Buffer[0] := $65; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $0C; FT_Out_Buffer[3] := $32; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $00; FT_Out_Buffer[6] := $00; FT_Out_Buffer[7] := $00; FT_Out_Buffer[8] := $00; FT_Out_Buffer[9] := $5D; FT_Out_Buffer[10] := $01; FT_Out_Buffer[11] := $27; FT_Out_Buffer[12] := $2D; for i := 13 to 32 do FT_Out_Buffer[i] := $FF; for i := 33 to 44 do FT_Out_Buffer[i] := $00; for i := 0 to Length(CERT) do FT_Out_Buffer[i + 33] := Ord(CERT[i + 1]); FT_Out_Buffer[45] := asic; case Asic of $00: if FLtype = 'NAND' then FT_Out_Buffer[46] := $03 else FT_Out_Buffer[46] := $00; $01: FT_Out_Buffer[46] := $01; end; FT_Out_Buffer[47] := $00; SetLength(tmp, length(DataStream) div 2); x := StrToBufHex(DataStream, @tmp[0]); CHK := FbusGetChk(@tmp[0], x); Word((@FT_Out_Buffer[48])^) := chk; DWord((@FT_Out_Buffer[50])^) := x; DWordSwap(@FT_Out_Buffer[50]); FT_Out_Buffer[54] := $FF; FT_Out_Buffer[55] := $FF; FT_Out_Buffer[56] := $FF; FT_Out_Buffer[57] := $FF; FT_Out_Buffer[58] := framecrc(@FT_Out_Buffer[0], 58); StrToBufHex(DataStream, @FT_Out_Buffer[59]); FT_Out_Buffer[4] := x div $10000; FT_Out_Buffer[5] := x div $100; FT_Out_Buffer[6] := x mod $100; //form1._msg(BufToHexStr(@Ft_out_buffer[0],x+59)); ufsfl_cmd(1500, @FT_out_buffer[0], x + 59, @cmd_buf[0], 7); //form1._msg(BufToHexStr(@cmd_buf[0],7)); if cmd_buf[5] > $F0 then result := True; UFSfinishsession; UFSfinishsession; end; function UFSeraseCRT(CRT: string; Asic: Byte): Boolean; var i, di: integer; crc: byte; begin Application.ProcessMessages; FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $0A; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $00; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $50; FT_Out_Buffer[6] := $00; di := 7; FT_Out_Buffer[di] := $13; Inc(di); FT_Out_Buffer[di] := $0D; Inc(di); case Asic of $00: FT_Out_Buffer[di] := $00; $01: FT_Out_Buffer[di] := $01; end; Inc(di); fillmemory(@FT_Out_Buffer[di], $0C, $00); for i := 0 to Length(CRT) - 1 do FT_Out_Buffer[di + i] := Ord(crt[i + 1]); Inc(di, $0C); form1._msg('Erase CRT FL : ' + crt); Application.ProcessMessages; Word((@FT_Out_Buffer[3])^) := di - 4; wordswap(@FT_Out_Buffer[3]); FT_Out_Buffer[6] := $01; crc := frameCrc(@Ft_out_buffer[6], di - 6); FT_Out_Buffer[di] := crc; inc(di); application.processMessages; form1.pb1.ForeColor := clYellow; form1.pb1.progress := 0; form1.pb1.maxvalue := 1000; application.processMessages; ufsfl_cmd(1000, @FT_out_buffer[0], di, @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @rd1byte, length(rd1byte), @cmd_buf, 3); repeat FillMemory(@cmd_buf[0], 2, $00); ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if (cmd_buf[0] > $F0) or (cmd_buf[0] < $B0) then break; application.processMessages; form1.pb1.progress := form1.pb1.progress + 1; application.processMessages; sleep(10); until cmd_buf[0] > $F0; if cmd_buf[0] < $B0 then begin form1._Msg('Erase CRT FL error! Conection lost :('); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; Exit; end; end; form1._msg('CMT : ' + crt + ' erase Ok'); Application.ProcessMessages; end else begin form1._msg('CMT : ' + crt + ' erase Ok'); Application.ProcessMessages; end; form1.pb1.Progress := 0; form1.pb1.ForeColor := clNavy; form1.pb1.MaxValue := 100; Application.ProcessMessages; UFSfinishsession; UFSfinishsession; end; function UFSeraseS40(area: string): Boolean; var di, erasecnt: Integer; crc: Byte; begin Form1._msg('Erase User Area now, Selected model : ' + form1.cbbLFmdel.text); Application.ProcessMessages; if furCMT <> $00 then begin ConFigureAsic($00); furCMT := $00; end; FillMemory(@Ft_out_buffer[0], $10000, $00); FT_Out_Buffer[0] := $74; FT_Out_Buffer[1] := $0A; FT_Out_Buffer[2] := $00; FT_Out_Buffer[3] := $00; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $50; FT_Out_Buffer[6] := $00; di := 7; FT_Out_Buffer[di] := $12; Inc(di); FT_Out_Buffer[di] := $0B; Inc(di); FT_Out_Buffer[di] := $00; Inc(di); FT_Out_Buffer[di] := $00; Inc(di); FT_Out_Buffer[di] := $00; Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 1, 2)); Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 3, 2)); Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 5, 2)); Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 7, 2)); Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 9, 2)); Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 11, 2)); Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 13, 2)); Inc(di); FT_Out_Buffer[di] := Str2Byte(Copy(area, 15, 2)); Inc(di); Application.ProcessMessages; Form1.statusbar.Panels[0].Text := ''; Form1.statusbar.Panels[1].Text := ''; Application.ProcessMessages; Word((@FT_Out_Buffer[3])^) := di - 4; wordswap(@FT_Out_Buffer[3]); FT_Out_Buffer[6] := $01; crc := frameCrc(@Ft_out_buffer[6], di - 6); FT_Out_Buffer[di] := crc; inc(di); // form1._msg(buftohexstr(@Ft_out_buffer[0],di)); application.processMessages; form1.pb1.progress := 0; form1.pb1.maxvalue := 5000; // Form1._msg('Erase : '+buftohexstr(@FT_Out_Buffer[0],di)); Form1._msg('Using TimeOut : 5 min ( 300 sec )'); Form1._msg('Erasing, wait.....'); application.processMessages; ufsfl_cmd(1000, @FT_out_buffer, di, @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if FT_In_Buffer[0] < $F0 then begin ufsfl_cmd(1000, @rd1byte, length(rd1byte), @cmd_buf, 3); // form1._msg(byte2str(FT_In_Buffer[0])); repeat FillMemory(@cmd_buf[0], 2, $00); ufsfl_cmd(1000, @Verifyreply, length(Verifyreply), @cmd_buf, 2); if (cmd_buf[0] > $F0) or (cmd_buf[0] < $B0) then break; application.processMessages; form1.pb1.progress := form1.pb1.progress + 1; application.processMessages; sleep(20); until cmd_buf[0] > $F0; if cmd_buf[0] < $B0 then begin form1._Msg('Erase error! Conection lost :('); result := False; Exit; end; end; ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); if not AsicComandFur then begin form1._msg('Erase CMT error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; Exit; end; form1._msg('CMT : Format Ok'); Application.ProcessMessages; result := True; end else begin ufsfl_cmd(1000, @rd7byte, length(rd7byte), @cmd_buf, 9); // form1._msg(buftohexstr(@ft_In_Buffer[0],9)); if not AsicComandFur then begin form1._msg('Erase CMT error!'); form1._msg('ERR : ' + buftohexstr(@cmd_buf[0], 7)); result := False; Exit; end; form1._msg('CMT : Format Ok'); Application.ProcessMessages; end; result := True; end; function Boot_infineon({Boot1:TMemoryStream;Boot2:TMemoryStream}): Boolean; var bflag: boolean; tryinit: integer; len: word; bcount: integer; x: Integer; begin result := false; Form1.statusbar.Panels[0].Text := 'UFS : Booting phone...'; form1._msg('Booting phone now....'); bcount := 0; repeat tryinit := 0; if not busreset then begin; form1._msg('UFSx init fail, reconnect box'); exit; end; //reset_usb_device; repeat FT_Out_Buffer[0] := $55; Write_USB_Device_Buffer(1); Read_USB_Device_Buffer(5); Application.ProcessMessages; //if FT_In_Buffer[0]=$C3 then Break; if FT_In_Buffer[0] = $A2 then Break; Application.ProcessMessages; sleep(50); Application.ProcessMessages; //sleep(200); Application.ProcessMessages; Application.ProcessMessages; Inc(tryinit); until tryinit = 35; inc(bcount); if FT_In_Buffer[0] = $A2 then Break; until bcount = 5; if (tryinit = 35) and (bcount = 5) then Exit; Form1._msg('Sync Ok , ' + byte2str(FT_In_Buffer[0])); //form1._msg('D : '+buftohexstr(@FT_In_Buffer[0],4)); tryinit := 0; Application.ProcessMessages; form1._msg('CPU ID : XGOLD , ' + buftohexstr(@FT_In_Buffer[0], 5)); result := True; end; function BusCheckInfineon(): Boolean; var pbl, sbl, dstr: TMemoryStream; i: integer; dsize: word; ostlen, packets, i2: integer; currpacketsize: integer; chkbuf: array of Byte; loadercheck: byte; flashven: string; begin result := false; Reset_USB_Device; Set_USB_Device_TimeOuts($2710, $2710); pbl := TMemoryStream.Create; pbl.Seek(0, soFromBeginning); pbl.LoadFromFile(ExtractFileDir(Application.ExeName) + '\Flash\UFS\SGPBL.bin'); dsize := pbl.Size; Purge_USB_Device_Out; Purge_USB_Device_In; FT_Out_Buffer[0] := $30; Word((@FT_Out_Buffer[1])^) := dsize; Write_USB_Device_Buffer(3); pbl.Seek(0, soFromBeginning); if pbl.size > $10000 then begin ostlen := pbl.size; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); pbl.Seek(0, soFromBeginning); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; pbl.Readbuffer(FT_Out_Buffer[0], currpacketsize); Write_USB_Device_Buffer(currpacketsize); Application.ProcessMessages; //Form1._msg('Packet : '+inttostr(packets)+' Len : '+inttostr(currpacketsize)); end; end else begin pbl.Readbuffer(FT_Out_Buffer[0], pbl.Size); Write_USB_Device_Buffer(pbl.Size); end; Application.ProcessMessages; Sleep(200); Application.ProcessMessages; FT_Out_Buffer[0] := $FE; //loadercheck; Write_USB_Device_Buffer(1); Read_USB_Device_Buffer(2); if ft_in_buffer[0] = $FF then begin form1._msg('Error booting! 2nd [PBL] not accepted!'); pbl.Free; exit; end; form1._msg('Boot Ok , ' + byte2str(ft_in_buffer[0])); pbl.Free; Application.ProcessMessages; Purge_USB_Device_Out; Purge_USB_Device_In; Application.ProcessMessages; Sleep(100); Application.ProcessMessages; FT_Out_Buffer[0] := $B4; FT_Out_Buffer[1] := $01; FT_Out_Buffer[2] := $02; FT_Out_Buffer[3] := $00; Write_USB_Device_Buffer(4); Application.ProcessMessages; FT_Current_Baud := FT_BAUD_921600; Set_USB_Device_BaudRate; Application.ProcessMessages; fillmemory(@ft_in_buffer[0], 200, $00); Application.ProcessMessages; Read_USB_Device_Buffer($1); if ft_in_buffer[0] <> $01 then exit; Application.ProcessMessages; read_USB_Device_Buffer($93); Application.ProcessMessages; Application.ProcessMessages; form1._msg('PBL : ' + hex2chr(buftohexstr(@FT_in_buffer[23], $0F))); Application.ProcessMessages; sbl := TMemoryStream.Create; sbl.Seek(0, soFromBeginning); sbl.loadfromfile(ExtractFileDir(Application.ExeName) + '\Flash\UFS\SGSBL.bin'); sbl.Seek(0, soFromBeginning); dsize := sbl.Size; Word((@FT_Out_Buffer[0])^) := dsize; Write_USB_Device_Buffer(2); sbl.Seek(0, soFromBeginning); if sbl.size > $A000 then begin ostlen := sbl.size; packets := ostlen div $A000; if ostlen mod $A000 > 0 then inc(packets); sbl.Seek(0, soFromBeginning); currpacketsize := $A000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $A000) > 0 then CurrPacketSize := (ostLen mod $A000) else CurrPacketSize := $A000; end; sbl.Readbuffer(FT_Out_Buffer[0], currpacketsize); Write_USB_Device_Buffer(currpacketsize); Application.ProcessMessages; //Form1._msg('Packet : '+inttostr(packets)+' Len : '+inttostr(currpacketsize)); end; end else begin pbl.Readbuffer(FT_Out_Buffer[0], sbl.Size); Write_USB_Device_Buffer(sbl.Size); end; Application.ProcessMessages; Sleep(100); Application.ProcessMessages; FT_Out_Buffer[0] := $8E; //loadercheck; Write_USB_Device_Buffer(1); Read_USB_Device_Buffer(1); if (ft_in_buffer[0] = $FF) or (ft_in_buffer[0] <> $01) then begin form1._msg('Error booting! ALGO [SBL] not accepted!'); Application.ProcessMessages; sbl.Free; exit; end; form1._msg('Algo Ok , ' + byte2str(ft_in_buffer[0])); Application.ProcessMessages; sbl.Free; Read_USB_Device_Buffer(1); if FT_In_Buffer[0] <> $CC then begin form1._msg('Error booting! Algo not start [' + byte2str(Ft_in_buffer[0]) + ']'); Exit; end; Application.ProcessMessages; form1._msg('SBL mode Ok'); if FT_In_Buffer[0] <> $CC then begin form1._msg('Error booting! Info stage failed! [' + byte2str(ft_in_buffer[0]) + ']'); Application.ProcessMessages; exit; end; Read_USB_Device_Buffer($4B); form1._msg('SBL : ' + hex2chr(buftohexstr(@FT_in_buffer[11], $16))); Application.ProcessMessages; BufCopy(@BLCFG[0], @ft_out_buffer[0], Length(BLCFG)); Write_USB_Device_Buffer(82); Application.ProcessMessages; Read_USB_Device_Buffer(12); //form1._msg('BL : '+buftohexstr(@FT_in_buffer[0],12)); BufCopy(@BLCHK[0], @ft_out_buffer[0], Length(BLCHK)); Write_USB_Device_Buffer(14); Application.ProcessMessages; Read_USB_Device_Buffer(14); Application.ProcessMessages; if not CompareTwoHexBuf(@BLCHK[0], @ft_in_buffer[0], 14) then begin form1._msg('Error booting! Check Boot failed! [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; exit; end; form1._msg('EPP CFG [Bering]...'); BufCopy(@EPPCFGB[0], @ft_out_buffer[0], Length(EPPCFGB)); Write_USB_Device_Buffer(182); Application.ProcessMessages; Read_USB_Device_Buffer(12); //form1._msg('BL : '+buftohexstr(@FT_in_buffer[0],12)); Purge_USB_Device_Out; Purge_USB_Device_In; BufCopy(@Get_FlashID[0], @ft_out_buffer[0], Length(Get_FlashID)); Write_USB_Device_Buffer(12); Application.ProcessMessages; Read_USB_Device_Buffer($10A); if FT_In_Buffer[2] <> $84 then begin form1._msg('Error Get Flash Info! Boot failed! [' + buftohexstr(@ft_in_buffer[0], 8) + ']'); Application.ProcessMessages; exit; end; flashven := ''; flashven := buftohexstr(@Ft_in_buffer[9], 8); form1._msg('FLASH ID : ' + flashven); if flashven = '0020000000C08800' then Form1._msg('FLASH ID : ST, M58WR064') else if flashven = '00EC000000542200' then Form1._msg('FLASH ID : Samsung, K8S6415E') else if flashven = '0000000000000000' then Form1._msg('FLASH ID : Damaged/Unknow') else Form1._msg('FLASH ID : UNKNOW [Not In Base]'); BufCopy(@ft_in_buffer[0], @ft_out_buffer[0], $10A); ft_out_buffer[2] := $85; ft_out_buffer[$107] := ft_out_buffer[$107] + 1; Write_USB_Device_Buffer($10A); Application.ProcessMessages; Read_USB_Device_Buffer(12); //form1._msg('BL : '+buftohexstr(@FT_in_buffer[0],12)); if (ft_in_buffer[0] <> $02) and (ft_in_buffer[2] <> $85) and (ft_in_buffer[6] <> $FF) then begin form1._msg('Error booting! Check Boot failed! [' + buftohexstr(@ft_in_buffer[0], 4) + ']'); Application.ProcessMessages; exit; end; Application.ProcessMessages; form1._msg('Boot Done!'); form1._msg(''); result := True; end; function InfineonEnd(): Boolean; begin result := false; BufCopy(@end_esession[0], @ft_out_buffer[0], length(end_esession)); Write_USB_Device_Buffer(14); Application.ProcessMessages; Read_usb_device_buffer(5); result := True; end; function sendCert(infcore: string): Boolean; var dtms: TmemoryStream; i: integer; a, b: byte; c: word; begin // sending certificate result := false; dtms := TmemoryStream.create; dtms.seek(0, sofrombeginning); ParseInfineon(infcore, 8, dtms); if (dtms.Size <= 0) or (dtms.size <> $80C) then begin dtms.Free; Exit; end; form1._msg('Cert block found, sending....'); dtms.seek($C, sofrombeginning); FT_Out_Buffer[0] := $02; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $04; FT_Out_Buffer[3] := $02; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $08; dtms.ReadBuffer(FT_Out_Buffer[6], $800); c := 0; b := (2052 div $100) + 1; a := b xor $FF; for i := 2 to 2051 do begin c := a + FT_Out_Buffer[i]; a := a + FT_Out_Buffer[i]; b := b + (c shr 8); end; //a:=a-$A; //b:=b+$A; FT_Out_Buffer[$806] := a; FT_Out_Buffer[$807] := b; FT_out_buffer[$808] := $03; FT_Out_Buffer[$809] := $00; FillMemory(@ft_in_buffer[0], 20, $00); //Form1._msg(BufToHexStr(@Ft_out_buffer[0],$80A)); write_usb_device_buffer($80A); Application.ProcessMessages; read_usb_device_buffer(12); if (ft_in_buffer[0] = $02) and (ft_in_buffer[6] = $01) then begin form1._msg('Cert sent'); result := True end else begin form1._msg('Cert not accepted [' + buftohexstr(@ft_in_buffer[0], 10) + ']'); result := false; end; end; function InfineonErase(infcore: string; curreg: string): Boolean; var erstrt, erstop, wrl: string; rstart, rstop, rwrlen: DWORD; i, i2: Integer; cs: byte; dcs, chkb: Integer; currer: DWORD; begin //erasing region result := False; //Form1._msg('Erase : '+curreg); //result:=True; //Exit; erstrt := Copy(curreg, 1, 8); erstop := Copy(curreg, 9, 8); wrl := Copy(curreg, 17, 8); currer := 0; Form1.statusbar.Panels.Items[0].text := 'Erasing....'; Application.ProcessMessages; Form1._msg('Erase , Start : 0x' + erstrt + ' , Len : 0x' + wrl); ft_out_buffer[0] := $02; ft_out_buffer[1] := $00; ft_out_buffer[2] := $05; ft_out_buffer[3] := $08; ft_out_buffer[4] := $08; ft_out_buffer[5] := $00; //fillmemory(@ft_out_buffer[5],20,$FF); rstart := 0; rstop := 0; rstart := hextoint(erstrt); DWord((@FT_Out_Buffer[6])^) := rstart; rstop := (rstart + hextoint(wrl)) - 2; DWord((@FT_Out_Buffer[10])^) := rstop; ///++ ) - 8 cs := $00; dcs := 0; chkb := 0; for i := 2 to 13 do begin cs := cs + ft_out_buffer[i]; dcs := dcs + ft_out_buffer[i]; end; cs := cs - $08; chkb := dcs div $100; //form1._msg(inttostr(chkb)); //ft_out_buffer[13]:=$00; ft_out_buffer[14] := cs; ft_out_buffer[15] := $08 + chkb; ft_out_buffer[16] := $03; ft_out_buffer[17] := $00; //Form1._msg('TX : '+BufToHexStr(@FT_out_buffer[0],18)); Form1._msg('Erasing, wait ... '); Write_USB_Device_Buffer(18); Application.ProcessMessages; Read_USB_Device_Buffer(12); if (FT_In_Buffer[0] <> $02) and (FT_In_Buffer[3] <> $08) and (FT_In_Buffer[8] <> $0F) then Form1._msg('ERR : ' + BufToHexStr(@Ft_in_buffer[0], 10)) else Application.ProcessMessages; rwrlen := hextoint(wrl); form1.pb1.MaxValue := rstop - rstart; Form1.pb1.ForeColor := clYellow; repeat BufCopy(@chhkerase[0], @Ft_out_buffer[0], 12); Write_USB_Device_Buffer(12); Application.ProcessMessages; Read_USB_Device_Buffer(16); if FT_In_Buffer[6] = $01 then Break; if FT_In_Buffer[4] <> $06 then Break; Application.ProcessMessages; DWordSwap(@Ft_in_buffer[7]); Application.ProcessMessages; currer := HexToInt(BufToHexStr(@Ft_in_buffer[7], 4)); Form1.pb1.Progress := currer - rstart; Application.ProcessMessages; Form1.statusbar.Panels.Items[1].text := 'CMT : 0x' + BufToHexStr(@Ft_in_buffer[7], 4); Application.ProcessMessages; until FT_In_Buffer[6] = $01; if (FT_In_Buffer[4] = $06) and (FT_In_Buffer[6] = $01) then begin Form1._msg('Erase done'); result := True; end else begin Form1._msg('Erase Error [' + buftohexstr(@FT_in_buffer[0], 14) + ']'); result := false; end; Application.ProcessMessages; Form1.statusbar.Panels.Items[1].text := ''; Form1.statusbar.Panels.Items[0].text := ''; Form1.pb1.ForeColor := clNavy; form1.pb1.MaxValue := 100; form1.pb1.Progress := 0; Application.ProcessMessages; end; function InfineonWrite(infcore: string; mode: Integer; dlen: string): Boolean; var prgstart, prglen: string; rstrt: dword; i: Integer; cs: Byte; Flstream: TMemoryStream; a, b: byte; c: word; bb: Boolean; ostlen, packets, i2, currpacketsize: integer; dcs, chkb: Integer; begin //writing region // set start adress prgstart := Copy(dlen, 1, 8); prglen := Copy(dlen, 17, 8); Form1.statusbar.Panels.Items[0].text := 'Write Data....'; form1._msg('Write , Start : 0x' + prgstart + ' , Len : 0x' + prglen); Application.ProcessMessages; ft_out_buffer[0] := $02; ft_out_buffer[1] := $00; ft_out_buffer[2] := $02; ft_out_buffer[3] := $08; ft_out_buffer[4] := $04; ft_out_buffer[5] := $00; rstrt := hextoint(prgstart); DWord((@FT_Out_Buffer[6])^) := rstrt; cs := $00; dcs := 0; chkb := 0; for i := 2 to 9 do begin cs := cs + ft_out_buffer[i]; dcs := dcs + ft_out_buffer[i]; end; cs := cs - $08; chkb := dcs div $100; ft_out_buffer[10] := cs; ft_out_buffer[11] := $08 + chkb; ft_out_buffer[12] := $03; ft_out_buffer[13] := $00; //Form1._msg('TX : '+BufToHexStr(@FT_out_buffer[0],14)); Write_USB_Device_Buffer(14); Application.ProcessMessages; Read_USB_Device_Buffer(12); if (FT_In_Buffer[0] <> $02) and (FT_In_Buffer[3] <> $08) and (FT_In_Buffer[8] <> $0C) then Form1._msg('ERR : ' + BufToHexStr(@Ft_in_buffer[0], 10)) else Form1._msg('Flashing , wait ...'); Flstream := TMemoryStream.Create; ParseInfineon(infcore, mode, flstream); if (Flstream.Size < $29) and (Flstream = nil) then begin form1._msg('No write data, skip'); Flstream.Free; result := true; Exit; end; Flstream.Seek(0, soFromBeginning); //Flstream.savetofile('C:\data_write.bin'); Application.ProcessMessages; if (Flstream.Size - $28) <> HexToInt(prglen) then form1._msg('Check cert <=> flash failed! Trying continue...'); Application.ProcessMessages; Flstream.Seek(40, soFromBeginning); //(Flstream.Size-$28) bb := True; ostlen := (Flstream.Size - $28); packets := ostlen div $800; if ostlen mod $800 > 0 then inc(packets); currpacketsize := $800; Form1.pb1.MaxValue := packets; Form1.pb1.ForeColor := clGreen; Form1.pb1.Progress := 0; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets >= 1) then begin if (ostlen mod $800) > 0 then CurrPacketSize := (ostLen mod $800) else CurrPacketSize := $800; end; Application.ProcessMessages; Form1.statusbar.Panels.Items[1].text := 'CMT : ' + inttostr(i2) + '/' + inttostr(packets - 1); Application.ProcessMessages; //form1._msg(inttostr(ostlen mod $800)); FT_Out_Buffer[0] := $02; FT_Out_Buffer[1] := $00; FT_Out_Buffer[2] := $04; FT_Out_Buffer[3] := $08; FT_Out_Buffer[4] := $00; FT_Out_Buffer[5] := $00; word((@Ft_out_buffer[4])^) := currpacketsize; Flstream.ReadBuffer(FT_Out_Buffer[6], currpacketsize); Application.ProcessMessages; // inpacket crc c := 0; b := (currpacketsize div $100) + 7; a := b xor $FF; for i := 2 to (currpacketsize + 5) do begin c := a + FT_Out_Buffer[i]; a := a + FT_Out_Buffer[i]; b := b + (c shr 8); end; /// //form1._msg(byte2str(a)+byte2str(b)); Application.ProcessMessages; FT_Out_Buffer[currpacketsize + 6] := a; FT_Out_Buffer[currpacketsize + 7] := b; FT_Out_Buffer[currpacketsize + 8] := $03; FT_Out_Buffer[currpacketsize + 9] := $00; Application.ProcessMessages; //Form1._msg('RX : '+buftohexstr(@ft_out_buffer[0], currpacketsize+$0A)); Write_USB_Device_Buffer(currpacketsize + $A); Application.ProcessMessages; Read_USB_Device_Buffer(12); if (FT_In_Buffer[0] <> $02) or (FT_In_Buffer[2] <> $04) and (FT_In_Buffer[10] <> $03) then begin Form1._msg('Error, ' + inttostr(i2) + ' , data missmatch! [' + buftohexstr(@ft_in_buffer[0], 10) + ']'); Application.ProcessMessages; bb := False; Break; end; Application.ProcessMessages; //form1._msg(buftohexstr(@ft_in_buffer[0],12)); Form1.pb1.Progress := Form1.pb1.Progress + 1; Application.ProcessMessages; end; if bb = true then begin Form1._msg('Region flash done'); result := true; end else begin Form1._msg('Region flash error'); result := False; end; Application.ProcessMessages; Form1.statusbar.Panels.Items[1].text := ''; Form1.statusbar.Panels.Items[0].text := ''; Form1.pb1.ForeColor := clNavy; form1.pb1.MaxValue := 100; form1.pb1.Progress := 0; Application.ProcessMessages; end; function getchecksum(infcore: string): Boolean; begin // check CS file CS data end; function infgetblockcnt(infcore: string; Erlist: Tstringlist): Integer; var dstrm: Tmemorystream; i: integer; begin // get count block, fill list of regions dstrm := TMemoryStream.Create; ParseInfineon(infcore, 8, dstrm); if (dstrm.Size < 40) or (dstrm = nil) then begin dstrm.Free; result := 0; Form1._msg('Error on file prepare, probably damaged!'); Exit; end; result := GetEraseBlk(dstrm, Erlist); end; function checkready(): Boolean; begin result := False; BufCopy(@chhkerase[0], @Ft_out_buffer[0], 12); Write_USB_Device_Buffer(12); Application.ProcessMessages; Read_USB_Device_Buffer(16); if FT_In_Buffer[6] = $01 then result := true; //Form1._msg(BufToHexStr(@ft_in_buffer[0],16)); //if FT_In_Buffer[4]<>$06 then exit; end; function getchksuminf(): Boolean; begin result := False; BufCopy(@getscss[0], @ft_out_buffer[0], 12); Write_USB_Device_Buffer(12); Application.ProcessMessages; Read_USB_Device_Buffer(14); if FT_In_Buffer[0] = $02 then result := true; Form1._msg('Check : ' + BufToHexStr(@ft_in_buffer[8], 2)); //if FT_In_Buffer[6]<>$01 then result:=false; end; function FlashInfineonFile(FlasHfile: string): Boolean; var i, cnt: integer; imgs: string; EraseList: TStringList; begin result := False; i := 0; cnt := 0; //form1._msg(''); Application.ProcessMessages; Form1._msg('File : ' + extractfilename(flashfile)); Application.ProcessMessages; imgs := getFwinfo(flashfile); if imgs = '' then Exit; form1._msg('Image : ' + imgs); //Exit; if not sendCert(FlasHfile) then Exit; EraseList := TStringList.Create; cnt := infgetblockcnt(FlasHfile, EraseList); form1._msg('Found ' + inttostr(cnt) + ' region(s)'); for i := 0 to cnt - 1 do begin form1._msg('Processing Region ' + inttostr(i + 1) + '/' + inttostr(cnt)); if not InfineonErase(Flashfile, EraseList[i]) then Exit; if not InfineonWrite(Flashfile, i + 1, EraseList[i]) then Exit; Application.ProcessMessages; Sleep(50); Application.ProcessMessages; end; Application.ProcessMessages; Sleep(150); Application.ProcessMessages; if not checkready then Form1._msg('Check error!'); Application.ProcessMessages; Sleep(150); Application.ProcessMessages; if not getchksuminf then Form1._msg('Error on Verify'); Application.ProcessMessages; Sleep(50); Application.ProcessMessages; result := true; end; function halfboot(): Boolean; var pbl, sbl, dstr: TMemoryStream; i: integer; dsize: word; ostlen, packets, i2: integer; currpacketsize: integer; chkbuf: array of Byte; loadercheck: byte; check: Word; begin result := false; check := 0; Reset_USB_Device; Set_USB_Device_TimeOuts($2710, $2710); pbl := TMemoryStream.Create; pbl.Seek(0, soFromBeginning); pbl.LoadFromFile(ExtractFileDir(Application.ExeName) + '\Flash\UFS\SGPBL.bin'); dsize := pbl.Size; Purge_USB_Device_Out; Purge_USB_Device_In; FT_Out_Buffer[0] := $30; Word((@FT_Out_Buffer[1])^) := dsize; Write_USB_Device_Buffer(3); pbl.Seek(0, soFromBeginning); if pbl.size > $10000 then begin ostlen := pbl.size; packets := ostlen div $10000; if ostlen mod $10000 > 0 then inc(packets); pbl.Seek(0, soFromBeginning); currpacketsize := $10000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $10000) > 0 then CurrPacketSize := (ostLen mod $10000) else CurrPacketSize := $10000; end; pbl.Readbuffer(FT_Out_Buffer[0], currpacketsize); Write_USB_Device_Buffer(currpacketsize); Application.ProcessMessages; //Form1._msg('Packet : '+inttostr(packets)+' Len : '+inttostr(currpacketsize)); end; end else begin pbl.Readbuffer(FT_Out_Buffer[0], pbl.Size); Write_USB_Device_Buffer(pbl.Size); end; Application.ProcessMessages; Sleep(200); Application.ProcessMessages; FT_Out_Buffer[0] := $FE; //loadercheck; Write_USB_Device_Buffer(1); Read_USB_Device_Buffer(1); if ft_in_buffer[0] <> $01 then begin form1._msg('Error booting! 2nd [PBL] not accepted!'); pbl.Free; exit; end; form1._msg('Boot Ok , ' + byte2str(ft_in_buffer[0])); Read_USB_Device_Buffer(1); pbl.Free; Application.ProcessMessages; Purge_USB_Device_Out; Purge_USB_Device_In; Application.ProcessMessages; Sleep(100); Application.ProcessMessages; FT_Out_Buffer[0] := $B4; FT_Out_Buffer[1] := $01; FT_Out_Buffer[2] := $02; FT_Out_Buffer[3] := $00; Write_USB_Device_Buffer(4); Application.ProcessMessages; FT_Current_Baud := FT_BAUD_921600; Set_USB_Device_BaudRate; Application.ProcessMessages; fillmemory(@ft_in_buffer[0], 200, $00); Application.ProcessMessages; Read_USB_Device_Buffer($1); if ft_in_buffer[0] <> $01 then exit; psi := ''; Application.ProcessMessages; read_USB_Device_Buffer($93); Application.ProcessMessages; // form1._msg('PSI Data : '+buftohexstr(@FT_in_buffer[0],$93)); psi := '01' + buftohexstr(@FT_in_buffer[0], $93); Application.ProcessMessages; form1._msg('PBL : ' + hex2chr(buftohexstr(@FT_in_buffer[23], $0F))); Application.ProcessMessages; sbl := TMemoryStream.Create; sbl.Seek(0, soFromBeginning); sbl.loadfromfile(ExtractFileDir(Application.ExeName) + '\Flash\UFS\SGSBL.bin'); sbl.Seek(0, soFromBeginning); dsize := sbl.Size; Word((@FT_Out_Buffer[0])^) := dsize; Write_USB_Device_Buffer(2); sbl.Seek(0, soFromBeginning); if sbl.size > $A000 then begin ostlen := sbl.size; packets := ostlen div $A000; if ostlen mod $A000 > 0 then inc(packets); sbl.Seek(0, soFromBeginning); currpacketsize := $A000; Application.ProcessMessages; for i2 := 0 to packets - 1 do begin Application.ProcessMessages; if (i2 = Packets - 1) and (Packets > 1) then begin if (ostlen mod $A000) > 0 then CurrPacketSize := (ostLen mod $A000) else CurrPacketSize := $A000; end; sbl.Readbuffer(FT_Out_Buffer[0], currpacketsize); Write_USB_Device_Buffer(currpacketsize); Application.ProcessMessages; //Form1._msg('Packet : '+inttostr(packets)+' Len : '+inttostr(currpacketsize)); end; end else begin pbl.Readbuffer(FT_Out_Buffer[0], sbl.Size); Write_USB_Device_Buffer(sbl.Size); end; Application.ProcessMessages; Sleep(100); Application.ProcessMessages; FT_Out_Buffer[0] := $8E; //loadercheck; Write_USB_Device_Buffer(1); Read_USB_Device_Buffer(1); if (ft_in_buffer[0] = $FF) or (ft_in_buffer[0] <> $01) then begin form1._msg('Error booting! ALGO [SBL] not accepted!'); Application.ProcessMessages; sbl.Free; exit; end; form1._msg('Algo Ok , ' + byte2str(ft_in_buffer[0])); Application.ProcessMessages; sbl.Free; Read_USB_Device_Buffer($4C); if FT_In_Buffer[0] <> $CC then begin form1._msg('Error booting! Info stage failed! [' + byte2str(ft_in_buffer[0]) + ']'); Application.ProcessMessages; exit; end; form1._msg('SBL mode Ok'); form1._msg('SBL : ' + hex2chr(buftohexstr(@FT_in_buffer[12], $16))); Application.ProcessMessages; bufcopy(@ft_in_buffer[0], @ft_out_buffer[6], $48); ft_out_buffer[0] := $02; ft_out_buffer[1] := $00; Word((@ft_out_buffer[2])^) := $86; Word((@ft_out_buffer[4])^) := $48; check := $86 + $48; ft_out_buffer[$36] := $00; ft_out_buffer[$37] := $00; for i := 6 to 5 + $48 do check := check + FT_Out_Buffer[i]; Word((@ft_out_buffer[$4E])^) := check; Word((@ft_out_buffer[$50])^) := $03; Word((@ft_out_buffer[$51])^) := $00; //Form1._msg(buftohexstr(@ft_out_buffer[0],82)); Write_USB_Device_Buffer(82); Application.ProcessMessages; Read_USB_Device_Buffer(12); //Form1._msg(buftohexstr(@ft_in_buffer[0],12)); result := True; end; procedure dumpregionepp(start, stop: dword; resstr: Tmemorystream); var len: dword; i, i2, j, j2: integer; eblcur: dword; tempstream: Tmemorystream; begin len := 0; len := stop - start; eblcur := 0; eblcur := start; resstr.seek(0, soFromBeginning); form1.pb1.MaxValue := len div $800; for i := 1 to (len div $800) do begin EBLcomandStartRead($80B, eblcur); Write_USB_Device_Buffer(14); Application.ProcessMessages; Read_USB_Device_Buffer(12); //if ft_in_buffer[8]<>$15 then break; Application.ProcessMessages; EBLcomandRead($803, $800); Write_USB_Device_Buffer(12); Application.ProcessMessages; fillmemory(@ft_in_buffer[0], $80A, $00); Application.ProcessMessages; Read_USB_Device_Buffer($80A); resstr.Write(ft_in_buffer[6], $800); form1.pb1.progress := form1.pb1.progress + 1; Application.ProcessMessages; Inc(eblcur, $800); end; form1.pb1.Progress := 0; end; procedure dumpppmcatalog(start, stop: dword; resstr: Tmemorystream); var len: dword; i, i2, j, j2: integer; eblcur: dword; tempstream: Tmemorystream; begin len := 0; len := stop - start; eblcur := 0; eblcur := start; resstr.seek(0, soFromBeginning); form1.pb1.MaxValue := len div $2000; for i := 1 to (len div $2000) do begin EBLcomandStartRead($80B, eblcur); Write_USB_Device_Buffer(14); Application.ProcessMessages; Read_USB_Device_Buffer(12); if ft_in_buffer[8] <> $15 then break; Application.ProcessMessages; EBLcomandRead($803, $800); Write_USB_Device_Buffer(12); Application.ProcessMessages; fillmemory(@ft_in_buffer[0], $80A, $00); Application.ProcessMessages; Read_USB_Device_Buffer($80A); if (FT_In_Buffer[8] = $F8) and (FT_In_Buffer[12] = $50) and (FT_In_Buffer[13] = $4D) then begin resstr.Write(ft_in_buffer[6], $800); inc(eblcur, $800); for j := 1 to 3 do begin EBLcomandStartRead($80B, eblcur); Write_USB_Device_Buffer(14); Application.ProcessMessages; Read_USB_Device_Buffer(12); //if ft_in_buffer[8]<>$15 then break; Application.ProcessMessages; EBLcomandRead($803, $800); Write_USB_Device_Buffer(12); Application.ProcessMessages; fillmemory(@ft_in_buffer[0], $80A, $00); Application.ProcessMessages; Read_USB_Device_Buffer($80A); resstr.Write(ft_in_buffer[6], $800); form1.pb1.progress := form1.pb1.progress + 1; Application.ProcessMessages; inc(eblcur, $800); end; end else Inc(eblcur, $2000); form1.pb1.progress := form1.pb1.progress + 1; Application.ProcessMessages; end; form1.pb1.Progress := 0; end; function busreset(): boolean; var ic, dc: integer; begin result := false; //reset_usb_device; FT_Out_Buffer[0] := $4C; FT_Out_Buffer[1] := $1D; FT_Out_Buffer[2] := $1D; FT_Out_Buffer[3] := $1F; FT_Out_Buffer[4] := $02; FT_Out_Buffer[5] := $0D; FT_Out_Buffer[6] := $98; Write_USB_Device_Buffer(7); //(7,$5, 300); // set ufs commands speed to 115200 FT_Out_Buffer[0] := $42; // >> just send this no reply needed FT_Out_Buffer[1] := $10; Write_USB_Device_Buffer(2); //Set UFS to Atmel MODE first Reset_USB_Device; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_DTR; Purge_USB_Device_Out; Purge_USB_Device_In; FT_Current_FlowControl := 0; Set_USB_Device_FlowControl; Set_USB_Device_TimeOuts(2000, 5000); Set_USB_Device_BaudRate_Divisor($1A); FT_out_Buffer[0] := $58; // Write_USB_Device_Buffer(1); sleep(5); Read_USB_Device_Buffer(1); FT_Out_Buffer[0] := $32; Write_USB_Device_Buffer(1); Read_USB_Device_Buffer(1); FT_out_Buffer[0] := $68; FT_out_Buffer[1] := $01; Write_USB_Device_Buffer(2); sleep(5); Read_USB_Device_Buffer(1); FT_Out_Buffer[0] := $67; sleep(5); Write_USB_Device_Buffer(1); sleep(5); Read_USB_Device_Buffer(1); Set_USB_Device_FlowControl; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_DTR; Purge_USB_Device_Out; Purge_USB_Device_In; FT_Out_Buffer[0] := $68; FT_Out_Buffer[1] := $00; sleep(5); Write_USB_Device_Buffer(2); sleep(5); Read_USB_Device_Buffer(1); FT_Out_Buffer[0] := $66; sleep(5); Write_USB_Device_Buffer(1); sleep(5); Set_USB_Device_DTR; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_FlowControl; Set_USB_Device_BaudRate_Divisor($1A); FT_Current_DataBits := $8; FT_Current_StopBits := $1; FT_Current_Parity := $0; Set_USB_Device_DataCharacteristics; //DataBits: 8, StopBits: 0 , Parity: 0 Set_USB_Device_TimeOuts(8000, 8000); Reset_USB_Device; Purge_USB_Device_Out; Purge_USB_Device_In; FT_out_Buffer[0] := $A5; // #$A5 >> must read 1 byte Write_USB_Device_Buffer(1); sleep(5); Read_USB_Device_Buffer(1); if ft_in_buffer[0] = $C3 then result := true; Clr_USB_Device_DTR; Purge_USB_Device_Out; Purge_USB_Device_In; Set_USB_Device_TimeOuts($50, $50); end; end.