File indexing completed on 2024-04-28 05:45:46
0001 /* 0002 SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de> 0003 SPDX-FileCopyrightText: 2016-2018 Andrius Štikonas <andrius@stikonas.eu> 0004 SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com> 0005 SPDX-FileCopyrightText: 2018 Anthony Fieroni <bvbfan@abv.bg> 0006 0007 SPDX-License-Identifier: GPL-3.0-or-later 0008 */ 0009 0010 #include "core/smartattribute.h" 0011 #include "core/smartstatus.h" 0012 #include "core/smartattributeparseddata.h" 0013 0014 #include <QLocale> 0015 0016 #include <KLocalizedString> 0017 #include <KFormat> 0018 0019 static QString getAttrName(qint32 id); 0020 static QString getAttrDescription(qint32 id); 0021 static QString getPrettyValue(quint64 value, SmartAttributeUnit unit); 0022 static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a); 0023 static QString getRaw(quint64 raw); 0024 0025 SmartAttribute::SmartAttribute(const SmartAttributeParsedData& a) : 0026 m_Id(a.id()), 0027 m_Name(getAttrName(a.id())), 0028 m_Desc(getAttrDescription(a.id())), 0029 m_FailureType(a.prefailure() ? FailureType::PreFailure : FailureType::OldAge), 0030 m_UpdateType(a.online() ? UpdateType::Online : UpdateType::Offline), 0031 m_Current(a.currentValueValid() ? a.currentValue() : -1), 0032 m_Worst(a.worstValueValid() ? a.worstValue() : -1), 0033 m_Threshold(a.thresholdValid() ? a.threshold() : -1), 0034 m_Raw(getRaw(a.raw())), 0035 m_Assessment(getAssessment(a)), 0036 m_Value(getPrettyValue(a.prettyValue(), a.prettyUnit())) 0037 { 0038 0039 } 0040 0041 QString SmartAttribute::assessmentToString(Assessment a) 0042 { 0043 switch (a) { 0044 case Assessment::Failing: 0045 return xi18nc("@item:intable", "failing"); 0046 0047 case Assessment::HasFailed: 0048 return xi18nc("@item:intable", "has failed"); 0049 0050 case Assessment::Warning: 0051 return xi18nc("@item:intable", "warning"); 0052 0053 case Assessment::Good: 0054 return xi18nc("@item:intable", "good"); 0055 0056 case Assessment::NotApplicable: 0057 default: 0058 return xi18nc("@item:intable not applicable", "N/A"); 0059 } 0060 } 0061 0062 static QString getPrettyValue(quint64 value, SmartAttributeUnit unit) 0063 { 0064 QString rval; 0065 0066 switch (unit) { 0067 case SmartAttributeUnit::Miliseconds: 0068 rval = KFormat().formatSpelloutDuration(value); 0069 break; 0070 0071 case SmartAttributeUnit::Sectors: 0072 rval = xi18ncp("@item:intable", "%1 sector", "%1 sectors", value); 0073 break; 0074 0075 case SmartAttributeUnit::Milikelvin: 0076 rval = SmartStatus::tempToString(value); 0077 break; 0078 0079 case SmartAttributeUnit::None: 0080 rval = QLocale().toString(value); 0081 break; 0082 0083 case SmartAttributeUnit::Unknown: 0084 default: 0085 rval = xi18nc("@item:intable not applicable", "N/A"); 0086 break; 0087 } 0088 0089 return rval; 0090 } 0091 0092 typedef struct { 0093 qint32 id; 0094 const QString name; 0095 const QString desc; 0096 } AttrDetails; 0097 0098 static const AttrDetails* attrDetails() 0099 { 0100 static const AttrDetails details[] = { 0101 { 1, i18nc("SMART attr name", "Read Error Rate"), i18nc("SMART attr description", "Rate of hardware read errors while reading data from the disk surface.") }, 0102 { 2, i18nc("SMART attr name", "Throughput Performance"), i18nc("SMART attr description", "Overall (general) throughput performance of a hard disk drive. If the value of this attribute is decreasing there is a high probability that there is a problem with the disk.") }, 0103 { 3, i18nc("SMART attr name", "Spin-Up Time"), i18nc("SMART attr description", "Average time of spindle spin up from zero RPM to fully operational.") }, 0104 { 4, i18nc("SMART attr name", "Start/Stop Count"), i18nc("SMART attr description", "A tally of spindle start/stop cycles.") }, 0105 { 5, i18nc("SMART attr name", "Reallocated Sectors Count"), i18nc("SMART attr description", "Count of reallocated sectors. When the hard drive finds a read/write/verification error, it marks this sector as "reallocated" and transfers data to a special reserved area (spare area).") }, 0106 { 6, i18nc("SMART attr name", "Read Channel Margin"), i18nc("SMART attr description", "Margin of a channel while reading data. The function of this attribute is not specified.") }, 0107 { 7, i18nc("SMART attr name", "Seek Error Rate"), i18nc("SMART attr description", "Rate of seek errors of the magnetic heads. If there is a partial failure in the mechanical positioning system, then seek errors will arise.") }, 0108 { 8, i18nc("SMART attr name", "Seek Time Performance"), i18nc("SMART attr description", "Average performance of seek operations of the magnetic heads. If this attribute is decreasing, it is a sign of problems in the mechanical subsystem.") }, 0109 { 9, i18nc("SMART attr name", "Power-On Hours"), i18nc("SMART attr description", "Count of hours in power-on state.") }, 0110 { 10, i18nc("SMART attr name", "Spin Retry Count"), i18nc("SMART attr description", "Count of retry of spin start attempts if the first attempt was unsuccessful. An increase of this attribute value is a sign of problems in the hard disk mechanical subsystem.") }, 0111 { 11, i18nc("SMART attr name", "Recalibration Retries"), i18nc("SMART attr description", "Count of recalibrations requested if the first attempt was unsuccessful. An increase of this attribute value is a sign of problems in the hard disk mechanical subsystem.") }, 0112 { 12, i18nc("SMART attr name", "Power Cycle Count"), i18nc("SMART attr description", "Count of full hard disk power on/off cycles.") }, 0113 { 13, i18nc("SMART attr name", "Soft Read Error Rate"), i18nc("SMART attr description", "Uncorrected read errors reported to the operating system.") }, 0114 { 170, i18nc("SMART attr name", "SSD Available Reserved Space"), i18nc("SMART attr description", "Number of available reserved space as a percentage of reserved space.") }, 0115 { 171, i18nc("SMART attr name", "SSD Program Fail Count"), i18nc("SMART attr description", "Number of flash program operation failures since the drive was deployed.") }, 0116 { 172, i18nc("SMART attr name", "SSD Erase Fail Count"), i18nc("SMART attr description", "Number of flash erase operation failures since the drive was deployed.") }, 0117 { 173, i18nc("SMART attr name", "SSD Wear Leveling Count"), i18nc("SMART attr description", "Counts the maximum worst erase count on any block.") }, 0118 { 174, i18nc("SMART attr name", "SSD Unexpected power loss count"), i18nc("SMART attr description", "Number of shutdowns without STANDBY IMMEDIATE as the last command (regardless of PLI activity using capacitor power). Normalized value is always 100.") }, 0119 { 175, i18nc("SMART attr name", "SSD Power Loss Protection Failure"), i18nc("SMART attr description", "Last test result, saturated at its maximum value. Bytes 0-1: last test result as microseconds to discharge cap in range [25, 5000000], lower indicates specific error code. Bytes 2-3: minutes since last test. Bytes 4-5: lifetime number of tests. Normalized value is set to 1 on test failure or 11 if the capacitor has been tested in an excessive temperature condition, otherwise 100.") }, 0120 { 176, i18nc("SMART attr name", "SSD Erase Fail Count (chip)"), i18nc("SMART attr description", "Number of flash erase command failures.") }, 0121 { 177, i18nc("SMART attr name", "SSD Wear Range Delta"), i18nc("SMART attr description", "Delta between most-worn and least-worn flash blocks.") }, 0122 { 178, i18nc("SMART attr name", "SSD Used Reserved Block Count Total"), i18nc("SMART attr description", "\"Pre-Fail\" Samsung attribute.") }, 0123 { 179, i18nc("SMART attr name", "SSD Used Reserved Block Count Total"), i18nc("SMART attr description", "\"Pre-Fail\" Samsung attribute.") }, 0124 { 180, i18nc("SMART attr name", "SSD Unused Reserved Block Count Total"), i18nc("SMART attr description", "\"Pre-Fail\" HP attribute.") }, 0125 { 181, i18nc("SMART attr name", "SSD Program Fail Count Total or Non-4K Aligned Access Count"), i18nc("SMART attr description", "Number of flash program operation failures since the drive was deployed.") }, 0126 { 182, i18nc("SMART attr name", "SSD Erase Fail Count"), i18nc("SMART attr description", "\"Pre-Fail\" Samsung attribute.") }, 0127 { 183, i18nc("SMART attr name", "SATA Downshift Error Count"), i18nc("SMART attr description", "Western Digital and Samsung attribute.") }, 0128 { 184, i18nc("SMART attr name", "End-to-End Error"), i18nc("SMART attr description", "Part of HP's SMART IV technology: After transferring through the cache RAM data buffer the parity data between the host and the hard drive did not match.") }, 0129 { 185, i18nc("SMART attr name", "Head Stability"), i18nc("SMART attr description", "Western Digital attribute.") }, 0130 { 186, i18nc("SMART attr name", "Induced Op-Vibration Detection"), i18nc("SMART attr description", "Western Digital attribute.") }, 0131 { 187, i18nc("SMART attr name", "Reported Uncorrectable Errors"), i18nc("SMART attr description", "Count of errors that could not be recovered using hardware ECC.") }, 0132 { 188, i18nc("SMART attr name", "Command Timeout"), i18nc("SMART attr description", "Count of aborted operations due to HDD timeout.") }, 0133 { 189, i18nc("SMART attr name", "High Fly Writes"), i18nc("SMART attr description", "Count of fly height errors detected.") }, 0134 { 190, i18nc("SMART attr name", "Temperature Difference From 100"), i18nc("SMART attr description", "Value is equal to (100 – temp. °C), allowing manufacturer to set a minimum threshold which corresponds to a maximum temperature.") }, 0135 { 191, i18nc("SMART attr name", "G-sense Error Rate"), i18nc("SMART attr description", "Count of errors resulting from externally-induced shock and vibration.") }, 0136 { 192, i18nc("SMART attr name", "Power Off Retract Count"), i18nc("SMART attr description", "Count of power-off or emergency retract cycles") }, 0137 { 193, i18nc("SMART attr name", "Load Cycle Count"), i18nc("SMART attr description", "Count of load/unload cycles into head landing zone position.") }, 0138 { 194, i18nc("SMART attr name", "Temperature"), i18nc("SMART attr description", "Current internal temperature.") }, 0139 { 195, i18nc("SMART attr name", "Hardware ECC Recovered"), i18nc("SMART attr description", "Count of errors that could be recovered using hardware ECC.") }, 0140 { 196, i18nc("SMART attr name", "Reallocation Event Count"), i18nc("SMART attr description", "Count of remap operations. The raw value of this attribute shows the total number of attempts to transfer data from reallocated sectors to a spare area.") }, 0141 { 197, i18nc("SMART attr name", "Current Pending Sector Count"), i18nc("SMART attr description", "Number of "unstable" sectors (waiting to be remapped, because of read errors).") }, 0142 { 198, i18nc("SMART attr name", "Uncorrectable Sector Count"), i18nc("SMART attr description", "Count of uncorrectable errors when reading/writing a sector.") }, 0143 { 199, i18nc("SMART attr name", "UltraDMA CRC Error Count"), i18nc("SMART attr description", "Count of errors in data transfer via the interface cable as determined by ICRC.") }, 0144 { 200, i18nc("SMART attr name", "Multi-Zone Error Rate<br/>Write Error Rate"), i18nc("SMART attr description", "The total number of errors when writing a sector.") }, 0145 { 201, i18nc("SMART attr name", "Soft Read Error Rate"), i18nc("SMART attr description", "Number of off-track errors.") }, 0146 { 202, i18nc("SMART attr name", "Data Address Mark Errors"), i18nc("SMART attr description", "Number of Data Address Mark errors (or vendor-specific).") }, 0147 { 203, i18nc("SMART attr name", "Run Out Cancel"), i18nc("SMART attr description", "Number of ECC errors") }, 0148 { 204, i18nc("SMART attr name", "Soft ECC Correction"), i18nc("SMART attr description", "Number of errors corrected by software ECC") }, 0149 { 205, i18nc("SMART attr name", "Thermal Asperity Rate"), i18nc("SMART attr description", "Number of errors due to high temperature.") }, 0150 { 206, i18nc("SMART attr name", "Flying Height"), i18nc("SMART attr description", "Height of heads above the disk surface. A flying height that is too low increases the chances of a head crash while a flying height that is too high increases the chances of a read/write error.") }, 0151 { 207, i18nc("SMART attr name", "Spin High Current"), i18nc("SMART attr description", "Amount of surge current used to spin up the drive.") }, 0152 { 208, i18nc("SMART attr name", "Spin Buzz"), i18nc("SMART attr description", "Number of buzz routines needed to spin up the drive due to insufficient power.") }, 0153 { 209, i18nc("SMART attr name", "Offline Seek Performance"), i18nc("SMART attr description", "Drive's seek performance during its internal tests.") }, 0154 { 211, i18nc("SMART attr name", "Vibration During Write"), i18nc("SMART attr description", "Vibration During Write") }, 0155 { 212, i18nc("SMART attr name", "Shock During Write"), i18nc("SMART attr description", "Shock During Write") }, 0156 { 220, i18nc("SMART attr name", "Disk Shift"), i18nc("SMART attr description", "Distance the disk has shifted relative to the spindle (usually due to shock or temperature).") }, 0157 { 221, i18nc("SMART attr name", "G-Sense Error Rate"), i18nc("SMART attr description", "The number of errors resulting from externally-induced shock and vibration.") }, 0158 { 222, i18nc("SMART attr name", "Loaded Hours"), i18nc("SMART attr description", "Time spent operating under data load.") }, 0159 { 223, i18nc("SMART attr name", "Load/Unload Retry Count"), i18nc("SMART attr description", "Number of times head changes position.") }, 0160 { 224, i18nc("SMART attr name", "Load Friction"), i18nc("SMART attr description", "Resistance caused by friction in mechanical parts while operating.") }, 0161 { 225, i18nc("SMART attr name", "Load/Unload Cycle Count"), i18nc("SMART attr description", "Total number of load cycles.") }, 0162 { 226, i18nc("SMART attr name", "Load-In Time"), i18nc("SMART attr description", "Total time of loading on the magnetic heads actuator (time not spent in parking area).") }, 0163 { 227, i18nc("SMART attr name", "Torque Amplification Count"), i18nc("SMART attr description", "Number of attempts to compensate for platter speed variations.") }, 0164 { 228, i18nc("SMART attr name", "Power-Off Retract Cycle"), i18nc("SMART attr description", "The number of times the magnetic armature was retracted automatically as a result of cutting power.") }, 0165 { 230, i18nc("SMART attr name", "GMR Head Amplitude"), i18nc("SMART attr description", "Amplitude of "thrashing" (distance of repetitive forward/reverse head motion)") }, 0166 { 231, i18nc("SMART attr name", "Temperature"), i18nc("SMART attr description", "Drive Temperature") }, 0167 { 232, i18nc("SMART attr name", "Endurance Remaining"), i18nc("SMART attr description", "Count of physical erase cycles completed on the drive as a percentage of the maximum physical erase cycles the drive supports") }, 0168 { 233, i18nc("SMART attr name", "Power-On Seconds"), i18nc("SMART attr description", "Time elapsed in the power-on state") }, 0169 { 234, i18nc("SMART attr name", "Unrecoverable ECC Count"), i18nc("SMART attr description", "Count of unrecoverable ECC errors") }, 0170 { 235, i18nc("SMART attr name", "Good Block Rate"), i18nc("SMART attr description", "Count of available reserved blocks as percentage of the total number of reserved blocks") }, 0171 { 240, i18nc("SMART attr name", "Head Flying Hours<br/>or Transfer Error Rate (Fujitsu)"), i18nc("SMART attr description", "Time while head is positioning<br/>or counts the number of times the link is reset during a data transfer.") }, 0172 { 241, i18nc("SMART attr name", "Total LBAs Written"), i18nc("SMART attr description", "Total LBAs Written") }, 0173 { 242, i18nc("SMART attr name", "Total LBAs Read"), i18nc("SMART attr description", "Total LBAs Read") }, 0174 { 249, i18nc("SMART attr name", "SSD NAND_Writes_1GiB"), i18nc("SMART attr description", "Number of writes to NAND in 1 GB increments") }, 0175 { 250, i18nc("SMART attr name", "Read Error Retry Rate"), i18nc("SMART attr description", "Number of errors while reading from a disk") }, 0176 { 254, i18nc("SMART attr name", "Free Fall Protection"), i18nc("SMART attr description", "Number of "Free Fall Events" detected") }, 0177 { -1, QString(), QString() } 0178 }; 0179 0180 return details; 0181 } 0182 0183 static QString getAttrName(qint32 id) 0184 { 0185 qint32 idx = 0; 0186 0187 while (attrDetails()[idx].id != -1) { 0188 if (attrDetails()[idx].id == id) 0189 return attrDetails()[idx].name; 0190 idx++; 0191 } 0192 0193 return QString(); 0194 } 0195 0196 static QString getAttrDescription(qint32 id) 0197 { 0198 qint32 idx = 0; 0199 0200 while (attrDetails()[idx].id != -1) { 0201 if (attrDetails()[idx].id == id) 0202 return attrDetails()[idx].desc; 0203 idx++; 0204 } 0205 0206 return QString(); 0207 } 0208 0209 static SmartAttribute::Assessment getAssessment(const SmartAttributeParsedData& a) 0210 { 0211 SmartAttribute::Assessment rval = SmartAttribute::Assessment::NotApplicable; 0212 0213 bool failed = false; 0214 bool hasFailed = false; 0215 0216 if (a.prefailure()) { 0217 if (a.goodNowValid() && !a.goodNow()) 0218 failed = true; 0219 0220 if (a.goodInThePastValid() && !a.goodInThePast()) 0221 hasFailed = true; 0222 } else if (a.thresholdValid()) { 0223 if (a.currentValueValid() && a.currentValue() <= a.threshold()) 0224 failed = true; 0225 else if (a.worstValueValid() && a.worstValue() <= a.threshold()) 0226 hasFailed = true; 0227 } 0228 0229 if (failed) 0230 rval = SmartAttribute::Assessment::Failing; 0231 else if (hasFailed) 0232 rval = SmartAttribute::Assessment::HasFailed; 0233 else if (a.warn()) 0234 rval = SmartAttribute::Assessment::Warning; 0235 else if (a.goodNowValid()) 0236 rval = SmartAttribute::Assessment::Good; 0237 0238 return rval; 0239 } 0240 0241 static QString getRaw(quint64 raw) 0242 { 0243 QString rval = QStringLiteral("0x"); 0244 rval += QStringLiteral("%1").arg(raw, 12, 16, QLatin1Char('0')); 0245 return rval; 0246 }