Add more fields to MultiMediaCard's Extended CSD.

This commit is contained in:
2020-12-09 20:11:12 +00:00
parent 3d1ff538b8
commit 5b9b6fab59

View File

@@ -88,128 +88,249 @@ namespace Aaru.Decoders.MMC
public byte PartitionsAttribute;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] MaxEnhancedAreaSize;
public byte PartitioningSupport;
public byte HPIManagement;
public byte HWResetFunction;
public byte EnableBackgroundOperationsHandshake;
public byte ManuallyStartBackgroundOperations;
public byte StartSanitizeOperation;
public byte WriteReliabilityParameterRegister;
public byte WriteReliabilitySettingRegister;
public byte RPMBSize;
public byte FirmwareConfiguration;
public byte Reserved4;
public byte UserAreaWriteProtectionRegister;
public byte Reserved5;
public byte BootAreaWriteProtectionRegister;
public byte BootWriteProtectionStatus;
public byte HighCapacityEraseGroupDefinition;
public byte Reserved6;
public byte BootBusConditions;
public byte BootConfigProtection;
public byte PartitionConfiguration;
public byte Reserved7;
public byte ErasedMemoryContent;
public byte Reserved8;
public byte BusWidth;
public byte StrobeSupport;
public byte HighSpeedInterfaceTiming;
public byte Reserved9;
public byte PowerClass;
public byte Reserved10;
public byte CommandSetRevision;
public byte Reserved11;
public byte CommandSet;
public byte Revision;
public byte Reserved12;
public byte Structure;
public byte Reserved13;
public byte DeviceType;
public byte DriverStrength;
public byte OutOfInterruptBusyTiming;
public byte PartitionSwitchingTime;
public byte PowerClass52_195;
public byte PowerClass26_195;
public byte PowerClass52;
public byte PowerClass26;
public byte Reserved14;
public byte MinimumReadPerformance26_4;
public byte MinimumWritePerformance26_4;
public byte MinimumReadPerformance26;
public byte MinimumWritePerformance26;
public byte MinimumReadPerformance52;
public byte MinimumWritePerformance52;
public byte SecureWriteProtectInformation;
public uint SectorCount;
public byte SleepNotificationTimeout;
public byte SleepAwakeTimeout;
public byte ProductionStateAwarenessTimeout;
public byte SleepCurrentVccQ;
public byte SleepCurrentVcc;
public byte HighCapacityWriteProtectGroupSize;
public byte ReliableWriteSectorCount;
public byte HighCapacityEraseTimeout;
public byte HighCapacityEraseUnitSize;
public byte AccessSize;
public byte BootPartitionSize;
public byte Reserved15;
public byte BootInformation;
public byte SecureTRIMMultiplier;
public byte SecureEraseMultiplier;
public byte SecureFeatureSupport;
public byte TRIMMultiplier;
public byte Reserved16;
public byte MinimumReadPerformanceDDR52;
public byte MinimumWritePerformanceDDR52;
public byte PowerClassDDR200_130;
public byte PowerClassDDR200_195;
public byte PowerClassDDR52_195;
public byte PowerClassDDR52;
public byte CacheFlushingPolicy;
public byte InitializationTimeAfterPartition;
public uint CorrectlyProgrammedSectors;
public byte BackgroundOperationsStatus;
public byte PowerOffNotificationTimeout;
public byte GenericCMD6Timeout;
public uint CacheSize;
public byte PowerClassDDR200;
public ulong FirmwareVersion;
public ushort DeviceVersion;
public byte OptimalTrimUnitSize;
public byte OptimalWriteSize;
public byte OptimalReadSize;
public byte PreEOLInformation;
public byte DeviceLifeEstimationTypeA;
public byte DeviceLifeEstimationTypeB;
public PartitioningSupport PartitioningSupport;
public byte HPIManagement;
public byte HWResetFunction;
public byte EnableBackgroundOperationsHandshake;
public byte ManuallyStartBackgroundOperations;
public byte StartSanitizeOperation;
public byte WriteReliabilityParameterRegister;
public byte WriteReliabilitySettingRegister;
public byte RPMBSize;
public byte FirmwareConfiguration;
public byte Reserved4;
public UserAreaWriteProtectionRegister UserAreaWriteProtectionRegister;
public byte Reserved5;
public BootAreaWriteProtectionRegister BootAreaWriteProtectionRegister;
public byte BootWriteProtectionStatus;
public HighCapacityEraseGroupDefinition HighCapacityEraseGroupDefinition;
public byte Reserved6;
public byte BootBusConditions;
public BootConfigProtection BootConfigProtection;
public byte PartitionConfiguration;
public byte Reserved7;
public byte ErasedMemoryContent;
public byte Reserved8;
public byte BusWidth;
public byte StrobeSupport;
public byte HighSpeedInterfaceTiming;
public byte Reserved9;
public byte PowerClass;
public byte Reserved10;
public byte CommandSetRevision;
public byte Reserved11;
public byte CommandSet;
public byte Revision;
public byte Reserved12;
public byte Structure;
public byte Reserved13;
public DeviceType DeviceType;
public DriverStrength DriverStrength;
public byte OutOfInterruptBusyTiming;
public byte PartitionSwitchingTime;
public byte PowerClass52_195;
public byte PowerClass26_195;
public byte PowerClass52;
public byte PowerClass26;
public byte Reserved14;
public byte MinimumReadPerformance26_4;
public byte MinimumWritePerformance26_4;
public byte MinimumReadPerformance26;
public byte MinimumWritePerformance26;
public byte MinimumReadPerformance52;
public byte MinimumWritePerformance52;
public SecureWriteProtectInformation SecureWriteProtectInformation;
public uint SectorCount;
public byte SleepNotificationTimeout;
public byte SleepAwakeTimeout;
public byte ProductionStateAwarenessTimeout;
public byte SleepCurrentVccQ;
public byte SleepCurrentVcc;
public byte HighCapacityWriteProtectGroupSize;
public byte ReliableWriteSectorCount;
public byte HighCapacityEraseTimeout;
public byte HighCapacityEraseUnitSize;
public byte AccessSize;
public byte BootPartitionSize;
public byte Reserved15;
public BootInformation BootInformation;
public byte SecureTRIMMultiplier;
public byte SecureEraseMultiplier;
public SecureFeatureSupport SecureFeatureSupport;
public byte TRIMMultiplier;
public byte Reserved16;
public byte MinimumReadPerformanceDDR52;
public byte MinimumWritePerformanceDDR52;
public byte PowerClassDDR200_130;
public byte PowerClassDDR200_195;
public byte PowerClassDDR52_195;
public byte PowerClassDDR52;
public CacheFlushingPolicy CacheFlushingPolicy;
public byte InitializationTimeAfterPartition;
public uint CorrectlyProgrammedSectors;
public byte BackgroundOperationsStatus;
public byte PowerOffNotificationTimeout;
public byte GenericCMD6Timeout;
public uint CacheSize;
public byte PowerClassDDR200;
public ulong FirmwareVersion;
public ushort DeviceVersion;
public byte OptimalTrimUnitSize;
public byte OptimalWriteSize;
public byte OptimalReadSize;
public byte PreEOLInformation;
public byte DeviceLifeEstimationTypeA;
public byte DeviceLifeEstimationTypeB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] VendorHealthReport;
public uint NumberofFWSectorsCorrectlyProgrammed;
public byte Reserved17;
public byte CMDQueuingDepth;
public byte CMDQueuingSupport;
public uint NumberOfFWSectorsCorrectlyProgrammed;
public byte Reserved17;
public byte CMDQueuingDepth;
public CMDQueuingSupport CMDQueuingSupport;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 177)]
public byte[] Reserved18;
public byte BarrierSupport;
public uint FFUArgument;
public byte OperationCodesTimeout;
public byte FFUFeatures;
public byte SupportedModes;
public byte ExtendedPartitionsSupport;
public byte LargeUnitSize;
public byte ContextManagementCaps;
public byte TagResourcesSize;
public byte TagUnitSize;
public byte DataTagSupport;
public byte MaxPackedWriteCommands;
public byte MaxPackedReadCommands;
public byte BackgroundOperationsSupport;
public byte HPIFeatures;
public byte SupportedCommandSets;
public byte ExtendedSecurityCommandsError;
public byte BarrierSupport;
public uint FFUArgument;
public byte OperationCodesTimeout;
public FFUFeatures FFUFeatures;
public SupportedModes SupportedModes;
public ExtendedPartitionsSupport ExtendedPartitionsSupport;
public byte LargeUnitSize;
public byte ContextManagementCaps;
public byte TagResourcesSize;
public byte TagUnitSize;
public DataTagSupport DataTagSupport;
public byte MaxPackedWriteCommands;
public byte MaxPackedReadCommands;
public BackgroundOperationsSupport BackgroundOperationsSupport;
public HPIFeatures HPIFeatures;
public DeviceSupportedCommandSets SupportedCommandSets;
public byte ExtendedSecurityCommandsError;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] Reserved19;
}
[Flags]
public enum DeviceSupportedCommandSets : byte
{
Standard = 1 << 0
}
[Flags]
public enum HPIFeatures : byte
{
Supported = 1 << 0, CMD12 = 1 << 1
}
[Flags]
public enum BackgroundOperationsSupport : byte
{
Supported = 1 << 0
}
[Flags]
public enum DataTagSupport : byte
{
Supported = 1 << 0
}
[Flags]
public enum ExtendedPartitionsSupport : byte
{
SystemCode = 1 << 0, NonPersistent = 1 << 1
}
[Flags]
public enum SupportedModes : byte
{
FFU = 1 << 0, VendorSpecific = 1 << 1
}
[Flags]
public enum FFUFeatures : byte
{
SupportedModeOperationCodes = 1 << 0
}
[Flags]
public enum CMDQueuingSupport : byte
{
Supported = 1 << 0
}
[Flags]
public enum CacheFlushingPolicy : byte
{
FIFO = 1 << 0
}
[Flags]
public enum SecureFeatureSupport : byte
{
Purge = 1 << 0, Defective = 1 << 2, Trim = 1 << 4,
Sanitize = 1 << 6
}
[Flags]
public enum BootInformation : byte
{
Alternative = 1 << 0, DDR = 1 << 1, HighSpeed = 1 << 2
}
[Flags]
public enum SecureWriteProtectInformation : byte
{
Supported = 1 << 0, Enabled = 1 << 1
}
[Flags]
public enum DriverStrength : byte
{
Type0 = 1 << 0, Type1 = 1 << 1, Type2 = 1 << 2,
Type3 = 1 << 3, Type4 = 1 << 4
}
[Flags]
public enum DeviceType : byte
{
HS_26 = 1 << 0, HS_52 = 1 << 1, HS_DDR_52 = 1 << 2,
HS_DDR_52_LV = 1 << 3, HS200_18 = 1 << 4, HS200_12 = 1 << 5,
HS400_18 = 1 << 6, HS400_12 = 1 << 7
}
[Flags]
public enum BootConfigProtection : byte
{
PowerCycle = 1 << 0, Permanent = 1 << 4
}
[Flags]
public enum HighCapacityEraseGroupDefinition : byte
{
Enabled = 1 << 0
}
[Flags]
public enum BootAreaWriteProtectionRegister : byte
{
PowerOn = 1 << 0, PowerOnArea2 = 1 << 1, Permanent = 1 << 2,
PermanentArea2 = 1 << 3, PermanentDisable = 1 << 4, PowerOnDisable = 1 << 6,
Selected = 1 << 7
}
[Flags]
public enum UserAreaWriteProtectionRegister : byte
{
ApplyPowerOn = 1 << 0, ApplyPermanent = 1 << 2, DisablePowerOn = 1 << 3,
DisablePermanent = 1 << 4, DisableWriteProtect = 1 << 6, DisablePassword = 1 << 7
}
[Flags]
public enum PartitioningSupport : byte
{
Supported = 1 << 0, Enhanced = 1 << 1, Extended = 1 << 2
}
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
public static partial class Decoders
@@ -236,39 +357,90 @@ namespace Aaru.Decoders.MMC
double unit;
if((csd.HPIFeatures & 0x01) == 0x01)
sb.AppendLine((csd.HPIFeatures & 0x02) == 0x02 ? "\tDevice implements HPI using CMD12"
if(csd.ExtendedSecurityCommandsError != 0)
sb.AppendFormat("\tLast extended security error was {0}", csd.ExtendedSecurityCommandsError).
AppendLine();
if(csd.SupportedCommandSets.HasFlag(DeviceSupportedCommandSets.Standard))
sb.AppendLine("\tDevice supports standard MMC command set");
if(((int)csd.SupportedCommandSets & 0xFE) != 0)
sb.AppendFormat("\tDevice supports unknown command sets 0x{0:X2}", (int)csd.SupportedCommandSets);
if(csd.HPIFeatures.HasFlag(HPIFeatures.Supported))
sb.AppendLine(csd.HPIFeatures.HasFlag(HPIFeatures.CMD12) ? "\tDevice implements HPI using CMD12"
: "\tDevice implements HPI using CMD13");
if((csd.BackgroundOperationsSupport & 0x01) == 0x01)
if(csd.BackgroundOperationsSupport.HasFlag(BackgroundOperationsSupport.Supported))
sb.AppendLine("\tDevice supports background operations");
sb.AppendFormat("\tDevice supports a maximum of {0} packed reads and {1} packed writes",
csd.MaxPackedReadCommands, csd.MaxPackedWriteCommands).AppendLine();
if((csd.DataTagSupport & 0x01) == 0x01)
if(csd.DataTagSupport.HasFlag(DataTagSupport.Supported))
{
sb.AppendLine("\tDevice supports Data Tag");
sb.AppendFormat("\tTags must be in units of {0} sectors", Math.Pow(2, csd.TagUnitSize)).AppendLine();
sb.AppendFormat("\tTag resources size is {0}.", csd.TagResourcesSize).AppendLine();
}
if((csd.ExtendedPartitionsSupport & 0x01) == 0x01)
if(csd.ContextManagementCaps != 0)
{
sb.AppendFormat("\tMax context ID is {0}.", csd.ContextManagementCaps & 0xF).AppendLine();
sb.AppendFormat("\tLarge unit maximum multiplier is {0}.",
((csd.ContextManagementCaps & 0x70) >> 4) + 1).AppendLine();
}
sb.AppendFormat("\tLarge unit size is {0} MiB", csd.LargeUnitSize + 1).AppendLine();
if(csd.ExtendedPartitionsSupport.HasFlag(ExtendedPartitionsSupport.NonPersistent))
sb.AppendLine("\tDevice supports non-persistent extended partitions");
if((csd.ExtendedPartitionsSupport & 0x02) == 0x02)
if(csd.ExtendedPartitionsSupport.HasFlag(ExtendedPartitionsSupport.SystemCode))
sb.AppendLine("\tDevice supports system code extended partitions");
if((csd.SupportedModes & 0x01) == 0x01)
if(csd.SupportedModes.HasFlag(SupportedModes.FFU))
{
sb.AppendLine("\tDevice supports FFU");
if((csd.SupportedModes & 0x02) == 0x02)
if(csd.FFUFeatures.HasFlag(FFUFeatures.SupportedModeOperationCodes))
{
// todo public byte ModeOperationCodes
if(csd.OperationCodesTimeout > 0)
{
unit = Math.Pow(2, csd.OperationCodesTimeout) * 100;
if(unit > 1000000)
sb.
AppendFormat("\t\tMaximum timeout for switch command when setting a value to the mode operation codes field is {0:D2}s",
unit / 1000000).AppendLine();
else if(unit > 1000)
sb.
AppendFormat("\tMaximum timeout for switch command when setting a value to the mode operation codes field is {0:D2}ms",
unit / 1000).AppendLine();
else
sb.
AppendFormat("\tMaximum timeout for switch command when setting a value to the mode operation codes field is {0:D2}µs",
unit).AppendLine();
}
}
}
if(csd.SupportedModes.HasFlag(SupportedModes.VendorSpecific))
sb.AppendLine("\tDevice supports Vendor Specific Mode");
if((csd.CMDQueuingSupport & 0x01) == 0x01)
if(csd.BarrierSupport == 0x01)
{
sb.AppendLine("\tDevice supports the barrier command");
}
if(csd.CMDQueuingSupport.HasFlag(CMDQueuingSupport.Supported))
sb.AppendFormat("\tDevice supports command queuing with a depth of {0}", csd.CMDQueuingDepth + 1).
AppendLine();
sb.AppendFormat("\t{0} firmware sectors correctly programmed", csd.NumberofFWSectorsCorrectlyProgrammed).
sb.AppendFormat("\t{0} firmware sectors correctly programmed", csd.NumberOfFWSectorsCorrectlyProgrammed).
AppendLine();
switch(csd.DeviceLifeEstimationTypeB)
@@ -383,9 +555,21 @@ namespace Aaru.Decoders.MMC
break;
}
sb.AppendFormat("\tOptimal read size is {0} logical sectors", csd.OptimalReadSize).AppendLine();
sb.AppendFormat("\tOptimal write size is {0} logical sectors", csd.OptimalWriteSize).AppendLine();
sb.AppendFormat("\tOptimal trim size is {0} logical sectors", csd.OptimalTrimUnitSize).AppendLine();
if(csd.OptimalReadSize == 0)
sb.AppendLine("\tDevice does not report an optimal read size");
else
sb.AppendFormat("\tOptimal read size is {0} KiB", 4 * csd.OptimalReadSize).AppendLine();
if(csd.OptimalWriteSize == 0)
sb.AppendLine("\tDevice does not report an optimal write size");
else
sb.AppendFormat("\tOptimal write size is {0} KiB", 4 * csd.OptimalWriteSize).AppendLine();
if(csd.OptimalTrimUnitSize == 0)
sb.AppendLine("\tDevice does not report an optimal trim size");
else
sb.AppendFormat("\tOptimal trim size is {0} KiB", 4 * Math.Pow(2, csd.OptimalTrimUnitSize - 1)).
AppendLine();
sb.AppendFormat("\tDevice version: {0}", csd.DeviceVersion).AppendLine();
sb.AppendFormat("\tFirmware version: {0}", csd.FirmwareVersion).AppendLine();
@@ -393,7 +577,7 @@ namespace Aaru.Decoders.MMC
if(csd.CacheSize == 0)
sb.AppendLine("\tDevice has no cache");
else
sb.AppendFormat("\tDevice has {0} KiB of cache", csd.CacheSize).AppendLine();
sb.AppendFormat("\tDevice has {0} KiB of cache", csd.CacheSize / 8).AppendLine();
if(csd.GenericCMD6Timeout > 0)
sb.AppendFormat("\tDevice takes a maximum of {0} ms by default for a SWITCH command",
@@ -431,23 +615,23 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice takes a maximum of {0} ms for initialization after partition",
csd.InitializationTimeAfterPartition * 100).AppendLine();
if((csd.CacheFlushingPolicy & 0x01) == 0x01)
if(csd.CacheFlushingPolicy.HasFlag(CacheFlushingPolicy.FIFO))
sb.AppendLine("\tDevice uses a FIFO policy for cache flushing");
if(csd.TRIMMultiplier > 0)
sb.AppendFormat("\tDevice takes a maximum of {0} ms for trimming a single erase group",
csd.TRIMMultiplier * 300).AppendLine();
if((csd.SecureFeatureSupport & 0x40) == 0x40)
if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Sanitize))
sb.AppendLine("\tDevice supports the sanitize operation");
if((csd.SecureFeatureSupport & 0x10) == 0x10)
if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Trim))
sb.AppendLine("\tDevice supports supports the secure and insecure trim operations");
if((csd.SecureFeatureSupport & 0x04) == 0x04)
if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Defective))
sb.AppendLine("\tDevice supports automatic erase on retired defective blocks");
if((csd.SecureFeatureSupport & 0x01) == 0x01)
if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Purge))
sb.AppendLine("\tDevice supports secure purge operations");
if(csd.SecureEraseMultiplier > 0)
@@ -458,21 +642,21 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice takes a maximum of {0} ms for securely trimming a single erase group",
csd.SecureTRIMMultiplier * 300).AppendLine();
if((csd.BootInformation & 0x04) == 0x04)
if(csd.BootInformation.HasFlag(BootInformation.HighSpeed))
sb.AppendLine("\tDevice supports high speed timing on boot");
if((csd.BootInformation & 0x02) == 0x02)
if(csd.BootInformation.HasFlag(BootInformation.DDR))
sb.AppendLine("\tDevice supports dual data rate on boot");
if((csd.BootInformation & 0x01) == 0x01)
if(csd.BootInformation.HasFlag(BootInformation.Alternative))
sb.AppendLine("\tDevice supports alternative boot method");
if(csd.BootPartitionSize > 0)
sb.AppendFormat("\tDevice has a {0} KiB boot partition", csd.BootPartitionSize * 128).AppendLine();
if((csd.AccessSize & 0x0F) > 0)
sb.AppendFormat("\tDevice has a page size of {0} KiB", (csd.AccessSize & 0x0F) * 512.0 / 1024.0).
AppendLine();
sb.AppendFormat("\tDevice has a page size of {0} KiB",
512 * Math.Pow(2, (csd.AccessSize & 0x0F) - 1) / 1024.0).AppendLine();
if(csd.HighCapacityEraseUnitSize > 0)
sb.AppendFormat("\tDevice erase groups are {0} KiB", csd.HighCapacityEraseUnitSize * 512).AppendLine();
@@ -551,15 +735,15 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice has {0} sectors", csd.SectorCount).AppendLine();
if((csd.SecureWriteProtectInformation & 0x01) == 0x01)
if(csd.SecureWriteProtectInformation.HasFlag(SecureWriteProtectInformation.Supported))
{
sb.AppendLine("\tDevice supports secure write protection");
if((csd.SecureWriteProtectInformation & 0x02) == 0x02)
if(csd.SecureWriteProtectInformation.HasFlag(SecureWriteProtectInformation.Enabled))
sb.AppendLine("\tDevice has secure write protection enabled");
}
unit = csd.MinimumReadPerformance26 * 150;
unit = csd.MinimumReadPerformance26 * 300;
if(csd.MinimumReadPerformance26 == 0)
sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz mode");
@@ -567,7 +751,7 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz mode", unit / 1000).
AppendLine();
unit = csd.MinimumReadPerformance26_4 * 150;
unit = csd.MinimumReadPerformance26_4 * 300;
if(csd.MinimumReadPerformance26_4 == 0)
sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz 4-bit mode");
@@ -575,7 +759,7 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz 4-bit mode",
unit / 1000).AppendLine();
unit = csd.MinimumReadPerformance52 * 150;
unit = csd.MinimumReadPerformance52 * 300;
if(csd.MinimumReadPerformance52 == 0)
sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 52Mhz mode");
@@ -583,7 +767,7 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 52Mhz mode", unit / 1000).
AppendLine();
unit = csd.MinimumReadPerformanceDDR52 * 300;
unit = csd.MinimumReadPerformanceDDR52 * 600;
if(csd.MinimumReadPerformanceDDR52 == 0)
sb.AppendLine("\tDevice cannot achieve 4.8MB/s reading in DDR 52Mhz mode");
@@ -591,7 +775,7 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in DDR 52Mhz mode", unit / 1000).
AppendLine();
unit = csd.MinimumWritePerformance26 * 150;
unit = csd.MinimumWritePerformance26 * 300;
if(csd.MinimumWritePerformance26 == 0)
sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz mode");
@@ -599,7 +783,7 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz mode", unit / 1000).
AppendLine();
unit = csd.MinimumWritePerformance26_4 * 150;
unit = csd.MinimumWritePerformance26_4 * 300;
if(csd.MinimumWritePerformance26_4 == 0)
sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz 4-bit mode");
@@ -607,7 +791,7 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz 4-bit mode",
unit / 1000).AppendLine();
unit = csd.MinimumWritePerformance52 * 150;
unit = csd.MinimumWritePerformance52 * 300;
if(csd.MinimumWritePerformance52 == 0)
sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 52Mhz mode");
@@ -615,7 +799,7 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 52Mhz mode", unit / 1000).
AppendLine();
unit = csd.MinimumWritePerformanceDDR52 * 300;
unit = csd.MinimumWritePerformanceDDR52 * 600;
if(csd.MinimumWritePerformanceDDR52 == 0)
sb.AppendLine("\tDevice cannot achieve 4.8MB/s writing in DDR 52Mhz mode");
@@ -631,32 +815,100 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice can take a maximum of {0} ms when releasing from an interrupt",
csd.OutOfInterruptBusyTiming * 10).AppendLine();
if((csd.DeviceType & 0x01) == 0x01)
if(csd.DriverStrength.HasFlag(DriverStrength.Type0))
sb.AppendLine("\tDevice supports I/O driver strength type 0.");
if(csd.DriverStrength.HasFlag(DriverStrength.Type1))
sb.AppendLine("\tDevice supports I/O driver strength type 1.");
if(csd.DriverStrength.HasFlag(DriverStrength.Type2))
sb.AppendLine("\tDevice supports I/O driver strength type 2.");
if(csd.DriverStrength.HasFlag(DriverStrength.Type3))
sb.AppendLine("\tDevice supports I/O driver strength type 3.");
if(csd.DriverStrength.HasFlag(DriverStrength.Type4))
sb.AppendLine("\tDevice supports I/O driver strength type 4.");
if(csd.DeviceType.HasFlag(DeviceType.HS_26))
sb.AppendLine("\tDevice supports 26 Mhz mode");
if((csd.DeviceType & 0x02) == 0x02)
if(csd.DeviceType.HasFlag(DeviceType.HS_52))
sb.AppendLine("\tDevice supports 52 Mhz mode");
if((csd.DeviceType & 0x04) == 0x04)
if(csd.DeviceType.HasFlag(DeviceType.HS_DDR_52))
sb.AppendLine("\tDevice supports DDR 52 Mhz mode at 1.8V or 3V");
if((csd.DeviceType & 0x08) == 0x08)
if(csd.DeviceType.HasFlag(DeviceType.HS_DDR_52_LV))
sb.AppendLine("\tDevice supports DDR 52 Mhz mode 1.2V");
if((csd.DeviceType & 0x10) == 0x10)
if(csd.DeviceType.HasFlag(DeviceType.HS200_18))
sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.8V");
if((csd.DeviceType & 0x20) == 0x20)
if(csd.DeviceType.HasFlag(DeviceType.HS200_12))
sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.2V");
if((csd.DeviceType & 0x40) == 0x40)
if(csd.DeviceType.HasFlag(DeviceType.HS400_18))
sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.8V");
if((csd.DeviceType & 0x80) == 0x80)
if(csd.DeviceType.HasFlag(DeviceType.HS400_12))
sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.2V");
sb.AppendFormat("\tCSD version 1.{0} revision 1.{1}", csd.Structure, csd.Revision).AppendLine();
switch(csd.CommandSet)
{
case 0:
sb.AppendLine("\tDevice follows compatibility MMC command set.");
break;
case 1:
switch(csd.CommandSetRevision)
{
case 0:
sb.AppendLine("\tDevice follows standard MMC command set v4.0.");
break;
default:
sb.AppendFormat("\tDevice follows standard MMC command set with unknown version code {0}.",
csd.CommandSetRevision).AppendLine();
break;
}
break;
default:
sb.AppendFormat("\tDevice follows unknown MMC command set code {0} with revision code {1}.",
csd.CommandSet, csd.CommandSetRevision).AppendLine();
break;
}
switch(csd.HighSpeedInterfaceTiming & 0x0F)
{
case 0: break;
case 1:
sb.AppendLine("\tDevice is in High Speed mode.");
break;
case 2:
sb.AppendLine("\tDevice is in HS-200 mode.");
break;
case 3:
sb.AppendLine("\tDevice is in HS-400 mode.");
break;
default:
sb.AppendFormat("\tDevice has unknown timing mode {0}.", csd.HighSpeedInterfaceTiming & 0x0F).
AppendLine();
break;
}
sb.AppendFormat("\tSelected driver strength is type {0}.", (csd.HighSpeedInterfaceTiming & 0xF0) >> 4).
AppendLine();
if((csd.StrobeSupport & 0x01) == 0x01)
{
sb.AppendLine("\tDevice supports enhanced strobe mode");
@@ -694,7 +946,20 @@ namespace Aaru.Decoders.MMC
break;
}
if((csd.PartitionConfiguration & 0x80) == 0x80)
switch(csd.ErasedMemoryContent)
{
case 0:
case 1:
sb.AppendFormat("\tErased memory range shall be '{0}'.", csd.ErasedMemoryContent).AppendLine();
break;
default:
sb.AppendFormat("\tUnknown erased memory content code {0}", csd.ErasedMemoryContent).AppendLine();
break;
}
if((csd.PartitionConfiguration & 0x40) == 0x40)
sb.AppendLine("\tDevice sends boot acknowledge");
switch((csd.PartitionConfiguration & 0x38) >> 3)
@@ -747,6 +1012,139 @@ namespace Aaru.Decoders.MMC
break;
}
if(csd.BootConfigProtection.HasFlag(BootConfigProtection.Permanent))
sb.AppendLine("\tChange of the boot configuration register bits is permanently disabled.");
else if(csd.BootConfigProtection.HasFlag(BootConfigProtection.PowerCycle))
sb.AppendLine("\tChange of the boot configuration register bits is disabled until the next power cycle.");
switch(csd.BootBusConditions & 0x03)
{
case 0:
sb.AppendLine("\tDevice will boot up in x1 SDR or x4 DDR bus width.");
break;
case 1:
sb.AppendLine("\tDevice will boot up in x4 SDR or DDR bus width.");
break;
case 2:
sb.AppendLine("\tDevice will boot up in x8 SDR or DDR bus width.");
break;
case 3:
sb.AppendLine("\tUnknown boot condition for bus width with code 3.");
break;
}
sb.AppendLine((csd.BootBusConditions & 4) == 4
? "\tDevice will retain boot conditions after boot operation."
: "\tDevice will reset boot conditions to compatibility mode after boot operation.");
switch((csd.BootBusConditions & 0x24) >> 3)
{
case 0:
sb.AppendLine("\tDevice will use single data rate with compatible timings in boot operation.");
break;
case 1:
sb.AppendLine("\tDevice will use single data rate with high speed timings in boot operation.");
break;
case 2:
sb.AppendLine("\tDevice will use dual data rate in boot operation.");
break;
case 3:
sb.AppendLine("\tDevice will use unknown boot mode with code 3.");
break;
}
if(csd.HighCapacityEraseGroupDefinition.HasFlag(HighCapacityEraseGroupDefinition.Enabled))
sb.AppendLine("\tDevice will use high capacity erase unit size, timeout and write protect group size definitions.");
switch(csd.BootWriteProtectionStatus & 0x03)
{
case 0:
sb.AppendLine("\tBoot area 1 is not protected");
break;
case 1:
sb.AppendLine("\tBoot area 1 is power on protected");
break;
case 2:
sb.AppendLine("\tBoot area 1 is permanently protected");
break;
}
switch((csd.BootWriteProtectionStatus & 0x0C) >> 2)
{
case 0:
sb.AppendLine("\tBoot area 2 is not protected");
break;
case 1:
sb.AppendLine("\tBoot area 2 is power on protected");
break;
case 2:
sb.AppendLine("\tBoot area 2 is permanently protected");
break;
}
if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.Permanent))
{
if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.Selected))
{
sb.AppendLine(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.
PermanentArea2)
? "\tBoot area 2 is permanently write protected."
: "\tBoot area 1 is permanently write protected.");
}
else
sb.AppendLine("\tBoth boot areas are permanently write protected.");
}
else if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.PowerOn))
{
if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.Selected))
{
sb.AppendLine(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.
PowerOnArea2)
? "\tBoot area 2 is write protected until next power cycle."
: "\tBoot area 1 is write protected until next power cycle.");
}
else
sb.AppendLine("\tBoth boot areas are write protected until next power cycle.");
}
if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.PermanentDisable))
sb.AppendLine("\tPermanent write protection of boot areas is disabled.");
if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.PowerOnDisable))
sb.AppendLine("\tPower cycled write protection of boot areas is disabled.");
if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisablePassword))
sb.AppendLine("\tUse of password protection features is permanently disabled.");
if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisableWriteProtect))
sb.AppendLine("\tUse of permanent write protection is disabled.");
if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisablePermanent))
sb.AppendLine("\tPermanent write protection is disabled.");
if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisablePowerOn))
sb.AppendLine("\tPower cycled write protection is disabled.");
if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.ApplyPermanent))
sb.AppendLine("\tPermanent write protection will be applied to selected group.");
if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.ApplyPowerOn))
sb.AppendLine("\tPower cycled write protection will be applied to selected group.");
if((csd.FirmwareConfiguration & 0x01) == 0x01)
sb.AppendLine("\tFirmware updates are permanently disabled");
@@ -754,6 +1152,17 @@ namespace Aaru.Decoders.MMC
sb.AppendFormat("\tDevice has a {0} KiB replay protected memory block", csd.RPMBSize * 128).
AppendLine();
if(csd.PartitioningSupport.HasFlag(PartitioningSupport.Supported))
{
sb.AppendLine("\tDevice supports partitioning features");
if(csd.PartitioningSupport.HasFlag(PartitioningSupport.Enhanced))
sb.AppendLine("\tDevice can have enhanced technological features in partitions and user data area");
if(csd.PartitioningSupport.HasFlag(PartitioningSupport.Extended))
sb.AppendLine("\tDevice can have extended partitions attribute.");
}
switch(csd.NativeSectorSize)
{
case 0: