I got bored, so I hacked my TV
By Ricardo
That’s right. I was bored and wanted to play/automate some of my bedroom gear, so I decided to hack my TV. I’ve been giving updates on this Twitter thread in case this seems odly familiar:
So.. I've downloaded the firmware update for my old dumb (non-smart) TV.
— Ricardo 'Bug' G. S. (@debugweshell) August 29, 2020
It has httpd, telnetd, udhcpd on it.
Ok, you got my attention!
My TV is an old Sony Bravia KDL-40BX425 - a really good yet very simple full HD thing. It has only two HDMI ports (back in the day I might have said I would never use both), a bunch of analog stuff and USB. The last one can be used to play media (including the so new (back in the day) MKV format), as well as updating the firmware.
I’ve downloaded the firmware from Sony’s website and did some analysis on it. I actually got some pretty interesting stuff out of the damn thing, including some scripts and configuration. Some hardcoded network stuff made me believe that there was a change my TV could be hacked into the network. I’ll get to that later. Most of the stuff was pretty simple, but some extra details require data in the TV flash memory, so it didn’t go very far. I even tried connecting some USB Ethernet devices, but no luck. That didn’t surprise me much as the scripts seem to indicate a very limited number of kernel modules, and USB network support was not there.
So I’ve downloaded the schematics. Screw it, if we’re gonna get into this thing, let’s do it right! A bunch of stuff in the schematics caught my attention, but the first thing was the Ethernet interface!
I thought: well, there should be pads for a connector for that. So as long as all passives and ICs are installed, I should be able to wire something up, right? Let’s open it up!
Remember kids, opening up a TV can be very dangerous unless you know what you’re doing. Even in old LCD models like mine there’s still letal voltage inside of it!
That being said, opening it up was harder that I thought. Most likely due to it being old and crusty. Anyway, yeah, Ethernet was not going to work: pretty much everything around it was missing.
Since I was making a thread about this on Twitter, a fellow user gave me an idea (thank you!):
Time to open it up and look for UART
— e99 (@tuxuser360) August 29, 2020
Hm, UART… that could help. Let’s check the schematics:
That seems promising! Sure, the CN410 connector is missing, but the pads are still there.
That ended up yielding some good results, as I’ve managed to get boot messages from it at 115200 bps.
First milestone: internal UART access!
Ok, good. I now have two questions that I want answers:
- Does RX work? Can I write something to the port?
- What can I do with it?
The first one was gonna be hard without soldering. I was considering adding some electrical tape to hold the wires there for a few seconds just to check my idea, but that would be a bit dangerous as the power circuit is not far from that.
The second question is an important one. Do I really want to solder something on this board, risking damaging it as my soldering skills are terrible? What if, in the end, the port is useless for me?
A week has passed and I was always wondering about this. Today I decided to wonder a bit more, as I was trying to figure out how HDMI CEC works on my TV. Eventually I started just looking for RX and TX all over the schematics - you know, just in case. Then I’ve found this:
At first I thought the TV was using the CPU to access the VGA SCL and SDA pins, responsible for (as far as I could figure out) the DDC communcation. But that didn’t make much sense - that would mix with boot messages and it would be a mess. Then I googled the NC7SB1357P6X part, and lo and behold, it’s (basically) a switch!
Guess what, that circuit is actually switching the VGASDA# and VGASCL# (external) pins being the VGASDA and VGASCL internal pins and the UART port! Damn, that’s some sneaky hack! So yeah, in some weird and bizarre situation, the VGA pins 12 and 15 will end up being U0TX and U0RX, the CPU’s UART port.
Ok, now we have to figure out how to enable this. Using a scope I’ve found the U110 and U111 ICs and checked pin 6 (control input on the switch): both high. That means the VGA port pins are connected to the expected internal VGA ones, so no access to UART. My electronics skills aren’t great, but that seems some kind of pull-up with the VGA_PLUGPWR. Following it to its source, the control input signal comes from the Q103, a BC847C NPN transistor. So to make it low, I’ve gotta apply some voltage to its base, so the collector is connected to the emitter (or something like that - hey, I’m a coder!). Checked the transistor with the scope again and indeed, its base pin is low, so nothing is driving it. That pin is connected to what seems to be a pull-down and some nasty “OR” logic: either UART_SW or VGA11 can drive it. VGA11 is literally pin 11 on the TV’s VGA connector, so.. would that work? The plan:
- Apply voltage on pin 11 (VGA11)
- Drive Q103’s base pin high, driving its collector low
- Collector on low means pin 6 (control input) on U110 and U111 are also low
- Control input being low means pins 4 on both ICs are connected internally to pins 3 (B0), switching them to the UART
Applying 3.3v on VGA11 seems to do the trick: the scope quickly showed data on it once I turned the TV on. Nice! Adding the USB UART thingy and yup, data is coming through!
Second milestone: external UART access! No need to open the TV again!
Typing stuff on the terminal yields no return, but the boot process can be interrupted by pressing some key during the U-Boot phase:
By messing with the boot arguments I’ve managed to boot into the TV’s Linux system without running its init. Running it would kill the serial port, as it just blocks it there for some reason (still need to figure out how and why). By following the OS boot scripts I’ve managed to mount the flash partitions enough so I could access the files:
Yep, exactly what I wanted: a list of kernel modules this thing has. Hell yeah!
So let’s go back to what we’ve accomplished here:
- We figured out the “secret” VGA serial console
- We got access to the CPU’s UART through it
- We don’t have to keep opening the TV (it’s heavy and dusty)
- We found a way of interrupting the boot process and accessing its filesystem
The TV has USB, which means it shouldn’t be too hard to copy all this data into my computer so I can better analyze it. One of my (dumb) goals is to build my own kernel module for it. Not my first time trying to do this (it’s annoying if you don’t have the config), but if I manage to match the kernel version and flags for this system, I could slowly add extra USB device support, including USB Ethernet - as long as I can keep the same kernel. That could be interesting. This would most likely require permanent filesystem changes, but at this moment I’m not willing to do that - I personally want to avoid killing my TV.
Another idea would be booting a custom kernel image with all resouces I need, and possibly (in a random future) keeping it there. This would allow for way, way easier access to whatever I want. This could be very fun to do as well. The binary blobs and proprietary files would be annoying to deal (and share) though.
Anyway, now let’s go to bed as it’s almost 3 AM and I need to think how to proceed. We’ll see how this goes in the next weeks - hopefully well! Goodbye!