opentitanlib/rescue/
serial.rs1use anyhow::Result;
6use std::rc::Rc;
7use std::time::Duration;
8
9use crate::app::TransportWrapper;
10use crate::chip::boot_log::BootLog;
11use crate::chip::boot_svc::{BootSlot, BootSvc, OwnershipActivateRequest, OwnershipUnlockRequest};
12use crate::chip::device_id::DeviceId;
13use crate::io::uart::Uart;
14use crate::rescue::RescueError;
15use crate::rescue::xmodem::Xmodem;
16use crate::uart::console::UartConsole;
17
18pub struct RescueSerial {
19 uart: Rc<dyn Uart>,
20 reset_delay: Duration,
21 enter_delay: Duration,
22}
23
24impl RescueSerial {
25 const ONE_SECOND: Duration = Duration::from_secs(1);
26 pub const RESCUE: [u8; 4] = *b"RESQ";
27 pub const RESCUE_B: [u8; 4] = *b"RESB";
28 pub const REBOOT: [u8; 4] = *b"REBO";
29 pub const BAUD: [u8; 4] = *b"BAUD";
30 pub const BOOT_LOG: [u8; 4] = *b"BLOG";
31 pub const BOOT_SVC_REQ: [u8; 4] = *b"BREQ";
32 pub const BOOT_SVC_RSP: [u8; 4] = *b"BRSP";
33 pub const OWNER_BLOCK: [u8; 4] = *b"OWNR";
34 pub const GET_OWNER_PAGE0: [u8; 4] = *b"OPG0";
35 pub const GET_OWNER_PAGE1: [u8; 4] = *b"OPG1";
36 pub const OT_ID: [u8; 4] = *b"OTID";
37 pub const ERASE_OWNER: [u8; 4] = *b"KLBR";
38 pub const WAIT: [u8; 4] = *b"WAIT";
39
40 const BAUD_115K: [u8; 4] = *b"115K";
41 const BAUD_230K: [u8; 4] = *b"230K";
42 const BAUD_460K: [u8; 4] = *b"460K";
43 const BAUD_921K: [u8; 4] = *b"921K";
44 const BAUD_1M33: [u8; 4] = *b"1M33";
45 const BAUD_1M50: [u8; 4] = *b"1M50";
46
47 pub fn new(uart: Rc<dyn Uart>) -> Self {
48 RescueSerial {
49 uart,
50 reset_delay: Duration::from_millis(50),
51 enter_delay: Duration::from_secs(5),
52 }
53 }
54
55 pub fn enter(&self, transport: &TransportWrapper, reset_target: bool) -> Result<()> {
56 log::info!("Setting serial break to trigger rescue mode.");
57 self.uart.set_break(true)?;
58 if reset_target {
59 transport.reset_target(self.reset_delay, true)?;
60 }
61 UartConsole::wait_for(&*self.uart, r"rescue:.*\r\n", self.enter_delay)?;
62 log::info!("Rescue triggered. clearing serial break.");
63 self.uart.set_break(false)?;
64 let _ = UartConsole::wait_for(&*self.uart, r"(ok|error):.*\r\n", Self::ONE_SECOND);
67 Ok(())
68 }
69
70 pub fn set_baud(&self, baud: u32) -> Result<()> {
71 let symbol = match baud {
73 115200 => Self::BAUD_115K,
74 230400 => Self::BAUD_230K,
75 460800 => Self::BAUD_460K,
76 921600 => Self::BAUD_921K,
77 1333333 => Self::BAUD_1M33,
78 1500000 => Self::BAUD_1M50,
79 _ => return Err(RescueError::BadMode(format!("Unsupported badrate {baud}")).into()),
80 };
81
82 self.uart.write(&Self::BAUD)?;
85 self.uart.write(b"\r")?;
86 let result = UartConsole::wait_for(&*self.uart, r"(ok|error):.*\r\n", Self::ONE_SECOND)?;
87 if result[1] == "error" {
88 return Err(RescueError::BadMode(result[0].clone()).into());
89 }
90
91 self.uart.write(&symbol)?;
93 let result = UartConsole::wait_for(&*self.uart, r"(ok|error):.*\r\n", Self::ONE_SECOND)?;
94 if result[1] == "error" {
95 return Err(RescueError::BadMode(result[0].clone()).into());
96 }
97 self.uart.set_baudrate(baud)?;
99 Ok(())
100 }
101
102 pub fn set_mode(&self, mode: [u8; 4]) -> Result<()> {
103 self.uart.write(&mode)?;
104 let enter = b'\r';
105 self.uart.write(std::slice::from_ref(&enter))?;
106 let mode = std::str::from_utf8(&mode)?;
107 let result = UartConsole::wait_for(
108 &*self.uart,
109 &format!("mode: {mode}\r\n(ok|error):.*\r\n"),
110 Self::ONE_SECOND,
111 )?;
112
113 if result[1] == "error" {
114 return Err(RescueError::BadMode(result[0].clone()).into());
115 }
116 Ok(())
117 }
118
119 pub fn wait(&self) -> Result<()> {
120 self.set_mode(Self::WAIT)?;
121 Ok(())
122 }
123
124 pub fn reboot(&self) -> Result<()> {
125 self.set_mode(Self::REBOOT)?;
126 Ok(())
127 }
128
129 pub fn update_firmware(&self, slot: BootSlot, image: &[u8]) -> Result<()> {
130 self.set_mode(if slot == BootSlot::SlotB {
131 Self::RESCUE_B
132 } else {
133 Self::RESCUE
134 })?;
135 let xm = Xmodem::new();
136 xm.send(&*self.uart, image)?;
137 Ok(())
138 }
139
140 pub fn get_raw(&self, mode: [u8; 4]) -> Result<Vec<u8>> {
141 self.set_mode(mode)?;
142 let mut data = Vec::new();
143 let xm = Xmodem::new();
144 xm.receive(&*self.uart, &mut data)?;
145 Ok(data)
146 }
147
148 pub fn get_boot_log(&self) -> Result<BootLog> {
149 let blog = self.get_raw(Self::BOOT_LOG)?;
150 Ok(BootLog::try_from(blog.as_slice())?)
151 }
152
153 pub fn get_boot_svc(&self) -> Result<BootSvc> {
154 let bsvc = self.get_raw(Self::BOOT_SVC_RSP)?;
155 Ok(BootSvc::try_from(bsvc.as_slice())?)
156 }
157
158 pub fn get_device_id(&self) -> Result<DeviceId> {
159 let id = self.get_raw(Self::OT_ID)?;
160 DeviceId::read(&mut std::io::Cursor::new(&id))
161 }
162
163 pub fn set_boot_svc_raw(&self, data: &[u8]) -> Result<()> {
164 self.set_mode(Self::BOOT_SVC_REQ)?;
165 let xm = Xmodem::new();
166 xm.send(&*self.uart, data)?;
167 Ok(())
168 }
169
170 pub fn set_next_bl0_slot(&self, primary: BootSlot, next: BootSlot) -> Result<()> {
171 let message = BootSvc::next_boot_bl0_slot(primary, next);
172 let data = message.to_bytes()?;
173 self.set_boot_svc_raw(&data)
174 }
175
176 pub fn ownership_unlock(&self, unlock: OwnershipUnlockRequest) -> Result<()> {
177 let message = BootSvc::ownership_unlock(unlock);
178 let data = message.to_bytes()?;
179 self.set_boot_svc_raw(&data)
180 }
181
182 pub fn ownership_activate(&self, activate: OwnershipActivateRequest) -> Result<()> {
183 let message = BootSvc::ownership_activate(activate);
184 let data = message.to_bytes()?;
185 self.set_boot_svc_raw(&data)
186 }
187
188 pub fn set_owner_config(&self, data: &[u8]) -> Result<()> {
189 self.set_mode(Self::OWNER_BLOCK)?;
190 let xm = Xmodem::new();
191 xm.send(&*self.uart, data)?;
192 Ok(())
193 }
194
195 pub fn erase_owner(&self) -> Result<()> {
196 self.set_mode(Self::ERASE_OWNER)?;
197 Ok(())
198 }
199}