atasmart: ignore sector count if it is -1
[platform/upstream/libatasmart.git] / atasmart.c
index f228aef..f3c8e32 100644 (file)
@@ -1213,7 +1213,12 @@ static void make_pretty(SkSmartAttributeParsedData *a) {
                 a->pretty_value = a->current_value;
         else if (!strcmp(a->name, "total-lbas-written") ||
                  !strcmp(a->name, "total-lbas-read"))
-                a->pretty_value = fourtyeight * 65535 * 512 / 1000000000;
+                a->pretty_value = fourtyeight * 65536LLU * 512LLU / 1000000LLU;
+        else if (!strcmp(a->name, "timed-workload-media-wear") ||
+                 !strcmp(a->name, "timed-workload-host-reads"))
+                a->pretty_value = (double)fourtyeight / 1024LLU;
+        else if (!strcmp(a->name, "workload-timer"))
+                a->pretty_value = fourtyeight * 60 * 1000;
         else
                 a->pretty_value = fourtyeight;
 }
@@ -1268,7 +1273,9 @@ static void verify_sectors(SkDisk *d, SkSmartAttributeParsedData *a) {
 
         max_sectors = d->size / 512ULL;
 
-        if (max_sectors > 0 && a->pretty_value > max_sectors) {
+        if (a->pretty_value == 0xffffffffULL ||
+            a->pretty_value == 0xffffffffffffffffULL ||
+            (max_sectors > 0 && a->pretty_value > max_sectors)) {
                 a->pretty_value = SK_SMART_ATTRIBUTE_UNIT_UNKNOWN;
                 d->attribute_verification_bad = TRUE;
         } else {
@@ -1297,6 +1304,8 @@ static const SkSmartAttributeInfo const attribute_info[256] = {
         [12]  = { "power-cycle-count",           SK_SMART_ATTRIBUTE_UNIT_NONE,     NULL },
         [13]  = { "read-soft-error-rate",        SK_SMART_ATTRIBUTE_UNIT_NONE,     NULL },
         [170] = { "available-reserved-space",    SK_SMART_ATTRIBUTE_UNIT_PERCENT,  NULL },
+        [171] = { "program-fail-count",          SK_SMART_ATTRIBUTE_UNIT_NONE,     NULL },
+        [172] = { "erase-fail-count",            SK_SMART_ATTRIBUTE_UNIT_NONE,     NULL },
         [184] = { "end-to-end-error",            SK_SMART_ATTRIBUTE_UNIT_NONE,     NULL },
         [187] = { "reported-uncorrect",          SK_SMART_ATTRIBUTE_UNIT_SECTORS,  verify_sectors },
         [188] = { "command-timeout",             SK_SMART_ATTRIBUTE_UNIT_NONE,     NULL },
@@ -1340,30 +1349,35 @@ static const SkSmartAttributeInfo const attribute_info[256] = {
         [235] = { "good-block-rate",             SK_SMART_ATTRIBUTE_UNIT_UNKNOWN,  NULL },
 
         [240] = { "head-flying-hours",           SK_SMART_ATTRIBUTE_UNIT_MSECONDS, verify_long_time },
-        [241] = { "total-lbas-written",          SK_SMART_ATTRIBUTE_UNIT_GB,  NULL },
-        [242] = { "total-lbas-read",             SK_SMART_ATTRIBUTE_UNIT_GB,  NULL },
+        [241] = { "total-lbas-written",          SK_SMART_ATTRIBUTE_UNIT_MB,  NULL },
+        [242] = { "total-lbas-read",             SK_SMART_ATTRIBUTE_UNIT_MB,  NULL },
         [250] = { "read-error-retry-rate",       SK_SMART_ATTRIBUTE_UNIT_NONE,     NULL }
 };
 /* %STRINGPOOLSTOP% */
 
 typedef enum SkSmartQuirk {
-        SK_SMART_QUIRK_9_POWERONMINUTES            = 0x00001,
-        SK_SMART_QUIRK_9_POWERONSECONDS            = 0x00002,
-        SK_SMART_QUIRK_9_POWERONHALFMINUTES        = 0x00004,
-        SK_SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT = 0x00008,
-        SK_SMART_QUIRK_193_LOADUNLOAD              = 0x00010,
-        SK_SMART_QUIRK_194_10XCELSIUS              = 0x00020,
-        SK_SMART_QUIRK_194_UNKNOWN                 = 0x00040,
-        SK_SMART_QUIRK_200_WRITEERRORCOUNT         = 0x00080,
-        SK_SMART_QUIRK_201_DETECTEDTACOUNT         = 0x00100,
-        SK_SMART_QUIRK_5_UNKNOWN                   = 0x00200,
-        SK_SMART_QUIRK_9_UNKNOWN                   = 0x00400,
-        SK_SMART_QUIRK_197_UNKNOWN                 = 0x00800,
-        SK_SMART_QUIRK_198_UNKNOWN                 = 0x01000,
-        SK_SMART_QUIRK_190_UNKNOWN                 = 0x02000,
-        SK_SMART_QUIRK_232_AVAILABLERESERVEDSPACE  = 0x04000,
-        SK_SMART_QUIRK_233_MEDIAWEAROUTINDICATOR   = 0x08000,
-        SK_SMART_QUIRK_225_TOTALLBASWRITTEN        = 0x10000
+        SK_SMART_QUIRK_9_POWERONMINUTES            = 0x000001,
+        SK_SMART_QUIRK_9_POWERONSECONDS            = 0x000002,
+        SK_SMART_QUIRK_9_POWERONHALFMINUTES        = 0x000004,
+        SK_SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT = 0x000008,
+        SK_SMART_QUIRK_193_LOADUNLOAD              = 0x000010,
+        SK_SMART_QUIRK_194_10XCELSIUS              = 0x000020,
+        SK_SMART_QUIRK_194_UNKNOWN                 = 0x000040,
+        SK_SMART_QUIRK_200_WRITEERRORCOUNT         = 0x000080,
+        SK_SMART_QUIRK_201_DETECTEDTACOUNT         = 0x000100,
+        SK_SMART_QUIRK_5_UNKNOWN                   = 0x000200,
+        SK_SMART_QUIRK_9_UNKNOWN                   = 0x000400,
+        SK_SMART_QUIRK_197_UNKNOWN                 = 0x000800,
+        SK_SMART_QUIRK_198_UNKNOWN                 = 0x001000,
+        SK_SMART_QUIRK_190_UNKNOWN                 = 0x002000,
+        SK_SMART_QUIRK_232_AVAILABLERESERVEDSPACE  = 0x004000,
+        SK_SMART_QUIRK_233_MEDIAWEAROUTINDICATOR   = 0x008000,
+        SK_SMART_QUIRK_225_TOTALLBASWRITTEN        = 0x010000,
+        SK_SMART_QUIRK_4_UNUSED                    = 0x020000,
+        SK_SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR   = 0x040000,
+        SK_SMART_QUIRK_227_TIMEWORKLOADHOSTREADS   = 0x080000,
+        SK_SMART_QUIRK_228_WORKLOADTIMER           = 0x100000,
+        SK_SMART_QUIRK_3_UNUSED                    = 0x200000
 } SkSmartQuirk;
 
 /* %STRINGPOOLSTART% */
@@ -1383,6 +1397,13 @@ static const char *quirk_name[] = {
         "198_UNKNOWN",
         "190_UNKNOWN",
         "232_AVAILABLERESERVEDSPACE",
+        "233_MEDIAWEAROUTINDICATOR",
+        "225_TOTALLBASWRITTEN",
+        "4_UNUSED",
+        "226_TIMEWORKLOADMEDIAWEAR",
+        "227_TIMEWORKLOADHOSTREADS",
+        "228_WORKLOADTIMER",
+        "3_UNUSED",
         NULL
 };
 /* %STRINGPOOLSTOP% */
@@ -1539,7 +1560,12 @@ static const SkSmartQuirkDatabase quirk_database[] = { {
         /*** Intel */
                 "^INTEL SSDSA2CW[0-9]{3}G3$",
                 NULL,
+                SK_SMART_QUIRK_3_UNUSED|
+                SK_SMART_QUIRK_4_UNUSED|
                 SK_SMART_QUIRK_225_TOTALLBASWRITTEN|
+                SK_SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR|
+                SK_SMART_QUIRK_227_TIMEWORKLOADHOSTREADS|
+                SK_SMART_QUIRK_228_WORKLOADTIMER|
                 SK_SMART_QUIRK_232_AVAILABLERESERVEDSPACE|
                 SK_SMART_QUIRK_233_MEDIAWEAROUTINDICATOR
         }, {
@@ -1624,6 +1650,29 @@ static const SkSmartAttributeInfo *lookup_attribute(SkDisk *d, uint8_t id) {
 
         if (quirk) {
                 switch (id) {
+                        case 3:
+                                /* %STRINGPOOLSTART% */
+                                if (quirk & SK_SMART_QUIRK_3_UNUSED) {
+                                        static const SkSmartAttributeInfo a = {
+                                                "spin-up-time", SK_SMART_ATTRIBUTE_UNIT_UNKNOWN, NULL
+                                        };
+                                        return &a;
+                                }
+                                /* %STRINGPOOLSTOP% */
+
+                                break;
+
+                        case 4:
+                                /* %STRINGPOOLSTART% */
+                                if (quirk & SK_SMART_QUIRK_4_UNUSED) {
+                                        static const SkSmartAttributeInfo a = {
+                                                "start-stop-count", SK_SMART_ATTRIBUTE_UNIT_UNKNOWN, NULL
+                                        };
+                                        return &a;
+                                }
+                                /* %STRINGPOOLSTOP% */
+
+                                break;
 
                         case 5:
                                 if (quirk & SK_SMART_QUIRK_5_UNKNOWN)
@@ -1727,7 +1776,43 @@ static const SkSmartAttributeInfo *lookup_attribute(SkDisk *d, uint8_t id) {
                                 /* %STRINGPOOLSTART% */
                                 if (quirk & SK_SMART_QUIRK_225_TOTALLBASWRITTEN) {
                                         static const SkSmartAttributeInfo a = {
-                                                "total-lbas-written", SK_SMART_ATTRIBUTE_UNIT_GB, NULL
+                                                "total-lbas-written", SK_SMART_ATTRIBUTE_UNIT_MB, NULL
+                                        };
+                                        return &a;
+                                }
+                                /* %STRINGPOOLSTOP% */
+
+                                break;
+
+                        case 226:
+                                /* %STRINGPOOLSTART% */
+                                if (quirk & SK_SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) {
+                                        static const SkSmartAttributeInfo a = {
+                                                "timed-workload-media-wear", SK_SMART_ATTRIBUTE_UNIT_SMALL_PERCENT, NULL
+                                        };
+                                        return &a;
+                                }
+                                /* %STRINGPOOLSTOP% */
+
+                                break;
+
+                        case 227:
+                                /* %STRINGPOOLSTART% */
+                                if (quirk & SK_SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) {
+                                        static const SkSmartAttributeInfo a = {
+                                                "timed-workload-host-reads", SK_SMART_ATTRIBUTE_UNIT_SMALL_PERCENT, NULL
+                                        };
+                                        return &a;
+                                }
+                                /* %STRINGPOOLSTOP% */
+
+                                break;
+
+                        case 228:
+                                /* %STRINGPOOLSTART% */
+                                if (quirk & SK_SMART_QUIRK_228_WORKLOADTIMER) {
+                                        static const SkSmartAttributeInfo a = {
+                                                "workload-timer", SK_SMART_ATTRIBUTE_UNIT_MSECONDS, NULL
                                         };
                                         return &a;
                                 }
@@ -1750,7 +1835,7 @@ static const SkSmartAttributeInfo *lookup_attribute(SkDisk *d, uint8_t id) {
                                 /* %STRINGPOOLSTART% */
                                 if (quirk & SK_SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) {
                                         static const SkSmartAttributeInfo a = {
-                                                "media-wearout-indicator", SK_SMART_ATTRIBUTE_UNIT_UNKNOWN, NULL
+                                                "media-wearout-indicator", SK_SMART_ATTRIBUTE_UNIT_PERCENT, NULL
                                         };
                                         return &a;
                                 }
@@ -1949,7 +2034,8 @@ const char* sk_smart_attribute_unit_to_string(SkSmartAttributeUnit unit) {
                 [SK_SMART_ATTRIBUTE_UNIT_SECTORS] = "sectors",
                 [SK_SMART_ATTRIBUTE_UNIT_MKELVIN] = "mK",
                 [SK_SMART_ATTRIBUTE_UNIT_PERCENT] = "%",
-                [SK_SMART_ATTRIBUTE_UNIT_GB] = "GB"
+                [SK_SMART_ATTRIBUTE_UNIT_SMALL_PERCENT] = "%",
+                [SK_SMART_ATTRIBUTE_UNIT_MB] = "MB"
         };
         /* %STRINGPOOLSTOP% */
 
@@ -2290,8 +2376,17 @@ static char *print_value(char *s, size_t len, uint64_t pretty_value, SkSmartAttr
                         snprintf(s, len, "%llu%%", (unsigned long long) pretty_value);
                         break;
 
-                case SK_SMART_ATTRIBUTE_UNIT_GB:
-                        snprintf(s, len, "%llu GB", (unsigned long long) pretty_value);
+                case SK_SMART_ATTRIBUTE_UNIT_SMALL_PERCENT:
+                        snprintf(s, len, "%0.3f%%", (double) pretty_value);
+                        break;
+
+                case SK_SMART_ATTRIBUTE_UNIT_MB:
+                        if (pretty_value >= 1000000LLU)
+                          snprintf(s, len, "%0.3f TB",  (double) pretty_value / 1000000LLU);
+                        else if (pretty_value >= 1000LLU)
+                          snprintf(s, len, "%0.3f GB",  (double) pretty_value / 1000LLU);
+                        else
+                          snprintf(s, len, "%llu MB", (unsigned long long) pretty_value);
                         break;
 
                 case SK_SMART_ATTRIBUTE_UNIT_NONE: