Skip to content
J. Neuschäfer edited this page Jan 25, 2026 · 12 revisions

I recently (2026-01-24) picked up a Sky-branded Roku 3 set-top box.

picture of the black Roku 3 device with 'sky' written on it, power supply attached picture of testpoints with labels

Debug port

photo of digital oscilloscope with blocky waveform

The underside has a ring of rubber, so I felt for holes in the plastic beneath the rubber. I found three screws (as expected), and one debug port: a 2x10 array of test points, all of which are labelled.

I probed around and found an interesting signal on TP13.

The signal had 1.8V of amplitude, a regular and pretty square-like waveform, and a bit rate of about 6 per 50 µs, which comes out to 120000 baud, close enough to the typical 115200.

Additional photos: rubber feet exposing the debug port, probe attached to TP13

Boot log

Thanks to the Glasgow Interface Explorer's level shifters, I could faily easily capture the boot log:

boot log
********************************************************************************
CAPRI Loader (version = 0.2) started. Built date: Aug 31 2012 Time 17:21:35
********************************************************************************
+bootldr_flash_init
NAND Page Size: 2048, 64
Loading image!
Attempting SDCard_Load.
reset the host controller, status 0x2
reset the host controller, status 0x3
CBOOT_Flash_init failed.
reset the host controller, status 0x3
reset the host controller, status 0x3
CBOOT_Flash_init failed.
SDCard_Load: 1
p1 starts at 16
p2 starts at 400
ver: 5, 6
Reading: 209
Checking: 427104
hash: 97 54 4a 90 f3 57 12 01 c3 c5 91 d3 13 3d dd 07 ff 0e e4 27 
Image valid.

********************************************************************************
CAPRI Preuboot (version = 0.1) started. Built date: Mar 30 2021 Time 13:05:47 (29320)(99500)
********************************************************************************
OTP h/w initialized successfully
in[0] = 7004fa76
in[1] = 78a6baf9
in[2] = 088db2ce
in[3] = 01647174
in[0] = 00000000
in[1] = 11111111
in[2] = 22222222
in[3] = 33333333


U-Boot 2011.06 (Mar 30 2021 - 13:05:55 UTC) - bcm11130_roku_austin

I2C:   ready
DRAM:  384 MiB
Relocation Offset is: 0x18236000
NAND:  ReadConfigValid: valid configuration

NAND 8 bit, ECC enabled
ID 98DA901576140300
banks 1
bank size 256 MB
page size 2 KB
block size 128 KB
aux data size 8 bytes
used oob bytes 64/64
main data ecc 8/512
aux data ecc 0/8
timing_select 2
timing mode 4
NAND read of geometry page succeeded
NAND: Remapping Bad Blocks:
NAND: Remapping Active partition using BBT 0x031e1000
block_map:
[1]1 
256 MiB
MMC:   KONA SD/MMC: 0, KONA SD/MMC: 1
secure; no flashIn:    serial
Out:   serial
Err:   serial
Card did not respond to voltage select!
MMC init failed
Auto-detected LDO daughtercard

CPU Info:
    Freq ID  =    7
    Cpu freq =  897 MHz
    AXI freq =  299 MHz (Cpu freq divided by 3)
    ndiv_int=69 pdiv=1 mdiv=2 pl310_div=3

Setting L2 MMU table for boot ROM -- not set in SWDEV mode
Core 1 patch function addr: 0x9fe46774
Core 1 patch function end addr: 0x9fe467b0
Core 1 patch SRAM loc: 0x3404bf00
   ******************
   Type: DDR3
   Jedec: DDR3-800E
      CL: 6
      CWL: 5
      WR: 6
   Chip Width : 16 bits
   Bus Width : 32 bits
   Rank : Single
   Each Chip Size : 2Gb
   Total Bytes: 0 MB
   Clock Speed: 399999994 Hz
   ******************
mtdparts variable not set, see 'help mtdparts'
mtdparts variable not set, see 'help mtdparts'
Application image detected
check image in partition 0
Partition 0: Verify uimage: Success
Partition 0: Verify firmware: Success
VC4 raw image detected
Enabling VC4 JTAG
Assigning GPIO CAM1_PWDN (8) to VideoCore as an OUTPUT.
Booting VideoCore at 0xc0000200.
Booted VC ok!
partition 0: OK
custom_pkg info: This file is 3rdParty/custom_pkg/austin/skyd/common/boot/info

