1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use super::ArmDebugSequence;
use crate::architecture::arm::ap::MemoryAp;
use crate::architecture::arm::memory::adi_v5_memory_interface::ArmProbe;
use crate::architecture::arm::sequences::ArmDebugSequenceError;
use crate::architecture::arm::ArmError;
use crate::architecture::arm::{
communication_interface::Initialized, ApAddress, ArmCommunicationInterface, ArmProbeInterface,
DapAccess,
};
use crate::session::MissingPermissions;
pub trait Nrf: Sync + Send {
fn core_aps(&self, interface: &mut dyn ArmProbe) -> Vec<(ApAddress, ApAddress)>;
fn is_core_unlocked(
&self,
arm_interface: &mut ArmCommunicationInterface<Initialized>,
ahb_ap_address: ApAddress,
ctrl_ap_address: ApAddress,
) -> Result<bool, ArmError>;
fn has_network_core(&self) -> bool;
}
const ERASEALL: u8 = 0x04;
const ERASEALLSTATUS: u8 = 0x08;
const APPLICATION_RESET_S_NETWORK_FORCEOFF_REGISTER: u32 = 0x50005614;
const RELEASE_FORCEOFF: u32 = 0;
fn unlock_core(
arm_interface: &mut ArmCommunicationInterface<Initialized>,
ap_address: ApAddress,
permissions: &crate::Permissions,
) -> Result<(), ArmError> {
permissions
.erase_all()
.map_err(|MissingPermissions(desc)| ArmError::MissingPermissions(desc))?;
arm_interface.write_raw_ap_register(ap_address, ERASEALL, 1)?;
while arm_interface.read_raw_ap_register(ap_address, ERASEALLSTATUS)? != 0 {}
Ok(())
}
fn set_network_core_running(interface: &mut dyn ArmProbe) -> Result<(), ArmError> {
interface.write_32(
APPLICATION_RESET_S_NETWORK_FORCEOFF_REGISTER as u64,
&[RELEASE_FORCEOFF],
)?;
Ok(())
}
impl<T: Nrf> ArmDebugSequence for T {
fn debug_device_unlock(
&self,
interface: &mut dyn ArmProbeInterface,
default_ap: MemoryAp,
permissions: &crate::Permissions,
) -> Result<(), ArmError> {
let mut interface = interface.memory_interface(default_ap)?;
for (core_index, (core_ahb_ap_address, core_ctrl_ap_address)) in
self.core_aps(&mut *interface).iter().copied().enumerate()
{
tracing::info!("Checking if core {} is unlocked", core_index);
if self.is_core_unlocked(
interface.get_arm_communication_interface()?,
core_ahb_ap_address,
core_ctrl_ap_address,
)? {
tracing::info!("Core {} is already unlocked", core_index);
continue;
}
tracing::warn!(
"Core {} is locked. Erase procedure will be started to unlock it.",
core_index
);
unlock_core(
interface.get_arm_communication_interface()?,
core_ctrl_ap_address,
permissions,
)?;
if !self.is_core_unlocked(
interface.get_arm_communication_interface()?,
core_ahb_ap_address,
core_ctrl_ap_address,
)? {
return Err(ArmDebugSequenceError::custom(format!(
"Could not unlock core {core_index}"
))
.into());
}
}
if self.has_network_core() {
set_network_core_running(&mut *interface)?;
}
Ok(())
}
}