Skip to main content

parse_rom_table/
parse-rom-table.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3use std::ops::DerefMut;
4use std::num::ParseIntError;
5
6use clap::Parser;
7
8use jtag_taps::taps::Taps;
9use jtag_taps::statemachine::JtagSM;
10use jtag_taps::cable::{self, Cable};
11
12use jtag_adi::{ArmDebugInterface, MemAP};
13
14fn trace_sink_to_str(devtype: u32) -> &'static str {
15    match devtype >> 4{
16        1 => "TPIU",
17        2 => "ETB",
18        3 => "Router",
19        _ => "Other",
20    }
21}
22
23fn trace_link_to_str(devtype: u32) -> &'static str {
24    match devtype >> 4 {
25        1 => "Router",
26        2 => "Filter",
27        3 => "FIFO",
28        _ => "Other",
29    }
30}
31
32fn trace_source_to_str(devtype: u32) -> &'static str {
33    match devtype >> 4 {
34        1 => "CPU",
35        2 => "DSP",
36        3 => "Coprocessor",
37        4 => "Bus",
38        _ => "Other",
39    }
40}
41
42fn debug_control_to_str(devtype: u32) -> &'static str {
43    match devtype >> 4 {
44        1 => "Trigger Matrix",
45        2 => "Debug Authentication",
46        3 => "Power Requestor",
47        _ => "Other",
48    }
49}
50
51fn debug_logic_to_str(devtype: u32) -> &'static str {
52    match devtype >> 4 {
53        1 => "CPU",
54        2 => "DSP",
55        3 => "Coprocessor",
56        4 => "BUS",
57        5 => "Memory",
58        _ => "Other",
59    }
60}
61
62fn devtype_to_str(devtype: u32) -> String {
63    match devtype & 0xf {
64        0 => format!("Misc"), 
65        1 => format!("Trace sink: {}", trace_sink_to_str(devtype)),
66        2 => format!("Trace link: {}", trace_link_to_str(devtype)),
67        3 => format!("Trace source: {}", trace_source_to_str(devtype)),
68        4 => format!("Debug control: {}", debug_control_to_str(devtype)),
69        5 => format!("Debug logic: {}", debug_logic_to_str(devtype)),
70        _ => "Other".to_string()
71    }
72}
73
74fn parse_rom_table<T,U>(mem: &mut MemAP<T>, base: u32) -> Result<(), u8>
75    where T: DerefMut<Target=U>,
76          U: Cable + ?Sized,
77{
78    let _cidr0 = mem.read(base + 0xff0)?;
79    //assert_eq!(cidr0, 0xd);
80    let cidr1 = mem.read(base + 0xff4)?;
81    let _cidr2 = mem.read(base + 0xff8)?;
82    //assert_eq!(cidr2, 0x5);
83    let _cidr3 = mem.read(base + 0xffc)?;
84    //assert_eq!(cidr3, 0xb1);
85
86    match cidr1 {
87        0x10 => {
88            println!("Found ROM table at {:x}", base);
89
90            for i in 0..960 {
91                let romentry = mem.read(base + i * 4)?;
92                if romentry == 0 {
93                    break;
94                }
95
96                if romentry & 1 != 0 {
97                    println!("Entry {} present", i);
98                    if romentry & (1 << 2) != 0 {
99                        println!("    PD valid");
100                    }
101                    let offset = romentry >> 12;
102                    println!("    Offset {}", offset);
103                    parse_rom_table(mem, base + (offset << 12)).expect("parse sub table");
104                }
105            }
106        }
107        0x90 => {
108            println!("Found CoreSight component at {:x}", base);
109            let auth = mem.read(base + 0xfb8)?;
110            println!("    Auth {:x}", auth);
111            let devaff0 = mem.read(base + 0xfa8)?;
112            let devaff1 = mem.read(base + 0xfac)?;
113            println!("    Device affinity {:08x} {:08x}", devaff0, devaff1);
114            let archid = mem.read(base + 0xfbc)?;
115            println!("    Arch ID {:08x}", archid);
116            let devtype = mem.read(base + 0xfcc)?;
117            println!("    Device type {:08x} {}", devtype, devtype_to_str(devtype));
118        }
119        _ => {
120            println!("Unknown entry at {:x}: {:x}", base, cidr1);
121        }
122    }
123
124    Ok(())
125}
126
127#[derive(Parser, Debug)]
128#[command(author, version, about, long_about = None)]
129struct Args {
130    #[arg(short, long)]
131    cable: String,
132    #[arg(short, long)]
133    baud: u32,
134    #[arg(short, long, default_value_t = 0)]
135    /// Which JTAG TAP to use
136    tap_index: usize,
137    #[arg(short, long, default_value_t = 0)]
138    /// Which access port to use
139    ap_num: u32,
140    addr: Option<String>,
141}
142
143fn parse_int(x: &str) -> Result<u32, ParseIntError> {
144    if x.starts_with("0x") {
145        let len = x.len();
146        u32::from_str_radix(&x[2..len], 16)
147    } else {
148        str::parse(&x)
149    }
150}
151
152fn main() {
153    let args = Args::parse();
154    let cable = cable::new_from_string(&args.cable, args.baud).expect("cable");
155    let jtag = JtagSM::new(cable);
156    let mut taps = Taps::new(jtag);
157    taps.detect();
158
159    // IDCODE instruction
160    let ir = vec![14];
161    taps.select_tap(args.tap_index, &ir);
162    let dr = taps.read_dr(32);
163    let idcode = u32::from_le_bytes(dr.try_into().unwrap());
164    assert_eq!(idcode & 0xfff, 0x477);
165
166    let adi = Rc::new(RefCell::new(ArmDebugInterface::new(taps)));
167    let mut mem = MemAP::new(adi.clone(), args.ap_num);
168    
169    let baseaddr = args.addr.map(|x| parse_int(&x)).unwrap_or(Ok(0)).expect("bad address");
170    parse_rom_table(&mut mem, baseaddr).expect("rom table");
171}