From 82958cfe743f4541074d77892ba02709f73c1e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gie=C3=9Fen?= Date: Wed, 22 Apr 2026 22:59:44 +0200 Subject: [PATCH] Clarify coverage wording and add ROM analysis guide --- README.md | 10 +- docs/GETTING_STARTED.md | 8 + docs/LARGE_ROM_ANALYSIS_WORKFLOW.md | 524 ++++++++++++++++++++++++++++ r2plugin/asm_adsp219x.c | 13 +- 4 files changed, 546 insertions(+), 9 deletions(-) create mode 100644 docs/LARGE_ROM_ANALYSIS_WORKFLOW.md diff --git a/README.md b/README.md index 132aa1d..180263a 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ engineering ADSP-2191 firmware. ## Plugin Status -The decoder now covers most ADSP-219x instruction types and has -assembler verification for 34 of 37 documented opcode families. +The decoder implements all documented ADSP-219x instruction types and +has assembler verification for 34 of 37 documented opcode families. Assembler-verified coverage includes: @@ -49,6 +49,12 @@ an open-source assembler/linker for ADSP-218x/219x. Build instructions are in the open21xx README. The resulting ELF is converted to raw binary with `dd` (extract the `int_pm` section). +## Analysis Guides + +- `docs/GETTING_STARTED.md` - setup, loading ROMs, and basic radare2 use +- `docs/LARGE_ROM_ANALYSIS_WORKFLOW.md` - step-by-step workflow for + analyzing large raw ADSP-219x ROM dumps + ## License Plugin code: LGPL-3.0-only. Example code from Analog Devices diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index 491312c..7884947 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -57,3 +57,11 @@ instruction set reference chapters (PDF and text extracts): - `9x_flowops.*` - Flow control (jumps, loops, returns) - `9x_moveops.*` - Data move operations - `9x_multiops.*` - Multifunction operations + +## Large ROM Workflow + +For a practical step-by-step workflow for analyzing a large raw +ADSP-219x ROM image, including how to separate likely code from likely +data and when to use graph analysis, see: + +- `LARGE_ROM_ANALYSIS_WORKFLOW.md` diff --git a/docs/LARGE_ROM_ANALYSIS_WORKFLOW.md b/docs/LARGE_ROM_ANALYSIS_WORKFLOW.md new file mode 100644 index 0000000..c4ae294 --- /dev/null +++ b/docs/LARGE_ROM_ANALYSIS_WORKFLOW.md @@ -0,0 +1,524 @@ +# Large ADSP-219x ROM Analysis Workflow + +This guide describes a practical workflow for reverse engineering a +large raw ADSP-219x ROM image in radare2 using the `adsp219x` +architecture plugin from this repository. + +It is written for the common case where you have a large blob, for +example a 1 MB ROM dump, and you do not yet know: + +- where code starts and where data starts +- how many independent code regions exist +- where the main loops and dispatchers are +- which PM words are instructions and which are tables + +The workflow below is intentionally conservative. For raw DSP ROMs, +manual validation beats aggressive auto-analysis. + +## Assumptions + +- The ROM is for an ADSP-219x family DSP. +- Instructions are 24-bit words. +- The dump is raw program memory, not a richly annotated executable. +- You already have a working radare2 installation and the + `adsp219x` plugin is installed or loadable with `-L`. + +## Load The ROM + +For an installed plugin: + +```bash +r2 -a adsp219x -b 24 firmware.bin +``` + +For a local plugin build that is not installed: + +```bash +r2 -a adsp219x -L ./r2plugin/asm_adsp219x.so -b 24 firmware.bin +``` + +Why the flags matter: + +- `-a adsp219x`: forces the custom architecture plugin +- `-b 24`: tells radare2 to treat the code as 24-bit ADSP-219x words + +## ROM Format Sanity Check + +Before analyzing flow, check whether the byte layout looks correct. + +ADSP-219x code is usually stored either as: + +- packed 24-bit words: `aa bb cc dd ee ff ...` +- padded 32-bit words with a leading zero byte + +If your disassembly looks completely implausible, confirm the ROM +format first. + +Helpful first commands: + +```text +px 64 +s 0 +pd 16 +``` + +If the first few decoded instructions look impossible but the hex dump +shows a repeating `00 xx xx xx` structure, you may be looking at a +32-bit padded dump and need to strip padding before analysis. + +## High-Level Strategy + +For a large ROM, do not start with `aaa`. + +A better sequence is: + +1. validate the entry region manually +2. mark only plausible functions +3. follow explicit control flow +4. distinguish code from tables +5. expand analysis gradually +6. use graph views only after local validation + +`aaa` on a large raw DSP ROM often creates a false sense of structure + by treating valid-looking data words as code. + +## Workflow Diagram + +```mermaid +flowchart TD + A[Load ROM in r2] --> B[Check raw bytes and first instructions] + B --> C{Plausible code at reset area?} + C -- no --> D[Verify ROM packing, offset, endianness, dump source] + D --> B + C -- yes --> E[Create first function manually] + E --> F[Inspect linear disassembly and graph] + F --> G{Looks like real control flow?} + G -- no --> H[Do not mark as function, treat as possible data] + G -- yes --> I[Follow jumps, calls, DO UNTIL loops] + I --> J[Name regions and comment findings] + J --> K[Search for more entry points and dispatchers] + K --> L[Only then expand with broader analysis] + L --> M[Separate code islands from PM data tables] +``` + +## Step 1: Inspect The Reset Region Manually + +Start at address zero unless you have evidence of a different boot +mapping. + +```text +s 0 +pd 20 +pd 64 +``` + +Look for signs of real code: + +- immediate register loads +- `JUMP` or `CALL` +- `DO ... UNTIL` +- initialization of `I`, `M`, `L`, `CNTR`, status registers +- branches to other regions + +Red flags that suggest you are not in code: + +- long stretches of decodeable but nonsensical instructions +- no branches, no calls, no returns +- bizarre register moves with no purpose +- disassembly that looks random but hex bytes look regular + +## Step 2: Mark The First Function Manually + +Once the entry region looks plausible: + +```text +s 0 +af +pdf +agf +``` + +Meaning: + +- `af`: define a function at the current address +- `pdf`: print the current function linearly +- `agf`: show the control-flow graph of the current function + +This is a better first move than `aaa`, because it forces you to +validate one region before scaling out. + +## Step 3: Use Graphs Locally, Not Globally + +For a large ROM, graphs are most useful once you already believe the +current region is code. + +Useful commands: + +```text +agf +VV +afb +``` + +- `agf`: static graph of current function +- `VV`: visual graph mode +- `afb`: list/show basic blocks + +If `agf` produces a clean graph with obvious branches and loop edges, +the region is probably code. + +If `agf` is trivial, chaotic, or makes no semantic sense, you may be +looking at data or a bad function boundary. + +## Step 4: Expand By Following Explicit Flow + +After validating the first function, expand manually through explicit +targets: + +```text +pdf +axt +afl +``` + +Then jump to interesting destinations: + +```text +s +af +pdf +agf +``` + +Prioritize: + +- call targets +- jump targets +- loop bodies +- indirect branch setup code + +For ADSP-219x specifically, also watch for: + +- `DO ... UNTIL` +- tight MAC loops +- register setup for DAGs +- memory access kernels + +## Step 5: Search For ADSP-219x-Specific Patterns + +Search directly for common control-flow patterns: + +```text +/a JUMP +/a CALL +/a DO +/a RTS +/a RTI +``` + +Also inspect likely DSP kernel patterns: + +```text +/a MR +/a MX0 +/a MY0 +/a IO( +``` + +These searches are not perfect, but they help locate: + +- processing loops +- dispatch logic +- hardware initialization +- coefficient loads + +## Step 6: Distinguish Code From Data + +In a large ADSP-219x ROM, many PM words are data, not instructions. +You must actively separate them. + +### Heuristic: likely code + +A region is likely code if it has: + +- incoming xrefs from jumps or calls +- meaningful block structure +- function-like boundaries +- setup followed by control flow +- loops, branches, and exits + +Check with: + +```text +axt @ +pdf +agf +``` + +### Heuristic: likely data + +A region is likely data if it has: + +- regular numeric patterns in hex +- no meaningful control flow +- no incoming code xrefs +- no returns or loop structure +- many decodeable instructions that make no programmatic sense + +Check with both disassembly and raw bytes: + +```text +pd 32 +px 64 +``` + +If the hex dump looks more plausible than the disassembly, it is often +a table. + +### ADSP-219x-specific data patterns + +Common PM data in DSP firmware: + +- FIR coefficients +- IIR coefficients +- FFT sine/cosine tables +- lookup tables +- packed constants +- boot configuration words + +These often decode into valid-looking instructions by accident. + +## Step 7: Delay Global Auto-Analysis + +Only after you have mapped a few real code islands should you broaden +analysis: + +```text +aa +afl +``` + +Prefer `aa` first. + +Use `aaa` only when: + +- the ROM format is confirmed +- the entry region is valid +- you already understand where major code regions are +- the plugin behaves consistently on this image + +Why this matters: + +- `aa` is less aggressive +- `aaa` can create junk functions in large raw ROMs +- false positives are expensive to clean up mentally + +## Step 8: Name What You Understand + +As soon as a region is understood, name and annotate it. + +Useful commands: + +```text +afn entry_init +afn main_loop +afn io_dispatch +CCu probable coefficient table +CCu hardware init and watchdog setup +``` + +Naming reduces rework and makes graph navigation much easier. + +## Step 9: Build A Region Map + +For a 1 MB ROM, keep a rough map as you go: + +- boot/reset code +- hardware init +- interrupt vector area +- main loop +- DSP kernels +- dispatch tables +- PM data tables +- obvious unused or padding regions + +This can live in: + +- r2 comments +- a notebook +- a separate markdown file + +The important thing is to stop treating the ROM as one continuous +thing. Large firmware becomes manageable once you divide it into +regions. + +## Step 10: Revisit Ambiguous Areas Later + +Do not force a conclusion too early. + +When a region is ambiguous: + +- leave it unnamed or mark it as tentative +- inspect surrounding xrefs first +- compare with neighboring validated code +- revisit it after understanding more of the firmware + +Good reverse engineering on large DSP ROMs is iterative. + +## Recommended First 15 Minutes + +If you want a concrete first-pass routine for a 1 MB ROM: + +### 1. Open the ROM + +```bash +r2 -a adsp219x -b 24 firmware.bin +``` + +### 2. Check the first bytes and first instructions + +```text +s 0 +px 64 +pd 32 +``` + +### 3. If plausible, define the first function + +```text +af +pdf +agf +``` + +### 4. Enter visual graph mode + +```text +VV +``` + +### 5. Follow obvious branch targets manually + +```text +s +af +pdf +agf +``` + +### 6. Search for loops and calls + +```text +/a DO +/a CALL +/a JUMP +``` + +### 7. Compare suspicious regions with hex + +```text +pd 32 +px 64 +``` + +### 8. Only then widen analysis + +```text +aa +afl +``` + +## When To Suspect A Bad Decode + +Pause and reassess if you see: + +- no meaningful flow anywhere near the entry region +- every region looks equally nonsensical +- branch targets never lead to reasonable code +- graph mode shows nonsense everywhere +- the ROM appears to decode but nothing behaves like firmware + +Then check: + +- ROM packing +- dump alignment +- whether the image is compressed or encrypted +- whether the base offset is wrong +- whether the file contains headers before the actual code + +## Practical Command Cheat Sheet + +Open: + +```bash +r2 -a adsp219x -b 24 firmware.bin +``` + +Start region: + +```text +s 0 +pd 20 +pd 64 +px 64 +``` + +Define and inspect function: + +```text +af +pdf +agf +``` + +Visual graph: + +```text +VV +``` + +Search: + +```text +/a JUMP +/a CALL +/a DO +/a RTS +``` + +Cross-references: + +```text +axt +axt @ +``` + +Broader analysis: + +```text +aa +afl +``` + +Naming: + +```text +afn main_loop +CCu probable PM coefficient table +``` + +## Summary + +For a large ADSP-219x ROM: + +- do not trust auto-analysis first +- validate the entry region manually +- graph only locally at first +- follow explicit flow edges +- use both disassembly and hex dumps +- treat PM as mixed code and data +- expand analysis gradually + +The core rule is simple: + +**Local confidence first, global analysis later.** diff --git a/r2plugin/asm_adsp219x.c b/r2plugin/asm_adsp219x.c index 6f8a89e..c7430d2 100644 --- a/r2plugin/asm_adsp219x.c +++ b/r2plugin/asm_adsp219x.c @@ -1,12 +1,11 @@ /* asm_adsp219x.c -- Radare2 arch plugin for Analog Devices ADSP-219x - Copyright (C) 2026 Dr. Christian Giessen + Author: Dr. Christian Giessen + Date: 2026 - Decodes most of the ADSP-219x instruction set (Types 1-37). - Verified against open21xx assembler output for Types 1, 3, 4, - 6, 7, 8, 9, 9a, 10, 10a, 11, 15, 17, 18, 20, 25, 33. - Structurally implemented but not yet assembler-verified: - Types 12, 14, 16, 19, 21, 21a, 22, 22a, 23, 24, 26, 29, - 30, 31, 32, 32a, 34, 35, 36, 37. */ + Decodes all documented ADSP-219x instruction types (Types 1-37). + Most types are verified against open21xx assembler output; see + TESTING.md for the current verification matrix and any remaining + structural-only cases. */ #include