1use anyhow::Result;
6use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
7use serde::{Deserialize, Serialize};
8use serde_annotate::Annotate;
9use std::convert::TryFrom;
10use std::io::{Read, Write};
11
12use super::GlobalFlags;
13use super::misc::{TlvHeader, TlvTag};
14use crate::chip::boot_svc::BootSvcKind;
15use crate::with_unknown;
16
17with_unknown! {
18 pub enum RescueType: u32 [default = Self::None] {
19 None = 0,
20 Xmodem = u32::from_le_bytes(*b"XMDM"),
21 }
22
23 pub enum CommandTag: u32 [default = Self::Unknown] {
24 Unknown = 0,
25 Empty = BootSvcKind::EmptyRequest.0,
26 MinBl0SecVerRequest = BootSvcKind::MinBl0SecVerRequest.0,
27 NextBl0SlotRequest = BootSvcKind::NextBl0SlotRequest.0,
28 OwnershipUnlockRequest = BootSvcKind::OwnershipUnlockRequest.0,
29 OwnershipActivateRequest = BootSvcKind::OwnershipActivateRequest.0,
30
31 Rescue = u32::from_be_bytes(*b"RESQ"),
33 RescueB = u32::from_be_bytes(*b"RESB"),
34 Reboot = u32::from_be_bytes(*b"REBO"),
35 GetBootLog = u32::from_be_bytes(*b"BLOG"),
36 BootSvcReq = u32::from_be_bytes(*b"BREQ"),
37 BootSvcRsp = u32::from_be_bytes(*b"BRSP"),
38 OwnerBlock = u32::from_be_bytes(*b"OWNR"),
39 GetOwnerPage0 = u32::from_be_bytes(*b"OPG0"),
40 GetOwnerPage1 = u32::from_be_bytes(*b"OPG1"),
41 GetDeviceId = u32::from_be_bytes(*b"OTID"),
42 Wait = u32::from_be_bytes(*b"WAIT"),
43 }
44}
45
46#[derive(Debug, Serialize, Deserialize, Annotate)]
48pub struct OwnerRescueConfig {
49 #[serde(
51 skip_serializing_if = "GlobalFlags::not_debug",
52 default = "OwnerRescueConfig::default_header"
53 )]
54 pub header: TlvHeader,
55 pub rescue_type: RescueType,
57 pub start: u16,
59 pub size: u16,
61 pub command_allow: Vec<CommandTag>,
63}
64
65impl Default for OwnerRescueConfig {
66 fn default() -> Self {
67 Self {
68 header: Self::default_header(),
69 rescue_type: RescueType::default(),
70 start: 0u16,
71 size: 0u16,
72 command_allow: Vec::new(),
73 }
74 }
75}
76
77impl OwnerRescueConfig {
78 const BASE_SIZE: usize = 16;
79 pub fn default_header() -> TlvHeader {
80 TlvHeader::new(TlvTag::Rescue, 0, "0.0")
81 }
82 pub fn read(src: &mut impl Read, header: TlvHeader) -> Result<Self> {
83 let rescue_type = RescueType(src.read_u32::<LittleEndian>()?);
84 let start = src.read_u16::<LittleEndian>()?;
85 let size = src.read_u16::<LittleEndian>()?;
86 let allow_len = (header.length - Self::BASE_SIZE) / std::mem::size_of::<u32>();
87 let mut command_allow = Vec::new();
88 for _ in 0..allow_len {
89 command_allow.push(CommandTag(src.read_u32::<LittleEndian>()?));
90 }
91 Ok(Self {
92 header,
93 rescue_type,
94 start,
95 size,
96 command_allow,
97 })
98 }
99 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
100 let header = TlvHeader::new(
101 TlvTag::Rescue,
102 Self::BASE_SIZE + self.command_allow.len() * std::mem::size_of::<u32>(),
103 "0.0",
104 );
105 header.write(dest)?;
106 dest.write_u32::<LittleEndian>(u32::from(self.rescue_type))?;
107 dest.write_u16::<LittleEndian>(self.start)?;
108 dest.write_u16::<LittleEndian>(self.size)?;
109 for allow in self.command_allow.iter() {
110 dest.write_u32::<LittleEndian>(u32::from(*allow))?;
111 }
112 Ok(())
113 }
114
115 pub fn all() -> Self {
116 OwnerRescueConfig {
117 rescue_type: RescueType::Xmodem,
118 start: 32,
120 size: 224,
122 command_allow: vec![
123 CommandTag::Empty,
124 CommandTag::MinBl0SecVerRequest,
125 CommandTag::NextBl0SlotRequest,
126 CommandTag::OwnershipUnlockRequest,
127 CommandTag::OwnershipActivateRequest,
128 CommandTag::Rescue,
129 CommandTag::RescueB,
130 CommandTag::Reboot,
131 CommandTag::GetBootLog,
132 CommandTag::BootSvcReq,
133 CommandTag::BootSvcRsp,
134 CommandTag::OwnerBlock,
135 CommandTag::GetOwnerPage0,
136 CommandTag::GetOwnerPage1,
137 CommandTag::GetDeviceId,
138 CommandTag::Wait,
139 ],
140 ..Default::default()
141 }
142 }
143}
144
145#[cfg(test)]
146mod test {
147 use super::*;
148 use crate::util::hexdump::{hexdump_parse, hexdump_string};
149
150 const OWNER_RESCUE_CONFIG_BIN: &str = "\
15100000000: 52 45 53 51 4c 00 00 00 58 4d 44 4d 20 00 64 00 RESQL...XMDM .d.\n\
15200000010: 45 4d 50 54 4d 53 45 43 4e 45 58 54 55 4e 4c 4b EMPTMSECNEXTUNLK\n\
15300000020: 41 43 54 56 51 53 45 52 42 53 45 52 47 4f 4c 42 ACTVQSERBSERGOLB\n\
15400000030: 51 45 52 42 50 53 52 42 52 4e 57 4f 30 47 50 4f QERBPSRBRNWO0GPO\n\
15500000040: 31 47 50 4f 44 49 54 4f 54 49 41 57 1GPODITOTIAW\n\
156";
157 const OWNER_RESCUE_CONFIG_JSON: &str = r#"{
158 rescue_type: "Xmodem",
159 start: 32,
160 size: 100,
161 command_allow: [
162 "Empty",
163 "MinBl0SecVerRequest",
164 "NextBl0SlotRequest",
165 "OwnershipUnlockRequest",
166 "OwnershipActivateRequest",
167 "Rescue",
168 "RescueB",
169 "GetBootLog",
170 "BootSvcReq",
171 "BootSvcRsp",
172 "OwnerBlock",
173 "GetOwnerPage0",
174 "GetOwnerPage1",
175 "GetDeviceId",
176 "Wait"
177 ]
178}"#;
179
180 #[test]
181 fn test_owner_rescue_config_write() -> Result<()> {
182 let orc = OwnerRescueConfig {
183 header: TlvHeader::default(),
184 rescue_type: RescueType::Xmodem,
185 start: 32,
186 size: 100,
187 command_allow: vec![
188 CommandTag::Empty,
189 CommandTag::MinBl0SecVerRequest,
190 CommandTag::NextBl0SlotRequest,
191 CommandTag::OwnershipUnlockRequest,
192 CommandTag::OwnershipActivateRequest,
193 CommandTag::Rescue,
194 CommandTag::RescueB,
195 CommandTag::GetBootLog,
196 CommandTag::BootSvcReq,
197 CommandTag::BootSvcRsp,
198 CommandTag::OwnerBlock,
199 CommandTag::GetOwnerPage0,
200 CommandTag::GetOwnerPage1,
201 CommandTag::GetDeviceId,
202 CommandTag::Wait,
203 ],
204 };
205
206 let mut bin = Vec::new();
207 orc.write(&mut bin)?;
208 eprintln!("{}", hexdump_string(&bin)?);
209 assert_eq!(hexdump_string(&bin)?, OWNER_RESCUE_CONFIG_BIN);
210 Ok(())
211 }
212
213 #[test]
214 fn test_owner_rescue_config_read() -> Result<()> {
215 let buf = hexdump_parse(OWNER_RESCUE_CONFIG_BIN)?;
216 let mut cur = std::io::Cursor::new(&buf);
217 let header = TlvHeader::read(&mut cur)?;
218 let orc = OwnerRescueConfig::read(&mut cur, header)?;
219 let doc = serde_annotate::serialize(&orc)?.to_json5().to_string();
220 eprintln!("{}", doc);
221 assert_eq!(doc, OWNER_RESCUE_CONFIG_JSON);
222 Ok(())
223 }
224}