1use crate::{Error, Result};
8use std::path::Path;
9
10const MAGIC_FLAG: u32 = 0xABCDDBCA;
11const VERSION_FLAG: u32 = 0xFFFF0003;
12const PIN_CFG_COUNT: usize = 12;
13const FLASH_CFG_COUNT: usize = 12;
14const PMIC_CHANNEL_COUNT: usize = 10;
15
16pub const DRIVER_CONFIG_SIZE: usize = 236;
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct StubConfig {
20 pub pins: Vec<PinConfig>,
21 pub flash: Vec<FlashConfig>,
22 pub pmic: Option<PmicConfig>,
23 pub sd0: Option<Sd0Config>,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum PinPort {
28 Pa,
29 Pb,
30 Pbr,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum PinLevel {
35 Low,
36 High,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct PinConfig {
41 pub port: PinPort,
42 pub number: u8,
43 pub level: PinLevel,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum FlashMedia {
48 Nor,
49 Nand,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
53pub struct FlashConfig {
54 pub media: FlashMedia,
55 pub driver_index: u8,
56 pub manufacturer_id: u8,
57 pub device_type: u8,
58 pub density_id: u8,
59 pub flags: u8,
60 pub capacity_bytes: u32,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum PmicChannel {
65 LvSw1001,
66 LvSw1002,
67 LvSw1003,
68 LvSw1004,
69 LvSw1005,
70 HvSw1501,
71 HvSw1502,
72 Ldo33,
73 Ldo30,
74 Ldo28,
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct PmicConfig {
79 pub disabled: bool,
80 pub scl_port: PinPort,
81 pub scl_pin: u8,
82 pub sda_port: PinPort,
83 pub sda_pin: u8,
84 pub channels: Vec<PmicChannel>,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum Sd0Pinmux {
89 ClkPa34OrPa09,
90 ClkPa60OrPa39,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub enum Sd0InitSequence {
95 EmmcThenSd,
96 SdThenEmmc,
97}
98
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub struct Sd0Config {
101 pub base_address: u32,
102 pub pinmux: Sd0Pinmux,
103 pub init_sequence: Sd0InitSequence,
104}
105
106pub fn find_stub_config_offset(data: &[u8]) -> Option<usize> {
108 if data.len() < DRIVER_CONFIG_SIZE {
109 return None;
110 }
111 let last = data.len() - DRIVER_CONFIG_SIZE;
112 for offset in 0..=last {
113 let header = read_u32_le(data, offset)?;
114 if header != MAGIC_FLAG {
115 continue;
116 }
117 let version = read_u32_le(data, offset + 4)?;
118 if version != VERSION_FLAG {
119 continue;
120 }
121 let tail = read_u32_le(data, offset + DRIVER_CONFIG_SIZE - 4)?;
122 if tail == MAGIC_FLAG {
123 return Some(offset);
124 }
125 }
126 None
127}
128
129pub fn read_stub_config_from_bytes(data: &[u8]) -> Result<StubConfig> {
131 let offset = find_stub_config_offset(data)
132 .ok_or_else(|| Error::invalid_input("driver config block not found"))?;
133 read_stub_config_at(data, offset)
134}
135
136pub fn write_stub_config_to_bytes(data: &mut [u8], config: &StubConfig) -> Result<()> {
138 let offset = find_stub_config_offset(data)
139 .ok_or_else(|| Error::invalid_input("driver config block not found"))?;
140 write_stub_config_at(data, offset, config)
141}
142
143pub fn clear_stub_config_in_bytes(data: &mut [u8]) -> Result<()> {
145 let empty = StubConfig {
146 pins: Vec::new(),
147 flash: Vec::new(),
148 pmic: None,
149 sd0: None,
150 };
151 write_stub_config_to_bytes(data, &empty)
152}
153
154pub fn read_stub_config_from_file<P: AsRef<Path>>(path: P) -> Result<StubConfig> {
156 let data = std::fs::read(path)?;
157 read_stub_config_from_bytes(&data)
158}
159
160pub fn write_stub_config_to_file<P: AsRef<Path>>(path: P, config: &StubConfig) -> Result<()> {
162 let path = path.as_ref();
163 let mut data = std::fs::read(path)?;
164 write_stub_config_to_bytes(&mut data, config)?;
165 std::fs::write(path, data)?;
166 Ok(())
167}
168
169pub fn clear_stub_config_in_file<P: AsRef<Path>>(path: P) -> Result<()> {
171 let path = path.as_ref();
172 let mut data = std::fs::read(path)?;
173 clear_stub_config_in_bytes(&mut data)?;
174 std::fs::write(path, data)?;
175 Ok(())
176}
177
178pub fn read_stub_config_at(data: &[u8], offset: usize) -> Result<StubConfig> {
180 if data.len() < offset + DRIVER_CONFIG_SIZE {
181 return Err(Error::invalid_input("buffer too small for driver config"));
182 }
183
184 let pin_mask = read_u16_le(data, offset + 8)
185 .ok_or_else(|| Error::invalid_input("failed to read pin_mask from driver config"))?;
186 let flash_mask = read_u16_le(data, offset + 10)
187 .ok_or_else(|| Error::invalid_input("failed to read flash_mask from driver config"))?;
188 let pmic_mask = read_u8_required(data, offset + 12, "pmic_mask from driver config")?;
189 let sd0_mask = read_u8_required(data, offset + 13, "sd0_mask from driver config")?;
190
191 let mut pins = Vec::new();
192 let pin_base = offset + 16;
193 for index in 0..PIN_CFG_COUNT {
194 if (pin_mask & (1 << index)) == 0 {
195 continue;
196 }
197 let entry_offset = pin_base + index * 4;
198 let port = PinPort::try_from(read_u8_required(data, entry_offset, "pin port")?)?;
199 let number = read_u8_required(data, entry_offset + 1, "pin number")?;
200 let level = PinLevel::try_from(read_u8_required(data, entry_offset + 2, "pin level")?)?;
201 pins.push(PinConfig {
202 port,
203 number,
204 level,
205 });
206 }
207
208 let mut flash = Vec::new();
209 let flash_base = pin_base + PIN_CFG_COUNT * 4;
210 for index in 0..FLASH_CFG_COUNT {
211 if (flash_mask & (1 << index)) == 0 {
212 continue;
213 }
214 let entry_offset = flash_base + index * 12;
215 let media = FlashMedia::try_from(read_u8_required(data, entry_offset, "flash media")?)?;
216 let driver_index = read_u8_required(data, entry_offset + 1, "flash driver index")?;
217 let manufacturer_id = read_u8_required(data, entry_offset + 4, "flash manufacturer_id")?;
218 let device_type = read_u8_required(data, entry_offset + 5, "flash device_type")?;
219 let density_id = read_u8_required(data, entry_offset + 6, "flash density_id")?;
220 let flags = read_u8_required(data, entry_offset + 7, "flash flags")?;
221 let capacity_bytes = read_u32_le(data, entry_offset + 8).ok_or_else(|| {
222 Error::invalid_input("failed to read flash capacity from driver config")
223 })?;
224 flash.push(FlashConfig {
225 media,
226 driver_index,
227 manufacturer_id,
228 device_type,
229 density_id,
230 flags,
231 capacity_bytes,
232 });
233 }
234
235 let pmic_offset = flash_base + FLASH_CFG_COUNT * 12;
236 let pmic = if pmic_mask != 0 {
237 let disabled = read_u8_required(data, pmic_offset, "pmic disabled")? != 0;
238 let scl_port =
239 PinPort::try_from(read_u8_required(data, pmic_offset + 1, "pmic scl_port")?)?;
240 let scl_pin = read_u8_required(data, pmic_offset + 2, "pmic scl_pin")?;
241 let sda_port =
242 PinPort::try_from(read_u8_required(data, pmic_offset + 3, "pmic sda_port")?)?;
243 let sda_pin = read_u8_required(data, pmic_offset + 4, "pmic sda_pin")?;
244 let mut channels = Vec::new();
245 for idx in 0..PMIC_CHANNEL_COUNT {
246 let value = read_u8_required(data, pmic_offset + 6 + idx, "pmic channel")?;
247 if value != 0 {
248 channels.push(PmicChannel::try_from(idx as u8)?);
249 }
250 }
251 Some(PmicConfig {
252 disabled,
253 scl_port,
254 scl_pin,
255 sda_port,
256 sda_pin,
257 channels,
258 })
259 } else {
260 None
261 };
262
263 let sd0_offset = pmic_offset + 16;
264 let sd0 = if sd0_mask != 0 {
265 let base_address = read_u32_le(data, sd0_offset).ok_or_else(|| {
266 Error::invalid_input("failed to read sd0 base address from driver config")
267 })?;
268 let pinmux = Sd0Pinmux::try_from(read_u8_required(data, sd0_offset + 4, "sd0 pinmux")?)?;
269 let init_sequence = Sd0InitSequence::try_from(read_u8_required(
270 data,
271 sd0_offset + 5,
272 "sd0 init sequence",
273 )?)?;
274 Some(Sd0Config {
275 base_address,
276 pinmux,
277 init_sequence,
278 })
279 } else {
280 None
281 };
282
283 Ok(StubConfig {
284 pins,
285 flash,
286 pmic,
287 sd0,
288 })
289}
290
291pub fn write_stub_config_at(data: &mut [u8], offset: usize, config: &StubConfig) -> Result<()> {
293 if data.len() < offset + DRIVER_CONFIG_SIZE {
294 return Err(Error::invalid_input("buffer too small for driver config"));
295 }
296
297 if config.pins.len() > PIN_CFG_COUNT {
298 return Err(Error::invalid_input("pin entries exceed 12"));
299 }
300 if config.flash.len() > FLASH_CFG_COUNT {
301 return Err(Error::invalid_input("flash entries exceed 12"));
302 }
303
304 let block = build_stub_config_block(config)?;
305 let target = &mut data[offset..offset + DRIVER_CONFIG_SIZE];
306 target.copy_from_slice(&block);
307 Ok(())
308}
309
310fn build_stub_config_block(config: &StubConfig) -> Result<Vec<u8>> {
312 let pin_mask: u16 = if config.pins.is_empty() {
313 0
314 } else {
315 (1u16 << config.pins.len()) - 1
316 };
317 let flash_mask: u16 = if config.flash.is_empty() {
318 0
319 } else {
320 (1u16 << config.flash.len()) - 1
321 };
322 let pmic_mask: u8 = if config.pmic.is_some() { 1 } else { 0 };
323 let sd0_mask: u8 = if config.sd0.is_some() { 1 } else { 0 };
324
325 let mut buf = Vec::with_capacity(DRIVER_CONFIG_SIZE);
326 push_u32(&mut buf, MAGIC_FLAG);
327 push_u32(&mut buf, VERSION_FLAG);
328 push_u16(&mut buf, pin_mask);
329 push_u16(&mut buf, flash_mask);
330 push_u8(&mut buf, pmic_mask);
331 push_u8(&mut buf, sd0_mask);
332 push_u8(&mut buf, 0);
333 push_u8(&mut buf, 0);
334
335 for i in 0..PIN_CFG_COUNT {
336 if let Some(entry) = config.pins.get(i) {
337 push_u8(&mut buf, u8::from(entry.port));
338 push_u8(&mut buf, entry.number);
339 push_u8(&mut buf, u8::from(entry.level));
340 push_u8(&mut buf, 0);
341 } else {
342 buf.extend_from_slice(&[0u8; 4]);
343 }
344 }
345
346 for i in 0..FLASH_CFG_COUNT {
347 if let Some(entry) = config.flash.get(i) {
348 push_u8(&mut buf, u8::from(entry.media));
349 push_u8(&mut buf, entry.driver_index);
350 push_u8(&mut buf, 0);
351 push_u8(&mut buf, 0);
352 push_u8(&mut buf, entry.manufacturer_id);
353 push_u8(&mut buf, entry.device_type);
354 push_u8(&mut buf, entry.density_id);
355 push_u8(&mut buf, entry.flags);
356 push_u32(&mut buf, entry.capacity_bytes);
357 } else {
358 buf.extend_from_slice(&[0u8; 12]);
359 }
360 }
361
362 if let Some(pmic) = &config.pmic {
363 push_u8(&mut buf, if pmic.disabled { 1 } else { 0 });
364 push_u8(&mut buf, u8::from(pmic.scl_port));
365 push_u8(&mut buf, pmic.scl_pin);
366 push_u8(&mut buf, u8::from(pmic.sda_port));
367 push_u8(&mut buf, pmic.sda_pin);
368 push_u8(&mut buf, 0);
369
370 let mut channel_bytes = [0u8; PMIC_CHANNEL_COUNT];
371 for channel in &pmic.channels {
372 let index = channel.index();
373 if channel_bytes[index] != 0 {
374 return Err(Error::invalid_input("duplicate PMIC channel"));
375 }
376 channel_bytes[index] = 1;
377 }
378 buf.extend_from_slice(&channel_bytes);
379 } else {
380 buf.extend_from_slice(&[0u8; 16]);
381 }
382
383 if let Some(sd0) = &config.sd0 {
384 push_u32(&mut buf, sd0.base_address);
385 push_u8(&mut buf, u8::from(sd0.pinmux));
386 push_u8(&mut buf, u8::from(sd0.init_sequence));
387 push_u8(&mut buf, 0);
388 push_u8(&mut buf, 0);
389 } else {
390 buf.extend_from_slice(&[0u8; 8]);
391 }
392
393 push_u32(&mut buf, MAGIC_FLAG);
394
395 if buf.len() != DRIVER_CONFIG_SIZE {
396 return Err(Error::invalid_input("driver config block size mismatch"));
397 }
398 Ok(buf)
399}
400
401fn push_u8(buf: &mut Vec<u8>, value: u8) {
403 buf.push(value);
404}
405
406fn push_u16(buf: &mut Vec<u8>, value: u16) {
408 buf.extend_from_slice(&value.to_le_bytes());
409}
410
411fn push_u32(buf: &mut Vec<u8>, value: u32) {
413 buf.extend_from_slice(&value.to_le_bytes());
414}
415
416fn read_u8(data: &[u8], offset: usize) -> Option<u8> {
418 data.get(offset).copied()
419}
420
421fn read_u8_required(data: &[u8], offset: usize, label: &str) -> Result<u8> {
423 read_u8(data, offset).ok_or_else(|| Error::invalid_input(format!("failed to read {}", label)))
424}
425
426fn read_u16_le(data: &[u8], offset: usize) -> Option<u16> {
428 let bytes = data.get(offset..offset + 2)?;
429 Some(u16::from_le_bytes([bytes[0], bytes[1]]))
430}
431
432fn read_u32_le(data: &[u8], offset: usize) -> Option<u32> {
434 let bytes = data.get(offset..offset + 4)?;
435 Some(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
436}
437
438impl PinPort {
439 fn to_u8(self) -> u8 {
441 match self {
442 PinPort::Pa => 0,
443 PinPort::Pb => 1,
444 PinPort::Pbr => 2,
445 }
446 }
447}
448
449impl From<PinPort> for u8 {
450 fn from(value: PinPort) -> Self {
452 value.to_u8()
453 }
454}
455
456impl TryFrom<u8> for PinPort {
457 type Error = Error;
458
459 fn try_from(value: u8) -> Result<Self> {
461 match value {
462 0 => Ok(PinPort::Pa),
463 1 => Ok(PinPort::Pb),
464 2 => Ok(PinPort::Pbr),
465 _ => Err(Error::invalid_input("invalid pin port value")),
466 }
467 }
468}
469
470impl PinLevel {
471 fn to_u8(self) -> u8 {
473 match self {
474 PinLevel::Low => 0,
475 PinLevel::High => 1,
476 }
477 }
478}
479
480impl From<PinLevel> for u8 {
481 fn from(value: PinLevel) -> Self {
483 value.to_u8()
484 }
485}
486
487impl TryFrom<u8> for PinLevel {
488 type Error = Error;
489
490 fn try_from(value: u8) -> Result<Self> {
492 match value {
493 0 => Ok(PinLevel::Low),
494 1 => Ok(PinLevel::High),
495 _ => Err(Error::invalid_input("invalid pin level value")),
496 }
497 }
498}
499
500impl FlashMedia {
501 fn to_u8(self) -> u8 {
503 match self {
504 FlashMedia::Nor => 0,
505 FlashMedia::Nand => 1,
506 }
507 }
508}
509
510impl From<FlashMedia> for u8 {
511 fn from(value: FlashMedia) -> Self {
513 value.to_u8()
514 }
515}
516
517impl TryFrom<u8> for FlashMedia {
518 type Error = Error;
519
520 fn try_from(value: u8) -> Result<Self> {
522 match value {
523 0 => Ok(FlashMedia::Nor),
524 1 => Ok(FlashMedia::Nand),
525 _ => Err(Error::invalid_input("invalid flash media value")),
526 }
527 }
528}
529
530impl PmicChannel {
531 fn index(self) -> usize {
533 match self {
534 PmicChannel::LvSw1001 => 0,
535 PmicChannel::LvSw1002 => 1,
536 PmicChannel::LvSw1003 => 2,
537 PmicChannel::LvSw1004 => 3,
538 PmicChannel::LvSw1005 => 4,
539 PmicChannel::HvSw1501 => 5,
540 PmicChannel::HvSw1502 => 6,
541 PmicChannel::Ldo33 => 7,
542 PmicChannel::Ldo30 => 8,
543 PmicChannel::Ldo28 => 9,
544 }
545 }
546}
547
548impl TryFrom<u8> for PmicChannel {
549 type Error = Error;
550
551 fn try_from(value: u8) -> Result<Self> {
553 match value {
554 0 => Ok(PmicChannel::LvSw1001),
555 1 => Ok(PmicChannel::LvSw1002),
556 2 => Ok(PmicChannel::LvSw1003),
557 3 => Ok(PmicChannel::LvSw1004),
558 4 => Ok(PmicChannel::LvSw1005),
559 5 => Ok(PmicChannel::HvSw1501),
560 6 => Ok(PmicChannel::HvSw1502),
561 7 => Ok(PmicChannel::Ldo33),
562 8 => Ok(PmicChannel::Ldo30),
563 9 => Ok(PmicChannel::Ldo28),
564 _ => Err(Error::invalid_input("invalid PMIC channel index")),
565 }
566 }
567}
568
569impl Sd0Pinmux {
570 fn to_u8(self) -> u8 {
572 match self {
573 Sd0Pinmux::ClkPa34OrPa09 => 0,
574 Sd0Pinmux::ClkPa60OrPa39 => 1,
575 }
576 }
577}
578
579impl From<Sd0Pinmux> for u8 {
580 fn from(value: Sd0Pinmux) -> Self {
582 value.to_u8()
583 }
584}
585
586impl TryFrom<u8> for Sd0Pinmux {
587 type Error = Error;
588
589 fn try_from(value: u8) -> Result<Self> {
591 match value {
592 0 => Ok(Sd0Pinmux::ClkPa34OrPa09),
593 1 => Ok(Sd0Pinmux::ClkPa60OrPa39),
594 _ => Err(Error::invalid_input("invalid SD0 pinmux value")),
595 }
596 }
597}
598
599impl Sd0InitSequence {
600 fn to_u8(self) -> u8 {
602 match self {
603 Sd0InitSequence::EmmcThenSd => 0,
604 Sd0InitSequence::SdThenEmmc => 1,
605 }
606 }
607}
608
609impl From<Sd0InitSequence> for u8 {
610 fn from(value: Sd0InitSequence) -> Self {
612 value.to_u8()
613 }
614}
615
616impl TryFrom<u8> for Sd0InitSequence {
617 type Error = Error;
618
619 fn try_from(value: u8) -> Result<Self> {
621 match value {
622 0 => Ok(Sd0InitSequence::EmmcThenSd),
623 1 => Ok(Sd0InitSequence::SdThenEmmc),
624 _ => Err(Error::invalid_input("invalid SD0 init sequence value")),
625 }
626 }
627}