I atteched a new explenation of the header data
Code wise it looks like this
Than the next happens
FFBB6B18 : The sub "Execute_Ceres_Job" contains a switch statement which executes all kinds of actions on the CF card like file open, read write etc.
FFBB7240 : This is case 29 "UPDATEFILEDATA_CERES_UPD_DecryptToFir" that opens the FIR file.
...
...
FFBB72E8 BL UPD_DecrypFlasher_FFBC4A5C
...
...
FFBC4AA0 BL "Check_FIR_and_read_and_decrypt_Flasher"
R0 contains the a pointer to the start of the FIR code.
here the size of the flasher code is loaded in R4 and on FFBC4DEC a call is made to "Goto_flasher_code_and_decrypt"
_40D_ROM:FFBC4D9C Check_FIR_and_read_and_decrypt_Flasher ; CODE XREF: UPD_DecrypFlasher_FFBC4A5C+44
_40D_ROM:FFBC4D9C STMFD SP!, {R4,LR} ; Store Block to Memory
_40D_ROM:FFBC4DA0 MOV R1, R0 ; R1 := R0 = Start of FIR file
_40D_ROM:FFBC4DA4 ADD R2, R1, #0x24 ; R2 := Start FIR +0x24 ([Start+0x24] =0x000000B0)
_40D_ROM:FFBC4DA8 LDMIA R2, {R2,R3} ; Load multiple and increase after ==> R2:=0xB0; R3:=0x120
_40D_ROM:FFBC4DAC CMP R3, #0x120 ; Set cond. codes on Op1 - Op2
_40D_ROM:FFBC4DB0 MOV R0, #0 ; R0;=0
_40D_ROM:FFBC4DB4 ADD R4, R1, R2 ; R4:= start of FIR +0xB0 = [0x0019DB60] = addr of size of flasher code excluding header
_40D_ROM:FFBC4DB8 LDMCCFD SP!, {R4,PC} ; return
_40D_ROM:FFBC4DBC LDR R3, [R1,#0x2C] ; R3 := [Start of FIR + 0x2C] = 0xFFFFFFFF
_40D_ROM:FFBC4DC0 CMN R3, #1 ; result := R3+1=0, only change flags, do not store
_40D_ROM:FFBC4DC4 ADD R0, R1, R3 ; R0 := R1+R3 = start of FIR -1
_40D_ROM:FFBC4DC8 BEQ loc_FFBC4DE8 ; jump if R3=-1
_40D_ROM:FFBC4DCC LDR R3, [R0,#0x24] ; R3 := [Start FIR - 1 +0x24] = 0x120
_40D_ROM:FFBC4DD0 ADD R0, R0, R3 ; R0 := Star FIR -1 + 120 = last byte of header
_40D_ROM:FFBC4DD4 BEQ loc_FFBC4DE8 ; R0 := R4 =start of FIR +0xB0 = addr of Size of flasher code
_40D_ROM:FFBC4DD8 BL Goto_flasher_code_and_decrypt ; this is where XOR takes place
_40D_ROM:FFBC4DDC CMN R0, #1 ; Set cond. codes on Op1 + Op2
_40D_ROM:FFBC4DE0 MOVL R0, 0xFFFFFFFF
_40D_ROM:FFBC4DE4 LDMEQFD SP!, {R4,PC} ; Load Block from Memory
_40D_ROM:FFBC4DE8
_40D_ROM:FFBC4DE8 loc_FFBC4DE8 ; CODE XREF: Check_FIR_and_read_and_decrypt_Flasher+2C
_40D_ROM:FFBC4DE8 ; Check_FIR_and_read_and_decrypt_Flasher+38
_40D_ROM:FFBC4DE8 MOV R0, R4 ; R0 := R4 =start of FIR +0xB0 = addr of Size of flasher code
_40D_ROM:FFBC4DEC BL Goto_flasher_code_and_decrypt ; this is where XOR takes place
Goto_flasher_code_and_decrypt
In this sub the data "0x806ECB00" is loaded form the header of the FIR. This value is used in the next sub to calculate an offset that is used as starting point in the KEY data in the FIR.
_40D_ROM:FFBC4E00 Goto_flasher_code_and_decrypt ; CODE XREF: Check_FIR_and_read_and_decrypt_Flasher+3C
_40D_ROM:FFBC4E00 ; Check_FIR_and_read_and_decrypt_Flasher+50
_40D_ROM:FFBC4E00 STMFD SP!, {R4,R5,LR} ; Store Block to Memory
_40D_ROM:FFBC4E04 MOV R4, R0 ; R0 := R4 =start of FIR +0xB0 = addr of Size of flasher code
_40D_ROM:FFBC4E08 LDR R3, [R4,#0xC] ; R3 := [Start of FIR + 0xB0 + 0xC] = 0x806ECB00
_40D_ROM:FFBC4E0C MOV R5, #0 ; Rd = Op2
_40D_ROM:FFBC4E10 CMP R3, R5 ; check if R3=0 ==> return
_40D_ROM:FFBC4E14 ADD R0, R4, #0x70 ; R0 := Start of FIR + 0xB0 + 0x70 =[start + 0x120]
_40D_ROM:FFBC4E18 MOV R2, R3 ; R2 := R3 = nr used to calc offset in XOR tables
_40D_ROM:FFBC4E1C MOVEQ R0, R3 ; Rd = Op2
_40D_ROM:FFBC4E20 LDMEQFD SP!, {R4,R5,PC} ; return of R3=0
_40D_ROM:FFBC4E24 LDR R1, [R4] ; R1 = [R4] = Size of flasher
_40D_ROM:FFBC4E28 BL CipherBuffer_ROM_and_get_Key ; R0 = start of flasher code
And here the decryption takes place.
On FFBC54C8 a second value is loaded in R12 that is combined with the value 0x806ECB00 to calculate the offset that is used as starting point in the KEY data in the FIR.
This resulyt is an offset for Key1 of 100
This resulyt is an offset for Key2 of 0x1A7
The Keys themselves are loaded into the RAM data during start-up.
An aditional XOR with the value 0x37 conclude the decryption on FFBC5540
_40D_ROM:FFBC54C8 CipherBuffer_ROM_and_get_Key ; CODE XREF: Goto_flasher_code_and_decrypt+28
_40D_ROM:FFBC54C8 LDR R12, =dword_FF803FE1 ; Load from Memory
_40D_ROM:FFBC54CC STMFD SP!, {R4-R8,LR} ; Store Block to Memory
_40D_ROM:FFBC54D0 UMULL LR, R3, R12, R2 ; RdHi,RdLo:=Rm*Rs ==> R3_hi,LR_lo := FF803FE1 * R2
_40D_ROM:FFBC54D0 ; 802E.B3A6 : A555.6B00 <== FF80.3FE1 * 806E.CB00
_40D_ROM:FFBC54D4 LDR R6, =End_of_Cipher_key1 ; = 80C3
_40D_ROM:FFBC54D8 MOV R3, R3,LSR#9 ; div by 0x200 = clear lower 9 bits
_40D_ROM:FFBC54DC LDR R5, =End_of_Cipher_key2 ; = 82C4
_40D_ROM:FFBC54E0 ADD R3, R3, R3,LSL#9 ; R3:=R3+(R3*0x200) ==> R3:=R3*0x201 ==> cleared lower bits
_40D_ROM:FFBC54E4 MOV R12, R2,LSL#23 ; R12 := lower 9 bits of R2 (0x806ECB00) (shifted)
_40D_ROM:FFBC54E8 SUB R7, R6, #0x1FC ; calculate near start of cipher key1 (-508)
_40D_ROM:FFBC54EC RSB R2, R3, R2 ; =0x1A7 = R2 := R2 - R3
_40D_ROM:FFBC54F0 MOV R12, R12,LSR#23 ; =0x100 = Shift lower 9 bits (of 0x806ECB00) back to original location
_40D_ROM:FFBC54F4 SUB R7, R7, #3 ; 7EC4 start of cipher key1 (-508-503=-511) => 512 bytes
_40D_ROM:FFBC54F8 SUB R3, R5, #0x200 ; 80C4 = start of cipher key2 (-512) => 513 bytes
_40D_ROM:FFBC54FC SUBS R4, R1, #0 ; R1 = R4:= flasher size
_40D_ROM:FFBC5500 ADD R12, R12, R7 ; R12=R12+R7 = starting location in the middle of Key1
_40D_ROM:FFBC5504 ADD LR, R2, R3 ; LR=R2+R3 = starting location in the middle of Key2
_40D_ROM:FFBC5508 LDMLEFD SP!, {R4-R8,PC} ; Return when file size = 0
_40D_ROM:FFBC550C MOV R8, R7 ; R8 = Start of Key1
_40D_ROM:FFBC5510 MOV R7, R3 ; R7 = Start of Key2
_40D_ROM:FFBC5514
_40D_ROM:FFBC5514 Cipher_Loop_ROM ; CODE XREF: CipherBuffer_ROM_and_get_Key+88
_40D_ROM:FFBC5514 LDRB R3, [LR] ; load next byte of key1
_40D_ROM:FFBC5518 LDRB R2, [R12] ; load next byte of key2
_40D_ROM:FFBC551C LDRB R1, [R0] ; load next byte of Flasher code
_40D_ROM:FFBC5520 ADD R12, R12, #1 ; Rd = Op1 + Op2
_40D_ROM:FFBC5524 ADD LR, LR, #1 ; Rd = Op1 + Op2
_40D_ROM:FFBC5528 CMP R12, R6 ; Set cond. codes on Op1 - Op2
_40D_ROM:FFBC552C EOR R3, R3, R2 ; key1 := Key1 XOR Key2
_40D_ROM:FFBC5530 EOR R1, R1, R3 ; R1:= R1 xor (key1 XOR key2)
_40D_ROM:FFBC5534 SUB R4, R4, #1 ; decrease bytes still to go
_40D_ROM:FFBC5538 MOVHI R12, R8 ; if R12 > R6 (R6=End of Key) then R12:=R8 =start of key2
_40D_ROM:FFBC553C CMP LR, R5 ; Set cond. codes on Op1 - Op2
_40D_ROM:FFBC5540 EOR R1, R1, #0x37 ; Rd = Op1 ^ Op2
_40D_ROM:FFBC5544 MOVHI LR, R7 ; if LR > R5 (R5 = end of key) then LR:=R7 =start of key1
_40D_ROM:FFBC5548 CMP R4, #0 ; compare bytes of file still to go >0
_40D_ROM:FFBC554C STRB R1, [R0],#1 ; store decrypted byte and goto next byte
_40D_ROM:FFBC5550 BGT Cipher_Loop_ROM ; load next byte of key1
_40D_ROM:FFBC5554 LDMFD SP!, {R4-R8,PC} ; Load Block from Memory
_40D_ROM:FFBC5554 ; End of function CipherBuffer_ROM_and_get_Key
=========================