The other day I was looking at my RTB2004 and wondering what makes it tick. Given the availability of fully-optioned scopes with the COM4 bundle when it was launched, it seems to not hold a lot of interest for people to scrutinize its innards.
So, I took it apart and dug in to tease out its secrets. It is important to note that I am not focused on "hacking" licenses or anything like that. My interest is mostly in learning how it ticks.
With that out of the way, there are 3 prominent debug connectors on the bottom of the mainboard. There is a 4-pin white connector, a 10-pin white connector, and a special 12-pin red connector.
The 4-pin seems to have a 115.2kbps UART on it. It spits out unintelligible binary data immediately on boot.
The 12-pin red connector (helpfully labeled) appears to be JTAG for 2 Altera Cyclone V FPGA device instances according to openOCD.
The 10-pin white connector is the one I focused my efforts on. It is labeled HPS. This is for the Cyclone V's HPS (Dual core Arm Cortex A9 processor) that is built into their Cyclone V FPGA's, and is the primary processor that handles the UI.
Using this minimal OpenOCD config, I can get access to read/write memory, set breakpoints and watchpoints etc:
source [find interface/jlink.cfg]
reset_config trst_and_srst
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME fpgasoc
}
if { [info exists DAP_TAPID] } {
set _DAP_TAPID $DAP_TAPID
} else {
set _DAP_TAPID 0x4ba00477
}
jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x01 -irmask 0x0f -expected-id $_DAP_TAPID
adapter_khz 4000
set _TARGETNAME1 $_CHIPNAME.cpu.0
target create $_TARGETNAME1 cortex_a -chain-position $_CHIPNAME.dap -endian little -coreid 0 -dbgbase 0x80110000
init
cortex_a dbginit
I started by examining memory dumps using OpenOCD's "dump_image" command. The memory configuration seems to put main SDRAM at memory address 0x10000000, and the CycloneV HPS memory mapping shows on-chip RAM @ 0xFFFF0000. The internal Altera Bootrom is @ 0xFFFD0000.
Access to memory is all well and good, but the contents of NAND flash would be even better. Inte'ls docs on the CycloneV HPS (
https://www.intel.com/content/www/us/en/programmable/hps/cyclone-v/hps.html#topic/sfo1410068585834.html) give detailed information on the I/O memory mapping of the NAND controller (0xFFB80000 for control, FFB90000 for data), and with openOCD it is possible to read/write these registers directly (we don't have a driver).
The NAND Flash is visible on the PCB, but just to verify functionality of the NAND controller while the CPU is halted, we can check appropriate registers with OpenOCD:
Doing some binary math, we can build and write a command to disable DMA on the NAND controller (necessary for our commands), select the first block and page, and read the first 16 words to verify we are getting good data.
With the particular command we are sending to the controller, it opens a page-size (2048 bytes) window @ 0xFFB90010 starting at the selected block/page. To get the full page we can just use openOCD's dump_image again, then select the next block/page and so forth. There are 4096 blocks with 64 pages per block with 2048 bytes per page.
A little scripting and 24hrs later (JTAG is SLOW) and you have a 512M NAND image.
binwalk returns a TON of images and files, some of the most interesting being the ELF binary executables, and the uBoot image:
The uboot image (via strings) has some interesting references to "MesOS" and appears to be an emergency boot image with debug capabilities:
[string] Writes a string.
<adr> <n> Loads n-bytes (binary) at <adr> in memory.
<src_adr> <n> <dst_adr> Copys n-bytes memory from <src_adr> to <dst_adr>.
[<form> [<adr1> [<adr2>]]] Displays memory at <adr1> to <adr2> with <form> (1, 2, 4 Byte).
<adr1> <adr2> [<pattern>] Testing memory from <adr1> to <adr2> with <pattern> and !<pattern> (def: 0x55555555).
<adr> <value> <size> Change memory at <adr> at <size> (1, 2, 4 Byte) to <value>.
<src_adr> <n> <dst_adr> Copys n-bytes memory from RAM to NAND-Flash (<dst_adr> blockaligned!)
<src_adr> <n> <dst_adr> Copys n-bytes memory from NAND-Flash to RAM (<src_adr> blockaligned!)
<dst_adr> <n> <value> Fills n-bytes in NAND-Flash with <value> (<dst_adr> blockaligned!)
<log_adr> [<dst_adr>] [<n>] Load and exec programm from <log_ adr> SD-Card/Nand at dst_adr ) with n-Byte (def: 0x73f33000 0x00120000 0x20000).
<adr> Start decrypted Update loaded at <adr>.
[<adr>] Quits 'MonDeb' and starts execution at <adr> (def: restart).
[<src_adr> [<n>]] Update Monitor from RAM with <src_adr> (def.: 0x0c000000) and <n> Bytes (def.: 0x10000) AND REBOOT!!!
Quits 'MonDeb' and reboot at 0x0.
Quits 'MonDeb' and reboot at 0x0 too.
Displays the version of 'MonDeb'.
Displays the detailed version of 'MonDeb'.
Displays this short help.
Displays this short help too.
MonDeb>Quitting
Version:
Monitor & Debugger for MesOS
Hardware: CycloneVSoC
Version:
Date: Oct 6 2016 16:40:22
The first ELF binary is ~2.2MB appears to be a firmware updater:
FWUPDATE
SERVICE
NVRAM
PWFUSB
OCFUSB
FUSB
TEST
DIAGNOSTIC
Please attach a USB flash drive containing a firmware update.
Abort!
Update failed!
Checksum incorrect!
Loading file info ... done.
No file found!
Loading file ...
The checksum of the firmware update is correct.
done.
Running update ... ! DO NOT SWITCH OFF THE DEVICE !
Reset internal memories ...
Update file OK.
Searching, please wait ...
USB flash drive ready.
File search starts in %i seconds.
The second one is ~20MB and appears to be the main binary. These are all static, stripped binaries with no relocations. The RTB2004 runs binaries bare-metal without an actual Operating system. This explains why it boots so quickly. You can see references to various memory areas via readelf, including .fpga_ram, which jives with the CycloneV HPS docs (0xc0000000 is the shared FPGA-HPS memory region).
I'm actually pretty impressed with what R&S has done here. Other vendors build on top of a pre-made OS. They seem to have developed their application for bare-metal and implemented it pretty efficiently. So far the most interesting stuff I have found reference a "textInit" file or folder on USB storage, but I haven't yet figured out if I can use this for something: