jtag flashing bcm6348 devices with a bus pirate and openocd

Having never used JTAG before I thought I'd see what I could do with my new Bus Pirate and one of the old ADSL routers I have lying around - ideally reading/writing to the flash. The v1 BT Home Hub is a Broadcom BCM6348-based device with 32MB RAM, that I'd previously added headers for the serial uart and replaced the bootloader with RedBoot and the OS with openwrt. You can see a small breakout with a TTL level converter and an FTDI uart<->USB on the right, and the Bus Pirate on the left in the picture above.

The JTAG pads are on the back of the board, behind the BCM6348; they are documented over on the openwrt wiki. I've soldered a short length of ribbon cable - held in place with a strip of duck tape to ease the mechanical stress on them.
As the v3 Bus Pirate doesn't have enough space for the openocd JTAG module in the stock build, I needed to flash the custom hex image I found here that has it compiled in.
The default install of openocd on Mint 20.04 doesn't support the Bus Pirate either, so it has to be built from source - remembering to add "--enable-buspirate" option:
./configure --enable-buspirate
make
sudo make install
Although openocd now detects the Bus Pirate, it needs a config (openocd.cfg) putting together so it knows it's dealing with a MIPS chip and where the flash lives. After much googling and trial and error I came up with this:
source [find interface/buspirate.cfg]
buspirate_port /dev/ttyUSB0
set _CHIPNAME bcm6348
jtag_nsrst_delay 100
jtag_ntrst_delay 100
reset_config trst_and_srst
jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id 0x0634817f
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME mips_m4k -endian big -chain-position $_TARGETNAME
# setup working area somewhere in RAM
#$_TARGETNAME configure -work-area-phys 0xa0600000 -work-area-size 0x20000
#$_TARGETNAME configure -work-area-phys 0xa0600000 -work-area-size 0x40000
# serial SPI capable flash
# flash bank <driver> <base> <size> <chip_width> <bus_width>
set _FLASHNAME $_CHIPNAME.flash
#4mb
#flash bank $_FLASHNAME cfi 0x1fc00000 0x00400000 2 2 $_TARGETNAME
#8MB
flash bank $_FLASHNAME cfi 0x1f800000 0x00800000 2 2 $_TARGETNAME
I'm sure it's still very incomplete as I can't inspect the state of registers. The important bits: halting the CPU, dumping memory to file and write to flash from a file seem to work though. In the openocd telnet shell - halting:
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> targets
TargetName Type Endian TapName State
-- ------------------ ---------- ------ ------------------ ------------
0* bcm6348.cpu mips_m4k big bcm6348.cpu running
> halt
target state: halted
target halted in MIPS32 mode due to debug-request, pc: 0x00000000
> targets
TargetName Type Endian TapName State
-- ------------------ ---------- ------ ------------------ ------------
0* bcm6348.cpu mips_m4k big bcm6348.cpu halted
Dumping the boot loader:
> dump_image bootloader 0x1fc00000 0x00020000
dumped 131072 bytes in 465.079559s (0.275 KiB/s)
Restoring the boot loader:
> flash write_image bootloader 0x1fc00000
No working memory available. Specify -work-area-phys to target.
not enough working area available(requested 140)
Programming at 0x1fc00000, count 0x00020000 bytes remaining
Programming at 0x1fc00100, count 0x0001ff00 bytes remaining
Programming at 0x1fc00200, count 0x0001fe00 bytes remaining
...
To final test, I zero'd out the first couple of K of the bootloader and cycled the power; device was now bricked. Nothing on the serial console and two of the LEDs wedged on. I used openocd to halt the CPU and then flash the bootloader back @ 0x1fc00000 - this took a couple of attempts and found the flash worked best when the CPU was halted as soon as possible after power on. When the flash was finished the device booted perfectly into RedBoot and then onto openwrt.

This is another BCM6348 based device, a BT Voyager 220V. Before attempting to install openwrt on it, I added the seven pin header to expose the JTAG pins and dumped the bootloader - just in case. Wasn't needed as it turned out as the CFE lets you flash openwrt images anyway.