booting kernel
Application image detected
Broadcom BCM11140 Ethernet driver 0.1
port 0 PHY ID: 0x0143, 0xBC31
BCM5241 has no required initialziation
bcm11140_eth-0
## Booting kernel from Legacy Image at 9f54cd28 ...
   Image Name:   Linux-3.0.82-grsec
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3759088 Bytes = 3.6 MiB
   Load Address: 88008000
   Entry Point:  88008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK
loadaddrstr = '9fea08dc' loadaddr=0x9fea08dc
Setting up dt-blob tag ...@0x880001ac from 0x9fea08dc
dt-blob size: 5361 bytes
Done dt-blob tag, 0x880016a8

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
66666666666666666666666666666666666666666666666666666666666666666[...]

It starts with a "CAPRI Loader" and a "CAPRI Preuboot", which seems to initialize some PLL or something (potentially for the DRAM controller). Then, U-Boot is started, reporting 384 MiB of RAM (out of the 512 one could expect - the board has two RAM chips of 2 Gbit each). Quite nonchalantly it announces: Enabling VC4 JTAG and Booting VideoCore at 0xc0000200.

The Broadcom VideoCore 4 is also the SoC family used in Raspberry Pis, but this is a different SoC, the BCM11130.

Finally U-Boot loads Linux. There's no explicit indication that one could interrupt the boot flow.

After Linux is loaded, it keeps printing 6, about 30 KiB of it until I aborted the capture. The leading theory is that they patched the UART driver to always print 6 instead of whatever character should actually be printed. I guess they don't want curious eyes on their digital content distribution system.

Some differences can be observed when the box is booted with a µSD card inserted
--- boot.log	2026-01-23 23:28:39.503777445 +0100
+++ boot-sd.log	2026-01-24 19:12:10.753524834 +0100
@@ -1,4 +1,4 @@
-ÿÿ
+ÿ
 ********************************************************************************
 CAPRI Loader (version = 0.2) started. Built date: Aug 31 2012 Time 17:21:35
 ********************************************************************************
@@ -7,12 +7,8 @@
 Loading image!
 Attempting SDCard_Load.
 reset the host controller, status 0x2
-reset the host controller, status 0x3
-CBOOT_Flash_init failed.
-reset the host controller, status 0x3
-reset the host controller, status 0x3
-CBOOT_Flash_init failed.
-SDCard_Load: 1
+Power setting offset=0x28, value=0xf00
+SDCard_Load: 3
 p1 starts at 16
 p2 starts at 400
 ver: 5, 6
@@ -64,8 +60,6 @@
 secure; no flashIn:    serial
 Out:   serial
 Err:   serial
-Card did not respond to voltage select!
-MMC init failed
 Auto-detected LDO daughtercard
 
 CPU Info:

Considering the prospect of a JTAG port, I soldered the whole debug connector.

Photos: after soldering one row and after soldering everything.

JTAG

flying header with JTAG signals and UART TX attached

Glasgow's JTAG applets quickly found the JTAG pinout (jtag-pinout) and told me what it is (jtag-probe, arm-debug):

Glasgow detection logs
$ glasgow run jtag-probe -V A=1.80,B=1.80 --tck A4 --tms A7 --tdi A6 --tdo A3 --trst B7
I: g.hardware.device: generating bitstream ID bd88e1d25e2999bfbafc94c7719e710e
I: g.hardware.assembly: port A voltage set to 1.8 V
I: g.hardware.assembly: port B voltage set to 1.8 V
I: g.cli: running handler for applet 'jtag-probe'
I: g.applet.interface.jtag_probe: shifted 32-bit DR=<11101110001000000000010111010010>
I: g.applet.interface.jtag_probe: shifted 4-bit IR=<1000>
I: g.applet.interface.jtag_probe: discovered 1 TAPs
I: g.applet.interface.jtag_probe: TAP #0: IR[4] IDCODE=0x4ba00477
I: g.applet.interface.jtag_probe: manufacturer=0x23b (ARM Ltd) part=0xba00 version=0x4

$ glasgow run debug-arm -V A=1.80,B=1.80 --tck A4 --tms A7 --tdi A6 --tdo A3 --trst B7
W: g.applet.debug.arm.jtag: applet is PREVIEW QUALITY and may CORRUPT DATA
I: g.hardware.device: device already has bitstream ID bd88e1d25e2999bfbafc94c7719e710e
I: g.hardware.assembly: port A voltage set to 1.8 V
I: g.hardware.assembly: port B voltage set to 1.8 V
I: g.cli: running handler for applet 'debug-arm'
I: g.applet.debug.arm.jtag: AP #0: IDR=0x44770001
I: g.applet.debug.arm.jtag: designer=0x23b (ARM Ltd) class=0x8 (MEM-AP) type=0x1 (unknown) variant=0x0 revision=0x4
I: g.applet.debug.arm.jtag: AP #1: IDR=0x24770002
I: g.applet.debug.arm.jtag: designer=0x23b (ARM Ltd) class=0x8 (MEM-AP) type=0x2 (unknown) variant=0x0 revision=0x2
I: g.applet.debug.arm.jtag: AP #2: IDR=0x14760010
I: g.applet.debug.arm.jtag: designer=0x23b (ARM Ltd) class=0x0 (none) type=0x0 (unknown) variant=0x1 revision=0x1

I initially expected to find the barely-documented VPU JTAG interface, but to my pleasant surprise it's a relatively normal ARM JTAG (IDCODE=0x4ba00477), exposing two MEM-APs and one JTAG-AP:

AP IDR class type comments
#0 0x44770001 8, MEM-AP 1, AHB main memory access
#1 0x24770002 8, MEM-AP 2, APB supposedly Coresight Private Peripheral Bus
#2 0x14760010 0, none 0, JTAG-AP OpenOCD complains about missing dbgbase

I set up Glasgow to connect to the UART and the JTAG port at the same time:

glasgow multi jtag-openocd -V 1.8 --tck A4 --tms A7 --tdi A6 --tdo A3 --trst B7 tcp:localhost:9999 \
           ++ uart --rx A0 socket tcp:localhost:2222

Thanks to a blogpost on starlabs.sg, I got some info out of OpenOCD.

OpenOCD config and output

config:

gdb_port

adapter driver remote_bitbang
remote_bitbang port 9999
remote_bitbang host localhost
#remote_bitbang use_remote_sleep on
adapter speed 10

set _CHIPNAME bcm11130

reset_config srst_only

jtag newtap $_CHIPNAME cpu -expected-id 0x4ba00477 -irlen 4
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
$_CHIPNAME.dap apcsw 0x200000

target create $_CHIPNAME.ahb mem_ap -dap $_CHIPNAME.dap -ap-num 0
target create $_CHIPNAME.apb mem_ap -dap $_CHIPNAME.dap -ap-num 1
target create $_CHIPNAME.cpu cortex_a -dap $_CHIPNAME.dap -ap-num 2
#target create $_CHIPNAME.cpu cortex_a -dap $_CHIPNAME.dap -coreid 0 -dbgbase 0x3fe12000
init

targets $_CHIPNAME.ahb

info about APs:

Open On-Chip Debugger
> dap info 0
AP # 0x0
		AP ID register 0x44770001
		Type is MEM-AP AHB3
MEM-AP BASE 0xffffffff
		No ROM table present

> dap info 1
JTAG-DP STICKY ERROR
AP # 0x1
		AP ID register 0x24770002
		Type is MEM-AP APB2 or APB3
MEM-AP BASE 0x80000000
		ROM table in legacy format
		Component base address 0x80000000
		Can't read component, the corresponding core might be turned off

> dap info 2
AP # 0x2
		AP ID register 0x14760010
		Type is JTAG-AP

>

Unfortunately, any reads from AP #0 fail with JTAG-DP STICKY ERROR.

Further research

  • Finding UART RX and possibly interrupting the boot flow
  • diving into ARM ADIv5 to better understand the problems

Clone this wiki locally