@@ -129,8 +129,9 @@ pub enum AdminGetLogPageLidRequestType {
129129 ErrorInformation = 0x01 ,
130130 SmartHealthInformation = 0x02 ,
131131 FeatureIdentifiersSupportedAndEffects = 0x12 ,
132+ SanitizeStatus = 0x81 ,
132133}
133- unsafe impl Discriminant < u8 > for AdminGetLogPageLidRequestType { }
134+ unsafe impl crate :: Discriminant < u8 > for AdminGetLogPageLidRequestType { }
134135
135136// Base v2.1, 5.1.12.1.1, Figure 203
136137#[ derive( Debug , DekuRead , DekuWrite ) ]
@@ -234,6 +235,84 @@ flags! {
234235 }
235236}
236237
238+ // Base v2.1, 5.1.12.1.33, Figure 291, SSTAT, SOS
239+ #[ derive( Clone , Copy , Debug , Default , Eq , PartialEq ) ]
240+ #[ repr( u8 ) ]
241+ pub enum SanitizeOperationStatus {
242+ #[ default]
243+ SanitizeNeverStarted = 0b000 ,
244+ Sanitized = 0b001 ,
245+ Sanitizing = 0b010 ,
246+ SanitizeFailed = 0b011 ,
247+ SanitizedUnexpectedDeallocate = 0b100 ,
248+ }
249+ unsafe impl crate :: Discriminant < u8 > for SanitizeOperationStatus { }
250+
251+ // Base v2.1, 5.1.12.1.33, Figure 291, SSTAT
252+ #[ derive( Clone , Copy , Debug , Default ) ]
253+ pub struct SanitizeStatus {
254+ sos : SanitizeOperationStatus ,
255+ opc : u8 ,
256+ gde : bool ,
257+ mvcncled : bool ,
258+ }
259+
260+ impl From < SanitizeStatus > for u16 {
261+ fn from ( value : SanitizeStatus ) -> Self {
262+ ( ( value. mvcncled as u16 ) << 9 )
263+ | ( ( value. gde as u16 ) << 8 )
264+ | ( ( value. opc & ( ( 1 << 6 ) - 1 ) ) << 3 ) as u16
265+ | value. sos . id ( ) as u16
266+ }
267+ }
268+
269+ // Base v2.1, 5.12.1.33, Fgure 291, SSI, SANS
270+ #[ derive( Clone , Copy , Debug , Default , Eq , PartialEq ) ]
271+ #[ repr( u8 ) ]
272+ #[ expect( dead_code) ]
273+ enum SanitizeState {
274+ #[ default]
275+ Idle = 0x00 ,
276+ RestrictedProcessing = 0x01 ,
277+ RestrictedFailure = 0x02 ,
278+ UnrestrictedProcessing = 0x03 ,
279+ UnrestrictedFailure = 0x04 ,
280+ MediaVerification = 0x05 ,
281+ PostVerificationDeallocation = 0x06 ,
282+ }
283+ unsafe impl crate :: Discriminant < u8 > for SanitizeState { }
284+
285+ // Base v2.1, 5.1.12.1.33, Figure 291, SSI
286+ #[ derive( Clone , Copy , Debug , Default ) ]
287+ pub struct SanitizeStateInformation {
288+ sans : SanitizeState ,
289+ fails : u8 ,
290+ }
291+
292+ impl From < SanitizeStateInformation > for u8 {
293+ fn from ( value : SanitizeStateInformation ) -> Self {
294+ ( value. fails << 4 ) | ( value. sans . id ( ) )
295+ }
296+ }
297+
298+ // Base v2.1, 5.1.12.1.33, Figure 291
299+ #[ derive( Debug , DekuRead , DekuWrite ) ]
300+ #[ deku( endian = "little" ) ]
301+ struct SanitizeStatusLogPageResponse {
302+ sprog : u16 ,
303+ sstat : u16 ,
304+ scdw10 : u32 ,
305+ eto : u32 ,
306+ etbe : u32 ,
307+ etce : u32 ,
308+ etodmm : u32 ,
309+ etbenmm : u32 ,
310+ etcenmm : u32 ,
311+ etpvds : u32 ,
312+ ssi : u8 ,
313+ }
314+ impl Encode < 512 > for SanitizeStatusLogPageResponse { }
315+
237316// Base v2.1, 5.1.13.1, Figure 310
238317#[ derive( Clone , Copy , Debug , DekuRead , DekuWrite , Eq , PartialEq ) ]
239318#[ deku( ctx = "endian: Endian, cns: u8" , id = "cns" , endian = "endian" ) ]
@@ -324,6 +403,53 @@ flags! {
324403 }
325404}
326405
406+ // Base v2.1, 5.1.13.2.1, Figure 312, SANICAP, NODMMAS
407+ #[ derive( Clone , Copy , Debug , Default ) ]
408+ #[ repr( u8 ) ]
409+ pub enum NoDeallocateModifiesMediaAfterSanitize {
410+ Undefined = 0b00 ,
411+ #[ default]
412+ Unmodified = 0b01 ,
413+ Modified = 0b10 ,
414+ Reserved = 0b11 ,
415+ }
416+ unsafe impl Discriminant < u8 > for NoDeallocateModifiesMediaAfterSanitize { }
417+
418+ // Base v2.1, 5.1.13.2.1, Figure 312, SANICAP
419+ #[ derive( Clone , Copy , Debug ) ]
420+ pub struct SanitizeCapabilities {
421+ ces : bool ,
422+ bes : bool ,
423+ ows : bool ,
424+ vers : bool ,
425+ ndi : bool ,
426+ nodmmas : NoDeallocateModifiesMediaAfterSanitize ,
427+ }
428+
429+ impl From < SanitizeCapabilities > for u32 {
430+ fn from ( value : SanitizeCapabilities ) -> Self {
431+ ( ( ( value. nodmmas . id ( ) & 0b11 ) as u32 ) << 30 )
432+ | ( ( value. ndi as u32 ) << 29 )
433+ | ( ( value. vers as u32 ) << 3 )
434+ | ( ( value. ows as u32 ) << 2 )
435+ | ( ( value. bes as u32 ) << 1 )
436+ | ( value. ces as u32 )
437+ }
438+ }
439+
440+ impl Default for SanitizeCapabilities {
441+ fn default ( ) -> Self {
442+ Self {
443+ ces : true ,
444+ bes : true ,
445+ ows : true ,
446+ vers : false ,
447+ ndi : true ,
448+ nodmmas : NoDeallocateModifiesMediaAfterSanitize :: Unmodified ,
449+ }
450+ }
451+ }
452+
327453// Base v2.1, 5.1.13.2.1, Figure 312
328454#[ derive( Debug , DekuRead , DekuWrite ) ]
329455#[ deku( endian = "little" ) ]
@@ -363,7 +489,9 @@ struct AdminIdentifyControllerResponse {
363489 #[ deku( seek_from_current = "49" ) ]
364490 fwug : u8 ,
365491 kas : u16 ,
366- #[ deku( seek_from_current = "64" ) ]
492+ #[ deku( seek_from_current = "6" ) ]
493+ sanicap : u32 ,
494+ #[ deku( seek_from_current = "54" ) ]
367495 cqt : u16 ,
368496 #[ deku( seek_from_current = "124" ) ]
369497 sqes : u8 ,
@@ -510,6 +638,72 @@ struct NvmNamespaceManagementCreate {
510638 lbstm : u64 ,
511639}
512640
641+ // Base v2.1, 5.1.22, Figure 372, SANACT
642+ #[ derive( Clone , Copy , Debug ) ]
643+ #[ repr( u8 ) ]
644+ enum SanitizeAction {
645+ Reserved = 0x00 ,
646+ ExitFailureMode = 0x01 ,
647+ StartBlockErase = 0x02 ,
648+ StartOverwrite = 0x03 ,
649+ StartCryptoErase = 0x04 ,
650+ ExitMediaVerificationState = 0x05 ,
651+ }
652+ unsafe impl Discriminant < u8 > for SanitizeAction { }
653+
654+ impl TryFrom < u32 > for SanitizeAction {
655+ type Error = ( ) ;
656+
657+ fn try_from ( value : u32 ) -> Result < Self , Self :: Error > {
658+ match value {
659+ 0x00 => Ok ( Self :: Reserved ) ,
660+ 0x01 => Ok ( Self :: ExitFailureMode ) ,
661+ 0x02 => Ok ( Self :: StartBlockErase ) ,
662+ 0x03 => Ok ( Self :: StartOverwrite ) ,
663+ 0x04 => Ok ( Self :: StartCryptoErase ) ,
664+ 0x05 => Ok ( Self :: ExitMediaVerificationState ) ,
665+ _ => Err ( ( ) ) ,
666+ }
667+ }
668+ }
669+
670+ // Base v2.1, 5.1.22, Figure 372
671+ #[ derive( Clone , Copy , Debug ) ]
672+ pub struct AdminSanitizeConfiguration {
673+ sanact : SanitizeAction ,
674+ ause : bool ,
675+ owpass : u8 ,
676+ oipbp : bool ,
677+ ndas : bool ,
678+ emvs : bool ,
679+ }
680+
681+ impl TryFrom < u32 > for AdminSanitizeConfiguration {
682+ type Error = ( ) ;
683+
684+ fn try_from ( value : u32 ) -> Result < Self , Self :: Error > {
685+ Ok ( Self {
686+ sanact : TryInto :: try_into ( value & 0x7 ) ?,
687+ ause : ( ( value >> 3 ) & 1 ) == 1 ,
688+ owpass : ( ( value >> 4 ) & 0xf ) as u8 ,
689+ oipbp : ( ( value >> 8 ) & 1 ) == 1 ,
690+ ndas : ( ( value >> 9 ) & 1 ) == 1 ,
691+ emvs : ( ( value >> 10 ) & 1 ) == 1 ,
692+ } )
693+ }
694+ }
695+
696+ impl From < AdminSanitizeConfiguration > for u32 {
697+ fn from ( value : AdminSanitizeConfiguration ) -> Self {
698+ ( ( value. emvs as u32 ) << 10 )
699+ | ( ( value. ndas as u32 ) << 9 )
700+ | ( ( value. oipbp as u32 ) << 8 )
701+ | ( ( ( value. owpass & 0xf ) as u32 ) << 4 )
702+ | ( ( value. ause as u32 ) << 3 )
703+ | value. sanact . id ( ) as u32
704+ }
705+ }
706+
513707// Base v2.1, 5.1.25, Figure 385
514708// Base v2.1, 3.1.3.6, Figure 32
515709#[ derive( Debug , DekuRead , DekuWrite ) ]
0 commit comments