frf-to-odx is done inside SoxUtil.dll (odis or DTS7)
text:10001CC5 call edi ; MString::operator char const *(void) ; MString::operator char const *(void)
.text:10001CC7 push ebx ; dest_zip_filename
.text:10001CC8 push eax ; frf_filename
.text:10001CC9 lea ecx, [ebp+var_170]
.text:10001CCF call MY_getKey_and_goto_descramble
.text:10001CD4 lea ecx, [ebp+var_170]
.text:10001CDA mov byte ptr [ebp+var_4], 2
.text:10001CDE call MY_unzipper_stuff
.text:10001CE3 test al, al
.text:10001CE5 jnz short loc_10001CFC
.text:10001CE7 lea ecx, [ebp+var_28]
.text:10001CEA push offset unk_100046E0
.text:10001CEF push ecx
.text:10001CF0 mov [ebp+var_28], offset aNotOne_odxInAr ; "Not one .odx in archive"
.text:10001CF7 call _CxxThrowException
key.bin is inside the resource area
Then, as told, the odx contains flash data in encrypted/compressed form.
I dont' know for ECUs, you need to RE bootarea to know the decryption/decompression algo and i did only for dq200 0CW, and yes they are simple once ported to C code, but takes some days to RE them, so i'm not surprised if they don't go opensource quickly.
Flashdata first need to be descrambled and, at least for dsg, it's the same scrambling algo found in previous sgo files, just the byte subst table is per ecu type.
About compression algo, don't know, probably dsg uses diff algo than bosch, anyway comparing compressed and uncompressed data makes the task very easy.