Hello
, long time lurker here. I never done reverse engineering before so i decided to try, I have been looking at the unlocked firmware for the past 2 day and I am getting the hang of it, maybe i will post some more informations if i can get to a succesfull point i which i can deobfuscate the bct and other data.
For now i just wanted to share that the firmware read the bootrom version from the rp2040 and actually do some different preparation based on it, it seems it does not know about the new bootrom versions greater than 1.
That could be the cause of why the rp2040 work for a only few people.
From my limited reversal of this firmware you're probably looking at pico SDK runtime init routines which initialize fplib function pointers; different bootrom versions have differing levels of support for them, like double-precision floating point funcs.
I'd recommend compiling your own pico SDK binaries and comparing the two with symbols loaded to help orient yourself, or at least know when a function has an equivalent C version you can just look up to be a bit faster. One thing that quickly becomes apparent is that the entrypoint is copied to SRAM, specifically starting at ROM address 0x10013ABC and into SRAM addresses 0x200200C0 to 0x200212A0. In IDA I'd recommend just copying the firmware.bin contents to that address.
On the subject, I haven't really found anything interesting:
-The PIO assembly someone posted from earlier is just the ws2812 LED example from the rpi pico-examples repo which it uses to change the colour of the ws2812 LED: (cant post link)
-Speaking of the pico SDK, the initial VTOR that does BKPT 0 on every interrupt is copied into SRAM and patched to jump to whatever IRQ handler is required.. this is in every single pico SDK binary, although the entrypoint does weird stuff to the VTOR later like set it to 0xEE2F8D10 (an invalid address) which would probably make more sense if I followed the massive chain of STR instructions. They disable IRQ 3 (external?) beforehand so I assume it doesn't really use that value.
-They have a 1 second watchdog timeout, and if the watchdog triggers they set the LED colour to red(?) and reset the SOC.
-Before this it (I think) waits up to 300ms for a sequence on the CMD/gpio27 pin. It has a bunch of other logic involving the time since startup that would probably make more sense if I knew how the hwfly worked. It's here that it sets the LED colour to blue which represents "glitching".
-They do seem to be changing the clock speed to 333Mhz and setting the SOC voltage to 1.30 volts. I can't exactly tell what it's doing due to the abundance of divmod_u32u32 calls that I don't want to sift through.
-It also later exits the XIP flash, probably because they overwrite the ROM.
-It writes to SWD pins not just to prevent debugging but also to explicitly send commands. It does send a 35-byte sequence which I can't wrap my head around before it writes standard SWD commands to interact with debug/access port registers.
It then sends a series of more standard SWD commands. I see in later portions of the entrypoint it writes other SWD commands but I haven't had the chance to look at those yet:
In total, on each core,
-Write TARGETSEL (as seen above)
-Read DPIDR, discard value (in fact it doesn't seem to really care about any SWDO value)
-Write 0x1E to (debug) AP abort register
-Write 0x50000001 to CTRL/STAT register (debug)
-Write 0x10 to (debug) AP abort register
-Write 0x3 to (debug) AP select register
-Write 0xA2000012 to (Access port) CSW
For more info see the ADIv5.2 spec.
Most of this is intelligible but I can't figure out why the final access port write (presumably to the MEM-AP?) sets the prot bits to 0x44, and looking up coresight docs doesn't help much either. I assume this setup is so that they can do funny stuff like write to SRAM using the SWD protocol given that they use it a bit later. This function is called for both cores on core 0.