OK, figured out how to patch libnickel.so.1.0.0 to disable the Critical Error popup. This way it would accept any non-empty registration data, like in older firmwares.
Spoiler:
The string "Critical Error" is referenced from these two functions:
Code:
008A85D0: _ZN18Nickel3Application20finishInitializationEv ; Nickel3Application::finishInitialization()
008FC95C: _ZN19PlugWorkflowManager16onDoneProcessingEv ; PlugWorkflowManager::onDoneProcessing()
Both functions contain a similar piece of code:
Code:
<...>
008FCA3E BL sub_643568 ; load and validate user data
008FCA42 CBNZ R0, no_error
008FCA44 LDR R1, =(_ZN19PlugWorkflowManager16staticMetaObjectE_ptr - 0xE29760)
008FCA46 ADDS R6, R7, #4
008FCA48 LDR R2, =(aCriticalError - 0x8FCA58)
008FCA4A MOV.W LR, #0xFFFFFFFF
008FCA4E MOV R3, R0 ; int
008FCA50 MOV R0, R6 ; this
008FCA52 LDR R1, [R5,R1] ; _ZN19PlugWorkflowManager16staticMetaObjectE_ptr ; char *
008FCA54 ADD R2, PC ; "Critical Error"
008FCA56 STR.W LR, [SP,#0x14+var_14]
008FCA5A BLX.W _ZNK11QMetaObject2trEPKcS1_i ; QMetaObject::tr(char const*,char const*,int)
008FCA5E MOV R0, R6
008FCA60 MOVS R1, #1
008FCA62 BLX.W j__ZN19AccountSignOutMixin17showSignOutDialogE7QStringb ; AccountSignOutMixin::showSignOutDialog(QString,bool)
008FCA66 LDR R0, [R7,#0xC+var_8]
008FCA68 LDR R3, [R0]
008FCA6A CBNZ R3, loc_8FCA80
008FCA6C MOVS R1, #2
008FCA6E MOVS R2, #4
008FCA70 BLX.W _ZN10QArrayData10deallocateEPS_jj ; QArrayData::deallocate(QArrayData*,uint,uint)
008FCA74
008FCA74 no_error ; continue normally
<...>
This code calls a function at 0x643568 that loads and validates the user data. If that function returns 0, the Critical Error dialog is shown. Otherwise, no dialog appears and everything is fine. So we can just modify that function to always return a non-zero value.
The end part of the load-and-validate-user-data function at 0x643568, where the result is returned, looks like this:
Code:
006435A6 ADDS R0, R5, #1 ; return 0 if R5 == -1
006435A8 ADD.W R7, R7, #0x3C
006435AC IT NE
006435AE MOVNE R0, #1 ; otherwize return 1
006435B0 MOV SP, R7
006435B2 POP {R4-R7,PC} ; return from function
Changing the first line to
Code:
006435A6 ADDS R0, R5, #2 ; return 1 if R5 == -1
will make the function always return 1. Done!
Here is the patch for libnickel.so.1.0.0 from the 3.19.5761 firmware:
Code:
<Patch>
patch_name = `Accept any registration data, disable the Critical Error dialog`
patch_enable = `yes`
replace_bytes = 6435A6, 68, A8
</Patch>
The only problem is that the patch would have to be manually updated for future firmwares. Perhaps we could find out how to generate valid registration data that would work with unpatched firmwares?