Made some progress while waiting for a LAN adapter, which ended up making getting one redundant.
First on the agenda was trying if I could simply "borrow" an 8P8C jack and some magnetics from an old network switch,
attach some probes to the expansion connector, and solder the wires attached to the probes directly to the magnetics.
It made for a wonderfully cursed setup:
Sadly, after a lot of fiddling around and re-soldering I wasn't able to fully get it to work; running ethernet signals was possibly not what dupont wires were invented for.
However, when closing up the probe setup and taking another look at the mainboard, I couldn't help but wonder why the user cal button was so auspiciously located on the back,
directly on the mainboard. What would happen if it was pushed while in the bootloader?
...
Well, nothing. What about while the scope is powering up?
Huh. No UART output. Is it just a weird reset line?
Maybe the SoC is doing something odd, let's hook up the USB and see if it enumerates at all.
... what's this? The
SPEAr300 reference manual has some hints:
38.5.3 USB boot
USB Boot refers upgrading of Flash memories (NAND and NOR) via USB.
[...]
After receiving 12 bytes BootROM decodes 12 byte command, changes the USB state machine to GET_DATA phase and then waits for expected number of bytes from Host.
BootROM receives the data and stores it into load address specified in the command, once all the data is received, BootROM changes the USB state machine to EXEC phase and decodes the type of data, if the received data is DDR Driver, then BootROM jumps to loadaddress, executes the DDR driver and jumps back to BootROM.
Now that the DDR is initialized, BootROM changes the USB state machine again to GET_CMD phase.
Now same process is repeated again, but this time type of data received is FIRMWARE, the FIRMWARE is capable of receiving data from Host, Flash upgrade capable etc.
After receiving the FIRMWARE, BootROM jumps to it in DDR.
That sounds great! Something is off though, even disregarding it containing one of the longest run-on sentences I've ever seen: the USB descriptors don't quite match.
Now, this is a reference manual for the SPEAr300, not SPEAr600, so maybe that's the sole difference? The SPEAr1340 seems to have a significantly more involved protocol.
Luckily (
found in this very thread even, thanks @abyrvalg!), ST has
released a "flasher", and it comes
with source code!
And, the source code mentions the main descriptor difference!
#define MY_VID 0x0483
#define SPR600_PID 0x7261
#define SPR300_PID 0x3801
It's a Windows-based tool however, based on old libusb 0.1.
I took the liberty of rewriting it into slightly more portable C taking advantage of the more modern libusb 1.0 (sources attached to this post).
Time to try it out! It needs a DDR driver and a U-boot image, both we can take from any Keysight firmware update:
$ spearload -t spear600 p500_ddrdriver.bin u-boot_image.bin
spearload: opening device...
spearload: sending DDR driver p500_ddrdriver.bin...
.
......
spearload: sending firmware u-boot_image.bin...
.
...
Back at the UART, we are greeted with success!
U-Boot 2010.03 (May 18 2017 - 11:28:22)Agilent P500
CPU: SPEAr600
DRAM: 128 MiB
Flash: 512 KiB
NAND: internal ecc 128 MiB
However, this just brings us back where we started: if you've been following along the thread, you may have noted that not everyone is lucky with getting a functional U-boot that can be interrupted.
Sadly, mine is no exception: after above output, any serial output simply dies.
I decided to finally take some time and dive into the U-Boot image to figure out why exactly this is happening.
It seems to happen right
after the early serial I/O is replaced by the more featured serial
drivers, but they seem to poke the same registers. Odd.
There's a little function call tucked away there, what does it do?
USB serial! But it would boot way too fast to allow us to enumerate the device, connect and interrupt! ... Right?
Well, Keysight seems to have thought of that as well: there's a sneaky little conditional waay later in the initialisation process:
This basically checks for pre-production silicon,
or the DDR driver being present at a specific address (the string is it is comparing to being present in p500_ddrdriver.bin).
I first tried loading the driver to appear at that expected address, but that didn't seem to work. Bummer, possibly the driver code is not relocatable.
Still, there's no reason we can't simply patch this conditional! Making the following changes in u-boot_image.bin from firmware 2.65:Offset 0x16100: 0c 00 00 1a -> 0c 00 00 ea ; bne -> b
Offset 0x18: 57 11 83 33 -> 4f 18 d7 f0 ; data checksum
Offset 0x4: 6c 2f de de -> 4e 52 6b 13 ; header checksum
Update: disregard the above! It seems that the DDR driver itself moves the string into that location (and presumably XLOADER, the normal loader after the DDR training sequence clears it),
so
no modifications are necessary!
Guess what suddenly appears on the USB side?
Welcome to minicom 2.8
OPTIONS:
Compiled on Oct 25 2021, 06:07:01.
Port /dev/tty.usbmodem00000001, 22:22:23
Press Meta-Z for help on special keys
p500>
Finally! So in summary, you can get a working U-Boot serial on these bad boys
without even opening the scope!
The short version:
1) Extract a Keysight 2.65 firmware update
2) Modify u-boot_image.img as per the instructions above3) Power up the scope while using a tool to hold down the button labeled "CAL" on the back
4) Connect to the scope USB port
5) Use the attached spearload program or ST's own flasher (linked above) to load p500_ddrdriver.bin and the modified u-boot_image.img
6) Enjoy your fresh USB serial, no functioning NAND required!
And since it's bootROM functionality, they can't patch this one out from existing products.