# 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.**