1use byteorder::{LittleEndian, ReadBytesExt};
6use serde::Serialize;
7use serde_annotate::Annotate;
8use std::convert::TryFrom;
9use std::time::Duration;
10use thiserror::Error;
11
12use crate::util::bitfield::BitField;
13
14#[derive(Debug, Error)]
15pub enum Error {
16 #[error(transparent)]
17 Io(#[from] std::io::Error),
18 #[error(transparent)]
19 TryFromIntError(#[from] std::num::TryFromIntError),
20 #[error("the range {0}..{1} is out of bounds")]
21 SliceRange(usize, usize),
22 #[error("SFDP header contains incorrect signature: {0:#010x}")]
23 WrongHeaderSignature(u32),
24
25 #[error(transparent)]
28 Infallible(#[from] std::convert::Infallible),
29}
30
31#[derive(Debug, Serialize, Annotate)]
33pub struct SfdpHeader {
34 #[annotate(format=hex, comment=comment_signature())]
35 pub signature: u32,
36 #[annotate(comment=comment_version())]
37 pub minor: u8,
38 pub major: u8,
39 #[annotate(comment = "Number of parameter headers minus one")]
40 pub nph: u8,
41 #[annotate(format=bin, comment="The reserved field should be all ones")]
42 pub reserved: u8,
43}
44
45impl SfdpHeader {
46 fn comment_signature(&self) -> Option<String> {
47 let signature = self.signature.to_le_bytes().map(|b| {
48 match b {
49 0x20..=0x7E => b as char,
51 _ => '.',
52 }
53 });
54 Some(format!(
55 "Signature value='{}{}{}{}' (should be 'SFDP')",
56 signature[0], signature[1], signature[2], signature[3],
57 ))
58 }
59 fn comment_version(&self) -> Option<String> {
60 Some(format!("{}.{}", self.major, self.minor))
61 }
62}
63
64impl TryFrom<&[u8]> for SfdpHeader {
65 type Error = Error;
66 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
67 const SFDP_HEADER_SIGNATURE: u32 = 0x50444653;
68
69 let mut reader = std::io::Cursor::new(buf);
70 let header = SfdpHeader {
71 signature: reader.read_u32::<LittleEndian>()?,
72 minor: reader.read_u8()?,
73 major: reader.read_u8()?,
74 nph: reader.read_u8()?,
75 reserved: reader.read_u8()?,
76 };
77 match header.signature {
78 SFDP_HEADER_SIGNATURE => Ok(header),
79 v => Err(Error::WrongHeaderSignature(v)),
80 }
81 }
82}
83
84#[derive(Debug, Serialize)]
87pub struct SfdpPhdr {
88 pub id: u8,
89 pub minor: u8,
90 pub major: u8,
91 pub dwords: u8,
92 pub offset: u32,
93}
94
95impl TryFrom<&[u8]> for SfdpPhdr {
96 type Error = Error;
97 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
98 let mut reader = std::io::Cursor::new(buf);
99 Ok(SfdpPhdr {
100 id: reader.read_u8()?,
101 minor: reader.read_u8()?,
102 major: reader.read_u8()?,
103 dwords: reader.read_u8()?,
104 offset: reader.read_u32::<LittleEndian>()? & 0x00FFFFFFu32,
105 })
106 }
107}
108
109struct InternalJedecParams {
112 pub data: Vec<u32>,
113}
114
115impl TryFrom<&[u8]> for InternalJedecParams {
116 type Error = Error;
117 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
118 let mut reader = std::io::Cursor::new(buf);
119 let mut data = vec![0u32; buf.len() / 4];
120 reader.read_u32_into::<LittleEndian>(&mut data)?;
121 Ok(InternalJedecParams { data })
122 }
123}
124
125macro_rules! field {
136 ($name:ident -> bool, $field:expr, $bitoffset:expr, $bitsize:expr) => {
138 pub fn $name(&self) -> Result<bool, Error> {
139 Ok(BitField::new($bitoffset, $bitsize).extract(self.data[$field - 1]) != 0)
140 }
141 };
142 ($name:ident -> u32, $field:expr, 0, 32) => {
144 pub fn $name(&self) -> Result<u32, Error> {
145 Ok(self.data[$field - 1])
146 }
147 };
148 ($name:ident -> u32, $field:expr, $bitoffset:expr, $bitsize:expr) => {
150 pub fn $name(&self) -> Result<u32, Error> {
151 Ok(BitField::new($bitoffset, $bitsize).extract(self.data[$field - 1]))
152 }
153 };
154 ($name:ident -> $type:ty, $field:expr, $bitoffset:expr, $bitsize:expr) => {
156 pub fn $name(&self) -> Result<$type, Error> {
157 Ok(<$type>::try_from(
158 BitField::new($bitoffset, $bitsize).extract(self.data[$field - 1]),
159 )?)
160 }
161 };
162}
163
164impl InternalJedecParams {
165 field!(block_erase_size -> BlockEraseSize, 1, 0, 2);
166 field!(write_granularity -> WriteGranularity, 1, 2, 1);
167 field!(write_en_required -> bool, 1, 3, 1);
168 field!(write_en_opcode -> bool, 1, 4, 1);
169 field!(erase_opcode_4kib -> u8, 1, 8, 8);
170 field!(support_fast_read_112 -> bool, 1, 16, 1);
171 field!(address_modes -> SupportedAddressModes, 1, 17, 2);
172 field!(support_double_rate_clocking -> bool, 1, 19, 1);
173 field!(support_fast_read_122 -> bool, 1, 20, 1);
174 field!(support_fast_read_144 -> bool, 1, 21, 1);
175 field!(support_fast_read_114 -> bool, 1, 22, 1);
176
177 field!(density -> u32, 2, 0, 31);
178 field!(density_pow2 -> bool, 2, 31, 1);
179
180 field!(wait_states_144 -> u8, 3, 0, 5);
181 field!(mode_bits_144 -> u8, 3, 5, 3);
182 field!(read_opcode_144 -> u8, 3, 8, 8);
183 field!(wait_states_114 -> u8, 3, 16, 5);
184 field!(mode_bits_114 -> u8, 3, 21, 3);
185 field!(read_opcode_114 -> u8, 3, 24, 8);
186
187 field!(wait_states_112 -> u8, 4, 0, 5);
188 field!(mode_bits_112 -> u8, 4, 5, 3);
189 field!(read_opcode_112 -> u8, 4, 8, 8);
190 field!(wait_states_122 -> u8, 4, 16, 5);
191 field!(mode_bits_122 -> u8, 4, 21, 3);
192 field!(read_opcode_122 -> u8, 4, 24, 8);
193
194 field!(support_fast_read_222 -> bool, 5, 0, 1);
195 field!(support_fast_read_444 -> bool, 5, 4, 1);
196
197 field!(wait_states_222 -> u8, 6, 16, 5);
198 field!(mode_bits_222 -> u8, 6, 21, 3);
199 field!(read_opcode_222 -> u8, 6, 24, 8);
200
201 field!(wait_states_444 -> u8, 7, 16, 5);
202 field!(mode_bits_444 -> u8, 7, 21, 3);
203 field!(read_opcode_444 -> u8, 7, 24, 8);
204
205 field!(sector_type1_size -> u8, 8, 0, 8);
206 field!(sector_type1_opcode -> u8, 8, 8, 8);
207 field!(sector_type2_size -> u8, 8, 16, 8);
208 field!(sector_type2_opcode -> u8, 8, 24, 8);
209
210 field!(sector_type3_size -> u8, 9, 0, 8);
211 field!(sector_type3_opcode -> u8, 9, 8, 8);
212 field!(sector_type4_size -> u8, 9, 16, 8);
213 field!(sector_type4_opcode -> u8, 9, 24, 8);
214
215 field!(erase_time_multiplier -> u32, 10, 0, 4);
217 field!(erase_type1_time -> u32, 10, 4, 5);
218 field!(erase_type1_unit -> usize, 10, 9, 2);
219 field!(erase_type2_time -> u32, 10, 11, 5);
220 field!(erase_type2_unit -> usize, 10, 16, 2);
221 field!(erase_type3_time -> u32, 10, 18, 5);
222 field!(erase_type3_unit -> usize, 10, 23, 2);
223 field!(erase_type4_time -> u32, 10, 25, 5);
224 field!(erase_type4_unit -> usize, 10, 30, 2);
225
226 field!(pgm_time_multiplier -> u32, 11, 0, 4);
228 field!(page_size -> u32, 11, 4, 4);
229 field!(page_pgm_time -> u32, 11, 8, 5);
230 field!(page_pgm_unit -> usize, 11, 13, 1);
231 field!(byte_pgm_time -> u32, 11, 14, 4);
232 field!(byte_pgm_unit -> usize, 11, 18, 1);
233 field!(additional_byte_pgm_time -> u32, 11, 19, 4);
234 field!(additional_byte_pgm_unit -> usize, 11, 23, 1);
235 field!(chip_erase_time -> u32, 11, 24, 5);
236 field!(chip_erase_unit -> usize, 11, 29, 2);
237
238 field!(prohibited_pgm_suspend -> u8, 12, 0, 4);
240 field!(prohibited_erase_suspend -> u8, 12, 4, 4);
241 field!(pgm_resume_to_suspend -> u32, 12, 9, 4);
242 field!(suspend_pgm_latency_time -> u32, 12, 13, 5);
243 field!(suspend_pgm_latency_unit -> usize, 12, 18, 2);
244 field!(erase_resume_to_suspend -> u32, 12, 20, 4);
245 field!(suspend_erase_latency_time -> u32, 12, 24, 5);
246 field!(suspend_erase_latency_unit -> usize, 12, 29, 2);
247 field!(suspend_resume_supported -> bool, 12, 31, 1);
248
249 field!(pgm_resume_instruction -> u8, 13, 0, 8);
251 field!(pgm_suspend_instruction -> u8, 13, 8, 8);
252 field!(resume_instruction -> u8, 13, 16, 8);
253 field!(suspend_instruction -> u8, 13, 24, 8);
254
255 field!(status_busy_polling -> u8, 14, 2, 6);
257 field!(exit_deep_powerdown_time -> u32, 14, 8, 5);
258 field!(exit_deep_powerdown_unit -> usize, 14, 13, 2);
259 field!(exit_deep_powerdown_instruction -> u8, 14, 15, 8);
260 field!(enter_deep_powerdown_instruction -> u8, 14, 23, 8);
261 field!(deep_powerdown_supported -> bool, 14, 31, 1);
262
263 field!(mode_444_disable -> u8, 15, 0, 4);
265 field!(mode_444_enable -> u8, 15, 4, 5);
266 field!(mode_444_supported -> bool, 15, 9, 1);
267 field!(mode_444_exit -> u8, 15, 10, 6);
268 field!(mode_444_entry -> u8, 15, 16, 4);
269 field!(quad_enable_requirements -> u8, 15, 20, 3);
270 field!(hold_or_reset_disable -> bool, 15, 23, 1);
271
272 field!(status_reg1_write_enable -> u8, 16, 0, 6);
274 field!(soft_reset_support -> u8, 16, 8, 6);
275 field!(exit_4b_addressing -> u16, 16, 14, 10);
276 field!(enter_4b_addressing -> u8, 16, 24, 8);
277
278 field!(wait_states_188 -> u8, 17, 0, 5);
280 field!(mode_bits_188 -> u8, 17, 5, 3);
281 field!(read_opcode_188 -> u8, 17, 8, 8);
282 field!(wait_states_118 -> u8, 17, 16, 5);
283 field!(mode_bits_118 -> u8, 17, 21, 3);
284 field!(read_opcode_118 -> u8, 17, 24, 8);
285
286 field!(output_driver_strength -> u8, 18, 18, 5);
288 field!(spi_protocol_reset -> bool, 18, 23, 1);
289 field!(data_strobe_str -> u8, 18, 24, 2);
290 field!(data_qpi_str -> bool, 18, 26, 1);
291 field!(data_qpi_dtr -> bool, 18, 27, 1);
292 field!(octal_dtr_command -> u8, 18, 29, 2);
293 field!(octal_byte_order -> u8, 18, 31, 1);
294
295 field!(mode_8s8s8s_disable-> u8, 19, 0, 4);
297 field!(mode_8s8s8s_enable-> u8, 19, 4, 5);
298 field!(mode_088_supported -> bool, 19, 9, 1);
299 field!(mode_088_exit -> u8, 19, 10, 6);
300 field!(mode_088_enter -> u8, 19, 16, 4);
301 field!(octal_enable_requirements -> u8, 19, 20, 3);
302
303 field!(max_speed_4s4s4s_no_strobe -> MaxSpeed, 20, 0, 4);
305 field!(max_speed_4s4s4s_strobe -> MaxSpeed, 20, 4, 4);
306 field!(max_speed_4d4d4d_no_strobe -> MaxSpeed, 20, 8, 4);
307 field!(max_speed_4d4d4d_strobe -> MaxSpeed, 20, 12, 4);
308 field!(max_speed_8s8s8s_no_strobe -> MaxSpeed, 20, 16, 4);
309 field!(max_speed_8s8s8s_strobe -> MaxSpeed, 20, 20, 4);
310 field!(max_speed_8d8d8d_no_strobe -> MaxSpeed, 20, 24, 4);
311 field!(max_speed_8d8d8d_strobe -> MaxSpeed, 20, 28, 4);
312
313 field!(support_fast_read_1s1d1d -> bool, 21, 0, 1);
315 field!(support_fast_read_1s2d2d -> bool, 21, 1, 1);
316 field!(support_fast_read_1s4d4d -> bool, 21, 2, 1);
317 field!(support_fast_read_4s4d4d -> bool, 21, 3, 1);
318
319 field!(wait_states_1s1d1d -> u8, 22, 0, 5);
321 field!(mode_bits_1s1d1d -> u8, 22, 5, 3);
322 field!(read_opcode_1s1d1d -> u8, 22, 8, 8);
323 field!(wait_states_1s2d2d -> u8, 22, 16, 5);
324 field!(mode_bits_1s2d2d -> u8, 22, 21, 3);
325 field!(read_opcode_1s2d2d -> u8, 22, 24, 8);
326
327 field!(wait_states_1s4d4d -> u8, 23, 0, 5);
329 field!(mode_bits_1s4d4d -> u8, 23, 5, 3);
330 field!(read_opcode_1s4d4d -> u8, 23, 8, 8);
331 field!(wait_states_4s4d4d -> u8, 23, 16, 5);
332 field!(mode_bits_4s4d4d -> u8, 23, 21, 3);
333 field!(read_opcode_4s4d4d -> u8, 23, 24, 8);
334}
335
336#[derive(Default, Debug, Eq, PartialEq, strum::FromRepr, Clone, Copy, Serialize)]
339#[repr(u32)]
340pub enum BlockEraseSize {
341 Reserved0 = 0,
342 Block4KiB = 1,
343 Reserved2 = 2,
344 BlockNot4KiB = 3,
345 #[default]
346 Invalid,
347}
348
349impl From<u32> for BlockEraseSize {
350 fn from(val: u32) -> Self {
351 Self::from_repr(val).unwrap_or(Self::Invalid)
352 }
353}
354
355#[derive(Default, Debug, Eq, PartialEq, strum::FromRepr, Clone, Copy, Serialize)]
358#[repr(u32)]
359pub enum WriteGranularity {
360 Granularity1Byte = 0,
361 Granularity64Bytes = 1,
362 #[default]
363 Invalid,
364}
365
366impl From<u32> for WriteGranularity {
367 fn from(val: u32) -> Self {
368 Self::from_repr(val).unwrap_or(Self::Invalid)
369 }
370}
371
372#[derive(Default, Debug, Eq, PartialEq, strum::FromRepr, Clone, Copy, Serialize)]
375#[repr(u32)]
376pub enum SupportedAddressModes {
377 Mode3b = 0,
378 Mode3b4b = 1,
379 Mode4b = 2,
380 Reserved = 3,
381 #[default]
382 Invalid,
383}
384
385impl From<u32> for SupportedAddressModes {
386 fn from(val: u32) -> Self {
387 Self::from_repr(val).unwrap_or(Self::Invalid)
388 }
389}
390
391#[derive(Default, Debug, Eq, PartialEq, strum::FromRepr, Clone, Copy, Serialize)]
392#[repr(u32)]
393pub enum MaxSpeed {
394 Reserved0 = 0,
395 Speed33MHz,
396 Speed50MHz,
397 Speed66MHz,
398 Speed80MHz,
399 Speed100MHz,
400 Speed133MHz,
401 Speed166MHz,
402 Speed200MHz,
403 Speed250MHz,
404 Speed266MHz,
405 Speed333MHz,
406 Speed400MHz,
407 Reserved10,
408 NotCharacterized,
409 #[default]
410 NotSupported,
411}
412
413impl From<u32> for MaxSpeed {
414 fn from(val: u32) -> Self {
415 Self::from_repr(val).unwrap_or(Self::NotSupported)
416 }
417}
418
419#[derive(Clone, Default, Debug, Serialize, Annotate)]
421pub struct FastReadParam {
422 pub wait_states: u8,
423 pub mode_bits: u8,
424 #[annotate(format=hex)]
425 pub opcode: u8,
426}
427
428#[derive(Clone, Default, Debug, Serialize, Annotate)]
430pub struct SectorErase {
431 pub size: u32,
432 #[annotate(format=hex)]
433 pub opcode: u8,
434 pub time: Option<TimeBound>,
435}
436
437#[derive(Clone, Default, Debug, Serialize)]
438pub struct TimeBound {
439 #[serde(with = "humantime_serde")]
440 pub typical: Duration,
441 #[serde(with = "humantime_serde")]
442 pub maximum: Duration,
443}
444
445#[derive(Default, Debug, Serialize, Annotate)]
464pub struct JedecParams {
465 pub block_erase_size: BlockEraseSize,
467 pub write_granularity: WriteGranularity,
469 pub write_en_required: bool,
471 #[annotate(format=hex)]
474 pub write_en_opcode: u8,
475 #[annotate(format=hex)]
477 pub erase_opcode_4kib: u8,
478 pub support_fast_read_112: bool,
480 pub address_modes: SupportedAddressModes,
482 pub support_double_rate_clocking: bool,
484 pub support_fast_read_122: bool,
490 pub support_fast_read_144: bool,
491 pub support_fast_read_114: bool,
492 pub support_fast_read_222: bool,
493 pub support_fast_read_444: bool,
494
495 pub density: u32,
498 pub param_112: FastReadParam,
500 pub param_122: FastReadParam,
501 pub param_114: FastReadParam,
502 pub param_144: FastReadParam,
503 pub param_222: FastReadParam,
504 pub param_444: FastReadParam,
505 pub erase: [SectorErase; 4],
508
509 pub rev_b: Option<JedecParamsRevB>,
511 pub rev_d: Option<JedecParamsRevD>,
512 pub rev_f: Option<JedecParamsRevF>,
513}
514
515#[derive(Default, Debug, Serialize, Annotate)]
517pub struct JedecParamsRevB {
518 pub page_size: u32,
519 pub page_program_time: TimeBound,
520 pub byte_program_time: TimeBound,
521 pub additional_byte_program_time: TimeBound,
522 pub chip_erase_time: TimeBound,
523
524 pub suspend_resume_supported: bool,
525 pub prohibited_ops_program_suspend: u8,
526 pub prohibited_ops_erase_suspend: u8,
527 #[serde(with = "humantime_serde")]
528 pub program_resume_to_suspend: Duration,
529 #[serde(with = "humantime_serde")]
530 pub suspend_in_progress_program_latency: Duration,
531 #[serde(with = "humantime_serde")]
532 pub erase_resume_to_suspend: Duration,
533 #[serde(with = "humantime_serde")]
534 pub suspend_in_progress_erase_latency: Duration,
535 #[annotate(format=hex)]
536 pub program_resume_instruction: u8,
537 #[annotate(format=hex)]
538 pub program_suspend_instruction: u8,
539 #[annotate(format=hex)]
540 pub resume_instruction: u8,
541 #[annotate(format=hex)]
542 pub suspend_instruction: u8,
543
544 pub deep_powerdown_supported: bool,
545 #[annotate(format=hex)]
546 pub enter_deep_powerdown_instruction: u8,
547 #[annotate(format=hex)]
548 pub exit_deep_powerdown_instruction: u8,
549 #[serde(with = "humantime_serde")]
550 pub exit_deep_powerdown_delay: Duration,
551 pub status_register_polling: u8,
552
553 pub hold_or_reset_disable: bool,
554 pub quad_enable_requirements: u8,
555 pub mode_444_entry: u8,
556 pub mode_444_exit: u8,
557 pub mode_444_supported: bool,
558 pub mode_444_disable: u8,
559 pub mode_444_enable: u8,
560
561 pub enter_4b_addressing: u8,
562 pub exit_4b_addressing: u16,
563 pub soft_reset_support: u8,
564 pub status_reg1_write_enable: u8,
565}
566
567#[derive(Default, Debug, Serialize)]
569pub struct JedecParamsRevD {
570 pub param_118: FastReadParam,
571 pub param_188: FastReadParam,
572
573 pub output_driver_strength: u8,
574 pub jedec_spi_protocol_reset: bool,
575 pub data_strobe_waveform_str: u8,
576 pub data_strobe_support_4s4s4s: bool,
577 pub data_strobe_support_4d4d4d: bool,
578 pub octal_dtr_command: u8,
579 pub octal_byte_order: u8,
580
581 pub mode_8s8s8s_disable: u8,
582 pub mode_8s8s8s_enable: u8,
583 pub mode_088_supported: bool,
584 pub mode_088_exit: u8,
585 pub mode_088_enter: u8,
586 pub octal_enable_requirements: u8,
587
588 pub max_speed_4s4s4s_no_strobe: MaxSpeed,
589 pub max_speed_4s4s4s_strobe: MaxSpeed,
590 pub max_speed_4d4d4d_no_strobe: MaxSpeed,
591 pub max_speed_4d4d4d_strobe: MaxSpeed,
592 pub max_speed_8s8s8s_no_strobe: MaxSpeed,
593 pub max_speed_8s8s8s_strobe: MaxSpeed,
594 pub max_speed_8d8d8d_no_strobe: MaxSpeed,
595 pub max_speed_8d8d8d_strobe: MaxSpeed,
596}
597
598#[derive(Default, Debug, Serialize)]
600pub struct JedecParamsRevF {
601 pub param_1s1d1d: Option<FastReadParam>,
602 pub param_1s2d2d: Option<FastReadParam>,
603 pub param_1s4d4d: Option<FastReadParam>,
604 pub param_4s4d4d: Option<FastReadParam>,
605}
606
607impl JedecParams {
608 const ERASE_TIME_UNITS: [Duration; 4] = [
610 Duration::from_millis(1),
611 Duration::from_millis(16),
612 Duration::from_millis(128),
613 Duration::from_secs(1),
614 ];
615 const CHIP_ERASE_UNITS: [Duration; 4] = [
617 Duration::from_millis(16),
618 Duration::from_millis(256),
619 Duration::from_secs(4),
620 Duration::from_secs(64),
621 ];
622 const PAGE_PGM_UNITS: [Duration; 2] = [Duration::from_micros(8), Duration::from_micros(64)];
624 const BYTE_PGM_UNITS: [Duration; 2] = [Duration::from_micros(1), Duration::from_micros(8)];
626 const SUSPEND_RESUME_UNITS: [Duration; 4] = [
628 Duration::from_nanos(128),
629 Duration::from_micros(1),
630 Duration::from_micros(8),
631 Duration::from_micros(64),
632 ];
633
634 fn pow2_size(shift: u8) -> u32 {
635 if shift == 0 { 0 } else { 1u32 << shift }
636 }
637}
638
639impl TryFrom<&[u8]> for JedecParams {
640 type Error = Error;
641 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
642 let p = InternalJedecParams::try_from(buf)?;
643 let size_bytes = if p.density_pow2()? {
644 1u32 << ((p.density()? & 0x7FFF_FFFF) - 8)
645 } else {
646 (p.density()? + 1) / 8
647 };
648 let mut jedec = JedecParams {
649 block_erase_size: p.block_erase_size()?,
650 write_granularity: p.write_granularity()?,
651 write_en_required: p.write_en_required()?,
652 write_en_opcode: if p.write_en_opcode()? { 0x50 } else { 0x06 },
653 erase_opcode_4kib: p.erase_opcode_4kib()?,
654 support_fast_read_112: p.support_fast_read_112()?,
655 address_modes: p.address_modes()?,
656 support_double_rate_clocking: p.support_double_rate_clocking()?,
657 support_fast_read_122: p.support_fast_read_122()?,
658 support_fast_read_144: p.support_fast_read_144()?,
659 support_fast_read_114: p.support_fast_read_114()?,
660 support_fast_read_222: p.support_fast_read_222()?,
661 support_fast_read_444: p.support_fast_read_444()?,
662 density: size_bytes,
663 erase: [
664 SectorErase {
665 size: Self::pow2_size(p.sector_type1_size()?),
666 opcode: p.sector_type1_opcode()?,
667 time: None,
668 },
669 SectorErase {
670 size: Self::pow2_size(p.sector_type2_size()?),
671 opcode: p.sector_type2_opcode()?,
672 time: None,
673 },
674 SectorErase {
675 size: Self::pow2_size(p.sector_type3_size()?),
676 opcode: p.sector_type3_opcode()?,
677 time: None,
678 },
679 SectorErase {
680 size: Self::pow2_size(p.sector_type4_size()?),
681 opcode: p.sector_type4_opcode()?,
682 time: None,
683 },
684 ],
685 ..Default::default()
686 };
687 if jedec.support_fast_read_112 {
688 jedec.param_112 = FastReadParam {
689 wait_states: p.wait_states_112()?,
690 mode_bits: p.mode_bits_112()?,
691 opcode: p.read_opcode_112()?,
692 }
693 }
694 if jedec.support_fast_read_122 {
695 jedec.param_122 = FastReadParam {
696 wait_states: p.wait_states_122()?,
697 mode_bits: p.mode_bits_122()?,
698 opcode: p.read_opcode_122()?,
699 }
700 }
701 if jedec.support_fast_read_144 {
702 jedec.param_144 = FastReadParam {
703 wait_states: p.wait_states_144()?,
704 mode_bits: p.mode_bits_144()?,
705 opcode: p.read_opcode_144()?,
706 }
707 }
708 if jedec.support_fast_read_114 {
709 jedec.param_114 = FastReadParam {
710 wait_states: p.wait_states_114()?,
711 mode_bits: p.mode_bits_114()?,
712 opcode: p.read_opcode_114()?,
713 }
714 }
715 if jedec.support_fast_read_222 {
716 jedec.param_222 = FastReadParam {
717 wait_states: p.wait_states_222()?,
718 mode_bits: p.mode_bits_222()?,
719 opcode: p.read_opcode_222()?,
720 }
721 }
722 if jedec.support_fast_read_444 {
723 jedec.param_444 = FastReadParam {
724 wait_states: p.wait_states_444()?,
725 mode_bits: p.mode_bits_444()?,
726 opcode: p.read_opcode_444()?,
727 }
728 }
729 if p.data.len() >= 16 {
730 let mult = 2 * (p.erase_time_multiplier()? + 1);
731 let type1 = Self::ERASE_TIME_UNITS[p.erase_type1_unit()?] * (p.erase_type1_time()? + 1);
732 let type2 = Self::ERASE_TIME_UNITS[p.erase_type2_unit()?] * (p.erase_type2_time()? + 1);
733 let type3 = Self::ERASE_TIME_UNITS[p.erase_type3_unit()?] * (p.erase_type3_time()? + 1);
734 let type4 = Self::ERASE_TIME_UNITS[p.erase_type4_unit()?] * (p.erase_type4_time()? + 1);
735 jedec.erase[0].time = Some(TimeBound {
736 typical: type1,
737 maximum: type1 * mult,
738 });
739 jedec.erase[1].time = Some(TimeBound {
740 typical: type2,
741 maximum: type2 * mult,
742 });
743 jedec.erase[2].time = Some(TimeBound {
744 typical: type3,
745 maximum: type3 * mult,
746 });
747 jedec.erase[3].time = Some(TimeBound {
748 typical: type4,
749 maximum: type4 * mult,
750 });
751
752 let mult = 2 * (p.pgm_time_multiplier()? + 1);
753 let chip_erase_unit = Self::CHIP_ERASE_UNITS[p.chip_erase_unit()?];
754 let page_pgm_unit = Self::PAGE_PGM_UNITS[p.page_pgm_unit()?];
755 let byte_pgm_unit = Self::BYTE_PGM_UNITS[p.byte_pgm_unit()?];
756 let additional_byte_pgm_unit = Self::BYTE_PGM_UNITS[p.additional_byte_pgm_unit()?];
757
758 jedec.rev_b = Some(JedecParamsRevB {
759 page_size: 1u32 << p.page_size()?,
760 page_program_time: TimeBound {
761 typical: page_pgm_unit * (1 + p.page_pgm_time()?),
762 maximum: page_pgm_unit * (1 + p.page_pgm_time()?) * mult,
763 },
764 byte_program_time: TimeBound {
765 typical: byte_pgm_unit * (1 + p.byte_pgm_time()?),
766 maximum: byte_pgm_unit * (1 + p.byte_pgm_time()?) * mult,
767 },
768 additional_byte_program_time: TimeBound {
769 typical: additional_byte_pgm_unit * (1 + p.additional_byte_pgm_time()?),
770 maximum: additional_byte_pgm_unit * (1 + p.additional_byte_pgm_time()?) * mult,
771 },
772 chip_erase_time: TimeBound {
773 typical: chip_erase_unit * (1 + p.chip_erase_time()?),
774 maximum: chip_erase_unit * (1 + p.chip_erase_time()?) * mult,
775 },
776
777 suspend_resume_supported: !p.suspend_resume_supported()?,
778 prohibited_ops_program_suspend: p.prohibited_pgm_suspend()?,
779 prohibited_ops_erase_suspend: p.prohibited_erase_suspend()?,
780 program_resume_to_suspend: Duration::from_millis(64)
781 * (1 + p.pgm_resume_to_suspend()?),
782 suspend_in_progress_program_latency: Self::SUSPEND_RESUME_UNITS
783 [p.suspend_pgm_latency_unit()?]
784 * (1 + p.suspend_pgm_latency_time()?),
785 erase_resume_to_suspend: Duration::from_millis(64)
786 * (1 + p.erase_resume_to_suspend()?),
787 suspend_in_progress_erase_latency: Self::SUSPEND_RESUME_UNITS
788 [p.suspend_erase_latency_unit()?]
789 * (1 + p.suspend_erase_latency_time()?),
790 program_resume_instruction: p.pgm_resume_instruction()?,
791 program_suspend_instruction: p.pgm_suspend_instruction()?,
792 resume_instruction: p.suspend_instruction()?,
793 suspend_instruction: p.resume_instruction()?,
794
795 deep_powerdown_supported: !p.deep_powerdown_supported()?,
796 enter_deep_powerdown_instruction: p.enter_deep_powerdown_instruction()?,
797 exit_deep_powerdown_instruction: p.exit_deep_powerdown_instruction()?,
798 exit_deep_powerdown_delay: Self::SUSPEND_RESUME_UNITS
799 [p.exit_deep_powerdown_unit()?]
800 * (1 + p.exit_deep_powerdown_time()?),
801 status_register_polling: p.status_busy_polling()?,
802
803 hold_or_reset_disable: p.hold_or_reset_disable()?,
804 quad_enable_requirements: p.quad_enable_requirements()?,
805 mode_444_entry: p.mode_444_entry()?,
806 mode_444_exit: p.mode_444_exit()?,
807 mode_444_supported: p.mode_444_supported()?,
808 mode_444_disable: p.mode_444_disable()?,
809 mode_444_enable: p.mode_444_enable()?,
810
811 enter_4b_addressing: p.enter_4b_addressing()?,
812 exit_4b_addressing: p.exit_4b_addressing()?,
813 soft_reset_support: p.soft_reset_support()?,
814 status_reg1_write_enable: p.status_reg1_write_enable()?,
815 });
816 }
817 if p.data.len() >= 20 {
818 jedec.rev_d = Some(JedecParamsRevD {
819 param_118: FastReadParam {
820 wait_states: p.wait_states_118()?,
821 mode_bits: p.mode_bits_118()?,
822 opcode: p.read_opcode_118()?,
823 },
824 param_188: FastReadParam {
825 wait_states: p.wait_states_188()?,
826 mode_bits: p.mode_bits_188()?,
827 opcode: p.read_opcode_188()?,
828 },
829
830 output_driver_strength: p.output_driver_strength()?,
831 jedec_spi_protocol_reset: p.spi_protocol_reset()?,
832 data_strobe_waveform_str: p.data_strobe_str()?,
833 data_strobe_support_4s4s4s: p.data_qpi_str()?,
834 data_strobe_support_4d4d4d: p.data_qpi_dtr()?,
835 octal_dtr_command: p.octal_dtr_command()?,
836 octal_byte_order: p.octal_byte_order()?,
837
838 mode_8s8s8s_disable: p.mode_8s8s8s_disable()?,
839 mode_8s8s8s_enable: p.mode_8s8s8s_enable()?,
840 mode_088_supported: p.mode_088_supported()?,
841 mode_088_exit: p.mode_088_exit()?,
842 mode_088_enter: p.mode_088_enter()?,
843 octal_enable_requirements: p.octal_enable_requirements()?,
844
845 max_speed_4s4s4s_no_strobe: p.max_speed_4s4s4s_no_strobe()?,
846 max_speed_4s4s4s_strobe: p.max_speed_4s4s4s_strobe()?,
847 max_speed_4d4d4d_no_strobe: p.max_speed_4d4d4d_no_strobe()?,
848 max_speed_4d4d4d_strobe: p.max_speed_4d4d4d_strobe()?,
849 max_speed_8s8s8s_no_strobe: p.max_speed_8s8s8s_no_strobe()?,
850 max_speed_8s8s8s_strobe: p.max_speed_8s8s8s_strobe()?,
851 max_speed_8d8d8d_no_strobe: p.max_speed_8d8d8d_no_strobe()?,
852 max_speed_8d8d8d_strobe: p.max_speed_8d8d8d_strobe()?,
853 });
854 }
855 if p.data.len() >= 23 {
856 let mut rev_f = JedecParamsRevF::default();
857 if p.support_fast_read_1s1d1d()? {
858 rev_f.param_1s1d1d = Some(FastReadParam {
859 wait_states: p.wait_states_1s1d1d()?,
860 mode_bits: p.mode_bits_1s1d1d()?,
861 opcode: p.read_opcode_1s1d1d()?,
862 });
863 }
864 if p.support_fast_read_1s2d2d()? {
865 rev_f.param_1s2d2d = Some(FastReadParam {
866 wait_states: p.wait_states_1s2d2d()?,
867 mode_bits: p.mode_bits_1s2d2d()?,
868 opcode: p.read_opcode_1s2d2d()?,
869 });
870 }
871 if p.support_fast_read_1s4d4d()? {
872 rev_f.param_1s4d4d = Some(FastReadParam {
873 wait_states: p.wait_states_1s4d4d()?,
874 mode_bits: p.mode_bits_1s4d4d()?,
875 opcode: p.read_opcode_1s4d4d()?,
876 });
877 }
878 if p.support_fast_read_4s4d4d()? {
879 rev_f.param_4s4d4d = Some(FastReadParam {
880 wait_states: p.wait_states_4s4d4d()?,
881 mode_bits: p.mode_bits_4s4d4d()?,
882 opcode: p.read_opcode_4s4d4d()?,
883 });
884 }
885 jedec.rev_f = Some(rev_f);
886 }
887 Ok(jedec)
888 }
889}
890
891#[derive(Debug, Serialize)]
894pub struct UnknownParams {
895 pub data: Vec<u32>,
896}
897
898impl TryFrom<&[u8]> for UnknownParams {
899 type Error = Error;
900 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
901 let mut reader = std::io::Cursor::new(buf);
902 let mut data = vec![0u32; buf.len() / 4];
903 reader.read_u32_into::<LittleEndian>(&mut data)?;
904 Ok(UnknownParams { data })
905 }
906}
907
908#[derive(Debug, Serialize)]
910pub struct Sfdp {
911 pub header: SfdpHeader,
912 pub phdr: Vec<SfdpPhdr>,
913 pub jedec: JedecParams,
914 pub params: Vec<UnknownParams>,
915}
916
917impl Sfdp {
918 pub fn length_required(buf: &[u8]) -> Result<usize, Error> {
921 if buf.len() < 256 {
922 Ok(256)
932 } else {
933 let header = SfdpHeader::try_from(&buf[0..8])?;
934 let mut len = 0;
935 for i in 0..=header.nph {
936 let start = (8 + i * 8) as usize;
937 let end = start + 8;
938 let phdr = SfdpPhdr::try_from(&buf[start..end])?;
939 len = std::cmp::max(len, phdr.offset + (phdr.dwords * 4) as u32);
940 log::debug!("computed sfdp len = {}", len);
941 }
942 Ok(len as usize)
943 }
944 }
945}
946
947impl TryFrom<&[u8]> for Sfdp {
949 type Error = anyhow::Error;
950 fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
951 let header = SfdpHeader::try_from(buf.get(0..8).ok_or(Error::SliceRange(0, 8))?)?;
952 let mut phdr = Vec::new();
953 for i in 0..=header.nph {
954 let start = (8 + i * 8) as usize;
955 let end = start + 8;
956 phdr.push(SfdpPhdr::try_from(
957 buf.get(start..end).ok_or(Error::SliceRange(start, end))?,
958 )?);
959 }
960
961 let start = phdr[0].offset as usize;
962 let end = start + phdr[0].dwords as usize * 4;
963 let jedec =
964 JedecParams::try_from(buf.get(start..end).ok_or(Error::SliceRange(start, end))?)?;
965
966 let mut params = Vec::new();
967 for ph in phdr.iter().take((header.nph as usize) + 1).skip(1) {
968 let start = ph.offset as usize;
969 let end = start + ph.dwords as usize * 4;
970 params.push(UnknownParams::try_from(
971 buf.get(start..end).ok_or(Error::SliceRange(start, end))?,
972 )?);
973 }
974
975 Ok(Sfdp {
976 header,
977 phdr,
978 jedec,
979 params,
980 })
981 }
982}
983
984#[cfg(test)]
985mod test {
986 use super::*;
987 use anyhow::Result;
988 use humantime::parse_duration;
989
990 #[rustfmt::skip]
991 const SFDP_MX66L1G: &[u8; 512] = include_bytes!("SFDP_MX66L1G.bin");
992
993 #[allow(clippy::bool_assert_comparison)]
994 #[test]
995 fn test_decode_mx66l1g() -> Result<()> {
996 let sfdp = Sfdp::try_from(&SFDP_MX66L1G[..])?;
997 assert_eq!(sfdp.header.signature, 0x50444653);
999 assert_eq!(sfdp.header.major, 1);
1000 assert_eq!(sfdp.header.minor, 6);
1001 assert_eq!(sfdp.header.nph, 2);
1002
1003 assert_eq!(sfdp.jedec.block_erase_size, BlockEraseSize::Block4KiB);
1004 assert_eq!(sfdp.jedec.write_en_required, false);
1005 assert_eq!(sfdp.jedec.write_en_opcode, 0x06);
1006 assert_eq!(sfdp.jedec.erase_opcode_4kib, 0x20);
1007 assert_eq!(sfdp.jedec.support_fast_read_112, true);
1008 assert_eq!(sfdp.jedec.address_modes, SupportedAddressModes::Mode3b4b);
1009 assert_eq!(sfdp.jedec.density, 128 * 1024 * 1024);
1010
1011 assert_eq!(sfdp.jedec.erase[0].size, 4096);
1012 assert_eq!(sfdp.jedec.erase[0].opcode, 0x20);
1013 assert_eq!(
1017 sfdp.jedec.erase[0].time.as_ref().unwrap().typical,
1018 parse_duration("30ms")?
1019 );
1020 assert_eq!(
1021 sfdp.jedec.erase[0].time.as_ref().unwrap().maximum,
1022 parse_duration("420ms")?
1023 );
1024
1025 assert_eq!(sfdp.jedec.erase[1].size, 32768);
1026 assert_eq!(sfdp.jedec.erase[1].opcode, 0x52);
1027 assert_eq!(
1029 sfdp.jedec.erase[1].time.as_ref().unwrap().typical,
1030 parse_duration("160ms")?
1031 );
1032 assert_eq!(
1033 sfdp.jedec.erase[1].time.as_ref().unwrap().maximum,
1034 parse_duration("2s 240ms")?
1035 );
1036
1037 assert_eq!(sfdp.jedec.erase[2].size, 65536);
1038 assert_eq!(sfdp.jedec.erase[2].opcode, 0xd8);
1039 assert_eq!(
1041 sfdp.jedec.erase[2].time.as_ref().unwrap().typical,
1042 parse_duration("288ms")?
1043 );
1044 assert_eq!(
1045 sfdp.jedec.erase[2].time.as_ref().unwrap().maximum,
1046 parse_duration("4s 32ms")?
1047 );
1048
1049 assert_eq!(sfdp.jedec.erase[3].size, 0);
1050 assert_eq!(sfdp.jedec.erase[3].opcode, 0xff);
1051
1052 let rev_b = sfdp.jedec.rev_b.as_ref().expect("rev_b parameters");
1053 assert_eq!(rev_b.page_size, 256);
1054 assert_eq!(rev_b.page_program_time.typical, parse_duration("256us")?);
1056 assert_eq!(rev_b.page_program_time.maximum, parse_duration("3ms 72us")?);
1057 assert_eq!(rev_b.byte_program_time.typical, parse_duration("32us")?);
1059 assert_eq!(rev_b.byte_program_time.maximum, parse_duration("384us")?);
1060 assert_eq!(
1062 rev_b.additional_byte_program_time.typical,
1063 parse_duration("1us")?
1064 );
1065 assert_eq!(
1066 rev_b.additional_byte_program_time.maximum,
1067 parse_duration("12us")?
1068 );
1069 assert_eq!(rev_b.chip_erase_time.typical, parse_duration("4m 16s")?);
1072 assert_eq!(rev_b.chip_erase_time.maximum, parse_duration("51m 12s")?);
1073
1074 assert!(sfdp.jedec.rev_d.is_none());
1076 assert!(sfdp.jedec.rev_f.is_none());
1077 Ok(())
1078 }
1079
1080 #[test]
1082 fn test_bad_header_signature() -> Result<()> {
1083 let buf = &[255u8; 256];
1084 let sfdp = Sfdp::try_from(&buf[..]);
1085 assert!(sfdp.is_err());
1086 let err = sfdp.unwrap_err();
1087 assert_eq!(
1088 err.to_string(),
1089 "SFDP header contains incorrect signature: 0xffffffff"
1090 );
1091 Ok(())
1092 }
1093}