4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2002-11 Bruce Allen
7 * Copyright (C) 2008-18 Christian Franke
8 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 #define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
23 #include "atacmdnames.h"
25 #include "ataidentify.h"
26 #include "dev_interface.h"
29 #include "sg_unaligned.h"
31 #include "knowndrives.h"
33 const char * ataprint_cpp_cvsid
= "$Id: ataprint.cpp 4842 2018-12-02 16:07:26Z chrfranke $"
37 static const char * infofound(const char *output
) {
38 return (*output
? output
: "[No Information Found]");
41 // Return true if '-T permissive' is specified,
42 // used to ignore missing capabilities
43 static bool is_permissive()
45 if (!failuretest_permissive
)
47 failuretest_permissive
--;
51 /* For the given Command Register (CR) and Features Register (FR), attempts
52 * to construct a string that describes the contents of the Status
53 * Register (ST) and Error Register (ER). If the meanings of the flags of
54 * the error register are not known for the given command then it returns an
57 * The meanings of the flags of the error register for all commands are
58 * described in the ATA spec and could all be supported here in theory.
59 * Currently, only a few commands are supported (those that have been seen
60 * to produce errors). If many more are to be added then this function
61 * should probably be redesigned.
64 static std::string
format_st_er_desc(
65 unsigned char CR
, unsigned char FR
,
66 unsigned char ST
, unsigned char ER
,
68 const ata_smart_errorlog_error_struct
* lba28_regs
,
69 const ata_smart_exterrlog_error
* lba48_regs
72 const char *error_flag
[8];
73 int i
, print_lba
=0, print_sector
=0;
75 // Set of character strings corresponding to different error codes.
76 // Please keep in alphabetic order if you add more.
77 const char *abrt
= "ABRT"; // ABORTED
78 const char *amnf
= "AMNF"; // ADDRESS MARK NOT FOUND
79 const char *ccto
= "CCTO"; // COMMAND COMPLETION TIMED OUT
80 const char *eom
= "EOM"; // END OF MEDIA
81 const char *icrc
= "ICRC"; // INTERFACE CRC ERROR
82 const char *idnf
= "IDNF"; // ID NOT FOUND
83 const char *ili
= "ILI"; // MEANING OF THIS BIT IS COMMAND-SET SPECIFIC
84 const char *mc
= "MC"; // MEDIA CHANGED
85 const char *mcr
= "MCR"; // MEDIA CHANGE REQUEST
86 const char *nm
= "NM"; // NO MEDIA
87 const char *obs
= "obs"; // OBSOLETE
88 const char *tk0nf
= "TK0NF"; // TRACK 0 NOT FOUND
89 const char *unc
= "UNC"; // UNCORRECTABLE
90 const char *wp
= "WP"; // WRITE PROTECTED
92 /* If for any command the Device Fault flag of the status register is
93 * not used then used_device_fault should be set to 0 (in the CR switch
96 int uses_device_fault
= 1;
98 /* A value of NULL means that the error flag isn't used */
99 for (i
= 0; i
< 8; i
++)
100 error_flag
[i
] = NULL
;
105 case 0x10: // RECALIBRATE
106 error_flag
[2] = abrt
;
107 error_flag
[1] = tk0nf
;
109 case 0x20: /* READ SECTOR(S) */
110 case 0x21: // READ SECTOR(S)
111 case 0x24: // READ SECTOR(S) EXT
112 case 0xC4: /* READ MULTIPLE */
113 case 0x29: // READ MULTIPLE EXT
116 error_flag
[4] = idnf
;
118 error_flag
[2] = abrt
;
120 error_flag
[0] = amnf
;
123 case 0x22: // READ LONG (with retries)
124 case 0x23: // READ LONG (without retries)
125 error_flag
[4] = idnf
;
126 error_flag
[2] = abrt
;
127 error_flag
[0] = amnf
;
130 case 0x2a: // READ STREAM DMA
131 case 0x2b: // READ STREAM PIO
133 error_flag
[7] = icrc
;
136 error_flag
[4] = idnf
;
138 error_flag
[2] = abrt
;
140 error_flag
[0] = ccto
;
144 case 0x3A: // WRITE STREAM DMA
145 case 0x3B: // WRITE STREAM PIO
147 error_flag
[7] = icrc
;
150 error_flag
[4] = idnf
;
152 error_flag
[2] = abrt
;
154 error_flag
[0] = ccto
;
158 case 0x25: // READ DMA EXT
159 case 0x26: // READ DMA QUEUED EXT
160 case 0xC7: // READ DMA QUEUED
161 case 0xC8: // READ DMA (with retries)
162 case 0xC9: // READ DMA (without retries, obsolete since ATA-5)
163 case 0x60: // READ FPDMA QUEUED (NCQ)
164 error_flag
[7] = icrc
;
167 error_flag
[4] = idnf
;
169 error_flag
[2] = abrt
;
171 error_flag
[0] = amnf
;
173 if (CR
==0x25 || CR
==0xC8)
176 case 0x30: /* WRITE SECTOR(S) */
177 case 0x31: // WRITE SECTOR(S)
178 case 0x34: // WRITE SECTOR(S) EXT
179 case 0xC5: /* WRITE MULTIPLE */
180 case 0x39: // WRITE MULTIPLE EXT
181 case 0xCE: // WRITE MULTIPLE FUA EXT
184 error_flag
[4] = idnf
;
186 error_flag
[2] = abrt
;
190 case 0x32: // WRITE LONG (with retries)
191 case 0x33: // WRITE LONG (without retries)
192 error_flag
[4] = idnf
;
193 error_flag
[2] = abrt
;
196 case 0x3C: // WRITE VERIFY
198 error_flag
[4] = idnf
;
199 error_flag
[2] = abrt
;
200 error_flag
[0] = amnf
;
203 case 0x40: // READ VERIFY SECTOR(S) with retries
204 case 0x41: // READ VERIFY SECTOR(S) without retries
205 case 0x42: // READ VERIFY SECTOR(S) EXT
208 error_flag
[4] = idnf
;
210 error_flag
[2] = abrt
;
212 error_flag
[0] = amnf
;
215 case 0xA0: /* PACKET */
216 /* Bits 4-7 are all used for sense key (a 'command packet set specific error
217 * indication' according to the ATA/ATAPI-7 standard), so "Sense key" will
218 * be repeated in the error description string if more than one of those
221 error_flag
[7] = "Sense key (bit 3)",
222 error_flag
[6] = "Sense key (bit 2)",
223 error_flag
[5] = "Sense key (bit 1)",
224 error_flag
[4] = "Sense key (bit 0)",
225 error_flag
[2] = abrt
;
229 case 0xA1: /* IDENTIFY PACKET DEVICE */
230 case 0xEF: /* SET FEATURES */
232 case 0xC6: /* SET MULTIPLE MODE */
233 error_flag
[2] = abrt
;
235 case 0x2F: // READ LOG EXT
237 error_flag
[4] = idnf
;
238 error_flag
[2] = abrt
;
241 case 0x3F: // WRITE LOG EXT
242 error_flag
[4] = idnf
;
243 error_flag
[2] = abrt
;
246 case 0xB0: /* SMART */
248 case 0xD0: // SMART READ DATA
249 case 0xD1: // SMART READ ATTRIBUTE THRESHOLDS
250 case 0xD5: /* SMART READ LOG */
252 error_flag
[4] = idnf
;
253 error_flag
[2] = abrt
;
256 case 0xD6: /* SMART WRITE LOG */
257 error_flag
[4] = idnf
;
258 error_flag
[2] = abrt
;
261 case 0xD2: // Enable/Disable Attribute Autosave
262 case 0xD3: // SMART SAVE ATTRIBUTE VALUES (ATA-3)
263 case 0xD8: // SMART ENABLE OPERATIONS
264 case 0xD9: /* SMART DISABLE OPERATIONS */
265 case 0xDA: /* SMART RETURN STATUS */
266 case 0xDB: // Enable/Disable Auto Offline (SFF)
267 error_flag
[2] = abrt
;
269 case 0xD4: // SMART EXECUTE IMMEDIATE OFFLINE
270 error_flag
[4] = idnf
;
271 error_flag
[2] = abrt
;
278 case 0xB1: /* DEVICE CONFIGURATION */
280 case 0xC0: /* DEVICE CONFIGURATION RESTORE */
281 error_flag
[2] = abrt
;
288 case 0xCA: // WRITE DMA (with retries)
289 case 0xCB: // WRITE DMA (without retries, obsolete since ATA-5)
290 case 0x35: // WRITE DMA EXT
291 case 0x3D: // WRITE DMA FUA EXT
292 case 0xCC: // WRITE DMA QUEUED
293 case 0x36: // WRITE DMA QUEUED EXT
294 case 0x3E: // WRITE DMA QUEUED FUA EXT
295 case 0x61: // WRITE FPDMA QUEUED (NCQ)
296 error_flag
[7] = icrc
;
299 error_flag
[4] = idnf
;
301 error_flag
[2] = abrt
;
303 error_flag
[0] = amnf
;
308 case 0xE4: // READ BUFFER
309 case 0xE8: // WRITE BUFFER
310 error_flag
[2] = abrt
;
316 /* We ignore any status flags other than Device Fault and Error */
318 if (uses_device_fault
&& (ST
& (1 << 5))) {
319 str
= "Device Fault";
320 if (ST
& 1) // Error flag
323 if (ST
& 1) { // Error flag
327 for (i
= 7; i
>= 0; i
--)
328 if ((ER
& (1 << i
)) && (error_flag
[i
])) {
331 str
+= error_flag
[i
];
335 // If the error was a READ or WRITE error, print the Logical Block
336 // Address (LBA) at which the read or write failed.
338 // print number of sectors, if known, and append to print string
340 str
+= strprintf(" %d sectors", print_sector
);
344 // bits 24-27: bits 0-3 of DH
345 lba
= 0xf & lba28_regs
->drive_head
;
348 lba
|= lba28_regs
->cylinder_high
;
351 lba
|= lba28_regs
->cylinder_low
;
354 lba
|= lba28_regs
->sector_number
;
355 str
+= strprintf(" at LBA = 0x%08x = %u", lba
, lba
);
357 else if (lba48_regs
) {
358 // This assumes that upper LBA registers are 0 for 28-bit commands
359 // (TODO: detect 48-bit commands above)
361 lba48
= lba48_regs
->lba_high_register_hi
;
363 lba48
|= lba48_regs
->lba_mid_register_hi
;
365 lba48
|= lba48_regs
->lba_low_register_hi
;
366 lba48
|= lba48_regs
->device_register
& 0xf;
368 lba48
|= lba48_regs
->lba_high_register
;
370 lba48
|= lba48_regs
->lba_mid_register
;
372 lba48
|= lba48_regs
->lba_low_register
;
373 str
+= strprintf(" at LBA = 0x%08" PRIx64
" = %" PRIu64
, lba48
, lba48
);
380 static inline std::string
format_st_er_desc(
381 const ata_smart_errorlog_struct
* data
)
383 return format_st_er_desc(
384 data
->commands
[4].commandreg
,
385 data
->commands
[4].featuresreg
,
386 data
->error_struct
.status
,
387 data
->error_struct
.error_register
,
388 data
->error_struct
.sector_count
,
389 &data
->error_struct
, (const ata_smart_exterrlog_error
*)0);
392 static inline std::string
format_st_er_desc(
393 const ata_smart_exterrlog_error_log
* data
)
395 return format_st_er_desc(
396 data
->commands
[4].command_register
,
397 data
->commands
[4].features_register
,
398 data
->error
.status_register
,
399 data
->error
.error_register
,
400 data
->error
.count_register_hi
<< 8 | data
->error
.count_register
,
401 (const ata_smart_errorlog_error_struct
*)0, &data
->error
);
405 static const char * get_form_factor(unsigned short word168
)
407 // Bits 0:3 are the form factor
408 // Table A.32 of T13/2161-D (ACS-3) Revision 4p, September 19, 2013
409 // Table 236 of T13/BSR INCITS 529 (ACS-4) Revision 04, August 25, 2014
410 switch (word168
& 0xF) {
411 case 0x1: return "5.25 inches";
412 case 0x2: return "3.5 inches";
413 case 0x3: return "2.5 inches";
414 case 0x4: return "1.8 inches";
415 case 0x5: return "< 1.8 inches";
416 case 0x6: return "mSATA"; // ACS-4
417 case 0x7: return "M.2"; // ACS-4
418 case 0x8: return "MicroSSD"; // ACS-4
419 case 0x9: return "CFast"; // ACS-4
424 static int find_msb(unsigned short word
)
426 for (int bit
= 15; bit
>= 0; bit
--)
427 if (word
& (1 << bit
))
432 static const char * get_ata_major_version(const ata_identify_device
* drive
)
434 // Table 13 of T13/1153D (ATA/ATAPI-4) revision 18, August 19, 1998
435 // Table 48 of T13/BSR INCITS 529 (ACS-4) Revision 16, February 21, 2017
436 switch (find_msb(drive
->major_rev_num
)) {
437 case 14: return "ACS >4 (14)";
438 case 13: return "ACS >4 (13)";
439 case 12: return "ACS >4 (12)";
440 case 11: return "ACS-4";
441 case 10: return "ACS-3";
442 case 9: return "ACS-2";
443 case 8: return "ATA8-ACS";
444 case 7: return "ATA/ATAPI-7";
445 case 6: return "ATA/ATAPI-6";
446 case 5: return "ATA/ATAPI-5";
447 case 4: return "ATA/ATAPI-4";
448 case 3: return "ATA-3";
449 case 2: return "ATA-2";
450 case 1: return "ATA-1";
455 static const char * get_ata_minor_version(const ata_identify_device
* drive
)
457 // Table 10 of X3T13/2008D (ATA-3) Revision 7b, January 27, 1997
458 // Table 28 of T13/1410D (ATA/ATAPI-6) Revision 3b, February 26, 2002
459 // Table 31 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
460 // Table 46 of T13/BSR INCITS 529 (ACS-4) Revision 08, April 28, 2015
461 switch (drive
->minor_rev_num
) {
462 case 0x0001: return "ATA-1 X3T9.2/781D prior to revision 4";
463 case 0x0002: return "ATA-1 published, ANSI X3.221-1994";
464 case 0x0003: return "ATA-1 X3T9.2/781D revision 4";
465 case 0x0004: return "ATA-2 published, ANSI X3.279-1996";
466 case 0x0005: return "ATA-2 X3T10/948D prior to revision 2k";
467 case 0x0006: return "ATA-3 X3T10/2008D revision 1";
468 case 0x0007: return "ATA-2 X3T10/948D revision 2k";
469 case 0x0008: return "ATA-3 X3T10/2008D revision 0";
470 case 0x0009: return "ATA-2 X3T10/948D revision 3";
471 case 0x000a: return "ATA-3 published, ANSI X3.298-1997";
472 case 0x000b: return "ATA-3 X3T10/2008D revision 6"; // 1st ATA-3 revision with SMART
473 case 0x000c: return "ATA-3 X3T13/2008D revision 7 and 7a";
474 case 0x000d: return "ATA/ATAPI-4 X3T13/1153D revision 6";
475 case 0x000e: return "ATA/ATAPI-4 T13/1153D revision 13";
476 case 0x000f: return "ATA/ATAPI-4 X3T13/1153D revision 7";
477 case 0x0010: return "ATA/ATAPI-4 T13/1153D revision 18";
478 case 0x0011: return "ATA/ATAPI-4 T13/1153D revision 15";
479 case 0x0012: return "ATA/ATAPI-4 published, ANSI NCITS 317-1998";
480 case 0x0013: return "ATA/ATAPI-5 T13/1321D revision 3";
481 case 0x0014: return "ATA/ATAPI-4 T13/1153D revision 14";
482 case 0x0015: return "ATA/ATAPI-5 T13/1321D revision 1";
483 case 0x0016: return "ATA/ATAPI-5 published, ANSI NCITS 340-2000";
484 case 0x0017: return "ATA/ATAPI-4 T13/1153D revision 17";
485 case 0x0018: return "ATA/ATAPI-6 T13/1410D revision 0";
486 case 0x0019: return "ATA/ATAPI-6 T13/1410D revision 3a";
487 case 0x001a: return "ATA/ATAPI-7 T13/1532D revision 1";
488 case 0x001b: return "ATA/ATAPI-6 T13/1410D revision 2";
489 case 0x001c: return "ATA/ATAPI-6 T13/1410D revision 1";
490 case 0x001d: return "ATA/ATAPI-7 published, ANSI INCITS 397-2005";
491 case 0x001e: return "ATA/ATAPI-7 T13/1532D revision 0";
492 case 0x001f: return "ACS-3 T13/2161-D revision 3b";
494 case 0x0021: return "ATA/ATAPI-7 T13/1532D revision 4a";
495 case 0x0022: return "ATA/ATAPI-6 published, ANSI INCITS 361-2002";
497 case 0x0027: return "ATA8-ACS T13/1699-D revision 3c";
498 case 0x0028: return "ATA8-ACS T13/1699-D revision 6";
499 case 0x0029: return "ATA8-ACS T13/1699-D revision 4";
501 case 0x0031: return "ACS-2 T13/2015-D revision 2";
503 case 0x0033: return "ATA8-ACS T13/1699-D revision 3e";
505 case 0x0039: return "ATA8-ACS T13/1699-D revision 4c";
507 case 0x0042: return "ATA8-ACS T13/1699-D revision 3f";
509 case 0x0052: return "ATA8-ACS T13/1699-D revision 3b";
511 case 0x005e: return "ACS-4 T13/BSR INCITS 529 revision 5";
513 case 0x006d: return "ACS-3 T13/2161-D revision 5";
515 case 0x0082: return "ACS-2 published, ANSI INCITS 482-2012";
517 case 0x0107: return "ATA8-ACS T13/1699-D revision 2d";
519 case 0x010a: return "ACS-3 published, ANSI INCITS 522-2014";
521 case 0x0110: return "ACS-2 T13/2015-D revision 3";
523 case 0x011b: return "ACS-3 T13/2161-D revision 4";
529 static const char * get_pata_version(unsigned short word222
, char (& buf
)[32])
531 switch (word222
& 0x0fff) {
532 default: snprintf(buf
, sizeof(buf
),
533 "Unknown (0x%03x)", word222
& 0x0fff); return buf
;
535 case 0x003: return "ATA8-APT";
536 case 0x002: return "ATA/ATAPI-7";
540 static const char * get_sata_version(unsigned short word222
)
542 switch (find_msb(word222
& 0x0fff)) {
543 case 11: return "SATA >3.3 (11)";
544 case 10: return "SATA >3.3 (10)";
545 case 9: return "SATA >3.3 (9)";
546 case 8: return "SATA 3.3";
547 case 7: return "SATA 3.2";
548 case 6: return "SATA 3.1";
549 case 5: return "SATA 3.0";
550 case 4: return "SATA 2.6";
551 case 3: return "SATA 2.5";
552 case 2: return "SATA II Ext";
553 case 1: return "SATA 1.0a";
554 case 0: return "ATA8-AST";
559 static const char * get_sata_speed(int speed
)
564 default: return ">6.0 Gb/s (7)";
565 case 6: return ">6.0 Gb/s (6)";
566 case 5: return ">6.0 Gb/s (5)";
567 case 4: return ">6.0 Gb/s (4)";
568 case 3: return "6.0 Gb/s";
569 case 2: return "3.0 Gb/s";
570 case 1: return "1.5 Gb/s";
574 static void jset_sata_speed(const char * key
, int value
, int speed
, const char * str
)
578 json::ref jref
= jglb
["interface_speed"][key
];
579 jref
["sata_value"] = value
;
581 jref
["string"] = str
;
584 case 3: ups
= 60; break;
585 case 2: ups
= 30; break;
586 case 1: ups
= 15; break;
589 jref
["units_per_second"] = ups
;
590 jref
["bits_per_unit"] = 100000000;
593 static void print_sata_version_and_speed(unsigned short word222
,
594 unsigned short word076
,
595 unsigned short word077
)
597 int allspeeds
= (!(word076
& 0x0001) ? (word076
& 0x00fe) : 0);
598 int maxspeed
= (allspeeds
? find_msb(allspeeds
) : 0);
599 int curspeed
= (!(word077
& 0x0001) ? ((word077
>> 1) & 0x7) : 0);
601 const char * verstr
= get_sata_version(word222
);
602 const char * maxstr
= get_sata_speed(maxspeed
);
603 const char * curstr
= get_sata_speed(curspeed
);
604 jout("SATA Version is: %s%s%s%s%s%s\n",
605 (verstr
? verstr
: "Unknown"),
606 (maxstr
? ", " : ""), (maxstr
? maxstr
: ""),
607 (curstr
? " (current: " : ""), (curstr
? curstr
: ""),
608 (curstr
? ")" : ""));
610 jglb
["sata_version"]["string"] = verstr
;
611 jglb
["sata_version"]["value"] = word222
& 0x0fff;
612 jset_sata_speed("max", allspeeds
, maxspeed
, maxstr
);
613 jset_sata_speed("current", curspeed
, curspeed
, curstr
);
616 static void print_drive_info(const ata_identify_device
* drive
,
617 const ata_size_info
& sizes
, int rpm
,
618 const drive_settings
* dbentry
)
620 // format drive information (with byte swapping as needed)
621 char model
[40+1], serial
[20+1], firmware
[8+1];
622 ata_format_id_string(model
, drive
->model
, sizeof(model
)-1);
623 ata_format_id_string(serial
, drive
->serial_no
, sizeof(serial
)-1);
624 ata_format_id_string(firmware
, drive
->fw_rev
, sizeof(firmware
)-1);
626 // Print model family if known
627 if (dbentry
&& *dbentry
->modelfamily
) {
628 jout("Model Family: %s\n", dbentry
->modelfamily
);
629 jglb
["model_family"] = dbentry
->modelfamily
;
632 jout("Device Model: %s\n", infofound(model
));
633 jglb
["model_name"] = model
;
635 if (!dont_print_serial_number
) {
636 jout("Serial Number: %s\n", infofound(serial
));
637 jglb
["serial_number"] = serial
;
639 unsigned oui
= 0; uint64_t unique_id
= 0;
640 int naa
= ata_get_wwn(drive
, oui
, unique_id
);
642 jout("LU WWN Device Id: %x %06x %09" PRIx64
"\n", naa
, oui
, unique_id
);
643 jglb
["wwn"]["naa"] = naa
;
644 jglb
["wwn"]["oui"] = oui
;
645 jglb
["wwn"]["id"] = unique_id
;
649 // Additional Product Identifier (OEM Id) string in words 170-173
650 // (e08130r1, added in ACS-2 Revision 1, December 17, 2008)
651 if (0x2020 <= drive
->words088_255
[170-88] && drive
->words088_255
[170-88] <= 0x7e7e) {
653 ata_format_id_string(add
, (const unsigned char *)(drive
->words088_255
+170-88), sizeof(add
)-1);
655 jout("Add. Product Id: %s\n", add
);
656 jglb
["ata_additional_product_id"] = add
;
660 jout("Firmware Version: %s\n", infofound(firmware
));
661 jglb
["firmware_version"] = firmware
;
663 if (sizes
.capacity
) {
665 char num
[64], cap
[32];
666 jout("User Capacity: %s bytes [%s]\n",
667 format_with_thousands_sep(num
, sizeof(num
), sizes
.capacity
),
668 format_capacity(cap
, sizeof(cap
), sizes
.capacity
));
669 jglb
["user_capacity"]["blocks"].set_unsafe_uint64(sizes
.sectors
);
670 jglb
["user_capacity"]["bytes"].set_unsafe_uint64(sizes
.capacity
);
672 // Print sector sizes.
673 if (sizes
.phy_sector_size
== sizes
.log_sector_size
)
674 jout("Sector Size: %u bytes logical/physical\n", sizes
.log_sector_size
);
676 jout("Sector Sizes: %u bytes logical, %u bytes physical",
677 sizes
.log_sector_size
, sizes
.phy_sector_size
);
678 if (sizes
.log_sector_offset
)
679 pout(" (offset %u bytes)", sizes
.log_sector_offset
);
682 jglb
["logical_block_size"] = sizes
.log_sector_size
;
683 jglb
["physical_block_size"] = sizes
.phy_sector_size
;
686 // Print nominal media rotation rate if reported
689 jout("Rotation Rate: Solid State Device\n");
691 jout("Rotation Rate: %d rpm\n", rpm
);
693 pout("Rotation Rate: Unknown (0x%04x)\n", -rpm
);
695 jglb
["rotation_rate"] = (rpm
== 1 ? 0 : rpm
);
698 // Print form factor if reported
699 unsigned short word168
= drive
->words088_255
[168-88];
701 const char * form_factor
= get_form_factor(word168
);
703 jout("Form Factor: %s\n", form_factor
);
705 jout("Form Factor: Unknown (0x%04x)\n", word168
);
706 jglb
["form_factor"]["ata_value"] = word168
;
707 jglb
["form_factor"]["name"] = form_factor
;
710 // See if drive is recognized
711 jout("Device is: %s\n", !dbentry
?
712 "Not in smartctl database [for details use: -P showall]":
713 "In smartctl database [for details use: -P show]");
714 jglb
["in_smartctl_database"] = !!dbentry
;
718 if ( (drive
->major_rev_num
!= 0x0000 && drive
->major_rev_num
!= 0xffff)
719 || (drive
->minor_rev_num
!= 0x0000 && drive
->minor_rev_num
!= 0xffff)) {
720 const char * majorver
= get_ata_major_version(drive
);
721 const char * minorver
= get_ata_minor_version(drive
);
723 if (majorver
&& minorver
&& str_starts_with(minorver
, majorver
)) {
724 // Major and minor strings match, print minor string only
731 ataver
= strprintf("Unknown(0x%04x)", drive
->major_rev_num
);
734 ataver
+= strprintf(", %s", minorver
);
735 else if (drive
->minor_rev_num
!= 0x0000 && drive
->minor_rev_num
!= 0xffff)
736 ataver
+= strprintf(" (unknown minor revision code: 0x%04x)", drive
->minor_rev_num
);
738 ataver
+= " (minor revision not indicated)";
741 jout("ATA Version is: %s\n", infofound(ataver
.c_str()));
742 if (!ataver
.empty()) {
743 jglb
["ata_version"]["string"] = ataver
;
744 jglb
["ata_version"]["major_value"] = drive
->major_rev_num
;
745 jglb
["ata_version"]["minor_value"] = drive
->minor_rev_num
;
748 // Print Transport specific version
749 unsigned short word222
= drive
->words088_255
[222-88];
750 if (word222
!= 0x0000 && word222
!= 0xffff) switch (word222
>> 12) {
754 pout("Transport Type: Parallel, %s\n", get_pata_version(word222
, buf
));
758 print_sata_version_and_speed(word222
,
759 drive
->words047_079
[76-47],
760 drive
->words047_079
[77-47]);
762 case 0xe: // PCIe (ACS-4)
763 pout("Transport Type: PCIe (0x%03x)\n", word222
& 0x0fff);
766 pout("Transport Type: Unknown (0x%04x)\n", word222
);
770 // print current time and date and timezone
771 time_t now
= time(0);
772 char timedatetz
[DATEANDEPOCHLEN
]; dateandtimezoneepoch(timedatetz
, now
);
773 jout("Local Time is: %s\n", timedatetz
);
774 jglb
["local_time"]["time_t"] = now
;
775 jglb
["local_time"]["asctime"] = timedatetz
;
777 // Print warning message, if there is one
778 if (dbentry
&& *dbentry
->warningmsg
)
779 pout("\n==> WARNING: %s\n\n", dbentry
->warningmsg
);
782 static const char *OfflineDataCollectionStatus(unsigned char status_byte
)
784 unsigned char stat
=status_byte
& 0x7f;
788 return "was never started";
790 return "was completed without error";
792 if (status_byte
== 0x03)
793 return "is in progress";
795 return "is in a Reserved state";
797 return "was suspended by an interrupting command from host";
799 return "was aborted by an interrupting command from host";
801 return "was aborted by the device with a fatal error";
804 return "is in a Vendor Specific state";
806 return "is in a Reserved state";
811 // prints verbose value Off-line data collection status byte
812 static void PrintSmartOfflineStatus(const ata_smart_values
* data
)
814 json::ref jref
= jglb
["ata_smart_data"]["offline_data_collection"]["status"];
816 jout("Offline data collection status: (0x%02x)\t",
817 (int)data
->offline_data_collection_status
);
818 jref
["value"] = data
->offline_data_collection_status
;
820 // Off-line data collection status byte is not a reserved
821 // or vendor specific value
822 jout("Offline data collection activity\n"
823 "\t\t\t\t\t%s.\n", OfflineDataCollectionStatus(data
->offline_data_collection_status
));
824 jref
["string"] = OfflineDataCollectionStatus(data
->offline_data_collection_status
);
825 switch (data
->offline_data_collection_status
& 0x7f) {
826 case 0x02: jref
["passed"] = true; break;
827 case 0x06: jref
["passed"] = false; break;
830 // Report on Automatic Data Collection Status. Only IBM documents
831 // this bit. See SFF 8035i Revision 2 for details.
832 if (data
->offline_data_collection_status
& 0x80)
833 pout("\t\t\t\t\tAuto Offline Data Collection: Enabled.\n");
835 pout("\t\t\t\t\tAuto Offline Data Collection: Disabled.\n");
840 static void PrintSmartSelfExecStatus(const ata_smart_values
* data
,
841 firmwarebug_defs firmwarebugs
)
843 unsigned char status
= data
->self_test_exec_status
;
844 jout("Self-test execution status: ");
846 switch (data
->self_test_exec_status
>> 4) {
848 jout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status
);
849 jout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
852 jout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", status
);
856 jout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", status
);
857 jout("by the host with a hard or soft reset.\n");
860 jout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", status
);
861 jout("occurred while the device was executing\n\t\t\t\t\t");
862 jout("its self-test routine and the device \n\t\t\t\t\t");
863 jout("was unable to complete the self-test \n\t\t\t\t\t");
867 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status
);
868 jout("a test element that failed and the test\n\t\t\t\t\t");
869 jout("element that failed is not known.\n");
872 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status
);
873 jout("the electrical element of the test\n\t\t\t\t\t");
877 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status
);
878 jout("the servo (and/or seek) element of the \n\t\t\t\t\t");
879 jout("test failed.\n");
882 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status
);
883 jout("the read element of the test failed.\n");
886 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status
);
887 jout("a test element that failed and the\n\t\t\t\t\t");
888 jout("device is suspected of having handling\n\t\t\t\t\t");
892 if (firmwarebugs
.is_set(BUG_SAMSUNG3
) && data
->self_test_exec_status
== 0xf0) {
893 pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status
);
894 pout("with unknown result or self-test in\n\t\t\t\t\t");
895 pout("progress with less than 10%% remaining.\n");
898 jout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", status
);
899 jout("%1d0%% of test remaining.\n", status
& 0x0f);
903 jout("(%4d)\tReserved.\n", status
);
907 json::ref jref
= jglb
["ata_smart_data"]["self_test"]["status"];
909 jref
["value"] = status
;
911 // TODO: Use common function for smartctl/smartd
912 switch (status
>> 4) {
913 case 0x0: msg
= "completed without error"; break;
914 case 0x1: msg
= "was aborted by the host"; break;
915 case 0x2: msg
= "was interrupted by the host with a reset"; break;
916 case 0x3: msg
= "could not complete due to a fatal or unknown error"; break;
917 case 0x4: msg
= "completed with error (unknown test element)"; break;
918 case 0x5: msg
= "completed with error (electrical test element)"; break;
919 case 0x6: msg
= "completed with error (servo/seek test element)"; break;
920 case 0x7: msg
= "completed with error (read test element)"; break;
921 case 0x8: msg
= "completed with error (handling damage?)"; break;
925 jref
["string"] = msg
;
926 switch (status
>> 4) {
927 case 0x1: case 0x2: case 0x3: break; // aborted -> unknown
928 default: jref
["passed"] = ((status
>> 4) == 0x0);
931 else if ((status
>> 4) == 0xf) {
932 jref
["string"] = strprintf("in progress, %u0%% remaining", status
& 0xf);
933 jref
["remaining_percent"] = (status
& 0xf) * 10;
937 static void PrintSmartTotalTimeCompleteOffline (const ata_smart_values
* data
)
939 jout("Total time to complete Offline \n");
940 jout("data collection: \t\t(%5d) seconds.\n",
941 (int)data
->total_time_to_complete_off_line
);
943 jglb
["ata_smart_data"]["offline_data_collection"]["completion_seconds"] =
944 data
->total_time_to_complete_off_line
;
947 static void PrintSmartOfflineCollectCap(const ata_smart_values
*data
)
949 json::ref jref
= jglb
["ata_smart_data"]["capabilities"];
951 jout("Offline data collection\n");
952 jout("capabilities: \t\t\t (0x%02x) ",
953 (int)data
->offline_data_collection_capability
);
954 jref
["values"][0] = data
->offline_data_collection_capability
;
956 if (data
->offline_data_collection_capability
== 0x00){
957 jout("\tOffline data collection not supported.\n");
960 jout( "%s\n", isSupportExecuteOfflineImmediate(data
)?
961 "SMART execute Offline immediate." :
962 "No SMART execute Offline immediate.");
963 jref
["exec_offline_immediate_supported"] = isSupportExecuteOfflineImmediate(data
);
965 // TODO: Bit 1 is vendor specific
966 pout( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data
)?
967 "Auto Offline data collection on/off support.":
968 "No Auto Offline data collection support.");
970 jout( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data
)?
971 "Abort Offline collection upon new\n\t\t\t\t\tcommand.":
972 "Suspend Offline collection upon new\n\t\t\t\t\tcommand.");
973 jref
["offline_is_aborted_upon_new_cmd"] = isSupportOfflineAbort(data
);
975 jout( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data
)?
976 "Offline surface scan supported.":
977 "No Offline surface scan supported.");
978 jref
["offline_surface_scan_supported"] = isSupportOfflineSurfaceScan(data
);
980 jout( "\t\t\t\t\t%s\n", isSupportSelfTest(data
)?
981 "Self-test supported.":
982 "No Self-test supported.");
983 jref
["self_tests_supported"] = isSupportSelfTest(data
);
985 jout( "\t\t\t\t\t%s\n", isSupportConveyanceSelfTest(data
)?
986 "Conveyance Self-test supported.":
987 "No Conveyance Self-test supported.");
988 jref
["conveyance_self_test_supported"] = isSupportConveyanceSelfTest(data
);
990 jout( "\t\t\t\t\t%s\n", isSupportSelectiveSelfTest(data
)?
991 "Selective Self-test supported.":
992 "No Selective Self-test supported.");
993 jref
["selective_self_test_supported"] = isSupportSelectiveSelfTest(data
);
997 static void PrintSmartCapability(const ata_smart_values
*data
)
999 json::ref jref
= jglb
["ata_smart_data"]["capabilities"];
1001 jout("SMART capabilities: ");
1002 jout("(0x%04x)\t", (int)data
->smart_capability
);
1003 jref
["values"][1] = data
->smart_capability
;
1005 if (data
->smart_capability
== 0x00)
1006 jout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
1008 jout("%s\n", (data
->smart_capability
& 0x01)?
1009 "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
1010 "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
1011 jref
["attribute_autosave_enabled"] = !!(data
->smart_capability
& 0x01);
1013 // TODO: Info possibly invalid or misleading
1014 // ATA-3 - ATA-5: Bit shall be set
1015 // ATA-6 - ACS-3: Bit shall be set to indicate support for
1016 // SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE
1017 if (data
->smart_capability
& 0x02)
1018 pout("\t\t\t\t\tSupports SMART auto save timer.\n");
1022 static void PrintSmartErrorLogCapability(const ata_smart_values
* data
, const ata_identify_device
* identity
)
1024 bool capable
= isSmartErrorLogCapable(data
, identity
);
1025 jout("Error logging capability: (0x%02x)\tError logging %ssupported.\n",
1026 data
->errorlog_capability
, (capable
? "" : "NOT "));
1027 jglb
["ata_smart_data"]["capabilities"]["error_logging_supported"] = capable
;
1030 static void PrintSmartShortSelfTestPollingTime(const ata_smart_values
* data
)
1032 jout("Short self-test routine \n");
1033 if (isSupportSelfTest(data
)) {
1034 jout("recommended polling time: \t (%4d) minutes.\n",
1035 (int)data
->short_test_completion_time
);
1036 jglb
["ata_smart_data"]["self_test"]["polling_minutes"]["short"] =
1037 data
->short_test_completion_time
;
1040 jout("recommended polling time: \t Not Supported.\n");
1043 static void PrintSmartExtendedSelfTestPollingTime(const ata_smart_values
* data
)
1045 jout("Extended self-test routine\n");
1046 if (isSupportSelfTest(data
)) {
1047 jout("recommended polling time: \t (%4d) minutes.\n",
1048 TestTime(data
, EXTEND_SELF_TEST
));
1049 jglb
["ata_smart_data"]["self_test"]["polling_minutes"]["extended"] =
1050 TestTime(data
, EXTEND_SELF_TEST
);
1053 jout("recommended polling time: \t Not Supported.\n");
1056 static void PrintSmartConveyanceSelfTestPollingTime(const ata_smart_values
* data
)
1058 jout("Conveyance self-test routine\n");
1059 if (isSupportConveyanceSelfTest(data
)) {
1060 jout("recommended polling time: \t (%4d) minutes.\n",
1061 (int)data
->conveyance_test_completion_time
);
1062 jglb
["ata_smart_data"]["self_test"]["polling_minutes"]["conveyance"] =
1063 data
->conveyance_test_completion_time
;
1066 jout("recommended polling time: \t Not Supported.\n");
1069 // Check SMART attribute table for Threshold failure
1070 // onlyfailed=0: are or were any age or prefailure attributes <= threshold
1071 // onlyfailed=1: are any prefailure attributes <= threshold now
1072 static int find_failed_attr(const ata_smart_values
* data
,
1073 const ata_smart_thresholds_pvt
* thresholds
,
1074 const ata_vendor_attr_defs
& defs
, int onlyfailed
)
1076 for (int i
= 0; i
< NUMBER_ATA_SMART_ATTRIBUTES
; i
++) {
1077 const ata_smart_attribute
& attr
= data
->vendor_attributes
[i
];
1079 ata_attr_state state
= ata_get_attr_state(attr
, i
, thresholds
->thres_entries
, defs
);
1082 if (state
>= ATTRSTATE_FAILED_PAST
)
1086 if (state
== ATTRSTATE_FAILED_NOW
&& ATTRIBUTE_FLAGS_PREFAILURE(attr
.flags
))
1093 static void set_json_globals_from_smart_attrib(int id
, const char * name
,
1094 const ata_vendor_attr_defs
& defs
,
1099 if (!str_starts_with(name
, "Power_On_"))
1103 switch (defs
[id
].raw_format
) {
1104 case RAWFMT_DEFAULT
: case RAWFMT_RAW48
: case RAWFMT_RAW64
:
1105 case RAWFMT_RAW16_OPT_RAW16
: case RAWFMT_RAW24_OPT_RAW8
: break;
1106 case RAWFMT_SEC2HOUR
: minutes
= (rawval
/ 60) % 60; rawval
/= 60*60; break;
1107 case RAWFMT_MIN2HOUR
: minutes
= rawval
% 60; rawval
/= 60; break;
1108 case RAWFMT_HALFMIN2HOUR
: minutes
= (rawval
/ 2) % 60; rawval
/= 2*60; break;
1109 case RAWFMT_MSEC24_HOUR32
:
1110 minutes
= (int)(rawval
>> 32) / (1000*60);
1113 rawval
&= 0xffffffffULL
;
1117 if (rawval
> 0x00ffffffULL
)
1118 return; // assume bogus value
1119 jglb
["power_on_time"]["hours"] = rawval
;
1121 jglb
["power_on_time"]["minutes"] = minutes
;
1125 if (strcmp(name
, "Power_Cycle_Count"))
1127 switch (defs
[id
].raw_format
) {
1128 case RAWFMT_DEFAULT
: case RAWFMT_RAW48
: case RAWFMT_RAW64
:
1129 case RAWFMT_RAW16_OPT_RAW16
: case RAWFMT_RAW24_OPT_RAW8
: break;
1132 if (rawval
> 0x00ffffffULL
)
1133 return; // assume bogus value
1134 jglb
["power_cycle_count"] = rawval
;
1137 // Temperature set separately from ata_return_temperature_value() below
1141 // onlyfailed=0 : print all attribute values
1142 // onlyfailed=1: just ones that are currently failed and have prefailure bit set
1143 // onlyfailed=2: ones that are failed, or have failed with or without prefailure bit set
1144 static void PrintSmartAttribWithThres(const ata_smart_values
* data
,
1145 const ata_smart_thresholds_pvt
* thresholds
,
1146 const ata_vendor_attr_defs
& defs
, int rpm
,
1147 int onlyfailed
, unsigned char format
)
1149 bool brief
= !!(format
& ata_print_options::FMT_BRIEF
);
1150 bool hexid
= !!(format
& ata_print_options::FMT_HEX_ID
);
1151 bool hexval
= !!(format
& ata_print_options::FMT_HEX_VAL
);
1152 bool needheader
= true;
1154 // step through all vendor attributes
1155 for (int i
= 0, ji
= 0; i
< NUMBER_ATA_SMART_ATTRIBUTES
; i
++) {
1156 const ata_smart_attribute
& attr
= data
->vendor_attributes
[i
];
1158 // Check attribute and threshold
1159 unsigned char threshold
= 0;
1160 ata_attr_state state
= ata_get_attr_state(attr
, i
, thresholds
->thres_entries
, defs
, &threshold
);
1161 if (state
== ATTRSTATE_NON_EXISTING
)
1164 // These break out of the loop if we are only printing certain entries...
1165 if (onlyfailed
== 1 && !(ATTRIBUTE_FLAGS_PREFAILURE(attr
.flags
) && state
== ATTRSTATE_FAILED_NOW
))
1168 if (onlyfailed
== 2 && state
< ATTRSTATE_FAILED_PAST
)
1171 // print header only if needed
1174 jout("SMART Attributes Data Structure revision number: %d\n",(int)data
->revnumber
);
1175 jglb
["ata_smart_attributes"]["revision"] = data
->revnumber
;
1176 jout("Vendor Specific SMART Attributes with Thresholds:\n");
1179 jout("ID#%s ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n",
1180 (!hexid
? "" : " "));
1182 jout("ID#%s ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE\n",
1183 (!hexid
? "" : " "));
1187 // Format value, worst, threshold
1188 std::string valstr
, worstr
, threstr
;
1189 if (state
> ATTRSTATE_NO_NORMVAL
)
1190 valstr
= (!hexval
? strprintf("%.3d", attr
.current
)
1191 : strprintf("0x%02x", attr
.current
));
1193 valstr
= (!hexval
? "---" : "----");
1194 if (!(defs
[attr
.id
].flags
& ATTRFLAG_NO_WORSTVAL
))
1195 worstr
= (!hexval
? strprintf("%.3d", attr
.worst
)
1196 : strprintf("0x%02x", attr
.worst
));
1198 worstr
= (!hexval
? "---" : "----");
1199 if (state
> ATTRSTATE_NO_THRESHOLD
)
1200 threstr
= (!hexval
? strprintf("%.3d", threshold
)
1201 : strprintf("0x%02x", threshold
));
1203 threstr
= (!hexval
? "---" : "----");
1205 // Print line for each valid attribute
1206 std::string idstr
= (!hexid
? strprintf("%3d", attr
.id
)
1207 : strprintf("0x%02x", attr
.id
));
1208 std::string attrname
= ata_get_smart_attr_name(attr
.id
, defs
, rpm
);
1209 std::string rawstr
= ata_format_attr_raw_value(attr
, defs
);
1212 (ATTRIBUTE_FLAGS_PREFAILURE(attr
.flags
) ? 'P' : '-'),
1213 (ATTRIBUTE_FLAGS_ONLINE(attr
.flags
) ? 'O' : '-'),
1214 (ATTRIBUTE_FLAGS_PERFORMANCE(attr
.flags
) ? 'S' : '-'),
1215 (ATTRIBUTE_FLAGS_ERRORRATE(attr
.flags
) ? 'R' : '-'),
1216 (ATTRIBUTE_FLAGS_EVENTCOUNT(attr
.flags
) ? 'C' : '-'),
1217 (ATTRIBUTE_FLAGS_SELFPRESERVING(attr
.flags
) ? 'K' : '-'),
1218 (ATTRIBUTE_FLAGS_OTHER(attr
.flags
) ? '+' : ' '),
1223 jout("%s %-24s0x%04x %-4s %-4s %-4s %-10s%-9s%-12s%s\n",
1224 idstr
.c_str(), attrname
.c_str(), attr
.flags
,
1225 valstr
.c_str(), worstr
.c_str(), threstr
.c_str(),
1226 (ATTRIBUTE_FLAGS_PREFAILURE(attr
.flags
) ? "Pre-fail" : "Old_age"),
1227 (ATTRIBUTE_FLAGS_ONLINE(attr
.flags
) ? "Always" : "Offline"),
1228 (state
== ATTRSTATE_FAILED_NOW
? "FAILING_NOW" :
1229 state
== ATTRSTATE_FAILED_PAST
? "In_the_past"
1233 jout("%s %-24s%s %-4s %-4s %-4s %-5s%s\n",
1234 idstr
.c_str(), attrname
.c_str(), flagstr
,
1235 valstr
.c_str(), worstr
.c_str(), threstr
.c_str(),
1236 (state
== ATTRSTATE_FAILED_NOW
? "NOW" :
1237 state
== ATTRSTATE_FAILED_PAST
? "Past"
1241 if (!jglb
.is_enabled())
1244 json::ref jref
= jglb
["ata_smart_attributes"]["table"][ji
++];
1245 jref
["id"] = attr
.id
;
1246 jref
["name"] = attrname
;
1247 if (state
> ATTRSTATE_NO_NORMVAL
)
1248 jref
["value"] = attr
.current
;
1249 if (!(defs
[attr
.id
].flags
& ATTRFLAG_NO_WORSTVAL
))
1250 jref
["worst"] = attr
.worst
;
1251 if (state
> ATTRSTATE_NO_THRESHOLD
) {
1252 jref
["thresh"] = threshold
;
1253 jref
["when_failed"] = (state
== ATTRSTATE_FAILED_NOW
? "now" :
1254 state
== ATTRSTATE_FAILED_PAST
? "past"
1258 json::ref jreff
= jref
["flags"];
1259 jreff
["value"] = attr
.flags
;
1260 jreff
["string"] = flagstr
;
1261 jreff
["prefailure"] = !!ATTRIBUTE_FLAGS_PREFAILURE(attr
.flags
);
1262 jreff
["updated_online"] = !!ATTRIBUTE_FLAGS_ONLINE(attr
.flags
);
1263 jreff
["performance"] = !!ATTRIBUTE_FLAGS_PERFORMANCE(attr
.flags
);
1264 jreff
["error_rate"] = !!ATTRIBUTE_FLAGS_ERRORRATE(attr
.flags
);
1265 jreff
["event_count"] = !!ATTRIBUTE_FLAGS_EVENTCOUNT(attr
.flags
);
1266 jreff
["auto_keep"] = !!ATTRIBUTE_FLAGS_SELFPRESERVING(attr
.flags
);
1267 if (ATTRIBUTE_FLAGS_OTHER(attr
.flags
))
1268 jreff
["other"] = ATTRIBUTE_FLAGS_OTHER(attr
.flags
);
1270 uint64_t rawval
= ata_get_attr_raw_value(attr
, defs
);
1271 jref
["raw"]["value"] = rawval
;
1272 jref
["raw"]["string"] = rawstr
;
1274 set_json_globals_from_smart_attrib(attr
.id
, attrname
.c_str(), defs
, rawval
);
1278 if (!onlyfailed
&& brief
) {
1279 int n
= (!hexid
? 28 : 29);
1280 jout("%*s||||||_ K auto-keep\n"
1281 "%*s|||||__ C event count\n"
1282 "%*s||||___ R error rate\n"
1283 "%*s|||____ S speed/performance\n"
1284 "%*s||_____ O updated online\n"
1285 "%*s|______ P prefailure warning\n",
1286 n
, "", n
, "", n
, "", n
, "", n
, "", n
, "");
1291 if (!jglb
.is_enabled())
1294 // Protocol independent temperature
1295 unsigned char t
= ata_return_temperature_value(data
, defs
);
1297 jglb
["temperature"]["current"] = t
;
1300 // Print SMART related SCT capabilities
1301 static void ataPrintSCTCapability(const ata_identify_device
*drive
)
1303 unsigned short sctcaps
= drive
->words088_255
[206-88];
1304 if (!(sctcaps
& 0x01))
1306 json::ref jref
= jglb
["ata_sct_capabilities"];
1307 jout("SCT capabilities: \t (0x%04x)\tSCT Status supported.\n", sctcaps
);
1308 jref
["value"] = sctcaps
;
1310 jout("\t\t\t\t\tSCT Error Recovery Control supported.\n");
1311 jref
["error_recovery_control_supported"] = !!(sctcaps
& 0x08);
1313 jout("\t\t\t\t\tSCT Feature Control supported.\n");
1314 jref
["feature_control_supported"] = !!(sctcaps
& 0x10);
1316 jout("\t\t\t\t\tSCT Data Table supported.\n");
1317 jref
["data_table_supported"] = !!(sctcaps
& 0x20);
1321 static void PrintGeneralSmartValues(const ata_smart_values
*data
, const ata_identify_device
*drive
,
1322 firmwarebug_defs firmwarebugs
)
1324 jout("General SMART Values:\n");
1326 PrintSmartOfflineStatus(data
);
1328 if (isSupportSelfTest(data
)){
1329 PrintSmartSelfExecStatus(data
, firmwarebugs
);
1332 PrintSmartTotalTimeCompleteOffline(data
);
1333 PrintSmartOfflineCollectCap(data
);
1334 PrintSmartCapability(data
);
1336 PrintSmartErrorLogCapability(data
, drive
);
1338 jout( "\t\t\t\t\t%s\n", isGeneralPurposeLoggingCapable(drive
)?
1339 "General Purpose Logging supported.":
1340 "No General Purpose Logging support.");
1341 jglb
["ata_smart_data"]["capabilities"]["gp_logging_supported"] =
1342 isGeneralPurposeLoggingCapable(drive
);
1344 if (isSupportSelfTest(data
)){
1345 PrintSmartShortSelfTestPollingTime (data
);
1346 PrintSmartExtendedSelfTestPollingTime (data
);
1348 if (isSupportConveyanceSelfTest(data
))
1349 PrintSmartConveyanceSelfTestPollingTime (data
);
1351 ataPrintSCTCapability(drive
);
1356 // Get # sectors of a log addr, 0 if log does not exist.
1357 static unsigned GetNumLogSectors(const ata_smart_log_directory
* logdir
, unsigned logaddr
, bool gpl
)
1365 unsigned n
= logdir
->entry
[logaddr
-1].numsectors
;
1367 // GP logs may have >255 sectors
1368 n
|= logdir
->entry
[logaddr
-1].reserved
<< 8;
1373 static const char * GetLogName(unsigned logaddr
)
1375 // Table A.2 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
1376 // Table 112 of Serial ATA Revision 3.2, August 7, 2013
1377 // Table A.2 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
1378 // Table 204 of T13/BSR INCITS 529 (ACS-4) Revision 16, February 21, 2017
1380 case 0x00: return "Log Directory";
1381 case 0x01: return "Summary SMART error log";
1382 case 0x02: return "Comprehensive SMART error log";
1383 case 0x03: return "Ext. Comprehensive SMART error log";
1384 case 0x04: return "Device Statistics log";
1385 case 0x05: return "Reserved for CFA"; // ACS-2
1386 case 0x06: return "SMART self-test log";
1387 case 0x07: return "Extended self-test log";
1388 case 0x08: return "Power Conditions log"; // ACS-2
1389 case 0x09: return "Selective self-test log";
1390 case 0x0a: return "Device Statistics Notification"; // ACS-3
1391 case 0x0b: return "Reserved for CFA"; // ACS-3
1392 case 0x0c: return "Pending Defects log"; // ACS-4
1393 case 0x0d: return "LPS Mis-alignment log"; // ACS-2
1394 case 0x0e: return "Reserved for ZAC-2"; // ACS-4
1395 case 0x0f: return "Sense Data for Successful NCQ Cmds log"; // ACS-4
1396 case 0x10: return "NCQ Command Error log";
1397 case 0x11: return "SATA Phy Event Counters log";
1398 //case 0x12: return "SATA NCQ Queue Management log"; // SATA 3.0/3.1, ACS-3
1399 case 0x12: return "SATA NCQ Non-Data log"; // SATA 3.2, ACS-4
1400 case 0x13: return "SATA NCQ Send and Receive log"; // SATA 3.1, ACS-3
1401 case 0x14: return "Hybrid Information log"; // SATA 3.2, ACS-4
1402 case 0x15: return "Rebuild Assist log"; // SATA 3.2, ACS-4
1404 case 0x17: return "Reserved for Serial ATA";
1406 case 0x19: return "LBA Status log"; // ACS-3
1408 case 0x20: return "Streaming performance log [OBS-8]";
1409 case 0x21: return "Write stream error log";
1410 case 0x22: return "Read stream error log";
1411 case 0x23: return "Delayed sector log [OBS-8]";
1412 case 0x24: return "Current Device Internal Status Data log"; // ACS-3
1413 case 0x25: return "Saved Device Internal Status Data log"; // ACS-3
1415 case 0x2f: return "Set Sector Configuration";; // ACS-4
1416 case 0x30: return "IDENTIFY DEVICE data log"; // ACS-3
1418 case 0xe0: return "SCT Command/Status";
1419 case 0xe1: return "SCT Data Transfer";
1421 if (0xa0 <= logaddr
&& logaddr
<= 0xdf)
1422 return "Device vendor specific log";
1423 if (0x80 <= logaddr
&& logaddr
<= 0x9f)
1424 return "Host vendor specific log";
1430 // Get log access permissions
1431 static const char * get_log_rw(unsigned logaddr
)
1433 if ( ( logaddr
<= 0x08)
1434 || (0x0c <= logaddr
&& logaddr
<= 0x0d)
1435 || (0x0f <= logaddr
&& logaddr
<= 0x14)
1436 || (0x19 == logaddr
)
1437 || (0x20 <= logaddr
&& logaddr
<= 0x25)
1438 || (0x30 == logaddr
))
1441 if ( (0x09 <= logaddr
&& logaddr
<= 0x0a)
1442 || (0x15 == logaddr
)
1443 || (0x80 <= logaddr
&& logaddr
<= 0x9f)
1444 || (0xe0 <= logaddr
&& logaddr
<= 0xe1))
1447 if (0xa0 <= logaddr
&& logaddr
<= 0xdf)
1448 return "VS"; // Vendor specific
1450 return "-"; // Unknown/Reserved
1453 // Init a fake log directory, assume that standard logs are supported
1454 const ata_smart_log_directory
* fake_logdir(ata_smart_log_directory
* logdir
,
1455 const ata_print_options
& options
)
1457 memset(logdir
, 0, sizeof(*logdir
));
1458 logdir
->logversion
= 255;
1459 logdir
->entry
[0x01-1].numsectors
= 1;
1460 logdir
->entry
[0x03-1].numsectors
= (options
.smart_ext_error_log
+ (4-1)) / 4;
1461 logdir
->entry
[0x04-1].numsectors
= 8;
1462 logdir
->entry
[0x06-1].numsectors
= 1;
1463 logdir
->entry
[0x07-1].numsectors
= (options
.smart_ext_selftest_log
+ (19-1)) / 19;
1464 logdir
->entry
[0x09-1].numsectors
= 1;
1465 logdir
->entry
[0x11-1].numsectors
= 1;
1469 // Print SMART and/or GP Log Directory
1470 static void PrintLogDirectories(const ata_smart_log_directory
* gplogdir
,
1471 const ata_smart_log_directory
* smartlogdir
)
1473 json::ref jref
= jglb
["ata_log_directory"];
1475 jout("General Purpose Log Directory Version %u\n", gplogdir
->logversion
);
1476 jref
["gp_dir_version"] = gplogdir
->logversion
;
1479 jout("SMART %sLog Directory Version %u%s\n",
1480 (gplogdir
? " " : ""), smartlogdir
->logversion
,
1481 (smartlogdir
->logversion
==1 ? " [multi-sector log support]" : ""));
1482 jref
["smart_dir_version"] = smartlogdir
->logversion
;
1483 jref
["smart_dir_multi_sector"] = (smartlogdir
->logversion
== 1);
1486 jout("Address Access R/W Size Description\n");
1488 for (unsigned i
= 0, ji
= 0; i
<= 0xff; i
++) {
1489 // Get number of sectors
1490 unsigned smart_numsect
= GetNumLogSectors(smartlogdir
, i
, false);
1491 unsigned gp_numsect
= GetNumLogSectors(gplogdir
, i
, true );
1493 if (!(smart_numsect
|| gp_numsect
))
1494 continue; // Log does not exist
1496 const char * acc
; unsigned size
;
1497 if (smart_numsect
== gp_numsect
) {
1498 acc
= "GPL,SL"; size
= gp_numsect
;
1500 else if (!smart_numsect
) {
1501 acc
= "GPL"; size
= gp_numsect
;
1503 else if (!gp_numsect
) {
1504 acc
= " SL"; size
= smart_numsect
;
1511 if (acc
&& ((0x80 <= i
&& i
< 0x9f) || (0xa0 <= i
&& i
< 0xdf))) {
1512 // Find range of Host/Device vendor specific logs with same size
1513 unsigned imax
= (i
< 0x9f ? 0x9f : 0xdf);
1514 for (unsigned j
= i
+1; j
<= imax
; j
++) {
1515 unsigned sn
= GetNumLogSectors(smartlogdir
, j
, false);
1516 unsigned gn
= GetNumLogSectors(gplogdir
, j
, true );
1518 if (!(sn
== smart_numsect
&& gn
== gp_numsect
))
1524 const char * name
= GetLogName(i
);
1525 const char * rw
= get_log_rw(i
);
1528 jout("0x%02x-0x%02x %-6s %-3s %5u %s\n", i
, i2
, acc
, rw
, size
, name
);
1530 jout( "0x%02x %-6s %-3s %5u %s\n", i
, acc
, rw
, size
, name
);
1532 // GPL and SL support different sizes
1533 jout( "0x%02x %-6s %-3s %5u %s\n", i
, "GPL", rw
, gp_numsect
, name
);
1534 jout( "0x%02x %-6s %-3s %5u %s\n", i
, "SL", rw
, smart_numsect
, name
);
1538 json::ref jrefi
= jref
["table"][ji
++];
1539 jrefi
["address"] = i
;
1540 jrefi
["name"] = name
;
1541 if (rw
[0] == 'R' && rw
[1] && rw
[2]) {
1542 jrefi
["read"] = true;
1543 jrefi
["write"] = (rw
[2] == 'W');
1546 jrefi
["gp_sectors"] = gp_numsect
;
1548 jrefi
["smart_sectors"] = smart_numsect
;
1557 // Print hexdump of log pages.
1558 // Format is compatible with 'xxd -r'.
1559 static void PrintLogPages(const char * type
, const unsigned char * data
,
1560 unsigned char logaddr
, unsigned page
,
1561 unsigned num_pages
, unsigned max_pages
)
1563 pout("%s Log 0x%02x [%s], Page %u-%u (of %u)\n",
1564 type
, logaddr
, GetLogName(logaddr
), page
, page
+num_pages
-1, max_pages
);
1565 for (unsigned i
= 0; i
< num_pages
* 512; i
+= 16) {
1566 const unsigned char * p
= data
+i
;
1567 pout("%07x: %02x %02x %02x %02x %02x %02x %02x %02x "
1568 "%02x %02x %02x %02x %02x %02x %02x %02x ",
1570 p
[ 0], p
[ 1], p
[ 2], p
[ 3], p
[ 4], p
[ 5], p
[ 6], p
[ 7],
1571 p
[ 8], p
[ 9], p
[10], p
[11], p
[12], p
[13], p
[14], p
[15]);
1572 #define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.')
1573 pout("|%c%c%c%c%c%c%c%c"
1574 "%c%c%c%c%c%c%c%c|\n",
1575 P( 0), P( 1), P( 2), P( 3), P( 4), P( 5), P( 6), P( 7),
1576 P( 8), P( 9), P(10), P(11), P(12), P(13), P(14), P(15));
1578 if ((i
& 0x1ff) == 0x1f0)
1583 ///////////////////////////////////////////////////////////////////////
1584 // Device statistics (Log 0x04)
1586 // Section A.5 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
1587 // Section 9.5 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
1589 struct devstat_entry_info
1591 short size
; // #bytes of value, -1 for signed char
1595 const devstat_entry_info devstat_info_0x00
[] = {
1596 { 2, "List of supported log pages" },
1600 const devstat_entry_info devstat_info_0x01
[] = {
1601 { 2, "General Statistics" },
1602 { 4, "Lifetime Power-On Resets" },
1603 { 4, "Power-on Hours" },
1604 { 6, "Logical Sectors Written" },
1605 { 6, "Number of Write Commands" },
1606 { 6, "Logical Sectors Read" },
1607 { 6, "Number of Read Commands" },
1608 { 6, "Date and Time TimeStamp" }, // ACS-3
1609 { 4, "Pending Error Count" }, // ACS-4
1610 { 2, "Workload Utilization" }, // ACS-4
1611 { 6, "Utilization Usage Rate" }, // ACS-4 (TODO: field provides 3 values)
1612 { 2, "Resource Availability" }, // ACS-4
1613 { 1, "Random Write Resources Used" }, // ACS-4
1617 const devstat_entry_info devstat_info_0x02
[] = {
1618 { 2, "Free-Fall Statistics" },
1619 { 4, "Number of Free-Fall Events Detected" },
1620 { 4, "Overlimit Shock Events" },
1624 const devstat_entry_info devstat_info_0x03
[] = {
1625 { 2, "Rotating Media Statistics" },
1626 { 4, "Spindle Motor Power-on Hours" },
1627 { 4, "Head Flying Hours" },
1628 { 4, "Head Load Events" },
1629 { 4, "Number of Reallocated Logical Sectors" },
1630 { 4, "Read Recovery Attempts" },
1631 { 4, "Number of Mechanical Start Failures" },
1632 { 4, "Number of Realloc. Candidate Logical Sectors" }, // ACS-3
1633 { 4, "Number of High Priority Unload Events" }, // ACS-3
1637 const devstat_entry_info devstat_info_0x04
[] = {
1638 { 2, "General Errors Statistics" },
1639 { 4, "Number of Reported Uncorrectable Errors" },
1640 //{ 4, "Number of Resets Between Command Acceptance and Command Completion" },
1641 { 4, "Resets Between Cmd Acceptance and Completion" },
1642 { 4, "Physical Element Status Changed" }, // ACS-4
1646 const devstat_entry_info devstat_info_0x05
[] = {
1647 { 2, "Temperature Statistics" },
1648 { -1, "Current Temperature" },
1649 { -1, "Average Short Term Temperature" },
1650 { -1, "Average Long Term Temperature" },
1651 { -1, "Highest Temperature" },
1652 { -1, "Lowest Temperature" },
1653 { -1, "Highest Average Short Term Temperature" },
1654 { -1, "Lowest Average Short Term Temperature" },
1655 { -1, "Highest Average Long Term Temperature" },
1656 { -1, "Lowest Average Long Term Temperature" },
1657 { 4, "Time in Over-Temperature" },
1658 { -1, "Specified Maximum Operating Temperature" },
1659 { 4, "Time in Under-Temperature" },
1660 { -1, "Specified Minimum Operating Temperature" },
1664 const devstat_entry_info devstat_info_0x06
[] = {
1665 { 2, "Transport Statistics" },
1666 { 4, "Number of Hardware Resets" },
1667 { 4, "Number of ASR Events" },
1668 { 4, "Number of Interface CRC Errors" },
1672 const devstat_entry_info devstat_info_0x07
[] = {
1673 { 2, "Solid State Device Statistics" },
1674 { 1, "Percentage Used Endurance Indicator" },
1678 const devstat_entry_info
* devstat_infos
[] = {
1687 // TODO: 0x08 Zoned Device Statistics (T13/f16136r7, January 2017)
1690 const int num_devstat_infos
= sizeof(devstat_infos
)/sizeof(devstat_infos
[0]);
1692 static const char * get_device_statistics_page_name(int page
)
1694 if (page
< num_devstat_infos
)
1695 return devstat_infos
[page
][0].name
;
1697 return "Vendor Specific Statistics"; // ACS-4
1698 return "Unknown Statistics";
1701 static void set_json_globals_from_device_statistics(int page
, int offset
, int64_t val
)
1706 case 0x008: jglb
["power_cycle_count"] = val
; break; // ~= Lifetime Power-On Resets
1707 case 0x010: jglb
["power_on_time"]["hours"]= val
; break;
1712 case 0x008: jglb
["temperature"]["current"] = val
; break;
1713 case 0x020: jglb
["temperature"]["lifetime_max"] = val
; break;
1714 case 0x028: jglb
["temperature"]["lifetime_min"] = val
; break;
1715 case 0x050: jglb
["temperature"]["lifetime_over_limit_minutes"] = val
; break;
1716 case 0x058: jglb
["temperature"]["op_limit_max"] = val
; break;
1717 case 0x060: jglb
["temperature"]["lifetime_under_limit_minutes"] = val
; break;
1718 case 0x068: jglb
["temperature"]["op_limit_min"] = val
; break;
1724 static void print_device_statistics_page(const json::ref
& jref
, const unsigned char * data
, int page
)
1726 const devstat_entry_info
* info
= (page
< num_devstat_infos
? devstat_infos
[page
] : 0);
1727 const char * name
= get_device_statistics_page_name(page
);
1729 // Check page number in header
1730 static const char line
[] = " ===== = = === == ";
1732 pout("0x%02x%s%s (empty) ==\n", page
, line
, name
);
1735 if (data
[2] != page
) {
1736 pout("0x%02x%s%s (invalid page 0x%02x in header) ==\n", page
, line
, name
, data
[2]);
1740 int rev
= data
[0] | (data
[1] << 8);
1741 jout("0x%02x%s%s (rev %d) ==\n", page
, line
, name
, rev
);
1742 jref
["number"] = page
;
1743 jref
["name"] = name
;
1744 jref
["revision"] = rev
;
1748 for (int i
= 1, offset
= 8; offset
< 512-7; i
++, offset
+=8) {
1749 // Check for last known entry
1750 if (info
&& !info
[i
].size
)
1753 // Skip unsupported entries
1754 unsigned char flags
= data
[offset
+7];
1755 if (!(flags
& 0x80))
1758 // Stop if unknown entries contain garbage data due to buggy firmware
1759 if (!info
&& (data
[offset
+5] || data
[offset
+6])) {
1760 pout("0x%02x 0x%03x - - [Trailing garbage ignored]\n", page
, offset
);
1765 const char * valname
= (info
? info
[i
].name
:
1766 (page
== 0xff) ? "Vendor Specific" // ACS-4
1769 // Get value size, default to max if unknown
1770 int size
= (info
? info
[i
].size
: 7);
1772 // Get flags (supported flag already checked above)
1773 bool valid
= !!(flags
& 0x40);
1774 bool normalized
= !!(flags
& 0x20);
1775 bool supports_dsn
= !!(flags
& 0x10); // ACS-3
1776 bool monitored_condition_met
= !!(flags
& 0x08); // ACS-3
1777 unsigned char reserved_flags
= (flags
& 0x07);
1785 val
= (signed char)data
[offset
];
1788 for (int j
= 0; j
< size
; j
++)
1789 val
|= (int64_t)data
[offset
+j
] << (j
*8);
1791 snprintf(valstr
, sizeof(valstr
), "%" PRId64
, val
);
1794 // Value not known (yet)
1795 valstr
[0] = '-'; valstr
[1] = 0;
1799 (valid
? 'V' : '-'), // JSON only
1800 (normalized
? 'N' : '-'),
1801 (supports_dsn
? 'D' : '-'),
1802 (monitored_condition_met
? 'C' : '-'),
1803 (reserved_flags
? '+' : ' '),
1807 jout("0x%02x 0x%03x %d %15s %s %s\n",
1808 page
, offset
, abs(size
), valstr
, flagstr
+1, valname
);
1810 if (!jglb
.is_enabled())
1813 json::ref jrefi
= jref
["table"][ji
++];
1814 jrefi
["offset"] = offset
;
1815 jrefi
["name"] = valname
;
1816 jrefi
["size"] = abs(size
);
1818 jrefi
["value"] = val
; // TODO: May be unsafe JSON int if size > 6
1820 json::ref jreff
= jrefi
["flags"];
1821 jreff
["value"] = flags
;
1822 jreff
["string"] = flagstr
;
1823 jreff
["valid"] = valid
;
1824 jreff
["normalized"] = normalized
;
1825 jreff
["supports_dsn"] = supports_dsn
;
1826 jreff
["monitored_condition_met"] = monitored_condition_met
;
1828 jreff
["other"] = reserved_flags
;
1831 set_json_globals_from_device_statistics(page
, offset
, val
);
1835 static bool print_device_statistics(ata_device
* device
, unsigned nsectors
,
1836 const std::vector
<int> & single_pages
, bool all_pages
, bool ssd_page
,
1839 // Read list of supported pages from page 0
1840 unsigned char page_0
[512] = {0, };
1844 rc
= ataReadLogExt(device
, 0x04, 0, 0, page_0
, 1);
1846 rc
= ataReadSmartLog(device
, 0x04, page_0
, 1);
1848 jerr("Read Device Statistics page 0x00 failed\n\n");
1852 unsigned char nentries
= page_0
[8];
1853 if (!(page_0
[2] == 0 && nentries
> 0)) {
1854 jerr("Device Statistics page 0x00 is invalid (page=0x%02x, nentries=%d)\n\n", page_0
[2], nentries
);
1858 // Prepare list of pages to print
1859 std::vector
<int> pages
;
1862 // Add all supported pages
1863 for (i
= 0; i
< nentries
; i
++) {
1864 int page
= page_0
[8+1+i
];
1866 pages
.push_back(page
);
1870 // Add manually specified pages
1871 bool print_page_0
= false;
1872 for (i
= 0; i
< single_pages
.size() || ssd_page
; i
++) {
1873 int page
= (i
< single_pages
.size() ? single_pages
[i
] : 0x07);
1875 print_page_0
= true;
1876 else if (page
>= (int)nsectors
)
1877 pout("Device Statistics Log has only 0x%02x pages\n", nsectors
);
1879 pages
.push_back(page
);
1884 json::ref jref
= jglb
["ata_device_statistics"];
1886 // Print list of supported pages if requested
1888 pout("Device Statistics (%s Log 0x04) supported pages\n",
1889 use_gplog
? "GP" : "SMART");
1890 jout("Page Description\n");
1891 for (i
= 0; i
< nentries
; i
++) {
1892 int page
= page_0
[8+1+i
];
1893 const char * name
= get_device_statistics_page_name(page
);
1894 jout("0x%02x %s\n", page
, name
);
1895 jref
["supported_pages"][i
]["number"] = page
;
1896 jref
["supported_pages"][i
]["name"] = name
;
1901 // Read & print pages
1902 if (!pages
.empty()) {
1903 pout("Device Statistics (%s Log 0x04)\n",
1904 use_gplog
? "GP" : "SMART");
1905 jout("Page Offset Size Value Flags Description\n");
1909 for (i
= 0; i
< pages
.size(); i
++) {
1910 int page
= pages
[i
];
1911 if (max_page
< page
&& page
< 0xff)
1915 raw_buffer
pages_buf((max_page
+1) * 512);
1917 if (!use_gplog
&& !ataReadSmartLog(device
, 0x04, pages_buf
.data(), max_page
+1)) {
1918 jerr("Read Device Statistics pages 0x00-0x%02x failed\n\n", max_page
);
1923 for (i
= 0; i
< pages
.size(); i
++) {
1924 int page
= pages
[i
];
1926 if (!ataReadLogExt(device
, 0x04, 0, page
, pages_buf
.data(), 1)) {
1927 jerr("Read Device Statistics page 0x%02x failed\n\n", page
);
1931 else if (page
> max_page
)
1934 int offset
= (use_gplog
? 0 : page
* 512);
1935 print_device_statistics_page(jref
["pages"][ji
++], pages_buf
.data() + offset
, page
);
1938 jout("%32s|||_ C monitored condition met\n", "");
1939 jout("%32s||__ D supports DSN\n", "");
1940 jout("%32s|___ N normalized value\n\n", "");
1947 ///////////////////////////////////////////////////////////////////////
1948 // Pending Defects log (Log 0x0c)
1950 // Section 9.26 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
1952 static bool print_pending_defects_log(ata_device
* device
, unsigned nsectors
,
1953 unsigned max_entries
)
1955 // Read #entries from page 0
1956 unsigned char page_buf
[512] = {0, };
1957 if (!ataReadLogExt(device
, 0x0c, 0, 0, page_buf
, 1)) {
1958 pout("Read Pending Defects log page 0x00 failed\n\n");
1962 jout("Pending Defects log (GP Log 0x0c)\n");
1963 unsigned nentries
= sg_get_unaligned_le32(page_buf
);
1964 json::ref jref
= jglb
["ata_pending_defects_log"];
1965 jref
["size"] = nsectors
* 32 - 1;
1966 jref
["count"] = nentries
;
1968 jout("No Defects Logged\n\n");
1973 jout("Index LBA Hours\n");
1974 for (unsigned i
= 0, pi
= 1, page
= 0; i
< nentries
&& i
< max_entries
; i
++, pi
++) {
1975 // Read new page if required
1977 if (++page
>= nsectors
) {
1978 pout("Pending Defects count %u exceeds log size (#pages=%u)\n\n",
1979 nentries
, nsectors
);
1982 if (!ataReadLogExt(device
, 0x0c, 0, page
, page_buf
, 1)) {
1983 pout("Read Pending Defects log page 0x%02x failed\n\n", page
);
1989 const unsigned char * entry
= page_buf
+ 16 * pi
;
1990 unsigned hours
= sg_get_unaligned_le32(entry
);
1992 if (hours
!= 0xffffffffU
)
1993 snprintf(hourstr
, sizeof(hourstr
), "%u", hours
);
1995 hourstr
[0] = '-', hourstr
[1] = 0;
1996 uint64_t lba
= sg_get_unaligned_le64(entry
+ 8);
1997 jout("%5u %18" PRIu64
" %8s\n", i
, lba
, hourstr
);
1999 json::ref jrefi
= jref
["table"][i
];
2000 jrefi
["lba"].set_unsafe_uint64(lba
);
2001 if (hours
!= 0xffffffffU
)
2002 jrefi
["power_on_hours"] = hours
;
2005 if (nentries
> max_entries
)
2006 pout("... (%u entries not shown)\n", nentries
- max_entries
);
2012 ///////////////////////////////////////////////////////////////////////
2015 static void PrintSataPhyEventCounters(const unsigned char * data
, bool reset
)
2018 checksumwarning("SATA Phy Event Counters");
2019 jout("SATA Phy Event Counters (GP Log 0x11)\n");
2020 if (data
[0] || data
[1] || data
[2] || data
[3])
2021 pout("[Reserved: 0x%02x 0x%02x 0x%02x 0x%02x]\n",
2022 data
[0], data
[1], data
[2], data
[3]);
2023 jout("ID Size Value Description\n");
2025 for (unsigned i
= 4, ji
= 0; ; ) {
2026 // Get counter id and size (bits 14:12)
2027 unsigned id
= data
[i
] | (data
[i
+1] << 8);
2028 unsigned size
= ((id
>> 12) & 0x7) << 1;
2031 // End of counter table ?
2036 if (!(2 <= size
&& size
<= 8 && i
+ size
< 512)) {
2037 pout("0x%04x %u: Invalid entry\n", id
, size
);
2042 uint64_t val
= 0, max_val
= 0;
2043 for (unsigned j
= 0; j
< size
; j
+=2) {
2044 val
|= (uint64_t)(data
[i
+j
] | (data
[i
+j
+1] << 8)) << (j
*8);
2045 max_val
|= (uint64_t)0xffffU
<< (j
*8);
2052 case 0x001: name
= "Command failed due to ICRC error"; break; // Mandatory
2053 case 0x002: name
= "R_ERR response for data FIS"; break;
2054 case 0x003: name
= "R_ERR response for device-to-host data FIS"; break;
2055 case 0x004: name
= "R_ERR response for host-to-device data FIS"; break;
2056 case 0x005: name
= "R_ERR response for non-data FIS"; break;
2057 case 0x006: name
= "R_ERR response for device-to-host non-data FIS"; break;
2058 case 0x007: name
= "R_ERR response for host-to-device non-data FIS"; break;
2059 case 0x008: name
= "Device-to-host non-data FIS retries"; break;
2060 case 0x009: name
= "Transition from drive PhyRdy to drive PhyNRdy"; break;
2061 case 0x00A: name
= "Device-to-host register FISes sent due to a COMRESET"; break; // Mandatory
2062 case 0x00B: name
= "CRC errors within host-to-device FIS"; break;
2063 case 0x00D: name
= "Non-CRC errors within host-to-device FIS"; break;
2064 case 0x00F: name
= "R_ERR response for host-to-device data FIS, CRC"; break;
2065 case 0x010: name
= "R_ERR response for host-to-device data FIS, non-CRC"; break;
2066 case 0x012: name
= "R_ERR response for host-to-device non-data FIS, CRC"; break;
2067 case 0x013: name
= "R_ERR response for host-to-device non-data FIS, non-CRC"; break;
2068 default: name
= ((id
& 0x8000) ? "Vendor specific" : "Unknown"); break;
2071 // Counters stop at max value, add '+' in this case
2072 jout("0x%04x %u %12" PRIu64
"%c %s\n", id
, size
, val
,
2073 (val
== max_val
? '+' : ' '), name
);
2075 json::ref jref
= jglb
["sata_phy_event_counters"]["table"][ji
++];
2077 jref
["name"] = name
;
2078 jref
["size"] = size
;
2079 jref
["value"] = val
;
2080 jref
["overflow"] = (val
== max_val
);
2083 jout("All counters reset\n");
2085 jglb
["sata_phy_event_counters"]["reset"] = reset
;
2088 // Format milliseconds from error log entry as "DAYS+H:M:S.MSEC"
2089 static std::string
format_milliseconds(unsigned msec
)
2091 unsigned days
= msec
/ 86400000U;
2092 msec
-= days
* 86400000U;
2093 unsigned hours
= msec
/ 3600000U;
2094 msec
-= hours
* 3600000U;
2095 unsigned min
= msec
/ 60000U;
2096 msec
-= min
* 60000U;
2097 unsigned sec
= msec
/ 1000U;
2098 msec
-= sec
* 1000U;
2102 str
= strprintf("%2ud+", days
);
2103 str
+= strprintf("%02u:%02u:%02u.%03u", hours
, min
, sec
, msec
);
2107 // Get description for 'state' value from SMART Error Logs
2108 static const char * get_error_log_state_desc(unsigned state
)
2112 case 0x0: return "in an unknown state";
2113 case 0x1: return "sleeping";
2114 case 0x2: return "in standby mode";
2115 case 0x3: return "active or idle";
2116 case 0x4: return "doing SMART Offline or Self-test";
2118 return (state
< 0xb ? "in a reserved state"
2119 : "in a vendor specific state");
2123 // returns number of errors
2124 static int PrintSmartErrorlog(const ata_smart_errorlog
*data
,
2125 firmwarebug_defs firmwarebugs
)
2127 json::ref jref
= jglb
["ata_smart_error_log"]["summary"];
2128 jout("SMART Error Log Version: %d\n", (int)data
->revnumber
);
2129 jref
["revision"] = data
->revnumber
;
2131 // if no errors logged, return
2132 if (!data
->error_log_pointer
){
2133 jout("No Errors Logged\n\n");
2138 // If log pointer out of range, return
2139 if (data
->error_log_pointer
>5){
2140 pout("Invalid Error Log index = 0x%02x (T13/1321D rev 1c "
2141 "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n",
2142 (int)data
->error_log_pointer
);
2146 // Some internal consistency checking of the data structures
2147 if ((data
->ata_error_count
-data
->error_log_pointer
) % 5 && !firmwarebugs
.is_set(BUG_SAMSUNG2
)) {
2148 pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n",
2149 data
->ata_error_count
,data
->error_log_pointer
);
2152 // starting printing error log info
2153 if (data
->ata_error_count
<=5)
2154 jout( "ATA Error Count: %d\n", (int)data
->ata_error_count
);
2156 jout( "ATA Error Count: %d (device log contains only the most recent five errors)\n",
2157 (int)data
->ata_error_count
);
2158 jref
["count"] = data
->ata_error_count
;
2159 jref
["logged_count"] = (data
->ata_error_count
<= 5 ? data
->ata_error_count
: 5);
2162 jout("\tCR = Command Register [HEX]\n"
2163 "\tFR = Features Register [HEX]\n"
2164 "\tSC = Sector Count Register [HEX]\n"
2165 "\tSN = Sector Number Register [HEX]\n"
2166 "\tCL = Cylinder Low Register [HEX]\n"
2167 "\tCH = Cylinder High Register [HEX]\n"
2168 "\tDH = Device/Head Register [HEX]\n"
2169 "\tDC = Device Command Register [HEX]\n"
2170 "\tER = Error register [HEX]\n"
2171 "\tST = Status register [HEX]\n"
2172 "Powered_Up_Time is measured from power on, and printed as\n"
2173 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2174 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2176 // now step through the five error log data structures (table 39 of spec)
2177 for (int k
= 4, ji
= 0; k
>= 0; k
--) {
2179 // The error log data structure entries are a circular buffer
2180 int i
= (data
->error_log_pointer
+ k
) % 5;
2181 const ata_smart_errorlog_struct
* elog
= data
->errorlog_struct
+i
;
2182 const ata_smart_errorlog_error_struct
* summary
= &(elog
->error_struct
);
2184 // Spec says: unused error log structures shall be zero filled
2185 if (nonempty(elog
, sizeof(*elog
))){
2186 // Table 57 of T13/1532D Volume 1 Revision 3
2187 const char *msgstate
= get_error_log_state_desc(summary
->state
);
2188 int days
= (int)summary
->timestamp
/24;
2190 // See table 42 of ATA5 spec
2192 jout("Error %d occurred at disk power-on lifetime: %d hours (%d days + %d hours)\n",
2193 (int)(data
->ata_error_count
+k
-4), (int)summary
->timestamp
, days
, (int)(summary
->timestamp
-24*days
));
2196 json::ref jrefi
= jref
["table"][ji
++];
2197 jrefi
["error_number"] = data
->ata_error_count
+ k
- 4;
2198 jrefi
["lifetime_hours"] = summary
->timestamp
;
2200 jout(" When the command that caused the error occurred, the device was %s.\n\n", msgstate
);
2201 jout(" After command completion occurred, registers were:\n"
2202 " ER ST SC SN CL CH DH\n"
2203 " -- -- -- -- -- -- --\n"
2204 " %02x %02x %02x %02x %02x %02x %02x",
2205 (int)summary
->error_register
,
2206 (int)summary
->status
,
2207 (int)summary
->sector_count
,
2208 (int)summary
->sector_number
,
2209 (int)summary
->cylinder_low
,
2210 (int)summary
->cylinder_high
,
2211 (int)summary
->drive_head
);
2214 json::ref jrefir
= jrefi
["completion_registers"];
2215 jrefir
["error"] = summary
->error_register
;
2216 jrefir
["status"] = summary
->status
;
2217 jrefir
["count"] = summary
->sector_count
;
2218 jrefir
["lba"] = (summary
->sector_number
)
2219 | (summary
->cylinder_low
<< 8)
2220 | (summary
->cylinder_high
<< 16);
2221 jrefir
["device"] = summary
->drive_head
;
2224 // Add a description of the contents of the status and error registers
2226 std::string st_er_desc
= format_st_er_desc(elog
);
2227 if (!st_er_desc
.empty()) {
2228 jout(" %s", st_er_desc
.c_str());
2229 jrefi
["error_description"] = st_er_desc
;
2232 jout(" Commands leading to the command that caused the error were:\n"
2233 " CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n"
2234 " -- -- -- -- -- -- -- -- ---------------- --------------------\n");
2235 for (int j
= 4, jj
= 0; j
>= 0; j
--) {
2236 const ata_smart_errorlog_command_struct
* thiscommand
= elog
->commands
+j
;
2238 // Spec says: unused data command structures shall be zero filled
2239 if (nonempty(thiscommand
, sizeof(*thiscommand
))) {
2240 const char * atacmd
= look_up_ata_command(thiscommand
->commandreg
, thiscommand
->featuresreg
);
2241 jout(" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2242 (int)thiscommand
->commandreg
,
2243 (int)thiscommand
->featuresreg
,
2244 (int)thiscommand
->sector_count
,
2245 (int)thiscommand
->sector_number
,
2246 (int)thiscommand
->cylinder_low
,
2247 (int)thiscommand
->cylinder_high
,
2248 (int)thiscommand
->drive_head
,
2249 (int)thiscommand
->devicecontrolreg
,
2250 format_milliseconds(thiscommand
->timestamp
).c_str(),
2253 json::ref jrefic
= jrefi
["previous_commands"][jj
++];
2254 json::ref jreficr
= jrefic
["registers"];
2255 jreficr
["command"] = thiscommand
->commandreg
;
2256 jreficr
["features"] = thiscommand
->featuresreg
,
2257 jreficr
["count"] = thiscommand
->sector_count
;
2258 jreficr
["lba"] = (thiscommand
->sector_number
)
2259 | (thiscommand
->cylinder_low
<< 8)
2260 | (thiscommand
->cylinder_high
<< 16);
2261 jreficr
["device"] = thiscommand
->drive_head
;
2262 jreficr
["device_control"] = thiscommand
->devicecontrolreg
;
2263 jrefic
["powerup_milliseconds"] = thiscommand
->timestamp
;
2264 jrefic
["command_name"] = atacmd
;
2271 if (printing_is_switchable
)
2274 return data
->ata_error_count
;
2277 // Print SMART Extended Comprehensive Error Log (GP Log 0x03)
2278 static int PrintSmartExtErrorLog(ata_device
* device
,
2279 const firmwarebug_defs
& firmwarebugs
,
2280 const ata_smart_exterrlog
* log
,
2281 unsigned nsectors
, unsigned max_errors
)
2283 json::ref jref
= jglb
["ata_smart_error_log"]["extended"];
2284 jout("SMART Extended Comprehensive Error Log Version: %u (%u sectors)\n",
2285 log
->version
, nsectors
);
2286 jref
["revision"] = log
->version
;
2287 jref
["sectors"] = nsectors
;
2289 if (!log
->device_error_count
) {
2290 jout("No Errors Logged\n\n");
2297 unsigned nentries
= nsectors
* 4;
2298 unsigned erridx
= log
->error_log_index
;
2299 if (!(1 <= erridx
&& erridx
<= nentries
)){
2300 // Some Samsung disks (at least SP1614C/SW100-25, HD300LJ/ZT100-12) use the
2301 // former index from Summary Error Log (byte 1, now reserved) and set byte 2-3
2303 if (!(erridx
== 0 && 1 <= log
->reserved1
&& log
->reserved1
<= nentries
)) {
2304 pout("Invalid Error Log index = 0x%04x (reserved = 0x%02x)\n", erridx
, log
->reserved1
);
2307 pout("Invalid Error Log index = 0x%04x, trying reserved byte (0x%02x) instead\n", erridx
, log
->reserved1
);
2308 erridx
= log
->reserved1
;
2311 // Index base is not clearly specified by ATA8-ACS (T13/1699-D Revision 6a),
2312 // it is 1-based in practice.
2315 // Calculate #errors to print
2316 unsigned errcnt
= log
->device_error_count
;
2318 if (errcnt
<= nentries
)
2319 jout("Device Error Count: %u\n", log
->device_error_count
);
2322 jout("Device Error Count: %u (device log contains only the most recent %u errors)\n",
2323 log
->device_error_count
, errcnt
);
2325 jref
["count"] = log
->device_error_count
;
2326 jref
["logged_count"] = errcnt
;
2328 if (max_errors
< errcnt
)
2329 errcnt
= max_errors
;
2332 jout("\tCR = Command Register\n"
2333 "\tFEATR = Features Register\n"
2334 "\tCOUNT = Count (was: Sector Count) Register\n"
2335 "\tLBA_48 = Upper bytes of LBA High/Mid/Low Registers ] ATA-8\n"
2336 "\tLH = LBA High (was: Cylinder High) Register ] LBA\n"
2337 "\tLM = LBA Mid (was: Cylinder Low) Register ] Register\n"
2338 "\tLL = LBA Low (was: Sector Number) Register ]\n"
2339 "\tDV = Device (was: Device/Head) Register\n"
2340 "\tDC = Device Control Register\n"
2341 "\tER = Error register\n"
2342 "\tST = Status register\n"
2343 "Powered_Up_Time is measured from power on, and printed as\n"
2344 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2345 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2347 // Recently read log page
2348 ata_smart_exterrlog log_buf
;
2349 unsigned log_buf_page
= ~0;
2351 // Iterate through circular buffer in reverse direction
2352 for (unsigned i
= 0, errnum
= log
->device_error_count
;
2353 i
< errcnt
; i
++, errnum
--, erridx
= (erridx
> 0 ? erridx
- 1 : nentries
- 1)) {
2355 // Read log page if needed
2356 const ata_smart_exterrlog
* log_p
;
2357 unsigned page
= erridx
/ 4;
2361 if (page
!= log_buf_page
) {
2362 memset(&log_buf
, 0, sizeof(log_buf
));
2363 if (!ataReadExtErrorLog(device
, &log_buf
, page
, 1, firmwarebugs
))
2365 log_buf_page
= page
;
2370 const ata_smart_exterrlog_error_log
& entry
= log_p
->error_logs
[erridx
% 4];
2372 json::ref jrefi
= jref
["table"][i
];
2373 jrefi
["error_number"] = errnum
;
2374 jrefi
["log_index"] = erridx
;
2376 // Skip unused entries
2377 if (!nonempty(&entry
, sizeof(entry
))) {
2378 jout("Error %u [%u] log entry is empty\n", errnum
, erridx
);
2382 // Print error information
2384 const ata_smart_exterrlog_error
& err
= entry
.error
;
2385 jout("Error %u [%u] occurred at disk power-on lifetime: %u hours (%u days + %u hours)\n",
2386 errnum
, erridx
, err
.timestamp
, err
.timestamp
/ 24, err
.timestamp
% 24);
2388 jrefi
["lifetime_hours"] = err
.timestamp
;
2390 const char * msgstate
= get_error_log_state_desc(err
.state
);
2391 jout(" When the command that caused the error occurred, the device was %s.\n\n", msgstate
);
2392 jrefi
["device_state"]["value"] = err
.state
;
2393 jrefi
["device_state"]["string"] = msgstate
;
2396 jout(" After command completion occurred, registers were:\n"
2397 " ER -- ST COUNT LBA_48 LH LM LL DV DC\n"
2398 " -- -- -- == -- == == == -- -- -- -- --\n"
2399 " %02x -- %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
2401 err
.status_register
,
2402 err
.count_register_hi
,
2404 err
.lba_high_register_hi
,
2405 err
.lba_mid_register_hi
,
2406 err
.lba_low_register_hi
,
2407 err
.lba_high_register
,
2408 err
.lba_mid_register
,
2409 err
.lba_low_register
,
2410 err
.device_register
,
2411 err
.device_control_register
);
2414 json::ref jrefir
= jrefi
["completion_registers"];
2415 jrefir
["error"] = err
.error_register
;
2416 jrefir
["status"] = err
.status_register
,
2417 jrefir
["count"] = (err
.count_register_hi
<< 8) | err
.count_register
;
2418 jrefir
["lba"] = ((uint64_t)err
.lba_high_register_hi
<< 40)
2419 | ((uint64_t)err
.lba_mid_register_hi
<< 32)
2420 | ((uint64_t)err
.lba_low_register_hi
<< 24)
2421 | ((unsigned)err
.lba_high_register
<< 16)
2422 | ((unsigned)err
.lba_mid_register
<< 8)
2423 | ((unsigned)err
.lba_low_register
);
2424 jrefir
["device"] = err
.device_register
;
2425 jrefir
["device_control"] = err
.device_control_register
;
2428 // Add a description of the contents of the status and error registers
2430 std::string st_er_desc
= format_st_er_desc(&entry
);
2431 if (!st_er_desc
.empty()) {
2432 jout(" %s", st_er_desc
.c_str());
2433 jrefi
["error_description"] = st_er_desc
;
2437 // Print command history
2438 jout(" Commands leading to the command that caused the error were:\n"
2439 " CR FEATR COUNT LBA_48 LH LM LL DV DC Powered_Up_Time Command/Feature_Name\n"
2440 " -- == -- == -- == == == -- -- -- -- -- --------------- --------------------\n");
2441 for (int ci
= 4, cji
= 0; ci
>= 0; ci
--) {
2442 const ata_smart_exterrlog_command
& cmd
= entry
.commands
[ci
];
2444 // Skip unused entries
2445 if (!nonempty(&cmd
, sizeof(cmd
)))
2448 // Print registers, timestamp and ATA command name
2449 const char * atacmd
= look_up_ata_command(cmd
.command_register
, cmd
.features_register
);
2450 jout(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2451 cmd
.command_register
,
2452 cmd
.features_register_hi
,
2453 cmd
.features_register
,
2454 cmd
.count_register_hi
,
2456 cmd
.lba_high_register_hi
,
2457 cmd
.lba_mid_register_hi
,
2458 cmd
.lba_low_register_hi
,
2459 cmd
.lba_high_register
,
2460 cmd
.lba_mid_register
,
2461 cmd
.lba_low_register
,
2462 cmd
.device_register
,
2463 cmd
.device_control_register
,
2464 format_milliseconds(cmd
.timestamp
).c_str(),
2467 json::ref jrefic
= jrefi
["previous_commands"][cji
++];
2468 json::ref jreficr
= jrefic
["registers"];
2469 jreficr
["command"] = cmd
.command_register
;
2470 jreficr
["features"] = (cmd
.features_register_hi
<< 8) | cmd
.features_register
;
2471 jreficr
["count"] = (cmd
.count_register_hi
<< 8) | cmd
.count_register
;
2472 jreficr
["lba"] = ((uint64_t)cmd
.lba_high_register_hi
<< 40)
2473 | ((uint64_t)cmd
.lba_mid_register_hi
<< 32)
2474 | ((uint64_t)cmd
.lba_low_register_hi
<< 24)
2475 | ((unsigned)cmd
.lba_high_register
<< 16)
2476 | ((unsigned)cmd
.lba_mid_register
<< 8)
2477 | ((unsigned)cmd
.lba_low_register
);
2478 jreficr
["device"] = cmd
.device_register
;
2479 jreficr
["device_control"] = cmd
.device_control_register
;
2480 jrefic
["powerup_milliseconds"] = cmd
.timestamp
;
2481 jrefic
["command_name"] = atacmd
;
2487 if (printing_is_switchable
)
2490 return log
->device_error_count
;
2493 // Print one self-test log entry.
2495 // -1: self-test failed
2496 // 1: extended self-test completed without error
2498 static int ataPrintSmartSelfTestEntry(const json::ref
& jref
,
2499 unsigned testnum
, unsigned char test_type
,
2500 unsigned char test_status
,
2501 unsigned short timestamp
,
2502 uint64_t failing_lba
,
2503 bool print_error_only
, bool & print_header
)
2505 // Check status and type for return value
2507 switch (test_status
>> 4) {
2509 if ((test_type
& 0x7f) == 0x02)
2510 retval
= 1; // extended self-test completed without error
2515 retval
= -1; // self-test failed
2519 if (retval
>= 0 && print_error_only
)
2522 std::string msgtest
;
2523 switch (test_type
) {
2524 case 0x00: msgtest
= "Offline"; break;
2525 case 0x01: msgtest
= "Short offline"; break;
2526 case 0x02: msgtest
= "Extended offline"; break;
2527 case 0x03: msgtest
= "Conveyance offline"; break;
2528 case 0x04: msgtest
= "Selective offline"; break;
2529 case 0x7f: msgtest
= "Abort offline test"; break;
2530 case 0x81: msgtest
= "Short captive"; break;
2531 case 0x82: msgtest
= "Extended captive"; break;
2532 case 0x83: msgtest
= "Conveyance captive"; break;
2533 case 0x84: msgtest
= "Selective captive"; break;
2535 if ((0x40 <= test_type
&& test_type
<= 0x7e) || 0x90 <= test_type
)
2536 msgtest
= strprintf("Vendor (0x%02x)", test_type
);
2538 msgtest
= strprintf("Reserved (0x%02x)", test_type
);
2541 std::string msgstat
;
2542 switch (test_status
>> 4) {
2543 case 0x0: msgstat
= "Completed without error"; break;
2544 case 0x1: msgstat
= "Aborted by host"; break;
2545 case 0x2: msgstat
= "Interrupted (host reset)"; break;
2546 case 0x3: msgstat
= "Fatal or unknown error"; break;
2547 case 0x4: msgstat
= "Completed: unknown failure"; break;
2548 case 0x5: msgstat
= "Completed: electrical failure"; break;
2549 case 0x6: msgstat
= "Completed: servo/seek failure"; break;
2550 case 0x7: msgstat
= "Completed: read failure"; break;
2551 case 0x8: msgstat
= "Completed: handling damage??"; break;
2552 case 0xf: msgstat
= "Self-test routine in progress"; break;
2553 default: msgstat
= strprintf("Unknown status (0x%x)", test_status
>> 4);
2556 // Print header once
2558 print_header
= false;
2559 jout("Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n");
2563 if (retval
< 0 && failing_lba
< 0xffffffffffffULL
)
2564 snprintf(msglba
, sizeof(msglba
), "%" PRIu64
, failing_lba
);
2566 msglba
[0] = '-'; msglba
[1] = 0;
2569 jout("#%2u %-19s %-29s %1d0%% %8u %s\n", testnum
,
2570 msgtest
.c_str(), msgstat
.c_str(), test_status
& 0x0f, timestamp
, msglba
);
2572 jref
["type"]["value"] = test_type
;
2573 jref
["type"]["string"] = msgtest
;
2575 jref
["status"]["value"] = test_status
;
2576 jref
["status"]["string"] = msgstat
;
2577 if (test_status
& 0x0f)
2578 jref
["status"]["remaining_percent"] = (test_status
& 0x0f) * 10;
2579 switch (test_status
>> 4) {
2580 case 0x1: case 0x2: case 0x3: break; // aborted -> unknown
2581 default: jref
["status"]["passed"] = (retval
>= 0);
2584 jref
["lifetime_hours"] = timestamp
;
2586 if (retval
< 0 && failing_lba
< 0xffffffffffffULL
)
2587 jref
["lba"] = failing_lba
;
2592 // Print SMART Self-test log, return error count
2593 static int ataPrintSmartSelfTestlog(const ata_smart_selftestlog
* log
, bool allentries
,
2594 firmwarebug_defs firmwarebugs
)
2596 json::ref jref
= jglb
["ata_smart_self_test_log"]["standard"];
2599 jout("SMART Self-test log structure revision number %d\n", log
->revnumber
);
2600 jref
["revision"] = log
->revnumber
;
2601 if (log
->revnumber
!= 0x0001 && allentries
&& !firmwarebugs
.is_set(BUG_SAMSUNG
))
2602 pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
2603 if (!log
->mostrecenttest
){
2605 jout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n");
2610 bool noheaderprinted
= true;
2611 int errcnt
= 0, igncnt
= 0;
2612 int testnum
= 1, ext_ok_testnum
= -1;
2614 // Iterate through circular buffer in reverse direction
2615 for (int i
= 20, ji
= 0; i
>= 0; i
--) {
2616 int j
= (i
+ log
->mostrecenttest
) % 21;
2617 const ata_smart_selftestlog_struct
& entry
= log
->selftest_struct
[j
];
2619 // Skip unused entries
2620 if (!nonempty(&entry
, sizeof(entry
)))
2624 uint64_t lba48
= (entry
.lbafirstfailure
< 0xffffffff ?
2625 entry
.lbafirstfailure
: 0xffffffffffffULL
);
2628 int state
= ataPrintSmartSelfTestEntry(jref
["table"][ji
++],
2629 testnum
, entry
.selftestnumber
, entry
.selfteststatus
,
2630 entry
.timestamp
, lba48
, !allentries
, noheaderprinted
);
2633 // Self-test showed an error
2634 if (ext_ok_testnum
< 0)
2637 // Newer successful extended self-test exits
2640 else if (state
> 0 && ext_ok_testnum
< 0) {
2641 // Latest successful extended self-test
2642 ext_ok_testnum
= testnum
;
2648 jout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2649 igncnt
, igncnt
+errcnt
, ext_ok_testnum
);
2650 jref
["count"] = testnum
- 1;
2651 jref
["error_count_total"] = igncnt
+ errcnt
;
2652 jref
["error_count_outdated"] = igncnt
;
2654 if (!allentries
&& !noheaderprinted
)
2660 // Print SMART Extended Self-test Log (GP Log 0x07)
2661 static int PrintSmartExtSelfTestLog(const ata_smart_extselftestlog
* log
,
2662 unsigned nsectors
, unsigned max_entries
)
2664 json::ref jref
= jglb
["ata_smart_self_test_log"]["extended"];
2666 jout("SMART Extended Self-test Log Version: %u (%u sectors)\n",
2667 log
->version
, nsectors
);
2668 jref
["revision"] = log
->version
;
2669 jref
["sectors"] = nsectors
;
2671 if (!log
->log_desc_index
){
2672 jout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n\n");
2678 unsigned nentries
= nsectors
* 19;
2679 unsigned logidx
= log
->log_desc_index
;
2680 if (logidx
> nentries
) {
2681 pout("Invalid Self-test Log index = 0x%04x (reserved = 0x%02x)\n", logidx
, log
->reserved1
);
2685 // Index base is not clearly specified by ATA8-ACS (T13/1699-D Revision 6a),
2686 // it is 1-based in practice.
2689 bool print_header
= true;
2690 int errcnt
= 0, igncnt
= 0;
2691 int ext_ok_testnum
= -1;
2692 unsigned testnum
= 1;
2694 // Iterate through circular buffer in reverse direction
2695 for (unsigned i
= 0, ji
= 0; i
< nentries
&& testnum
<= max_entries
;
2696 i
++, logidx
= (logidx
> 0 ? logidx
- 1 : nentries
- 1)) {
2698 const ata_smart_extselftestlog_desc
& entry
= log
[logidx
/ 19].log_descs
[logidx
% 19];
2700 // Skip unused entries
2701 if (!nonempty(&entry
, sizeof(entry
)))
2705 const unsigned char * b
= entry
.failing_lba
;
2706 uint64_t lba48
= b
[0]
2709 | ((uint64_t)b
[3] << 24)
2710 | ((uint64_t)b
[4] << 32)
2711 | ((uint64_t)b
[5] << 40);
2714 int state
= ataPrintSmartSelfTestEntry(jref
["table"][ji
++],
2715 testnum
, entry
.self_test_type
,
2716 entry
.self_test_status
, entry
.timestamp
, lba48
,
2717 false /*!print_error_only*/, print_header
);
2720 // Self-test showed an error
2721 if (ext_ok_testnum
< 0)
2724 // Newer successful extended self-test exits
2727 else if (state
> 0 && ext_ok_testnum
< 0) {
2728 // Latest successful extended self-test
2729 ext_ok_testnum
= testnum
;
2735 jout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2736 igncnt
, igncnt
+errcnt
, ext_ok_testnum
);
2737 jref
["count"] = testnum
- 1;
2738 jref
["error_count_total"] = igncnt
+ errcnt
;
2739 jref
["error_count_outdated"] = igncnt
;
2745 static void ataPrintSelectiveSelfTestLog(const ata_selective_self_test_log
* log
, const ata_smart_values
* sv
)
2747 json::ref jref
= jglb
["ata_smart_selective_self_test_log"];
2749 // print data structure revision number
2750 jout("SMART Selective self-test log data structure revision number %d\n", log
->logversion
);
2751 jref
["revision"] = log
->logversion
;
2752 if (1 != log
->logversion
)
2753 pout("Note: revision number not 1 implies that no selective self-test has ever been run\n");
2756 switch((sv
->self_test_exec_status
)>>4){
2757 case 0:msg
="Completed";
2759 case 1:msg
="Aborted_by_host";
2761 case 2:msg
="Interrupted";
2763 case 3:msg
="Fatal_error";
2765 case 4:msg
="Completed_unknown_failure";
2767 case 5:msg
="Completed_electrical_failure";
2769 case 6:msg
="Completed_servo/seek_failure";
2771 case 7:msg
="Completed_read_failure";
2773 case 8:msg
="Completed_handling_damage??";
2775 case 15:msg
="Self_test_in_progress";
2777 default:msg
="Unknown_status ";
2781 // find the number of columns needed for printing. If in use, the
2782 // start/end of span being read-scanned...
2783 uint64_t maxl
= 0, maxr
= 0;
2784 uint64_t current
= log
->currentlba
;
2785 uint64_t currentend
= current
+ 0xffff;
2786 if (log
->currentspan
>5) {
2790 for (int i
= 0; i
< 5; i
++) {
2791 uint64_t start
=log
->span
[i
].start
;
2792 uint64_t end
=log
->span
[i
].end
;
2793 // ... plus max start/end of each of the five test spans.
2800 // we need at least 7 characters wide fields to accommodate the
2804 if ((field1
=snprintf(tmp
,64, "%" PRIu64
, maxl
))<7)
2806 if ((field2
=snprintf(tmp
,64, "%" PRIu64
, maxr
))<7)
2809 // now print the five test spans
2810 jout(" SPAN %*s %*s CURRENT_TEST_STATUS\n", field1
, "MIN_LBA", field2
, "MAX_LBA");
2812 for (int i
= 0; i
< 5; i
++) {
2813 uint64_t start
=log
->span
[i
].start
;
2814 uint64_t end
=log
->span
[i
].end
;
2815 bool active
= (i
+ 1 == log
->currentspan
);
2818 // this span is currently under test
2819 jout(" %d %*" PRIu64
" %*" PRIu64
" %s [%01d0%% left] (%" PRIu64
"-%" PRIu64
")\n",
2820 i
+ 1, field1
, start
, field2
, end
, msg
,
2821 (sv
->self_test_exec_status
& 0xf), current
, currentend
);
2823 // this span is not currently under test
2824 jout(" %d %*" PRIu64
" %*" PRIu64
" Not_testing\n",
2825 i
+ 1, field1
, start
, field2
, end
);
2827 json::ref jrefi
= jref
["table"][i
];
2828 jrefi
["lba_min"] = start
;
2829 jrefi
["lba_max"] = end
;
2830 jrefi
["status"]["value"] = sv
->self_test_exec_status
;
2831 jrefi
["status"]["string"] = (active
? msg
: "Not_testing");
2833 jrefi
["status"]["remaining_percent"] = sv
->self_test_exec_status
& 0xf;
2834 jrefi
["current_lba_min"] = current
;
2835 jrefi
["current_lba_max"] = currentend
;
2839 // if we are currently read-scanning, print LBAs and the status of
2841 if (log
->currentspan
> 5) {
2842 const char * ost
= OfflineDataCollectionStatus(sv
->offline_data_collection_status
);
2843 jout("%5d %*" PRIu64
" %*" PRIu64
" Read_scanning %s\n",
2844 log
->currentspan
, field1
, current
, field2
, currentend
, ost
);
2845 json::ref jrefc
= jref
["current_read_scan"];
2846 jrefc
["lba_min"] = current
;
2847 jrefc
["lba_max"] = currentend
;
2848 jrefc
["status"]["value"] = sv
->offline_data_collection_status
;
2849 jrefc
["status"]["string"] = ost
;
2852 /* Print selective self-test flags. Possible flag combinations are
2853 (numbering bits from 0-15):
2857 1 0 0 Will carry out scan after selective test
2858 1 1 0 Waiting to carry out scan after powerup
2859 1 0 1 Currently scanning
2860 1 1 1 Currently scanning
2863 jout("Selective self-test flags (0x%x):\n", (unsigned)log
->flags
);
2864 json::ref jreff
= jref
["flags"];
2865 jreff
["value"] = log
->flags
;
2866 jreff
["remainder_scan_enabled"] = !!(log
->flags
& SELECTIVE_FLAG_DOSCAN
);
2867 if (log
->flags
& SELECTIVE_FLAG_DOSCAN
) {
2868 if (log
->flags
& SELECTIVE_FLAG_ACTIVE
)
2869 jout(" Currently read-scanning the remainder of the disk.\n");
2870 else if (log
->flags
& SELECTIVE_FLAG_PENDING
)
2871 jout(" Read-scan of remainder of disk interrupted; will resume %d min after power-up.\n",
2874 jout(" After scanning selected spans, read-scan remainder of disk.\n");
2875 jreff
["remainder_scan_active"] = !!(log
->flags
& SELECTIVE_FLAG_ACTIVE
);
2876 jreff
["power_up_scan_pending"] = !!(log
->flags
& SELECTIVE_FLAG_PENDING
);
2879 jout(" After scanning selected spans, do NOT read-scan remainder of disk.\n");
2881 // print pending time
2882 jout("If Selective self-test is pending on power-up, resume after %d minute delay.\n",
2884 jref
["power_up_scan_resume_minutes"] = log
->pendingtime
;
2887 // Format SCT Temperature value
2888 static const char * sct_ptemp(signed char x
, char (& buf
)[20])
2890 if (x
== -128 /*0x80 = unknown*/)
2892 snprintf(buf
, sizeof(buf
), "%2d", x
);
2896 static void sct_jtemp2(const json::ref
& jref
, const char * name
, signed char x
)
2898 if (x
== -128 /*0x80 = unknown*/)
2900 jglb
["temperature"][name
] = x
;
2901 jref
["temperature"][name
] = x
;
2904 static const char * sct_pbar(int x
, char (& buf
)[64])
2915 memset(buf
, '*', x
);
2921 buf
[0] = '-'; buf
[1] = 0;
2926 static const char * sct_device_state_msg(unsigned char state
)
2929 case 0: return "Active";
2930 case 1: return "Stand-by";
2931 case 2: return "Sleep";
2932 case 3: return "DST executing in background";
2933 case 4: return "SMART Off-line Data Collection executing in background";
2934 case 5: return "SCT command executing in background";
2935 default:return "Unknown";
2940 static int ataPrintSCTStatus(const ata_sct_status_response
* sts
)
2942 json::ref jref
= jglb
["ata_sct_status"];
2944 jout("SCT Status Version: %u\n", sts
->format_version
);
2945 jref
["format_version"] = sts
->format_version
;
2946 jout("SCT Version (vendor specific): %u (0x%04x)\n", sts
->sct_version
, sts
->sct_version
);
2947 jref
["sct_version"] = sts
->sct_version
;
2948 // SCT Support Level (1) from original SCT draft was later declared obsolete in ATA-8 ACS.
2949 // Drives typically return 0 or 1. Print only if unknown value is returned.
2950 if (sts
->sct_spec
> 1)
2951 pout("SCT Support Level: %u\n", sts
->sct_spec
);
2952 const char * statestr
= sct_device_state_msg(sts
->device_state
);
2953 jout("Device State: %s (%u)\n", statestr
, sts
->device_state
);
2954 jref
["device_state"]["value"] = sts
->device_state
;
2955 jref
["device_state"]["string"] = statestr
;
2957 // If "Reserved" fields not set, assume "old" format version 2:
2958 // Table 11 of T13/1701DT-N (SMART Command Transport) Revision 5, February 2005
2959 // Table 54 of T13/1699-D (ATA8-ACS) Revision 3e, July 2006
2960 // ... else assume "new" format version 2 or version 3:
2961 // T13/e06152r0-3 (Additional SCT Temperature Statistics), August - October 2006
2962 // Table 60 of T13/1699-D (ATA8-ACS) Revision 3f, December 2006 (format version 2)
2963 // Table 80 of T13/1699-D (ATA8-ACS) Revision 6a, September 2008 (format version 3)
2964 // Table 194 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
2965 // (max_op_limit, smart_status, min_erc_time)
2966 bool old_format_2
= ( !sts
->min_temp
&& !sts
->life_min_temp
2967 && !sts
->under_limit_count
&& !sts
->over_limit_count
);
2969 char buf1
[20], buf2
[20];
2970 jout("Current Temperature: %s Celsius\n",
2971 sct_ptemp(sts
->hda_temp
, buf1
));
2972 sct_jtemp2(jref
, "current", sts
->hda_temp
);
2973 jout("Power Cycle Min/Max Temperature: %s/%s Celsius\n",
2974 (!old_format_2
? sct_ptemp(sts
->min_temp
, buf1
) : "--"),
2975 sct_ptemp(sts
->max_temp
, buf2
));
2977 sct_jtemp2(jref
, "power_cycle_min", sts
->min_temp
);
2978 sct_jtemp2(jref
, "power_cycle_max", sts
->max_temp
);
2979 jout("Lifetime Min/Max Temperature: %s/%s Celsius\n",
2980 (!old_format_2
? sct_ptemp(sts
->life_min_temp
, buf1
) : "--"),
2981 sct_ptemp(sts
->life_max_temp
, buf2
));
2983 sct_jtemp2(jref
, "lifetime_min", sts
->life_min_temp
);
2984 sct_jtemp2(jref
, "lifetime_max", sts
->life_max_temp
);
2988 if (sts
->max_op_limit
> 0) { // e06152r0-2: "Average Temperature"
2989 jout("Specified Max Operating Temperature: %3d Celsius\n", sts
->max_op_limit
);
2990 sct_jtemp2(jref
, "op_limit_max", sts
->max_op_limit
);
2992 jout("Under/Over Temperature Limit Count: %2u/%u\n",
2993 sts
->under_limit_count
, sts
->over_limit_count
);
2994 jref
["temperature"]["under_limit_count"] = sts
->under_limit_count
;
2995 jref
["temperature"]["over_limit_count"] = sts
->over_limit_count
;
2997 if (sts
->smart_status
) { // ACS-4
2998 int passed
= (sts
->smart_status
== 0x2cf4 ? 0 :
2999 sts
->smart_status
== 0xc24f ? 1 : -1);
3000 jout("SMART Status: 0x%04x (%s)\n", sts
->smart_status
,
3001 (passed
== 0 ? "FAILED" : passed
> 0 ? "PASSED" : "Reserved"));
3003 jref
["smart_status"]["passed"] = !!passed
;
3004 jglb
["smart_status"]["passed"] = !!passed
;
3007 jref
["smart_status"]["reserved_value"] = sts
->smart_status
;
3010 if (sts
->min_erc_time
) // ACS-4
3011 pout("Minimum supported ERC Time Limit: %d (%0.1f seconds)\n",
3012 sts
->min_erc_time
, sts
->min_erc_time
/10.0);
3014 if (nonempty(sts
->vendor_specific
, sizeof(sts
->vendor_specific
))) {
3015 jout("Vendor specific:\n");
3016 for (unsigned i
= 0; i
< sizeof(sts
->vendor_specific
); i
++) {
3017 jout("%02x%c", sts
->vendor_specific
[i
], ((i
& 0xf) != 0xf ? ' ' : '\n'));
3018 jref
["vendor_specific"][i
] = sts
->vendor_specific
[i
];
3024 // Print SCT Temperature History Table
3025 static int ataPrintSCTTempHist(const ata_sct_temperature_history_table
* tmh
)
3027 json::ref jref
= jglb
["ata_sct_temperature_history"];
3029 char buf1
[20], buf2
[20], buf3
[64];
3030 jout("SCT Temperature History Version: %u%s\n", tmh
->format_version
,
3031 (tmh
->format_version
!= 2 ? " (Unknown, should be 2)" : ""));
3032 jref
["version"] = tmh
->format_version
;
3033 jout("Temperature Sampling Period: %u minute%s\n",
3034 tmh
->sampling_period
, (tmh
->sampling_period
==1?"":"s"));
3035 jref
["sampling_period_minutes"] = tmh
->sampling_period
;
3036 jout("Temperature Logging Interval: %u minute%s\n",
3037 tmh
->interval
, (tmh
->interval
==1?"":"s"));
3038 jref
["logging_interval_minutes"] = tmh
->interval
;
3040 jout("Min/Max recommended Temperature: %s/%s Celsius\n",
3041 sct_ptemp(tmh
->min_op_limit
, buf1
), sct_ptemp(tmh
->max_op_limit
, buf2
));
3042 sct_jtemp2(jref
, "op_limit_min", tmh
->min_op_limit
);
3043 sct_jtemp2(jref
, "op_limit_max", tmh
->max_op_limit
);
3044 jout("Min/Max Temperature Limit: %s/%s Celsius\n",
3045 sct_ptemp(tmh
->under_limit
, buf1
), sct_ptemp(tmh
->over_limit
, buf2
));
3046 sct_jtemp2(jref
, "limit_min", tmh
->under_limit
);
3047 sct_jtemp2(jref
, "limit_max", tmh
->over_limit
);
3048 jout("Temperature History Size (Index): %u (%u)\n", tmh
->cb_size
, tmh
->cb_index
);
3049 jref
["size"] = tmh
->cb_size
;
3050 jref
["index"] = tmh
->cb_index
;
3052 if (!(0 < tmh
->cb_size
&& tmh
->cb_size
<= sizeof(tmh
->cb
) && tmh
->cb_index
< tmh
->cb_size
)) {
3054 pout("Temperature History is empty\n");
3056 pout("Invalid Temperature History Size or Index\n");
3061 jout("\nIndex Estimated Time Temperature Celsius\n");
3062 unsigned n
= 0, i
= (tmh
->cb_index
+1) % tmh
->cb_size
;
3063 unsigned interval
= (tmh
->interval
> 0 ? tmh
->interval
: 1);
3064 time_t t
= time(0) - (tmh
->cb_size
-1) * interval
* 60;
3065 t
-= t
% (interval
* 60);
3066 while (n
< tmh
->cb_size
) {
3067 // Find range of identical temperatures
3068 unsigned n1
= n
, n2
= n
+1, i2
= (i
+1) % tmh
->cb_size
;
3069 while (n2
< tmh
->cb_size
&& tmh
->cb
[i2
] == tmh
->cb
[i
]) {
3070 n2
++; i2
= (i2
+1) % tmh
->cb_size
;
3074 if (n
== n1
|| n
== n2
-1 || n2
<= n1
+3) {
3076 // TODO: Don't print times < boot time
3077 strftime(date
, sizeof(date
), "%Y-%m-%d %H:%M", localtime(&t
));
3078 jout(" %3u %s %s %s\n", i
, date
,
3079 sct_ptemp(tmh
->cb
[i
], buf1
), sct_pbar(tmh
->cb
[i
], buf3
));
3081 else if (n
== n1
+1) {
3082 jout(" ... ..(%3u skipped). .. %s\n",
3083 n2
-n1
-2, sct_pbar(tmh
->cb
[i
], buf3
));
3085 if (tmh
->cb
[i
] != -128)
3086 jref
["table"][n
] = tmh
->cb
[i
];
3087 t
+= interval
* 60; i
= (i
+1) % tmh
->cb_size
; n
++;
3090 //assert(n == tmh->cb_size && i == (tmh->cb_index+1) % tmh->cb_size);
3095 // Print SCT Error Recovery Control timers
3096 static void ataPrintSCTErrorRecoveryControl(bool set
, unsigned short read_timer
, unsigned short write_timer
)
3098 json::ref jref
= jglb
["ata_sct_erc"];
3099 jout("SCT Error Recovery Control%s:\n", (set
? " set to" : ""));
3101 jref
["read"]["enabled"] = !!read_timer
;
3103 jout(" Read: Disabled\n");
3105 jout(" Read: %6d (%0.1f seconds)\n", read_timer
, read_timer
/10.0);
3106 jref
["read"]["deciseconds"] = read_timer
;
3109 jref
["write"]["enabled"] = !!write_timer
;
3111 jout(" Write: Disabled\n");
3113 jout(" Write: %6d (%0.1f seconds)\n", write_timer
, write_timer
/10.0);
3114 jref
["write"]["deciseconds"] = write_timer
;
3118 static void print_aam_level(const char * msg
, int level
, int recommended
= -1)
3120 // Table 56 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
3121 // Obsolete since T13/2015-D (ACS-2) Revision 4a, December 9, 2010
3124 s
= "vendor specific";
3125 else if (level
< 128)
3126 s
= "unknown/retired";
3127 else if (level
== 128)
3129 else if (level
< 254)
3131 else if (level
== 254)
3132 s
= "maximum performance";
3136 if (recommended
>= 0)
3137 jout("%s%d (%s), recommended: %d\n", msg
, level
, s
, recommended
);
3139 jout("%s%d (%s)\n", msg
, level
, s
);
3141 json::ref jref
= jglb
["ata_aam"];
3142 jref
["enabled"] = true;
3143 jref
["level"] = level
;
3145 if (recommended
>= 0)
3146 jref
["recommended_level"] = recommended
;
3149 static void print_apm_level(const char * msg
, int level
)
3151 // Table 120 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3153 if (!(1 <= level
&& level
<= 254))
3155 else if (level
== 1)
3156 s
= "minimum power consumption with standby";
3157 else if (level
< 128)
3158 s
= "intermediate level with standby";
3159 else if (level
== 128)
3160 s
= "minimum power consumption without standby";
3161 else if (level
< 254)
3162 s
= "intermediate level without standby";
3164 s
= "maximum performance";
3166 jout("%s%d (%s)\n", msg
, level
, s
);
3168 json::ref jref
= jglb
["ata_apm"];
3169 jref
["enabled"] = true;
3170 jref
["level"] = level
;
3172 if (1 <= level
&& level
<= 254) {
3173 jref
["max_performance"] = (level
== 254);
3174 jref
["min_power"] = (level
== 1 || level
== 128);
3175 jref
["with_standby"] = (level
< 128);
3179 static void print_ata_security_status(const char * msg
, unsigned short state
)
3181 // Table 6 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3182 if (!(state
& 0x0001)) {
3183 pout("%sUnavailable\n", msg
);
3187 const char * s1
, * s2
= "", * s3
= "", * s4
= "";
3188 bool enabled
= false, locked
= false;
3189 if (!(state
& 0x0002)) {
3191 if (!(state
& 0x0008))
3192 s2
= "NOT FROZEN [SEC1]";
3194 s2
= "frozen [SEC2]";
3198 s1
= "ENABLED, PW level ";
3199 if (!(state
& 0x0100))
3204 if (!(state
& 0x0004)) {
3205 s3
= ", not locked, ";
3206 if (!(state
& 0x0008))
3207 s4
= "not frozen [SEC5]";
3209 s4
= "frozen [SEC6]";
3213 s3
= ", **LOCKED** [SEC4]";
3215 s4
= ", PW ATTEMPTS EXCEEDED";
3219 jout("%s%s%s%s%s\n", msg
, s1
, s2
, s3
, s4
);
3221 json::ref jref
= jglb
["ata_security"];
3222 jref
["state"] = state
;
3223 jref
["string"] = strprintf("%s%s%s%s", s1
, s2
, s3
, s4
);
3224 jref
["enabled"] = enabled
;
3225 if (!enabled
|| !locked
)
3226 jref
["frozen"] = !!(state
& 0x0008);
3228 jref
["pw_level_max"] = !!(state
& 0x0100);
3229 jref
["locked"] = locked
;
3231 jref
["pw_attempts_exceeded"] = !!(state
& 0x0010);
3235 static void print_standby_timer(const char * msg
, int timer
, const ata_identify_device
& drive
)
3237 const char * s1
= 0;
3238 int hours
= 0, minutes
= 0 , seconds
= 0;
3240 // Table 63 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3243 else if (timer
<= 240)
3244 seconds
= timer
* 5, minutes
= seconds
/ 60, seconds
%= 60;
3245 else if (timer
<= 251)
3246 minutes
= (timer
- 240) * 30, hours
= minutes
/ 60, minutes
%= 60;
3247 else if (timer
== 252)
3249 else if (timer
== 253)
3250 s1
= "between 8 hours and 12 hours";
3251 else if (timer
== 255)
3252 minutes
= 21, seconds
= 15;
3256 const char * s2
= "", * s3
= "";
3257 if (!(drive
.words047_079
[49-47] & 0x2000))
3258 s2
= " or vendor-specific";
3259 if (timer
> 0 && (drive
.words047_079
[50-47] & 0xc001) == 0x4001)
3260 s3
= ", a vendor-specific minimum applies";
3263 pout("%s%d (%s%s%s)\n", msg
, timer
, s1
, s2
, s3
);
3265 pout("%s%d (%02d:%02d:%02d%s%s)\n", msg
, timer
, hours
, minutes
, seconds
, s2
, s3
);
3269 int ataPrintMain (ata_device
* device
, const ata_print_options
& options
)
3271 // If requested, check power mode first
3272 const char * powername
= 0;
3273 bool powerchg
= false;
3274 if (options
.powermode
) {
3275 unsigned char powerlimit
= 0xff;
3276 int powermode
= ataCheckPowerMode(device
);
3277 // TODO: Move to new function used by smartctl and smartd.
3278 switch (powermode
) {
3280 if (device
->is_syscall_unsup()) {
3281 pout("CHECK POWER MODE not implemented, ignoring -n option\n"); break;
3283 powername
= "SLEEP"; powerlimit
= 2;
3285 // Table 215 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3286 // Table 293 of T13/BSR INCITS 529 (ACS-4) Revision 12, February 18, 2016
3287 case 0x00: // PM2:Standby, EPC unavailable or Standby_z power condition
3288 powername
= "STANDBY"; powerlimit
= 3; break;
3289 case 0x01: // PM2:Standby, Standby_y power condition
3290 powername
= "STANDBY_Y"; powerlimit
= 3; break;
3291 case 0x80: // PM1:Idle, EPC unavailable
3292 powername
= "IDLE"; powerlimit
= 4; break;
3293 case 0x81: // PM1:Idle, Idle_a power condition
3294 powername
= "IDLE_A"; powerlimit
= 4; break;
3295 case 0x82: // PM1:Idle, Idle_b power condition
3296 powername
= "IDLE_B"; powerlimit
= 4; break;
3297 case 0x83: // PM1:Idle, Idle_c power condition
3298 powername
= "IDLE_C"; powerlimit
= 4; break;
3299 // 0x40/41 were declared obsolete in ACS-3 Revision 1
3300 case 0x40: // PM0:Active, NV Cache power mode enabled, spun down
3301 powername
= "ACTIVE_NV_DOWN"; break;
3302 case 0x41: // PM0:Active, NV Cache power mode enabled, spun up
3303 powername
= "ACTIVE_NV_UP" ; break;
3304 case 0xff: // PM0:Active or PM1:Idle
3305 powername
= "ACTIVE or IDLE"; break;
3308 pout("CHECK POWER MODE returned unknown value 0x%02x, ignoring -n option\n", powermode
);
3312 if (options
.powermode
>= powerlimit
) {
3313 jinf("Device is in %s mode, exit(%d)\n", powername
, options
.powerexit
);
3314 return options
.powerexit
;
3316 powerchg
= (powermode
!= 0xff); // SMART tests will spin up drives
3320 // SMART values needed ?
3321 bool need_smart_val
= (
3322 options
.smart_check_status
3323 || options
.smart_general_values
3324 || options
.smart_vendor_attrib
3325 || options
.smart_error_log
3326 || options
.smart_selftest_log
3327 || options
.smart_selective_selftest_log
3328 || options
.smart_ext_error_log
3329 || options
.smart_ext_selftest_log
3330 || options
.smart_auto_offl_enable
3331 || options
.smart_auto_offl_disable
3332 || options
.smart_selftest_type
!= -1
3335 // SMART must be enabled ?
3336 bool need_smart_enabled
= (
3338 || options
.smart_auto_save_enable
3339 || options
.smart_auto_save_disable
3342 // SMART feature set needed ?
3343 bool need_smart_support
= (
3345 || options
.smart_enable
3346 || options
.smart_disable
3349 // SMART and GP log directories needed ?
3350 bool need_smart_logdir
= (
3351 options
.smart_logdir
3352 || options
.devstat_all_pages
// devstat fallback to smartlog if needed
3353 || options
.devstat_ssd_page
3354 || !options
.devstat_pages
.empty()
3357 bool need_gp_logdir
= (
3359 || options
.smart_ext_error_log
3360 || options
.smart_ext_selftest_log
3361 || options
.devstat_all_pages
3362 || options
.devstat_ssd_page
3363 || !options
.devstat_pages
.empty()
3364 || options
.pending_defects_log
3368 for (i
= 0; i
< options
.log_requests
.size(); i
++) {
3369 if (options
.log_requests
[i
].gpl
)
3370 need_gp_logdir
= true;
3372 need_smart_logdir
= true;
3375 // SCT commands needed ?
3376 bool need_sct_support
= (
3377 options
.sct_temp_sts
3378 || options
.sct_temp_hist
3379 || options
.sct_temp_int
3380 || options
.sct_erc_get
3381 || options
.sct_erc_set
3382 || options
.sct_wcache_reorder_get
3383 || options
.sct_wcache_reorder_set
3384 || options
.sct_wcache_sct_get
3385 || options
.sct_wcache_sct_set
3388 // Exit if no further options specified
3389 if (!( options
.drive_info
|| options
.show_presets
3390 || need_smart_support
|| need_smart_logdir
3391 || need_gp_logdir
|| need_sct_support
3393 || options
.identify_word_level
>= 0
3394 || options
.get_set_used
)) {
3396 pout("Device is in %s mode\n", powername
);
3398 pout("ATA device successfully opened\n\n"
3399 "Use 'smartctl -a' (or '-x') to print SMART (and more) information\n\n");
3403 // Start by getting Drive ID information. We need this, to know if SMART is supported.
3405 ata_identify_device drive
; memset(&drive
, 0, sizeof(drive
));
3406 unsigned char raw_drive
[sizeof(drive
)]; memset(&raw_drive
, 0, sizeof(raw_drive
));
3408 device
->clear_err();
3409 int retid
= ata_read_identity(device
, &drive
, options
.fix_swapped_id
, raw_drive
);
3411 pout("Read Device Identity failed: %s\n\n",
3412 (device
->get_errno() ? device
->get_errmsg() : "Unknown error"));
3413 failuretest(MANDATORY_CMD
, returnval
|=FAILID
);
3415 else if (!nonempty(&drive
, sizeof(drive
))) {
3416 pout("Read Device Identity failed: empty IDENTIFY data\n\n");
3417 failuretest(MANDATORY_CMD
, returnval
|=FAILID
);
3420 // If requested, show which presets would be used for this drive and exit.
3421 if (options
.show_presets
) {
3422 show_presets(&drive
);
3426 // Use preset vendor attribute options unless user has requested otherwise.
3427 ata_vendor_attr_defs attribute_defs
= options
.attribute_defs
;
3428 firmwarebug_defs firmwarebugs
= options
.firmwarebugs
;
3429 const drive_settings
* dbentry
= 0;
3430 if (!options
.ignore_presets
)
3431 dbentry
= lookup_drive_apply_presets(&drive
, attribute_defs
,
3434 // Get capacity, sector sizes and rotation rate
3435 ata_size_info sizes
;
3436 ata_get_size_info(&drive
, sizes
);
3437 int rpm
= ata_get_rotation_rate(&drive
);
3439 // Print ATA IDENTIFY info if requested
3440 if (options
.identify_word_level
>= 0) {
3441 pout("=== ATA IDENTIFY DATA ===\n");
3442 // Pass raw data without endianness adjustments
3443 ata_print_identify_data(raw_drive
, (options
.identify_word_level
> 0), options
.identify_bit_level
);
3446 // Print most drive identity information if requested
3447 if (options
.drive_info
) {
3448 pout("=== START OF INFORMATION SECTION ===\n");
3449 print_drive_info(&drive
, sizes
, rpm
, dbentry
);
3452 // Check and print SMART support and state
3453 int smart_supported
= -1, smart_enabled
= -1;
3454 if (need_smart_support
|| options
.drive_info
) {
3458 pout("SMART support is: Unavailable - Packet Interface Devices [this device: %s] don't support ATA SMART\n",
3459 packetdevicetype(retid
-1));
3462 // Disk device: SMART supported and enabled ?
3463 smart_supported
= ataSmartSupport(&drive
);
3464 smart_enabled
= ataIsSmartEnabled(&drive
);
3466 if (smart_supported
< 0)
3467 pout("SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 82-83 don't show if SMART supported.\n");
3468 if (smart_supported
&& smart_enabled
< 0) {
3469 pout("SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 85-87 don't show if SMART is enabled.\n");
3470 if (need_smart_support
) {
3471 failuretest(MANDATORY_CMD
, returnval
|=FAILSMART
);
3472 // check SMART support by trying a command
3473 pout(" Checking to be sure by trying SMART RETURN STATUS command.\n");
3474 if (ataDoesSmartWork(device
))
3475 smart_supported
= smart_enabled
= 1;
3478 else if (smart_supported
< 0 && (smart_enabled
> 0 || dbentry
))
3479 // Assume supported if enabled or in drive database
3480 smart_supported
= 1;
3482 if (smart_supported
< 0)
3483 pout("SMART support is: Unknown - Try option -s with argument 'on' to enable it.");
3484 else if (!smart_supported
)
3485 pout("SMART support is: Unavailable - device lacks SMART capability.\n");
3487 if (options
.drive_info
)
3488 pout("SMART support is: Available - device has SMART capability.\n");
3489 if (smart_enabled
>= 0) {
3490 if (device
->ata_identify_is_cached()) {
3491 if (options
.drive_info
)
3492 pout(" %sabled status cached by OS, trying SMART RETURN STATUS cmd.\n",
3493 (smart_enabled
?"En":"Dis"));
3494 smart_enabled
= ataDoesSmartWork(device
);
3496 if (options
.drive_info
)
3497 pout("SMART support is: %s\n",
3498 (smart_enabled
? "Enabled" : "Disabled"));
3505 if (options
.get_aam
) {
3506 if ((drive
.command_set_2
& 0xc200) != 0x4200) // word083
3507 pout("AAM feature is: Unavailable\n");
3508 else if (!(drive
.word086
& 0x0200)) {
3509 jout("AAM feature is: Disabled\n");
3510 jglb
["ata_aam"]["enabled"] = false;
3513 print_aam_level("AAM level is: ", drive
.words088_255
[94-88] & 0xff,
3514 drive
.words088_255
[94-88] >> 8);
3518 if (options
.get_apm
) {
3519 if ((drive
.command_set_2
& 0xc008) != 0x4008) // word083
3520 pout("APM feature is: Unavailable\n");
3521 else if (!(drive
.word086
& 0x0008)) {
3522 jout("APM feature is: Disabled\n");
3523 jglb
["ata_apm"]["enabled"] = false;
3526 print_apm_level("APM level is: ", drive
.words088_255
[91-88] & 0xff);
3529 // Print read look-ahead status
3530 if (options
.get_lookahead
) {
3531 if ( (drive
.command_set_2
& 0xc000) != 0x4000 // word083
3532 || !(drive
.command_set_1
& 0x0040) ) // word082
3533 pout("Rd look-ahead is: Unavailable\n");
3535 bool enabled
= !!(drive
.cfs_enable_1
& 0x0040); // word085
3536 jout("Rd look-ahead is: %sabled\n", (enabled
? "En" : "Dis"));
3537 jglb
["read_lookahead"]["enabled"] = enabled
;
3541 // Print write cache status
3542 if (options
.get_wcache
) {
3543 if ( (drive
.command_set_2
& 0xc000) != 0x4000 // word083
3544 || !(drive
.command_set_1
& 0x0020) ) // word082
3545 pout("Write cache is: Unavailable\n");
3547 bool enabled
= !!(drive
.cfs_enable_1
& 0x0020); // word085
3548 jout("Write cache is: %sabled\n", (enabled
? "En" : "Dis"));
3549 jglb
["write_cache"]["enabled"] = enabled
;
3554 unsigned short word120
= drive
.words088_255
[120-88];
3555 unsigned short word119
= drive
.words088_255
[119-88];
3556 if (options
.get_dsn
) {
3557 if (!(drive
.word086
& 0x8000) // word086
3558 || ((word119
& 0xc200) != 0x4200) // word119
3559 || ((word120
& 0xc000) != 0x4000)) // word120
3560 pout("DSN feature is: Unavailable\n");
3562 bool enabled
= !!(word120
& 0x200);
3563 jout("DSN feature is: %sabled\n", (enabled
? "En" : "Dis"));
3564 jglb
["ata_dsn"]["enabled"] = enabled
;
3568 // Check for ATA Security LOCK
3569 unsigned short word128
= drive
.words088_255
[128-88];
3570 bool locked
= ((word128
& 0x0007) == 0x0007); // LOCKED|ENABLED|SUPPORTED
3572 // Print ATA Security status
3573 if (options
.get_security
)
3574 print_ata_security_status("ATA Security is: ", word128
);
3576 // Print write cache reordering status
3577 if (options
.sct_wcache_reorder_get
) {
3578 if (!isSCTFeatureControlCapable(&drive
))
3579 pout("Wt Cache Reorder: Unavailable\n");
3581 pout("Wt Cache Reorder: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3583 int wcache_reorder
= ataGetSetSCTWriteCacheReordering(device
,
3584 false /*enable*/, false /*persistent*/, false /*set*/);
3586 if (-1 <= wcache_reorder
&& wcache_reorder
<= 2)
3587 pout("Wt Cache Reorder: %s\n",
3588 (wcache_reorder
== -1 ? "Unknown (SCT Feature Control command failed)" :
3589 wcache_reorder
== 0 ? "Unknown" : // not defined in standard but returned on some drives if not set
3590 wcache_reorder
== 1 ? "Enabled" : "Disabled"));
3592 pout("Wt Cache Reorder: Unknown (0x%02x)\n", wcache_reorder
);
3596 const char * sct_write_cache_state_desc
[4] = {
3597 "Unknown", // 0: not defined in standard but returned on some drives if not set
3598 "Controlled by ATA", // 1: controlled ATA Set Features command
3599 "Force Enabled", // 2
3600 "Force Disabled" // 3
3603 // Print SCT feature control of write cache
3604 if (options
.sct_wcache_sct_get
) {
3605 if (!isSCTFeatureControlCapable(&drive
))
3606 pout("SCT Write Cache Control: Unavailable\n");
3608 pout("SCT Write Cache Control: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3610 int state
= ataGetSetSCTWriteCache(device
, 1, false /*persistent*/, false /*set*/);
3611 if (-1 <= state
&& state
<= 3)
3612 pout("SCT Write Cache Control: %s\n",
3613 (state
== -1 ? "Unknown (SCT Feature Control command failed)" :
3614 sct_write_cache_state_desc
[state
]));
3616 pout("SCT Write Cache Control: Unknown (0x%02x)\n", state
);
3621 // Print remaining drive info
3622 if (options
.drive_info
) {
3623 // Print the (now possibly changed) power mode if available
3625 pout("Power mode %s %s\n", (powerchg
?"was:":"is: "), powername
);
3629 // Exit if SMART is not supported but must be available to proceed
3630 if (smart_supported
<= 0 && need_smart_support
)
3631 failuretest(MANDATORY_CMD
, returnval
|=FAILSMART
);
3633 // START OF THE ENABLE/DISABLE SECTION OF THE CODE
3634 if ( options
.smart_disable
|| options
.smart_enable
3635 || options
.smart_auto_save_disable
|| options
.smart_auto_save_enable
3636 || options
.smart_auto_offl_disable
|| options
.smart_auto_offl_enable
3637 || options
.set_aam
|| options
.set_apm
|| options
.set_lookahead
3638 || options
.set_wcache
|| options
.set_security_freeze
|| options
.set_standby
3639 || options
.sct_wcache_reorder_set
|| options
.sct_wcache_sct_set
|| options
.set_dsn
)
3640 pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
3642 // Enable/Disable AAM
3643 if (options
.set_aam
) {
3644 if (options
.set_aam
> 0) {
3645 if (!ata_set_features(device
, ATA_ENABLE_AAM
, options
.set_aam
-1)) {
3646 pout("AAM enable failed: %s\n", device
->get_errmsg());
3647 returnval
|= FAILSMART
;
3650 print_aam_level("AAM set to level ", options
.set_aam
-1);
3653 if (!ata_set_features(device
, ATA_DISABLE_AAM
)) {
3654 pout("AAM disable failed: %s\n", device
->get_errmsg());
3655 returnval
|= FAILSMART
;
3658 pout("AAM disabled\n");
3662 // Enable/Disable APM
3663 if (options
.set_apm
) {
3664 if (options
.set_apm
> 0) {
3665 if (!ata_set_features(device
, ATA_ENABLE_APM
, options
.set_apm
-1)) {
3666 pout("APM enable failed: %s\n", device
->get_errmsg());
3667 returnval
|= FAILSMART
;
3670 print_apm_level("APM set to level ", options
.set_apm
-1);
3673 if (!ata_set_features(device
, ATA_DISABLE_APM
)) {
3674 pout("APM disable failed: %s\n", device
->get_errmsg());
3675 returnval
|= FAILSMART
;
3678 pout("APM disabled\n");
3682 // Enable/Disable read look-ahead
3683 if (options
.set_lookahead
) {
3684 bool enable
= (options
.set_lookahead
> 0);
3685 if (!ata_set_features(device
, (enable
? ATA_ENABLE_READ_LOOK_AHEAD
: ATA_DISABLE_READ_LOOK_AHEAD
))) {
3686 pout("Read look-ahead %sable failed: %s\n", (enable
? "en" : "dis"), device
->get_errmsg());
3687 returnval
|= FAILSMART
;
3690 pout("Read look-ahead %sabled\n", (enable
? "en" : "dis"));
3693 // Enable/Disable write cache
3694 if (options
.set_wcache
) {
3695 bool enable
= (options
.set_wcache
> 0);
3696 if (!ata_set_features(device
, (enable
? ATA_ENABLE_WRITE_CACHE
: ATA_DISABLE_WRITE_CACHE
))) {
3697 pout("Write cache %sable failed: %s\n", (enable
? "en" : "dis"), device
->get_errmsg());
3698 returnval
|= FAILSMART
;
3701 pout("Write cache %sabled\n", (enable
? "en" : "dis"));
3704 // Enable/Disable DSN
3705 if (options
.set_dsn
) {
3706 bool enable
= (options
.set_dsn
> 0);
3707 if (!ata_set_features(device
, ATA_ENABLE_DISABLE_DSN
, (enable
? 0x1 : 0x2))) {
3708 pout("DSN %sable failed: %s\n", (enable
? "en" : "dis"), device
->get_errmsg());
3709 returnval
|= FAILSMART
;
3712 pout("DSN %sabled\n", (enable
? "en" : "dis"));
3715 // Enable/Disable write cache reordering
3716 if (options
.sct_wcache_reorder_set
) {
3717 bool enable
= (options
.sct_wcache_reorder_set
> 0);
3718 if (!isSCTFeatureControlCapable(&drive
))
3719 pout("Write cache reordering %sable failed: SCT Feature Control command not supported\n",
3720 (enable
? "en" : "dis"));
3722 pout("Write cache reordering %sable failed: SCT not supported if ATA Security is LOCKED\n",
3723 (enable
? "en" : "dis"));
3724 else if (ataGetSetSCTWriteCacheReordering(device
,
3725 enable
, options
.sct_wcache_reorder_set_pers
, true /*set*/) < 0) {
3726 pout("Write cache reordering %sable failed: %s\n", (enable
? "en" : "dis"), device
->get_errmsg());
3727 returnval
|= FAILSMART
;
3730 pout("Write cache reordering %sabled (%s)\n", (enable
? "en" : "dis"),
3731 (options
.sct_wcache_reorder_set_pers
? "persistent" : "volatile"));
3734 // Enable/Disable write cache in SCT
3735 if (options
.sct_wcache_sct_set
) {
3736 if (!isSCTFeatureControlCapable(&drive
))
3737 pout("SCT Feature Control of write cache failed: SCT Feature Control command not supported\n");
3739 pout("SCT Feature Control of write cache failed: SCT not supported if ATA Security is LOCKED\n");
3740 else if (ataGetSetSCTWriteCache(device
,
3741 options
.sct_wcache_sct_set
, options
.sct_wcache_sct_set_pers
, true /*set*/) < 0) {
3742 pout("SCT Feature Control of write cache failed: %s\n", device
->get_errmsg());
3743 returnval
|= FAILSMART
;
3746 pout("Write cache SCT Feature Control is set to: %s (%s)\n",
3747 sct_write_cache_state_desc
[options
.sct_wcache_sct_set
],
3748 (options
.sct_wcache_sct_set_pers
? "persistent" : "volatile"));
3751 // Freeze ATA security
3752 if (options
.set_security_freeze
) {
3753 if (!ata_nodata_command(device
, ATA_SECURITY_FREEZE_LOCK
)) {
3754 pout("ATA SECURITY FREEZE LOCK failed: %s\n", device
->get_errmsg());
3755 returnval
|= FAILSMART
;
3758 pout("ATA Security set to frozen mode\n");
3761 // Set standby timer unless immediate standby is also requested
3762 if (options
.set_standby
&& !options
.set_standby_now
) {
3763 if (!ata_nodata_command(device
, ATA_IDLE
, options
.set_standby
-1)) {
3764 pout("ATA IDLE command failed: %s\n", device
->get_errmsg());
3765 returnval
|= FAILSMART
;
3768 print_standby_timer("Standby timer set to ", options
.set_standby
-1, drive
);
3771 // Enable/Disable SMART commands
3772 if (options
.smart_enable
) {
3773 if (ataEnableSmart(device
)) {
3774 pout("SMART Enable failed: %s\n\n", device
->get_errmsg());
3775 failuretest(MANDATORY_CMD
, returnval
|=FAILSMART
);
3778 pout("SMART Enabled.\n");
3783 // Turn off SMART on device
3784 if (options
.smart_disable
) {
3785 if (ataDisableSmart(device
)) {
3786 pout("SMART Disable failed: %s\n\n", device
->get_errmsg());
3787 failuretest(MANDATORY_CMD
,returnval
|=FAILSMART
);
3791 // Exit if SMART is disabled but must be enabled to proceed
3792 if (options
.smart_disable
|| (smart_enabled
<= 0 && need_smart_enabled
&& !is_permissive())) {
3793 pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n");
3794 if (!options
.smart_disable
)
3795 pout("(override with '-T permissive' option)\n");
3799 // Enable/Disable Auto-save attributes
3800 if (options
.smart_auto_save_enable
) {
3801 if (ataEnableAutoSave(device
)){
3802 pout("SMART Enable Attribute Autosave failed: %s\n\n", device
->get_errmsg());
3803 failuretest(MANDATORY_CMD
, returnval
|=FAILSMART
);
3806 pout("SMART Attribute Autosave Enabled.\n");
3809 if (options
.smart_auto_save_disable
) {
3810 if (ataDisableAutoSave(device
)){
3811 pout("SMART Disable Attribute Autosave failed: %s\n\n", device
->get_errmsg());
3812 failuretest(MANDATORY_CMD
, returnval
|=FAILSMART
);
3815 pout("SMART Attribute Autosave Disabled.\n");
3818 // Read SMART values and thresholds if necessary
3819 ata_smart_values smartval
; memset(&smartval
, 0, sizeof(smartval
));
3820 ata_smart_thresholds_pvt smartthres
; memset(&smartthres
, 0, sizeof(smartthres
));
3821 bool smart_val_ok
= false, smart_thres_ok
= false;
3823 if (need_smart_val
) {
3824 if (ataReadSmartValues(device
, &smartval
)) {
3825 pout("Read SMART Data failed: %s\n\n", device
->get_errmsg());
3826 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3829 smart_val_ok
= true;
3831 if (options
.smart_check_status
|| options
.smart_vendor_attrib
) {
3832 if (ataReadSmartThresholds(device
, &smartthres
)){
3833 pout("Read SMART Thresholds failed: %s\n\n", device
->get_errmsg());
3834 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3837 smart_thres_ok
= true;
3842 // Enable/Disable Off-line testing
3843 bool needupdate
= false;
3844 if (options
.smart_auto_offl_enable
) {
3845 if (!isSupportAutomaticTimer(&smartval
)){
3846 pout("SMART Automatic Timers not supported\n\n");
3847 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3849 needupdate
= smart_val_ok
;
3850 if (ataEnableAutoOffline(device
)){
3851 pout("SMART Enable Automatic Offline failed: %s\n\n", device
->get_errmsg());
3852 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3855 pout("SMART Automatic Offline Testing Enabled every four hours.\n");
3858 if (options
.smart_auto_offl_disable
) {
3859 if (!isSupportAutomaticTimer(&smartval
)){
3860 pout("SMART Automatic Timers not supported\n\n");
3861 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3863 needupdate
= smart_val_ok
;
3864 if (ataDisableAutoOffline(device
)){
3865 pout("SMART Disable Automatic Offline failed: %s\n\n", device
->get_errmsg());
3866 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3869 pout("SMART Automatic Offline Testing Disabled.\n");
3872 if (needupdate
&& ataReadSmartValues(device
, &smartval
)){
3873 pout("Read SMART Data failed: %s\n\n", device
->get_errmsg());
3874 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3875 smart_val_ok
= false;
3878 // all this for a newline!
3879 if ( options
.smart_disable
|| options
.smart_enable
3880 || options
.smart_auto_save_disable
|| options
.smart_auto_save_enable
3881 || options
.smart_auto_offl_disable
|| options
.smart_auto_offl_enable
3882 || options
.set_aam
|| options
.set_apm
|| options
.set_lookahead
3883 || options
.set_wcache
|| options
.set_security_freeze
|| options
.set_standby
3884 || options
.sct_wcache_reorder_set
|| options
.set_dsn
)
3887 // START OF READ-ONLY OPTIONS APART FROM -V and -i
3888 if ( options
.smart_check_status
|| options
.smart_general_values
3889 || options
.smart_vendor_attrib
|| options
.smart_error_log
3890 || options
.smart_selftest_log
|| options
.smart_selective_selftest_log
3891 || options
.smart_ext_error_log
|| options
.smart_ext_selftest_log
3892 || options
.sct_temp_sts
|| options
.sct_temp_hist
)
3893 pout("=== START OF READ SMART DATA SECTION ===\n");
3895 // Check SMART status
3896 if (options
.smart_check_status
) {
3898 switch (ataSmartStatus2(device
)) {
3901 // The case where the disk health is OK
3902 jout("SMART overall-health self-assessment test result: PASSED\n");
3903 jglb
["smart_status"]["passed"] = true;
3904 if (smart_thres_ok
&& find_failed_attr(&smartval
, &smartthres
, attribute_defs
, 0)) {
3905 if (options
.smart_vendor_attrib
)
3906 pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
3909 pout("Please note the following marginal Attributes:\n");
3910 PrintSmartAttribWithThres(&smartval
, &smartthres
, attribute_defs
, rpm
, 2, options
.output_format
);
3919 // The case where the disk health is NOT OK
3921 jout("SMART overall-health self-assessment test result: FAILED!\n"
3922 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
3923 jglb
["smart_status"]["passed"] = false;
3925 if (smart_thres_ok
&& find_failed_attr(&smartval
, &smartthres
, attribute_defs
, 1)) {
3926 returnval
|=FAILATTR
;
3927 if (options
.smart_vendor_attrib
)
3928 pout("See vendor-specific Attribute list for failed Attributes.\n\n");
3931 pout("Failed Attributes:\n");
3932 PrintSmartAttribWithThres(&smartval
, &smartthres
, attribute_defs
, rpm
, 1, options
.output_format
);
3936 pout("No failed Attributes found.\n\n");
3937 returnval
|=FAILSTATUS
;
3943 // Something went wrong with the SMART STATUS command.
3944 // The ATA SMART RETURN STATUS command provides the result in the ATA output
3945 // registers. Buggy ATA/SATA drivers and SAT Layers often do not properly
3946 // return the registers values.
3947 pout("SMART Status %s: %s\n",
3948 (device
->is_syscall_unsup() ? "not supported" : "command failed"),
3949 device
->get_errmsg());
3950 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
3952 if (!(smart_val_ok
&& smart_thres_ok
)) {
3954 pout("SMART overall-health self-assessment test result: UNKNOWN!\n"
3955 "SMART Status, Attributes and Thresholds cannot be read.\n\n");
3957 else if (find_failed_attr(&smartval
, &smartthres
, attribute_defs
, 1)) {
3959 jout("SMART overall-health self-assessment test result: FAILED!\n"
3960 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
3961 jwrn("Warning: This result is based on an Attribute check.\n");
3962 jglb
["smart_status"]["passed"] = false;
3964 returnval
|=FAILATTR
;
3965 returnval
|=FAILSTATUS
;
3966 if (options
.smart_vendor_attrib
)
3967 pout("See vendor-specific Attribute list for failed Attributes.\n\n");
3970 pout("Failed Attributes:\n");
3971 PrintSmartAttribWithThres(&smartval
, &smartthres
, attribute_defs
, rpm
, 1, options
.output_format
);
3975 jout("SMART overall-health self-assessment test result: PASSED\n");
3976 jwrn("Warning: This result is based on an Attribute check.\n");
3977 jglb
["smart_status"]["passed"] = true;
3978 if (find_failed_attr(&smartval
, &smartthres
, attribute_defs
, 0)) {
3979 if (options
.smart_vendor_attrib
)
3980 pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
3983 pout("Please note the following marginal Attributes:\n");
3984 PrintSmartAttribWithThres(&smartval
, &smartthres
, attribute_defs
, rpm
, 2, options
.output_format
);
3993 } // end of switch statement
3996 } // end of checking SMART Status
3998 // Print general SMART values
3999 if (smart_val_ok
&& options
.smart_general_values
)
4000 PrintGeneralSmartValues(&smartval
, &drive
, firmwarebugs
);
4002 // Print vendor-specific attributes
4003 if (smart_val_ok
&& options
.smart_vendor_attrib
) {
4005 PrintSmartAttribWithThres(&smartval
, &smartthres
, attribute_defs
, rpm
,
4006 (printing_is_switchable
? 2 : 0), options
.output_format
);
4010 // If GP Log is supported use smart log directory for
4011 // error and selftest log support check.
4012 bool gp_log_supported
= isGeneralPurposeLoggingCapable(&drive
);
4013 if ( gp_log_supported
4014 && ( options
.smart_error_log
|| options
.smart_selftest_log
4015 || options
.retry_error_log
|| options
.retry_selftest_log
))
4016 need_smart_logdir
= true;
4018 ata_smart_log_directory smartlogdir_buf
, gplogdir_buf
;
4019 const ata_smart_log_directory
* smartlogdir
= 0, * gplogdir
= 0;
4021 // Read SMART Log directory
4022 if (need_smart_logdir
) {
4023 if (firmwarebugs
.is_set(BUG_NOLOGDIR
))
4024 smartlogdir
= fake_logdir(&smartlogdir_buf
, options
);
4025 else if (ataReadLogDirectory(device
, &smartlogdir_buf
, false)) {
4026 pout("Read SMART Log Directory failed: %s\n\n", device
->get_errmsg());
4027 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4030 smartlogdir
= &smartlogdir_buf
;
4033 // Read GP Log directory
4034 if (need_gp_logdir
) {
4035 if (firmwarebugs
.is_set(BUG_NOLOGDIR
))
4036 gplogdir
= fake_logdir(&gplogdir_buf
, options
);
4037 else if (!gp_log_supported
&& !is_permissive()) {
4038 if (options
.gp_logdir
)
4039 pout("General Purpose Log Directory not supported\n\n");
4041 else if (ataReadLogDirectory(device
, &gplogdir_buf
, true)) {
4042 pout("Read GP Log Directory failed\n\n");
4043 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4046 gplogdir
= &gplogdir_buf
;
4049 // Print log directories
4050 if ((options
.gp_logdir
&& gplogdir
) || (options
.smart_logdir
&& smartlogdir
)) {
4051 if (firmwarebugs
.is_set(BUG_NOLOGDIR
))
4052 pout("Log Directories not read due to '-F nologdir' option\n\n");
4054 PrintLogDirectories(gplogdir
, smartlogdir
);
4058 for (i
= 0; i
< options
.log_requests
.size(); i
++) {
4059 const ata_log_request
& req
= options
.log_requests
[i
];
4062 unsigned max_nsectors
;
4064 type
= "General Purpose";
4065 max_nsectors
= GetNumLogSectors(gplogdir
, req
.logaddr
, true);
4069 max_nsectors
= GetNumLogSectors(smartlogdir
, req
.logaddr
, false);
4072 if (!max_nsectors
) {
4073 if (!is_permissive()) {
4074 pout("%s Log 0x%02x does not exist (override with '-T permissive' option)\n", type
, req
.logaddr
);
4077 max_nsectors
= req
.page
+1;
4079 if (max_nsectors
<= req
.page
) {
4080 pout("%s Log 0x%02x has only %u sectors, output skipped\n", type
, req
.logaddr
, max_nsectors
);
4084 unsigned ns
= req
.nsectors
;
4085 if (ns
> max_nsectors
- req
.page
) {
4086 if (req
.nsectors
!= ~0U) // "FIRST-max"
4087 pout("%s Log 0x%02x has only %u sectors, output truncated\n", type
, req
.logaddr
, max_nsectors
);
4088 ns
= max_nsectors
- req
.page
;
4091 // SMART log don't support sector offset, start with first sector
4092 unsigned offs
= (req
.gpl
? 0 : req
.page
);
4094 raw_buffer
log_buf((offs
+ ns
) * 512);
4097 ok
= ataReadLogExt(device
, req
.logaddr
, 0x00, req
.page
, log_buf
.data(), ns
);
4099 ok
= ataReadSmartLog(device
, req
.logaddr
, log_buf
.data(), offs
+ ns
);
4101 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4103 PrintLogPages(type
, log_buf
.data() + offs
*512, req
.logaddr
, req
.page
, ns
, max_nsectors
);
4106 // Print SMART Extendend Comprehensive Error Log
4107 bool do_smart_error_log
= options
.smart_error_log
;
4108 if (options
.smart_ext_error_log
) {
4110 unsigned nsectors
= GetNumLogSectors(gplogdir
, 0x03, true);
4112 pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n\n");
4114 // Read only first sector to get error count and index
4115 // Print function will read more sectors as needed
4116 ata_smart_exterrlog log_03
; memset(&log_03
, 0, sizeof(log_03
));
4117 if (!ataReadExtErrorLog(device
, &log_03
, 0, 1, firmwarebugs
)) {
4118 pout("Read SMART Extended Comprehensive Error Log failed\n\n");
4119 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4122 if (PrintSmartExtErrorLog(device
, firmwarebugs
, &log_03
, nsectors
, options
.smart_ext_error_log
))
4123 returnval
|= FAILERR
;
4129 if (options
.retry_error_log
)
4130 do_smart_error_log
= true;
4131 else if (!do_smart_error_log
)
4132 pout("Try '-l [xerror,]error' to read traditional SMART Error Log\n");
4136 // Print SMART error log
4137 if (do_smart_error_log
) {
4138 if (!( GetNumLogSectors(smartlogdir
, 0x01, false)
4139 || ( !(smartlogdir
&& gp_log_supported
)
4140 && isSmartErrorLogCapable(&smartval
, &drive
))
4141 || is_permissive() )) {
4142 pout("SMART Error Log not supported\n\n");
4145 ata_smart_errorlog smarterror
; memset(&smarterror
, 0, sizeof(smarterror
));
4146 if (ataReadErrorLog(device
, &smarterror
, firmwarebugs
)) {
4147 pout("Read SMART Error Log failed: %s\n\n", device
->get_errmsg());
4148 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4151 // quiet mode is turned on inside PrintSmartErrorLog()
4152 if (PrintSmartErrorlog(&smarterror
, firmwarebugs
))
4159 // Print SMART Extendend Self-test Log
4160 bool do_smart_selftest_log
= options
.smart_selftest_log
;
4161 if (options
.smart_ext_selftest_log
) {
4163 unsigned nsectors
= GetNumLogSectors(gplogdir
, 0x07, true);
4165 pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n\n");
4166 else if (nsectors
>= 256)
4167 pout("SMART Extended Self-test Log size %u not supported\n\n", nsectors
);
4169 raw_buffer
log_07_buf(nsectors
* 512);
4170 ata_smart_extselftestlog
* log_07
= reinterpret_cast<ata_smart_extselftestlog
*>(log_07_buf
.data());
4171 if (!ataReadExtSelfTestLog(device
, log_07
, nsectors
)) {
4172 pout("Read SMART Extended Self-test Log failed\n\n");
4173 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4176 if (PrintSmartExtSelfTestLog(log_07
, nsectors
, options
.smart_ext_selftest_log
))
4177 returnval
|= FAILLOG
;
4183 if (options
.retry_selftest_log
)
4184 do_smart_selftest_log
= true;
4185 else if (!do_smart_selftest_log
)
4186 pout("Try '-l [xselftest,]selftest' to read traditional SMART Self Test Log\n");
4190 // Print SMART self-test log
4191 if (do_smart_selftest_log
) {
4192 if (!( GetNumLogSectors(smartlogdir
, 0x06, false)
4193 || ( !(smartlogdir
&& gp_log_supported
)
4194 && isSmartTestLogCapable(&smartval
, &drive
))
4195 || is_permissive() )) {
4196 pout("SMART Self-test Log not supported\n\n");
4199 ata_smart_selftestlog smartselftest
; memset(&smartselftest
, 0, sizeof(smartselftest
));
4200 if (ataReadSelfTestLog(device
, &smartselftest
, firmwarebugs
)) {
4201 pout("Read SMART Self-test Log failed: %s\n\n", device
->get_errmsg());
4202 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4206 if (ataPrintSmartSelfTestlog(&smartselftest
, !printing_is_switchable
, firmwarebugs
))
4207 returnval
|= FAILLOG
;
4214 // Print SMART selective self-test log
4215 if (options
.smart_selective_selftest_log
) {
4216 ata_selective_self_test_log log
;
4218 if (!isSupportSelectiveSelfTest(&smartval
))
4219 pout("Selective Self-tests/Logging not supported\n\n");
4220 else if(ataReadSelectiveSelfTestLog(device
, &log
)) {
4221 pout("Read SMART Selective Self-test Log failed: %s\n\n", device
->get_errmsg());
4222 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4226 // If any errors were found, they are logged in the SMART Self-test log.
4227 // So there is no need to print the Selective Self Test log in silent
4229 if (!printing_is_switchable
)
4230 ataPrintSelectiveSelfTestLog(&log
, &smartval
);
4236 // Check if SCT commands available
4237 bool sct_ok
= isSCTCapable(&drive
);
4238 if ( options
.sct_temp_sts
|| options
.sct_temp_hist
|| options
.sct_temp_int
4239 || options
.sct_erc_get
|| options
.sct_erc_set
) {
4241 pout("SCT Commands not supported\n\n");
4243 pout("SCT Commands not supported if ATA Security is LOCKED\n\n");
4248 // Print SCT status and temperature history table
4249 if (sct_ok
&& (options
.sct_temp_sts
|| options
.sct_temp_hist
|| options
.sct_temp_int
)) {
4251 bool sct_temp_hist_ok
= isSCTDataTableCapable(&drive
);
4252 ata_sct_status_response sts
;
4254 if (options
.sct_temp_sts
|| (options
.sct_temp_hist
&& sct_temp_hist_ok
)) {
4256 if (ataReadSCTStatus(device
, &sts
)) {
4258 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4261 if (options
.sct_temp_sts
) {
4262 ataPrintSCTStatus(&sts
);
4267 if (!sct_temp_hist_ok
&& (options
.sct_temp_hist
|| options
.sct_temp_int
)) {
4268 pout("SCT Data Table command not supported\n\n");
4269 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4273 if (options
.sct_temp_hist
) {
4274 // Read SCT temperature history,
4275 // requires initial SCT status from above
4276 ata_sct_temperature_history_table tmh
;
4277 if (ataReadSCTTempHist(device
, &tmh
, &sts
)) {
4278 pout("Read SCT Temperature History failed\n\n");
4279 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4282 ataPrintSCTTempHist(&tmh
);
4286 if (options
.sct_temp_int
) {
4287 // Set new temperature logging interval
4288 if (!isSCTFeatureControlCapable(&drive
)) {
4289 pout("SCT Feature Control command not supported\n\n");
4290 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4293 if (ataSetSCTTempInterval(device
, options
.sct_temp_int
, options
.sct_temp_int_pers
)) {
4294 pout("Write Temperature Logging Interval failed\n\n");
4295 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4298 pout("Temperature Logging Interval set to %u minute%s (%s)\n",
4299 options
.sct_temp_int
, (options
.sct_temp_int
== 1 ? "" : "s"),
4300 (options
.sct_temp_int_pers
? "persistent" : "volatile"));
4306 // SCT Error Recovery Control
4307 if (sct_ok
&& (options
.sct_erc_get
|| options
.sct_erc_set
)) {
4308 if (!isSCTErrorRecoveryControlCapable(&drive
)) {
4309 pout("SCT Error Recovery Control command not supported\n\n");
4310 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4313 bool sct_erc_get
= options
.sct_erc_get
;
4314 if (options
.sct_erc_set
) {
4315 // Set SCT Error Recovery Control
4316 if ( ataSetSCTErrorRecoveryControltime(device
, 1, options
.sct_erc_readtime
)
4317 || ataSetSCTErrorRecoveryControltime(device
, 2, options
.sct_erc_writetime
)) {
4318 pout("SCT (Set) Error Recovery Control command failed\n");
4319 if (!( (options
.sct_erc_readtime
== 70 && options
.sct_erc_writetime
== 70)
4320 || (options
.sct_erc_readtime
== 0 && options
.sct_erc_writetime
== 0)))
4321 pout("Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n");
4322 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4323 sct_erc_get
= false;
4325 else if (!sct_erc_get
)
4326 ataPrintSCTErrorRecoveryControl(true, options
.sct_erc_readtime
,
4327 options
.sct_erc_writetime
);
4331 // Print SCT Error Recovery Control
4332 unsigned short read_timer
, write_timer
;
4333 if ( ataGetSCTErrorRecoveryControltime(device
, 1, read_timer
)
4334 || ataGetSCTErrorRecoveryControltime(device
, 2, write_timer
)) {
4335 pout("SCT (Get) Error Recovery Control command failed\n");
4336 if (options
.sct_erc_set
) {
4337 pout("The previous SCT (Set) Error Recovery Control command succeeded\n");
4338 ataPrintSCTErrorRecoveryControl(true, options
.sct_erc_readtime
,
4339 options
.sct_erc_writetime
);
4341 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4344 ataPrintSCTErrorRecoveryControl(false, read_timer
, write_timer
);
4350 // Print Device Statistics
4351 if (options
.devstat_all_pages
|| options
.devstat_ssd_page
|| !options
.devstat_pages
.empty()) {
4352 bool use_gplog
= true;
4353 unsigned nsectors
= 0;
4355 nsectors
= GetNumLogSectors(gplogdir
, 0x04, true);
4356 else if (smartlogdir
){ // for systems without ATA_READ_LOG_EXT
4357 nsectors
= GetNumLogSectors(smartlogdir
, 0x04, false);
4361 pout("Device Statistics (GP/SMART Log 0x04) not supported\n\n");
4362 else if (!print_device_statistics(device
, nsectors
, options
.devstat_pages
,
4363 options
.devstat_all_pages
, options
.devstat_ssd_page
, use_gplog
))
4364 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4367 // Print Pending Defects log
4368 if (options
.pending_defects_log
) {
4369 unsigned nsectors
= GetNumLogSectors(gplogdir
, 0x0c, true);
4371 pout("Pending Defects log (GP Log 0x0c) not supported\n\n");
4372 else if (!print_pending_defects_log(device
, nsectors
, options
.pending_defects_log
))
4373 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4376 // Print SATA Phy Event Counters
4377 if (options
.sataphy
) {
4378 unsigned nsectors
= GetNumLogSectors(gplogdir
, 0x11, true);
4379 // Packet interface devices do not provide a log directory, check support bit
4380 if (!nsectors
&& (drive
.words047_079
[76-47] & 0x0401) == 0x0400)
4383 pout("SATA Phy Event Counters (GP Log 0x11) not supported\n\n");
4384 else if (nsectors
!= 1)
4385 pout("SATA Phy Event Counters with %u sectors not supported\n\n", nsectors
);
4387 unsigned char log_11
[512] = {0, };
4388 unsigned char features
= (options
.sataphy_reset
? 0x01 : 0x00);
4389 if (!ataReadLogExt(device
, 0x11, features
, 0, log_11
, 1)) {
4390 pout("Read SATA Phy Event Counters failed\n\n");
4391 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4394 PrintSataPhyEventCounters(log_11
, options
.sataphy_reset
);
4398 // Set to standby (spindown) mode and set standby timer if not done above
4399 // (Above commands may spinup drive)
4400 if (options
.set_standby_now
) {
4401 if (options
.set_standby
) {
4402 if (!ata_nodata_command(device
, ATA_STANDBY
, options
.set_standby
-1)) {
4403 pout("ATA STANDBY command failed: %s\n", device
->get_errmsg());
4404 returnval
|= FAILSMART
;
4407 print_standby_timer("Standby timer set to ", options
.set_standby
-1, drive
);
4408 pout("Device placed in STANDBY mode\n");
4412 if (!ata_nodata_command(device
, ATA_STANDBY_IMMEDIATE
)) {
4413 pout("ATA STANDBY IMMEDIATE command failed: %s\n", device
->get_errmsg());
4414 returnval
|= FAILSMART
;
4417 pout("Device placed in STANDBY mode\n");
4421 // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN
4422 if (!smart_val_ok
|| options
.smart_selftest_type
== -1)
4425 pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
4426 // if doing a self-test, be sure it's supported by the hardware
4427 switch (options
.smart_selftest_type
) {
4428 case OFFLINE_FULL_SCAN
:
4429 if (!isSupportExecuteOfflineImmediate(&smartval
)){
4430 pout("Execute Offline Immediate function not supported\n\n");
4431 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4434 case ABORT_SELF_TEST
:
4435 case SHORT_SELF_TEST
:
4436 case EXTEND_SELF_TEST
:
4437 case SHORT_CAPTIVE_SELF_TEST
:
4438 case EXTEND_CAPTIVE_SELF_TEST
:
4439 if (!isSupportSelfTest(&smartval
)){
4440 pout("Self-test functions not supported\n\n");
4441 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4444 case CONVEYANCE_SELF_TEST
:
4445 case CONVEYANCE_CAPTIVE_SELF_TEST
:
4446 if (!isSupportConveyanceSelfTest(&smartval
)){
4447 pout("Conveyance Self-test functions not supported\n\n");
4448 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4451 case SELECTIVE_SELF_TEST
:
4452 case SELECTIVE_CAPTIVE_SELF_TEST
:
4453 if (!isSupportSelectiveSelfTest(&smartval
)){
4454 pout("Selective Self-test functions not supported\n\n");
4455 failuretest(MANDATORY_CMD
, returnval
|=FAILSMART
);
4459 break; // Vendor specific type
4462 // Now do the test. Note ataSmartTest prints its own error/success
4464 if (ataSmartTest(device
, options
.smart_selftest_type
, options
.smart_selftest_force
,
4465 options
.smart_selective_args
, &smartval
, sizes
.sectors
))
4466 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4468 // Tell user how long test will take to complete. This is tricky
4469 // because in the case of an Offline Full Scan, the completion
4470 // timer is volatile, and needs to be read AFTER the command is
4471 // given. If this will interrupt the Offline Full Scan, we don't
4472 // do it, just warn user.
4473 if (options
.smart_selftest_type
== OFFLINE_FULL_SCAN
) {
4474 if (isSupportOfflineAbort(&smartval
))
4475 pout("Note: giving further SMART commands will abort Offline testing\n");
4476 else if (ataReadSmartValues(device
, &smartval
)){
4477 pout("Read SMART Data failed: %s\n\n", device
->get_errmsg());
4478 failuretest(OPTIONAL_CMD
, returnval
|=FAILSMART
);
4482 // Now say how long the test will take to complete
4483 int timewait
= TestTime(&smartval
, options
.smart_selftest_type
);
4485 time_t t
=time(NULL
);
4486 if (options
.smart_selftest_type
== OFFLINE_FULL_SCAN
) {
4488 pout("Please wait %d seconds for test to complete.\n", (int)timewait
);
4491 pout("Please wait %d minutes for test to complete.\n", (int)timewait
);
4493 pout("Test will complete after %s\n", ctime(&t
));
4495 if ( options
.smart_selftest_type
!= SHORT_CAPTIVE_SELF_TEST
4496 && options
.smart_selftest_type
!= EXTEND_CAPTIVE_SELF_TEST
4497 && options
.smart_selftest_type
!= CONVEYANCE_CAPTIVE_SELF_TEST
4498 && options
.smart_selftest_type
!= SELECTIVE_CAPTIVE_SELF_TEST
)
4499 pout("Use smartctl -X to abort test.\n");