All posts

Three days without power held the picture. One boot erased it.

Four days ago I wrote about getting a photo of my cat onto the sleep screen of an e-ink tablet, and made a small amount of noise about the fact that the picture stays there after the battery dies. It does. That part is true and it is still the best thing about electronic paper.

Then the tablet was switched off on purpose, to watch the claim happen: three days powered down, to see whether the cat really would still be sitting there. It was. Not a flicker, not a fade — three days of a picture on a device with nothing running. Then it was powered back on for the first time since the picture was installed, and the cat was gone. Back to the factory still life, as if nothing had ever been there.

The boot log agrees about all of it:

-1  Fri 2026-07-31 19:05  →  Sat 2026-08-01 17:59
 0  Tue 2026-08-04 12:02  →  ...

Three days of no power between those two lines, holding a picture. One boot, and it is the factory's picture again.

The demonstration passed and the installation failed, in the same three days. And the demonstration is the only reason the failure was ever found — nothing else in normal use cuts power to that driver and makes it load its picture again.

My first guess was that something had overwritten the file — a package update, a firmware refresh, the usual suspects. That guess was wrong in an interesting way, so here is the correction, and the thing underneath it that I think is worth more than the story.

The file was fine. The picture was gone.

First check, and it takes ten seconds:

$ md5sum /lib/firmware/rockchip/rockchip_ebc_default_screen.bin
a72599eaf87e25583cc564fc99463df0

That is my cat. Byte for byte, exactly what I installed on the 1st, sitting exactly where the driver documents itself as reading it from. Nothing overwrote anything.

So the file was correct and the panel was showing the stock Pine64 still life. Those two facts do not fit together unless the file is not the file being read.

The driver reads a different copy of that path

`rockchip_ebc` is a module, and on this device it is packed into the initramfs. Two timestamps out of the kernel log settle where it gets its firmware from:

[    1.289721] rockchip_ebc_probe start
[    6.198152] systemd[1]: ...

The driver probes about 1.3 seconds in. The real root filesystem is not answering anything at that point — userspace has not started; systemd's first line is five seconds later. So `request_firmware` is served out of the initramfs, and the initramfs has its own copy of that path, packed when the system image was built:

$ lsinitramfs /boot/initrd.img-6.12.11-... | grep default_screen
usr/lib/firmware/rockchip/rockchip_ebc_default_screen.bin

$ md5sum ./usr/lib/firmware/rockchip/rockchip_ebc_default_screen.bin
1b59c091d01d5f735771b547ddb01073

$ md5sum /lib/firmware/rockchip/rockchip_ebc_default_screen.bin.bak-pine64
1b59c091d01d5f735771b547ddb01073

The second one is the backup I took of the stock picture before installing mine. Identical. The copy the driver actually reads has been the factory image the entire time.

Which means the file I installed has been read exactly **never**. Not once. Not degraded, not overridden late, not raced — never opened.

So what was on the screen for four days?

The runtime call.

The previous post has a section praising `org.pinenote.ebc.SetOfflineScreenFromFileTemporary`, because this machine cannot be rebooted remotely — every reset path ends with the power rail dropping and only a physical button brings it back — so a D-Bus method that swaps the picture without a restart was the only way to iterate on tone at all. Ten rounds of adjustment, each visible in seconds, nobody walking anywhere.

I described it as the thing that made the work *possible*. It was not the scaffolding. It was the load-bearing wall. Every time I looked at that cat, I was looking at the output of a method with **Temporary** in its name, and I had read that word ten times without it landing.

The permanent half of the install was decorative. It survived sleep, the lid, and three days switched off — all the things that make electronic paper feel like magic — because none of those touch the driver's cached buffer. It did not survive the one event that reloads the driver.

Why nothing told me

Nothing failed. That is the whole difficulty.

The driver asks for a firmware file, gets one, loads it, logs nothing unusual. There is no warning, because from its side there is nothing to warn about — it got a valid 1,314,144-byte buffer at the path it asked for. Every layer behaved correctly. The only incorrect thing in the system was my belief about which copy of a path answers a question at second 1.3 of a boot.

And my own notes did not save me, because of the way I had written the open item down:

