Skip to content

Instantly share code, notes, and snippets.

@throwaway96
Last active November 27, 2024 20:39
Show Gist options
  • Save throwaway96/827ff726981cc2cbc46a22a2ad7337a1 to your computer and use it in GitHub Desktop.
Save throwaway96/827ff726981cc2cbc46a22a2ad7337a1 to your computer and use it in GitHub Desktop.
Enabling debug and getting root on LG webOS by modifying NVM

Warnings

What you do with this information is your own responsibility. If you brick your TV trying this, it's not my fault. You should probably have some electronics experience if you want to attempt this.

This is going to involve opening your TV and attaching wires to the pins of an integrated circuit. If you're not comfortable with that, this is not for you.

This document is a work in progress.

debugstatus

LG TVs since at least the era of NetCast and "Global Platform" (webOS predecessors) have had the notion of a debug level, generally called "debugstatus". There are three modes: DEBUG, EVENT, and RELEASE. TVs normally operate in RELEASE mode. DEBUG mode enables a variety of logging and other debugging features in webOS, including access to the bootloader console and debug menus via serial. EVENT is similar to DEBUG, although it may not enable as much logging and has other relatively minor differences.

NVM

In older versions of webOS, debugstatus is stored in what LG calls "NVM" alongside a bunch of other configuration data, such as the baud rate for serial communications. You can find the relevant structures and enumerations in LG's GPL packages. Of note:

  • debugstatus on webOS: DEBUG is 3, EVENT is 4, and RELEASE is 5

    debug level value (webOS) value (NetCast/GP)
    DEBUG_LEVEL 3 0
    EVENT_LEVEL 4 1
    RELEASE_LEVEL 5 2

    From lg_modeldef.h

  • baud rate: 2400 is 0, 9600 is 2, 115200 is 7

    baud rate value
    2400 0
    4800 1
    9600 2
    14400 3
    19200 4
    38400 5
    57600 6
    115200 7
    460800 8

    SYS_BAUDRATE_T from cmnio_type.h

Although I've seen a default baud rate of 115200 in bootloader code, in practice the default seems to be 9600.

In all the cases I've encountered on webOS, debugstatus is a single byte at offset 0x1a1 in NVM. I'll use 0x1a1 throughout this document, but it may be different for your model. The best way of determining the correct offset is reverse engineering your bootloader (or programs that access NVM such as RELEASE), but the GPL package for your TV model should also provide the necessary information (except for LX SoCs, since lxboot is not open source). After dumping the contents of the EEPROM, you should verify that the structure matches your expectations.

History

Before webOS 5 (released on 2020 models), LG stored NVM in an I²C EEPROM IC. NVM is entirely unencrypted on webOS 3.5 (2017) models. In webOS 4.0 (2018), LG started encrypting debugstatus in NVM, although other config settings remained accessible. In webOS 4.5 (2019), they attempted to obfuscate debugstatus a bit by calling it "Doption". With webOS 5 (2020), NVM was removed and replaced by "bootdb", which is stored in an encrypted eMMC partition named dbboot.

ICs

The ICs I've seen being used for NVM are usually 256Kbit (32Kbyte) in SO-8 packages. Sometimes larger EEPROMs up to 1Mbit are used, but these seem to be mostly on less mainstream products. You may also find I²C EEPROM ICs (potentially smaller ones like 24C08 or 24C02) for HDMI stuff (EDID), which are not relevant here.

Rohm BR24G256F-3

