[GH-ISSUE #7590] [Design] Admit Intel MCS-96 (80C196) raw-binary targets in the Ghidra lane #4523

Open
opened 2026-10-31 00:50:29 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @16vmini on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7590

Before submitting

  • I searched existing issues and discussions for MCS-96 / 80C196 / 8096 and found no prior request.
  • I understand that opening this issue does not authorise integration and that scope is decided by maintainers.
  • No credentials, private samples or sensitive target data are included. The sample firmware referenced below is self-owned and will be shared only as the verifier requires.

Decision needed

Should REA admit a new raw-binary architecture, mcs96, mapped to Ghidra's stock MCS96:LE:16:default language, so that late-1990s automotive and industrial firmware built on the Intel 80C196 family can be analysed through the existing open_binary / rea inspect raw-binary path?

Three alternatives:

  1. Admit mcs96 as a raw-only architecture on POSIX hosts, following the 6502 lane (proposed).
  2. Admit it on POSIX and extend the Windows P0 gate to cover it alongside 6502.
  3. Keep refusing it and document MCS-96 as out of scope.

Context and evidence

Observed. A 32 KB EPROM image from an MBE941 engine control unit (Intel 80C196KC, controlling a TVR AJP8 V8) cannot be opened by rea-agents 6.8.0:

  • domain/rawBinary.js restricts architecture to x86, x86_64, arm, arm64, 6502, m68k.
  • ghidra/GhidraRawBinaryLanguage.js has no MCS-96 entry.
  • ghidra/GhidraAnalysisProfile.js rejects REA_GHIDRA_LANGUAGE_ID for raw-binary imports ("overrides cannot replace the admitted raw-binary import"), so the language cannot be supplied from outside.
  • On Windows, ghidra/GhidraProvider.js admits only PE and raw 6502.

Source-derived. Ghidra ships an MCS96 processor module (Ghidra/Processors/MCS96, language id MCS96:LE:16:default, 16-bit little-endian, 64 KB address space, ram default space). No SLEIGH work is required. Hopper and IDA refuse raw-binary targets, so this is a Ghidra-lane-only change.

Target layout. The 80C196 family has a fixed memory map that makes the raw import well defined:

Range Contents
0x0000–0x00FF Special function registers and internal register file (not file-backed)
0x2000–0x201F Interrupt vector table (0x2030–0x203F additional vectors on KC parts)
0x2018 Chip configuration byte
0x2080 Reset entry point, fixed in silicon

A full 27C256 image maps at 0x0000, so the vector table and reset entry fall at the same file offsets. In our sample, file offset 0x2080 holds E7 01 02, a long jump into the startup code, which confirms the mapping.

Precedent. The 6502 lane is the closest template: raw-only, 16-bit address space, caller-supplied entry, address-width rule of 0xffff, verifier built from a known-good assembled image. An mcs96 lane would be shaped the same way.

Expected interaction with targets

Read existing files only. The caller supplies format: "raw-binary", architecture: "mcs96", and an entry_point (normally 0x2080). Ghidra imports with BinaryLoader, maps the file at the entry-derived base, seeds the entry function and runs auto-analysis. No target execution, injection or mutation.

Boundary details

  • Raw-binary only. No ELF, OMF-96 or Intel HEX parsing; the entry must be given explicitly, as for the other raw lanes.
  • Whole mapped file must fit within 0x0000–0xFFFF, same rule as 6502.
  • Internal SFR and register-file ranges are not file-backed. Uninitialised blocks Ghidra adds for them are observations, not evidence, following the existing load-image rules.
  • Single Ghidra language variant. 8096, 80C196KB, KC, KD and NU parts share the instruction set that MCS96:LE:16:default decodes; part-specific SFR maps are out of scope for the import and belong to annotations.
  • Windows P0 stays as it is unless maintainers choose option 2. Proposed scope is POSIX-first.

Options and tradeoffs

  1. Admit mcs96 on POSIX, raw-only (proposed). Smallest change, reuses every 6502 pattern, gives a verified lane for a widely used 1990s automotive controller family. Coordination: touches the same architecture-vocabulary surfaces that #7478 proposes to centralise, so sequencing after or alongside that work would avoid churn.
  2. Also extend Windows P0. Useful to the people most likely to hold these images, but widens the Windows gate that has been kept deliberately narrow. Can be a follow-up once the POSIX lane is verified.
  3. Refuse. Zero cost, but leaves a whole class of embedded firmware with no route into REA even though Ghidra already supports it.

Verification available so far

  • Reproduction of the refusal on Windows with rea-agents 6.8.0 (file and line references above).
  • A self-owned 32 KB 80C196KC image whose reset vector and interrupt table are documented, suitable as a real-provider sample.
  • A verifier toolchain. The sample's owner, Mark Burton (GitHub: @markb139), has written an open-source Intel 8096 assembler, disassembler, emulator and structural decompiler (https://github.com/16vmini/ecudump, tools/asm_8096.py, intel_8096/). The assembler round-trips the full firmware, so a small known-good image can be assembled for an npm run verify:ghidra:mcs96 lane in the same way ca65/ld65 serve the 6502 verifier. Mark has done the overwhelming majority of the reverse-engineering work on this target and would be the technical reference for the lane.
  • Named human owner for any resulting PR: Matt (@16vmini). I will review the final diff, run npm run check and the real Ghidra lane on a POSIX host, and complete the Author readiness declaration personally. Mark remains the technical reference for the MCS-96 toolchain and the sample.
  • Not yet run: the Ghidra side. JDK 21 and Ghidra 12 are not installed on the Windows reproduction machine. If maintainers are open to the lane, the first step on our side is a POSIX host with Ghidra 12.1.x, a headless MCS96:LE:16:default import of the sample, and a load-image check against the documented vector table.

Success criteria and open questions

Success criteria:

  • rea inspect <image> --target-format raw-binary --architecture mcs96 --entry-point 0x2080 --provider ghidra --json opens the sample on Linux and macOS and reports the canonical entry point.
  • inspect-native-load-image shows one initialised, loaded, non-overlay block in the default space covering the file, within 0x0000–0xFFFF.
  • procedure_pseudo_code on the reset entry returns decompiler output rather than a refusal.
  • A verifier lane assembles a known image with asm_8096.py, imports it, and checks the load image and entry, mirroring verify:ghidra:6502.
  • Docs updated: docs/raw-binary.md architecture table, native-and-artifacts.md lane list.

Open questions:

  1. Should the lane land before or after the architecture-vocabulary consolidation in #7478?
  2. Is a Python-based verifier toolchain acceptable, or must the verifier assembler be a native binary like ca65?
  3. Is there appetite for extending Windows P0 to mcs96 in a follow-up, given that most holders of these images work on Windows tuning tools?

References

Originally created by @16vmini on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7590 ## Before submitting - [x] I searched existing issues and discussions for MCS-96 / 80C196 / 8096 and found no prior request. - [x] I understand that opening this issue does not authorise integration and that scope is decided by maintainers. - [x] No credentials, private samples or sensitive target data are included. The sample firmware referenced below is self-owned and will be shared only as the verifier requires. ## Decision needed Should REA admit a new raw-binary architecture, `mcs96`, mapped to Ghidra's stock `MCS96:LE:16:default` language, so that late-1990s automotive and industrial firmware built on the Intel 80C196 family can be analysed through the existing `open_binary` / `rea inspect` raw-binary path? Three alternatives: 1. Admit `mcs96` as a raw-only architecture on POSIX hosts, following the `6502` lane (proposed). 2. Admit it on POSIX and extend the Windows P0 gate to cover it alongside `6502`. 3. Keep refusing it and document MCS-96 as out of scope. ## Context and evidence **Observed.** A 32 KB EPROM image from an MBE941 engine control unit (Intel 80C196KC, controlling a TVR AJP8 V8) cannot be opened by `rea-agents` 6.8.0: - `domain/rawBinary.js` restricts `architecture` to `x86, x86_64, arm, arm64, 6502, m68k`. - `ghidra/GhidraRawBinaryLanguage.js` has no MCS-96 entry. - `ghidra/GhidraAnalysisProfile.js` rejects `REA_GHIDRA_LANGUAGE_ID` for raw-binary imports ("overrides cannot replace the admitted raw-binary import"), so the language cannot be supplied from outside. - On Windows, `ghidra/GhidraProvider.js` admits only PE and raw `6502`. **Source-derived.** Ghidra ships an MCS96 processor module (`Ghidra/Processors/MCS96`, language id `MCS96:LE:16:default`, 16-bit little-endian, 64 KB address space, `ram` default space). No SLEIGH work is required. Hopper and IDA refuse raw-binary targets, so this is a Ghidra-lane-only change. **Target layout.** The 80C196 family has a fixed memory map that makes the raw import well defined: | Range | Contents | |-------|----------| | `0x0000`–`0x00FF` | Special function registers and internal register file (not file-backed) | | `0x2000`–`0x201F` | Interrupt vector table (`0x2030`–`0x203F` additional vectors on KC parts) | | `0x2018` | Chip configuration byte | | `0x2080` | Reset entry point, fixed in silicon | A full 27C256 image maps at `0x0000`, so the vector table and reset entry fall at the same file offsets. In our sample, file offset `0x2080` holds `E7 01 02`, a long jump into the startup code, which confirms the mapping. **Precedent.** The `6502` lane is the closest template: raw-only, 16-bit address space, caller-supplied entry, address-width rule of `0xffff`, verifier built from a known-good assembled image. An `mcs96` lane would be shaped the same way. ## Expected interaction with targets Read existing files only. The caller supplies `format: "raw-binary"`, `architecture: "mcs96"`, and an `entry_point` (normally `0x2080`). Ghidra imports with `BinaryLoader`, maps the file at the entry-derived base, seeds the `entry` function and runs auto-analysis. No target execution, injection or mutation. ## Boundary details - Raw-binary only. No ELF, OMF-96 or Intel HEX parsing; the entry must be given explicitly, as for the other raw lanes. - Whole mapped file must fit within `0x0000`–`0xFFFF`, same rule as `6502`. - Internal SFR and register-file ranges are not file-backed. Uninitialised blocks Ghidra adds for them are observations, not evidence, following the existing load-image rules. - Single Ghidra language variant. 8096, 80C196KB, KC, KD and NU parts share the instruction set that `MCS96:LE:16:default` decodes; part-specific SFR maps are out of scope for the import and belong to annotations. - Windows P0 stays as it is unless maintainers choose option 2. Proposed scope is POSIX-first. ## Options and tradeoffs 1. **Admit `mcs96` on POSIX, raw-only (proposed).** Smallest change, reuses every `6502` pattern, gives a verified lane for a widely used 1990s automotive controller family. Coordination: touches the same architecture-vocabulary surfaces that #7478 proposes to centralise, so sequencing after or alongside that work would avoid churn. 2. **Also extend Windows P0.** Useful to the people most likely to hold these images, but widens the Windows gate that has been kept deliberately narrow. Can be a follow-up once the POSIX lane is verified. 3. **Refuse.** Zero cost, but leaves a whole class of embedded firmware with no route into REA even though Ghidra already supports it. ## Verification available so far - Reproduction of the refusal on Windows with `rea-agents` 6.8.0 (file and line references above). - A self-owned 32 KB 80C196KC image whose reset vector and interrupt table are documented, suitable as a real-provider sample. - A verifier toolchain. The sample's owner, Mark Burton (GitHub: `@markb139`), has written an open-source Intel 8096 assembler, disassembler, emulator and structural decompiler (https://github.com/16vmini/ecudump, `tools/asm_8096.py`, `intel_8096/`). The assembler round-trips the full firmware, so a small known-good image can be assembled for an `npm run verify:ghidra:mcs96` lane in the same way `ca65`/`ld65` serve the `6502` verifier. Mark has done the overwhelming majority of the reverse-engineering work on this target and would be the technical reference for the lane. - Named human owner for any resulting PR: Matt (`@16vmini`). I will review the final diff, run `npm run check` and the real Ghidra lane on a POSIX host, and complete the Author readiness declaration personally. Mark remains the technical reference for the MCS-96 toolchain and the sample. - Not yet run: the Ghidra side. JDK 21 and Ghidra 12 are not installed on the Windows reproduction machine. If maintainers are open to the lane, the first step on our side is a POSIX host with Ghidra 12.1.x, a headless `MCS96:LE:16:default` import of the sample, and a load-image check against the documented vector table. ## Success criteria and open questions Success criteria: - `rea inspect <image> --target-format raw-binary --architecture mcs96 --entry-point 0x2080 --provider ghidra --json` opens the sample on Linux and macOS and reports the canonical entry point. - `inspect-native-load-image` shows one initialised, loaded, non-overlay block in the default space covering the file, within `0x0000`–`0xFFFF`. - `procedure_pseudo_code` on the reset entry returns decompiler output rather than a refusal. - A verifier lane assembles a known image with `asm_8096.py`, imports it, and checks the load image and entry, mirroring `verify:ghidra:6502`. - Docs updated: `docs/raw-binary.md` architecture table, `native-and-artifacts.md` lane list. Open questions: 1. Should the lane land before or after the architecture-vocabulary consolidation in #7478? 2. Is a Python-based verifier toolchain acceptable, or must the verifier assembler be a native binary like `ca65`? 3. Is there appetite for extending Windows P0 to `mcs96` in a follow-up, given that most holders of these images work on Windows tuning tools? ## References - Ghidra MCS96 processor module: https://github.com/NationalSecurityAgency/ghidra/tree/master/Ghidra/Processors/MCS96 - REA raw-binary guide: https://github.com/morluto/rea/blob/main/docs/raw-binary.md - Related design issues: #7477 (RISC-V ELF admission), #7478 (single owner for target-format and architecture vocabularies) - Toolchain and sample owner: https://github.com/16vmini/ecudump — Intel 8096 assembler, disassembler, cycle-accurate 80C196KC emulator, decompiler and MBE941 findings, written by Mark Burton (`@markb139`) - Intel 80C196KB/KC user's guide (November 1990) for the fixed memory map and reset entry
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4523
No description provided.