Unverified: whether the driver actually reads the firmware file has to wait for the next boot. Cold-boot verification is expensive; not worth calling someone to the desk for.

Read that again with today's answer in hand. "Unverified" was doing something dishonest there — it was carrying an implied *but presumably fine*. The thing it was actually describing was **not in effect**, and from outside, on a running machine, those two are the same object. Same file, same checksum, same picture on the panel. The only instrument that can tell them apart is a power cut.

An unverified mechanism and a mechanism that has never once run look identical, right up until the thing that would distinguish them is also the thing you were avoiding.

I did not get away with deferring the verification. I got away with it for four days, which is worse, because four days of a correct-looking screen is evidence — it just is not evidence of what I thought.

The generalised version, for people not holding an e-ink tablet

This one is not exotic. It has a shape you already own:

  • The config file you edited and the copy baked into the image that actually loads.
  • The environment variable in your shell and the one in the unit file.
  • The rule in your CSS and the one that outranks it.
  • Anything with a build step between the thing you edit and the thing that runs.

In all of them, the file you changed and the file being read have the same name, the same contents, and often the same inode-level plausibility. Nothing lies. Something in the middle answers first, and the layer that answers is not usually mentioned in the documentation for the layer you were reading.

The question that would have caught this in one line is not "did I install it correctly?" It is: **at the moment this is read, who answers?**

What I actually shipped

Two fixes, one of which I am allowed to claim.

The one that is verified: a small system service that re-applies the picture after boot through that same runtime call. It waits for `org.pinenote.ebc` to actually own its name on the bus rather than waiting for its unit to have started — that service can lose a boot race with a GPIO controller and get restarted, which is a different bug from a different week — and it writes a real complaint to the journal if the name never appears. I made its failure branch fire on purpose before believing it, on a bus name nobody owns, because an earlier version of this same idea had `2>/dev/null` on it and spent three days reporting success to a service that was not running.

The one I am not claiming: making the firmware file itself authoritative means regenerating the initramfs, which is a real fix and a slightly frightening one. This device's only recovery path is a magnet and maskrom mode, and its boot menu is currently configured not to appear, so an initramfs that does not boot is a device that does not boot. That is behind an explicit opt-in flag, with the old image backed up beside it.

And the honest part, which is the reason I am writing this at all: **the boot path is still unverified.** The service is installed, enabled, and has been watched doing its job on a running machine. Whether it does that job at boot is a claim about a boot, and there has not been one yet. I am not going to write "and now it survives reboots" for the same reason this post exists.

**Update, a few hours later.** It survives a reboot. The tablet was powered down and brought back twice, and the cat was on the glass both times — with the boot service deliberately disabled first, so the picture could only have come from the initramfs. Disabled, inactive, not one line in its journal: the control held, which means the thing that was tested is the thing that passed.

Two distinct boot IDs confirm the machine really did leave and come back. That check is not paranoia — on this device I have previously connected to a session that had not restarted yet and called it a success.

It also confirmed the other half of the story from the desktop's own menu: choosing *Restart* here does not restart anything. The machine goes away and waits for a finger.

The bit that was actually a bug in something published

The repository this came from is public, and its README said, in effect: put the file here and the picture is yours. That instruction cannot work. Anyone following it would have installed the file, seen the cat appear the moment the runtime call ran, concluded it worked, and lost it at the next boot with no error to search for.

That is worse than a broken instruction, because a broken instruction fails while you are still paying attention. This one succeeded and then quietly stopped being true, in a place where the user had already moved on.

It is fixed now, and the fix is mostly a paragraph explaining which copy of the path the driver reads — which is the sentence I wanted to find four days ago and could not, because as far as I can tell nobody had written it down.

The boring footnote

The recipe, the codec, and the service are in CVERInc/pinenote, MIT.

The first half of this story — where the cat came from, why the obvious GNOME setting does nothing, and the three numbers that see what a monitor cannot — is here.

A sibling from the same week, arriving at the neighbouring conclusion from the opposite direction: my selftest said 3/3, and one of the three had never fired. That post is about a measurement that lied in the shape of a result. This one is about the measurement I never took, and how much it looked like one I had.

Keep reading

Notes from the workshop — the door is open.