When I try to crack an embedded hardware I usually start from finding where the UART is so I can get a serial console, to identify its firmware, and to dump as much info as possible to help with later mainline open source integration.

Of course there would be missing UART header, or missing through-holes altogether so I had to jump wire sometimes. But surely as long as I can find some 3.3V stuffs with some expected behaviours during power cycles I can identify Tx and Rx.

A common factor that made these possible, is the fact that the vendor / designer also needed to debug the product themselves, so while those headers / holes / pads might be hard to find, their location and how the pinout is layed down, usually makes sense.

However, recently, as I were trying to bring RTLPlayground support to FG-8GT-1SX, I was bit by a wrong UART pinout in the problemetic board design.

This boils down to seemingly just 5 through-holes for a missing normal UART header with missing resistors:

The PCB has five unpopulated through-holes near the SoC, with a white rectangle surrouding them, labeled as J18 and a triangle points to the square shaped first pin.

This is where the “expected” UART header should be soldered at, with redundant 3V3 VCC, …

First I soldered a 1x5 pins 2.54mm header to fill the holes. Easy. But then as I tried to identity the pinout, I found Tx and Rx are 0V, which suggests something is missing:

… but also with missing 0Ω resistors between TX/RX and SoC, so simply soldering a header would not work. One need also add the missing resistors or solder the pads together, while making sure not connecting unrelated pads.

Numbered from the triangle, the header pinout is:

Position Signal GPIO Status
1 GND GND Internal
2 TX GPIO31 Unconnected
3 RX GPIO32 Unconnected
4 3V3 - Internal
5 3V3 - Internal

Not a big problem. Since there’re four pairs of resistor pads near the header, R1240, R1243, R1242 and R1241, and among them only two connect to the header, one to pin 2 and one to pin 3, and their near-SoC-side measured ~3.3V: the possibly Tx is ~3.3V steady with slight drop during power up, the possibly Rx is ~3.3V steady, it’s natural to consider them Tx and Rx. So I just soldered the pads together, which wires possibly Tx through R1240 and possibly Rx through R1242.

Resistor ID SoC Side Header Side
R1240 TX / GPIO31? Pin 2
R1243 3V3 -
R1242 RX / GPIO32? Pin 3
R1241 3V3 -

With a USB to UART converter connected and picocom started, I had logs but no input could be picked up. My first guess is that vendor disabled input on the stock firmware, so I just went on adding RTLPlayground support from firmware dump and reverse engineering, rather than vendor serial commands. But after switching to RTLPlayground there’s still no input.

The easy guess would be Rx was not configured correctly, so I started agents to waste more than a day to make a lot of revisions of firmware that I flash one after another to “fix” Rx init. The switch would hang, would have broken LED, would not even start. I had to just a cliper and flashrom quite a lot. But of course nothing worked.

Until I decided to stop all agents and myself trying and actually re-measure the electrical stuffs, and to compare them to what could be gotten on another switch from the same vendor on my hand, RY-4GT-2SX / FG-4GT-2SX_V2.0, and found the vendor firmware and RTLPlayground both take serial input there, and the Rx is ~3.2V steady. Back to FG-8GT-1SX and I found R1242 measured ~3.3V steady yet R1241 measured ~3.2V steady. So, that means the vendor wired stuffs wrong?

I still wouldn’t really believe such PCB could be made. As with sample PCB the vendor should’ve had header and resistors all soldered and verified stuffs through the serial console. No way they would make such mistake, right?

So here came my oscilloscope that I barely used. I measures the SoC side pin for the four resistor pads to capture their behaviour on boot: R1240 with pulses, R1243 with a flat line, R1242 with a flat line, R1241 with pulses. Hard to accept but the vendor did make a mistake!

This means the actual layout of resistor pads are:

There’re four resistor pads near the header.

Resistor ID SoC Side Header Side
R1240 TX / GPIO31 Pin 2
R1243 3V3 -
R1242 3V3 Pin 3
R1241 RX / GPIO32 -

With that layout, Tx is still simply

To get TX working, solder a 0Ω resistor between the pads for R1240 or solder them together.

But I had to be really creative to connect Rx to Pin3

For RX However, the designer certainly made a mistake, as the SoC-side lines to the resistor expected for Rx (R1242) and 3V3 (R1241) are swapped. For RX to work, the R1241 SoC side and R1242 header side shall be connected, so either:

  • Solder: R1241 SoC side -> R1241 header side -> R1242 header side
  • Jump wire: R1241 SoC side -> R1242 header side

Apparently the vendor either didn’t verify the serial in their sample PCB, or they just considered a serial with output log as OK, not verifying input.

The whole wasted day tells one thing: always doubt UART pinout; multimeter is not enough; use oscilloscope to confirm.