mediatek_optical/receiver/programming/
acceptance.rs1use super::{literal, word, IntegritySelection, PlainSignature, Selection};
4use crate::receiver::decoding::branch_link;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct AcceptanceTail {
9 pub address: u32,
11 pub tag_check: u32,
13 pub marker_check: u32,
15 pub descriptor_byte: u32,
17 pub program_call: u32,
19 pub program_target: u32,
21 pub source_pointer_register: u8,
23 pub failure_pointer_register: u8,
25 pub error: u32,
27 pub before_program: [u32; 2],
29}
30
31pub fn inspect_acceptance_tail(
34 bytes: &[u8],
35 base: u32,
36 selection: &Selection,
37 signature: &PlainSignature,
38 integrity: &IntegritySelection,
39) -> Option<AcceptanceTail> {
40 if super::inspect_selection(bytes, base, selection.address)? != *selection
41 || super::inspect_plain_signature(bytes, base, selection)? != *signature
42 || super::inspect_legacy_integrity(bytes, base, integrity.address)? != *integrity
43 {
44 return None;
45 }
46 let start = integrity.success;
47 let at = |delta: u32| start.checked_add(delta);
48 for (offset, expected) in [
49 (4, 0x2800),
50 (6, 0xd103),
51 (14, 0xe00a),
52 (20, 0x6809),
53 (22, 0x1840),
54 (24, 0x7801),
55 (26, 0x29de),
56 (28, 0xd006),
57 (32, 0x22de),
58 (38, 0x2200),
59 (40, 0x2124),
60 (48, 0x2800),
61 (50, 0xd105),
62 (58, 0x2203),
63 (60, 0x2126),
64 (68, 0x2107),
65 (70, 0x2000),
66 (76, 0x7838),
67 (78, 0x2801),
68 (80, 0xd007),
69 (84, 0x6832),
70 (86, 0x6821),
71 (90, 0x6800),
72 (92, 0x2303),
73 (98, 0x980d),
74 ] {
75 if word(bytes, base, at(offset)?)? != expected {
76 return None;
77 }
78 }
79 if literal(bytes, base, at(16)?, 1)? != signature.staging_cell
80 || literal(bytes, base, at(82)?, 6)? != selection.length_cell
81 || literal(bytes, base, at(88)?, 0)? != selection.start_cell
82 {
83 return None;
84 }
85 let descriptor_byte = literal(bytes, base, at(18)?, 0)?;
86 if descriptor_byte != 0x1ec056 {
87 return None;
88 }
89 let diagnostic = branch_link(bytes, base, at(10)?)?;
90 for offset in [34, 54] {
91 if branch_link(bytes, base, at(offset)?)? != diagnostic {
92 return None;
93 }
94 }
95 for offset in [8, 30, 52] {
96 literal(bytes, base, at(offset)?, 0)?;
97 }
98 let branch = |offset| {
99 let address = at(offset)?;
100 let op = word(bytes, base, address)?;
101 if op & 0xf800 != 0xe000 {
102 return None;
103 }
104 let delta = (i32::from(op & 0x7ff) << 21) >> 20;
105 u32::try_from(i64::from(address) + 4 + i64::from(delta)).ok()
106 };
107 let error = branch(42)?;
108 if error != branch(62)? || (start..at(100)?).contains(&error) {
109 return None;
110 }
111 Some(AcceptanceTail {
112 address: start,
113 tag_check: branch_link(bytes, base, start)?,
114 marker_check: branch_link(bytes, base, at(44)?)?,
115 descriptor_byte,
116 program_call: at(94)?,
117 program_target: branch_link(bytes, base, at(94)?)?,
118 source_pointer_register: 4,
119 failure_pointer_register: 7,
120 error,
121 before_program: [
122 branch_link(bytes, base, at(64)?)?,
123 branch_link(bytes, base, at(72)?)?,
124 ],
125 })
126}