/* ###################################################################### # Patch 'EXE Loader' ver=2.0 id=00C00X20. Loads and runs patches, # # compiled as EXE program. Patch consist of non-changeble part (core) # # and part, depending from hardware and place of shortcut (invoker). # # There are many invokers can be placed, linked to common core. Each # # invoker have his own config section with the list of Patches ID, # # addicted to run. Just set the of field "ID_X" with values of desired # # Patches ID, terminated with zero Patch ID, put .exe files into # # 0:\Misc\Patches\ folder and corresponding .ptc files into # # 0:\Misc\Patches\ptc folder, and it will run. Enjoy. # #######################################################################*/ ;© KonstanT 2006 $ARM9E $genonly ;----- Machine specific addresses (for CX70 sw50 here): -------- ShortCut equ 001711F82h ; Place, from where invoker is called Invoker equ 001738970h ; Small subr., recalls EXELoader core OrigSubr equ 001711A34h ; Original subr., called from ShortCut LocalPatchID equ 0x00C00120 ; ID of current copy of Invoker ;----- Machine independent addresses ---------------------------- ;aLoadExePatch equ 000FC2E00h ; Place, where ExeLoader core is situated $INCLUDE (..\..\CX70_50.inc) ;******************** EXE Loader CORE ******************************* AREA PATCHCODE, CODE, at aLoadExePatch code16 Patch: push {LR} add R1, R0, #4 ; R1=^list of Patches ID push {R1, R3} ; store ^first_patchID MainCycle: pop {R1, R3} ; load ^next_patchID into R1, run switcher - in R3 ldr R0, [R1] ; load patchID add R1, #4 ; prepare ^next_patchID push {R1, R3} ; store values into stack cmp R0, #0 ; the end of list? beq Exit ; all is clear... bl Bufferizator ; ask MP, is enabled? beq NextPatch ; no - treat next patch mov R7, R0 ; now R7=^PTC of starting exepatch ldrb R2, [R7, #1] ; check, is the starting parameter cmp R2, R3 ; equal to the run switcher 'A' or 'B' (after or before) bne MainCycle ; if not equal - treat next patch mov R2, #0x10 ; R4=1024 bytes - area from begin of PTC, within lsl R4, R2, #6 ; this place we try to find path to exe string LoadReg 3, Path ; sample '0:\M' - begin of the path 0:\Misc\Patches\ SrchCycP: ldr R5, [R7, R2] ; check PTC record from offset 10h with step 4 cmp R3, R5 beq FoundP ; Found File Path add R2, #4 tst R2, R4 ; End of scanning area? beq SrchCycP ; no - continue scan b NextPatch ; File Path not found - treat next patch FoundP: add R0, R2, R7 ; now R0=^PathString mov R6, R0 add R6, #0x20 ; after PathString (up to 20h chars) pointer R6=^^EXE add R4, R6, #4 ; R4=^FreeRAM (PathString + 24h) ldr R5, [R6] ; check pointer of loaded EXE file cmp R5, #0 ; it already loaded? bne ChkSCEP ; yes - check, is it really EXE format str R6, [R6] ; no - load file and put pointer after PathString mov R1, R6 push {R7} bl FLOpenReadClose ; standard procedure... pop {R7} ChkSCEP: ldr R6, [R6] ; now R6=^EXE file LoadReg 3, SCEP ; signature 'SCEP' - EXE files MUST begins from this ldr R5, [R6] cmp R3, R5 ; is signature correct? beq FoundSCEP b NextPatch ; no - treat next patch FoundSCEP: ldrh R3, [R6, #0xC] ; field INFOBLOFFS in doublewords lsl R3, #2 add R3, R6 ; R3=^INFOBLOCK ldr R2, [R3, #4] ; R2=^DATABLOCK cmp R2, #0 ; DATABLOCK set? bne SkipTune ; yes - field already set add R2, R7, #4 ; DATA begins from offset 4 from begin of PTC of exe str R2, [R3, #4] ; set field DATABLOCK with ^DATA str R4, [R3] ; set field FREERAM with ^FREERAM mov R2, #0 ; str R2, [R3, #8] ; MSGXCHG - reserved for future str R2, [R3, #0xC] ; RESERVED - reserved for future ldrh R3, [R6, #6] ; R3=RELOSCNT a number of RELOTABLES in EXE mov R2, R6 add R2, #0x10 ; R2=^RELOTBL0CNT - pointer to 1st RELOTABLE Cycle0: sub R3, #1 ; treat all RELOTABLEs bcc ExReloAll ; treat complete - to start exe ldrh R4, [R2] ; a number of elements in a current RELOTABLE lsl R4, #2 ; x4 - bytes in a table ldrh R5, [R2, #2] ; RELOOFFSET in doublewords lsl R5, #2 ; RELOOFFSET in bytes add R5, R6 ; R5=^end_of_current_RELOTABLE IntCyc: sub R4, #4 ; previos element bcc EndReloTbl ; treat of relotable complete - treat next ldr R1, [R5, R4] ; load offset from begin of exe add R1, R6 ; transform to address in memory str R1, [R5, R4] ; store this address in RELOTABLE b IntCyc ; until begin of RELOTABLE EndReloTbl: add R2, #4 ; Next RELOTABLE b Cycle0 ; until treated the last RELOTABLE ExReloAll: ldr R1, [R6, #8] ; EntryPoint - offset from begin of exe add R1, R6 ; transform to absolete address str R1, [R6, #8] ; store in a field ENTRYPOINT SkipTune: ldr R7, [R6, #8] ; load value of ENTRYPOINT ldr R0, [SP, #0x28] ;\ ldr R1, [SP, #0xC] ; \ ldr R2, [SP, #0x10] ; \ ldr R3, [SP, #0x14] ; load initial values R0 - R6 from stack ldr R4, [SP, #0x18] ; / ldr R5, [SP, #0x1C] ; / ldr R6, [SP, #0x20] ;/ blx R7 ; run loaded exe file! str R0, [SP, #0x28] ;\ str R1, [SP, #0xC] ; \ str R2, [SP, #0x10] ; \ str R3, [SP, #0x14] ; store resulting values R0 - R6 into stack str R4, [SP, #0x18] ; / str R5, [SP, #0x1C] ; / str R6, [SP, #0x20] ;/ NextPatch: b MainCycle ; Load next patch from list Exit: pop {R1, R3} ; returning... pop {PC} ;-------- OnStartUp procedure, runs at the powering up a phone ----------------- OnStartUp: push {R0,LR} mov R0, #6 bl FLSetProfile ;SetProfile(6) pop {R0,PC} ;---------------------------------------------------------------------------- Align4 SCEP db 'SCEP' Align16 FakeConfig: dd 0xB1C2D3E4, 0x00C001FF, OnStartUp+q1, 0, 0 ;fake, just for StartUp... Align4 Path db '0:\M' ;***************** End of LoadEXE CORE ********************************* ;***************** Start of INVOKER ************************************ ;---------- ShortCut from firmware ------------------ AREA STARTUPCODE, CODE, at ShortCut code16 bl Invoker ; replaces original branch ; -------- Invoker Subroutine ----------------------- ; ! Do not modify any push/pop command ! org Invoker push {R0,LR} LoadReg 0, LocConfig+4 ; R0=EXELoaderID LoadReg 7, aBufferizator blx R7 bne RunPatch pop {R0} LoadReg 7, aOrigSubr blx R7 pop {PC} ;-------------------------------------------- RunPatch: push {R0} ; ^ExeLoader PTC push {R1-R6} ; storing Old registers values mov R3, #'B' ; 'B' - run patch before invoke of original sub. LoadReg 7, LoadExePatch blx R7 ; run EXELoader with run mode 'B' (before) pop {R1-R6} ; restore {modified} R1-R6 values ldr R0, [SP, #4] ; restore {modified} R0 value LoadReg 7, aOrigSubr blx R7 ; call original firmware subroutine str R0, [SP, #4] ; storing new R0 value ldr R0, [SP] ; reload ^EXELoader PTC push {R1-R6} mov R3, #'A' ; 'A' - run patch after invoke of original sub. LoadReg 7, LoadExePatch blx R7 ; run EXELoader with run mode 'A' (after) pop {R1-R7} pop {R0, PC} Align4 LoadExePatch dd aLoadExePatch + q1 aOrigSubr dd OrigSubr + q1 aBufferizator dd Bufferizator + q1 Align16 LocConfig: dd 0xB1C2D3E4, LocalPatchID, 0, 0 ; Config for Master midlet db '{patch=`NetSrch EXEloader` ver=2.0 id=00C00120 cp=`KonstanT`}' db '{0x04 h `ID_0` ml=4 v=1011C000}' db '{0x08 h `ID_1` ml=4 v=00000000}' db '{0x0C h `ID_2` ml=4 v=00000000}' db '{0x10 h `ID_3` ml=4 v=00000000}' db '{0x14 h `ID_4` ml=4 v=00000000}' db '{0x18 h `ID_5` ml=4 v=00000000}' db '{0x1C h `ID_6` ml=4 v=00000000}' db '{0x20 h `ID_7` ml=4 v=00000000}' db 0 ;******************** End of INVOKER ************************************ END