Skip to main content

mediatek_optical/receiver/programming/
acceptance.rs

1//! The checked continuation from integrity success to the programming call.
2//! Called helper semantics and the incoming r4/r7 bindings remain obligations.
3use super::{literal, word, IntegritySelection, PlainSignature, Selection};
4use crate::receiver::decoding::branch_link;
5
6/// Operand-bound acceptance checks and programming arguments.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct AcceptanceTail {
9    /// Start of the continuation, equal to integrity success.
10    pub address: u32,
11    /// Tag-check helper, required to return nonzero.
12    pub tag_check: u32,
13    /// Marker-check helper, required to return nonzero.
14    pub marker_check: u32,
15    /// Staged byte required to equal 0xDE.
16    pub descriptor_byte: u32,
17    /// Actual programming call instruction.
18    pub program_call: u32,
19    /// Programming wrapper called with mode three.
20    pub program_target: u32,
21    /// Incoming register that must still hold selection.offset_cell.
22    pub source_pointer_register: u8,
23    /// Incoming register pointing to the failure-state byte.
24    pub failure_pointer_register: u8,
25    /// Common error-report continuation for invalid descriptor/tag/marker.
26    pub error: u32,
27    /// Helpers called after validation, before examining failure state.
28    pub before_program: [u32; 2],
29}
30
31/// Match both validation branches and every instruction of the success path.
32/// This proves argument use, not the independently called helper bodies.
33pub 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}