Marek Niepiekło

20 August 2026

Why the Second Version of Our Factory Flashing Tool Ran Linux

Manufacturing tooling is software, and it is usually the last software anyone designs. The product gets the architecture reviews, the coding standards and the test plan. The tool that writes firmware onto every unit leaving the factory gets whatever time is left.

That tool sits on the critical path of every shipped unit. If it is slow, the line is slow. If it is flaky, you get false failures that look like hardware faults — and an operator who no longer trusts the station.

At Samsung I worked on two generations of one such tool: a flasher that wrote images to the eMMC on smart TV mainboards. The interesting part is not the tool. It is why the second version threw away the foundation of the first.

Version one was bare metal, for good reasons

The first version ran on bare metal, and that was a defensible choice. You need to touch storage early, before anything resembling an operating system exists. Bare metal gives you a small binary, a fast start, no dependencies to manage and total control over timing. It worked, and it improved the process it was built for.

The costs arrive later, and they do not arrive as a single dramatic failure. They arrive as a slow tax:

  • Every driver is yours. The eMMC controller, the transport, the timing quirks — you own the code and, more importantly, you own the errata.
  • There is no filesystem. Images are offsets on a medium rather than files. The tool has to know the layout, so changing the image set means changing the tool.
  • Every hardware change lands on your desk. A new board revision or a second-source eMMC part becomes a driver project, in code only your team has ever read, with no upstream to compare notes with.
  • Debugging is whatever you built. No shell, no logs, no standard tooling — only the diagnostics you thought to add before you needed them.

None of these are arguments against bare metal in general. They are arguments about where the work goes over time, which is a different question from what is fastest to stand up.

Version two: a Linux kernel and a deliberately small user-space

For the second version — RomWriter — I designed it around a Linux kernel with a minimal user-space, and led the team that built it.

Framed as a trade, what that buys:

  • MMC and USB stacks that thousands of other products have already exercised. A second-source memory part usually becomes a configuration change rather than a driver investigation. You inherit other people’s bug fixes instead of discovering their bugs yourself.
  • A real filesystem. Images become files. The tool stops needing to know what is in the image set, which decouples two things that had no business being coupled.
  • Ordinary debugging. A shell, kernel logs, standard utilities. When something misbehaves at three in the morning on a production line, the difference between “attach a debugger you wrote” and “read the log” is the difference between a shift lost and a shift saved.

And what it costs, honestly:

  • Boot time. Kernel initialisation is not free, and on a station that runs thousands of cycles, start-up time is a throughput budget, not a detail.
  • Image size. Bigger than a bare-metal binary, by a lot.
  • A kernel configuration to own. You have traded driver maintenance for configuration maintenance. That is usually a good trade, but it is not zero.

The discipline that makes this work is keeping the user-space genuinely minimal. The failure mode is obvious in hindsight: relax that constraint and you have not built a flashing tool, you have built a small Linux distribution, and now you maintain a distribution.

The other half: let the board identify itself

Alongside the tool, I integrated USB 2.0 mass storage and FAT filesystem support into the TV bootloader, so a board could discover and select its own board-specific image.

This sounds like a minor convenience. It is actually the more interesting design change, because it moves a decision to where the information already lives. Previously something outside the board — the station configuration, or an operator — had to know which image belonged to which hardware. That is a category of error no amount of care eliminates, because it depends on humans and configuration staying in sync with a board revision they cannot see.

Once the board identifies itself and picks, the wrong-image-on-the-right-board failure stops being possible rather than becoming less likely. Those are very different guarantees.

What generalises

Four things I would take to any hardware programme:

  1. Manufacturing is a deployment target. It deserves the same architectural attention as the product. It has requirements, throughput budgets, failure modes and users.
  2. “We own every line” is a cost, not only a virtue. Owning code means owning its errata. Reuse where the reuse has been beaten on by other people at scale.
  3. Push identification to the thing being identified. Prefer designs where a failure becomes impossible over designs where it becomes unlikely.
  4. Revisit the foundation when the tax gets clear. The first version was not a mistake. It was correct for what was known at the time, and rewriting it was correct for what was known later.

The second point is the one teams resist most, usually on instinct rather than analysis. Bare metal feels rigorous. Sometimes it is. But “we control everything” and “we maintain everything” are the same sentence, and only one of them shows up in the plan.


If you are taking a product from prototype toward a production line and the tooling story is still undecided, that is what I do — or drop me an email.