A "4G25" marking (with a lot number underneath) indicates a Rohm BR24G256F-3 (datasheet). (There is also a -5 part supporting 1MHz operation and more write cycles that LG sometimes uses in more recent models. The differences shouldn't matter here.)

EEPROM IC marked "4G25"
The NVM EEPROM IC on a 43LJ5500-UA board (webOS 3.5; 2017; MStar M2R SoC) marked 4G25.

FMD FT24C256A

The Fremont Micro Devices (FMD) FT24C256A-ESR (datasheet) is commonly used for NVM. It is marked "FT24C256A".

ST M24M01

The AN-WL100W main board stores NVM on a 1Mbit STMicroelectronics M24M01 (datasheet) EEPROM marked "24H01RP".

Atmel AT24C256C

The AT24C256C I²C EEPROM from Microchip (formerly Atmel) often appears in schematics as an alternative to the Rohm part, and I have seen it on non-webOS boards. Like the others, it's in an SOIC-8 package. The key markings for identifying it are a first line starting with ATML (usually ATMLH followed by three numbers forming a date code) and a second line starting with 2EC. See the datasheet for more information on the markings.

Hardware Requirements

You'll need a test clip unless you want to solder wires directly to the EEPROM IC's leads or otherwise find a way to connect to the I²C bus. Mini-grabbers (random example) may work. The I²C bus may be brought out to an unpopulated connector footprint (or, if you're really lucky, an actual connector) somewhere. There are other devices on the board that use I²C, but I don't know whether they're on the same bus.

Test Clip

A SOIC-8/SOP-8 test clip, such as the Pomona 5250, fits over the IC and provides easy access to the pins. Note that there are much cheaper generic test clips available from the usual sources (e.g., eBay, Amazon, AliExpress).

test clip on 43LJ5500-UA
A cheap test clip on the NVM EEPROM IC of a 43LJ5500-UA board.

Programmer

Any device that speaks I²C can potentially work. For example, a board based on the WCH CH341A or FTDI FT2232H (e.g., FT2232H Mini-Module) should work. An FT232H-based board can work, but note that the pre-2020 version of the Adafruit FT232H Breakout only has a 5V power output pin (see Notes below), although the I/O voltage should be fine. A Bus Pirate should theoretically work, although I had trouble with a Bus Pirate v4; I was able to detect the EEPROM and dump its contents, but the data was corrupted. I switched to using a Raspberry Pi 3 (Model B+), which gave me fewer problems, and ultimately allowed me to sucessfully change debugstatus. I used pins 3 and 5 of the 40-pin header, which are SDA and SCL, respectively. These pins correspond to /dev/i2c-1 in Linux by default.

Serial

Once you have DEBUG, you'll need a way to communicate with one of the TV's serial interfaces: RS-232 on a DE-9 connector or 3.5mm jack (if present), a 3.3V UART, or USB to serial adapter. If you are using a PC, you can accomplish this with a USB to serial adapter. If you're going to use the UART, make sure your adapter is configured to use 3.3V. If you are using something like a Raspberry Pi, you may be able to connect directly to its UART pins, although I haven't tried this. If you want to go the USB to serial route on the TV side, you may need two USB to serial adapters, at least one of which is PL2303-based.

Notes

While the EEPROM ICs themselves will tolerate 5V, you'll be backpowering parts of the board that are expecting 3.3V, so make sure your I²C adapter uses 3.3V.

I²C is pretty tolerant of less-than-ideal connections, especially at the lower speeds in use here.

Apparently at least some models can boot with an invalid or entirely missing NVM EEPROM. (As far as debugstatus goes, it'll default to RELEASE.)

Modification

The general idea is to attach a test clip to the EEPROM IC and use some I²C master device to access it. Then you should:

  1. Back up contents of EEPROM. (You may want to do this multiple times and make sure you always get the same result.)
  2. Make sure the value at offset 0x1a1 is 5. (If it's not, and you're sure you dumped the EEPROM correctly, I'd like to hear about it.)
  3. Write 3 to 0x1a1.
  4. Read the contents of EEPROM.
  5. Make sure everything is the same as before except the byte at 0x1a1 being 3 instead of 5.

After DEBUG

Confirmation

First, you should check that you have DEBUG. You should see this in the Instart menu:
Instart with DEBUG

There are several ways to launch the Instart menu. The intended method is probably via IR (e.g., with a service remote or IR blaster), but you can also use a Luna request. My super hacky SSAP client can send the necessary request. This predefined request should work on webOS 3.0+:
predefined Instart request

The password is almost certainly 0413.
password prompt

Enabling Serial Access

You can use the Instart menu to enable serial access: in System 1 set Baudrate to something sensible (like 115200), and in System 2, set RS-232C Control to On.

Serial

After enabling serial access, you'll need to connect to a serial port. The baud rate will be what you set earlier. Some models have RS-232 on a DE-9 connector, which may work, but most will have a 3.3V UART edge connector (and/or a UART on a 4-pin wafer connector). A potentially easier option is using two USB to serial adapters back-to-back, ultimately connecting from the TV's USB port to one on a PC. You can also connect from any of these options (except RS-232) to a Raspberry Pi via the appropriate pins in the P1 (GPIO) header.

You'll need to connect the GND, RX, and TX pins. (Don't connect anything to +3V3.) Connect the two GNDs first. The RX and TX pins should probably be swapped (i.e., RX on the TV to TX on your serial adapter and vice versa).

Edge Connector

The pinout of the edge connector is:

  1. +3V3
  2. RX
  3. GND
  4. TX

edge connector
UART edge connector.

On the boards I've seen, each data line has a 100Ω series resistor providing a bit of protection, but after that they probably run straight to the SoC, so be careful. The RX line is pulled up to 3.3V with a 10kΩ resistor.

The dimensions of the edge connector happen to match those of a SOIC-8 test clip. With a bit of padding (such as cardboard) underneath the board, a test clip will stay on well enough. If you can't get that to work, it's possible to solder wires to the test pads on the bottom of the board. There's usually a group of four with the same signals as the edge connector somewhere nearby. I'm not sure how they're arranged, so check what pin each one corresponds to with a multimeter.

USB to Serial

You can also use a USB to serial device in one of the TV's USB ports, although only certain types will work. Your best bet is a PL2303-based adapter. Some LG TVs have been known to specifically check for an Aten UC232A, but I haven't had any problems with generic (even possibly counterfeit) PL2303 devices.

Using a USB to serial adapter connected to the TV means you'll likely need another one to connect to your PC. Make sure you remember to swap TX and RX: TX on one goes to RX on the other. Connect the GND pins, but don't connect the VCC/+3V3 pins.

Debug Menu

NOTE: Some LX SoCs prohibit access to certain debug menu commands—including those that open a shell—without AccessUSB authentication. I've also encountered this on an MStar LM15U signage board. These restrictions may be more common on signage (and other commercial) models. There are likely workarounds, but I'm currently unable to help with this.

From the serial debug menu you can spawn a root shell. Press F9 to open the menu, and use the sh command to start the shell. (On newer models, you may just have to press s for shell access. You can usually press h for a list of available keys.)

Root Shell

Once you have the root shell, you need to use it to achieve persistent root access. First, force-enable dev mode by creating a directory named /var/luna/preferences/devmode_enabled. You may have to remove the existing file with that name. Make sure the LG Developer Mode app is uninstalled, or it will cause problems. Once you've created the devmode_enabled directory, reboot so that processes such as the app installer know that dev mode is enabled.

With dev mode enabled, you can install Homebrew Channel. Use the following commands to download and install it:

curl -L -o /home/root/hb.ipk https://github.com/webosbrew/webos-homebrew-channel/releases/download/v0.6.3/org.webosbrew.hbchannel_0.6.3_all.ipk

luna-send-pub -i 'luna://com.webos.appInstallService/dev/install' '{"id":"com.ares.defaultName","ipkUrl":"/home/root/hb.ipk","subscribe":true}'

You'll have to terminate luna-send-pub with control+C when it's done.

Once Homebrew Channel is installed, run its elevation script from the root shell:

/media/developer/apps/usr/palm/services/org.webosbrew.hbchannel.service/elevate-service

Homebrew Channel

General information about Homebrew Channel and root can be found in my crashd guide.

I recommend you block updates using the Homebrew Channel settings (although this is not totally effective). I also prefer to disable telnet, enable SSH, and set up an SSH key.

Older Platforms

Remember that on NetCast and Global Platform, DEBUG is 0 and RELEASE is 2, so you'd be changing 2 to 0.

The board in the AN-WL100W wireless transmitter box has an MStar Saturn7 SoC that runs Global Platform 2 (GP2). The general structure of NVM data is similar to more modern models, but it includes fewer fields. (However, it is on a 1 megabit EEPROM, which probably means it stores unknown other data.) There doesn't seem to be a baud rate setting in NVM. Its debugstatus byte appears to be at offset 0x185, and would be changed from 2 to 0 for DEBUG. I still haven't been able to get any further access, though.

Resources

@Denisuu
Copy link

Denisuu commented Jul 2, 2024

@febman123

I posted on the WebOS forum, but there hasn't been much response. It seems either no one knows the answer or the menu doesn't exist, which makes sense since SSAP-web says it wasn't found.

People probably don't even understand why anyone would want to root a 10-year-old TV in the first place, haha.

WebOS Forum Post: Does the 'In Start' menu exist on WebOS 1.4

@throwaway96
Copy link
Author

@Denisuu

On webOS 1 and 2, Instart and ezadj are in com.webos.app.livetv rather than com.webos.app.factorywin.

@Denisuu
Copy link

Denisuu commented Jul 9, 2024

@Denisuu

On webOS 1 and 2, Instart and ezadj are in com.webos.app.livetv rather than com.webos.app.factorywin.

That worked thanks! I just did a find and replace on factorywin to livetv in the index.html file of your SSAP-Client

@krei-se
Copy link

krei-se commented Jul 25, 2024

Thanks for this, i had plenty of fun and learned a lot!! I used a raspberry pi pico with this firmware:

https://github.com/Nicolai-Electronics/rp2040-i2c-interface
you get a /dev/i2c-x

dumping and restoring was done with this little tool: https://gist.github.com/Zibri/cf8ac0b311301aeeaa8910c7da824bff which is easily compiled and worked flawlessly.

Model: 49UF8509 - WebOS 2.0

No Kodi though, but that's fine - I LOVE IT!!

@Denisuu
Copy link

Denisuu commented Jul 25, 2024

Model: 49UF8509 - WebOS 2.0

No Kodi though, but that's fine - I LOVE IT!!

I also loved the process of obtaining root access with this tutorial, it was very educational for me, although it's not very useful on such an old TV, except for PPLGPwn. I also wanted to install Kodi, but it doesn't even boot.

I have the LG AKB73756571 remote. Since your TV is from 2015 I was wondering if it's the same remote and if LG Input Hook works. It doesn't seem to work for me on WebOS 1.4 (2014)

@krei-se
Copy link

krei-se commented Jul 26, 2024

Denisuu, i don't want to spam this thread too much, but after a day of testing different apps i cannot much else but retroarch and the adfree youtube (0.3.2 especially compiled for webos1/2). As a plus, the inbuilt pulseaudio has module-tunnel-sink available, so i can stream my mpd to it.

neither input hook nor the steam client, etc. work - most bug out failing after "elevating homebrew service".

As i am mainly interested in developing something on my own thats fine for now. I will keep the TV until it breaks, as it's passive 3D and was hard to get.

@nielsman
Copy link

Anyone able to help me? I tried to read eeprom on two different LG TVs. One with WebOS 2.xx, which has the 4G25-Chip and one TV with WebOS 3.4x, which has the Atmel Chip. On both eeprom-Dumps i just found the 1a1 byte to be empty ("FF"). Which is super odd to me. I read out the eeprom with python script on a RPi3... i really feel dumb, but can someone who had succesfully read out the eeprom provide me with a detailed instruction how to read out properly and how to change the regarding byte on eeprom? Im nota total beginner, but never had to do a task like this and already tried like 50 times, but always end up finding "FF" whereas it should be "05"... i think it wont change anything to the good if i write 03 to this empty byte...?

@nielsman
Copy link

nielsman commented Nov 17, 2024

Anyone able to help me? I tried to read eeprom on two different LG TVs. One with WebOS 2.xx, which has the 4G25-Chip and one TV with WebOS 3.4x, which has the Atmel Chip. On both eeprom-Dumps i just found the 1a1 byte to be empty ("FF"). Which is super odd to me. I read out the eeprom with python script on a RPi3... i really feel dumb, but can someone who had succesfully read out the eeprom provide me with a detailed instruction how to read out properly and how to change the regarding byte on eeprom? Im nota total beginner, but never had to do a task like this and already tried like 50 times, but always end up finding "FF" whereas it should be "05"... i think it wont change anything to the good if i write 03 to this empty byte...?

managed to swap the byte on the older one of my TVs, which is on WebOS 2.xx - Also i can access the Instart-Menu (using a Logitech Harmony Remote to get the additional "In-Start" Button. But now i'm stuck again... i want to access service 1 and service 2 submenu to change baudrate and activate serial access... but whatever i try, after pressing downwards two times to get to the regarding menupoints, the whole menu seems to freeze, so i cant access service1 or 2... and i cant even go back. only help is pushing "instart"-button again, entering the PIN again and im back to In-Start Manu, but cant come down to the service1&2 menupoints again.... this is super weird. On my other TV with WebOS 3.4 (which i dont get to be in Debug-Mode) i can access instart and go down to those points without any problem, but that doesnt help much, as im not getting this device to debug-state in the first instance... this is SO frustrating.... help...?

@throwaway96
Copy link
Author

@nielsman

No idea why Instart isn't working. You can try accessing it over SSAP.

The RS232C and Baud Rate settings are stored in NVM. Baud Rate is one byte and should be at 0x98c; see guide for values. RS232C is also a single byte and should be at 0x2db; change it from 0 to 1.

@krei-se
Copy link

krei-se commented Nov 18, 2024

I had good luck with SSAP and the normal remote. Also my LG is one of the older ones with WebOS 2.xx so it is doable. In the service menus i noticed though that yes, you cannot hit the back buttons, so that is maybe related to the remote, but you can enter the menus once for the change to be made with the normal remote and if needed restart the TV and use SSAP again.

@nielsman
Copy link

nielsman commented Nov 18, 2024

@nielsman

No idea why Instart isn't working. You can try accessing it over SSAP.

The RS232C and Baud Rate settings are stored in NVM. Baud Rate is one byte and should be at 0x98c; see guide for values. RS232C is also a single byte and should be at 0x2db; change it from 0 to 1.

I tried using SSAP, same problem... directing down it will get stuck at Submenu "3. Power On/Off Status" - right before "System 1". I tried navigating upwards and had access via the other direction... 13, 12, 11, 10... I reached "System 2" submenu and can indeed confirm, that "RS-232C Control" was already turned on (which is odd, cause I did not change it, so I was expecting it to be turned off)...

Anyways, trying to navigate up one more sub-menu it gets stuck again, so I can't check on "4. System 1" to see and set the Baudrate. As the TV is already back on the wall and I can't access the Eeprom anymore, I can only try to check the dump I already got on my pc, to see what value is stored in the depending byte (0x98c). Wish me luck...

Isnt it odd, that I can't navigate to the system 1 submenu? Im wondering if it might have to do with a wrong programmed NVM (I messed around a lot yesterday, till I reached debug status..)?

EDIT: i checked yesterday's Dump and can indeed confirm, that 0x98c is set to "02" -> 9600... damn.
Also I checked 0x2db and yes its already set to "01"...

So do I really need to unmount, unscrew everything again to flash the dump again and set the baudrate to higher value? Or is there another alternative (as in-start seems to block me from touching this setting..)?

@nielsman
Copy link

...and next question, when I manage to get everything set up properly, will this adapter https://www.amazon.de/gp/product/B08T24NML9/ and my RPi3 be the right hardware to perform the next steps without physical access to the Mainboard? (only accessing the USB Ports of the TV)? Thank you so much, help is very much appreciated!

@throwaway96
Copy link
Author

@nielsman

Just use it at 9600 baud for now. It'll be slow, but once you install Homebrew Channel you'll be able to connect over the network.

For USB serial on the TV, you need something PL2303-based, like this: https://www.amazon.de/dp/B00MHJUMHI
Connect it to the UART pins on the Raspberry Pi.

@nielsman
Copy link

@nielsman

Just use it at 9600 baud for now. It'll be slow, but once you install Homebrew Channel you'll be able to connect over the network.

For USB serial on the TV, you need something PL2303-based, like this: https://www.amazon.de/dp/B00MHJUMHI Connect it to the UART pins on the Raspberry Pi.

Thanks for your reply! Will this one also do?
https://amzn.eu/d/imqd1sH

As the one you posted does have some weeks of delivery time… and I want to finish the project soon 😜

@throwaway96
Copy link
Author

@nielsman

Yes, as long as it's PL2303. It looks like the one I usually use.

@nielsman
Copy link

@nielsman

Yes, as long as it's PL2303. It looks like the one I usually use.

Thank you very much. Ordered two of these, just in case I won’t figure out how to do it with the Raspi. Can you help me a bit on what to do when I got the Raspi or PC hooked up via the adapter to the TV? I read about serial debug menu and root shell, but I’m confused what exactly to do next… terminal? Sorry I’m a noob, but I totally want to do it. 😃

@krei-se
Copy link

krei-se commented Nov 18, 2024

I started web os 2.x zero knowledge, so can walk you through it, but the serial console is after the big hurdles - you'll figure it out. Relax.

To add to that: 2 serial/usb adapters make it real easy. remember not to write to any ro/system partitions and don't expect much stuff to work on webos 2.x - in my case only youtube adfree older version works. I still plan to reroute the magic remote to my pc though, so the root console is noice for tinkerers.

@throwaway96
Copy link
Author

Once it's connected, try <break> x. (That's a break sequence followed by the x key.) See your terminal emulator's documentation for how to send break. (In PuTTY, it's in the menu.)

If you want to use function keys (F1–F12), make sure your terminal emulator is configured to send ESC[n~ sequences. (It's the default in PuTTY.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment