f_ changed the topic of ##raspberrypi-internals to: The inner workings of the Raspberry Pi (Low level VPU/HW) -- for general queries please visit #raspberrypi -- open firmware: https://librerpi.github.io/ -- VC4 VPU Programmers Manual: https://github.com/hermanhermitage/videocoreiv/wiki -- chat logs: https://libera.irclog.whitequark.org/~h~raspberrypi-internals -- bridged to matrix and discord
Stromeko has quit [Ping timeout: 252 seconds]
Stromeko has joined ##raspberrypi-internals
jn has quit [Ping timeout: 255 seconds]
jn has joined ##raspberrypi-internals
jn has joined ##raspberrypi-internals
jn has quit [Changing host]
jcea has quit [Ping timeout: 240 seconds]
wael has quit [Ping timeout: 256 seconds]
bonda_000 has joined ##raspberrypi-internals
<bonda_000> clever: u here man?
<bonda_000> addcmpbeq param_1,DAT_ffffffff,0x0,LAB_0ec9b64c
<bonda_000> that's camera_subsystem_attached_devices() at 0ec9b65c
<bonda_000> it says, subtract one, compare with 0, and if equals, branch?
wael has joined ##raspberrypi-internals
Bitweasil has quit [Read error: Connection reset by peer]
Bitweasil- has joined ##raspberrypi-internals
pavelow has quit [Ping timeout: 268 seconds]
pavelow has joined ##raspberrypi-internals
bonda_000 has quit [Ping timeout: 272 seconds]
bonda_000 has joined ##raspberrypi-internals
jcea has joined ##raspberrypi-internals
<bonda_000> clever: u still here dude?
<bonda_000> Been messaging you for the past few days but the place seems to be dead
jcea has quit [Ping timeout: 240 seconds]
jcea has joined ##raspberrypi-internals
<clever> bonda_000: sleep schedule is out of sync with you
<bonda_000> oh I was just gonna ask are you still doing this thing or no
<bonda_000> the decompiling of start_x.elf
<bonda_000> I've dug pretty deep into camera stuff but some key parts are missing that I cannot find
<bonda_000> some offsets into cdi_struct that are referenced but I can't see them being instantiated anywhere
<bonda_000> I've identified all the function tables that are being used
<bonda_000> camera_ril creates a ca_process_thread, that loads a cdi, cdi talks to the camera_driver (ov5647 stuff), cdi also starts unicam, then ca_thread starts camplus that has access to both cdi and isp
<bonda_000> and then ca_thread checks _tx_event_flags and calls different functions
<bonda_000> I've found where the actual hardware signal to start capture is
<bonda_000> <bonda_000> unicam_rx_start(camera_subsystem_state + offset, *(cdi_struct + 0xDC) + 0x37, *(cdi_struct + 0x38))
<bonda_000> as a last function pointer call in update_channel_control_params() which is called from cdi_change_state
<bonda_000> so the last two I have trouble identifying
<bonda_000> what is at cdi_struct + 0xDC and cdi_struct + 0x38
<clever> i would assume that cdi_struct is a pointer, and dc/38 are an offset into the struct, and its then reading a word at that offset
<clever> what does ghidra claim the type of cdi_struct is?
<bonda_000> THA
<bonda_000> that's the one malloced in cdi_open
<bonda_000> of size 0x784c
<bonda_000> I gotta run I'll be back in 1 hour
bonda_000 has quit [Quit: Leaving]
<clever> and in this function, what was the type tagged as?
jcea1 has joined ##raspberrypi-internals
jcea has quit [Read error: Connection reset by peer]
jcea1 is now known as jcea
bonda_000 has joined ##raspberrypi-internals
<bonda_000> clever: back
<bonda_000> I mean, cdi_camera_open()
<bonda_000> __ptr = rtos_malloc_priority(0x784c,4,1,0)
Bitweasil- is now known as Bitweasil
jcea1 has joined ##raspberrypi-internals
jcea has quit [Read error: Connection reset by peer]
jcea1 is now known as jcea
<clever> bonda_000: i'm not sure whats up with cdi_camera_open, my ghidra is decompiling it weirdly
<bonda_000> here's what mine looks like
<bonda_000> that's what I though, it may be tripping up on something
<bonda_000> so pretty much the key stuff in this struct is
<bonda_000> void ** unicam_func_table at offset 0x7838
<bonda_000> void ** ov5647_lens_func_table at offset 0x1D0
<bonda_000> void ** ov5647_func_table at offset 0x1CC
<bonda_000> camplus_ctrl_struct * is at offset 0xC
<bonda_000> camplus_ctrl_struct is 0x70810 bytes
<bonda_000> if you want to trace it down
<bonda_000> ca_process_thread() is the starting point
<bonda_000> it calls load_and_open_cdi()
<bonda_000> so first it's gonna do is call cdi_load() which is a part of camplus, at line 30
<bonda_000> then at line 104, it calls cdi_camera_open()
<bonda_000> it doesn't know what number of arguments it takes so that last pointer to itself is non-important
<bonda_000> there's not much going on so it's just a byproduct of it loading the function pointer to r2 and then doing bl r2
<bonda_000> here's ca_process_thread where it all begins
<bonda_000> line 82: load_and_open_cdi()
<bonda_000> this is cdi_camera_change_state
<bonda_000> this is open_camera_driver
<bonda_000> which loads the ov5647, i2c interface stuff
<bonda_000> this is open_camera_peripheral
<bonda_000> this is open_camplus
<bonda_000> open_camplus comes from start_stills_capture()
bonda_000 has quit [Quit: Leaving]
bonda_000 has joined ##raspberrypi-internals
<bonda_000> clever: cdi_camera_task_func does reference cdi_struct + 0xDC a lot
<bonda_000> puVar13[0x31] is that
<bonda_000> since puVar13 = param_1 + 0x18 at the beginning
<bonda_000> and param_1 is the cdi_struct, 0x31*4 thats cdi_struct + 0x18 + 0xC4 = cdi_struct + 0xDC in total
<bonda_000> it seems to be a pointer to some kind of table
<bonda_000> as it keeps plucking bytes out of there for if statements such as:
<bonda_000> bVar2 = *(byte *)((uint *)puVar13[0x31] + 0xd);
<clever> bonda_000: and what is the type of puVar13 ?
<bonda_000> pu pointer unsigned int
<clever> its clearly a struct, not an int pointer
<clever> so you need to create a struct of the right size, and change the type
<bonda_000> struct is param_1
<bonda_000> it takes an offset +0x18 from the beginning of param_1 and calls it "puVar13"
<clever> that is a second struct within the struct
<bonda_000> look at how it is referenced
<bonda_000> bVar2 = *(byte *)((uint *)puVar13[0x31] + 0xd);
<bonda_000> so puVar13 + 0x31 holds a pointer to something
<clever> so puVar13 is a struct pointer, and offset 0x31*4 within it is a pointer
<bonda_000> puVar13 could point to anything 4 byte aligned
<bonda_000> actually it could be
<clever> this is just how decompiling goes, you have to guess when something is a struct, and make a struct
<bonda_000> pointer undefined4
<bonda_000> no in my window its uint *puVar13; but I don't think it truly matters
<clever> the decompile is a mess because ghidra incorrectly guessed `uint*`
<clever> you need to create a struct, and change the type to a struct pointer
<bonda_000> I did
<bonda_000> param_1 is a big struct
<clever> 2024-05-22 19:01:00 < bonda_000> it takes an offset +0x18 from the beginning of param_1 and calls it "puVar13"
<clever> 2024-05-22 19:01:12 < clever> that is a second struct within the struct
<bonda_000> cdi_struct of size 0x784c
<clever> so you need to create a second struct, and make offset +0x18 of the first struct into that second struct
<bonda_000> I know
<bonda_000> whatever is at cdi_struct + 0xDC
<bonda_000> all references I find it grabs data from there
<bonda_000> as if it is already instantiated somewhere
<bonda_000> so for example
<bonda_000> cdi_struct + 0x10 is camera_subsystem_state global table
<bonda_000> so if I pass cdi_struct to a function that accesses that table
<bonda_000> it can make a variable puVar = cdi_struct+0x10
<bonda_000> it usually means that the assembly did something like
<bonda_000> mov r10, param_1 (cdi_struct is param_1)
<bonda_000> add r10, 0x10
<bonda_000> and that r10 is what it will refer to as puVar
<bonda_000> so yeah it is an address, a pointer
<bonda_000> for example
<bonda_000> int open_camera_driver(cdi_camera_ctrl_struct *param_1,int param_2,int *param_3)
<bonda_000> it takes camera_subsystem_get_func_table()
<bonda_000> then it calls functions 3, 5, and 4 from that function table, which is camera_subsystem_open, camera_subsystem_get_attached_devices, and camera_subsystem_close
<bonda_000> here it passes cdi_struct + 0x10 as param_1, so an offset into the big struct
<clever> sounds reasonable
<bonda_000> undefined4
<bonda_000> camera_subsystem_get_attached_devices(int *param_1,undefined4 *param_2,int *param_3,uint param_4)
<bonda_000> line 41: local_90 = param_1;
<bonda_000> it puts it on a stack
<bonda_000> then if you highlight the entire function and set gp=0ef07e00
<bonda_000> you will see camera_subsystem_state name pop up
<clever> that looke to be a 292 byte struct
<bonda_000> yep I called it a table
<bonda_000> some values are bytes in there
<bonda_000> so at the end it will do
<bonda_000> local_a8 = 0xefc275c;
<bonda_000> that's an offset into camera_subsystem_state
<bonda_000> and then the very last do-while loop
<bonda_000> which is weird because it seems to run only once
<bonda_000> *local_90 = local_a8; it does that so it put the camera_subsystem_state + offset into cdi_struct + 0x10
<clever> it was probably meant to loop over every available camera
<clever> and on the pi1-pi4, only 1 camera is available
<bonda_000> I guess but the 0 is hardcoded
<clever> because it starts at 0
<clever> oh, the end condition
<clever> it might be a compile-time option
<bonda_000> yeah and the loop only allows it to increment once
<clever> like, for (int i=0; i<CAM_COUNT; i++)
<clever> and then it got compiles with -DCAM_COUNT=1
<bonda_000> probably
<clever> and the compiler didnt optimize it out
<bonda_000> I was expecting something similar for cdi_struct + 0xDC but I only haven't looked into the isp stuff
<bonda_000> the hierarchy of these modules is weird
<bonda_000> cdi spawns camplus but then camplus seems to control the cdi
<bonda_000> then if you look at open_camera_peripheral
<bonda_000> which in the init sequence goes shortly after open_camera_driver that we just talked about
<bonda_000> it does
<bonda_000> iVar2 = (*(code *)param_1->unicam_func_table[3])
<bonda_000> (&local_54,&param_1->unicam_state +offset + param_2 * 0xf04,
<bonda_000> param_1->unicam_func_table[3]);
<bonda_000> it passed the same cdi_struct + 0x10 as param_2 to the unicam_open
<bonda_000> and then it overwrites it!
<bonda_000> the first thing that int unicam_open(byte *param_1,undefined4 *param_2) does is:
<bonda_000> *param_2 = 0;
<bonda_000> if you highlight the entire function and set gp=0ef07e00 it now pulled the unicam_state global struct
<bonda_000> and the last thing before it returns it puts *param_2 = iVar2 + 0xf37c7b0;
<bonda_000> an offset into unicam_state so we just overwrote camera_subsystem_state with unicam_state
<clever> i'm a bit distracted right now by factorio, i'll need to look into that camera stuff some more when i have time
<juri_> clever: there is one game, it is called life, and we lose each time we play other games. ;)
bonda_000 has quit [Ping timeout: 268 seconds]
bonda_000 has joined ##raspberrypi-internals
<bonda_000> good night
bonda_000 has quit [Client Quit]