Skip to content
cmdadaPublic

About

For MU-43, squashed down this whole git repo from my private git server and pushed it to github here

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

em10-fw

Taking apart the firmware of the Olympus OM-D E-M10 — the original Mark I, on version 1.4 — and putting things back into it.

This is notes, tools, a system emulator that boots the real image, a loader that runs code off the SD card without reflashing, and a FreeRTOS port to the camera's own CPU. The Mark I has had much less attention than the Pen-F and the newer bodies, so most of what is written down here was not documented anywhere when I started on it.

Everything is specific to one image: OLY_E_113_1400_0000_0000.BIN, model signature 0x1130, version 0x1400. Addresses in the notes are addresses in that build and nothing else. Other OM-D bodies of the same generation are close enough that the shapes transfer and the offsets do not.

The camera, briefly

A TruePic VII: three Panasonic MN103S cores (AM32, disassembled as am33-2) running a three-core µITRON 4.0 kernel, with a UART shell, a USF shell and a Wi-Fi telnet shell left in the shipping firmware, along with most of its debug strings and a good number of its function names.

The update file holds three blocks — main code, strings and fonts, and one more whose content is still unidentified. Block 00 is loaded at 0x7D991020, which is how the strings line up; c_start then copies it into RAM section by section from a table at 0x7D9988E8, and skips the padding between sections. That last detail cost three non-booting builds before I understood it: bytes written into the 0xFF padding are in the image and are simply not in RAM at run time. tools/patch.py load-padding extends the section descriptor so the padding is copied too, which turns the whole tail into usable space for a two-byte edit.

The other trap of the same kind: the MN103 faults on a 32-bit load from an address that is not a multiple of four. The emulator used to execute those quite happily, so a relocation pass doing unaligned word writes looked fine offline and would not boot. It now logs every misaligned access and can stop the run on one.

What is here

  • notes/ — the writeup, and the reason the rest of this exists. Memory map and boot, the RTOS and its objects, USB and PTP, Wi-Fi and the OI.Share API, the movie recorder, stills/AF/lens, the GPU and GUI, the menu tables, what a flash actually does, and a ranked list of what can and cannot be changed. Start at notes/README.md.
  • tools/ — the analysis and patching side. mkdb.py builds a SQLite database of 67.6k functions with their xrefs and strings; show.py ADDR disassembles one with names filled in; patch.py applies the verified byte patches; theme.py, font.py, icons.py, guides.py and friends rewrite the GUI's palettes, bitmap fonts and images; ghidra.sh sets up a Ghidra project on the MN103 with a compiler spec for this firmware's calling convention.
  • emu/ — em10emu, a system emulator for this generation. It runs the stock image on all three cores with the kernel, the display controller and an SD host, boots to the GUI, and will open a window on the camera's rear monitor. It does not model the image processor or the sensor, so it cannot make a picture, but it catches the whole class of mistake that otherwise costs a flash cycle.
  • plugins/ — the SD-card plugin loader, its SDK, and nine plugins. The loader is patched into block 00 once; after that, code goes on the card under C:\PLUGINS\ and is loaded at startup, with a page of its own under Setup.
  • openkernel/ — FreeRTOS V11.3.2 ported to the MN103S cores, with a µITRON service layer offering the calls the camera's own code makes, and thunks at the addresses it calls them at.
  • web/ — replacement pages for the card browser the camera serves over its own Wi-Fi.
  • tools/em10ctl/ — a terminal menu that drives the camera over the documented OI.Share HTTP API. It never touches firmware, so it is the one thing in here that cannot brick a body.

Setting up

./setup.sh

That fetches the firmware from the xdel.ru mirror and checks its hash, unpacks the three blocks with that mirror's oly_fw_manip (vendored in tools/), builds mn10300-elf binutils, and writes the annotated listing. It needs wine — the unpacker is a Windows binary — plus gcc, curl, xz and python3. None of its output is in git; the repo carries only what was written here.

Then, as you need them:

python3 tools/mkdb.py          # disasm/fw.db — functions, xrefs, strings
tools/ghidra.sh setup          # a Ghidra project, about 8 minutes
make -C emu                    # emu/em10emu
make -C plugins                # the loader and the plugins, into plugins/build
make -C openkernel             # openkernel/build/kernel.bin

Building an image

tools/build.sh NAME PATCH… applies patches, runs the image tools, packs the result to patched/OLY_E_113_1400_NAME.BIN, then unpacks that again and compares every block, which is the check that matters. The ones worth naming:

patch what it does
load-padding copies the section padding into RAM; everything below needs it
video-29min the movie clip limit, mov 1740,d0 → mov 32767,d0
plugins the SD-card plugin loader and its hooks
homebrew-menu a Homebrew entry in the Setup menu, and the page it opens
menu-bg-paint paints the menu background instead of leaving live view under it
picture-modes extra entries in the Picture Mode list, named everywhere
web-ui replaces the card browser's pages with web/
guide-pictures redrawn SCN and ART guide artwork

Unpack → pack with no changes reproduces the original BIN byte for byte, which is worth confirming before trusting anything else.

Running it without a camera

cd emu
./em10emu -N ../emu-state/nand.img ../unpacked/OLY_E_113_1400.dissected ../orig/OLY_E_113_1400_0000_0000.BIN
./em10emu -w …     # a window on the rear monitor, keys on the debug shell

With a card directory it will boot a patched image with plugins on it and drive the menus, which is how most of the plugin work was done. plugins/test/ runs each capture plugin on a test picture inside the emulator and again as a host build of the same sources, and requires the two to match byte for byte.

What has run on the camera

Honest status, because the difference matters a great deal here.

Plugin loader and the Homebrew page works
Capture plugins (partial colour, raw monochrome, film looks) work; slow — 3.2 s for raw monochrome across all three cores, up to 16 s for the arithmetic-heavy ones
Hardware colour key works, in live view as well as on the captured frame
GUI theme, fonts, icons, guide artwork works
Replacement card-browser pages works
Movie clip limit the counter reads past the 29-minute cap — but see below
Focus bracketing the plugin runs and the lens does not move
Immich uploader the card walk, TLS and HTTP all work off the camera; on the camera the radio associates and DHCP never completes
The open kernel boots and schedules on three cores in the emulator only

The movie patch needs its caveat spelled out. At FHD Fine, around 24 Mb/s, 4 GiB of FAT32 is about 24 minutes, so the file-size limit arrives long before the duration does, and what that counter now reports is card space rather than when recording will actually stop. There is an AVSCA_INF_DIV_FILESIZE in the recorder and I have not established whether this generation splits files. Two reports on the mu-43 thread have the same patch stopping at about 30 minutes with a card error. I would not call it solved on the Mark I.

In-camera focus stacking, the feature I most wanted, is not reachable. Compared against E-M5 II, E-M1 and E-M10 II images it is four interlocking layers — a menu and settings component, a shooting sequencer, a per-frame REC-API lens wrapper, and the focus task primitive underneath — and only the fourth exists here, as fcs_lens_mfts_move_lens_ofset at 0x7DF016A9. The wrapper above it is absent on the Mark I and a stub on the Mark II. Grafting the upper layers across means rebasing non-relocatable code and inserting entries into four build-specific tables, which is a porting project rather than a patch. notes/focus.md has the comparison.

Flashing, and getting a camera back

A card update writes only the three main blocks. The boot chain underneath is not in the update file and an ordinary flash cannot touch it:

  • a 2 KiB mask ROM at 0x40000000, 0x4F5 bytes of code mirrored every 0x800, which reads a strap word, sets up the NAND controller, reads the first 4096 bytes of flash into on-chip RAM and jumps there;
  • a first stage at 0x40000000, 0x7800 long, which loads the rest of itself and programs the clocks;
  • a second stage at 0x40020000, 0x31800 long, with its own FAT and flash code, the sub-CPU code, and the [firmup] card updater.

That was dumped off a running camera rather than inferred, and it is why holding OK at power-on with a good BIN in DCOLYMP/ on the card recovers a body that will not boot. I have done it once, after flashing a build that did not come up. One data point on one body, but a hardware one.

None of which makes this safe. A wrong image can leave a camera that does not start, the sequence above is the only way back, and nobody is obliged to help you if it fails. The firmware here was written for a body I bought to take apart. Do not put it on a camera you need.

Credits

The firmware images and most of the tooling came out of the modified firmware thread on mu-43 and the xdel.ru mirror behind it, and the groundwork on Olympus's firmware format — the block headers, the scrambling, the checksums, the model signatures — is mx3, Altsoph, wictor, Virus, tester13 and foxo's, in tools/oly_fw_tools/. tools/credits.txt is the list that came with the mirror. The Ghidra language for the MN103 is txt231's GhidraMn10300, with two local changes in tools/ghidra/.

Licence

GPL-3.0, except where a subdirectory says otherwise. openkernel/third_party/ is FreeRTOS (MIT), plugins/third_party/ is BearSSL (MIT), the on-screen keyboard in plugins/loader/ctrosk/ is ctr-osk-rt (GPL-3.0), and the contents of tools/oly_fw_tools/ and the reference PDFs in tools/ are other people's, mirrored here as they were distributed.

Olympus and OM Digital Solutions have nothing to do with any of this.

About

For MU-43, squashed down this whole git repo from my private git server and pushed it to github here

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages