14#define __STDC_FORMAT_MACROS 1
41 return (*output ? output :
"[No Information Found]");
68 unsigned char CR,
unsigned char FR,
69 unsigned char ST,
unsigned char ER,
75 const char *error_flag[8];
76 int i, print_lba=0, print_sector=0;
80 const char *abrt =
"ABRT";
81 const char *amnf =
"AMNF";
82 const char *ccto =
"CCTO";
83 const char *eom =
"EOM";
84 const char *icrc =
"ICRC";
85 const char *idnf =
"IDNF";
86 const char *ili =
"ILI";
87 const char *mc =
"MC";
88 const char *mcr =
"MCR";
89 const char *nm =
"NM";
90 const char *obs =
"obs";
91 const char *tk0nf =
"TK0NF";
92 const char *unc =
"UNC";
93 const char *wp =
"WP";
99 int uses_device_fault = 1;
102 for (i = 0; i < 8; i++)
103 error_flag[i] = NULL;
109 error_flag[2] = abrt;
110 error_flag[1] = tk0nf;
119 error_flag[4] = idnf;
121 error_flag[2] = abrt;
123 error_flag[0] = amnf;
128 error_flag[4] = idnf;
129 error_flag[2] = abrt;
130 error_flag[0] = amnf;
136 error_flag[7] = icrc;
139 error_flag[4] = idnf;
141 error_flag[2] = abrt;
143 error_flag[0] = ccto;
150 error_flag[7] = icrc;
153 error_flag[4] = idnf;
155 error_flag[2] = abrt;
157 error_flag[0] = ccto;
167 error_flag[7] = icrc;
170 error_flag[4] = idnf;
172 error_flag[2] = abrt;
174 error_flag[0] = amnf;
176 if (CR==0x25 || CR==0xC8)
187 error_flag[4] = idnf;
189 error_flag[2] = abrt;
195 error_flag[4] = idnf;
196 error_flag[2] = abrt;
201 error_flag[4] = idnf;
202 error_flag[2] = abrt;
203 error_flag[0] = amnf;
211 error_flag[4] = idnf;
213 error_flag[2] = abrt;
215 error_flag[0] = amnf;
224 error_flag[7] =
"Sense key (bit 3)",
225 error_flag[6] =
"Sense key (bit 2)",
226 error_flag[5] =
"Sense key (bit 1)",
227 error_flag[4] =
"Sense key (bit 0)",
228 error_flag[2] = abrt;
236 error_flag[2] = abrt;
240 error_flag[4] = idnf;
241 error_flag[2] = abrt;
245 error_flag[4] = idnf;
246 error_flag[2] = abrt;
255 error_flag[4] = idnf;
256 error_flag[2] = abrt;
260 error_flag[4] = idnf;
261 error_flag[2] = abrt;
270 error_flag[2] = abrt;
273 error_flag[4] = idnf;
274 error_flag[2] = abrt;
284 error_flag[2] = abrt;
299 error_flag[7] = icrc;
302 error_flag[4] = idnf;
304 error_flag[2] = abrt;
306 error_flag[0] = amnf;
313 error_flag[2] = abrt;
321 if (uses_device_fault && (ST & (1 << 5))) {
322 str =
"Device Fault";
330 for (i = 7; i >= 0; i--)
331 if ((ER & (1 << i)) && (error_flag[i])) {
334 str += error_flag[i];
343 str +=
strprintf(
" %d sectors", print_sector);
358 str +=
strprintf(
" at LBA = 0x%08x = %u", lba, lba);
360 else if (lba48_regs) {
376 str +=
strprintf(
" at LBA = 0x%08" PRIx64
" = %" PRIu64, lba48, lba48);
387 data->commands[4].commandreg,
388 data->commands[4].featuresreg,
389 data->error_struct.status,
390 data->error_struct.error_register,
391 data->error_struct.sector_count,
399 data->commands[4].command_register,
400 data->commands[4].features_register,
401 data->error.status_register,
402 data->error.error_register,
403 data->error.count_register_hi << 8 |
data->error.count_register,
414 switch (word168 & 0xF) {
415 case 0x1:
return "5.25 inches";
416 case 0x2:
return "3.5 inches";
417 case 0x3:
return "2.5 inches";
418 case 0x4:
return "1.8 inches";
419 case 0x5:
return "< 1.8 inches";
420 case 0x6:
return "mSATA";
421 case 0x7:
return "M.2";
422 case 0x8:
return "MicroSSD";
423 case 0x9:
return "CFast";
430 for (
int bit = 15; bit >= 0; bit--)
431 if (word & (1 << bit))
444 case 15:
return "ACS >6 (15)";
445 case 14:
return "ACS >6 (14)";
446 case 13:
return "ACS-6";
447 case 12:
return "ACS-5";
448 case 11:
return "ACS-4";
449 case 10:
return "ACS-3";
450 case 9:
return "ACS-2";
451 case 8:
return "ATA8-ACS";
452 case 7:
return "ATA/ATAPI-7";
453 case 6:
return "ATA/ATAPI-6";
454 case 5:
return "ATA/ATAPI-5";
455 case 4:
return "ATA/ATAPI-4";
456 case 3:
return "ATA-3";
457 case 2:
return "ATA-2";
458 case 1:
return "ATA-1";
474 case 0x0001:
return "ATA-1 X3T9.2/781D prior to revision 4";
475 case 0x0002:
return "ATA-1 published, ANSI X3.221-1994";
476 case 0x0003:
return "ATA-1 X3T9.2/781D revision 4";
477 case 0x0004:
return "ATA-2 published, ANSI X3.279-1996";
478 case 0x0005:
return "ATA-2 X3T10/948D prior to revision 2k";
479 case 0x0006:
return "ATA-3 X3T10/2008D revision 1";
480 case 0x0007:
return "ATA-2 X3T10/948D revision 2k";
481 case 0x0008:
return "ATA-3 X3T10/2008D revision 0";
482 case 0x0009:
return "ATA-2 X3T10/948D revision 3";
483 case 0x000a:
return "ATA-3 published, ANSI X3.298-1997";
484 case 0x000b:
return "ATA-3 X3T10/2008D revision 6";
485 case 0x000c:
return "ATA-3 X3T13/2008D revision 7 and 7a";
486 case 0x000d:
return "ATA/ATAPI-4 X3T13/1153D revision 6";
487 case 0x000e:
return "ATA/ATAPI-4 T13/1153D revision 13";
488 case 0x000f:
return "ATA/ATAPI-4 X3T13/1153D revision 7";
489 case 0x0010:
return "ATA/ATAPI-4 T13/1153D revision 18";
490 case 0x0011:
return "ATA/ATAPI-4 T13/1153D revision 15";
491 case 0x0012:
return "ATA/ATAPI-4 published, ANSI NCITS 317-1998";
492 case 0x0013:
return "ATA/ATAPI-5 T13/1321D revision 3";
493 case 0x0014:
return "ATA/ATAPI-4 T13/1153D revision 14";
494 case 0x0015:
return "ATA/ATAPI-5 T13/1321D revision 1";
495 case 0x0016:
return "ATA/ATAPI-5 published, ANSI NCITS 340-2000";
496 case 0x0017:
return "ATA/ATAPI-4 T13/1153D revision 17";
497 case 0x0018:
return "ATA/ATAPI-6 T13/1410D revision 0";
498 case 0x0019:
return "ATA/ATAPI-6 T13/1410D revision 3a";
499 case 0x001a:
return "ATA/ATAPI-7 T13/1532D revision 1";
500 case 0x001b:
return "ATA/ATAPI-6 T13/1410D revision 2";
501 case 0x001c:
return "ATA/ATAPI-6 T13/1410D revision 1";
502 case 0x001d:
return "ATA/ATAPI-7 published, ANSI INCITS 397-2005";
503 case 0x001e:
return "ATA/ATAPI-7 T13/1532D revision 0";
504 case 0x001f:
return "ACS-3 T13/2161-D revision 3b";
506 case 0x0021:
return "ATA/ATAPI-7 T13/1532D revision 4a";
507 case 0x0022:
return "ATA/ATAPI-6 published, ANSI INCITS 361-2002";
509 case 0x0025:
return "ACS-6 T13/BSR INCITS 574 revision 7";
511 case 0x0027:
return "ATA8-ACS T13/1699-D revision 3c";
512 case 0x0028:
return "ATA8-ACS T13/1699-D revision 6";
513 case 0x0029:
return "ATA8-ACS T13/1699-D revision 4";
515 case 0x0030:
return "ACS-5 T13/BSR INCITS 558 revision 10";
516 case 0x0031:
return "ACS-2 T13/2015-D revision 2";
518 case 0x0033:
return "ATA8-ACS T13/1699-D revision 3e";
520 case 0x0039:
return "ATA8-ACS T13/1699-D revision 4c";
522 case 0x0042:
return "ATA8-ACS T13/1699-D revision 3f";
524 case 0x0052:
return "ATA8-ACS T13/1699-D revision 3b";
526 case 0x005e:
return "ACS-4 T13/BSR INCITS 529 revision 5";
528 case 0x006d:
return "ACS-3 T13/2161-D revision 5";
530 case 0x0070:
return "ACS-6 T13/BSR INCITS 574 revision 11";
532 case 0x0073:
return "ACS-6 T13/BSR INCITS 574 revision 2";
534 case 0x0082:
return "ACS-2 published, ANSI INCITS 482-2012";
536 case 0x009c:
return "ACS-4 published, ANSI INCITS 529-2018";
538 case 0x0107:
return "ATA8-ACS T13/1699-D revision 2d";
540 case 0x010a:
return "ACS-3 published, ANSI INCITS 522-2014";
542 case 0x0110:
return "ACS-2 T13/2015-D revision 3";
544 case 0x011b:
return "ACS-3 T13/2161-D revision 4";
554 switch (word222 & 0x0fff) {
555 default: snprintf(buf,
sizeof(buf),
556 "Unknown (0x%03x)", word222 & 0x0fff);
return buf;
558 case 0x003:
return "ATA8-APT";
559 case 0x002:
return "ATA/ATAPI-7";
571 switch (
find_msb(word222 & 0x0fff)) {
572 case 11:
return "SATA >3.5 (11)";
573 case 10:
return "SATA 3.5";
574 case 9:
return "SATA 3.4";
575 case 8:
return "SATA 3.3";
576 case 7:
return "SATA 3.2";
577 case 6:
return "SATA 3.1";
578 case 5:
return "SATA 3.0";
579 case 4:
return "SATA 2.6";
580 case 3:
return "SATA 2.5";
581 case 2:
return "SATA II Ext";
582 case 1:
return "SATA 1.0a";
583 case 0:
return "ATA8-AST";
597 default:
return ">6.0 Gb/s (7)";
598 case 6:
return ">6.0 Gb/s (6)";
599 case 5:
return ">6.0 Gb/s (5)";
600 case 4:
return ">6.0 Gb/s (4)";
601 case 3:
return "6.0 Gb/s";
602 case 2:
return "3.0 Gb/s";
603 case 1:
return "1.5 Gb/s";
612 jref[
"sata_value"] = value;
614 jref[
"string"] = str;
617 case 3: ups = 60;
break;
618 case 2: ups = 30;
break;
619 case 1: ups = 15;
break;
622 jref[
"units_per_second"] = ups;
623 jref[
"bits_per_unit"] = 100000000;
627 unsigned short word076,
628 unsigned short word077)
630 int allspeeds = (!(word076 & 0x0001) ? (word076 & 0x00fe) : 0);
631 int maxspeed = (allspeeds ?
find_msb(allspeeds) : 0);
632 int curspeed = (!(word077 & 0x0001) ? ((word077 >> 1) & 0x7) : 0);
637 jout(
"SATA Version is: %s%s%s%s%s%s\n",
638 (verstr ? verstr :
"Unknown"),
639 (maxstr ?
", " :
""), (maxstr ? maxstr :
""),
640 (curstr ?
" (current: " :
""), (curstr ? curstr :
""),
641 (curstr ?
")" :
""));
643 jglb[
"sata_version"][
"string"] = verstr;
644 jglb[
"sata_version"][
"value"] = word222 & 0x0fff;
654 char model[40+1], serial[20+1], firmware[8+1];
666 jglb[
"model_name"] = model;
670 jglb[
"serial_number"] = serial;
672 unsigned oui = 0; uint64_t unique_id = 0;
675 jout(
"LU WWN Device Id: %x %06x %09" PRIx64
"\n", naa, oui, unique_id);
676 jglb[
"wwn"][
"naa"] = naa;
677 jglb[
"wwn"][
"oui"] = oui;
678 jglb[
"wwn"][
"id"] = unique_id;
688 jout(
"Add. Product Id: %s\n", add);
689 jglb[
"ata_additional_product_id"] = add;
694 jglb[
"firmware_version"] = firmware;
698 char num[64], cap[32];
699 jout(
"User Capacity: %s bytes [%s]\n",
702 jglb[
"user_capacity"][
"blocks"].set_unsafe_uint64(sizes.
sectors);
703 jglb[
"user_capacity"][
"bytes"].set_unsafe_uint64(sizes.
capacity);
709 jout(
"Sector Sizes: %u bytes logical, %u bytes physical",
722 jout(
"Rotation Rate: Solid State Device\n");
724 jout(
"Rotation Rate: %d rpm\n", rpm);
726 pout(
"Rotation Rate: Unknown (0x%04x)\n", -rpm);
728 jglb[
"rotation_rate"] = (rpm == 1 ? 0 : rpm);
736 jout(
"Form Factor: %s\n", form_factor);
738 jout(
"Form Factor: Unknown (0x%04x)\n", word168);
739 jglb[
"form_factor"][
"ata_value"] = word168;
741 jglb[
"form_factor"][
"name"] = form_factor;
745 bool trim_sup = !!(drive->
words088_255[169-88] & 0x0001);
747 bool trim_det = !!(word069 & 0x4000), trim_zeroed = !!(word069 & 0x0020);
748 if (trim_sup || rpm == 1)
749 jout(
"TRIM Command: %s%s%s\n",
750 (!trim_sup ?
"Unavailable" :
"Available"),
751 (!(trim_sup && trim_det) ?
"" :
", deterministic"),
752 (!(trim_sup && trim_zeroed) ?
"" :
", zeroed") );
753 jglb[
"trim"][
"supported"] = trim_sup;
755 jglb[
"trim"][
"deterministic"] = trim_det;
756 jglb[
"trim"][
"zeroed"] = trim_zeroed;
761 unsigned short zoned_caps = word069 & 0x3;
763 jout(
"Zoned Device: %s\n",
764 (zoned_caps == 0x1 ?
"Host Aware Zones" :
765 zoned_caps == 0x2 ?
"Device managed zones" :
"Unknown (0x3)"));
766 if (zoned_caps < 0x3)
767 jglb[
"zoned_device"][
"capabilities"] = (zoned_caps == 0x1 ?
"host_aware" :
"device_managed");
771 jout(
"Device is: %s%s%s\n",
772 (dbentry ?
"In smartctl database" :
"Not in smartctl database"),
773 (*dbversion ?
" " :
""), (*dbversion ? dbversion :
""));
774 jglb[
"in_smartctl_database"] = !!dbentry;
798 ataver +=
" (minor revision not indicated)";
802 if (!ataver.empty()) {
803 jglb[
"ata_version"][
"string"] = ataver;
810 if (word222 != 0x0000 && word222 != 0xffff)
switch (word222 >> 12) {
823 pout(
"Transport Type: PCIe (0x%03x)\n", word222 & 0x0fff);
826 pout(
"Transport Type: Unknown (0x%04x)\n", word222);
839 unsigned char stat=status_byte & 0x7f;
843 return "was never started";
845 return "was completed without error";
847 if (status_byte == 0x03)
848 return "is in progress";
850 return "is in a Reserved state";
852 return "was suspended by an interrupting command from host";
854 return "was aborted by an interrupting command from host";
856 return "was aborted by the device with a fatal error";
859 return "is in a Vendor Specific state";
861 return "is in a Reserved state";
869 json::ref jref =
jglb[
"ata_smart_data"][
"offline_data_collection"][
"status"];
871 jout(
"Offline data collection status: (0x%02x)\t",
872 (
int)
data->offline_data_collection_status);
873 jref[
"value"] =
data->offline_data_collection_status;
877 jout(
"Offline data collection activity\n"
880 switch (
data->offline_data_collection_status & 0x7f) {
881 case 0x02: jref[
"passed"] =
true;
break;
882 case 0x06: jref[
"passed"] =
false;
break;
887 if (
data->offline_data_collection_status & 0x80)
888 pout(
"\t\t\t\t\tAuto Offline Data Collection: Enabled.\n");
890 pout(
"\t\t\t\t\tAuto Offline Data Collection: Disabled.\n");
898 unsigned char status =
data->self_test_exec_status;
899 jout(
"Self-test execution status: ");
901 switch (
data->self_test_exec_status >> 4) {
903 jout(
"(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status);
904 jout(
"without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
907 jout(
"(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", status);
911 jout(
"(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", status);
912 jout(
"by the host with a hard or soft reset.\n");
915 jout(
"(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", status);
916 jout(
"occurred while the device was executing\n\t\t\t\t\t");
917 jout(
"its self-test routine and the device \n\t\t\t\t\t");
918 jout(
"was unable to complete the self-test \n\t\t\t\t\t");
922 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
923 jout(
"a test element that failed and the test\n\t\t\t\t\t");
924 jout(
"element that failed is not known.\n");
927 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
928 jout(
"the electrical element of the test\n\t\t\t\t\t");
932 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
933 jout(
"the servo (and/or seek) element of the \n\t\t\t\t\t");
934 jout(
"test failed.\n");
937 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
938 jout(
"the read element of the test failed.\n");
941 jout(
"(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
942 jout(
"a test element that failed and the\n\t\t\t\t\t");
943 jout(
"device is suspected of having handling\n\t\t\t\t\t");
948 pout(
"(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status);
949 pout(
"with unknown result or self-test in\n\t\t\t\t\t");
950 pout(
"progress with less than 10%% remaining.\n");
953 jout(
"(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", status);
954 jout(
"%1d0%% of test remaining.\n", status & 0x0f);
958 jout(
"(%4d)\tReserved.\n", status);
962 json::ref jref =
jglb[
"ata_smart_data"][
"self_test"][
"status"];
964 jref[
"value"] = status;
967 switch (status >> 4) {
968 case 0x0: msg =
"completed without error";
break;
969 case 0x1: msg =
"was aborted by the host";
break;
970 case 0x2: msg =
"was interrupted by the host with a reset";
break;
971 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
972 case 0x4: msg =
"completed with error (unknown test element)";
break;
973 case 0x5: msg =
"completed with error (electrical test element)";
break;
974 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
975 case 0x7: msg =
"completed with error (read test element)";
break;
976 case 0x8: msg =
"completed with error (handling damage?)";
break;
980 jref[
"string"] = msg;
981 switch (status >> 4) {
982 case 0x1:
case 0x2:
case 0x3:
break;
983 default: jref[
"passed"] = ((status >> 4) == 0x0);
986 else if ((status >> 4) == 0xf) {
987 jref[
"string"] =
strprintf(
"in progress, %u0%% remaining", status & 0xf);
988 jref[
"remaining_percent"] = (status & 0xf) * 10;
994 jout(
"Total time to complete Offline \n");
995 jout(
"data collection: \t\t(%5d) seconds.\n",
996 (
int)
data->total_time_to_complete_off_line);
998 jglb[
"ata_smart_data"][
"offline_data_collection"][
"completion_seconds"] =
999 data->total_time_to_complete_off_line;
1006 jout(
"Offline data collection\n");
1007 jout(
"capabilities: \t\t\t (0x%02x) ",
1008 (
int)
data->offline_data_collection_capability);
1009 jref[
"values"][0] =
data->offline_data_collection_capability;
1011 if (
data->offline_data_collection_capability == 0x00){
1012 jout(
"\tOffline data collection not supported.\n");
1016 "SMART execute Offline immediate." :
1017 "No SMART execute Offline immediate.");
1022 "Auto Offline data collection on/off support.":
1023 "No Auto Offline data collection support.");
1026 "Abort Offline collection upon new\n\t\t\t\t\tcommand.":
1027 "Suspend Offline collection upon new\n\t\t\t\t\tcommand.");
1031 "Offline surface scan supported.":
1032 "No Offline surface scan supported.");
1036 "Self-test supported.":
1037 "No Self-test supported.");
1041 "Conveyance Self-test supported.":
1042 "No Conveyance Self-test supported.");
1046 "Selective Self-test supported.":
1047 "No Selective Self-test supported.");
1056 jout(
"SMART capabilities: ");
1057 jout(
"(0x%04x)\t", (
int)
data->smart_capability);
1058 jref[
"values"][1] =
data->smart_capability;
1060 if (
data->smart_capability == 0x00)
1061 jout(
"Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
1063 jout(
"%s\n", (
data->smart_capability & 0x01)?
1064 "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
1065 "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
1066 jref[
"attribute_autosave_enabled"] = !!(
data->smart_capability & 0x01);
1072 if (
data->smart_capability & 0x02)
1073 pout(
"\t\t\t\t\tSupports SMART auto save timer.\n");
1080 jout(
"Error logging capability: (0x%02x)\tError logging %ssupported.\n",
1081 data->errorlog_capability, (capable ?
"" :
"NOT "));
1082 jglb[
"ata_smart_data"][
"capabilities"][
"error_logging_supported"] = capable;
1087 jout(
"Short self-test routine \n");
1089 jout(
"recommended polling time: \t (%4d) minutes.\n",
1090 (
int)
data->short_test_completion_time);
1091 jglb[
"ata_smart_data"][
"self_test"][
"polling_minutes"][
"short"] =
1092 data->short_test_completion_time;
1095 jout(
"recommended polling time: \t Not Supported.\n");
1100 jout(
"Extended self-test routine\n");
1102 jout(
"recommended polling time: \t (%4d) minutes.\n",
1104 jglb[
"ata_smart_data"][
"self_test"][
"polling_minutes"][
"extended"] =
1108 jout(
"recommended polling time: \t Not Supported.\n");
1113 jout(
"Conveyance self-test routine\n");
1115 jout(
"recommended polling time: \t (%4d) minutes.\n",
1116 (
int)
data->conveyance_test_completion_time);
1117 jglb[
"ata_smart_data"][
"self_test"][
"polling_minutes"][
"conveyance"] =
1118 data->conveyance_test_completion_time;
1121 jout(
"recommended polling time: \t Not Supported.\n");
1150 uint8_t normval, uint8_t threshold,
1159 switch (defs[
id].raw_format) {
1162 case RAWFMT_SEC2HOUR: minutes = (rawval / 60) % 60; rawval /= 60*60;
break;
1166 rawval &= 0xffffffffULL;
1169 minutes = (int)(rawval >> 32) / (1000*60);
1172 rawval &= 0xffffffffULL;
1176 if (rawval > 0x00ffffffULL)
1178 jglb[
"power_on_time"][
"hours"] = rawval;
1180 jglb[
"power_on_time"][
"minutes"] = minutes;
1184 if (strcmp(name,
"Power_Cycle_Count"))
1186 switch (defs[
id].raw_format) {
1191 if (rawval > 0x00ffffffULL)
1193 jglb[
"power_cycle_count"] = rawval;
1202 "Reallocated_Sector_C.*|Retired_Block_C.*|"
1203 "(Remain.*_)?Spare_Blocks(_(Avail|Remain).*)?"
1205 if ((
id == 5 ||
id == 17 ||
id >= 100) && spare_regex.
full_match(name)) {
1206 jglb[
"spare_available"][
"current_percent"] = (normval <= 100 ? normval : 100);
1207 if (0 < threshold && threshold < 50)
1208 jglb[
"spare_available"][
"threshold_percent"] = threshold;
1213 "SSD_Life_Left.*|Wear_Leveling.*"
1215 if (
id >= 100 && endurance_regex.
full_match(name)) {
1217 jglb[
"endurance_used"][
"current_percent"] = (normval <= 100 ? 100 - normval : 0);
1228 int onlyfailed,
unsigned char format)
1233 bool needheader =
true;
1240 unsigned char threshold = 0;
1255 jout(
"SMART Attributes Data Structure revision number: %d\n",(
int)
data->revnumber);
1256 jglb[
"ata_smart_attributes"][
"revision"] =
data->revnumber;
1257 jout(
"Vendor Specific SMART Attributes with Thresholds:\n");
1260 jout(
"ID#%s ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n",
1261 (!hexid ?
"" :
" "));
1263 jout(
"ID#%s ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE\n",
1264 (!hexid ?
"" :
" "));
1269 std::string valstr, worstr, threstr;
1274 valstr = (!hexval ?
"---" :
"----");
1279 worstr = (!hexval ?
"---" :
"----");
1281 threstr = (!hexval ?
strprintf(
"%.3d", threshold)
1284 threstr = (!hexval ?
"---" :
"----");
1287 std::string idstr = (!hexid ?
strprintf(
"%3d", attr.
id)
1304 jout(
"%s %-24s0x%04x %-4s %-4s %-4s %-10s%-9s%-12s%s\n",
1305 idstr.c_str(), attrname.c_str(), attr.
flags,
1306 valstr.c_str(), worstr.c_str(), threstr.c_str(),
1314 jout(
"%s %-24s%s %-4s %-4s %-4s %-5s%s\n",
1315 idstr.c_str(), attrname.c_str(), flagstr,
1316 valstr.c_str(), worstr.c_str(), threstr.c_str(),
1325 json::ref jref =
jglb[
"ata_smart_attributes"][
"table"][ji++];
1326 jref[
"id"] = attr.
id;
1327 jref[
"name"] = attrname;
1331 jref[
"worst"] = attr.
worst;
1333 jref[
"thresh"] = threshold;
1340 jreff[
"value"] = attr.
flags;
1341 jreff[
"string"] = flagstr;
1352 jref[
"raw"][
"value"] = rawval;
1353 jref[
"raw"][
"string"] = rawstr;
1356 attr.
current, threshold, rawval);
1360 if (!onlyfailed && brief) {
1361 int n = (!hexid ? 28 : 29);
1362 jout(
"%*s||||||_ K auto-keep\n"
1363 "%*s|||||__ C event count\n"
1364 "%*s||||___ R error rate\n"
1365 "%*s|||____ S speed/performance\n"
1366 "%*s||_____ O updated online\n"
1367 "%*s|______ P prefailure warning\n",
1368 n,
"", n,
"", n,
"", n,
"", n,
"", n,
"");
1379 jglb[
"temperature"][
"current"] = t;
1386 if (!(sctcaps & 0x01))
1389 jout(
"SCT capabilities: \t (0x%04x)\tSCT Status supported.\n", sctcaps);
1390 jref[
"value"] = sctcaps;
1392 jout(
"\t\t\t\t\tSCT Error Recovery Control supported.\n");
1393 jref[
"error_recovery_control_supported"] = !!(sctcaps & 0x08);
1395 jout(
"\t\t\t\t\tSCT Feature Control supported.\n");
1396 jref[
"feature_control_supported"] = !!(sctcaps & 0x10);
1398 jout(
"\t\t\t\t\tSCT Data Table supported.\n");
1399 jref[
"data_table_supported"] = !!(sctcaps & 0x20);
1406 jout(
"General SMART Values:\n");
1421 "General Purpose Logging supported.":
1422 "No General Purpose Logging support.");
1423 jglb[
"ata_smart_data"][
"capabilities"][
"gp_logging_supported"] =
1464 case 0x00:
return "Log Directory";
1465 case 0x01:
return "Summary SMART error log";
1466 case 0x02:
return "Comprehensive SMART error log";
1467 case 0x03:
return "Ext. Comprehensive SMART error log";
1468 case 0x04:
return "Device Statistics log";
1469 case 0x05:
return "Reserved for CFA";
1470 case 0x06:
return "SMART self-test log";
1471 case 0x07:
return "Extended self-test log";
1472 case 0x08:
return "Power Conditions log";
1473 case 0x09:
return "Selective self-test log";
1474 case 0x0a:
return "Device Statistics Notification";
1475 case 0x0b:
return "Reserved for CFA";
1476 case 0x0c:
return "Pending Defects log";
1477 case 0x0d:
return "LPS Mis-alignment log";
1478 case 0x0e:
return "Reserved for ZAC-2";
1479 case 0x0f:
return "Sense Data for Successful NCQ Cmds log";
1480 case 0x10:
return "NCQ Command Error log";
1481 case 0x11:
return "SATA Phy Event Counters log";
1483 case 0x12:
return "SATA NCQ Non-Data log";
1484 case 0x13:
return "SATA NCQ Send and Receive log";
1485 case 0x14:
return "Hybrid Information log";
1486 case 0x15:
return "Rebuild Assist log";
1487 case 0x16:
return "Out Of Band Management Control log";
1488 case 0x17:
return "Reserved for Serial ATA";
1489 case 0x18:
return "Command Duration Limits log";
1490 case 0x19:
return "LBA Status log";
1492 case 0x20:
return "Streaming performance log";
1493 case 0x21:
return "Write stream error log";
1494 case 0x22:
return "Read stream error log";
1495 case 0x23:
return "Delayed sector log";
1496 case 0x24:
return "Current Device Internal Status Data log";
1497 case 0x25:
return "Saved Device Internal Status Data log";
1499 case 0x2f:
return "Sector Configuration log";
1500 case 0x30:
return "IDENTIFY DEVICE data log";
1502 case 0x42:
return "Mutate Configurations log";
1504 case 0x47:
return "Concurrent Positioning Ranges log";
1506 case 0x53:
return "Sense Data log";
1508 case 0x59:
return "Power Consumption Control log";
1510 case 0x61:
return "Capacity/Model Number Mapping log";
1512 case 0xe0:
return "SCT Command/Status";
1513 case 0xe1:
return "SCT Data Transfer";
1515 if (0xa0 <= logaddr && logaddr <= 0xdf)
1516 return "Device vendor specific log";
1517 if (0x80 <= logaddr && logaddr <= 0x9f)
1518 return "Host vendor specific log";
1527 if ( ( logaddr <= 0x08)
1528 || (0x0c <= logaddr && logaddr <= 0x0d)
1529 || (0x0f <= logaddr && logaddr <= 0x14)
1530 || (0x19 == logaddr)
1531 || (0x20 <= logaddr && logaddr <= 0x25)
1532 || (0x2f <= logaddr && logaddr <= 0x30)
1533 || (0x42 == logaddr)
1534 || (0x47 == logaddr)
1535 || (0x53 == logaddr)
1536 || (0x59 == logaddr)
1537 || (0x61 == logaddr))
1540 if ( ( logaddr <= 0x0a)
1541 || (0x15 <= logaddr && logaddr <= 0x16)
1542 || (0x18 == logaddr)
1543 || (0x80 <= logaddr && logaddr <= 0x9f)
1544 || (0xe0 <= logaddr && logaddr <= 0xe1))
1547 if (0xa0 <= logaddr && logaddr <= 0xdf)
1557 memset(logdir, 0,
sizeof(*logdir));
1575 jout(
"General Purpose Log Directory Version %u\n", gplogdir->
logversion);
1576 jref[
"gp_dir_version"] = gplogdir->
logversion;
1579 jout(
"SMART %sLog Directory Version %u%s\n",
1580 (gplogdir ?
" " :
""), smartlogdir->
logversion,
1581 (smartlogdir->
logversion==1 ?
" [multi-sector log support]" :
""));
1582 jref[
"smart_dir_version"] = smartlogdir->
logversion;
1583 jref[
"smart_dir_multi_sector"] = (smartlogdir->
logversion == 1);
1586 jout(
"Address Access R/W Size Description\n");
1588 for (
unsigned i = 0, ji = 0; i <= 0xff; i++) {
1593 if (!(smart_numsect || gp_numsect))
1596 const char * acc;
unsigned size;
1597 if (smart_numsect == gp_numsect) {
1598 acc =
"GPL,SL";
size = gp_numsect;
1600 else if (!smart_numsect) {
1601 acc =
"GPL";
size = gp_numsect;
1603 else if (!gp_numsect) {
1604 acc =
" SL";
size = smart_numsect;
1611 if (acc && ((0x80 <= i && i < 0x9f) || (0xa0 <= i && i < 0xdf))) {
1613 unsigned imax = (i < 0x9f ? 0x9f : 0xdf);
1614 for (
unsigned j = i+1; j <= imax; j++) {
1618 if (!(sn == smart_numsect && gn == gp_numsect))
1628 jout(
"0x%02x-0x%02x %-6s %-3s %5u %s\n", i, i2, acc, rw,
size, name);
1630 jout(
"0x%02x %-6s %-3s %5u %s\n", i, acc, rw,
size, name);
1633 jout(
"0x%02x %-6s %-3s %5u %s\n", i,
"GPL", rw, gp_numsect, name);
1634 jout(
"0x%02x %-6s %-3s %5u %s\n", i,
"SL", rw, smart_numsect, name);
1639 jrefi[
"address"] = i;
1640 jrefi[
"name"] = name;
1641 if (rw[0] ==
'R' && rw[1] && rw[2]) {
1642 jrefi[
"read"] =
true;
1643 jrefi[
"write"] = (rw[2] ==
'W');
1646 jrefi[
"gp_sectors"] = gp_numsect;
1648 jrefi[
"smart_sectors"] = smart_numsect;
1660 unsigned char logaddr,
unsigned page,
1661 unsigned num_pages,
unsigned max_pages)
1663 pout(
"%s Log 0x%02x [%s], Page %u-%u (of %u)\n",
1664 type, logaddr,
GetLogName(logaddr), page, page+num_pages-1, max_pages);
1665 for (
unsigned i = 0; i < num_pages * 512; i += 16) {
1666 const unsigned char * p =
data+i;
1667 pout(
"%07x: %02x %02x %02x %02x %02x %02x %02x %02x "
1668 "%02x %02x %02x %02x %02x %02x %02x %02x ",
1670 p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
1671 p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15]);
1672#define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.')
1673 pout(
"|%c%c%c%c%c%c%c%c"
1674 "%c%c%c%c%c%c%c%c|\n",
1675 P( 0),
P( 1),
P( 2),
P( 3),
P( 4),
P( 5),
P( 6),
P( 7),
1676 P( 8),
P( 9),
P(10),
P(11),
P(12),
P(13),
P(14),
P(15));
1678 if ((i & 0x1ff) == 0x1f0)
1696 { 2,
"List of supported log pages" },
1701 { 2,
"General Statistics" },
1702 { 4,
"Lifetime Power-On Resets" },
1703 { 4,
"Power-on Hours" },
1704 { 6,
"Logical Sectors Written" },
1705 { 6,
"Number of Write Commands" },
1706 { 6,
"Logical Sectors Read" },
1707 { 6,
"Number of Read Commands" },
1708 { 6,
"Date and Time TimeStamp" },
1709 { 4,
"Pending Error Count" },
1710 { 2,
"Workload Utilization" },
1711 { 6,
"Utilization Usage Rate" },
1712 { 7,
"Resource Availability" },
1713 { 1,
"Random Write Resources Used" },
1718 { 2,
"Free-Fall Statistics" },
1719 { 4,
"Number of Free-Fall Events Detected" },
1720 { 4,
"Overlimit Shock Events" },
1725 { 2,
"Rotating Media Statistics" },
1726 { 4,
"Spindle Motor Power-on Hours" },
1727 { 4,
"Head Flying Hours" },
1728 { 4,
"Head Load Events" },
1729 { 4,
"Number of Reallocated Logical Sectors" },
1730 { 4,
"Read Recovery Attempts" },
1731 { 4,
"Number of Mechanical Start Failures" },
1732 { 4,
"Number of Realloc. Candidate Logical Sectors" },
1733 { 4,
"Number of High Priority Unload Events" },
1738 { 2,
"General Errors Statistics" },
1739 { 4,
"Number of Reported Uncorrectable Errors" },
1741 { 4,
"Resets Between Cmd Acceptance and Completion" },
1742 { 4,
"Physical Element Status Changed" },
1747 { 2,
"Temperature Statistics" },
1748 { -1,
"Current Temperature" },
1749 { -1,
"Average Short Term Temperature" },
1750 { -1,
"Average Long Term Temperature" },
1751 { -1,
"Highest Temperature" },
1752 { -1,
"Lowest Temperature" },
1753 { -1,
"Highest Average Short Term Temperature" },
1754 { -1,
"Lowest Average Short Term Temperature" },
1755 { -1,
"Highest Average Long Term Temperature" },
1756 { -1,
"Lowest Average Long Term Temperature" },
1757 { 4,
"Time in Over-Temperature" },
1758 { -1,
"Specified Maximum Operating Temperature" },
1759 { 4,
"Time in Under-Temperature" },
1760 { -1,
"Specified Minimum Operating Temperature" },
1765 { 2,
"Transport Statistics" },
1766 { 4,
"Number of Hardware Resets" },
1767 { 4,
"Number of ASR Events" },
1768 { 4,
"Number of Interface CRC Errors" },
1773 { 2,
"Solid State Device Statistics" },
1774 { 1,
"Percentage Used Endurance Indicator" },
1799 return "Vendor Specific Statistics";
1800 return "Unknown Statistics";
1808 case 0x008:
jglb[
"power_cycle_count"] = val;
break;
1809 case 0x010:
jglb[
"power_on_time"][
"hours"]= val;
break;
1814 case 0x008:
jglb[
"temperature"][
"current"] = val;
break;
1815 case 0x020:
jglb[
"temperature"][
"lifetime_max"] = val;
break;
1816 case 0x028:
jglb[
"temperature"][
"lifetime_min"] = val;
break;
1817 case 0x050:
jglb[
"temperature"][
"lifetime_over_limit_minutes"] = val;
break;
1818 case 0x058:
jglb[
"temperature"][
"op_limit_max"] = val;
break;
1819 case 0x060:
jglb[
"temperature"][
"lifetime_under_limit_minutes"] = val;
break;
1820 case 0x068:
jglb[
"temperature"][
"op_limit_min"] = val;
break;
1825 case 0x008:
jglb[
"endurance_used"][
"current_percent"] = val;
break;
1837 static const char line[] =
" ===== = = === == ";
1839 pout(
"0x%02x%s%s (empty) ==\n", page, line, name);
1842 if (
data[2] != page) {
1843 pout(
"0x%02x%s%s (invalid page 0x%02x in header) ==\n", page, line, name,
data[2]);
1847 int rev =
data[0] | (
data[1] << 8);
1848 jout(
"0x%02x%s%s (rev %d) ==\n", page, line, name, rev);
1849 jref[
"number"] = page;
1850 jref[
"name"] = name;
1851 jref[
"revision"] = rev;
1855 for (
int i = 1, offset = 8; offset < 512-7; i++, offset+=8) {
1857 if (info && !info[i].
size)
1862 if (!(
flags & 0x80))
1866 if (!info && (
data[offset+5] ||
data[offset+6])) {
1867 pout(
"0x%02x 0x%03x - - [Trailing garbage ignored]\n", page, offset);
1872 const char * valname = (info ? info[i].
name :
1873 (page == 0xff) ?
"Vendor Specific"
1877 int size = (info ? info[i].
size : 7);
1880 bool valid = !!(
flags & 0x40);
1881 bool normalized = !!(
flags & 0x20);
1882 bool supports_dsn = !!(
flags & 0x10);
1883 bool monitored_condition_met = !!(
flags & 0x08);
1885 unsigned char reserved_flags = (
flags & 0x07);
1893 val = (
signed char)
data[offset];
1896 for (
int j = 0; j <
size; j++)
1897 val |= (int64_t)
data[offset+j] << (j*8);
1899 snprintf(valstr,
sizeof(valstr),
"%" PRId64, val);
1903 valstr[0] =
'-'; valstr[1] = 0;
1907 (valid ?
'V' :
'-'),
1908 (normalized ?
'N' :
'-'),
1909 (supports_dsn ?
'D' :
'-'),
1910 (monitored_condition_met ?
'C' :
'-'),
1911 (reserved_flags ?
'+' :
' '),
1915 jout(
"0x%02x 0x%03x %d %15s %s %s\n",
1916 page, offset, abs(
size), valstr, flagstr+1, valname);
1922 jrefi[
"offset"] = offset;
1923 jrefi[
"name"] = valname;
1924 jrefi[
"size"] = abs(
size);
1926 jrefi[
"value"] = val;
1929 jreff[
"value"] =
flags;
1930 jreff[
"string"] = flagstr;
1931 jreff[
"valid"] = valid;
1932 jreff[
"normalized"] = normalized;
1933 jreff[
"supports_dsn"] = supports_dsn;
1934 jreff[
"monitored_condition_met"] = monitored_condition_met;
1936 jreff[
"other"] = reserved_flags;
1944 const std::vector<int> & single_pages,
bool all_pages,
bool ssd_page,
1948 unsigned char page_0[512] = {0, };
1956 jerr(
"Read Device Statistics page 0x00 failed\n\n");
1960 unsigned char nentries = page_0[8];
1961 if (!(page_0[2] == 0 && nentries > 0)) {
1962 jerr(
"Device Statistics page 0x00 is invalid (page=0x%02x, nentries=%d)\n\n", page_0[2], nentries);
1967 std::vector<int> pages;
1971 for (i = 0; i < nentries; i++) {
1972 int page = page_0[8+1+i];
1974 pages.push_back(page);
1979 bool print_page_0 =
false;
1980 for (i = 0; i < single_pages.size() || ssd_page; i++) {
1981 int page = (i < single_pages.size() ? single_pages[i] : 0x07);
1983 print_page_0 =
true;
1984 else if (page >= (
int)nsectors)
1985 pout(
"Device Statistics Log has only 0x%02x pages\n", nsectors);
1987 pages.push_back(page);
1996 pout(
"Device Statistics (%s Log 0x04) supported pages\n",
1997 use_gplog ?
"GP" :
"SMART");
1998 jout(
"Page Description\n");
1999 for (i = 0; i < nentries; i++) {
2000 int page = page_0[8+1+i];
2002 jout(
"0x%02x %s\n", page, name);
2003 jref[
"supported_pages"][i][
"number"] = page;
2004 jref[
"supported_pages"][i][
"name"] = name;
2010 if (!pages.empty()) {
2011 pout(
"Device Statistics (%s Log 0x04)\n",
2012 use_gplog ?
"GP" :
"SMART");
2013 jout(
"Page Offset Size Value Flags Description\n");
2017 for (i = 0; i < pages.size(); i++) {
2018 int page = pages[i];
2019 if (max_page < page && page < 0xff)
2026 jerr(
"Read Device Statistics pages 0x00-0x%02x failed\n\n", max_page);
2031 for (i = 0; i < pages.size(); i++) {
2032 int page = pages[i];
2035 jerr(
"Read Device Statistics page 0x%02x failed\n\n", page);
2039 else if (page > max_page)
2042 int offset = (use_gplog ? 0 : page * 512);
2046 jout(
"%32s|||_ C monitored condition met\n",
"");
2047 jout(
"%32s||__ D supports DSN\n",
"");
2048 jout(
"%32s|___ N normalized value\n\n",
"");
2061 unsigned max_entries)
2064 unsigned char page_buf[512] = {0, };
2066 pout(
"Read Pending Defects log page 0x00 failed\n\n");
2070 jout(
"Pending Defects log (GP Log 0x0c)\n");
2073 jref[
"size"] = nsectors * 32 - 1;
2074 jref[
"count"] = nentries;
2076 jout(
"No Defects Logged\n\n");
2081 jout(
"Index LBA Hours\n");
2082 for (
unsigned i = 0, pi = 1, page = 0; i < nentries && i < max_entries; i++, pi++) {
2085 if (++page >= nsectors) {
2086 pout(
"Pending Defects count %u exceeds log size (#pages=%u)\n\n",
2087 nentries, nsectors);
2091 pout(
"Read Pending Defects log page 0x%02x failed\n\n", page);
2097 const unsigned char *
entry = page_buf + 16 * pi;
2100 if (hours != 0xffffffffU)
2101 snprintf(hourstr,
sizeof(hourstr),
"%u", hours);
2103 hourstr[0] =
'-', hourstr[1] = 0;
2105 jout(
"%5u %18" PRIu64
" %8s\n", i, lba, hourstr);
2109 if (hours != 0xffffffffU)
2110 jrefi[
"power_on_hours"] = hours;
2113 if (nentries > max_entries)
2114 pout(
"... (%u entries not shown)\n", nentries - max_entries);
2127 jout(
"SATA Phy Event Counters (GP Log 0x11)\n");
2129 pout(
"[Reserved: 0x%02x 0x%02x 0x%02x 0x%02x]\n",
2131 jout(
"ID Size Value Description\n");
2133 for (
unsigned i = 4, ji = 0; ; ) {
2135 unsigned id =
data[i] | (
data[i+1] << 8);
2136 unsigned size = ((
id >> 12) & 0x7) << 1;
2145 pout(
"0x%04x %u: Invalid entry\n",
id,
size);
2150 uint64_t val = 0, max_val = 0;
2151 for (
unsigned j = 0; j <
size; j+=2) {
2152 val |= (uint64_t)(
data[i+j] | (
data[i+j+1] << 8)) << (j*8);
2153 max_val |= (uint64_t)0xffffU << (j*8);
2160 case 0x001: name =
"Command failed due to ICRC error";
break;
2161 case 0x002: name =
"R_ERR response for data FIS";
break;
2162 case 0x003: name =
"R_ERR response for device-to-host data FIS";
break;
2163 case 0x004: name =
"R_ERR response for host-to-device data FIS";
break;
2164 case 0x005: name =
"R_ERR response for non-data FIS";
break;
2165 case 0x006: name =
"R_ERR response for device-to-host non-data FIS";
break;
2166 case 0x007: name =
"R_ERR response for host-to-device non-data FIS";
break;
2167 case 0x008: name =
"Device-to-host non-data FIS retries";
break;
2168 case 0x009: name =
"Transition from drive PhyRdy to drive PhyNRdy";
break;
2169 case 0x00A: name =
"Device-to-host register FISes sent due to a COMRESET";
break;
2170 case 0x00B: name =
"CRC errors within host-to-device FIS";
break;
2171 case 0x00D: name =
"Non-CRC errors within host-to-device FIS";
break;
2172 case 0x00F: name =
"R_ERR response for host-to-device data FIS, CRC";
break;
2173 case 0x010: name =
"R_ERR response for host-to-device data FIS, non-CRC";
break;
2174 case 0x012: name =
"R_ERR response for host-to-device non-data FIS, CRC";
break;
2175 case 0x013: name =
"R_ERR response for host-to-device non-data FIS, non-CRC";
break;
2176 default: name = ((
id & 0x8000) ?
"Vendor specific" :
"Unknown");
break;
2180 jout(
"0x%04x %u %12" PRIu64
"%c %s\n",
id,
size, val,
2181 (val == max_val ?
'+' :
' '), name);
2183 json::ref jref =
jglb[
"sata_phy_event_counters"][
"table"][ji++];
2185 jref[
"name"] = name;
2186 jref[
"size"] =
size;
2187 jref[
"value"] = val;
2188 jref[
"overflow"] = (val == max_val);
2191 jout(
"All counters reset\n");
2193 jglb[
"sata_phy_event_counters"][
"reset"] = reset;
2199 unsigned days = msec / 86400000U;
2200 msec -= days * 86400000U;
2201 unsigned hours = msec / 3600000U;
2202 msec -= hours * 3600000U;
2203 unsigned min = msec / 60000U;
2204 msec -= min * 60000U;
2205 unsigned sec = msec / 1000U;
2206 msec -= sec * 1000U;
2211 str +=
strprintf(
"%02u:%02u:%02u.%03u", hours, min, sec, msec);
2220 case 0x0:
return "in an unknown state";
2221 case 0x1:
return "sleeping";
2222 case 0x2:
return "in standby mode";
2223 case 0x3:
return "active or idle";
2224 case 0x4:
return "doing SMART Offline or Self-test";
2226 return (state < 0xb ?
"in a reserved state"
2227 :
"in a vendor specific state");
2236 jout(
"SMART Error Log Version: %d\n", (
int)
data->revnumber);
2237 jref[
"revision"] =
data->revnumber;
2241 if ( !( !
data->ata_error_count == !
data->error_log_pointer
2242 && !((
data->ata_error_count -
data->error_log_pointer) % 5))
2244 pout(
"Warning: ATA error count %d inconsistent with error log index %d\n",
2245 data->ata_error_count,
data->error_log_pointer);
2248 if (!(
data->ata_error_count &&
data->error_log_pointer)) {
2249 jout(
"No Errors Logged\n\n");
2255 if (
data->error_log_pointer>5){
2256 pout(
"Invalid Error Log index = 0x%02x (valid range is from 1 to 5)\n",
2257 data->error_log_pointer);
2258 pout(
"ATA Error Count: %d (possibly also invalid)\n\n",
data->ata_error_count);
2263 if (
data->ata_error_count<=5)
2264 jout(
"ATA Error Count: %d\n", (
int)
data->ata_error_count);
2266 jout(
"ATA Error Count: %d (device log contains only the most recent five errors)\n",
2267 (
int)
data->ata_error_count);
2268 jref[
"count"] =
data->ata_error_count;
2269 jref[
"logged_count"] = (
data->ata_error_count <= 5 ?
data->ata_error_count : 5);
2272 jout(
"\tCR = Command Register [HEX]\n"
2273 "\tFR = Features Register [HEX]\n"
2274 "\tSC = Sector Count Register [HEX]\n"
2275 "\tSN = Sector Number Register [HEX]\n"
2276 "\tCL = Cylinder Low Register [HEX]\n"
2277 "\tCH = Cylinder High Register [HEX]\n"
2278 "\tDH = Device/Head Register [HEX]\n"
2279 "\tDC = Device Command Register [HEX]\n"
2280 "\tER = Error register [HEX]\n"
2281 "\tST = Status register [HEX]\n"
2282 "Powered_Up_Time is measured from power on, and printed as\n"
2283 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2284 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2287 for (
int k = 4, ji = 0; k >= 0; k--) {
2290 int i = (
data->error_log_pointer + k) % 5;
2295 if (
nonempty(elog,
sizeof(*elog))){
2302 jout(
"Error %d occurred at disk power-on lifetime: %d hours (%d days + %d hours)\n",
2307 jrefi[
"error_number"] =
data->ata_error_count + k - 4;
2308 jrefi[
"lifetime_hours"] = summary->
timestamp;
2310 jout(
" When the command that caused the error occurred, the device was %s.\n\n", msgstate);
2311 jout(
" After command completion occurred, registers were:\n"
2312 " ER ST SC SN CL CH DH\n"
2313 " -- -- -- -- -- -- --\n"
2314 " %02x %02x %02x %02x %02x %02x %02x",
2324 json::ref jrefir = jrefi[
"completion_registers"];
2326 jrefir[
"status"] = summary->
status;
2337 if (!st_er_desc.empty()) {
2338 jout(
" %s", st_er_desc.c_str());
2339 jrefi[
"error_description"] = st_er_desc;
2342 jout(
" Commands leading to the command that caused the error were:\n"
2343 " CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n"
2344 " -- -- -- -- -- -- -- -- ---------------- --------------------\n");
2345 for (
int j = 4, jj = 0; j >= 0; j--) {
2349 if (
nonempty(thiscommand,
sizeof(*thiscommand))) {
2351 jout(
" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2363 json::ref jrefic = jrefi[
"previous_commands"][jj++];
2364 json::ref jreficr = jrefic[
"registers"];
2365 jreficr[
"command"] = thiscommand->
commandreg;
2373 jrefic[
"powerup_milliseconds"] = thiscommand->
timestamp;
2374 jrefic[
"command_name"] = atacmd;
2384 return data->ata_error_count;
2391 unsigned nsectors,
unsigned max_errors)
2394 jout(
"SMART Extended Comprehensive Error Log Version: %u (%u sectors)\n",
2396 jref[
"revision"] = log->
version;
2397 jref[
"sectors"] = nsectors;
2400 jout(
"No Errors Logged\n\n");
2407 unsigned nentries = nsectors * 4;
2409 if (!(1 <= erridx && erridx <= nentries)){
2414 pout(
"Invalid Error Log index = 0x%04x (reserved = 0x%02x)\n", erridx, log->
reserved1);
2418 pout(
"Invalid Error Log index = 0x%04x, trying reserved byte (0x%02x) instead\n", erridx, log->
reserved1);
2429 if (errcnt <= nentries)
2433 jout(
"Device Error Count: %u (device log contains only the most recent %u errors)\n",
2437 jref[
"logged_count"] = errcnt;
2439 if (max_errors < errcnt)
2440 errcnt = max_errors;
2443 jout(
"\tCR = Command Register\n"
2444 "\tFEATR = Features Register\n"
2445 "\tCOUNT = Count (was: Sector Count) Register\n"
2446 "\tLBA_48 = Upper bytes of LBA High/Mid/Low Registers ] ATA-8\n"
2447 "\tLH = LBA High (was: Cylinder High) Register ] LBA\n"
2448 "\tLM = LBA Mid (was: Cylinder Low) Register ] Register\n"
2449 "\tLL = LBA Low (was: Sector Number) Register ]\n"
2450 "\tDV = Device (was: Device/Head) Register\n"
2451 "\tDC = Device Control Register\n"
2452 "\tER = Error register\n"
2453 "\tST = Status register\n"
2454 "Powered_Up_Time is measured from power on, and printed as\n"
2455 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2456 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2460 unsigned log_buf_page = ~0;
2464 i < errcnt; i++, errnum--, erridx = (erridx > 0 ? erridx - 1 : nentries - 1)) {
2468 unsigned page = erridx / 4;
2472 if (page != log_buf_page) {
2473 memset(&log_buf, 0,
sizeof(log_buf));
2476 log_buf_page = page;
2484 jrefi[
"error_number"] = errnum;
2485 jrefi[
"log_index"] = erridx;
2489 jout(
"Error %u [%u] log entry is empty\n", errnum, erridx);
2496 jout(
"Error %u [%u] occurred at disk power-on lifetime: %u hours (%u days + %u hours)\n",
2499 jrefi[
"lifetime_hours"] = err.
timestamp;
2502 jout(
" When the command that caused the error occurred, the device was %s.\n\n", msgstate);
2503 jrefi[
"device_state"][
"value"] = err.
state;
2504 jrefi[
"device_state"][
"string"] = msgstate;
2507 jout(
" After command completion occurred, registers were:\n"
2508 " ER -- ST COUNT LBA_48 LH LM LL DV DC\n"
2509 " -- -- -- == -- == == == -- -- -- -- --\n"
2510 " %02x -- %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
2525 json::ref jrefir = jrefi[
"completion_registers"];
2542 if (!st_er_desc.empty()) {
2543 jout(
" %s", st_er_desc.c_str());
2544 jrefi[
"error_description"] = st_er_desc;
2549 jout(
" Commands leading to the command that caused the error were:\n"
2550 " CR FEATR COUNT LBA_48 LH LM LL DV DC Powered_Up_Time Command/Feature_Name\n"
2551 " -- == -- == -- == == == -- -- -- -- -- --------------- --------------------\n");
2552 for (
int ci = 4, cji = 0; ci >= 0; ci--) {
2561 jout(
" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2562 cmd.command_register,
2563 cmd.features_register_hi,
2564 cmd.features_register,
2565 cmd.count_register_hi,
2567 cmd.lba_high_register_hi,
2568 cmd.lba_mid_register_hi,
2569 cmd.lba_low_register_hi,
2570 cmd.lba_high_register,
2571 cmd.lba_mid_register,
2572 cmd.lba_low_register,
2573 cmd.device_register,
2574 cmd.device_control_register,
2578 json::ref jrefic = jrefi[
"previous_commands"][cji++];
2579 json::ref jreficr = jrefic[
"registers"];
2580 jreficr[
"command"] =
cmd.command_register;
2581 jreficr[
"features"] = (
cmd.features_register_hi << 8) |
cmd.features_register;
2582 jreficr[
"count"] = (
cmd.count_register_hi << 8) |
cmd.count_register;
2583 jreficr[
"lba"] = ((uint64_t)
cmd.lba_high_register_hi << 40)
2584 | ((uint64_t)
cmd.lba_mid_register_hi << 32)
2585 | ((uint64_t)
cmd.lba_low_register_hi << 24)
2586 | ((unsigned)
cmd.lba_high_register << 16)
2587 | ((unsigned)
cmd.lba_mid_register << 8)
2588 | ((unsigned)
cmd.lba_low_register );
2589 jreficr[
"device"] =
cmd.device_register;
2590 jreficr[
"device_control"] =
cmd.device_control_register;
2591 jrefic[
"powerup_milliseconds"] =
cmd.timestamp;
2592 jrefic[
"command_name"] = atacmd;
2610 unsigned testnum,
unsigned char test_type,
2611 unsigned char test_status,
2612 unsigned short timestamp,
2613 uint64_t failing_lba,
2614 bool print_error_only,
bool & print_header)
2618 switch (test_status >> 4) {
2620 if ((test_type & 0x7f) == 0x02)
2630 if (retval >= 0 && print_error_only)
2633 std::string msgtest;
2634 switch (test_type) {
2635 case 0x00: msgtest =
"Offline";
break;
2636 case 0x01: msgtest =
"Short offline";
break;
2637 case 0x02: msgtest =
"Extended offline";
break;
2638 case 0x03: msgtest =
"Conveyance offline";
break;
2639 case 0x04: msgtest =
"Selective offline";
break;
2640 case 0x7f: msgtest =
"Abort offline test";
break;
2641 case 0x81: msgtest =
"Short captive";
break;
2642 case 0x82: msgtest =
"Extended captive";
break;
2643 case 0x83: msgtest =
"Conveyance captive";
break;
2644 case 0x84: msgtest =
"Selective captive";
break;
2646 if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
2647 msgtest =
strprintf(
"Vendor (0x%02x)", test_type);
2649 msgtest =
strprintf(
"Reserved (0x%02x)", test_type);
2652 std::string msgstat;
2653 switch (test_status >> 4) {
2654 case 0x0: msgstat =
"Completed without error";
break;
2655 case 0x1: msgstat =
"Aborted by host";
break;
2656 case 0x2: msgstat =
"Interrupted (host reset)";
break;
2657 case 0x3: msgstat =
"Fatal or unknown error";
break;
2658 case 0x4: msgstat =
"Completed: unknown failure";
break;
2659 case 0x5: msgstat =
"Completed: electrical failure";
break;
2660 case 0x6: msgstat =
"Completed: servo/seek failure";
break;
2661 case 0x7: msgstat =
"Completed: read failure";
break;
2662 case 0x8: msgstat =
"Completed: handling damage??";
break;
2663 case 0xf: msgstat =
"Self-test routine in progress";
break;
2664 default: msgstat =
strprintf(
"Unknown status (0x%x)", test_status >> 4);
2669 print_header =
false;
2670 jout(
"Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n");
2674 if (retval < 0 && failing_lba < 0xffffffffffffULL)
2675 snprintf(msglba,
sizeof(msglba),
"%" PRIu64, failing_lba);
2677 msglba[0] =
'-'; msglba[1] = 0;
2680 jout(
"#%2u %-19s %-29s %1d0%% %8u %s\n", testnum,
2681 msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
2683 jref[
"type"][
"value"] = test_type;
2684 jref[
"type"][
"string"] = msgtest;
2686 jref[
"status"][
"value"] = test_status;
2687 jref[
"status"][
"string"] = msgstat;
2688 if (test_status & 0x0f)
2689 jref[
"status"][
"remaining_percent"] = (test_status & 0x0f) * 10;
2690 switch (test_status >> 4) {
2691 case 0x1:
case 0x2:
case 0x3:
break;
2692 default: jref[
"status"][
"passed"] = (retval >= 0);
2695 jref[
"lifetime_hours"] = timestamp;
2697 if (retval < 0 && failing_lba < 0xffffffffffffULL)
2698 jref[
"lba"] = failing_lba;
2707 json::ref jref =
jglb[
"ata_smart_self_test_log"][
"standard"];
2710 jout(
"SMART Self-test log structure revision number %d\n", log->
revnumber);
2713 pout(
"Warning: ATA Specification requires self-test log structure revision number = 1\n");
2716 jout(
"No self-tests have been logged. [To run self-tests, use: smartctl -t]\n");
2721 bool noheaderprinted =
true;
2722 int errcnt = 0, igncnt = 0;
2723 int testnum = 1, ext_ok_testnum = -1;
2726 for (
int i = 20, ji = 0; i >= 0; i--) {
2735 uint64_t lba48 = (
entry.lbafirstfailure < 0xffffffff ?
2736 entry.lbafirstfailure : 0xffffffffffffULL);
2740 testnum,
entry.selftestnumber,
entry.selfteststatus,
2741 entry.timestamp, lba48, !allentries, noheaderprinted);
2745 if (ext_ok_testnum < 0)
2751 else if (state > 0 && ext_ok_testnum < 0) {
2753 ext_ok_testnum = testnum;
2759 jout(
"%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2760 igncnt, igncnt+errcnt, ext_ok_testnum);
2761 jref[
"count"] = testnum - 1;
2762 jref[
"error_count_total"] = igncnt + errcnt;
2763 jref[
"error_count_outdated"] = igncnt;
2765 if (!allentries && !noheaderprinted)
2773 unsigned nsectors,
unsigned max_entries)
2775 json::ref jref =
jglb[
"ata_smart_self_test_log"][
"extended"];
2777 jout(
"SMART Extended Self-test Log Version: %u (%u sectors)\n",
2779 jref[
"revision"] = log->
version;
2780 jref[
"sectors"] = nsectors;
2783 jout(
"No self-tests have been logged. [To run self-tests, use: smartctl -t]\n\n");
2789 unsigned nentries = nsectors * 19;
2791 if (logidx > nentries) {
2792 pout(
"Invalid Self-test Log index = 0x%04x (reserved = 0x%02x)\n", logidx, log->
reserved1);
2800 bool print_header =
true;
2801 int errcnt = 0, igncnt = 0;
2802 int ext_ok_testnum = -1;
2803 unsigned testnum = 1;
2806 for (
unsigned i = 0, ji = 0; i < nentries && testnum <= max_entries;
2807 i++, logidx = (logidx > 0 ? logidx - 1 : nentries - 1)) {
2816 const unsigned char *
b =
entry.failing_lba;
2817 uint64_t lba48 =
b[0]
2820 | ((uint64_t)
b[3] << 24)
2821 | ((uint64_t)
b[4] << 32)
2822 | ((uint64_t)
b[5] << 40);
2826 testnum,
entry.self_test_type,
2827 entry.self_test_status,
entry.timestamp, lba48,
2828 false , print_header);
2832 if (ext_ok_testnum < 0)
2838 else if (state > 0 && ext_ok_testnum < 0) {
2840 ext_ok_testnum = testnum;
2846 jout(
"%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2847 igncnt, igncnt+errcnt, ext_ok_testnum);
2848 jref[
"count"] = testnum - 1;
2849 jref[
"error_count_total"] = igncnt + errcnt;
2850 jref[
"error_count_outdated"] = igncnt;
2861 jout(
"SMART Selective self-test log data structure revision number %d\n", log->
logversion);
2864 pout(
"Note: revision number not 1 implies that no selective self-test has ever been run\n");
2868 case 0:msg=
"Completed";
2870 case 1:msg=
"Aborted_by_host";
2872 case 2:msg=
"Interrupted";
2874 case 3:msg=
"Fatal_error";
2876 case 4:msg=
"Completed_unknown_failure";
2878 case 5:msg=
"Completed_electrical_failure";
2880 case 6:msg=
"Completed_servo/seek_failure";
2882 case 7:msg=
"Completed_read_failure";
2884 case 8:msg=
"Completed_handling_damage??";
2886 case 15:msg=
"Self_test_in_progress";
2888 default:msg=
"Unknown_status ";
2894 uint64_t maxl = 0, maxr = 0;
2896 uint64_t currentend = current + 0xffff;
2901 for (
int i = 0; i < 5; i++) {
2903 uint64_t end =log->
span[i].
end;
2915 if ((field1=snprintf(tmp,64,
"%" PRIu64, maxl))<7)
2917 if ((field2=snprintf(tmp,64,
"%" PRIu64, maxr))<7)
2921 jout(
" SPAN %*s %*s CURRENT_TEST_STATUS\n", field1,
"MIN_LBA", field2,
"MAX_LBA");
2923 for (
int i = 0; i < 5; i++) {
2925 uint64_t end=log->
span[i].
end;
2930 jout(
" %d %*" PRIu64
" %*" PRIu64
" %s [%01d0%% left] (%" PRIu64
"-%" PRIu64
")\n",
2931 i + 1, field1, start, field2, end, msg,
2935 jout(
" %d %*" PRIu64
" %*" PRIu64
" Not_testing\n",
2936 i + 1, field1, start, field2, end);
2939 jrefi[
"lba_min"] = start;
2940 jrefi[
"lba_max"] = end;
2942 jrefi[
"status"][
"string"] = (active ? msg :
"Not_testing");
2945 jrefi[
"current_lba_min"] = current;
2946 jrefi[
"current_lba_max"] = currentend;
2954 jout(
"%5d %*" PRIu64
" %*" PRIu64
" Read_scanning %s\n",
2955 log->
currentspan, field1, current, field2, currentend, ost);
2956 json::ref jrefc = jref[
"current_read_scan"];
2957 jrefc[
"lba_min"] = current;
2958 jrefc[
"lba_max"] = currentend;
2960 jrefc[
"status"][
"string"] = ost;
2974 jout(
"Selective self-test flags (0x%x):\n", (
unsigned)log->
flags);
2976 jreff[
"value"] = log->
flags;
2980 jout(
" Currently read-scanning the remainder of the disk.\n");
2982 jout(
" Read-scan of remainder of disk interrupted; will resume %d min after power-up.\n",
2985 jout(
" After scanning selected spans, read-scan remainder of disk.\n");
2990 jout(
" After scanning selected spans, do NOT read-scan remainder of disk.\n");
2993 jout(
"If Selective self-test is pending on power-up, resume after %d minute delay.\n",
2995 jref[
"power_up_scan_resume_minutes"] = log->
pendingtime;
2999static const char *
sct_ptemp(
signed char x,
char (& buf)[20])
3003 snprintf(buf,
sizeof(buf),
"%2d", x);
3011 jglb[
"temperature"][name] = x;
3012 jref[
"temperature"][name] = x;
3026 memset(buf,
'*', x);
3032 buf[0] =
'-'; buf[1] = 0;
3040 case 0:
return "Active";
3041 case 1:
return "Stand-by";
3042 case 2:
return "Sleep";
3043 case 3:
return "DST executing in background";
3044 case 4:
return "SMART Off-line Data Collection executing in background";
3045 case 5:
return "SCT command executing in background";
3046 default:
return "Unknown";
3066 jref[
"device_state"][
"string"] = statestr;
3080 char buf1[20], buf2[20];
3081 jout(
"Current Temperature: %s Celsius\n",
3084 jout(
"Power Cycle Min/Max Temperature: %s/%s Celsius\n",
3090 jout(
"Lifetime Min/Max Temperature: %s/%s Celsius\n",
3100 jout(
"Specified Max Operating Temperature: %3d Celsius\n", sts->
max_op_limit);
3103 jout(
"Under/Over Temperature Limit Count: %2u/%u\n",
3112 (passed == 0 ?
"FAILED" : passed > 0 ?
"PASSED" :
"Reserved"));
3114 jref[
"smart_status"][
"passed"] = !!passed;
3115 jglb[
"smart_status"][
"passed"] = !!passed;
3118 jref[
"smart_status"][
"reserved_value"] = sts->
smart_status;
3122 pout(
"Minimum supported ERC Time Limit: %d (%0.1f seconds)\n",
3126 jout(
"Vendor specific:\n");
3140 char buf1[20], buf2[20], buf3[64];
3144 jout(
"Temperature Sampling Period: %u minute%s\n",
3147 jout(
"Temperature Logging Interval: %u minute%s\n",
3149 jref[
"logging_interval_minutes"] = tmh->
interval;
3151 jout(
"Min/Max recommended Temperature: %s/%s Celsius\n",
3155 jout(
"Min/Max Temperature Limit: %s/%s Celsius\n",
3165 pout(
"Temperature History is empty\n");
3167 pout(
"Invalid Temperature History Size or Index\n");
3172 jout(
"\nIndex Estimated Time Temperature Celsius\n");
3175 time_t t = time(0) - (time_t)(tmh->
cb_size-1) * interval * 60;
3176 t -= t % (interval * 60);
3177 while (n < tmh->cb_size) {
3179 unsigned n1 = n, n2 = n+1, i2 = (i+1) % tmh->
cb_size;
3180 while (n2 < tmh->cb_size && tmh->
cb[i2] == tmh->
cb[i]) {
3181 n2++; i2 = (i2+1) % tmh->
cb_size;
3185 if (n == n1 || n == n2-1 || n2 <= n1+3) {
3189 strftime(date,
sizeof(date),
"%Y-%m-%d %H:%M",
time_to_tm_local(&tmbuf, t));
3190 jout(
" %3u %s %s %s\n", i, date,
3193 else if (n == n1+1) {
3194 jout(
" ... ..(%3u skipped). .. %s\n",
3197 if (tmh->
cb[i] != -128)
3198 jref[
"table"][n] = tmh->
cb[i];
3199 t += interval * 60; i = (i+1) % tmh->
cb_size; n++;
3210 const char* power_on_str = (power_on ?
"Power-on " :
"");
3212 jout(
"SCT Error Recovery Control%s:%s\n", (set ?
" set to" :
""), (mfg_default ?
" default values." :
""));
3215 jref[
"read"][
"enabled"] = !!read_timer;
3217 jout(
" %sRead: Disabled\n", power_on_str);
3219 jout(
" %sRead: %6d (%0.1f seconds)\n", power_on_str, read_timer, read_timer/10.0);
3220 jref[
"read"][
"deciseconds"] = read_timer;
3223 jref[
"write"][
"enabled"] = !!write_timer;
3225 jout(
" %sWrite: Disabled\n", power_on_str);
3227 jout(
" %sWrite: %6d (%0.1f seconds)\n", power_on_str, write_timer, write_timer/10.0);
3228 jref[
"write"][
"deciseconds"] = write_timer;
3239 s =
"vendor specific";
3240 else if (level < 128)
3241 s =
"unknown/retired";
3242 else if (level == 128)
3244 else if (level < 254)
3246 else if (level == 254)
3247 s =
"maximum performance";
3251 if (recommended >= 0)
3252 jout(
"%s%d (%s), recommended: %d\n", msg, level,
s, recommended);
3254 jout(
"%s%d (%s)\n", msg, level,
s);
3257 jref[
"enabled"] =
true;
3258 jref[
"level"] = level;
3260 if (recommended >= 0)
3261 jref[
"recommended_level"] = recommended;
3268 if (!(1 <= level && level <= 254))
3270 else if (level == 1)
3271 s =
"minimum power consumption with standby";
3272 else if (level < 128)
3273 s =
"intermediate level with standby";
3274 else if (level == 128)
3275 s =
"minimum power consumption without standby";
3276 else if (level < 254)
3277 s =
"intermediate level without standby";
3279 s =
"maximum performance";
3281 jout(
"%s%d (%s)\n", msg, level,
s);
3284 jref[
"enabled"] =
true;
3285 jref[
"level"] = level;
3287 if (1 <= level && level <= 254) {
3288 jref[
"max_performance"] = (level == 254);
3289 jref[
"min_power"] = (level == 1 || level == 128);
3290 jref[
"with_standby"] = (level < 128);
3297 if (!(state & 0x0001)) {
3298 pout(
"%sUnavailable\n", msg);
3302 const char * s1, * s2 =
"", * s3 =
"", * s4 =
"";
3303 bool enabled =
false, locked =
false;
3304 if (!(state & 0x0002)) {
3306 if (!(state & 0x0008))
3307 s2 =
"NOT FROZEN [SEC1]";
3309 s2 =
"frozen [SEC2]";
3313 s1 =
"ENABLED, PW level ";
3314 if (!(state & 0x0100))
3319 if (!(state & 0x0004)) {
3320 s3 =
", not locked, ";
3321 if (!(state & 0x0008))
3322 s4 =
"not frozen [SEC5]";
3324 s4 =
"frozen [SEC6]";
3328 s3 =
", **LOCKED** [SEC4]";
3330 s4 =
", PW ATTEMPTS EXCEEDED";
3337 if (0x0000 < master_password_id && master_password_id < 0xfffe)
3338 snprintf(s5,
sizeof(s5),
", Master PW ID: 0x%04x", master_password_id);
3340 jout(
"%s%s%s%s%s%s\n", msg, s1, s2, s3, s4, s5);
3343 jref[
"state"] = state;
3344 jref[
"string"] =
strprintf(
"%s%s%s%s", s1, s2, s3, s4);
3345 jref[
"enabled"] = enabled;
3346 if (!enabled || !locked)
3347 jref[
"frozen"] = !!(state & 0x0008);
3349 jref[
"pw_level_max"] = !!(state & 0x0100);
3350 jref[
"locked"] = locked;
3352 jref[
"pw_attempts_exceeded"] = !!(state & 0x0010);
3354 jref[
"master_password_id"] = master_password_id;
3359 const char * s1 = 0;
3360 int hours = 0, minutes = 0 , seconds = 0;
3365 else if (timer <= 240)
3366 seconds = timer * 5, minutes = seconds / 60, seconds %= 60;
3367 else if (timer <= 251)
3368 minutes = (timer - 240) * 30, hours = minutes / 60, minutes %= 60;
3369 else if (timer == 252)
3371 else if (timer == 253)
3372 s1 =
"between 8 hours and 12 hours";
3373 else if (timer == 255)
3374 minutes = 21, seconds = 15;
3378 const char * s2 =
"", * s3 =
"";
3380 s2 =
" or vendor-specific";
3381 if (timer > 0 && (drive.
words047_079[50-47] & 0xc001) == 0x4001)
3382 s3 =
", a vendor-specific minimum applies";
3385 pout(
"%s%d (%s%s%s)\n", msg, timer, s1, s2, s3);
3387 pout(
"%s%d (%02d:%02d:%02d%s%s)\n", msg, timer, hours, minutes, seconds, s2, s3);
3394 const char * powername = 0;
3395 bool powerchg =
false;
3397 unsigned char powerlimit = 0xff;
3400 switch (powermode) {
3407 jinf(
"CHECK POWER MODE not implemented, ignoring -n option\n");
break;
3409 powername =
"SLEEP"; powerlimit = 2;
3414 powername =
"STANDBY"; powerlimit = 3;
break;
3416 powername =
"STANDBY_Y"; powerlimit = 3;
break;
3418 powername =
"IDLE"; powerlimit = 4;
break;
3420 powername =
"IDLE_A"; powerlimit = 4;
break;
3422 powername =
"IDLE_B"; powerlimit = 4;
break;
3424 powername =
"IDLE_C"; powerlimit = 4;
break;
3427 powername =
"ACTIVE_NV_DOWN";
break;
3429 powername =
"ACTIVE_NV_UP" ;
break;
3431 powername =
"ACTIVE or IDLE";
break;
3435 jinf(
"CHECK POWER MODE returned unknown value 0x%02x, exit(%d)\n", powermode,
3439 jinf(
"CHECK POWER MODE returned unknown value 0x%02x, ignoring -n option\n", powermode);
3443 jglb[
"power_mode"] += {
3444 {
"ata_value", powermode },
3445 {
"name", powername }
3448 jinf(
"Device is in %s mode, exit(%d)\n", powername, options.
powerexit);
3451 powerchg = (powermode != 0xff);
3456 bool need_smart_val = (
3471 bool need_smart_enabled = (
3478 bool need_smart_support = (
3485 bool need_smart_logdir = (
3492 bool need_gp_logdir = (
3506 need_gp_logdir =
true;
3508 need_smart_logdir =
true;
3512 bool need_sct_support = (
3526 bool not_part_of_a_option = (
3539 || need_smart_support
3540 || not_part_of_a_option)) {
3542 pout(
"Device is in %s mode\n", powername);
3544 pout(
"ATA device successfully opened\n\n"
3545 "Use 'smartctl -a' (or '-x') to print SMART (and more) information\n\n");
3552 unsigned char raw_drive[
sizeof(drive)]; memset(&raw_drive, 0,
sizeof(raw_drive));
3557 pout(
"Read Device Identity failed: %s\n\n",
3559 pout(
"If this is a USB connected device, look at the various "
3560 "--device=TYPE variants\n");
3563 else if (!
nonempty(&drive,
sizeof(drive))) {
3564 pout(
"Read Device Identity failed: empty IDENTIFY data\n\n");
3577 std::string dbversion;
3581 firmwarebugs, dbversion);
3582 if (!dbversion.empty())
3583 jglb[
"smartctl"][
"drive_database_version"][
"string"] = dbversion;
3593 pout(
"=== ATA IDENTIFY DATA ===\n");
3600 pout(
"=== START OF INFORMATION SECTION ===\n");
3605 int smart_supported = -1, smart_enabled = -1;
3606 if (need_smart_support || options.
drive_info) {
3610 pout(
"SMART support is: Unavailable - Packet Interface Devices [this device: %s] don't support ATA SMART\n",
3618 if (smart_supported < 0)
3619 pout(
"SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 82-83 don't show if SMART supported.\n");
3620 if (smart_supported && smart_enabled < 0) {
3621 pout(
"SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 85-87 don't show if SMART is enabled.\n");
3622 if (need_smart_support) {
3625 pout(
" Checking to be sure by trying SMART RETURN STATUS command.\n");
3627 smart_supported = smart_enabled = 1;
3630 else if (smart_supported < 0 && (smart_enabled > 0 || dbentry))
3632 smart_supported = 1;
3634 if (smart_supported < 0)
3635 pout(
"SMART support is: Unknown - Try option -s with argument 'on' to enable it.");
3636 else if (!smart_supported)
3637 jout(
"SMART support is: Unavailable - device lacks SMART capability.\n");
3640 jout(
"SMART support is: Available - device has SMART capability.\n");
3641 if (smart_enabled >= 0) {
3644 pout(
" %sabled status cached by OS, trying SMART RETURN STATUS cmd.\n",
3645 (smart_enabled?
"En":
"Dis"));
3649 jout(
"SMART support is: %s\n",
3650 (smart_enabled ?
"Enabled" :
"Disabled"));
3655 if (options.
drive_info || smart_supported <= 0) {
3656 jglb[
"smart_support"][
"available"] = (smart_supported > 0);
3657 if (smart_supported > 0)
3658 jglb[
"smart_support"][
"enabled"] = (smart_enabled > 0);
3665 pout(
"AAM feature is: Unavailable\n");
3666 else if (!(drive.
word086 & 0x0200)) {
3667 jout(
"AAM feature is: Disabled\n");
3668 jglb[
"ata_aam"][
"enabled"] =
false;
3678 pout(
"APM feature is: Unavailable\n");
3679 else if (!(drive.
word086 & 0x0008)) {
3680 jout(
"APM feature is: Disabled\n");
3681 jglb[
"ata_apm"][
"enabled"] =
false;
3691 pout(
"Rd look-ahead is: Unavailable\n");
3694 jout(
"Rd look-ahead is: %sabled\n", (enabled ?
"En" :
"Dis"));
3695 jglb[
"read_lookahead"][
"enabled"] = enabled;
3703 pout(
"Write cache is: Unavailable\n");
3706 jout(
"Write cache is: %sabled\n", (enabled ?
"En" :
"Dis"));
3707 jglb[
"write_cache"][
"enabled"] = enabled;
3716 || ((word119 & 0xc200) != 0x4200)
3717 || ((word120 & 0xc000) != 0x4000))
3718 pout(
"DSN feature is: Unavailable\n");
3720 bool enabled = !!(word120 & 0x200);
3721 jout(
"DSN feature is: %sabled\n", (enabled ?
"En" :
"Dis"));
3722 jglb[
"ata_dsn"][
"enabled"] = enabled;
3728 bool locked = ((word128 & 0x0007) == 0x0007);
3737 pout(
"Wt Cache Reorder: Unavailable\n");
3739 pout(
"Wt Cache Reorder: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3742 false ,
false ,
false );
3744 if (-1 <= wcache_reorder && wcache_reorder <= 2)
3745 pout(
"Wt Cache Reorder: %s\n",
3746 (wcache_reorder == -1 ?
"Unknown (SCT Feature Control command failed)" :
3747 wcache_reorder == 0 ?
"Unknown" :
3748 wcache_reorder == 1 ?
"Enabled" :
"Disabled"));
3750 pout(
"Wt Cache Reorder: Unknown (0x%02x)\n", wcache_reorder);
3754 const char * sct_write_cache_state_desc[4] = {
3756 "Controlled by ATA",
3764 pout(
"SCT Write Cache Control: Unavailable\n");
3766 pout(
"SCT Write Cache Control: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3769 if (-1 <= state && state <= 3)
3770 pout(
"SCT Write Cache Control: %s\n",
3771 (state == -1 ?
"Unknown (SCT Feature Control command failed)" :
3772 sct_write_cache_state_desc[state]));
3774 pout(
"SCT Write Cache Control: Unknown (0x%02x)\n", state);
3783 pout(
"Power mode %s %s\n", (powerchg?
"was:":
"is: "), powername);
3788 if (smart_supported <= 0 && need_smart_support)
3798 pout(
"=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
3816 pout(
"AAM disabled\n");
3836 pout(
"APM disabled\n");
3844 pout(
"Read look-ahead %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3848 pout(
"Read look-ahead %sabled\n", (enable ?
"en" :
"dis"));
3855 pout(
"Write cache %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3859 pout(
"Write cache %sabled\n", (enable ?
"en" :
"dis"));
3864 bool enable = (options.
set_dsn > 0);
3866 pout(
"DSN %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3870 pout(
"DSN %sabled\n", (enable ?
"en" :
"dis"));
3877 pout(
"Write cache reordering %sable failed: SCT Feature Control command not supported\n",
3878 (enable ?
"en" :
"dis"));
3880 pout(
"Write cache reordering %sable failed: SCT not supported if ATA Security is LOCKED\n",
3881 (enable ?
"en" :
"dis"));
3884 pout(
"Write cache reordering %sable failed: %s\n", (enable ?
"en" :
"dis"), device->
get_errmsg());
3888 pout(
"Write cache reordering %sabled (%s)\n", (enable ?
"en" :
"dis"),
3895 pout(
"SCT Feature Control of write cache failed: SCT Feature Control command not supported\n");
3897 pout(
"SCT Feature Control of write cache failed: SCT not supported if ATA Security is LOCKED\n");
3900 pout(
"SCT Feature Control of write cache failed: %s\n", device->
get_errmsg());
3904 pout(
"Write cache SCT Feature Control is set to: %s (%s)\n",
3912 pout(
"ATA SECURITY FREEZE LOCK failed: %s\n", device->
get_errmsg());
3916 pout(
"ATA Security set to frozen mode\n");
3936 pout(
"SMART Enabled.\n");
3951 pout(
"SMART Disabled. Use option -s with argument 'on' to enable it.\n");
3953 pout(
"(override with '-T permissive' option)\n");
3960 pout(
"SMART Enable Attribute Autosave failed: %s\n\n", device->
get_errmsg());
3964 pout(
"SMART Attribute Autosave Enabled.\n");
3969 pout(
"SMART Disable Attribute Autosave failed: %s\n\n", device->
get_errmsg());
3973 pout(
"SMART Attribute Autosave Disabled.\n");
3979 bool smart_val_ok =
false, smart_thres_ok =
false;
3981 if (need_smart_val) {
3987 smart_val_ok =
true;
3991 pout(
"Read SMART Thresholds failed: %s\n\n", device->
get_errmsg());
3995 smart_thres_ok =
true;
4001 bool needupdate =
false;
4004 pout(
"SMART Automatic Timers not supported\n\n");
4007 needupdate = smart_val_ok;
4009 pout(
"SMART Enable Automatic Offline failed: %s\n\n", device->
get_errmsg());
4013 pout(
"SMART Automatic Offline Testing Enabled every four hours.\n");
4018 pout(
"SMART Automatic Timers not supported\n\n");
4021 needupdate = smart_val_ok;
4023 pout(
"SMART Disable Automatic Offline failed: %s\n\n", device->
get_errmsg());
4027 pout(
"SMART Automatic Offline Testing Disabled.\n");
4033 smart_val_ok =
false;
4051 pout(
"=== START OF READ SMART DATA SECTION ===\n");
4060 jout(
"SMART overall-health self-assessment test result: PASSED\n");
4061 jglb[
"smart_status"][
"passed"] =
true;
4062 if (smart_thres_ok &&
find_failed_attr(&smartval, &smartthres, attribute_defs, 0)) {
4064 pout(
"See vendor-specific Attribute list for marginal Attributes.\n\n");
4067 pout(
"Please note the following marginal Attributes:\n");
4079 jout(
"SMART overall-health self-assessment test result: FAILED!\n"
4080 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
4081 jglb[
"smart_status"][
"passed"] =
false;
4083 if (smart_thres_ok &&
find_failed_attr(&smartval, &smartthres, attribute_defs, 1)) {
4086 pout(
"See vendor-specific Attribute list for failed Attributes.\n\n");
4089 pout(
"Failed Attributes:\n");
4094 pout(
"No failed Attributes found.\n\n");
4105 pout(
"SMART Status %s: %s\n",
4112 if (!(smart_val_ok && smart_thres_ok)) {
4114 pout(
"SMART overall-health self-assessment test result: UNKNOWN!\n"
4115 "SMART Status, Attributes and Thresholds cannot be read.\n\n");
4119 jout(
"SMART overall-health self-assessment test result: FAILED!\n"
4120 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
4121 jwrn(
"Warning: This result is based on an Attribute check.\n");
4122 jglb[
"smart_status"][
"passed"] =
false;
4127 pout(
"See vendor-specific Attribute list for failed Attributes.\n\n");
4130 pout(
"Failed Attributes:\n");
4135 jout(
"SMART overall-health self-assessment test result: PASSED\n");
4136 jwrn(
"Warning: This result is based on an Attribute check.\n");
4137 jglb[
"smart_status"][
"passed"] =
true;
4140 pout(
"See vendor-specific Attribute list for marginal Attributes.\n\n");
4143 pout(
"Please note the following marginal Attributes:\n");
4173 if ( gp_log_supported
4176 need_smart_logdir =
true;
4182 if (need_smart_logdir) {
4184 smartlogdir =
fake_logdir(&smartlogdir_buf, options);
4186 pout(
"Read SMART Log Directory failed: %s\n\n", device->
get_errmsg());
4190 smartlogdir = &smartlogdir_buf;
4194 if (need_gp_logdir) {
4199 pout(
"General Purpose Log Directory not supported\n\n");
4202 pout(
"Read GP Log Directory failed\n\n");
4206 gplogdir = &gplogdir_buf;
4212 pout(
"Log Directories not read due to '-F nologdir' option\n\n");
4222 unsigned max_nsectors;
4224 type =
"General Purpose";
4232 if (!max_nsectors) {
4234 pout(
"%s Log 0x%02x does not exist (override with '-T permissive' option)\n", type, req.
logaddr);
4237 max_nsectors = req.
page+1;
4239 if (max_nsectors <= req.
page) {
4240 pout(
"%s Log 0x%02x has only %u sectors, output skipped\n", type, req.
logaddr, max_nsectors);
4245 if (ns > max_nsectors - req.
page) {
4247 pout(
"%s Log 0x%02x has only %u sectors, output truncated\n", type, req.
logaddr, max_nsectors);
4248 ns = max_nsectors - req.
page;
4252 unsigned offs = (req.
gpl ? 0 : req.
page);
4272 pout(
"SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n\n");
4278 pout(
"Read SMART Extended Comprehensive Error Log failed\n\n");
4290 do_smart_error_log =
true;
4291 else if (!do_smart_error_log)
4292 pout(
"Try '-l [xerror,]error' to read traditional SMART Error Log\n");
4297 if (do_smart_error_log) {
4299 || ( !(smartlogdir && gp_log_supported)
4302 pout(
"SMART Error Log not supported\n\n");
4307 pout(
"Read SMART Error Log failed: %s\n\n", device->
get_errmsg());
4325 pout(
"SMART Extended Self-test Log (GP Log 0x07) not supported\n\n");
4326 else if (nsectors >= 256)
4327 pout(
"SMART Extended Self-test Log size %u not supported\n\n", nsectors);
4332 pout(
"Read SMART Extended Self-test Log failed\n\n");
4344 do_smart_selftest_log =
true;
4345 else if (!do_smart_selftest_log)
4346 pout(
"Try '-l [xselftest,]selftest' to read traditional SMART Self Test Log\n");
4351 if (do_smart_selftest_log) {
4353 || ( !(smartlogdir && gp_log_supported)
4356 pout(
"SMART Self-test Log not supported\n\n");
4361 pout(
"Read SMART Self-test Log failed: %s\n\n", device->
get_errmsg());
4379 pout(
"Selective Self-tests/Logging not supported\n\n");
4381 pout(
"Read SMART Selective Self-test Log failed: %s\n\n", device->
get_errmsg());
4401 pout(
"SCT Commands not supported\n\n");
4403 pout(
"SCT Commands not supported if ATA Security is LOCKED\n\n");
4428 pout(
"SCT Data Table command not supported\n\n");
4438 pout(
"Read SCT Temperature History failed\n\n");
4449 pout(
"SCT Feature Control command not supported\n\n");
4454 pout(
"Write Temperature Logging Interval failed\n\n");
4458 pout(
"Temperature Logging Interval set to %u minute%s (%s)\n",
4469 pout(
"SCT Error Recovery Control command not supported\n\n");
4480 pout(
"SCT (Set) Error Recovery Control command failed\n");
4483 pout(
"Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n");
4487 else if (!sct_erc_get)
4494 bool get_power_on = (sct_erc_get == 2);
4495 unsigned short read_timer, write_timer;
4498 pout(
"SCT (Get) Error Recovery Control command failed\n");
4500 pout(
"The previous SCT (Set) Error Recovery Control command succeeded\n");
4515 bool use_gplog =
true;
4516 unsigned nsectors = 0;
4519 else if (smartlogdir){
4524 pout(
"Device Statistics (GP/SMART Log 0x04) not supported\n\n");
4534 pout(
"Pending Defects log (GP Log 0x0c) not supported\n\n");
4543 if (!nsectors && (drive.
words047_079[76-47] & 0x0401) == 0x0400)
4546 pout(
"SATA Phy Event Counters (GP Log 0x11) not supported\n\n");
4547 else if (nsectors != 1)
4548 pout(
"SATA Phy Event Counters with %u sectors not supported\n\n", nsectors);
4550 unsigned char log_11[512] = {0, };
4551 unsigned char features = (options.
sataphy_reset ? 0x01 : 0x00);
4553 pout(
"Read SATA Phy Event Counters failed\n\n");
4563 bool farm_supported =
true;
4570 jout(
"FARM log (GP Log 0xa6) not supported\n\n");
4572 farm_supported =
false;
4576 jout(
"Seagate FARM log (GP Log 0xa6) supported [try: -l farm]\n\n");
4581 pout(
"Read FARM log (GP Log 0xa6) failed\n\n");
4582 farm_supported =
false;
4591 jout(
"FARM log (GP Log 0xa6) not supported for non-Seagate drives\n"
4592 "(override with '-T permissive' option)\n\n");
4593 farm_supported =
false;
4595 jglb[
"seagate_farm_log"][
"supported"] = farm_supported;
4599 if (options.
a_option && !not_part_of_a_option)
4600 pout(
"The above only provides legacy SMART information - try 'smartctl -x' for more\n\n");
4612 pout(
"Device placed in STANDBY mode\n");
4617 pout(
"ATA STANDBY IMMEDIATE command failed: %s\n", device->
get_errmsg());
4621 pout(
"Device placed in STANDBY mode\n");
4629 pout(
"=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
4634 pout(
"Execute Offline Immediate function not supported\n\n");
4644 pout(
"Self-test functions not supported\n\n");
4651 pout(
"Conveyance Self-test functions not supported\n\n");
4658 pout(
"Selective Self-test functions not supported\n\n");
4679 pout(
"Note: giving further SMART commands will abort Offline testing\n");
4689 time_t t=time(NULL);
4692 pout(
"Please wait %d seconds for test to complete.\n", (
int)timewait);
4695 pout(
"Please wait %d minutes for test to complete.\n", (
int)timewait);
4699 pout(
"Test will complete after %s\n", comptime);
4705 pout(
"Use smartctl -X to abort test.\n");
const char * look_up_ata_command(unsigned char c_code, unsigned char f_reg)
bool ata_nodata_command(ata_device *device, unsigned char command, int sector_count)
int ataDisableAutoOffline(ata_device *device)
unsigned char ata_return_temperature_value(const ata_smart_values *data, const ata_vendor_attr_defs &defs)
bool isSmartErrorLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
int ataGetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short &time_limit, bool power_on)
bool ataReadSmartLog(ata_device *device, unsigned char logaddr, void *data, unsigned nsectors)
int ata_get_wwn(const ata_identify_device *id, unsigned &oui, uint64_t &unique_id)
int ataSmartTest(ata_device *device, int testtype, bool force, const ata_selective_selftest_args &selargs, const ata_smart_values *sv, uint64_t num_sectors)
int ataEnableAutoOffline(ata_device *device)
int ataSmartStatus2(ata_device *device)
int ataSmartSupport(const ata_identify_device *drive)
int ataDisableAutoSave(ata_device *device)
int ata_get_rotation_rate(const ata_identify_device *id)
bool ataReadLogExt(ata_device *device, unsigned char logaddr, unsigned char features, unsigned page, void *data, unsigned nsectors)
int ataEnableAutoSave(ata_device *device)
int ataReadSelfTestLog(ata_device *device, ata_smart_selftestlog *data, firmwarebug_defs firmwarebugs)
std::string ata_format_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
int ataReadSCTTempHist(ata_device *device, ata_sct_temperature_history_table *tmh, ata_sct_status_response *sts)
int ataReadErrorLog(ata_device *device, ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
void ata_get_size_info(const ata_identify_device *id, ata_size_info &sizes)
int ata_read_identity(ata_device *device, ata_identify_device *buf, bool fix_swapped_id, unsigned char *raw_buf)
int TestTime(const ata_smart_values *data, int testtype)
int ataEnableSmart(ata_device *device)
bool isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
int ataCheckPowerMode(ata_device *device)
int ataGetSetSCTWriteCacheReordering(ata_device *device, bool enable, bool persistent, bool set)
unsigned char checksum(const void *data)
bool ataReadExtSelfTestLog(ata_device *device, ata_smart_extselftestlog *log, unsigned nsectors)
int ataReadSelectiveSelfTestLog(ata_device *device, struct ata_selective_self_test_log *data)
bool isSmartTestLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
int ataReadSmartValues(ata_device *device, struct ata_smart_values *data)
int ataSetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default)
int ataDoesSmartWork(ata_device *device)
uint64_t ata_get_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
bool dont_print_serial_number
int ataReadSCTStatus(ata_device *device, ata_sct_status_response *sts)
bool ataReadExtErrorLog(ata_device *device, ata_smart_exterrlog *log, unsigned page, unsigned nsectors, firmwarebug_defs firmwarebugs)
int ataDisableSmart(ata_device *device)
int ataSetSCTTempInterval(ata_device *device, unsigned interval, bool persistent)
std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs &defs, int rpm)
int ataGetSetSCTWriteCache(ata_device *device, unsigned short state, bool persistent, bool set)
int ataReadSmartThresholds(ata_device *device, struct ata_smart_thresholds_pvt *data)
int ataIsSmartEnabled(const ata_identify_device *drive)
void ata_format_id_string(char *out, const unsigned char *in, int n)
int ataReadLogDirectory(ata_device *device, ata_smart_log_directory *data, bool gpl)
bool ata_set_features(ata_device *device, unsigned char features, int sector_count)
ata_attr_state ata_get_attr_state(const ata_smart_attribute &attr, int attridx, const ata_smart_threshold_entry *thresholds, const ata_vendor_attr_defs &defs, unsigned char *threshval)
#define ATA_ENABLE_READ_LOOK_AHEAD
#define ATTRIBUTE_FLAGS_OTHER(x)
#define SELECTIVE_FLAG_PENDING
#define ATA_DISABLE_WRITE_CACHE
#define ATTRIBUTE_FLAGS_SELFPRESERVING(x)
bool isSupportSelfTest(const ata_smart_values *data)
#define SELECTIVE_SELF_TEST
bool isSCTErrorRecoveryControlCapable(const ata_identify_device *drive)
#define ATA_STANDBY_IMMEDIATE
bool isSupportOfflineSurfaceScan(const ata_smart_values *data)
#define OFFLINE_FULL_SCAN
#define SELECTIVE_FLAG_DOSCAN
bool isSupportConveyanceSelfTest(const ata_smart_values *data)
#define ATA_ENABLE_DISABLE_DSN
void checksumwarning(const char *string)
#define ATTRIBUTE_FLAGS_EVENTCOUNT(x)
#define ATTRIBUTE_FLAGS_PERFORMANCE(x)
bool isSupportAutomaticTimer(const ata_smart_values *data)
#define ATA_ENABLE_WRITE_CACHE
bool isSupportSelectiveSelfTest(const ata_smart_values *data)
bool isSCTDataTableCapable(const ata_identify_device *drive)
#define ATA_DISABLE_READ_LOOK_AHEAD
#define ATTRIBUTE_FLAGS_PREFAILURE(x)
bool isSupportExecuteOfflineImmediate(const ata_smart_values *data)
bool isSupportOfflineAbort(const ata_smart_values *data)
#define SELECTIVE_FLAG_ACTIVE
#define ATTRIBUTE_FLAGS_ERRORRATE(x)
#define EXTEND_CAPTIVE_SELF_TEST
#define CONVEYANCE_CAPTIVE_SELF_TEST
#define CONVEYANCE_SELF_TEST
#define ATA_SECURITY_FREEZE_LOCK
#define SHORT_CAPTIVE_SELF_TEST
#define NUMBER_ATA_SMART_ATTRIBUTES
#define SELECTIVE_CAPTIVE_SELF_TEST
#define ATTRIBUTE_FLAGS_ONLINE(x)
bool isSCTFeatureControlCapable(const ata_identify_device *drive)
bool isSCTCapable(const ata_identify_device *drive)
void ata_print_identify_data(const void *id, bool all_words, int bit_level)
static void print_standby_timer(const char *msg, int timer, const ata_identify_device &drive)
static const char * sct_ptemp(signed char x, char(&buf)[20])
static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer, bool power_on, bool mfg_default=false)
static void PrintSmartCapability(const ata_smart_values *data)
static const char * infofound(const char *output)
const char * ataprint_cpp_cvsid
static void ataPrintSCTCapability(const ata_identify_device *drive)
const devstat_entry_info devstat_info_0x04[]
static void PrintSmartTotalTimeCompleteOffline(const ata_smart_values *data)
static void print_aam_level(const char *msg, int level, int recommended=-1)
const devstat_entry_info devstat_info_0x01[]
static void set_json_globals_from_device_statistics(int page, int offset, int64_t val)
static void print_sata_version_and_speed(unsigned short word222, unsigned short word076, unsigned short word077)
static void print_ata_security_status(const char *msg, unsigned short state, unsigned short master_password_id)
static void PrintSmartOfflineCollectCap(const ata_smart_values *data)
int ataPrintMain(ata_device *device, const ata_print_options &options)
static void PrintSmartOfflineStatus(const ata_smart_values *data)
static void print_drive_info(const ata_identify_device *drive, const ata_size_info &sizes, int rpm, const drive_settings *dbentry, const char *dbversion)
static void PrintSmartSelfExecStatus(const ata_smart_values *data, firmwarebug_defs firmwarebugs)
const int num_devstat_infos
static const char * get_sata_version(unsigned short word222)
const devstat_entry_info devstat_info_0x03[]
static void PrintSmartConveyanceSelfTestPollingTime(const ata_smart_values *data)
static bool is_permissive()
const devstat_entry_info devstat_info_0x02[]
static int ataPrintSmartSelfTestlog(const ata_smart_selftestlog *log, bool allentries, firmwarebug_defs firmwarebugs)
static int PrintSmartErrorlog(const ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
static const char * get_ata_major_version(const ata_identify_device *drive)
static const char * sct_device_state_msg(unsigned char state)
static const char * sct_pbar(int x, char(&buf)[64])
static std::string format_st_er_desc(unsigned char CR, unsigned char FR, unsigned char ST, unsigned char ER, unsigned short SC, const ata_smart_errorlog_error_struct *lba28_regs, const ata_smart_exterrlog_error *lba48_regs)
static void ataPrintSelectiveSelfTestLog(const ata_selective_self_test_log *log, const ata_smart_values *sv)
static const char * get_pata_version(unsigned short word222, char(&buf)[32])
static bool print_pending_defects_log(ata_device *device, unsigned nsectors, unsigned max_entries)
static void PrintSmartAttribWithThres(const ata_smart_values *data, const ata_smart_thresholds_pvt *thresholds, const ata_vendor_attr_defs &defs, int rpm, int onlyfailed, unsigned char format)
static void PrintSmartExtendedSelfTestPollingTime(const ata_smart_values *data)
static void set_json_globals_from_smart_attrib(int id, const char *name, const ata_vendor_attr_defs &defs, uint8_t normval, uint8_t threshold, uint64_t rawval)
static void print_device_statistics_page(const json::ref &jref, const unsigned char *data, int page)
static bool print_device_statistics(ata_device *device, unsigned nsectors, const std::vector< int > &single_pages, bool all_pages, bool ssd_page, bool use_gplog)
static void PrintSataPhyEventCounters(const unsigned char *data, bool reset)
static void PrintSmartErrorLogCapability(const ata_smart_values *data, const ata_identify_device *identity)
static void PrintSmartShortSelfTestPollingTime(const ata_smart_values *data)
static const char * OfflineDataCollectionStatus(unsigned char status_byte)
static int find_msb(unsigned short word)
static std::string format_milliseconds(unsigned msec)
static void PrintGeneralSmartValues(const ata_smart_values *data, const ata_identify_device *drive, firmwarebug_defs firmwarebugs)
static void PrintLogPages(const char *type, const unsigned char *data, unsigned char logaddr, unsigned page, unsigned num_pages, unsigned max_pages)
static void sct_jtemp2(const json::ref &jref, const char *name, signed char x)
static unsigned GetNumLogSectors(const ata_smart_log_directory *logdir, unsigned logaddr, bool gpl)
const ata_smart_log_directory * fake_logdir(ata_smart_log_directory *logdir, const ata_print_options &options)
static void print_apm_level(const char *msg, int level)
const devstat_entry_info devstat_info_0x07[]
static const char * get_error_log_state_desc(unsigned state)
static int ataPrintSCTTempHist(const ata_sct_temperature_history_table *tmh)
const devstat_entry_info devstat_info_0x00[]
static const char * get_log_rw(unsigned logaddr)
static const char * GetLogName(unsigned logaddr)
const devstat_entry_info devstat_info_0x05[]
static int PrintSmartExtSelfTestLog(const ata_smart_extselftestlog *log, unsigned nsectors, unsigned max_entries)
static void jset_sata_speed(const char *key, int value, int speed, const char *str)
static const char * get_sata_speed(int speed)
static int find_failed_attr(const ata_smart_values *data, const ata_smart_thresholds_pvt *thresholds, const ata_vendor_attr_defs &defs, int onlyfailed)
static int ataPrintSCTStatus(const ata_sct_status_response *sts)
static const char * get_device_statistics_page_name(int page)
const devstat_entry_info devstat_info_0x06[]
static const char * get_ata_minor_version(const ata_identify_device *drive)
static int ataPrintSmartSelfTestEntry(const json::ref &jref, unsigned testnum, unsigned char test_type, unsigned char test_status, unsigned short timestamp, uint64_t failing_lba, bool print_error_only, bool &print_header)
static int PrintSmartExtErrorLog(ata_device *device, const firmwarebug_defs &firmwarebugs, const ata_smart_exterrlog *log, unsigned nsectors, unsigned max_errors)
static void PrintLogDirectories(const ata_smart_log_directory *gplogdir, const ata_smart_log_directory *smartlogdir)
const devstat_entry_info * devstat_infos[]
static const char * get_form_factor(unsigned short word168)
virtual bool ata_identify_is_cached() const
Return true if OS caches ATA identify sector.
bool is_set(firmwarebug_t bug) const
Reference to a JSON element.
void set_unsafe_uint64(uint64_t value)
bool is_enabled() const
Return true if enabled.
Wrapper class for POSIX regex(3) or std::regex Supports copy & assignment and is compatible with STL ...
bool full_match(const char *str) const
Return true if full string matches pattern.
int get_errno() const
Get last error number.
const char * get_errmsg() const
Get last error message.
virtual bool is_syscall_unsup() const
Return true if last error indicates an unsupported system call.
void clear_err()
Clear last error info.
bool ataIsSeagate(const ata_identify_device &drive, const drive_settings *dbentry)
bool ataReadFarmLog(ata_device *device, ataFarmLog &farmLog, unsigned nsectors)
void ataPrintFarmLog(const ataFarmLog &farmLog)
const drive_settings * lookup_drive_apply_presets(const ata_identify_device *drive, ata_vendor_attr_defs &defs, firmwarebug_defs &firmwarebugs, std::string &dbversion)
void show_presets(const ata_identify_device *drive)
unsigned char failuretest_permissive
static uint64_t sg_get_unaligned_le64(const void *p)
static uint32_t sg_get_unaligned_le32(const void *p)
void jout_startup_datetime(const char *prefix)
void failuretest(failure_type type, int returnvalue)
bool printing_is_switchable
void void jinf(const char *fmt,...) __attribute_format_printf(1
void void void jwrn(const char *fmt,...) __attribute_format_printf(1
void void void void jerr(const char *fmt,...) __attribute_format_printf(1
void jout(const char *fmt,...) __attribute_format_printf(1
void pout(const char *fmt,...)
unsigned short minor_rev_num
unsigned short major_rev_num
unsigned short words047_079[33]
unsigned short cfs_enable_1
unsigned short words088_255[168]
unsigned short command_set_2
unsigned short command_set_1
unsigned char serial_no[20]
bool smart_auto_offl_disable
bool sct_wcache_reorder_get
bool smart_auto_save_enable
bool smart_general_values
unsigned sct_erc_writetime
unsigned pending_defects_log
ata_selective_selftest_args smart_selective_args
std::vector< int > devstat_pages
unsigned smart_ext_error_log
unsigned smart_ext_selftest_log
firmwarebug_defs firmwarebugs
unsigned char output_format
int sct_wcache_reorder_set
bool smart_selftest_force
bool smart_selective_selftest_log
ata_vendor_attr_defs attribute_defs
unsigned sct_erc_readtime
std::vector< ata_log_request > log_requests
bool sct_wcache_sct_set_pers
bool sct_wcache_reorder_set_pers
bool smart_auto_offl_enable
bool smart_auto_save_disable
unsigned int over_limit_count
unsigned short min_erc_time
unsigned short sct_version
unsigned short format_version
signed char life_max_temp
unsigned char vendor_specific[32]
unsigned char device_state
unsigned int under_limit_count
signed char life_min_temp
unsigned short smart_status
unsigned short sampling_period
unsigned short format_version
unsigned short pendingtime
unsigned short logversion
unsigned short currentspan
unsigned log_sector_offset
unsigned char devicecontrolreg
unsigned char cylinder_high
unsigned char cylinder_low
unsigned char featuresreg
unsigned char sector_count
unsigned char sector_number
unsigned char cylinder_low
unsigned char sector_count
unsigned char sector_number
unsigned char cylinder_high
unsigned char error_register
struct ata_smart_errorlog_command_struct commands[5]
struct ata_smart_errorlog_error_struct error_struct
unsigned char device_control_register
unsigned char lba_low_register_hi
unsigned char lba_low_register
unsigned char count_register
unsigned char error_register
unsigned char count_register_hi
unsigned char lba_high_register_hi
unsigned char device_register
unsigned char status_register
unsigned char lba_mid_register
unsigned char lba_mid_register_hi
unsigned char lba_high_register
unsigned short error_log_index
ata_smart_exterrlog_error_log error_logs[4]
unsigned short device_error_count
struct ata_smart_extselftestlog_desc log_descs[19]
unsigned short log_desc_index
struct ata_smart_log_entry entry[255]
unsigned short int logversion
unsigned char mostrecenttest
struct ata_smart_selftestlog_struct selftest_struct[21]
unsigned short int revnumber
struct ata_smart_threshold_entry thres_entries[NUMBER_ATA_SMART_ATTRIBUTES]
unsigned char self_test_exec_status
unsigned char offline_data_collection_status
void dateandtimezoneepoch(char(&buffer)[DATEANDEPOCHLEN], time_t tval)
const char * format_capacity(char *str, int strsize, uint64_t val, const char *decimal_point)
const char * format_with_thousands_sep(char *str, int strsize, uint64_t val, const char *thousands_sep)
std::string strprintf(const char *fmt,...)
bool nonempty(const void *data, int size)
const char * packetdevicetype(int type)
struct tm * time_to_tm_local(struct tm *tp, time_t t)
bool str_starts_with(const char *str, const char *prefix)