Repurposing boring eInk electronic shelf labels / price tags into useful photo frames / status displays, with blackjack and hookers custom firmware and greyscale! Quick video (partially sped up) here: . There you can see association, image download with progress bar, and image display in greyscale + yellow.
They have been appearing in stores since the early 2000s, but have really become prevalent in the last five to seven years! Also known as ESL (Electronic Shelf Labels), they basically allow the store to change prices dynamically as they see fit, without having to send a person out with a new printed piece of paper to place unto the shelf. The extra benefits include ability to show off more of the product's features (bullet point lists often shown on large price tags), change that shown feature list (advertise differently based on current day/month/etc), and use colours (last five years brought red and yellows to the previously only-black-and-white electronic shelf labels). There is a lot more marketing fluff about why ESLs are cool, and you can read all about it on your own time!
Most of the current-generation ESLs are updated wirelessly, using some sort of a custom protocol. The company "Pricer" distinguishes themselves here, using InfraRed instead, making their devices completely useless for us. InfraRed is dead, guys, get over it! Anyways, all of the protocols are of cource not documented, so we're on our own.
Most of the current-generation ESLs use eInk displays (aka: EPD - electrophoretic displays). Why? The main selling point is power. eInk uses none while it is showing a static image. You've likely seen a screen of this type last you looked at an eBook reader, like a Kindle. They do need power to change their contents (quite a lot actually), and are a giant pain in the rear to work with in general, but more on that later. Having a screen that needs no power to show prices, combined with the fact that prices do not change often, leads to good battery lives. Multiple years is the advertised figure. Based on my work below, I believe it entirely, and I was even able to improve on it!
I saw some "Samsung NFC Tag ST-GM42KC0 Solum ESL SmartTAG" listings on eBay. I figured that I was, at the moment, short precisely one interesting project, and given that is was an electronic device, there was approximately a 100% chance I'd be able to bend it to my will. I thought it would be a cool way to show weather and stocks in an easily glanceable fashion in the morning. Maybe a cool black-and-white picture frame too? The listing said these were NFC based, but the model number I looked up at the FCC website showed that this model lacked NFC. Fine, NFC is no use to me anyways. Clearly they are not updated in the store over NFC (what good is an electronic price tag if you need to send a real live human to update it?), there must be some real wireless in there somewhere. I clicked "buy", and waited.
Well, that is not that exciting, some passives, two 2.4GHz antennas, and a shield can. No fun at all! Where's the beef? The board is attached to black plastic by super-strong double-sided tape. The screen is attached to this same plastic from the other side using the same kind of tape. Of course the eInk panel is also by a company that no longer exists and no documentation exists either... Time to open it up!
After prying the annoying metal can off the board, I could finally see the brains of this operation, and my heart sank. "Marvell" No name elicits such a visceral response as that one. These are the assholes who bought Intel's X-Scale SoC line, deleted the datasheets off the website, and then found every datasheet copy on the internet and had it taken down. If you ever have a choice between working with their chips and paying twice the price for some other chip, pay someone else twice as much, thank me later. They have a pre-arranged, reserved parking garage just for them in hell! The chances of ever seeing a real datashet were now clearly zero. Damn!
Well, in any case, predictably googling for 88MZ100 produces nothing but Marvell's own website, with their public "datasheet" for the chip. Wait, didn't I just say they do not have datasheets? Yeah, they indeed publish a PDF for each chip that they call "datasheet". It serves as a giant "screw you" to all developers who would futilely hope that it would contain specifications of how the chip works or how to use it. This one was two pages long. The only useful thing it contained was a diagram roughly outlining the features of the chip. Well, ok, now we know that it is a Cortex-M3 (most any chip made this decade would be), it has 512K of flash, 160K of RAM, and speaks ZigBee.
The board also had a 2x3 arrangement of landing pads for pogo pins, clearly for factory programming/testing. This is obvious since they are accessible from the outside, hidden behind the serial number sticker on the back of the device. Scoping them as the tag was powered up revealed that one was power, one was ground, and one was a TX line of a UART, configured as 115,200 8n1
Cortex-M class chips are debugged using a standard interface called SWD that was designed by ARM specifically for this purpose. This is nice compared to the 10000 different interfaces that are used to program/debug 8-bit microcontrollers. Conveniently, I have a wonderful SWD debugger called CortexProg that I can use. SWD uses just two pins, one for clock and one for bidirectional data. I tried those 6 pogo pin landing positions in every possible order, and had no luck. Hmm, well on every chip I've ever used, the pins for these two were next to each other. Obviously nothing requires that, but it is common. I decided to try my luck and try every pair of nearby pins to see if I got any response to my SWD debugger. Well, what do you know? I get a response from the chip when I use pin 22 as SWDCK and pin 23 as SWDIO.
Most production devices lock the chips in a way that their code cannot be read out. This protection is usually a big deal, and is often advertised for chips. It is strange that Marvell did not advertise anything of the sort. Could it be? Does this chip really lack something as basic as an ability to prevent code readout? Well, as far as I knew at this point, perhaps. Plus, Marvell is not exactly known for competence (just for being assholes), so I would not put it past them to forget something this obvious. In any case, I tried to read it using CortexProg. It worked... It reads 128K of ROM. Yes 128K, despite the "datasheet" saying 4K. Well, what did you expect? It is Marvell. Not only that, I could also debug the code successfully. Step, set breakpoints, everything!
The chip, however, seemed to crash often when debugged. A bit of sleuthing revealed that it was being reset by the watchdog timer. Now, most Cortex-M chips are designed by intelligent people, who realize that debugging needs to happen, so they either design the WDT to pause while debugging is ongoing, or have a bit somewhere to configure that, and default to pause while debugging. But of course, Marvell...
The flash seemed divided into four parts: a bootloader, some binary data that later turned out to be radio calibration and settings, what seemed to be peripheral drivers, and what looked like a complete ZigBee stack. How did I know? ZigBee packet format is rather specific and code that parses it has a rather obvious shape. And I've seen enough i2c and spi drivers in my life to recognize one by code shape quite easily. But randomly stopping the device while it was running revealed that it ran from RAM, never entering ROM. This one fact tells us three distinct things. One: the peripheral drivers and ZigBee stack in the ROM are unused, Two: The code in RAM must thus have its own comms layer. And three: that code must be coming from somewhere, and it is not in the ROM!
Remember that block diagram? "In-Package 512KB Flash" it said. But how is it addressed? To figure it out, I'd have to disassemble the bootloader. Luckily, it was only 4KB in size, and did not call out to any other code - fully self-contained. If the bytes 0xAB, 0x06, and 0xB9 mean anything to you, you'll immediately realize, as I did, that the internal flash must be attached over an internal SPI bus. Those are typical (de facto standard) SPI/QSPI NOR flash memory commands. Knowing that, in turn, allowed me to label the functions and sort out more or less how the SPI peripheral works in this SoC. It also showed where the code comes from, and what the bootloader does. It seems like the internal interface is actually QSPI.
The bootloader starts by reading the first 32 bytes of the QSPI flash into RAM. It is checked for a magic number, and if it is not found, the bootloader enters a loop looking for a UART that it can use (it tries all possible pinmuxes of all UARTs for receiving a magic char with a small wait on each possibility). If the magic number is found, a few words of those 32 bytes are used to configure both UARTs. Then another is used to decide if SWD will be ok. I guess this is their way of locking out code readout - by locking out debugging. A poor strategy, that is easily glitched. Oh well, it's Marvell... Then comes a checksum of the "application" and a few bits to indicate its type ("none" is an option, and this device uses it), and then the QSPI address of the "application", its size, the RAM address to load it to and its entry point address. A word contains a password, defaulting to 0xffffffff, and Samsung/SoluM uses that too, luckily. Another config word defines how long to give an external user to interrupt the boot process by sending a magic character over a UART. If the checksum matches (or none is used), and said timeout has passed with no magic characters RXed on the UART, the application is loaded into RAM and control passes to it. Else, the device goes to an interactive UART shell. Here you can see the pinout of the debug connector and the pogo-pin jig I made to interface with the devices, so that I could talk to the bootloader's command shell.
795a8134c1