FreeCalypso > hg > tcs211-l1-reconst
view STATUS @ 289:f2f7f4dff6d7
STATUS: analysis complete
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 19 Mar 2017 23:41:49 +0000 |
parents | 595cdc5ff4e5 |
children | 7ad882cbce4c |
line wrap: on
line source
Objects in l1_ext.lib: l1_afunc.obj: not exact, see explanation below l1_async.obj: perfect match l1_cmplx.obj: perfect match to 20070608 version except line number points l1_init.obj: perfect match l1_pwmgr.obj: perfect match l1_small.obj: perfect match l1_sync.obj: not exact, see explanation below l1_trace.obj: bits match perfectly, diff only in symbolic metadata l1_dyn_dwl_afunc.obj: perfect match l1_dyn_dwl_apihisr.obj: perfect match l1_dyn_dwl_async.obj: perfect match l1_dyn_dwl_func.obj: not exact, see explanation below l1_dyn_dwl_init.obj: sole diff is in the num_of_primitives oddity, see explanation below l1_dyn_dwl_sync.obj: perfect match l1audio_abb.obj: perfect match l1audio_afunc.obj: bits match perfectly, diff only in symbolic metadata l1audio_async.obj: diffs only in register alloc and symbolic metadata l1audio_back.obj: perfect match l1audio_drive.obj: perfect match l1audio_init.obj: perfect match l1tm_async.obj: bits match perfectly, diff only in the line number points l1tm_func.obj: bits match perfectly, diffs only in symbolic and line numbers l1tm_stats.obj: perfect match Objects in l1_int.lib: dl1_com.obj: not exact, see analysis below l1_api_hisr.obj: perfect match l1_cmplx_intram.obj: perfect match to 20070608 version l1_ctl.obj: perfect match to 20070608 version l1_drive.obj: perfect match l1_func.obj: perfect match l1_mfmgr.obj: perfect match l1_sync_intram.obj: not exact, see explanation below l1audio_func.obj: perfect match l1audio_sync.obj: perfect match Objects in l1_custom_ext.lib: l1audio_cust.obj: dead functions not reconstructed, perfect match otherwise l1tm_cust.obj: perfect match l1tm_tpu12.obj: perfect match Objects in l1_custom_int.lib: ind_os.obj: perfect match l1_cust.obj: perfect match Objects in tpudrv.lib: tpudrv.obj: perfect match tpudrv12.obj: not exact, see analysis below Detailed analysis of differences, i.e., cases where the reconstructed C code compiles into an object that is not bit-identical to the original blob: l1_afunc.obj: The l1_afunc.c module from LoCosto is used without any changes: it compiled right away after adding one constant to l1_const.h, and the result of recompilation is identical to the original up until the l1a_clip_txpwr() function, which is the last function in the module. Disassembly of the original blob version of this function has been analyzed and found to be identical in logic to the available C code, but there must have been some change to the code expression that results in different output from the compiler. In particular, the symbolic info indicates the presence of a local variable named power in the original, but no such local var exists in the LoCosto version. The TSM30 version was of no help as it is entirely different there. See g23m/objdiff/l1_ext/l1_afunc.notes for further info. l1_sync.obj: The last function in this module is l1s_dedicated_mode_manager(); the two preceding functions match perfectly, but for this last function when the reconstructed code is recompiled, the compiler's register allocator makes different picks for reasons that could not be successfully reversed. Because the code is compiled in Thumb mode and the compiler made a different choice between low and high registers in some places, the instructions do not line perfectly. The logic match has instead been verified by manual comparison. l1_sync_intram.obj: Similar situation in the l1s_schedule_tasks() function: the function is huge, there is an unknown set of factors determining what the compiler's register allocator will do, and in this case there is even a difference in the choice of register vs. stack for some temporaries. As a result, the code does not line up and the logic had to be verified manually. All other functions (preceding and following) match perfectly. dl1_com.obj: The reconstruction of this module is not exact, but the logic has been verified to be an exact match except for the removal of some non-functional bogons. Specifically: l1_create_ISR(): diff in one local variable name (result vs. status), affects the generated assert string, but the length stays the same. This assert string also contains the line number which differs (3 digits in both cases), and the location of the string changes because of the diffs in later functions listed below. Verified exact match otherwise. TP_FrameIntHandler(): verified exact match. layer_1_sync_HISR_entry(): the version in the blob contains a non-functional bogon which has not been reconstructed, see the comments in the reconstructed source. Verified to be an exact match except for the removal of this bogon. rx_tch_data(): empty function in both versions, trivial exact match. tx_tch_data(): this stub function is supposed to return a pointer, but the original blob does a bare bx lr, returning whatever happens to be in r0 on entry, which is unpredictable as the function takes no arguments. The reconstructed version returns NULL. Strings and literals after the functions: manually verified to be an exact match. .bss section: the original blob contains these defunct uninitialized data objects: BACK_queue, DLL1_queue, L1C1_queue, RRM1_queue, pool_52, pool_100, pool_400, pool_1600, and a static variable i in layer_1_sync_HISR_entry() related to the bogon mentioned above. These global data objects are not referenced from anywhere else in the firmware and the link succeeds without them being present, hence they have been omitted from the reconstruction. The rest is an exact match. l1_dyn_dwl_func.obj: The LoCosto version uses a function (implemented in l1_func.c in the LoCosto code) named l1_memcpy_16bit() to download patch bits into the DSP's API RAM; the function does what the name says, and the logic of using 16-bit accesses when hitting this API RAM makes perfect sense to me (Mychaela). The original TCS211 code apparently used plain memcpy(), which the compiler turned into its C$MEMCPY call. If one does a #define l1_memcpy_16bit memcpy in l1_dyn_dwl_func.c, the resulting l1_dyn_dwl_func.obj is almost bit-identical to the original blob: the only diff is in register allocation - the compiler's register allocator picks a different choice of registers, but all instructions still perfectly line up. For production use of our reconstructed TCS211 L1 code, we have adopted the version with l1_memcpy_16bit() - the function body itself has been moved into l1_dyn_dwl_func.c so that l1_func.c remains a perfect match. l1_dyn_dwl_init.obj: In the TCS211 configuration without L1_GTT, there are a total of 5 signals (aka primitives aka L1 messages) which trigger a dynamic DSP patch download. These 5 signals are enumerated in signal_patch_array[] in l1_dyn_dwl_afunc.c (which has been reconstructed to a perfect match), and their total count (which should be 5) goes into l1a.dyn_dwnld.num_of_primitives, set in l1_dyn_dwnld_initialize_var() in l1_dyn_dwl_init.c. In the original blob version this num_of_primitives variable ends up being set to 6: first set to 2, then incremented by 4. In the LoCosto source this var is first set to 0 as they apparently have no patches that are independent of compilation config options, and then incremented for every enabled option. In our reconstruction we have made the GPRS and AMR_SCH patches and the primitives that trigger them mandatory, and conditionalized the E2 and AMR_MMS patches on MELODY_E2. The GPRS and AMR_MMS critters are preinstalled by the static patch, and get pushed out by AMR_SCH and E2, respectively. Of the 5 primitives listed in signal_patch_array[] in the original blob, the first 2 are always-present core ones, whereas the last 3 are specific to E2. The AMR_MMS patch is reinstated upon L1_BACK_MELODY_E2_UNLOAD_INSTRUMENT_CON. Based on the above reasoning, our reconstructed version sets l1a.dyn_dwnld.num_of_primitives to 5 in the full configuration: first sets to 2, then increments by 3. If one makes a sans-MELODY_E2 build, only the GPRS and AMR_SCH patches will be retained, and only the two non-E2 primitives for entry into and exit from dedicated mode. l1audio_async.obj: The only bit diff is in register allocation - the compiler's register allocator picks a different choice of registers, but all instructions still perfectly line up. There is also a slight diff in the symbolic metadata emitted for functions, which might be related to the diff in the register allocation. The root cause of these diffs could not be found, but there is no functional difference as only some in-function temporary registers have been interchanged. l1audio_cust.obj: The original blob version has these demo/test functions at the end of the module: audio_melo_e1_demo1_start() audio_melo_e1_demo1_stop() audio_melo_e1_demo2_start() audio_melo_e1_demo2_stop() audio_melo_e2_load_lsi() audio_melo_e2_demo1_start() audio_melo_e2_demo1_stop() audio_melo_e2_demo2_start() audio_melo_e2_demo2_stop() These functions are dead code, i.e., they are not called or referenced from anywhere else in the firmware, and the link succeeds without them being present. These dead functions have been omitted from the reconstructed version. The reconstruction is a perfect match otherwise. tpudrv12.obj: The reconstruction of this module was more of a translation of logic from disassembly to C than adaptation of source from other versions, hence it is not a bit-for-bit match or even close. However, the logic has been carefully verified and confirmed to match the original; see chipsetsw/layer1/tpu_drivers/source0/tpudrv12.notes for the details.