smartmontools SVN Rev 5659
Utility to control and monitor storage systems with "S.M.A.R.T."
ataprint.cpp
Go to the documentation of this file.
1/*
2 * ataprint.cpp
3 *
4 * Home page of code is: https://www.smartmontools.org
5 *
6 * Copyright (C) 2002-11 Bruce Allen
7 * Copyright (C) 2008-25 Christian Franke
8 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13#include "config.h"
14#define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
15
16#include <ctype.h>
17#include <errno.h>
18#include <inttypes.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include "atacmdnames.h"
24#include "atacmds.h"
25#include "ataidentify.h"
26#include "dev_interface.h"
27#include "ataprint.h"
28#include "smartctl.h"
29#include "sg_unaligned.h"
30#include "utility.h"
31#include "knowndrives.h"
32
33#include "farmcmds.h"
34#include "farmprint.h"
35
36const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 5658 2025-02-02 17:56:14Z chrfranke $"
38
39
40static const char * infofound(const char *output) {
41 return (*output ? output : "[No Information Found]");
42}
43
44// Return true if '-T permissive' is specified,
45// used to ignore missing capabilities
46static bool is_permissive()
47{
49 return false;
51 return true;
52}
53
54/* For the given Command Register (CR) and Features Register (FR), attempts
55 * to construct a string that describes the contents of the Status
56 * Register (ST) and Error Register (ER). If the meanings of the flags of
57 * the error register are not known for the given command then it returns an
58 * empty string.
59 *
60 * The meanings of the flags of the error register for all commands are
61 * described in the ATA spec and could all be supported here in theory.
62 * Currently, only a few commands are supported (those that have been seen
63 * to produce errors). If many more are to be added then this function
64 * should probably be redesigned.
65 */
66
67static std::string format_st_er_desc(
68 unsigned char CR, unsigned char FR,
69 unsigned char ST, unsigned char ER,
70 unsigned short SC,
71 const ata_smart_errorlog_error_struct * lba28_regs,
72 const ata_smart_exterrlog_error * lba48_regs
73)
74{
75 const char *error_flag[8];
76 int i, print_lba=0, print_sector=0;
77
78 // Set of character strings corresponding to different error codes.
79 // Please keep in alphabetic order if you add more.
80 const char *abrt = "ABRT"; // ABORTED
81 const char *amnf = "AMNF"; // ADDRESS MARK NOT FOUND
82 const char *ccto = "CCTO"; // COMMAND COMPLETION TIMED OUT
83 const char *eom = "EOM"; // END OF MEDIA
84 const char *icrc = "ICRC"; // INTERFACE CRC ERROR
85 const char *idnf = "IDNF"; // ID NOT FOUND
86 const char *ili = "ILI"; // MEANING OF THIS BIT IS COMMAND-SET SPECIFIC
87 const char *mc = "MC"; // MEDIA CHANGED
88 const char *mcr = "MCR"; // MEDIA CHANGE REQUEST
89 const char *nm = "NM"; // NO MEDIA
90 const char *obs = "obs"; // OBSOLETE
91 const char *tk0nf = "TK0NF"; // TRACK 0 NOT FOUND
92 const char *unc = "UNC"; // UNCORRECTABLE
93 const char *wp = "WP"; // WRITE PROTECTED
94
95 /* If for any command the Device Fault flag of the status register is
96 * not used then used_device_fault should be set to 0 (in the CR switch
97 * below)
98 */
99 int uses_device_fault = 1;
100
101 /* A value of NULL means that the error flag isn't used */
102 for (i = 0; i < 8; i++)
103 error_flag[i] = NULL;
104
105 std::string str;
106
107 switch (CR) {
108 case 0x10: // RECALIBRATE
109 error_flag[2] = abrt;
110 error_flag[1] = tk0nf;
111 break;
112 case 0x20: /* READ SECTOR(S) */
113 case 0x21: // READ SECTOR(S)
114 case 0x24: // READ SECTOR(S) EXT
115 case 0xC4: /* READ MULTIPLE */
116 case 0x29: // READ MULTIPLE EXT
117 error_flag[6] = unc;
118 error_flag[5] = mc;
119 error_flag[4] = idnf;
120 error_flag[3] = mcr;
121 error_flag[2] = abrt;
122 error_flag[1] = nm;
123 error_flag[0] = amnf;
124 print_lba=1;
125 break;
126 case 0x22: // READ LONG (with retries)
127 case 0x23: // READ LONG (without retries)
128 error_flag[4] = idnf;
129 error_flag[2] = abrt;
130 error_flag[0] = amnf;
131 print_lba=1;
132 break;
133 case 0x2a: // READ STREAM DMA
134 case 0x2b: // READ STREAM PIO
135 if (CR==0x2a)
136 error_flag[7] = icrc;
137 error_flag[6] = unc;
138 error_flag[5] = mc;
139 error_flag[4] = idnf;
140 error_flag[3] = mcr;
141 error_flag[2] = abrt;
142 error_flag[1] = nm;
143 error_flag[0] = ccto;
144 print_lba=1;
145 print_sector=SC;
146 break;
147 case 0x3A: // WRITE STREAM DMA
148 case 0x3B: // WRITE STREAM PIO
149 if (CR==0x3A)
150 error_flag[7] = icrc;
151 error_flag[6] = wp;
152 error_flag[5] = mc;
153 error_flag[4] = idnf;
154 error_flag[3] = mcr;
155 error_flag[2] = abrt;
156 error_flag[1] = nm;
157 error_flag[0] = ccto;
158 print_lba=1;
159 print_sector=SC;
160 break;
161 case 0x25: // READ DMA EXT
162 case 0x26: // READ DMA QUEUED EXT
163 case 0xC7: // READ DMA QUEUED
164 case 0xC8: // READ DMA (with retries)
165 case 0xC9: // READ DMA (without retries, obsolete since ATA-5)
166 case 0x60: // READ FPDMA QUEUED (NCQ)
167 error_flag[7] = icrc;
168 error_flag[6] = unc;
169 error_flag[5] = mc;
170 error_flag[4] = idnf;
171 error_flag[3] = mcr;
172 error_flag[2] = abrt;
173 error_flag[1] = nm;
174 error_flag[0] = amnf;
175 print_lba=1;
176 if (CR==0x25 || CR==0xC8)
177 print_sector=SC;
178 break;
179 case 0x30: /* WRITE SECTOR(S) */
180 case 0x31: // WRITE SECTOR(S)
181 case 0x34: // WRITE SECTOR(S) EXT
182 case 0xC5: /* WRITE MULTIPLE */
183 case 0x39: // WRITE MULTIPLE EXT
184 case 0xCE: // WRITE MULTIPLE FUA EXT
185 error_flag[6] = wp;
186 error_flag[5] = mc;
187 error_flag[4] = idnf;
188 error_flag[3] = mcr;
189 error_flag[2] = abrt;
190 error_flag[1] = nm;
191 print_lba=1;
192 break;
193 case 0x32: // WRITE LONG (with retries)
194 case 0x33: // WRITE LONG (without retries)
195 error_flag[4] = idnf;
196 error_flag[2] = abrt;
197 print_lba=1;
198 break;
199 case 0x3C: // WRITE VERIFY
200 error_flag[6] = unc;
201 error_flag[4] = idnf;
202 error_flag[2] = abrt;
203 error_flag[0] = amnf;
204 print_lba=1;
205 break;
206 case 0x40: // READ VERIFY SECTOR(S) with retries
207 case 0x41: // READ VERIFY SECTOR(S) without retries
208 case 0x42: // READ VERIFY SECTOR(S) EXT
209 error_flag[6] = unc;
210 error_flag[5] = mc;
211 error_flag[4] = idnf;
212 error_flag[3] = mcr;
213 error_flag[2] = abrt;
214 error_flag[1] = nm;
215 error_flag[0] = amnf;
216 print_lba=1;
217 break;
218 case 0xA0: /* PACKET */
219 /* Bits 4-7 are all used for sense key (a 'command packet set specific error
220 * indication' according to the ATA/ATAPI-7 standard), so "Sense key" will
221 * be repeated in the error description string if more than one of those
222 * bits is set.
223 */
224 error_flag[7] = "Sense key (bit 3)",
225 error_flag[6] = "Sense key (bit 2)",
226 error_flag[5] = "Sense key (bit 1)",
227 error_flag[4] = "Sense key (bit 0)",
228 error_flag[2] = abrt;
229 error_flag[1] = eom;
230 error_flag[0] = ili;
231 break;
232 case 0xA1: /* IDENTIFY PACKET DEVICE */
233 case 0xEF: /* SET FEATURES */
234 case 0x00: /* NOP */
235 case 0xC6: /* SET MULTIPLE MODE */
236 error_flag[2] = abrt;
237 break;
238 case 0x2F: // READ LOG EXT
239 error_flag[6] = unc;
240 error_flag[4] = idnf;
241 error_flag[2] = abrt;
242 error_flag[0] = obs;
243 break;
244 case 0x3F: // WRITE LOG EXT
245 error_flag[4] = idnf;
246 error_flag[2] = abrt;
247 error_flag[0] = obs;
248 break;
249 case 0xB0: /* SMART */
250 switch(FR) {
251 case 0xD0: // SMART READ DATA
252 case 0xD1: // SMART READ ATTRIBUTE THRESHOLDS
253 case 0xD5: /* SMART READ LOG */
254 error_flag[6] = unc;
255 error_flag[4] = idnf;
256 error_flag[2] = abrt;
257 error_flag[0] = obs;
258 break;
259 case 0xD6: /* SMART WRITE LOG */
260 error_flag[4] = idnf;
261 error_flag[2] = abrt;
262 error_flag[0] = obs;
263 break;
264 case 0xD2: // Enable/Disable Attribute Autosave
265 case 0xD3: // SMART SAVE ATTRIBUTE VALUES (ATA-3)
266 case 0xD8: // SMART ENABLE OPERATIONS
267 case 0xD9: /* SMART DISABLE OPERATIONS */
268 case 0xDA: /* SMART RETURN STATUS */
269 case 0xDB: // Enable/Disable Auto Offline (SFF)
270 error_flag[2] = abrt;
271 break;
272 case 0xD4: // SMART EXECUTE IMMEDIATE OFFLINE
273 error_flag[4] = idnf;
274 error_flag[2] = abrt;
275 break;
276 default:
277 return str; // ""
278 break;
279 }
280 break;
281 case 0xB1: /* DEVICE CONFIGURATION */
282 switch (FR) {
283 case 0xC0: /* DEVICE CONFIGURATION RESTORE */
284 error_flag[2] = abrt;
285 break;
286 default:
287 return str; // ""
288 break;
289 }
290 break;
291 case 0xCA: // WRITE DMA (with retries)
292 case 0xCB: // WRITE DMA (without retries, obsolete since ATA-5)
293 case 0x35: // WRITE DMA EXT
294 case 0x3D: // WRITE DMA FUA EXT
295 case 0xCC: // WRITE DMA QUEUED
296 case 0x36: // WRITE DMA QUEUED EXT
297 case 0x3E: // WRITE DMA QUEUED FUA EXT
298 case 0x61: // WRITE FPDMA QUEUED (NCQ)
299 error_flag[7] = icrc;
300 error_flag[6] = wp;
301 error_flag[5] = mc;
302 error_flag[4] = idnf;
303 error_flag[3] = mcr;
304 error_flag[2] = abrt;
305 error_flag[1] = nm;
306 error_flag[0] = amnf;
307 print_lba=1;
308 if (CR==0x35)
309 print_sector=SC;
310 break;
311 case 0xE4: // READ BUFFER
312 case 0xE8: // WRITE BUFFER
313 error_flag[2] = abrt;
314 break;
315 default:
316 return str; // ""
317 }
318
319 /* We ignore any status flags other than Device Fault and Error */
320
321 if (uses_device_fault && (ST & (1 << 5))) {
322 str = "Device Fault";
323 if (ST & 1) // Error flag
324 str += "; ";
325 }
326 if (ST & 1) { // Error flag
327 int count = 0;
328
329 str += "Error: ";
330 for (i = 7; i >= 0; i--)
331 if ((ER & (1 << i)) && (error_flag[i])) {
332 if (count++ > 0)
333 str += ", ";
334 str += error_flag[i];
335 }
336 }
337
338 // If the error was a READ or WRITE error, print the Logical Block
339 // Address (LBA) at which the read or write failed.
340 if (print_lba) {
341 // print number of sectors, if known, and append to print string
342 if (print_sector)
343 str += strprintf(" %d sectors", print_sector);
344
345 if (lba28_regs) {
346 unsigned lba;
347 // bits 24-27: bits 0-3 of DH
348 lba = 0xf & lba28_regs->drive_head;
349 lba <<= 8;
350 // bits 16-23: CH
351 lba |= lba28_regs->cylinder_high;
352 lba <<= 8;
353 // bits 8-15: CL
354 lba |= lba28_regs->cylinder_low;
355 lba <<= 8;
356 // bits 0-7: SN
357 lba |= lba28_regs->sector_number;
358 str += strprintf(" at LBA = 0x%08x = %u", lba, lba);
359 }
360 else if (lba48_regs) {
361 // This assumes that upper LBA registers are 0 for 28-bit commands
362 // (TODO: detect 48-bit commands above)
363 uint64_t lba48;
364 lba48 = lba48_regs->lba_high_register_hi;
365 lba48 <<= 8;
366 lba48 |= lba48_regs->lba_mid_register_hi;
367 lba48 <<= 8;
368 lba48 |= lba48_regs->lba_low_register_hi;
369 lba48 |= lba48_regs->device_register & 0xf;
370 lba48 <<= 8;
371 lba48 |= lba48_regs->lba_high_register;
372 lba48 <<= 8;
373 lba48 |= lba48_regs->lba_mid_register;
374 lba48 <<= 8;
375 lba48 |= lba48_regs->lba_low_register;
376 str += strprintf(" at LBA = 0x%08" PRIx64 " = %" PRIu64, lba48, lba48);
377 }
378 }
379
380 return str;
381}
382
383static inline std::string format_st_er_desc(
385{
386 return format_st_er_desc(
387 data->commands[4].commandreg,
388 data->commands[4].featuresreg,
389 data->error_struct.status,
390 data->error_struct.error_register,
391 data->error_struct.sector_count,
392 &data->error_struct, (const ata_smart_exterrlog_error *)0);
393}
394
395static inline std::string format_st_er_desc(
397{
398 return format_st_er_desc(
399 data->commands[4].command_register,
400 data->commands[4].features_register,
401 data->error.status_register,
402 data->error.error_register,
403 data->error.count_register_hi << 8 | data->error.count_register,
404 (const ata_smart_errorlog_error_struct *)0, &data->error);
405}
406
407
408static const char * get_form_factor(unsigned short word168)
409{
410 // Bits 0:3 are the form factor
411 // Table A.32 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
412 // Table 247 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
413 // Table 265 of T13/BSR INCITS 574 (ACS-6) Revision 3, March 30, 2023
414 switch (word168 & 0xF) {
415 case 0x1: return "5.25 inches";
416 case 0x2: return "3.5 inches";
417 case 0x3: return "2.5 inches";
418 case 0x4: return "1.8 inches";
419 case 0x5: return "< 1.8 inches";
420 case 0x6: return "mSATA"; // ACS-4
421 case 0x7: return "M.2"; // ACS-4
422 case 0x8: return "MicroSSD"; // ACS-4
423 case 0x9: return "CFast"; // ACS-4
424 default : return 0;
425 }
426}
427
428static int find_msb(unsigned short word)
429{
430 for (int bit = 15; bit >= 0; bit--)
431 if (word & (1 << bit))
432 return bit;
433 return -1;
434}
435
436static const char * get_ata_major_version(const ata_identify_device * drive)
437{
438 // Table 13 of T13/1153D (ATA/ATAPI-4) revision 18, August 19, 1998
439 // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
440 // Table 55 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
441 // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021
442 switch (find_msb(drive->major_rev_num)) {
443 case 15: return "ACS >5 (15)";
444 case 14: return "ACS >5 (14)";
445 case 13: return "ACS >5 (13)";
446 case 12: return "ACS-5";
447 case 11: return "ACS-4";
448 case 10: return "ACS-3";
449 case 9: return "ACS-2";
450 case 8: return "ATA8-ACS";
451 case 7: return "ATA/ATAPI-7";
452 case 6: return "ATA/ATAPI-6";
453 case 5: return "ATA/ATAPI-5";
454 case 4: return "ATA/ATAPI-4";
455 case 3: return "ATA-3";
456 case 2: return "ATA-2";
457 case 1: return "ATA-1";
458 default: return 0;
459 }
460}
461
462static const char * get_ata_minor_version(const ata_identify_device * drive)
463{
464 // Table 10 of X3T13/2008D (ATA-3) Revision 7b, January 27, 1997
465 // Table 28 of T13/1410D (ATA/ATAPI-6) Revision 3b, February 26, 2002
466 // Table 31 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
467 // Table 52 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
468 // Table 47 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
469 // Table 57 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
470 // Table 59 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021
471 // Table 59 of T13/BSR INCITS 574 (ACS-6) Revision 3, March 30, 2023
472 switch (drive->minor_rev_num) {
473 case 0x0001: return "ATA-1 X3T9.2/781D prior to revision 4";
474 case 0x0002: return "ATA-1 published, ANSI X3.221-1994";
475 case 0x0003: return "ATA-1 X3T9.2/781D revision 4";
476 case 0x0004: return "ATA-2 published, ANSI X3.279-1996";
477 case 0x0005: return "ATA-2 X3T10/948D prior to revision 2k";
478 case 0x0006: return "ATA-3 X3T10/2008D revision 1";
479 case 0x0007: return "ATA-2 X3T10/948D revision 2k";
480 case 0x0008: return "ATA-3 X3T10/2008D revision 0";
481 case 0x0009: return "ATA-2 X3T10/948D revision 3";
482 case 0x000a: return "ATA-3 published, ANSI X3.298-1997";
483 case 0x000b: return "ATA-3 X3T10/2008D revision 6"; // 1st ATA-3 revision with SMART
484 case 0x000c: return "ATA-3 X3T13/2008D revision 7 and 7a";
485 case 0x000d: return "ATA/ATAPI-4 X3T13/1153D revision 6";
486 case 0x000e: return "ATA/ATAPI-4 T13/1153D revision 13";
487 case 0x000f: return "ATA/ATAPI-4 X3T13/1153D revision 7";
488 case 0x0010: return "ATA/ATAPI-4 T13/1153D revision 18";
489 case 0x0011: return "ATA/ATAPI-4 T13/1153D revision 15";
490 case 0x0012: return "ATA/ATAPI-4 published, ANSI NCITS 317-1998";
491 case 0x0013: return "ATA/ATAPI-5 T13/1321D revision 3";
492 case 0x0014: return "ATA/ATAPI-4 T13/1153D revision 14";
493 case 0x0015: return "ATA/ATAPI-5 T13/1321D revision 1";
494 case 0x0016: return "ATA/ATAPI-5 published, ANSI NCITS 340-2000";
495 case 0x0017: return "ATA/ATAPI-4 T13/1153D revision 17";
496 case 0x0018: return "ATA/ATAPI-6 T13/1410D revision 0";
497 case 0x0019: return "ATA/ATAPI-6 T13/1410D revision 3a";
498 case 0x001a: return "ATA/ATAPI-7 T13/1532D revision 1";
499 case 0x001b: return "ATA/ATAPI-6 T13/1410D revision 2";
500 case 0x001c: return "ATA/ATAPI-6 T13/1410D revision 1";
501 case 0x001d: return "ATA/ATAPI-7 published, ANSI INCITS 397-2005";
502 case 0x001e: return "ATA/ATAPI-7 T13/1532D revision 0";
503 case 0x001f: return "ACS-3 T13/2161-D revision 3b";
504
505 case 0x0021: return "ATA/ATAPI-7 T13/1532D revision 4a";
506 case 0x0022: return "ATA/ATAPI-6 published, ANSI INCITS 361-2002";
507
508 case 0x0030: return "ACS-5 T13/BSR INCITS 558 revision 10";
509
510 case 0x0027: return "ATA8-ACS T13/1699-D revision 3c";
511 case 0x0028: return "ATA8-ACS T13/1699-D revision 6";
512 case 0x0029: return "ATA8-ACS T13/1699-D revision 4";
513
514 case 0x0031: return "ACS-2 T13/2015-D revision 2";
515
516 case 0x0033: return "ATA8-ACS T13/1699-D revision 3e";
517
518 case 0x0039: return "ATA8-ACS T13/1699-D revision 4c";
519
520 case 0x0042: return "ATA8-ACS T13/1699-D revision 3f";
521
522 case 0x0052: return "ATA8-ACS T13/1699-D revision 3b";
523
524 case 0x005e: return "ACS-4 T13/BSR INCITS 529 revision 5";
525
526 case 0x006d: return "ACS-3 T13/2161-D revision 5";
527
528 case 0x0073: return "ACS-6 T13/BSR INCITS 558 revision 2";
529
530 case 0x0082: return "ACS-2 published, ANSI INCITS 482-2012";
531
532 case 0x009c: return "ACS-4 published, ANSI INCITS 529-2018";
533
534 case 0x0107: return "ATA8-ACS T13/1699-D revision 2d";
535
536 case 0x010a: return "ACS-3 published, ANSI INCITS 522-2014";
537
538 case 0x0110: return "ACS-2 T13/2015-D revision 3";
539
540 case 0x011b: return "ACS-3 T13/2161-D revision 4";
541
542 default: return 0;
543 }
544}
545
546static const char * get_pata_version(unsigned short word222, char (& buf)[32])
547{
548 // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
549 // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021
550 switch (word222 & 0x0fff) {
551 default: snprintf(buf, sizeof(buf),
552 "Unknown (0x%03x)", word222 & 0x0fff); return buf;
553 case 0x001:
554 case 0x003: return "ATA8-APT"; // OBS-ACS-5
555 case 0x002: return "ATA/ATAPI-7"; // OBS-ACS-5
556 }
557}
558
559static const char * get_sata_version(unsigned short word222)
560{
561 // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
562 // Table 50 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
563 // Table 45 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
564 // Table 55 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
565 // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021
566 switch (find_msb(word222 & 0x0fff)) {
567 case 11: return "SATA >3.5 (11)";
568 case 10: return "SATA 3.5"; // ACS-5
569 case 9: return "SATA 3.4"; // ACS-5
570 case 8: return "SATA 3.3"; // ACS-4
571 case 7: return "SATA 3.2"; // ACS-4
572 case 6: return "SATA 3.1"; // ACS-3
573 case 5: return "SATA 3.0"; // ACS-2
574 case 4: return "SATA 2.6";
575 case 3: return "SATA 2.5";
576 case 2: return "SATA II Ext";
577 case 1: return "SATA 1.0a";
578 case 0: return "ATA8-AST";
579 default: return 0;
580 }
581}
582
583static const char * get_sata_speed(int speed)
584{
585 if (speed <= 0)
586 return 0;
587 // Table 29 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
588 // Table 50 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
589 // Table 45 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
590 // Table 57 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021
591 switch (speed) {
592 default: return ">6.0 Gb/s (7)";
593 case 6: return ">6.0 Gb/s (6)";
594 case 5: return ">6.0 Gb/s (5)";
595 case 4: return ">6.0 Gb/s (4)";
596 case 3: return "6.0 Gb/s"; // ACS-3
597 case 2: return "3.0 Gb/s";
598 case 1: return "1.5 Gb/s"; // ATA8-ACS
599 }
600}
601
602static void jset_sata_speed(const char * key, int value, int speed, const char * str)
603{
604 if (speed <= 0)
605 return;
606 json::ref jref = jglb["interface_speed"][key];
607 jref["sata_value"] = value;
608 if (str)
609 jref["string"] = str;
610 int ups;
611 switch (speed) {
612 case 3: ups = 60; break;
613 case 2: ups = 30; break;
614 case 1: ups = 15; break;
615 default: return;
616 }
617 jref["units_per_second"] = ups;
618 jref["bits_per_unit"] = 100000000;
619}
620
621static void print_sata_version_and_speed(unsigned short word222,
622 unsigned short word076,
623 unsigned short word077)
624{
625 int allspeeds = (!(word076 & 0x0001) ? (word076 & 0x00fe) : 0);
626 int maxspeed = (allspeeds ? find_msb(allspeeds) : 0);
627 int curspeed = (!(word077 & 0x0001) ? ((word077 >> 1) & 0x7) : 0);
628
629 const char * verstr = get_sata_version(word222);
630 const char * maxstr = get_sata_speed(maxspeed);
631 const char * curstr = get_sata_speed(curspeed);
632 jout("SATA Version is: %s%s%s%s%s%s\n",
633 (verstr ? verstr : "Unknown"),
634 (maxstr ? ", " : ""), (maxstr ? maxstr : ""),
635 (curstr ? " (current: " : ""), (curstr ? curstr : ""),
636 (curstr ? ")" : ""));
637 if (verstr)
638 jglb["sata_version"]["string"] = verstr;
639 jglb["sata_version"]["value"] = word222 & 0x0fff;
640 jset_sata_speed("max", allspeeds, maxspeed, maxstr);
641 jset_sata_speed("current", curspeed, curspeed, curstr);
642}
643
644static void print_drive_info(const ata_identify_device * drive,
645 const ata_size_info & sizes, int rpm,
646 const drive_settings * dbentry, const char * dbversion)
647{
648 // format drive information (with byte swapping as needed)
649 char model[40+1], serial[20+1], firmware[8+1];
650 ata_format_id_string(model, drive->model, sizeof(model)-1);
651 ata_format_id_string(serial, drive->serial_no, sizeof(serial)-1);
652 ata_format_id_string(firmware, drive->fw_rev, sizeof(firmware)-1);
653
654 // Print model family if known
655 if (dbentry && *dbentry->modelfamily) {
656 jout("Model Family: %s\n", dbentry->modelfamily);
657 jglb["model_family"] = dbentry->modelfamily;
658 }
659
660 jout("Device Model: %s\n", infofound(model));
661 jglb["model_name"] = model;
662
664 jout("Serial Number: %s\n", infofound(serial));
665 jglb["serial_number"] = serial;
666
667 unsigned oui = 0; uint64_t unique_id = 0;
668 int naa = ata_get_wwn(drive, oui, unique_id);
669 if (naa >= 0) {
670 jout("LU WWN Device Id: %x %06x %09" PRIx64 "\n", naa, oui, unique_id);
671 jglb["wwn"]["naa"] = naa;
672 jglb["wwn"]["oui"] = oui;
673 jglb["wwn"]["id"] = unique_id;
674 }
675 }
676
677 // Additional Product Identifier (OEM Id) string in words 170-173
678 // (e08130r1, added in ACS-2 Revision 1, December 17, 2008)
679 if (0x2020 <= drive->words088_255[170-88] && drive->words088_255[170-88] <= 0x7e7e) {
680 char add[8+1];
681 ata_format_id_string(add, (const unsigned char *)(drive->words088_255+(170-88)), sizeof(add)-1);
682 if (add[0]) {
683 jout("Add. Product Id: %s\n", add);
684 jglb["ata_additional_product_id"] = add;
685 }
686 }
687
688 jout("Firmware Version: %s\n", infofound(firmware));
689 jglb["firmware_version"] = firmware;
690
691 if (sizes.capacity) {
692 // Print capacity
693 char num[64], cap[32];
694 jout("User Capacity: %s bytes [%s]\n",
695 format_with_thousands_sep(num, sizeof(num), sizes.capacity),
696 format_capacity(cap, sizeof(cap), sizes.capacity));
697 jglb["user_capacity"]["blocks"].set_unsafe_uint64(sizes.sectors);
698 jglb["user_capacity"]["bytes"].set_unsafe_uint64(sizes.capacity);
699
700 // Print sector sizes.
701 if (sizes.phy_sector_size == sizes.log_sector_size)
702 jout("Sector Size: %u bytes logical/physical\n", sizes.log_sector_size);
703 else {
704 jout("Sector Sizes: %u bytes logical, %u bytes physical",
705 sizes.log_sector_size, sizes.phy_sector_size);
706 if (sizes.log_sector_offset)
707 pout(" (offset %u bytes)", sizes.log_sector_offset);
708 jout("\n");
709 }
710 jglb["logical_block_size"] = sizes.log_sector_size;
711 jglb["physical_block_size"] = sizes.phy_sector_size;
712 }
713
714 // Print nominal media rotation rate if reported
715 if (rpm) {
716 if (rpm == 1)
717 jout("Rotation Rate: Solid State Device\n");
718 else if (rpm > 1)
719 jout("Rotation Rate: %d rpm\n", rpm);
720 else
721 pout("Rotation Rate: Unknown (0x%04x)\n", -rpm);
722 if (rpm > 0)
723 jglb["rotation_rate"] = (rpm == 1 ? 0 : rpm);
724 }
725
726 // Print form factor if reported
727 unsigned short word168 = drive->words088_255[168-88];
728 if (word168) {
729 const char * form_factor = get_form_factor(word168);
730 if (form_factor)
731 jout("Form Factor: %s\n", form_factor);
732 else
733 jout("Form Factor: Unknown (0x%04x)\n", word168);
734 jglb["form_factor"]["ata_value"] = word168;
735 if (form_factor)
736 jglb["form_factor"]["name"] = form_factor;
737 }
738
739 // Print TRIM support
740 bool trim_sup = !!(drive->words088_255[169-88] & 0x0001);
741 unsigned short word069 = drive->words047_079[69-47];
742 bool trim_det = !!(word069 & 0x4000), trim_zeroed = !!(word069 & 0x0020);
743 if (trim_sup || rpm == 1) // HDD: if supported (SMR), SSD: always
744 jout("TRIM Command: %s%s%s\n",
745 (!trim_sup ? "Unavailable" : "Available"),
746 (!(trim_sup && trim_det) ? "" : ", deterministic"),
747 (!(trim_sup && trim_zeroed) ? "" : ", zeroed") );
748 jglb["trim"]["supported"] = trim_sup;
749 if (trim_sup) {
750 jglb["trim"]["deterministic"] = trim_det;
751 jglb["trim"]["zeroed"] = trim_zeroed;
752 }
753
754 // Print Zoned Device Capabilities if reported
755 // (added in ACS-4, obsoleted in ACS-5)
756 unsigned short zoned_caps = word069 & 0x3;
757 if (zoned_caps) {
758 jout("Zoned Device: %s\n",
759 (zoned_caps == 0x1 ? "Host Aware Zones" :
760 zoned_caps == 0x2 ? "Device managed zones" : "Unknown (0x3)"));
761 if (zoned_caps < 0x3)
762 jglb["zoned_device"]["capabilities"] = (zoned_caps == 0x1 ? "host_aware" : "device_managed");
763 }
764
765 // See if drive is recognized
766 jout("Device is: %s%s%s\n",
767 (dbentry ? "In smartctl database" : "Not in smartctl database"),
768 (*dbversion ? " " : ""), (*dbversion ? dbversion : ""));
769 jglb["in_smartctl_database"] = !!dbentry;
770
771 // Print ATA version
772 std::string ataver;
773 if ( (drive->major_rev_num != 0x0000 && drive->major_rev_num != 0xffff)
774 || (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff)) {
775 const char * majorver = get_ata_major_version(drive);
776 const char * minorver = get_ata_minor_version(drive);
777
778 if (majorver && minorver && str_starts_with(minorver, majorver)) {
779 // Major and minor strings match, print minor string only
780 ataver = minorver;
781 }
782 else {
783 if (majorver)
784 ataver = majorver;
785 else
786 ataver = strprintf("Unknown(0x%04x)", drive->major_rev_num);
787
788 if (minorver)
789 ataver += strprintf(", %s", minorver);
790 else if (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff)
791 ataver += strprintf(" (unknown minor revision code: 0x%04x)", drive->minor_rev_num);
792 else
793 ataver += " (minor revision not indicated)";
794 }
795 }
796 jout("ATA Version is: %s\n", infofound(ataver.c_str()));
797 if (!ataver.empty()) {
798 jglb["ata_version"]["string"] = ataver;
799 jglb["ata_version"]["major_value"] = drive->major_rev_num;
800 jglb["ata_version"]["minor_value"] = drive->minor_rev_num;
801 }
802
803 // Print Transport specific version
804 unsigned short word222 = drive->words088_255[222-88];
805 if (word222 != 0x0000 && word222 != 0xffff) switch (word222 >> 12) {
806 case 0x0: // PATA
807 {
808 char buf[32] = "";
809 pout("Transport Type: Parallel, %s\n", get_pata_version(word222, buf));
810 }
811 break;
812 case 0x1: // SATA
814 drive->words047_079[76-47],
815 drive->words047_079[77-47]);
816 break;
817 case 0xe: // PCIe (ACS-4)
818 pout("Transport Type: PCIe (0x%03x)\n", word222 & 0x0fff);
819 break;
820 default:
821 pout("Transport Type: Unknown (0x%04x)\n", word222);
822 break;
823 }
824
825 jout_startup_datetime("Local Time is: ");
826
827 // Print warning message, if there is one
828 if (dbentry && *dbentry->warningmsg)
829 pout("\n==> WARNING: %s\n\n", dbentry->warningmsg);
830}
831
832static const char *OfflineDataCollectionStatus(unsigned char status_byte)
833{
834 unsigned char stat=status_byte & 0x7f;
835
836 switch(stat){
837 case 0x00:
838 return "was never started";
839 case 0x02:
840 return "was completed without error";
841 case 0x03:
842 if (status_byte == 0x03)
843 return "is in progress";
844 else
845 return "is in a Reserved state";
846 case 0x04:
847 return "was suspended by an interrupting command from host";
848 case 0x05:
849 return "was aborted by an interrupting command from host";
850 case 0x06:
851 return "was aborted by the device with a fatal error";
852 default:
853 if (stat >= 0x40)
854 return "is in a Vendor Specific state";
855 else
856 return "is in a Reserved state";
857 }
858}
859
860
861// prints verbose value Off-line data collection status byte
863{
864 json::ref jref = jglb["ata_smart_data"]["offline_data_collection"]["status"];
865
866 jout("Offline data collection status: (0x%02x)\t",
867 (int)data->offline_data_collection_status);
868 jref["value"] = data->offline_data_collection_status;
869
870 // Off-line data collection status byte is not a reserved
871 // or vendor specific value
872 jout("Offline data collection activity\n"
873 "\t\t\t\t\t%s.\n", OfflineDataCollectionStatus(data->offline_data_collection_status));
874 jref["string"] = OfflineDataCollectionStatus(data->offline_data_collection_status);
875 switch (data->offline_data_collection_status & 0x7f) {
876 case 0x02: jref["passed"] = true; break;
877 case 0x06: jref["passed"] = false; break;
878 }
879
880 // Report on Automatic Data Collection Status. Only IBM documents
881 // this bit. See SFF 8035i Revision 2 for details.
882 if (data->offline_data_collection_status & 0x80)
883 pout("\t\t\t\t\tAuto Offline Data Collection: Enabled.\n");
884 else
885 pout("\t\t\t\t\tAuto Offline Data Collection: Disabled.\n");
886
887 return;
888}
889
891 firmwarebug_defs firmwarebugs)
892{
893 unsigned char status = data->self_test_exec_status;
894 jout("Self-test execution status: ");
895
896 switch (data->self_test_exec_status >> 4) {
897 case 0:
898 jout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status);
899 jout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
900 break;
901 case 1:
902 jout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", status);
903 jout("the host.\n");
904 break;
905 case 2:
906 jout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", status);
907 jout("by the host with a hard or soft reset.\n");
908 break;
909 case 3:
910 jout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", status);
911 jout("occurred while the device was executing\n\t\t\t\t\t");
912 jout("its self-test routine and the device \n\t\t\t\t\t");
913 jout("was unable to complete the self-test \n\t\t\t\t\t");
914 jout("routine.\n");
915 break;
916 case 4:
917 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
918 jout("a test element that failed and the test\n\t\t\t\t\t");
919 jout("element that failed is not known.\n");
920 break;
921 case 5:
922 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
923 jout("the electrical element of the test\n\t\t\t\t\t");
924 jout("failed.\n");
925 break;
926 case 6:
927 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
928 jout("the servo (and/or seek) element of the \n\t\t\t\t\t");
929 jout("test failed.\n");
930 break;
931 case 7:
932 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
933 jout("the read element of the test failed.\n");
934 break;
935 case 8:
936 jout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", status);
937 jout("a test element that failed and the\n\t\t\t\t\t");
938 jout("device is suspected of having handling\n\t\t\t\t\t");
939 jout("damage.\n");
940 break;
941 case 15:
942 if (firmwarebugs.is_set(BUG_SAMSUNG3) && data->self_test_exec_status == 0xf0) {
943 pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", status);
944 pout("with unknown result or self-test in\n\t\t\t\t\t");
945 pout("progress with less than 10%% remaining.\n");
946 }
947 else {
948 jout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", status);
949 jout("%1d0%% of test remaining.\n", status & 0x0f);
950 }
951 break;
952 default:
953 jout("(%4d)\tReserved.\n", status);
954 break;
955 }
956
957 json::ref jref = jglb["ata_smart_data"]["self_test"]["status"];
958
959 jref["value"] = status;
960 const char * msg;
961 // TODO: Use common function for smartctl/smartd
962 switch (status >> 4) {
963 case 0x0: msg = "completed without error"; break;
964 case 0x1: msg = "was aborted by the host"; break;
965 case 0x2: msg = "was interrupted by the host with a reset"; break;
966 case 0x3: msg = "could not complete due to a fatal or unknown error"; break;
967 case 0x4: msg = "completed with error (unknown test element)"; break;
968 case 0x5: msg = "completed with error (electrical test element)"; break;
969 case 0x6: msg = "completed with error (servo/seek test element)"; break;
970 case 0x7: msg = "completed with error (read test element)"; break;
971 case 0x8: msg = "completed with error (handling damage?)"; break;
972 default: msg = 0;
973 }
974 if (msg) {
975 jref["string"] = msg;
976 switch (status >> 4) {
977 case 0x1: case 0x2: case 0x3: break; // aborted -> unknown
978 default: jref["passed"] = ((status >> 4) == 0x0);
979 }
980 }
981 else if ((status >> 4) == 0xf) {
982 jref["string"] = strprintf("in progress, %u0%% remaining", status & 0xf);
983 jref["remaining_percent"] = (status & 0xf) * 10;
984 }
985}
986
988{
989 jout("Total time to complete Offline \n");
990 jout("data collection: \t\t(%5d) seconds.\n",
991 (int)data->total_time_to_complete_off_line);
992
993 jglb["ata_smart_data"]["offline_data_collection"]["completion_seconds"] =
994 data->total_time_to_complete_off_line;
995}
996
998{
999 json::ref jref = jglb["ata_smart_data"]["capabilities"];
1000
1001 jout("Offline data collection\n");
1002 jout("capabilities: \t\t\t (0x%02x) ",
1003 (int)data->offline_data_collection_capability);
1004 jref["values"][0] = data->offline_data_collection_capability;
1005
1006 if (data->offline_data_collection_capability == 0x00){
1007 jout("\tOffline data collection not supported.\n");
1008 }
1009 else {
1011 "SMART execute Offline immediate." :
1012 "No SMART execute Offline immediate.");
1013 jref["exec_offline_immediate_supported"] = isSupportExecuteOfflineImmediate(data);
1014
1015 // TODO: Bit 1 is vendor specific
1016 pout( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)?
1017 "Auto Offline data collection on/off support.":
1018 "No Auto Offline data collection support.");
1019
1020 jout( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data)?
1021 "Abort Offline collection upon new\n\t\t\t\t\tcommand.":
1022 "Suspend Offline collection upon new\n\t\t\t\t\tcommand.");
1023 jref["offline_is_aborted_upon_new_cmd"] = isSupportOfflineAbort(data);
1024
1025 jout( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)?
1026 "Offline surface scan supported.":
1027 "No Offline surface scan supported.");
1028 jref["offline_surface_scan_supported"] = isSupportOfflineSurfaceScan(data);
1029
1030 jout( "\t\t\t\t\t%s\n", isSupportSelfTest(data)?
1031 "Self-test supported.":
1032 "No Self-test supported.");
1033 jref["self_tests_supported"] = isSupportSelfTest(data);
1034
1035 jout( "\t\t\t\t\t%s\n", isSupportConveyanceSelfTest(data)?
1036 "Conveyance Self-test supported.":
1037 "No Conveyance Self-test supported.");
1038 jref["conveyance_self_test_supported"] = isSupportConveyanceSelfTest(data);
1039
1040 jout( "\t\t\t\t\t%s\n", isSupportSelectiveSelfTest(data)?
1041 "Selective Self-test supported.":
1042 "No Selective Self-test supported.");
1043 jref["selective_self_test_supported"] = isSupportSelectiveSelfTest(data);
1044 }
1045}
1046
1048{
1049 json::ref jref = jglb["ata_smart_data"]["capabilities"];
1050
1051 jout("SMART capabilities: ");
1052 jout("(0x%04x)\t", (int)data->smart_capability);
1053 jref["values"][1] = data->smart_capability;
1054
1055 if (data->smart_capability == 0x00)
1056 jout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
1057 else {
1058 jout("%s\n", (data->smart_capability & 0x01)?
1059 "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
1060 "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
1061 jref["attribute_autosave_enabled"] = !!(data->smart_capability & 0x01);
1062
1063 // TODO: Info possibly invalid or misleading
1064 // ATA-3 - ATA-5: Bit shall be set
1065 // ATA-6 - ACS-3: Bit shall be set to indicate support for
1066 // SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE
1067 if (data->smart_capability & 0x02)
1068 pout("\t\t\t\t\tSupports SMART auto save timer.\n");
1069 }
1070}
1071
1073{
1074 bool capable = isSmartErrorLogCapable(data, identity);
1075 jout("Error logging capability: (0x%02x)\tError logging %ssupported.\n",
1076 data->errorlog_capability, (capable ? "" : "NOT "));
1077 jglb["ata_smart_data"]["capabilities"]["error_logging_supported"] = capable;
1078}
1079
1081{
1082 jout("Short self-test routine \n");
1083 if (isSupportSelfTest(data)) {
1084 jout("recommended polling time: \t (%4d) minutes.\n",
1085 (int)data->short_test_completion_time);
1086 jglb["ata_smart_data"]["self_test"]["polling_minutes"]["short"] =
1087 data->short_test_completion_time;
1088 }
1089 else
1090 jout("recommended polling time: \t Not Supported.\n");
1091}
1092
1094{
1095 jout("Extended self-test routine\n");
1096 if (isSupportSelfTest(data)) {
1097 jout("recommended polling time: \t (%4d) minutes.\n",
1099 jglb["ata_smart_data"]["self_test"]["polling_minutes"]["extended"] =
1101 }
1102 else
1103 jout("recommended polling time: \t Not Supported.\n");
1104}
1105
1107{
1108 jout("Conveyance self-test routine\n");
1110 jout("recommended polling time: \t (%4d) minutes.\n",
1111 (int)data->conveyance_test_completion_time);
1112 jglb["ata_smart_data"]["self_test"]["polling_minutes"]["conveyance"] =
1113 data->conveyance_test_completion_time;
1114 }
1115 else
1116 jout("recommended polling time: \t Not Supported.\n");
1117}
1118
1119// Check SMART attribute table for Threshold failure
1120// onlyfailed=0: are or were any age or prefailure attributes <= threshold
1121// onlyfailed=1: are any prefailure attributes <= threshold now
1123 const ata_smart_thresholds_pvt * thresholds,
1124 const ata_vendor_attr_defs & defs, int onlyfailed)
1125{
1126 for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
1127 const ata_smart_attribute & attr = data->vendor_attributes[i];
1128
1129 ata_attr_state state = ata_get_attr_state(attr, i, thresholds->thres_entries, defs);
1130
1131 if (!onlyfailed) {
1132 if (state >= ATTRSTATE_FAILED_PAST)
1133 return attr.id;
1134 }
1135 else {
1137 return attr.id;
1138 }
1139 }
1140 return 0;
1141}
1142
1143static void set_json_globals_from_smart_attrib(int id, const char * name,
1144 const ata_vendor_attr_defs & defs,
1145 uint8_t normval, uint8_t threshold,
1146 uint64_t rawval)
1147{
1148 switch (id) {
1149 case 9:
1150 if (!str_starts_with(name, "Power_On_"))
1151 return;
1152 {
1153 int minutes = -1;
1154 switch (defs[id].raw_format) {
1155 case RAWFMT_RAW48: case RAWFMT_RAW64:
1157 case RAWFMT_SEC2HOUR: minutes = (rawval / 60) % 60; rawval /= 60*60; break;
1158 case RAWFMT_MIN2HOUR: minutes = rawval % 60; rawval /= 60; break;
1159 case RAWFMT_HALFMIN2HOUR: minutes = (rawval / 2) % 60; rawval /= 2*60; break;
1160 case RAWFMT_DEFAULT: // No database entry:
1161 rawval &= 0xffffffffULL; // ignore milliseconds from RAWFMT_MSEC24_HOUR32
1162 break;
1164 minutes = (int)(rawval >> 32) / (1000*60);
1165 if (minutes >= 60)
1166 minutes = -1;
1167 rawval &= 0xffffffffULL;
1168 break;
1169 default: return;
1170 }
1171 if (rawval > 0x00ffffffULL)
1172 return; // assume bogus value
1173 jglb["power_on_time"]["hours"] = rawval;
1174 if (minutes >= 0)
1175 jglb["power_on_time"]["minutes"] = minutes;
1176 }
1177 return;
1178 case 12:
1179 if (strcmp(name, "Power_Cycle_Count"))
1180 return;
1181 switch (defs[id].raw_format) {
1182 case RAWFMT_DEFAULT: case RAWFMT_RAW48: case RAWFMT_RAW64:
1184 default: return;
1185 }
1186 if (rawval > 0x00ffffffULL)
1187 return; // assume bogus value
1188 jglb["power_cycle_count"] = rawval;
1189 return;
1190 //case 194:
1191 // Temperature set separately from ata_return_temperature_value() below
1192 }
1193
1194 // Guess available spare and endurance from normalized value of related attributes
1195 // (In many cases, the normalized value starts at 100)
1196 static const regular_expression spare_regex(
1197 "Reallocated_Sector_C.*|Retired_Block_C.*|"
1198 "(Remain.*_)?Spare_Blocks(_(Avail|Remain).*)?" // TODO: Unify names in drivedb.h
1199 );
1200 if ((id == 5 || id == 17 || id >= 100) && spare_regex.full_match(name)) {
1201 jglb["spare_available"]["current_percent"] = (normval <= 100 ? normval : 100);
1202 if (0 < threshold && threshold < 50)
1203 jglb["spare_available"]["threshold_percent"] = threshold;
1204 return;
1205 }
1206
1207 static const regular_expression endurance_regex(
1208 "SSD_Life_Left.*|Wear_Leveling.*"
1209 );
1210 if (id >= 100 && endurance_regex.full_match(name)) {
1211 // May be later overridden by Device Statistics
1212 jglb["endurance_used"]["current_percent"] = (normval <= 100 ? 100 - normval : 0);
1213 return;
1214 }
1215}
1216
1217// onlyfailed=0 : print all attribute values
1218// onlyfailed=1: just ones that are currently failed and have prefailure bit set
1219// onlyfailed=2: ones that are failed, or have failed with or without prefailure bit set
1221 const ata_smart_thresholds_pvt * thresholds,
1222 const ata_vendor_attr_defs & defs, int rpm,
1223 int onlyfailed, unsigned char format)
1224{
1225 bool brief = !!(format & ata_print_options::FMT_BRIEF);
1226 bool hexid = !!(format & ata_print_options::FMT_HEX_ID);
1227 bool hexval = !!(format & ata_print_options::FMT_HEX_VAL);
1228 bool needheader = true;
1229
1230 // step through all vendor attributes
1231 for (int i = 0, ji = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
1232 const ata_smart_attribute & attr = data->vendor_attributes[i];
1233
1234 // Check attribute and threshold
1235 unsigned char threshold = 0;
1236 ata_attr_state state = ata_get_attr_state(attr, i, thresholds->thres_entries, defs, &threshold);
1237 if (state == ATTRSTATE_NON_EXISTING)
1238 continue;
1239
1240 // These break out of the loop if we are only printing certain entries...
1241 if (onlyfailed == 1 && !(ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) && state == ATTRSTATE_FAILED_NOW))
1242 continue;
1243
1244 if (onlyfailed == 2 && state < ATTRSTATE_FAILED_PAST)
1245 continue;
1246
1247 // print header only if needed
1248 if (needheader) {
1249 if (!onlyfailed) {
1250 jout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber);
1251 jglb["ata_smart_attributes"]["revision"] = data->revnumber;
1252 jout("Vendor Specific SMART Attributes with Thresholds:\n");
1253 }
1254 if (!brief)
1255 jout("ID#%s ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n",
1256 (!hexid ? "" : " "));
1257 else
1258 jout("ID#%s ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE\n",
1259 (!hexid ? "" : " "));
1260 needheader = false;
1261 }
1262
1263 // Format value, worst, threshold
1264 std::string valstr, worstr, threstr;
1265 if (state > ATTRSTATE_NO_NORMVAL)
1266 valstr = (!hexval ? strprintf("%.3d", attr.current)
1267 : strprintf("0x%02x", attr.current));
1268 else
1269 valstr = (!hexval ? "---" : "----");
1270 if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL))
1271 worstr = (!hexval ? strprintf("%.3d", attr.worst)
1272 : strprintf("0x%02x", attr.worst));
1273 else
1274 worstr = (!hexval ? "---" : "----");
1275 if (state > ATTRSTATE_NO_THRESHOLD)
1276 threstr = (!hexval ? strprintf("%.3d", threshold)
1277 : strprintf("0x%02x", threshold));
1278 else
1279 threstr = (!hexval ? "---" : "----");
1280
1281 // Print line for each valid attribute
1282 std::string idstr = (!hexid ? strprintf("%3d", attr.id)
1283 : strprintf("0x%02x", attr.id));
1284 std::string attrname = ata_get_smart_attr_name(attr.id, defs, rpm);
1285 std::string rawstr = ata_format_attr_raw_value(attr, defs);
1286
1287 char flagstr[] = {
1288 (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) ? 'P' : '-'),
1289 (ATTRIBUTE_FLAGS_ONLINE(attr.flags) ? 'O' : '-'),
1290 (ATTRIBUTE_FLAGS_PERFORMANCE(attr.flags) ? 'S' : '-'),
1291 (ATTRIBUTE_FLAGS_ERRORRATE(attr.flags) ? 'R' : '-'),
1292 (ATTRIBUTE_FLAGS_EVENTCOUNT(attr.flags) ? 'C' : '-'),
1293 (ATTRIBUTE_FLAGS_SELFPRESERVING(attr.flags) ? 'K' : '-'),
1294 (ATTRIBUTE_FLAGS_OTHER(attr.flags) ? '+' : ' '),
1295 0
1296 };
1297
1298 if (!brief)
1299 jout("%s %-24s0x%04x %-4s %-4s %-4s %-10s%-9s%-12s%s\n",
1300 idstr.c_str(), attrname.c_str(), attr.flags,
1301 valstr.c_str(), worstr.c_str(), threstr.c_str(),
1302 (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) ? "Pre-fail" : "Old_age"),
1303 (ATTRIBUTE_FLAGS_ONLINE(attr.flags) ? "Always" : "Offline"),
1304 (state == ATTRSTATE_FAILED_NOW ? "FAILING_NOW" :
1305 state == ATTRSTATE_FAILED_PAST ? "In_the_past"
1306 : " -" ) ,
1307 rawstr.c_str());
1308 else
1309 jout("%s %-24s%s %-4s %-4s %-4s %-5s%s\n",
1310 idstr.c_str(), attrname.c_str(), flagstr,
1311 valstr.c_str(), worstr.c_str(), threstr.c_str(),
1312 (state == ATTRSTATE_FAILED_NOW ? "NOW" :
1313 state == ATTRSTATE_FAILED_PAST ? "Past"
1314 : "-" ),
1315 rawstr.c_str());
1316
1317 if (!jglb.is_enabled())
1318 continue;
1319
1320 json::ref jref = jglb["ata_smart_attributes"]["table"][ji++];
1321 jref["id"] = attr.id;
1322 jref["name"] = attrname;
1323 if (state > ATTRSTATE_NO_NORMVAL)
1324 jref["value"] = attr.current;
1325 if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL))
1326 jref["worst"] = attr.worst;
1327 if (state > ATTRSTATE_NO_THRESHOLD) {
1328 jref["thresh"] = threshold;
1329 jref["when_failed"] = (state == ATTRSTATE_FAILED_NOW ? "now" :
1330 state == ATTRSTATE_FAILED_PAST ? "past"
1331 : "" );
1332 }
1333
1334 json::ref jreff = jref["flags"];
1335 jreff["value"] = attr.flags;
1336 jreff["string"] = flagstr;
1337 jreff["prefailure"] = !!ATTRIBUTE_FLAGS_PREFAILURE(attr.flags);
1338 jreff["updated_online"] = !!ATTRIBUTE_FLAGS_ONLINE(attr.flags);
1339 jreff["performance"] = !!ATTRIBUTE_FLAGS_PERFORMANCE(attr.flags);
1340 jreff["error_rate"] = !!ATTRIBUTE_FLAGS_ERRORRATE(attr.flags);
1341 jreff["event_count"] = !!ATTRIBUTE_FLAGS_EVENTCOUNT(attr.flags);
1342 jreff["auto_keep"] = !!ATTRIBUTE_FLAGS_SELFPRESERVING(attr.flags);
1343 if (ATTRIBUTE_FLAGS_OTHER(attr.flags))
1344 jreff["other"] = ATTRIBUTE_FLAGS_OTHER(attr.flags);
1345
1346 uint64_t rawval = ata_get_attr_raw_value(attr, defs);
1347 jref["raw"]["value"] = rawval;
1348 jref["raw"]["string"] = rawstr;
1349
1350 set_json_globals_from_smart_attrib(attr.id, attrname.c_str(), defs,
1351 attr.current, threshold, rawval);
1352 }
1353
1354 if (!needheader) {
1355 if (!onlyfailed && brief) {
1356 int n = (!hexid ? 28 : 29);
1357 jout("%*s||||||_ K auto-keep\n"
1358 "%*s|||||__ C event count\n"
1359 "%*s||||___ R error rate\n"
1360 "%*s|||____ S speed/performance\n"
1361 "%*s||_____ O updated online\n"
1362 "%*s|______ P prefailure warning\n",
1363 n, "", n, "", n, "", n, "", n, "", n, "");
1364 }
1365 pout("\n");
1366 }
1367
1368 if (!jglb.is_enabled())
1369 return;
1370
1371 // Protocol independent temperature
1372 unsigned char t = ata_return_temperature_value(data, defs);
1373 if (t)
1374 jglb["temperature"]["current"] = t;
1375}
1376
1377// Print SMART related SCT capabilities
1379{
1380 unsigned short sctcaps = drive->words088_255[206-88];
1381 if (!(sctcaps & 0x01))
1382 return;
1383 json::ref jref = jglb["ata_sct_capabilities"];
1384 jout("SCT capabilities: \t (0x%04x)\tSCT Status supported.\n", sctcaps);
1385 jref["value"] = sctcaps;
1386 if (sctcaps & 0x08)
1387 jout("\t\t\t\t\tSCT Error Recovery Control supported.\n");
1388 jref["error_recovery_control_supported"] = !!(sctcaps & 0x08);
1389 if (sctcaps & 0x10)
1390 jout("\t\t\t\t\tSCT Feature Control supported.\n");
1391 jref["feature_control_supported"] = !!(sctcaps & 0x10);
1392 if (sctcaps & 0x20)
1393 jout("\t\t\t\t\tSCT Data Table supported.\n");
1394 jref["data_table_supported"] = !!(sctcaps & 0x20);
1395}
1396
1397
1399 firmwarebug_defs firmwarebugs)
1400{
1401 jout("General SMART Values:\n");
1402
1404
1405 if (isSupportSelfTest(data)){
1406 PrintSmartSelfExecStatus(data, firmwarebugs);
1407 }
1408
1412
1414
1415 jout( "\t\t\t\t\t%s\n", isGeneralPurposeLoggingCapable(drive)?
1416 "General Purpose Logging supported.":
1417 "No General Purpose Logging support.");
1418 jglb["ata_smart_data"]["capabilities"]["gp_logging_supported"] =
1420
1421 if (isSupportSelfTest(data)){
1424 }
1427
1428 ataPrintSCTCapability(drive);
1429
1430 jout("\n");
1431}
1432
1433// Get # sectors of a log addr, 0 if log does not exist.
1434static unsigned GetNumLogSectors(const ata_smart_log_directory * logdir, unsigned logaddr, bool gpl)
1435{
1436 if (!logdir)
1437 return 0;
1438 if (logaddr > 0xff)
1439 return 0;
1440 if (logaddr == 0)
1441 return 1;
1442 unsigned n = logdir->entry[logaddr-1].numsectors;
1443 if (gpl)
1444 // GP logs may have >255 sectors
1445 n |= logdir->entry[logaddr-1].reserved << 8;
1446 return n;
1447}
1448
1449// Get name of log.
1450static const char * GetLogName(unsigned logaddr)
1451{
1452 // Table A.2 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
1453 // Table 112 of Serial ATA Revision 3.2, August 7, 2013
1454 // Table A.2 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
1455 // Table 213 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
1456 // Table 213 of T13/BSR INCITS 558 (ACS-5) Revision 10, March 3, 2021
1457 // Table 223 of T13/BSR INCITS 574 (ACS-6) Revision 3, March 30, 2023
1458 switch (logaddr) {
1459 case 0x00: return "Log Directory";
1460 case 0x01: return "Summary SMART error log";
1461 case 0x02: return "Comprehensive SMART error log";
1462 case 0x03: return "Ext. Comprehensive SMART error log";
1463 case 0x04: return "Device Statistics log";
1464 case 0x05: return "Reserved for CFA"; // ACS-2
1465 case 0x06: return "SMART self-test log"; // OBS-ACS-5
1466 case 0x07: return "Extended self-test log"; // OBS-ACS-5
1467 case 0x08: return "Power Conditions log"; // ACS-2
1468 case 0x09: return "Selective self-test log";
1469 case 0x0a: return "Device Statistics Notification"; // ACS-3
1470 case 0x0b: return "Reserved for CFA"; // ACS-3
1471 case 0x0c: return "Pending Defects log"; // ACS-4
1472 case 0x0d: return "LPS Mis-alignment log"; // ACS-2
1473 case 0x0e: return "Reserved for ZAC-2"; // ACS-4
1474 case 0x0f: return "Sense Data for Successful NCQ Cmds log"; // ACS-4
1475 case 0x10: return "NCQ Command Error log";
1476 case 0x11: return "SATA Phy Event Counters log";
1477 //case 0x12: return "SATA NCQ Queue Management log"; // SATA 3.0/3.1, ACS-3
1478 case 0x12: return "SATA NCQ Non-Data log"; // SATA 3.2, ACS-4
1479 case 0x13: return "SATA NCQ Send and Receive log"; // SATA 3.1, ACS-3
1480 case 0x14: return "Hybrid Information log"; // SATA 3.2, ACS-4
1481 case 0x15: return "Rebuild Assist log"; // SATA 3.2, ACS-4
1482 case 0x16: return "Out Of Band Management Control log"; // ACS-5
1483 case 0x17: return "Reserved for Serial ATA";
1484 case 0x18: return "Command Duration Limits log"; // ACS-5
1485 case 0x19: return "LBA Status log"; // ACS-3
1486
1487 case 0x20: return "Streaming performance log"; // OBS-8
1488 case 0x21: return "Write stream error log";
1489 case 0x22: return "Read stream error log";
1490 case 0x23: return "Delayed sector log"; // OBS-8
1491 case 0x24: return "Current Device Internal Status Data log"; // ACS-3
1492 case 0x25: return "Saved Device Internal Status Data log"; // ACS-3
1493
1494 case 0x2f: return "Set Sector Configuration"; // ACS-4
1495 case 0x30: return "IDENTIFY DEVICE data log"; // ACS-3
1496
1497 case 0x42: return "Mutate Configurations log"; // ACS-5
1498
1499 case 0x47: return "Concurrent Positioning Ranges log"; // ACS-5
1500
1501 case 0x53: return "Sense Data log"; // ACS-5
1502
1503 case 0x59: return "Power Consumption Control log"; // ACS-6
1504
1505 case 0x61: return "Capacity/Model Number Mapping log"; // ACS-6
1506
1507 case 0xe0: return "SCT Command/Status";
1508 case 0xe1: return "SCT Data Transfer";
1509 default:
1510 if (0xa0 <= logaddr && logaddr <= 0xdf)
1511 return "Device vendor specific log";
1512 if (0x80 <= logaddr && logaddr <= 0x9f)
1513 return "Host vendor specific log";
1514 return "Reserved";
1515 }
1516 /*NOTREACHED*/
1517}
1518
1519// Get log access permissions
1520static const char * get_log_rw(unsigned logaddr)
1521{
1522 if ( ( logaddr <= 0x08)
1523 || (0x0c <= logaddr && logaddr <= 0x0d)
1524 || (0x0f <= logaddr && logaddr <= 0x14)
1525 || (0x19 == logaddr)
1526 || (0x20 <= logaddr && logaddr <= 0x25)
1527 || (0x2f <= logaddr && logaddr <= 0x30)
1528 || (0x42 == logaddr)
1529 || (0x47 == logaddr)
1530 || (0x53 == logaddr)
1531 || (0x59 == logaddr)
1532 || (0x61 == logaddr))
1533 return "R/O";
1534
1535 if ( ( logaddr <= 0x0a)
1536 || (0x15 <= logaddr && logaddr <= 0x16)
1537 || (0x18 == logaddr)
1538 || (0x80 <= logaddr && logaddr <= 0x9f)
1539 || (0xe0 <= logaddr && logaddr <= 0xe1))
1540 return "R/W";
1541
1542 if (0xa0 <= logaddr && logaddr <= 0xdf)
1543 return "VS"; // Vendor specific
1544
1545 return "-"; // Unknown/Reserved
1546}
1547
1548// Init a fake log directory, assume that standard logs are supported
1550 const ata_print_options & options)
1551{
1552 memset(logdir, 0, sizeof(*logdir));
1553 logdir->logversion = 255;
1554 logdir->entry[0x01-1].numsectors = 1;
1555 logdir->entry[0x03-1].numsectors = (options.smart_ext_error_log + (4-1)) / 4;
1556 logdir->entry[0x04-1].numsectors = 8;
1557 logdir->entry[0x06-1].numsectors = 1;
1558 logdir->entry[0x07-1].numsectors = (options.smart_ext_selftest_log + (19-1)) / 19;
1559 logdir->entry[0x09-1].numsectors = 1;
1560 logdir->entry[0x11-1].numsectors = 1;
1561 return logdir;
1562}
1563
1564// Print SMART and/or GP Log Directory
1566 const ata_smart_log_directory * smartlogdir)
1567{
1568 json::ref jref = jglb["ata_log_directory"];
1569 if (gplogdir) {
1570 jout("General Purpose Log Directory Version %u\n", gplogdir->logversion);
1571 jref["gp_dir_version"] = gplogdir->logversion;
1572 }
1573 if (smartlogdir) {
1574 jout("SMART %sLog Directory Version %u%s\n",
1575 (gplogdir ? " " : ""), smartlogdir->logversion,
1576 (smartlogdir->logversion==1 ? " [multi-sector log support]" : ""));
1577 jref["smart_dir_version"] = smartlogdir->logversion;
1578 jref["smart_dir_multi_sector"] = (smartlogdir->logversion == 1);
1579 }
1580
1581 jout("Address Access R/W Size Description\n");
1582
1583 for (unsigned i = 0, ji = 0; i <= 0xff; i++) {
1584 // Get number of sectors
1585 unsigned smart_numsect = GetNumLogSectors(smartlogdir, i, false);
1586 unsigned gp_numsect = GetNumLogSectors(gplogdir , i, true );
1587
1588 if (!(smart_numsect || gp_numsect))
1589 continue; // Log does not exist
1590
1591 const char * acc; unsigned size;
1592 if (smart_numsect == gp_numsect) {
1593 acc = "GPL,SL"; size = gp_numsect;
1594 }
1595 else if (!smart_numsect) {
1596 acc = "GPL"; size = gp_numsect;
1597 }
1598 else if (!gp_numsect) {
1599 acc = " SL"; size = smart_numsect;
1600 }
1601 else {
1602 acc = 0; size = 0;
1603 }
1604
1605 unsigned i2 = i;
1606 if (acc && ((0x80 <= i && i < 0x9f) || (0xa0 <= i && i < 0xdf))) {
1607 // Find range of Host/Device vendor specific logs with same size
1608 unsigned imax = (i < 0x9f ? 0x9f : 0xdf);
1609 for (unsigned j = i+1; j <= imax; j++) {
1610 unsigned sn = GetNumLogSectors(smartlogdir, j, false);
1611 unsigned gn = GetNumLogSectors(gplogdir , j, true );
1612
1613 if (!(sn == smart_numsect && gn == gp_numsect))
1614 break;
1615 i2 = j;
1616 }
1617 }
1618
1619 const char * name = GetLogName(i);
1620 const char * rw = get_log_rw(i);
1621
1622 if (i2 > i)
1623 jout("0x%02x-0x%02x %-6s %-3s %5u %s\n", i, i2, acc, rw, size, name);
1624 else if (acc)
1625 jout( "0x%02x %-6s %-3s %5u %s\n", i, acc, rw, size, name);
1626 else {
1627 // GPL and SL support different sizes
1628 jout( "0x%02x %-6s %-3s %5u %s\n", i, "GPL", rw, gp_numsect, name);
1629 jout( "0x%02x %-6s %-3s %5u %s\n", i, "SL", rw, smart_numsect, name);
1630 }
1631
1632 for (;;) {
1633 json::ref jrefi = jref["table"][ji++];
1634 jrefi["address"] = i;
1635 jrefi["name"] = name;
1636 if (rw[0] == 'R' && rw[1] && rw[2]) {
1637 jrefi["read"] = true;
1638 jrefi["write"] = (rw[2] == 'W');
1639 }
1640 if (gp_numsect)
1641 jrefi["gp_sectors"] = gp_numsect;
1642 if (smart_numsect)
1643 jrefi["smart_sectors"] = smart_numsect;
1644 if (i >= i2)
1645 break;
1646 i++;
1647 }
1648 }
1649 jout("\n");
1650}
1651
1652// Print hexdump of log pages.
1653// Format is compatible with 'xxd -r'.
1654static void PrintLogPages(const char * type, const unsigned char * data,
1655 unsigned char logaddr, unsigned page,
1656 unsigned num_pages, unsigned max_pages)
1657{
1658 pout("%s Log 0x%02x [%s], Page %u-%u (of %u)\n",
1659 type, logaddr, GetLogName(logaddr), page, page+num_pages-1, max_pages);
1660 for (unsigned i = 0; i < num_pages * 512; i += 16) {
1661 const unsigned char * p = data+i;
1662 pout("%07x: %02x %02x %02x %02x %02x %02x %02x %02x "
1663 "%02x %02x %02x %02x %02x %02x %02x %02x ",
1664 (page * 512) + i,
1665 p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
1666 p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15]);
1667#define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.')
1668 pout("|%c%c%c%c%c%c%c%c"
1669 "%c%c%c%c%c%c%c%c|\n",
1670 P( 0), P( 1), P( 2), P( 3), P( 4), P( 5), P( 6), P( 7),
1671 P( 8), P( 9), P(10), P(11), P(12), P(13), P(14), P(15));
1672#undef P
1673 if ((i & 0x1ff) == 0x1f0)
1674 pout("\n");
1675 }
1676}
1677
1678///////////////////////////////////////////////////////////////////////
1679// Device statistics (Log 0x04)
1680
1681// Section A.5 of T13/2161-D (ACS-3) Revision 5, October 28, 2013
1682// Section 9.5 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
1683
1685{
1686 short size; // #bytes of value, -1 for signed char
1687 const char * name;
1688};
1689
1691 { 2, "List of supported log pages" },
1692 { 0, 0 }
1693};
1694
1696 { 2, "General Statistics" },
1697 { 4, "Lifetime Power-On Resets" },
1698 { 4, "Power-on Hours" },
1699 { 6, "Logical Sectors Written" },
1700 { 6, "Number of Write Commands" },
1701 { 6, "Logical Sectors Read" },
1702 { 6, "Number of Read Commands" },
1703 { 6, "Date and Time TimeStamp" }, // ACS-3
1704 { 4, "Pending Error Count" }, // ACS-4
1705 { 2, "Workload Utilization" }, // ACS-4
1706 { 6, "Utilization Usage Rate" }, // ACS-4 (TODO: 47:40: Validity, 39:36 Basis, 7:0 Usage rate)
1707 { 7, "Resource Availability" }, // ACS-4 (TODO: 55:16 Resources, 15:0 Fraction)
1708 { 1, "Random Write Resources Used" }, // ACS-4
1709 { 0, 0 }
1710};
1711
1713 { 2, "Free-Fall Statistics" },
1714 { 4, "Number of Free-Fall Events Detected" },
1715 { 4, "Overlimit Shock Events" },
1716 { 0, 0 }
1717};
1718
1720 { 2, "Rotating Media Statistics" },
1721 { 4, "Spindle Motor Power-on Hours" },
1722 { 4, "Head Flying Hours" },
1723 { 4, "Head Load Events" },
1724 { 4, "Number of Reallocated Logical Sectors" },
1725 { 4, "Read Recovery Attempts" },
1726 { 4, "Number of Mechanical Start Failures" },
1727 { 4, "Number of Realloc. Candidate Logical Sectors" }, // ACS-3
1728 { 4, "Number of High Priority Unload Events" }, // ACS-3
1729 { 0, 0 }
1730};
1731
1733 { 2, "General Errors Statistics" },
1734 { 4, "Number of Reported Uncorrectable Errors" },
1735//{ 4, "Number of Resets Between Command Acceptance and Command Completion" },
1736 { 4, "Resets Between Cmd Acceptance and Completion" },
1737 { 4, "Physical Element Status Changed" }, // ACS-4
1738 { 0, 0 }
1739};
1740
1742 { 2, "Temperature Statistics" },
1743 { -1, "Current Temperature" },
1744 { -1, "Average Short Term Temperature" },
1745 { -1, "Average Long Term Temperature" },
1746 { -1, "Highest Temperature" },
1747 { -1, "Lowest Temperature" },
1748 { -1, "Highest Average Short Term Temperature" },
1749 { -1, "Lowest Average Short Term Temperature" },
1750 { -1, "Highest Average Long Term Temperature" },
1751 { -1, "Lowest Average Long Term Temperature" },
1752 { 4, "Time in Over-Temperature" },
1753 { -1, "Specified Maximum Operating Temperature" },
1754 { 4, "Time in Under-Temperature" },
1755 { -1, "Specified Minimum Operating Temperature" },
1756 { 0, 0 }
1757};
1758
1760 { 2, "Transport Statistics" },
1761 { 4, "Number of Hardware Resets" },
1762 { 4, "Number of ASR Events" },
1763 { 4, "Number of Interface CRC Errors" },
1764 { 0, 0 }
1765};
1766
1768 { 2, "Solid State Device Statistics" },
1769 { 1, "Percentage Used Endurance Indicator" },
1770 { 0, 0 }
1771};
1772
1782 // TODO: 0x08 Zoned Device Statistics (T13/f16136r7, January 2017)
1783 // TODO: 0x09 Command Duration Limits Statistics (ACS-5 Revision 10, March 2021)
1784 // TODO: 0x0a Command Duration Limits Statistics 2..3 (ACS-6 Revision 3, March 2023)
1785};
1786
1787const int num_devstat_infos = sizeof(devstat_infos)/sizeof(devstat_infos[0]);
1788
1789static const char * get_device_statistics_page_name(int page)
1790{
1791 if (page < num_devstat_infos)
1792 return devstat_infos[page][0].name;
1793 if (page == 0xff)
1794 return "Vendor Specific Statistics"; // ACS-4
1795 return "Unknown Statistics";
1796}
1797
1798static void set_json_globals_from_device_statistics(int page, int offset, int64_t val)
1799{
1800 switch (page) {
1801 case 1:
1802 switch (offset) {
1803 case 0x008: jglb["power_cycle_count"] = val; break; // ~= Lifetime Power-On Resets
1804 case 0x010: jglb["power_on_time"]["hours"]= val; break;
1805 }
1806 break;
1807 case 5:
1808 switch (offset) {
1809 case 0x008: jglb["temperature"]["current"] = val; break;
1810 case 0x020: jglb["temperature"]["lifetime_max"] = val; break;
1811 case 0x028: jglb["temperature"]["lifetime_min"] = val; break;
1812 case 0x050: jglb["temperature"]["lifetime_over_limit_minutes"] = val; break;
1813 case 0x058: jglb["temperature"]["op_limit_max"] = val; break;
1814 case 0x060: jglb["temperature"]["lifetime_under_limit_minutes"] = val; break;
1815 case 0x068: jglb["temperature"]["op_limit_min"] = val; break;
1816 }
1817 break;
1818 case 7:
1819 switch (offset) {
1820 case 0x008: jglb["endurance_used"]["current_percent"] = val; break;
1821 }
1822 break;
1823 }
1824}
1825
1826static void print_device_statistics_page(const json::ref & jref, const unsigned char * data, int page)
1827{
1828 const devstat_entry_info * info = (page < num_devstat_infos ? devstat_infos[page] : 0);
1829 const char * name = get_device_statistics_page_name(page);
1830
1831 // Check page number in header
1832 static const char line[] = " ===== = = === == ";
1833 if (!data[2]) {
1834 pout("0x%02x%s%s (empty) ==\n", page, line, name);
1835 return;
1836 }
1837 if (data[2] != page) {
1838 pout("0x%02x%s%s (invalid page 0x%02x in header) ==\n", page, line, name, data[2]);
1839 return;
1840 }
1841
1842 int rev = data[0] | (data[1] << 8);
1843 jout("0x%02x%s%s (rev %d) ==\n", page, line, name, rev);
1844 jref["number"] = page;
1845 jref["name"] = name;
1846 jref["revision"] = rev;
1847
1848 // Print entries
1849 int ji = 0;
1850 for (int i = 1, offset = 8; offset < 512-7; i++, offset+=8) {
1851 // Check for last known entry
1852 if (info && !info[i].size)
1853 info = 0;
1854
1855 // Skip unsupported entries
1856 unsigned char flags = data[offset+7];
1857 if (!(flags & 0x80))
1858 continue;
1859
1860 // Stop if unknown entries contain garbage data due to buggy firmware
1861 if (!info && (data[offset+5] || data[offset+6])) {
1862 pout("0x%02x 0x%03x - - [Trailing garbage ignored]\n", page, offset);
1863 break;
1864 }
1865
1866 // Get value name
1867 const char * valname = (info ? info[i].name :
1868 (page == 0xff) ? "Vendor Specific" // ACS-4
1869 : "Unknown" );
1870
1871 // Get value size, default to max if unknown
1872 int size = (info ? info[i].size : 7);
1873
1874 // Get flags (supported flag already checked above)
1875 bool valid = !!(flags & 0x40);
1876 bool normalized = !!(flags & 0x20);
1877 bool supports_dsn = !!(flags & 0x10); // ACS-3
1878 bool monitored_condition_met = !!(flags & 0x08); // ACS-3
1879 // TODO: 0x04: READ THEN INITIALIZE SUPPORTED (ACS-5)
1880 unsigned char reserved_flags = (flags & 0x07);
1881
1882 // Format value
1883 int64_t val = 0;
1884 char valstr[32];
1885 if (valid) {
1886 // Get value
1887 if (size < 0) {
1888 val = (signed char)data[offset];
1889 }
1890 else {
1891 for (int j = 0; j < size; j++)
1892 val |= (int64_t)data[offset+j] << (j*8);
1893 }
1894 snprintf(valstr, sizeof(valstr), "%" PRId64, val);
1895 }
1896 else {
1897 // Value not known (yet)
1898 valstr[0] = '-'; valstr[1] = 0;
1899 }
1900
1901 char flagstr[] = {
1902 (valid ? 'V' : '-'), // JSON only
1903 (normalized ? 'N' : '-'),
1904 (supports_dsn ? 'D' : '-'),
1905 (monitored_condition_met ? 'C' : '-'),
1906 (reserved_flags ? '+' : ' '),
1907 0
1908 };
1909
1910 jout("0x%02x 0x%03x %d %15s %s %s\n",
1911 page, offset, abs(size), valstr, flagstr+1, valname);
1912
1913 if (!jglb.is_enabled())
1914 continue;
1915
1916 json::ref jrefi = jref["table"][ji++];
1917 jrefi["offset"] = offset;
1918 jrefi["name"] = valname;
1919 jrefi["size"] = abs(size);
1920 if (valid)
1921 jrefi["value"] = val; // TODO: May be unsafe JSON int if size > 6
1922
1923 json::ref jreff = jrefi["flags"];
1924 jreff["value"] = flags;
1925 jreff["string"] = flagstr;
1926 jreff["valid"] = valid;
1927 jreff["normalized"] = normalized;
1928 jreff["supports_dsn"] = supports_dsn;
1929 jreff["monitored_condition_met"] = monitored_condition_met;
1930 if (reserved_flags)
1931 jreff["other"] = reserved_flags;
1932
1933 if (valid)
1934 set_json_globals_from_device_statistics(page, offset, val);
1935 }
1936}
1937
1938static bool print_device_statistics(ata_device * device, unsigned nsectors,
1939 const std::vector<int> & single_pages, bool all_pages, bool ssd_page,
1940 bool use_gplog)
1941{
1942 // Read list of supported pages from page 0
1943 unsigned char page_0[512] = {0, };
1944 int rc;
1945
1946 if (use_gplog)
1947 rc = ataReadLogExt(device, 0x04, 0, 0, page_0, 1);
1948 else
1949 rc = ataReadSmartLog(device, 0x04, page_0, 1);
1950 if (!rc) {
1951 jerr("Read Device Statistics page 0x00 failed\n\n");
1952 return false;
1953 }
1954
1955 unsigned char nentries = page_0[8];
1956 if (!(page_0[2] == 0 && nentries > 0)) {
1957 jerr("Device Statistics page 0x00 is invalid (page=0x%02x, nentries=%d)\n\n", page_0[2], nentries);
1958 return false;
1959 }
1960
1961 // Prepare list of pages to print
1962 std::vector<int> pages;
1963 unsigned i;
1964 if (all_pages) {
1965 // Add all supported pages
1966 for (i = 0; i < nentries; i++) {
1967 int page = page_0[8+1+i];
1968 if (page)
1969 pages.push_back(page);
1970 }
1971 ssd_page = false;
1972 }
1973 // Add manually specified pages
1974 bool print_page_0 = false;
1975 for (i = 0; i < single_pages.size() || ssd_page; i++) {
1976 int page = (i < single_pages.size() ? single_pages[i] : 0x07);
1977 if (!page)
1978 print_page_0 = true;
1979 else if (page >= (int)nsectors)
1980 pout("Device Statistics Log has only 0x%02x pages\n", nsectors);
1981 else
1982 pages.push_back(page);
1983 if (page == 0x07)
1984 ssd_page = false;
1985 }
1986
1987 json::ref jref = jglb["ata_device_statistics"];
1988
1989 // Print list of supported pages if requested
1990 if (print_page_0) {
1991 pout("Device Statistics (%s Log 0x04) supported pages\n",
1992 use_gplog ? "GP" : "SMART");
1993 jout("Page Description\n");
1994 for (i = 0; i < nentries; i++) {
1995 int page = page_0[8+1+i];
1996 const char * name = get_device_statistics_page_name(page);
1997 jout("0x%02x %s\n", page, name);
1998 jref["supported_pages"][i]["number"] = page;
1999 jref["supported_pages"][i]["name"] = name;
2000 }
2001 jout("\n");
2002 }
2003
2004 // Read & print pages
2005 if (!pages.empty()) {
2006 pout("Device Statistics (%s Log 0x04)\n",
2007 use_gplog ? "GP" : "SMART");
2008 jout("Page Offset Size Value Flags Description\n");
2009 int max_page = 0;
2010
2011 if (!use_gplog)
2012 for (i = 0; i < pages.size(); i++) {
2013 int page = pages[i];
2014 if (max_page < page && page < 0xff)
2015 max_page = page;
2016 }
2017
2018 raw_buffer pages_buf((max_page+1) * 512);
2019
2020 if (!use_gplog && !ataReadSmartLog(device, 0x04, pages_buf.data(), max_page+1)) {
2021 jerr("Read Device Statistics pages 0x00-0x%02x failed\n\n", max_page);
2022 return false;
2023 }
2024
2025 int ji = 0;
2026 for (i = 0; i < pages.size(); i++) {
2027 int page = pages[i];
2028 if (use_gplog) {
2029 if (!ataReadLogExt(device, 0x04, 0, page, pages_buf.data(), 1)) {
2030 jerr("Read Device Statistics page 0x%02x failed\n\n", page);
2031 return false;
2032 }
2033 }
2034 else if (page > max_page)
2035 continue;
2036
2037 int offset = (use_gplog ? 0 : page * 512);
2038 print_device_statistics_page(jref["pages"][ji++], pages_buf.data() + offset, page);
2039 }
2040
2041 jout("%32s|||_ C monitored condition met\n", "");
2042 jout("%32s||__ D supports DSN\n", "");
2043 jout("%32s|___ N normalized value\n\n", "");
2044 }
2045
2046 return true;
2047}
2048
2049
2050///////////////////////////////////////////////////////////////////////
2051// Pending Defects log (Log 0x0c)
2052
2053// Section 9.26 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
2054
2055static bool print_pending_defects_log(ata_device * device, unsigned nsectors,
2056 unsigned max_entries)
2057{
2058 // Read #entries from page 0
2059 unsigned char page_buf[512] = {0, };
2060 if (!ataReadLogExt(device, 0x0c, 0, 0, page_buf, 1)) {
2061 pout("Read Pending Defects log page 0x00 failed\n\n");
2062 return false;
2063 }
2064
2065 jout("Pending Defects log (GP Log 0x0c)\n");
2066 unsigned nentries = sg_get_unaligned_le32(page_buf);
2067 json::ref jref = jglb["ata_pending_defects_log"];
2068 jref["size"] = nsectors * 32 - 1;
2069 jref["count"] = nentries;
2070 if (!nentries) {
2071 jout("No Defects Logged\n\n");
2072 return true;
2073 }
2074
2075 // Print entries
2076 jout("Index LBA Hours\n");
2077 for (unsigned i = 0, pi = 1, page = 0; i < nentries && i < max_entries; i++, pi++) {
2078 // Read new page if required
2079 if (pi >= 32) {
2080 if (++page >= nsectors) {
2081 pout("Pending Defects count %u exceeds log size (#pages=%u)\n\n",
2082 nentries, nsectors);
2083 return false;
2084 }
2085 if (!ataReadLogExt(device, 0x0c, 0, page, page_buf, 1)) {
2086 pout("Read Pending Defects log page 0x%02x failed\n\n", page);
2087 return false;
2088 }
2089 pi = 0;
2090 }
2091
2092 const unsigned char * entry = page_buf + 16 * pi;
2093 unsigned hours = sg_get_unaligned_le32(entry);
2094 char hourstr[32];
2095 if (hours != 0xffffffffU)
2096 snprintf(hourstr, sizeof(hourstr), "%u", hours);
2097 else
2098 hourstr[0] = '-', hourstr[1] = 0;
2099 uint64_t lba = sg_get_unaligned_le64(entry + 8);
2100 jout("%5u %18" PRIu64 " %8s\n", i, lba, hourstr);
2101
2102 json::ref jrefi = jref["table"][i];
2103 jrefi["lba"].set_unsafe_uint64(lba);
2104 if (hours != 0xffffffffU)
2105 jrefi["power_on_hours"] = hours;
2106 }
2107
2108 if (nentries > max_entries)
2109 pout("... (%u entries not shown)\n", nentries - max_entries);
2110 jout("\n");
2111 return true;
2112}
2113
2114
2115///////////////////////////////////////////////////////////////////////
2116
2117// Print log 0x11
2118static void PrintSataPhyEventCounters(const unsigned char * data, bool reset)
2119{
2120 if (checksum(data))
2121 checksumwarning("SATA Phy Event Counters");
2122 jout("SATA Phy Event Counters (GP Log 0x11)\n");
2123 if (data[0] || data[1] || data[2] || data[3])
2124 pout("[Reserved: 0x%02x 0x%02x 0x%02x 0x%02x]\n",
2125 data[0], data[1], data[2], data[3]);
2126 jout("ID Size Value Description\n");
2127
2128 for (unsigned i = 4, ji = 0; ; ) {
2129 // Get counter id and size (bits 14:12)
2130 unsigned id = data[i] | (data[i+1] << 8);
2131 unsigned size = ((id >> 12) & 0x7) << 1;
2132 id &= 0x8fff;
2133
2134 // End of counter table ?
2135 if (!id)
2136 break;
2137 i += 2;
2138
2139 if (!(2 <= size && size <= 8 && i + size < 512)) {
2140 pout("0x%04x %u: Invalid entry\n", id, size);
2141 break;
2142 }
2143
2144 // Get value
2145 uint64_t val = 0, max_val = 0;
2146 for (unsigned j = 0; j < size; j+=2) {
2147 val |= (uint64_t)(data[i+j] | (data[i+j+1] << 8)) << (j*8);
2148 max_val |= (uint64_t)0xffffU << (j*8);
2149 }
2150 i += size;
2151
2152 // Get name
2153 const char * name;
2154 switch (id) {
2155 case 0x001: name = "Command failed due to ICRC error"; break; // Mandatory
2156 case 0x002: name = "R_ERR response for data FIS"; break;
2157 case 0x003: name = "R_ERR response for device-to-host data FIS"; break;
2158 case 0x004: name = "R_ERR response for host-to-device data FIS"; break;
2159 case 0x005: name = "R_ERR response for non-data FIS"; break;
2160 case 0x006: name = "R_ERR response for device-to-host non-data FIS"; break;
2161 case 0x007: name = "R_ERR response for host-to-device non-data FIS"; break;
2162 case 0x008: name = "Device-to-host non-data FIS retries"; break;
2163 case 0x009: name = "Transition from drive PhyRdy to drive PhyNRdy"; break;
2164 case 0x00A: name = "Device-to-host register FISes sent due to a COMRESET"; break; // Mandatory
2165 case 0x00B: name = "CRC errors within host-to-device FIS"; break;
2166 case 0x00D: name = "Non-CRC errors within host-to-device FIS"; break;
2167 case 0x00F: name = "R_ERR response for host-to-device data FIS, CRC"; break;
2168 case 0x010: name = "R_ERR response for host-to-device data FIS, non-CRC"; break;
2169 case 0x012: name = "R_ERR response for host-to-device non-data FIS, CRC"; break;
2170 case 0x013: name = "R_ERR response for host-to-device non-data FIS, non-CRC"; break;
2171 default: name = ((id & 0x8000) ? "Vendor specific" : "Unknown"); break;
2172 }
2173
2174 // Counters stop at max value, add '+' in this case
2175 jout("0x%04x %u %12" PRIu64 "%c %s\n", id, size, val,
2176 (val == max_val ? '+' : ' '), name);
2177
2178 json::ref jref = jglb["sata_phy_event_counters"]["table"][ji++];
2179 jref["id"] = id;
2180 jref["name"] = name;
2181 jref["size"] = size;
2182 jref["value"] = val;
2183 jref["overflow"] = (val == max_val);
2184 }
2185 if (reset)
2186 jout("All counters reset\n");
2187 jout("\n");
2188 jglb["sata_phy_event_counters"]["reset"] = reset;
2189}
2190
2191// Format milliseconds from error log entry as "DAYS+H:M:S.MSEC"
2192static std::string format_milliseconds(unsigned msec)
2193{
2194 unsigned days = msec / 86400000U;
2195 msec -= days * 86400000U;
2196 unsigned hours = msec / 3600000U;
2197 msec -= hours * 3600000U;
2198 unsigned min = msec / 60000U;
2199 msec -= min * 60000U;
2200 unsigned sec = msec / 1000U;
2201 msec -= sec * 1000U;
2202
2203 std::string str;
2204 if (days)
2205 str = strprintf("%2ud+", days);
2206 str += strprintf("%02u:%02u:%02u.%03u", hours, min, sec, msec);
2207 return str;
2208}
2209
2210// Get description for 'state' value from SMART Error Logs
2211static const char * get_error_log_state_desc(unsigned state)
2212{
2213 state &= 0x0f;
2214 switch (state){
2215 case 0x0: return "in an unknown state";
2216 case 0x1: return "sleeping";
2217 case 0x2: return "in standby mode";
2218 case 0x3: return "active or idle";
2219 case 0x4: return "doing SMART Offline or Self-test";
2220 default:
2221 return (state < 0xb ? "in a reserved state"
2222 : "in a vendor specific state");
2223 }
2224}
2225
2226// returns number of errors
2228 firmwarebug_defs firmwarebugs)
2229{
2230 json::ref jref = jglb["ata_smart_error_log"]["summary"];
2231 jout("SMART Error Log Version: %d\n", (int)data->revnumber);
2232 jref["revision"] = data->revnumber;
2233
2234 // Check consistency of error count and log index (pointer).
2235 // Starting with ATA/ATAPI 6, the index shall be zero if there are no log entries.
2236 if ( !( !data->ata_error_count == !data->error_log_pointer
2237 && !((data->ata_error_count - data->error_log_pointer) % 5))
2238 && !firmwarebugs.is_set(BUG_SAMSUNG2) )
2239 pout("Warning: ATA error count %d inconsistent with error log index %d\n",
2240 data->ata_error_count, data->error_log_pointer);
2241
2242 // if no errors logged, return
2243 if (!(data->ata_error_count && data->error_log_pointer)) {
2244 jout("No Errors Logged\n\n");
2245 jref["count"] = 0;
2246 return 0;
2247 }
2248 print_on();
2249 // If log pointer out of range, return
2250 if (data->error_log_pointer>5){
2251 pout("Invalid Error Log index = 0x%02x (valid range is from 1 to 5)\n",
2252 data->error_log_pointer);
2253 pout("ATA Error Count: %d (possibly also invalid)\n\n", data->ata_error_count);
2254 return 0;
2255 }
2256
2257 // starting printing error log info
2258 if (data->ata_error_count<=5)
2259 jout( "ATA Error Count: %d\n", (int)data->ata_error_count);
2260 else
2261 jout( "ATA Error Count: %d (device log contains only the most recent five errors)\n",
2262 (int)data->ata_error_count);
2263 jref["count"] = data->ata_error_count;
2264 jref["logged_count"] = (data->ata_error_count <= 5 ? data->ata_error_count : 5);
2265
2266 print_off();
2267 jout("\tCR = Command Register [HEX]\n"
2268 "\tFR = Features Register [HEX]\n"
2269 "\tSC = Sector Count Register [HEX]\n"
2270 "\tSN = Sector Number Register [HEX]\n"
2271 "\tCL = Cylinder Low Register [HEX]\n"
2272 "\tCH = Cylinder High Register [HEX]\n"
2273 "\tDH = Device/Head Register [HEX]\n"
2274 "\tDC = Device Command Register [HEX]\n"
2275 "\tER = Error register [HEX]\n"
2276 "\tST = Status register [HEX]\n"
2277 "Powered_Up_Time is measured from power on, and printed as\n"
2278 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2279 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2280
2281 // now step through the five error log data structures (table 39 of spec)
2282 for (int k = 4, ji = 0; k >= 0; k--) {
2283
2284 // The error log data structure entries are a circular buffer
2285 int i = (data->error_log_pointer + k) % 5;
2286 const ata_smart_errorlog_struct * elog = data->errorlog_struct+i;
2287 const ata_smart_errorlog_error_struct * summary = &(elog->error_struct);
2288
2289 // Spec says: unused error log structures shall be zero filled
2290 if (nonempty(elog, sizeof(*elog))){
2291 // Table 57 of T13/1532D Volume 1 Revision 3
2292 const char *msgstate = get_error_log_state_desc(summary->state);
2293 int days = (int)summary->timestamp/24;
2294
2295 // See table 42 of ATA5 spec
2296 print_on();
2297 jout("Error %d occurred at disk power-on lifetime: %d hours (%d days + %d hours)\n",
2298 (int)(data->ata_error_count+k-4), (int)summary->timestamp, days, (int)(summary->timestamp-24*days));
2299 print_off();
2300
2301 json::ref jrefi = jref["table"][ji++];
2302 jrefi["error_number"] = data->ata_error_count + k - 4;
2303 jrefi["lifetime_hours"] = summary->timestamp;
2304
2305 jout(" When the command that caused the error occurred, the device was %s.\n\n", msgstate);
2306 jout(" After command completion occurred, registers were:\n"
2307 " ER ST SC SN CL CH DH\n"
2308 " -- -- -- -- -- -- --\n"
2309 " %02x %02x %02x %02x %02x %02x %02x",
2310 (int)summary->error_register,
2311 (int)summary->status,
2312 (int)summary->sector_count,
2313 (int)summary->sector_number,
2314 (int)summary->cylinder_low,
2315 (int)summary->cylinder_high,
2316 (int)summary->drive_head);
2317
2318 {
2319 json::ref jrefir = jrefi["completion_registers"];
2320 jrefir["error"] = summary->error_register;
2321 jrefir["status"] = summary->status;
2322 jrefir["count"] = summary->sector_count;
2323 jrefir["lba"] = (summary->sector_number )
2324 | (summary->cylinder_low << 8)
2325 | (summary->cylinder_high << 16);
2326 jrefir["device"] = summary->drive_head;
2327 }
2328
2329 // Add a description of the contents of the status and error registers
2330 // if possible
2331 std::string st_er_desc = format_st_er_desc(elog);
2332 if (!st_er_desc.empty()) {
2333 jout(" %s", st_er_desc.c_str());
2334 jrefi["error_description"] = st_er_desc;
2335 }
2336 jout("\n\n");
2337 jout(" Commands leading to the command that caused the error were:\n"
2338 " CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n"
2339 " -- -- -- -- -- -- -- -- ---------------- --------------------\n");
2340 for (int j = 4, jj = 0; j >= 0; j--) {
2341 const ata_smart_errorlog_command_struct * thiscommand = elog->commands+j;
2342
2343 // Spec says: unused data command structures shall be zero filled
2344 if (nonempty(thiscommand, sizeof(*thiscommand))) {
2345 const char * atacmd = look_up_ata_command(thiscommand->commandreg, thiscommand->featuresreg);
2346 jout(" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2347 (int)thiscommand->commandreg,
2348 (int)thiscommand->featuresreg,
2349 (int)thiscommand->sector_count,
2350 (int)thiscommand->sector_number,
2351 (int)thiscommand->cylinder_low,
2352 (int)thiscommand->cylinder_high,
2353 (int)thiscommand->drive_head,
2354 (int)thiscommand->devicecontrolreg,
2355 format_milliseconds(thiscommand->timestamp).c_str(),
2356 atacmd);
2357
2358 json::ref jrefic = jrefi["previous_commands"][jj++];
2359 json::ref jreficr = jrefic["registers"];
2360 jreficr["command"] = thiscommand->commandreg;
2361 jreficr["features"] = thiscommand->featuresreg,
2362 jreficr["count"] = thiscommand->sector_count;
2363 jreficr["lba"] = (thiscommand->sector_number )
2364 | (thiscommand->cylinder_low << 8)
2365 | (thiscommand->cylinder_high << 16);
2366 jreficr["device"] = thiscommand->drive_head;
2367 jreficr["device_control"] = thiscommand->devicecontrolreg;
2368 jrefic["powerup_milliseconds"] = thiscommand->timestamp;
2369 jrefic["command_name"] = atacmd;
2370 }
2371 }
2372 jout("\n");
2373 }
2374 }
2375 print_on();
2377 pout("\n");
2378 print_off();
2379 return data->ata_error_count;
2380}
2381
2382// Print SMART Extended Comprehensive Error Log (GP Log 0x03)
2384 const firmwarebug_defs & firmwarebugs,
2385 const ata_smart_exterrlog * log,
2386 unsigned nsectors, unsigned max_errors)
2387{
2388 json::ref jref = jglb["ata_smart_error_log"]["extended"];
2389 jout("SMART Extended Comprehensive Error Log Version: %u (%u sectors)\n",
2390 log->version, nsectors);
2391 jref["revision"] = log->version;
2392 jref["sectors"] = nsectors;
2393
2394 if (!log->device_error_count) {
2395 jout("No Errors Logged\n\n");
2396 jref["count"] = 0;
2397 return 0;
2398 }
2399 print_on();
2400
2401 // Check index
2402 unsigned nentries = nsectors * 4;
2403 unsigned erridx = log->error_log_index;
2404 if (!(1 <= erridx && erridx <= nentries)){
2405 // Some Samsung disks (at least SP1614C/SW100-25, HD300LJ/ZT100-12) use the
2406 // former index from Summary Error Log (byte 1, now reserved) and set byte 2-3
2407 // to 0.
2408 if (!(erridx == 0 && 1 <= log->reserved1 && log->reserved1 <= nentries)) {
2409 pout("Invalid Error Log index = 0x%04x (reserved = 0x%02x)\n", erridx, log->reserved1);
2410 pout("Device Error Count: %d (possibly also invalid)\n\n", log->device_error_count);
2411 return 0;
2412 }
2413 pout("Invalid Error Log index = 0x%04x, trying reserved byte (0x%02x) instead\n", erridx, log->reserved1);
2414 erridx = log->reserved1;
2415 }
2416
2417 // Index base is not clearly specified by ATA8-ACS (T13/1699-D Revision 6a),
2418 // it is 1-based in practice.
2419 erridx--;
2420
2421 // Calculate #errors to print
2422 unsigned errcnt = log->device_error_count;
2423
2424 if (errcnt <= nentries)
2425 jout("Device Error Count: %u\n", log->device_error_count);
2426 else {
2427 errcnt = nentries;
2428 jout("Device Error Count: %u (device log contains only the most recent %u errors)\n",
2429 log->device_error_count, errcnt);
2430 }
2431 jref["count"] = log->device_error_count;
2432 jref["logged_count"] = errcnt;
2433
2434 if (max_errors < errcnt)
2435 errcnt = max_errors;
2436
2437 print_off();
2438 jout("\tCR = Command Register\n"
2439 "\tFEATR = Features Register\n"
2440 "\tCOUNT = Count (was: Sector Count) Register\n"
2441 "\tLBA_48 = Upper bytes of LBA High/Mid/Low Registers ] ATA-8\n"
2442 "\tLH = LBA High (was: Cylinder High) Register ] LBA\n"
2443 "\tLM = LBA Mid (was: Cylinder Low) Register ] Register\n"
2444 "\tLL = LBA Low (was: Sector Number) Register ]\n"
2445 "\tDV = Device (was: Device/Head) Register\n"
2446 "\tDC = Device Control Register\n"
2447 "\tER = Error register\n"
2448 "\tST = Status register\n"
2449 "Powered_Up_Time is measured from power on, and printed as\n"
2450 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n"
2451 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n");
2452
2453 // Recently read log page
2454 ata_smart_exterrlog log_buf;
2455 unsigned log_buf_page = ~0;
2456
2457 // Iterate through circular buffer in reverse direction
2458 for (unsigned i = 0, errnum = log->device_error_count;
2459 i < errcnt; i++, errnum--, erridx = (erridx > 0 ? erridx - 1 : nentries - 1)) {
2460
2461 // Read log page if needed
2462 const ata_smart_exterrlog * log_p;
2463 unsigned page = erridx / 4;
2464 if (page == 0)
2465 log_p = log;
2466 else {
2467 if (page != log_buf_page) {
2468 memset(&log_buf, 0, sizeof(log_buf));
2469 if (!ataReadExtErrorLog(device, &log_buf, page, 1, firmwarebugs))
2470 break;
2471 log_buf_page = page;
2472 }
2473 log_p = &log_buf;
2474 }
2475
2476 const ata_smart_exterrlog_error_log & entry = log_p->error_logs[erridx % 4];
2477
2478 json::ref jrefi = jref["table"][i];
2479 jrefi["error_number"] = errnum;
2480 jrefi["log_index"] = erridx;
2481
2482 // Skip unused entries
2483 if (!nonempty(&entry, sizeof(entry))) {
2484 jout("Error %u [%u] log entry is empty\n", errnum, erridx);
2485 continue;
2486 }
2487
2488 // Print error information
2489 print_on();
2490 const ata_smart_exterrlog_error & err = entry.error;
2491 jout("Error %u [%u] occurred at disk power-on lifetime: %u hours (%u days + %u hours)\n",
2492 errnum, erridx, err.timestamp, err.timestamp / 24, err.timestamp % 24);
2493 print_off();
2494 jrefi["lifetime_hours"] = err.timestamp;
2495
2496 const char * msgstate = get_error_log_state_desc(err.state);
2497 jout(" When the command that caused the error occurred, the device was %s.\n\n", msgstate);
2498 jrefi["device_state"]["value"] = err.state;
2499 jrefi["device_state"]["string"] = msgstate;
2500
2501 // Print registers
2502 jout(" After command completion occurred, registers were:\n"
2503 " ER -- ST COUNT LBA_48 LH LM LL DV DC\n"
2504 " -- -- -- == -- == == == -- -- -- -- --\n"
2505 " %02x -- %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
2506 err.error_register,
2507 err.status_register,
2509 err.count_register,
2514 err.lba_mid_register,
2515 err.lba_low_register,
2516 err.device_register,
2518
2519 {
2520 json::ref jrefir = jrefi["completion_registers"];
2521 jrefir["error"] = err.error_register;
2522 jrefir["status"] = err.status_register,
2523 jrefir["count"] = (err.count_register_hi << 8) | err.count_register;
2524 jrefir["lba"] = ((uint64_t)err.lba_high_register_hi << 40)
2525 | ((uint64_t)err.lba_mid_register_hi << 32)
2526 | ((uint64_t)err.lba_low_register_hi << 24)
2527 | ((unsigned)err.lba_high_register << 16)
2528 | ((unsigned)err.lba_mid_register << 8)
2529 | ((unsigned)err.lba_low_register );
2530 jrefir["device"] = err.device_register;
2531 jrefir["device_control"] = err.device_control_register;
2532 }
2533
2534 // Add a description of the contents of the status and error registers
2535 // if possible
2536 std::string st_er_desc = format_st_er_desc(&entry);
2537 if (!st_er_desc.empty()) {
2538 jout(" %s", st_er_desc.c_str());
2539 jrefi["error_description"] = st_er_desc;
2540 }
2541 jout("\n\n");
2542
2543 // Print command history
2544 jout(" Commands leading to the command that caused the error were:\n"
2545 " CR FEATR COUNT LBA_48 LH LM LL DV DC Powered_Up_Time Command/Feature_Name\n"
2546 " -- == -- == -- == == == -- -- -- -- -- --------------- --------------------\n");
2547 for (int ci = 4, cji = 0; ci >= 0; ci--) {
2548 const ata_smart_exterrlog_command & cmd = entry.commands[ci];
2549
2550 // Skip unused entries
2551 if (!nonempty(&cmd, sizeof(cmd)))
2552 continue;
2553
2554 // Print registers, timestamp and ATA command name
2555 const char * atacmd = look_up_ata_command(cmd.command_register, cmd.features_register);
2556 jout(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n",
2557 cmd.command_register,
2558 cmd.features_register_hi,
2559 cmd.features_register,
2560 cmd.count_register_hi,
2561 cmd.count_register,
2562 cmd.lba_high_register_hi,
2563 cmd.lba_mid_register_hi,
2564 cmd.lba_low_register_hi,
2565 cmd.lba_high_register,
2566 cmd.lba_mid_register,
2567 cmd.lba_low_register,
2568 cmd.device_register,
2569 cmd.device_control_register,
2570 format_milliseconds(cmd.timestamp).c_str(),
2571 atacmd);
2572
2573 json::ref jrefic = jrefi["previous_commands"][cji++];
2574 json::ref jreficr = jrefic["registers"];
2575 jreficr["command"] = cmd.command_register;
2576 jreficr["features"] = (cmd.features_register_hi << 8) | cmd.features_register;
2577 jreficr["count"] = (cmd.count_register_hi << 8) | cmd.count_register;
2578 jreficr["lba"] = ((uint64_t)cmd.lba_high_register_hi << 40)
2579 | ((uint64_t)cmd.lba_mid_register_hi << 32)
2580 | ((uint64_t)cmd.lba_low_register_hi << 24)
2581 | ((unsigned)cmd.lba_high_register << 16)
2582 | ((unsigned)cmd.lba_mid_register << 8)
2583 | ((unsigned)cmd.lba_low_register );
2584 jreficr["device"] = cmd.device_register;
2585 jreficr["device_control"] = cmd.device_control_register;
2586 jrefic["powerup_milliseconds"] = cmd.timestamp;
2587 jrefic["command_name"] = atacmd;
2588 }
2589 jout("\n");
2590 }
2591
2592 print_on();
2594 pout("\n");
2595 print_off();
2596 return log->device_error_count;
2597}
2598
2599// Print one self-test log entry.
2600// Returns:
2601// -1: self-test failed
2602// 1: extended self-test completed without error
2603// 0: otherwise
2605 unsigned testnum, unsigned char test_type,
2606 unsigned char test_status,
2607 unsigned short timestamp,
2608 uint64_t failing_lba,
2609 bool print_error_only, bool & print_header)
2610{
2611 // Check status and type for return value
2612 int retval = 0;
2613 switch (test_status >> 4) {
2614 case 0x0:
2615 if ((test_type & 0x7f) == 0x02)
2616 retval = 1; // extended self-test completed without error
2617 break;
2618 case 0x3: case 0x4:
2619 case 0x5: case 0x6:
2620 case 0x7: case 0x8:
2621 retval = -1; // self-test failed
2622 break;
2623 }
2624
2625 if (retval >= 0 && print_error_only)
2626 return retval;
2627
2628 std::string msgtest;
2629 switch (test_type) {
2630 case 0x00: msgtest = "Offline"; break;
2631 case 0x01: msgtest = "Short offline"; break;
2632 case 0x02: msgtest = "Extended offline"; break;
2633 case 0x03: msgtest = "Conveyance offline"; break;
2634 case 0x04: msgtest = "Selective offline"; break;
2635 case 0x7f: msgtest = "Abort offline test"; break;
2636 case 0x81: msgtest = "Short captive"; break;
2637 case 0x82: msgtest = "Extended captive"; break;
2638 case 0x83: msgtest = "Conveyance captive"; break;
2639 case 0x84: msgtest = "Selective captive"; break;
2640 default:
2641 if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
2642 msgtest = strprintf("Vendor (0x%02x)", test_type);
2643 else
2644 msgtest = strprintf("Reserved (0x%02x)", test_type);
2645 }
2646
2647 std::string msgstat;
2648 switch (test_status >> 4) {
2649 case 0x0: msgstat = "Completed without error"; break;
2650 case 0x1: msgstat = "Aborted by host"; break;
2651 case 0x2: msgstat = "Interrupted (host reset)"; break;
2652 case 0x3: msgstat = "Fatal or unknown error"; break;
2653 case 0x4: msgstat = "Completed: unknown failure"; break;
2654 case 0x5: msgstat = "Completed: electrical failure"; break;
2655 case 0x6: msgstat = "Completed: servo/seek failure"; break;
2656 case 0x7: msgstat = "Completed: read failure"; break;
2657 case 0x8: msgstat = "Completed: handling damage??"; break;
2658 case 0xf: msgstat = "Self-test routine in progress"; break;
2659 default: msgstat = strprintf("Unknown status (0x%x)", test_status >> 4);
2660 }
2661
2662 // Print header once
2663 if (print_header) {
2664 print_header = false;
2665 jout("Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n");
2666 }
2667
2668 char msglba[32];
2669 if (retval < 0 && failing_lba < 0xffffffffffffULL)
2670 snprintf(msglba, sizeof(msglba), "%" PRIu64, failing_lba);
2671 else {
2672 msglba[0] = '-'; msglba[1] = 0;
2673 }
2674
2675 jout("#%2u %-19s %-29s %1d0%% %8u %s\n", testnum,
2676 msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
2677
2678 jref["type"]["value"] = test_type;
2679 jref["type"]["string"] = msgtest;
2680
2681 jref["status"]["value"] = test_status;
2682 jref["status"]["string"] = msgstat;
2683 if (test_status & 0x0f)
2684 jref["status"]["remaining_percent"] = (test_status & 0x0f) * 10;
2685 switch (test_status >> 4) {
2686 case 0x1: case 0x2: case 0x3: break; // aborted -> unknown
2687 default: jref["status"]["passed"] = (retval >= 0);
2688 }
2689
2690 jref["lifetime_hours"] = timestamp;
2691
2692 if (retval < 0 && failing_lba < 0xffffffffffffULL)
2693 jref["lba"] = failing_lba;
2694
2695 return retval;
2696}
2697
2698// Print SMART Self-test log, return error count
2699static int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * log, bool allentries,
2700 firmwarebug_defs firmwarebugs)
2701{
2702 json::ref jref = jglb["ata_smart_self_test_log"]["standard"];
2703
2704 if (allentries)
2705 jout("SMART Self-test log structure revision number %d\n", log->revnumber);
2706 jref["revision"] = log->revnumber;
2707 if (log->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG))
2708 pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
2709 if (!log->mostrecenttest){
2710 if (allentries)
2711 jout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n");
2712 jref["count"] = 0;
2713 return 0;
2714 }
2715
2716 bool noheaderprinted = true;
2717 int errcnt = 0, igncnt = 0;
2718 int testnum = 1, ext_ok_testnum = -1;
2719
2720 // Iterate through circular buffer in reverse direction
2721 for (int i = 20, ji = 0; i >= 0; i--) {
2722 int j = (i + log->mostrecenttest) % 21;
2724
2725 // Skip unused entries
2726 if (!nonempty(&entry, sizeof(entry)))
2727 continue;
2728
2729 // Get LBA if valid
2730 uint64_t lba48 = (entry.lbafirstfailure < 0xffffffff ?
2731 entry.lbafirstfailure : 0xffffffffffffULL);
2732
2733 // Print entry
2734 int state = ataPrintSmartSelfTestEntry(jref["table"][ji++],
2735 testnum, entry.selftestnumber, entry.selfteststatus,
2736 entry.timestamp, lba48, !allentries, noheaderprinted);
2737
2738 if (state < 0) {
2739 // Self-test showed an error
2740 if (ext_ok_testnum < 0)
2741 errcnt++;
2742 else
2743 // Newer successful extended self-test exits
2744 igncnt++;
2745 }
2746 else if (state > 0 && ext_ok_testnum < 0) {
2747 // Latest successful extended self-test
2748 ext_ok_testnum = testnum;
2749 }
2750 testnum++;
2751 }
2752
2753 if (igncnt)
2754 jout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2755 igncnt, igncnt+errcnt, ext_ok_testnum);
2756 jref["count"] = testnum - 1;
2757 jref["error_count_total"] = igncnt + errcnt;
2758 jref["error_count_outdated"] = igncnt;
2759
2760 if (!allentries && !noheaderprinted)
2761 jout("\n");
2762
2763 return errcnt;
2764}
2765
2766// Print SMART Extended Self-test Log (GP Log 0x07)
2768 unsigned nsectors, unsigned max_entries)
2769{
2770 json::ref jref = jglb["ata_smart_self_test_log"]["extended"];
2771
2772 jout("SMART Extended Self-test Log Version: %u (%u sectors)\n",
2773 log->version, nsectors);
2774 jref["revision"] = log->version;
2775 jref["sectors"] = nsectors;
2776
2777 if (!log->log_desc_index){
2778 jout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n\n");
2779 jref["count"] = 0;
2780 return 0;
2781 }
2782
2783 // Check index
2784 unsigned nentries = nsectors * 19;
2785 unsigned logidx = log->log_desc_index;
2786 if (logidx > nentries) {
2787 pout("Invalid Self-test Log index = 0x%04x (reserved = 0x%02x)\n", logidx, log->reserved1);
2788 return 0;
2789 }
2790
2791 // Index base is not clearly specified by ATA8-ACS (T13/1699-D Revision 6a),
2792 // it is 1-based in practice.
2793 logidx--;
2794
2795 bool print_header = true;
2796 int errcnt = 0, igncnt = 0;
2797 int ext_ok_testnum = -1;
2798 unsigned testnum = 1;
2799
2800 // Iterate through circular buffer in reverse direction
2801 for (unsigned i = 0, ji = 0; i < nentries && testnum <= max_entries;
2802 i++, logidx = (logidx > 0 ? logidx - 1 : nentries - 1)) {
2803
2804 const ata_smart_extselftestlog_desc & entry = log[logidx / 19].log_descs[logidx % 19];
2805
2806 // Skip unused entries
2807 if (!nonempty(&entry, sizeof(entry)))
2808 continue;
2809
2810 // Get LBA
2811 const unsigned char * b = entry.failing_lba;
2812 uint64_t lba48 = b[0]
2813 | ( b[1] << 8)
2814 | ( b[2] << 16)
2815 | ((uint64_t)b[3] << 24)
2816 | ((uint64_t)b[4] << 32)
2817 | ((uint64_t)b[5] << 40);
2818
2819 // Print entry
2820 int state = ataPrintSmartSelfTestEntry(jref["table"][ji++],
2821 testnum, entry.self_test_type,
2822 entry.self_test_status, entry.timestamp, lba48,
2823 false /*!print_error_only*/, print_header);
2824
2825 if (state < 0) {
2826 // Self-test showed an error
2827 if (ext_ok_testnum < 0)
2828 errcnt++;
2829 else
2830 // Newer successful extended self-test exits
2831 igncnt++;
2832 }
2833 else if (state > 0 && ext_ok_testnum < 0) {
2834 // Latest successful extended self-test
2835 ext_ok_testnum = testnum;
2836 }
2837 testnum++;
2838 }
2839
2840 if (igncnt)
2841 jout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2842 igncnt, igncnt+errcnt, ext_ok_testnum);
2843 jref["count"] = testnum - 1;
2844 jref["error_count_total"] = igncnt + errcnt;
2845 jref["error_count_outdated"] = igncnt;
2846
2847 jout("\n");
2848 return errcnt;
2849}
2850
2852{
2853 json::ref jref = jglb["ata_smart_selective_self_test_log"];
2854
2855 // print data structure revision number
2856 jout("SMART Selective self-test log data structure revision number %d\n", log->logversion);
2857 jref["revision"] = log->logversion;
2858 if (1 != log->logversion)
2859 pout("Note: revision number not 1 implies that no selective self-test has ever been run\n");
2860
2861 const char *msg;
2862 switch((sv->self_test_exec_status)>>4){
2863 case 0:msg="Completed";
2864 break;
2865 case 1:msg="Aborted_by_host";
2866 break;
2867 case 2:msg="Interrupted";
2868 break;
2869 case 3:msg="Fatal_error";
2870 break;
2871 case 4:msg="Completed_unknown_failure";
2872 break;
2873 case 5:msg="Completed_electrical_failure";
2874 break;
2875 case 6:msg="Completed_servo/seek_failure";
2876 break;
2877 case 7:msg="Completed_read_failure";
2878 break;
2879 case 8:msg="Completed_handling_damage??";
2880 break;
2881 case 15:msg="Self_test_in_progress";
2882 break;
2883 default:msg="Unknown_status ";
2884 break;
2885 }
2886
2887 // find the number of columns needed for printing. If in use, the
2888 // start/end of span being read-scanned...
2889 uint64_t maxl = 0, maxr = 0;
2890 uint64_t current = log->currentlba;
2891 uint64_t currentend = current + 0xffff;
2892 if (log->currentspan>5) {
2893 maxl=current;
2894 maxr=currentend;
2895 }
2896 for (int i = 0; i < 5; i++) {
2897 uint64_t start=log->span[i].start;
2898 uint64_t end =log->span[i].end;
2899 // ... plus max start/end of each of the five test spans.
2900 if (start>maxl)
2901 maxl=start;
2902 if (end > maxr)
2903 maxr=end;
2904 }
2905
2906 // we need at least 7 characters wide fields to accommodate the
2907 // labels
2908 int field1,field2;
2909 char tmp[64];
2910 if ((field1=snprintf(tmp,64, "%" PRIu64, maxl))<7)
2911 field1=7;
2912 if ((field2=snprintf(tmp,64, "%" PRIu64, maxr))<7)
2913 field2=7;
2914
2915 // now print the five test spans
2916 jout(" SPAN %*s %*s CURRENT_TEST_STATUS\n", field1, "MIN_LBA", field2, "MAX_LBA");
2917
2918 for (int i = 0; i < 5; i++) {
2919 uint64_t start=log->span[i].start;
2920 uint64_t end=log->span[i].end;
2921 bool active = (i + 1 == log->currentspan);
2922
2923 if (active)
2924 // this span is currently under test
2925 jout(" %d %*" PRIu64 " %*" PRIu64 " %s [%01d0%% left] (%" PRIu64 "-%" PRIu64 ")\n",
2926 i + 1, field1, start, field2, end, msg,
2927 (sv->self_test_exec_status & 0xf), current, currentend);
2928 else
2929 // this span is not currently under test
2930 jout(" %d %*" PRIu64 " %*" PRIu64 " Not_testing\n",
2931 i + 1, field1, start, field2, end);
2932
2933 json::ref jrefi = jref["table"][i];
2934 jrefi["lba_min"] = start;
2935 jrefi["lba_max"] = end;
2936 jrefi["status"]["value"] = sv->self_test_exec_status;
2937 jrefi["status"]["string"] = (active ? msg : "Not_testing");
2938 if (active) {
2939 jrefi["status"]["remaining_percent"] = sv->self_test_exec_status & 0xf;
2940 jrefi["current_lba_min"] = current;
2941 jrefi["current_lba_max"] = currentend;
2942 }
2943 }
2944
2945 // if we are currently read-scanning, print LBAs and the status of
2946 // the read scan
2947 if (log->currentspan > 5) {
2949 jout("%5d %*" PRIu64 " %*" PRIu64 " Read_scanning %s\n",
2950 log->currentspan, field1, current, field2, currentend, ost);
2951 json::ref jrefc = jref["current_read_scan"];
2952 jrefc["lba_min"] = current;
2953 jrefc["lba_max"] = currentend;
2954 jrefc["status"]["value"] = sv->offline_data_collection_status;
2955 jrefc["status"]["string"] = ost;
2956 }
2957
2958 /* Print selective self-test flags. Possible flag combinations are
2959 (numbering bits from 0-15):
2960 Bit-1 Bit-3 Bit-4
2961 Scan Pending Active
2962 0 * * Don't scan
2963 1 0 0 Will carry out scan after selective test
2964 1 1 0 Waiting to carry out scan after powerup
2965 1 0 1 Currently scanning
2966 1 1 1 Currently scanning
2967 */
2968
2969 jout("Selective self-test flags (0x%x):\n", (unsigned)log->flags);
2970 json::ref jreff = jref["flags"];
2971 jreff["value"] = log->flags;
2972 jreff["remainder_scan_enabled"] = !!(log->flags & SELECTIVE_FLAG_DOSCAN);
2973 if (log->flags & SELECTIVE_FLAG_DOSCAN) {
2974 if (log->flags & SELECTIVE_FLAG_ACTIVE)
2975 jout(" Currently read-scanning the remainder of the disk.\n");
2976 else if (log->flags & SELECTIVE_FLAG_PENDING)
2977 jout(" Read-scan of remainder of disk interrupted; will resume %d min after power-up.\n",
2978 log->pendingtime);
2979 else
2980 jout(" After scanning selected spans, read-scan remainder of disk.\n");
2981 jreff["remainder_scan_active"] = !!(log->flags & SELECTIVE_FLAG_ACTIVE);
2982 jreff["power_up_scan_pending"] = !!(log->flags & SELECTIVE_FLAG_PENDING);
2983 }
2984 else
2985 jout(" After scanning selected spans, do NOT read-scan remainder of disk.\n");
2986
2987 // print pending time
2988 jout("If Selective self-test is pending on power-up, resume after %d minute delay.\n",
2989 log->pendingtime);
2990 jref["power_up_scan_resume_minutes"] = log->pendingtime;
2991}
2992
2993// Format SCT Temperature value
2994static const char * sct_ptemp(signed char x, char (& buf)[20])
2995{
2996 if (x == -128 /*0x80 = unknown*/)
2997 return " ?";
2998 snprintf(buf, sizeof(buf), "%2d", x);
2999 return buf;
3000}
3001
3002static void sct_jtemp2(const json::ref & jref, const char * name, signed char x)
3003{
3004 if (x == -128 /*0x80 = unknown*/)
3005 return;
3006 jglb["temperature"][name] = x;
3007 jref["temperature"][name] = x;
3008}
3009
3010static const char * sct_pbar(int x, char (& buf)[64])
3011{
3012 if (x <= 19)
3013 x = 0;
3014 else
3015 x -= 19;
3016 bool ov = false;
3017 if (x > 40) {
3018 x = 40; ov = true;
3019 }
3020 if (x > 0) {
3021 memset(buf, '*', x);
3022 if (ov)
3023 buf[x-1] = '+';
3024 buf[x] = 0;
3025 }
3026 else {
3027 buf[0] = '-'; buf[1] = 0;
3028 }
3029 return buf;
3030}
3031
3032static const char * sct_device_state_msg(unsigned char state)
3033{
3034 switch (state) {
3035 case 0: return "Active";
3036 case 1: return "Stand-by";
3037 case 2: return "Sleep";
3038 case 3: return "DST executing in background";
3039 case 4: return "SMART Off-line Data Collection executing in background";
3040 case 5: return "SCT command executing in background";
3041 default:return "Unknown";
3042 }
3043}
3044
3045// Print SCT Status
3047{
3048 json::ref jref = jglb["ata_sct_status"];
3049
3050 jout("SCT Status Version: %u\n", sts->format_version);
3051 jref["format_version"] = sts->format_version;
3052 jout("SCT Version (vendor specific): %u (0x%04x)\n", sts->sct_version, sts->sct_version);
3053 jref["sct_version"] = sts->sct_version;
3054 // SCT Support Level (1) from original SCT draft was later declared obsolete in ATA-8 ACS.
3055 // Drives typically return 0 or 1. Print only if unknown value is returned.
3056 if (sts->sct_spec > 1)
3057 pout("SCT Support Level: %u\n", sts->sct_spec);
3058 const char * statestr = sct_device_state_msg(sts->device_state);
3059 jout("Device State: %s (%u)\n", statestr, sts->device_state);
3060 jref["device_state"]["value"] = sts->device_state;
3061 jref["device_state"]["string"] = statestr;
3062
3063 // If "Reserved" fields not set, assume "old" format version 2:
3064 // Table 11 of T13/1701DT-N (SMART Command Transport) Revision 5, February 2005
3065 // Table 54 of T13/1699-D (ATA8-ACS) Revision 3e, July 2006
3066 // ... else assume "new" format version 2 or version 3:
3067 // T13/e06152r0-3 (Additional SCT Temperature Statistics), August - October 2006
3068 // Table 60 of T13/1699-D (ATA8-ACS) Revision 3f, December 2006 (format version 2)
3069 // Table 80 of T13/1699-D (ATA8-ACS) Revision 6a, September 2008 (format version 3)
3070 // Table 194 of T13/BSR INCITS 529 (ACS-4) Revision 20, October 26, 2017
3071 // (max_op_limit, smart_status, min_erc_time)
3072 bool old_format_2 = ( !sts->min_temp && !sts->life_min_temp
3073 && !sts->under_limit_count && !sts->over_limit_count);
3074
3075 char buf1[20], buf2[20];
3076 jout("Current Temperature: %s Celsius\n",
3077 sct_ptemp(sts->hda_temp, buf1));
3078 sct_jtemp2(jref, "current", sts->hda_temp);
3079 jout("Power Cycle Min/Max Temperature: %s/%s Celsius\n",
3080 (!old_format_2 ? sct_ptemp(sts->min_temp, buf1) : "--"),
3081 sct_ptemp(sts->max_temp, buf2));
3082 if (!old_format_2)
3083 sct_jtemp2(jref, "power_cycle_min", sts->min_temp);
3084 sct_jtemp2(jref, "power_cycle_max", sts->max_temp);
3085 jout("Lifetime Min/Max Temperature: %s/%s Celsius\n",
3086 (!old_format_2 ? sct_ptemp(sts->life_min_temp, buf1) : "--"),
3087 sct_ptemp(sts->life_max_temp, buf2));
3088 if (!old_format_2)
3089 sct_jtemp2(jref, "lifetime_min", sts->life_min_temp);
3090 sct_jtemp2(jref, "lifetime_max", sts->life_max_temp);
3091 if (old_format_2)
3092 return 0;
3093
3094 if (sts->max_op_limit > 0) { // e06152r0-2: "Average Temperature"
3095 jout("Specified Max Operating Temperature: %3d Celsius\n", sts->max_op_limit);
3096 sct_jtemp2(jref, "op_limit_max", sts->max_op_limit);
3097 }
3098 jout("Under/Over Temperature Limit Count: %2u/%u\n",
3100 jref["temperature"]["under_limit_count"] = sts->under_limit_count;
3101 jref["temperature"]["over_limit_count"] = sts->over_limit_count;
3102
3103 if (sts->smart_status) { // ACS-4
3104 int passed = (sts->smart_status == 0x2cf4 ? 0 :
3105 sts->smart_status == 0xc24f ? 1 : -1);
3106 jout("SMART Status: 0x%04x (%s)\n", sts->smart_status,
3107 (passed == 0 ? "FAILED" : passed > 0 ? "PASSED" : "Reserved"));
3108 if (passed >= 0) {
3109 jref["smart_status"]["passed"] = !!passed;
3110 jglb["smart_status"]["passed"] = !!passed;
3111 }
3112 else
3113 jref["smart_status"]["reserved_value"] = sts->smart_status;
3114 }
3115
3116 if (sts->min_erc_time) // ACS-4
3117 pout("Minimum supported ERC Time Limit: %d (%0.1f seconds)\n",
3118 sts->min_erc_time, sts->min_erc_time/10.0);
3119
3120 if (nonempty(sts->vendor_specific, sizeof(sts->vendor_specific))) {
3121 jout("Vendor specific:\n");
3122 for (unsigned i = 0; i < sizeof(sts->vendor_specific); i++) {
3123 jout("%02x%c", sts->vendor_specific[i], ((i & 0xf) != 0xf ? ' ' : '\n'));
3124 jref["vendor_specific"][i] = sts->vendor_specific[i];
3125 }
3126 }
3127 return 0;
3128}
3129
3130// Print SCT Temperature History Table
3132{
3133 json::ref jref = jglb["ata_sct_temperature_history"];
3134
3135 char buf1[20], buf2[20], buf3[64];
3136 jout("SCT Temperature History Version: %u%s\n", tmh->format_version,
3137 (tmh->format_version != 2 ? " (Unknown, should be 2)" : ""));
3138 jref["version"] = tmh->format_version;
3139 jout("Temperature Sampling Period: %u minute%s\n",
3140 tmh->sampling_period, (tmh->sampling_period==1?"":"s"));
3141 jref["sampling_period_minutes"] = tmh->sampling_period;
3142 jout("Temperature Logging Interval: %u minute%s\n",
3143 tmh->interval, (tmh->interval==1?"":"s"));
3144 jref["logging_interval_minutes"] = tmh->interval;
3145
3146 jout("Min/Max recommended Temperature: %s/%s Celsius\n",
3147 sct_ptemp(tmh->min_op_limit, buf1), sct_ptemp(tmh->max_op_limit, buf2));
3148 sct_jtemp2(jref, "op_limit_min", tmh->min_op_limit);
3149 sct_jtemp2(jref, "op_limit_max", tmh->max_op_limit);
3150 jout("Min/Max Temperature Limit: %s/%s Celsius\n",
3151 sct_ptemp(tmh->under_limit, buf1), sct_ptemp(tmh->over_limit, buf2));
3152 sct_jtemp2(jref, "limit_min", tmh->under_limit);
3153 sct_jtemp2(jref, "limit_max", tmh->over_limit);
3154 jout("Temperature History Size (Index): %u (%u)\n", tmh->cb_size, tmh->cb_index);
3155 jref["size"] = tmh->cb_size;
3156 jref["index"] = tmh->cb_index;
3157
3158 if (!(0 < tmh->cb_size && tmh->cb_size <= sizeof(tmh->cb) && tmh->cb_index < tmh->cb_size)) {
3159 if (!tmh->cb_size)
3160 pout("Temperature History is empty\n");
3161 else
3162 pout("Invalid Temperature History Size or Index\n");
3163 return 0;
3164 }
3165
3166 // Print table
3167 jout("\nIndex Estimated Time Temperature Celsius\n");
3168 unsigned n = 0, i = (tmh->cb_index+1) % tmh->cb_size;
3169 unsigned interval = (tmh->interval > 0 ? tmh->interval : 1);
3170 time_t t = time(0) - (time_t)(tmh->cb_size-1) * interval * 60;
3171 t -= t % (interval * 60);
3172 while (n < tmh->cb_size) {
3173 // Find range of identical temperatures
3174 unsigned n1 = n, n2 = n+1, i2 = (i+1) % tmh->cb_size;
3175 while (n2 < tmh->cb_size && tmh->cb[i2] == tmh->cb[i]) {
3176 n2++; i2 = (i2+1) % tmh->cb_size;
3177 }
3178 // Print range
3179 while (n < n2) {
3180 if (n == n1 || n == n2-1 || n2 <= n1+3) {
3181 // TODO: Don't print times < boot time
3182 char date[32] = "";
3183 struct tm tmbuf;
3184 strftime(date, sizeof(date), "%Y-%m-%d %H:%M", time_to_tm_local(&tmbuf, t));
3185 jout(" %3u %s %s %s\n", i, date,
3186 sct_ptemp(tmh->cb[i], buf1), sct_pbar(tmh->cb[i], buf3));
3187 }
3188 else if (n == n1+1) {
3189 jout(" ... ..(%3u skipped). .. %s\n",
3190 n2-n1-2, sct_pbar(tmh->cb[i], buf3));
3191 }
3192 if (tmh->cb[i] != -128)
3193 jref["table"][n] = tmh->cb[i];
3194 t += interval * 60; i = (i+1) % tmh->cb_size; n++;
3195 }
3196 }
3197 //assert(n == tmh->cb_size && i == (tmh->cb_index+1) % tmh->cb_size);
3198
3199 return 0;
3200}
3201
3202// Print SCT Error Recovery Control timers
3203static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer, bool power_on, bool mfg_default = false)
3204{
3205 const char* power_on_str = (power_on ? "Power-on " : "");
3206 json::ref jref = jglb["ata_sct_erc"];
3207 jout("SCT Error Recovery Control%s:%s\n", (set ? " set to" : ""), (mfg_default ? " default values." : ""));
3208
3209 if (!mfg_default) {
3210 jref["read"]["enabled"] = !!read_timer;
3211 if (!read_timer)
3212 jout(" %sRead: Disabled\n", power_on_str);
3213 else {
3214 jout(" %sRead: %6d (%0.1f seconds)\n", power_on_str, read_timer, read_timer/10.0);
3215 jref["read"]["deciseconds"] = read_timer;
3216 }
3217
3218 jref["write"]["enabled"] = !!write_timer;
3219 if (!write_timer)
3220 jout(" %sWrite: Disabled\n", power_on_str);
3221 else {
3222 jout(" %sWrite: %6d (%0.1f seconds)\n", power_on_str, write_timer, write_timer/10.0);
3223 jref["write"]["deciseconds"] = write_timer;
3224 }
3225 }
3226}
3227
3228static void print_aam_level(const char * msg, int level, int recommended = -1)
3229{
3230 // Table 56 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
3231 // Obsolete since T13/2015-D (ACS-2) Revision 4a, December 9, 2010
3232 const char * s;
3233 if (level == 0)
3234 s = "vendor specific";
3235 else if (level < 128)
3236 s = "unknown/retired";
3237 else if (level == 128)
3238 s = "quiet";
3239 else if (level < 254)
3240 s = "intermediate";
3241 else if (level == 254)
3242 s = "maximum performance";
3243 else
3244 s = "reserved";
3245
3246 if (recommended >= 0)
3247 jout("%s%d (%s), recommended: %d\n", msg, level, s, recommended);
3248 else
3249 jout("%s%d (%s)\n", msg, level, s);
3250
3251 json::ref jref = jglb["ata_aam"];
3252 jref["enabled"] = true;
3253 jref["level"] = level;
3254 jref["string"] = s;
3255 if (recommended >= 0)
3256 jref["recommended_level"] = recommended;
3257}
3258
3259static void print_apm_level(const char * msg, int level)
3260{
3261 // Table 120 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3262 const char * s;
3263 if (!(1 <= level && level <= 254))
3264 s = "reserved";
3265 else if (level == 1)
3266 s = "minimum power consumption with standby";
3267 else if (level < 128)
3268 s = "intermediate level with standby";
3269 else if (level == 128)
3270 s = "minimum power consumption without standby";
3271 else if (level < 254)
3272 s = "intermediate level without standby";
3273 else
3274 s = "maximum performance";
3275
3276 jout("%s%d (%s)\n", msg, level, s);
3277
3278 json::ref jref = jglb["ata_apm"];
3279 jref["enabled"] = true;
3280 jref["level"] = level;
3281 jref["string"] = s;
3282 if (1 <= level && level <= 254) {
3283 jref["max_performance"] = (level == 254);
3284 jref["min_power"] = (level == 1 || level == 128);
3285 jref["with_standby"] = (level < 128);
3286 }
3287}
3288
3289static void print_ata_security_status(const char * msg, unsigned short state, unsigned short master_password_id)
3290{
3291 // Table 6 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3292 if (!(state & 0x0001)) {
3293 pout("%sUnavailable\n", msg);
3294 return;
3295 }
3296
3297 const char * s1, * s2 = "", * s3 = "", * s4 = "";
3298 bool enabled = false, locked = false;
3299 if (!(state & 0x0002)) {
3300 s1 = "Disabled, ";
3301 if (!(state & 0x0008))
3302 s2 = "NOT FROZEN [SEC1]";
3303 else
3304 s2 = "frozen [SEC2]";
3305 }
3306 else {
3307 enabled = true;
3308 s1 = "ENABLED, PW level ";
3309 if (!(state & 0x0100))
3310 s2 = "HIGH";
3311 else
3312 s2 = "MAX";
3313
3314 if (!(state & 0x0004)) {
3315 s3 = ", not locked, ";
3316 if (!(state & 0x0008))
3317 s4 = "not frozen [SEC5]";
3318 else
3319 s4 = "frozen [SEC6]";
3320 }
3321 else {
3322 locked = true;
3323 s3 = ", **LOCKED** [SEC4]";
3324 if (state & 0x0010)
3325 s4 = ", PW ATTEMPTS EXCEEDED";
3326 }
3327 }
3328
3329 // Print Master Password ID if set to non-default value
3330 // (0x0000, 0xffff: unsupported, 0xfffe: default)
3331 char s5[32] = "";
3332 if (0x0000 < master_password_id && master_password_id < 0xfffe)
3333 snprintf(s5, sizeof(s5), ", Master PW ID: 0x%04x", master_password_id);
3334
3335 jout("%s%s%s%s%s%s\n", msg, s1, s2, s3, s4, s5);
3336
3337 json::ref jref = jglb["ata_security"];
3338 jref["state"] = state;
3339 jref["string"] = strprintf("%s%s%s%s", s1, s2, s3, s4);
3340 jref["enabled"] = enabled;
3341 if (!enabled || !locked)
3342 jref["frozen"] = !!(state & 0x0008);
3343 if (enabled) {
3344 jref["pw_level_max"] = !!(state & 0x0100);
3345 jref["locked"] = locked;
3346 if (locked)
3347 jref["pw_attempts_exceeded"] = !!(state & 0x0010);
3348 }
3349 jref["master_password_id"] = master_password_id;
3350}
3351
3352static void print_standby_timer(const char * msg, int timer, const ata_identify_device & drive)
3353{
3354 const char * s1 = 0;
3355 int hours = 0, minutes = 0 , seconds = 0;
3356
3357 // Table 63 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3358 if (timer == 0)
3359 s1 = "disabled";
3360 else if (timer <= 240)
3361 seconds = timer * 5, minutes = seconds / 60, seconds %= 60;
3362 else if (timer <= 251)
3363 minutes = (timer - 240) * 30, hours = minutes / 60, minutes %= 60;
3364 else if (timer == 252)
3365 minutes = 21;
3366 else if (timer == 253)
3367 s1 = "between 8 hours and 12 hours";
3368 else if (timer == 255)
3369 minutes = 21, seconds = 15;
3370 else
3371 s1 = "reserved";
3372
3373 const char * s2 = "", * s3 = "";
3374 if (!(drive.words047_079[49-47] & 0x2000))
3375 s2 = " or vendor-specific";
3376 if (timer > 0 && (drive.words047_079[50-47] & 0xc001) == 0x4001)
3377 s3 = ", a vendor-specific minimum applies";
3378
3379 if (s1)
3380 pout("%s%d (%s%s%s)\n", msg, timer, s1, s2, s3);
3381 else
3382 pout("%s%d (%02d:%02d:%02d%s%s)\n", msg, timer, hours, minutes, seconds, s2, s3);
3383}
3384
3385
3386int ataPrintMain (ata_device * device, const ata_print_options & options)
3387{
3388 // If requested, check power mode first
3389 const char * powername = 0;
3390 bool powerchg = false;
3391 if (options.powermode) {
3392 unsigned char powerlimit = 0xff;
3393 int powermode = ataCheckPowerMode(device);
3394 // TODO: Move to new function used by smartctl and smartd.
3395 switch (powermode) {
3396 case -1:
3397 if (device->is_syscall_unsup()) {
3398 if (options.powerexit_unsup >= 0) {
3399 jinf("CHECK POWER MODE not implemented, exit(%d)\n", options.powerexit_unsup);
3400 return options.powerexit_unsup;
3401 }
3402 jinf("CHECK POWER MODE not implemented, ignoring -n option\n"); break;
3403 }
3404 powername = "SLEEP"; powerlimit = 2;
3405 break;
3406 // Table 215 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
3407 // Table 293 of T13/BSR INCITS 529 (ACS-4) Revision 12, February 18, 2016
3408 case 0x00: // PM2:Standby, EPC unavailable or Standby_z power condition
3409 powername = "STANDBY"; powerlimit = 3; break;
3410 case 0x01: // PM2:Standby, Standby_y power condition
3411 powername = "STANDBY_Y"; powerlimit = 3; break;
3412 case 0x80: // PM1:Idle, EPC unavailable
3413 powername = "IDLE"; powerlimit = 4; break;
3414 case 0x81: // PM1:Idle, Idle_a power condition
3415 powername = "IDLE_A"; powerlimit = 4; break;
3416 case 0x82: // PM1:Idle, Idle_b power condition
3417 powername = "IDLE_B"; powerlimit = 4; break;
3418 case 0x83: // PM1:Idle, Idle_c power condition
3419 powername = "IDLE_C"; powerlimit = 4; break;
3420 // 0x40/41 were declared obsolete in ACS-3 Revision 1
3421 case 0x40: // PM0:Active, NV Cache power mode enabled, spun down
3422 powername = "ACTIVE_NV_DOWN"; break;
3423 case 0x41: // PM0:Active, NV Cache power mode enabled, spun up
3424 powername = "ACTIVE_NV_UP" ; break;
3425 case 0xff: // PM0:Active or PM1:Idle
3426 powername = "ACTIVE or IDLE"; break;
3427
3428 default:
3429 if (options.powerexit_unsup >= 0) {
3430 jinf("CHECK POWER MODE returned unknown value 0x%02x, exit(%d)\n", powermode,
3431 options.powerexit_unsup);
3432 return options.powerexit_unsup;
3433 }
3434 jinf("CHECK POWER MODE returned unknown value 0x%02x, ignoring -n option\n", powermode);
3435 break;
3436 }
3437 if (powername) {
3438 if (options.powermode >= powerlimit) {
3439 jinf("Device is in %s mode, exit(%d)\n", powername, options.powerexit);
3440 return options.powerexit;
3441 }
3442 powerchg = (powermode != 0xff); // SMART tests will spin up drives
3443 }
3444 }
3445
3446 // SMART values needed ?
3447 bool need_smart_val = (
3448 options.smart_check_status
3449 || options.smart_general_values
3450 || options.smart_vendor_attrib
3451 || options.smart_error_log
3452 || options.smart_selftest_log
3454 || options.smart_ext_error_log
3455 || options.smart_ext_selftest_log
3456 || options.smart_auto_offl_enable
3457 || options.smart_auto_offl_disable
3458 || options.smart_selftest_type != -1
3459 );
3460
3461 // SMART must be enabled ?
3462 bool need_smart_enabled = (
3463 need_smart_val
3464 || options.smart_auto_save_enable
3465 || options.smart_auto_save_disable
3466 );
3467
3468 // SMART feature set needed ?
3469 bool need_smart_support = (
3470 need_smart_enabled
3471 || options.smart_enable
3472 || options.smart_disable
3473 );
3474
3475 // SMART and GP log directories needed ?
3476 bool need_smart_logdir = (
3477 options.smart_logdir
3478 || options.devstat_all_pages // devstat fallback to smartlog if needed
3479 || options.devstat_ssd_page
3480 || !options.devstat_pages.empty()
3481 );
3482
3483 bool need_gp_logdir = (
3484 options.gp_logdir
3485 || options.smart_ext_error_log
3486 || options.smart_ext_selftest_log
3487 || options.devstat_all_pages
3488 || options.devstat_ssd_page
3489 || !options.devstat_pages.empty()
3490 || options.pending_defects_log
3491 || options.farm_log
3492 );
3493
3494 unsigned i;
3495 for (i = 0; i < options.log_requests.size(); i++) {
3496 if (options.log_requests[i].gpl)
3497 need_gp_logdir = true;
3498 else
3499 need_smart_logdir = true;
3500 }
3501
3502 // SCT commands needed ?
3503 bool need_sct_support = (
3504 options.sct_temp_sts
3505 || options.sct_temp_hist
3506 || options.sct_temp_int
3507 || options.sct_erc_get
3508 || options.sct_erc_set
3509 || options.sct_wcache_reorder_get
3510 || options.sct_wcache_reorder_set
3511 || options.sct_wcache_sct_get
3512 || options.sct_wcache_sct_set
3513 );
3514
3515 // Print any newer info not included in '-a' ?
3516 // Also used below to suppress suggestion of '-x'
3517 bool not_part_of_a_option = (
3518 need_smart_logdir
3519 || need_gp_logdir
3520 || need_sct_support
3521 || options.sataphy
3522 || options.farm_log
3523 || options.identify_word_level >= 0
3524 || options.get_set_used
3525 );
3526
3527 // Exit if no further options specified
3528 if (!( options.drive_info
3529 || options.show_presets
3530 || need_smart_support
3531 || not_part_of_a_option)) {
3532 if (powername)
3533 pout("Device is in %s mode\n", powername);
3534 else
3535 pout("ATA device successfully opened\n\n"
3536 "Use 'smartctl -a' (or '-x') to print SMART (and more) information\n\n");
3537 return 0;
3538 }
3539
3540 // Start by getting Drive ID information. We need this, to know if SMART is supported.
3541 int returnval = 0;
3542 ata_identify_device drive; memset(&drive, 0, sizeof(drive));
3543 unsigned char raw_drive[sizeof(drive)]; memset(&raw_drive, 0, sizeof(raw_drive));
3544
3545 device->clear_err();
3546 int retid = ata_read_identity(device, &drive, options.fix_swapped_id, raw_drive);
3547 if (retid < 0) {
3548 pout("Read Device Identity failed: %s\n\n",
3549 (device->get_errno() ? device->get_errmsg() : "Unknown error"));
3550 pout("If this is a USB connected device, look at the various "
3551 "--device=TYPE variants\n");
3552 failuretest(MANDATORY_CMD, returnval|=FAILID);
3553 }
3554 else if (!nonempty(&drive, sizeof(drive))) {
3555 pout("Read Device Identity failed: empty IDENTIFY data\n\n");
3556 failuretest(MANDATORY_CMD, returnval|=FAILID);
3557 }
3558
3559 // If requested, show which presets would be used for this drive and exit.
3560 if (options.show_presets) {
3561 show_presets(&drive);
3562 return 0;
3563 }
3564
3565 // Use preset vendor attribute options unless user has requested otherwise.
3566 ata_vendor_attr_defs attribute_defs = options.attribute_defs;
3567 firmwarebug_defs firmwarebugs = options.firmwarebugs;
3568 std::string dbversion;
3569 const drive_settings * dbentry = 0;
3570 if (!options.ignore_presets) {
3571 dbentry = lookup_drive_apply_presets(&drive, attribute_defs,
3572 firmwarebugs, dbversion);
3573 if (!dbversion.empty())
3574 jglb["smartctl"]["drive_database_version"]["string"] = dbversion;
3575 }
3576
3577 // Get capacity, sector sizes and rotation rate
3578 ata_size_info sizes;
3579 ata_get_size_info(&drive, sizes);
3580 int rpm = ata_get_rotation_rate(&drive);
3581
3582 // Print ATA IDENTIFY info if requested
3583 if (options.identify_word_level >= 0) {
3584 pout("=== ATA IDENTIFY DATA ===\n");
3585 // Pass raw data without endianness adjustments
3586 ata_print_identify_data(raw_drive, (options.identify_word_level > 0), options.identify_bit_level);
3587 }
3588
3589 // Print most drive identity information if requested
3590 if (options.drive_info) {
3591 pout("=== START OF INFORMATION SECTION ===\n");
3592 print_drive_info(&drive, sizes, rpm, dbentry, dbversion.c_str());
3593 }
3594
3595 // Check and print SMART support and state
3596 int smart_supported = -1, smart_enabled = -1;
3597 if (need_smart_support || options.drive_info) {
3598
3599 // Packet device ?
3600 if (retid > 0) {
3601 pout("SMART support is: Unavailable - Packet Interface Devices [this device: %s] don't support ATA SMART\n",
3602 packetdevicetype(retid-1));
3603 }
3604 else {
3605 // Disk device: SMART supported and enabled ?
3606 smart_supported = ataSmartSupport(&drive);
3607 smart_enabled = ataIsSmartEnabled(&drive);
3608
3609 if (smart_supported < 0)
3610 pout("SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 82-83 don't show if SMART supported.\n");
3611 if (smart_supported && smart_enabled < 0) {
3612 pout("SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 85-87 don't show if SMART is enabled.\n");
3613 if (need_smart_support) {
3614 failuretest(MANDATORY_CMD, returnval|=FAILSMART);
3615 // check SMART support by trying a command
3616 pout(" Checking to be sure by trying SMART RETURN STATUS command.\n");
3617 if (ataDoesSmartWork(device))
3618 smart_supported = smart_enabled = 1;
3619 }
3620 }
3621 else if (smart_supported < 0 && (smart_enabled > 0 || dbentry))
3622 // Assume supported if enabled or in drive database
3623 smart_supported = 1;
3624
3625 if (smart_supported < 0)
3626 pout("SMART support is: Unknown - Try option -s with argument 'on' to enable it.");
3627 else if (!smart_supported)
3628 jout("SMART support is: Unavailable - device lacks SMART capability.\n");
3629 else {
3630 if (options.drive_info)
3631 jout("SMART support is: Available - device has SMART capability.\n");
3632 if (smart_enabled >= 0) {
3633 if (device->ata_identify_is_cached()) {
3634 if (options.drive_info)
3635 pout(" %sabled status cached by OS, trying SMART RETURN STATUS cmd.\n",
3636 (smart_enabled?"En":"Dis"));
3637 smart_enabled = ataDoesSmartWork(device);
3638 }
3639 if (options.drive_info)
3640 jout("SMART support is: %s\n",
3641 (smart_enabled ? "Enabled" : "Disabled"));
3642 }
3643 }
3644 }
3645
3646 if (options.drive_info || smart_supported <= 0) {
3647 jglb["smart_support"]["available"] = (smart_supported > 0);
3648 if (smart_supported > 0)
3649 jglb["smart_support"]["enabled"] = (smart_enabled > 0);
3650 }
3651 }
3652
3653 // Print AAM status
3654 if (options.get_aam) {
3655 if ((drive.command_set_2 & 0xc200) != 0x4200) // word083
3656 pout("AAM feature is: Unavailable\n");
3657 else if (!(drive.word086 & 0x0200)) {
3658 jout("AAM feature is: Disabled\n");
3659 jglb["ata_aam"]["enabled"] = false;
3660 }
3661 else
3662 print_aam_level("AAM level is: ", drive.words088_255[94-88] & 0xff,
3663 drive.words088_255[94-88] >> 8);
3664 }
3665
3666 // Print APM status
3667 if (options.get_apm) {
3668 if ((drive.command_set_2 & 0xc008) != 0x4008) // word083
3669 pout("APM feature is: Unavailable\n");
3670 else if (!(drive.word086 & 0x0008)) {
3671 jout("APM feature is: Disabled\n");
3672 jglb["ata_apm"]["enabled"] = false;
3673 }
3674 else
3675 print_apm_level("APM level is: ", drive.words088_255[91-88] & 0xff);
3676 }
3677
3678 // Print read look-ahead status
3679 if (options.get_lookahead) {
3680 if ( (drive.command_set_2 & 0xc000) != 0x4000 // word083
3681 || !(drive.command_set_1 & 0x0040) ) // word082
3682 pout("Rd look-ahead is: Unavailable\n");
3683 else {
3684 bool enabled = !!(drive.cfs_enable_1 & 0x0040); // word085
3685 jout("Rd look-ahead is: %sabled\n", (enabled ? "En" : "Dis"));
3686 jglb["read_lookahead"]["enabled"] = enabled;
3687 }
3688 }
3689
3690 // Print write cache status
3691 if (options.get_wcache) {
3692 if ( (drive.command_set_2 & 0xc000) != 0x4000 // word083
3693 || !(drive.command_set_1 & 0x0020) ) // word082
3694 pout("Write cache is: Unavailable\n");
3695 else {
3696 bool enabled = !!(drive.cfs_enable_1 & 0x0020); // word085
3697 jout("Write cache is: %sabled\n", (enabled ? "En" : "Dis"));
3698 jglb["write_cache"]["enabled"] = enabled;
3699 }
3700 }
3701
3702 // Print DSN status
3703 unsigned short word120 = drive.words088_255[120-88];
3704 unsigned short word119 = drive.words088_255[119-88];
3705 if (options.get_dsn) {
3706 if (!(drive.word086 & 0x8000) // word086
3707 || ((word119 & 0xc200) != 0x4200) // word119
3708 || ((word120 & 0xc000) != 0x4000)) // word120
3709 pout("DSN feature is: Unavailable\n");
3710 else {
3711 bool enabled = !!(word120 & 0x200);
3712 jout("DSN feature is: %sabled\n", (enabled ? "En" : "Dis"));
3713 jglb["ata_dsn"]["enabled"] = enabled;
3714 }
3715 }
3716
3717 // Check for ATA Security LOCK
3718 unsigned short word128 = drive.words088_255[128-88];
3719 bool locked = ((word128 & 0x0007) == 0x0007); // LOCKED|ENABLED|SUPPORTED
3720
3721 // Print ATA Security status
3722 if (options.get_security)
3723 print_ata_security_status("ATA Security is: ", word128, drive.words088_255[92-88]);
3724
3725 // Print write cache reordering status
3726 if (options.sct_wcache_reorder_get) {
3727 if (!isSCTFeatureControlCapable(&drive))
3728 pout("Wt Cache Reorder: Unavailable\n");
3729 else if (locked)
3730 pout("Wt Cache Reorder: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3731 else {
3732 int wcache_reorder = ataGetSetSCTWriteCacheReordering(device,
3733 false /*enable*/, false /*persistent*/, false /*set*/);
3734
3735 if (-1 <= wcache_reorder && wcache_reorder <= 2)
3736 pout("Wt Cache Reorder: %s\n",
3737 (wcache_reorder == -1 ? "Unknown (SCT Feature Control command failed)" :
3738 wcache_reorder == 0 ? "Unknown" : // not defined in standard but returned on some drives if not set
3739 wcache_reorder == 1 ? "Enabled" : "Disabled"));
3740 else
3741 pout("Wt Cache Reorder: Unknown (0x%02x)\n", wcache_reorder);
3742 }
3743 }
3744
3745 const char * sct_write_cache_state_desc[4] = {
3746 "Unknown", // 0: not defined in standard but returned on some drives if not set
3747 "Controlled by ATA", // 1: controlled ATA Set Features command
3748 "Force Enabled", // 2
3749 "Force Disabled" // 3
3750 };
3751
3752 // Print SCT feature control of write cache
3753 if (options.sct_wcache_sct_get) {
3754 if (!isSCTFeatureControlCapable(&drive))
3755 pout("SCT Write Cache Control: Unavailable\n");
3756 else if (locked)
3757 pout("SCT Write Cache Control: Unknown (SCT not supported if ATA Security is LOCKED)\n");
3758 else {
3759 int state = ataGetSetSCTWriteCache(device, 1, false /*persistent*/, false /*set*/);
3760 if (-1 <= state && state <= 3)
3761 pout("SCT Write Cache Control: %s\n",
3762 (state == -1 ? "Unknown (SCT Feature Control command failed)" :
3763 sct_write_cache_state_desc[state]));
3764 else
3765 pout("SCT Write Cache Control: Unknown (0x%02x)\n", state);
3766 }
3767 }
3768
3769
3770 // Print remaining drive info
3771 if (options.drive_info) {
3772 // Print the (now possibly changed) power mode if available
3773 if (powername)
3774 pout("Power mode %s %s\n", (powerchg?"was:":"is: "), powername);
3775 pout("\n");
3776 }
3777
3778 // Exit if SMART is not supported but must be available to proceed
3779 if (smart_supported <= 0 && need_smart_support)
3780 failuretest(MANDATORY_CMD, returnval|=FAILSMART);
3781
3782 // START OF THE ENABLE/DISABLE SECTION OF THE CODE
3783 if ( options.smart_disable || options.smart_enable
3786 || options.set_aam || options.set_apm || options.set_lookahead
3787 || options.set_wcache || options.set_security_freeze || options.set_standby
3788 || options.sct_wcache_reorder_set || options.sct_wcache_sct_set || options.set_dsn)
3789 pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
3790
3791 // Enable/Disable AAM
3792 if (options.set_aam) {
3793 if (options.set_aam > 0) {
3794 if (!ata_set_features(device, ATA_ENABLE_AAM, options.set_aam-1)) {
3795 pout("AAM enable failed: %s\n", device->get_errmsg());
3796 returnval |= FAILSMART;
3797 }
3798 else
3799 print_aam_level("AAM set to level ", options.set_aam-1);
3800 }
3801 else {
3802 if (!ata_set_features(device, ATA_DISABLE_AAM)) {
3803 pout("AAM disable failed: %s\n", device->get_errmsg());
3804 returnval |= FAILSMART;
3805 }
3806 else
3807 pout("AAM disabled\n");
3808 }
3809 }
3810
3811 // Enable/Disable APM
3812 if (options.set_apm) {
3813 if (options.set_apm > 0) {
3814 if (!ata_set_features(device, ATA_ENABLE_APM, options.set_apm-1)) {
3815 pout("APM enable failed: %s\n", device->get_errmsg());
3816 returnval |= FAILSMART;
3817 }
3818 else
3819 print_apm_level("APM set to level ", options.set_apm-1);
3820 }
3821 else {
3822 if (!ata_set_features(device, ATA_DISABLE_APM)) {
3823 pout("APM disable failed: %s\n", device->get_errmsg());
3824 returnval |= FAILSMART;
3825 }
3826 else
3827 pout("APM disabled\n");
3828 }
3829 }
3830
3831 // Enable/Disable read look-ahead
3832 if (options.set_lookahead) {
3833 bool enable = (options.set_lookahead > 0);
3835 pout("Read look-ahead %sable failed: %s\n", (enable ? "en" : "dis"), device->get_errmsg());
3836 returnval |= FAILSMART;
3837 }
3838 else
3839 pout("Read look-ahead %sabled\n", (enable ? "en" : "dis"));
3840 }
3841
3842 // Enable/Disable write cache
3843 if (options.set_wcache) {
3844 bool enable = (options.set_wcache > 0);
3846 pout("Write cache %sable failed: %s\n", (enable ? "en" : "dis"), device->get_errmsg());
3847 returnval |= FAILSMART;
3848 }
3849 else
3850 pout("Write cache %sabled\n", (enable ? "en" : "dis"));
3851 }
3852
3853 // Enable/Disable DSN
3854 if (options.set_dsn) {
3855 bool enable = (options.set_dsn > 0);
3856 if (!ata_set_features(device, ATA_ENABLE_DISABLE_DSN, (enable ? 0x1 : 0x2))) {
3857 pout("DSN %sable failed: %s\n", (enable ? "en" : "dis"), device->get_errmsg());
3858 returnval |= FAILSMART;
3859 }
3860 else
3861 pout("DSN %sabled\n", (enable ? "en" : "dis"));
3862 }
3863
3864 // Enable/Disable write cache reordering
3865 if (options.sct_wcache_reorder_set) {
3866 bool enable = (options.sct_wcache_reorder_set > 0);
3867 if (!isSCTFeatureControlCapable(&drive))
3868 pout("Write cache reordering %sable failed: SCT Feature Control command not supported\n",
3869 (enable ? "en" : "dis"));
3870 else if (locked)
3871 pout("Write cache reordering %sable failed: SCT not supported if ATA Security is LOCKED\n",
3872 (enable ? "en" : "dis"));
3873 else if (ataGetSetSCTWriteCacheReordering(device,
3874 enable, options.sct_wcache_reorder_set_pers, true /*set*/) < 0) {
3875 pout("Write cache reordering %sable failed: %s\n", (enable ? "en" : "dis"), device->get_errmsg());
3876 returnval |= FAILSMART;
3877 }
3878 else
3879 pout("Write cache reordering %sabled (%s)\n", (enable ? "en" : "dis"),
3880 (options.sct_wcache_reorder_set_pers ? "persistent" : "volatile"));
3881 }
3882
3883 // Enable/Disable write cache in SCT
3884 if (options.sct_wcache_sct_set) {
3885 if (!isSCTFeatureControlCapable(&drive))
3886 pout("SCT Feature Control of write cache failed: SCT Feature Control command not supported\n");
3887 else if (locked)
3888 pout("SCT Feature Control of write cache failed: SCT not supported if ATA Security is LOCKED\n");
3889 else if (ataGetSetSCTWriteCache(device,
3890 options.sct_wcache_sct_set, options.sct_wcache_sct_set_pers, true /*set*/) < 0) {
3891 pout("SCT Feature Control of write cache failed: %s\n", device->get_errmsg());
3892 returnval |= FAILSMART;
3893 }
3894 else
3895 pout("Write cache SCT Feature Control is set to: %s (%s)\n",
3896 sct_write_cache_state_desc[options.sct_wcache_sct_set],
3897 (options.sct_wcache_sct_set_pers ? "persistent" : "volatile"));
3898 }
3899
3900 // Freeze ATA security
3901 if (options.set_security_freeze) {
3903 pout("ATA SECURITY FREEZE LOCK failed: %s\n", device->get_errmsg());
3904 returnval |= FAILSMART;
3905 }
3906 else
3907 pout("ATA Security set to frozen mode\n");
3908 }
3909
3910 // Set standby timer unless immediate standby is also requested
3911 if (options.set_standby && !options.set_standby_now) {
3912 if (!ata_nodata_command(device, ATA_IDLE, options.set_standby-1)) {
3913 pout("ATA IDLE command failed: %s\n", device->get_errmsg());
3914 returnval |= FAILSMART;
3915 }
3916 else
3917 print_standby_timer("Standby timer set to ", options.set_standby-1, drive);
3918 }
3919
3920 // Enable/Disable SMART commands
3921 if (options.smart_enable) {
3922 if (ataEnableSmart(device)) {
3923 pout("SMART Enable failed: %s\n\n", device->get_errmsg());
3924 failuretest(MANDATORY_CMD, returnval|=FAILSMART);
3925 }
3926 else {
3927 pout("SMART Enabled.\n");
3928 smart_enabled = 1;
3929 }
3930 }
3931
3932 // Turn off SMART on device
3933 if (options.smart_disable) {
3934 if (ataDisableSmart(device)) {
3935 pout("SMART Disable failed: %s\n\n", device->get_errmsg());
3937 }
3938 }
3939
3940 // Exit if SMART is disabled but must be enabled to proceed
3941 if (options.smart_disable || (smart_enabled <= 0 && need_smart_enabled && !is_permissive())) {
3942 pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n");
3943 if (!options.smart_disable)
3944 pout("(override with '-T permissive' option)\n");
3945 return returnval;
3946 }
3947
3948 // Enable/Disable Auto-save attributes
3949 if (options.smart_auto_save_enable) {
3950 if (ataEnableAutoSave(device)){
3951 pout("SMART Enable Attribute Autosave failed: %s\n\n", device->get_errmsg());
3952 failuretest(MANDATORY_CMD, returnval|=FAILSMART);
3953 }
3954 else
3955 pout("SMART Attribute Autosave Enabled.\n");
3956 }
3957
3958 if (options.smart_auto_save_disable) {
3959 if (ataDisableAutoSave(device)){
3960 pout("SMART Disable Attribute Autosave failed: %s\n\n", device->get_errmsg());
3961 failuretest(MANDATORY_CMD, returnval|=FAILSMART);
3962 }
3963 else
3964 pout("SMART Attribute Autosave Disabled.\n");
3965 }
3966
3967 // Read SMART values and thresholds if necessary
3968 ata_smart_values smartval; memset(&smartval, 0, sizeof(smartval));
3969 ata_smart_thresholds_pvt smartthres; memset(&smartthres, 0, sizeof(smartthres));
3970 bool smart_val_ok = false, smart_thres_ok = false;
3971
3972 if (need_smart_val) {
3973 if (ataReadSmartValues(device, &smartval)) {
3974 pout("Read SMART Data failed: %s\n\n", device->get_errmsg());
3975 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
3976 }
3977 else {
3978 smart_val_ok = true;
3979
3980 if (options.smart_check_status || options.smart_vendor_attrib) {
3981 if (ataReadSmartThresholds(device, &smartthres)){
3982 pout("Read SMART Thresholds failed: %s\n\n", device->get_errmsg());
3983 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
3984 }
3985 else
3986 smart_thres_ok = true;
3987 }
3988 }
3989 }
3990
3991 // Enable/Disable Off-line testing
3992 bool needupdate = false;
3993 if (options.smart_auto_offl_enable) {
3994 if (!isSupportAutomaticTimer(&smartval)){
3995 pout("SMART Automatic Timers not supported\n\n");
3996 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
3997 }
3998 needupdate = smart_val_ok;
3999 if (ataEnableAutoOffline(device)){
4000 pout("SMART Enable Automatic Offline failed: %s\n\n", device->get_errmsg());
4001 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4002 }
4003 else
4004 pout("SMART Automatic Offline Testing Enabled every four hours.\n");
4005 }
4006
4007 if (options.smart_auto_offl_disable) {
4008 if (!isSupportAutomaticTimer(&smartval)){
4009 pout("SMART Automatic Timers not supported\n\n");
4010 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4011 }
4012 needupdate = smart_val_ok;
4013 if (ataDisableAutoOffline(device)){
4014 pout("SMART Disable Automatic Offline failed: %s\n\n", device->get_errmsg());
4015 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4016 }
4017 else
4018 pout("SMART Automatic Offline Testing Disabled.\n");
4019 }
4020
4021 if (needupdate && ataReadSmartValues(device, &smartval)){
4022 pout("Read SMART Data failed: %s\n\n", device->get_errmsg());
4023 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4024 smart_val_ok = false;
4025 }
4026
4027 // all this for a newline!
4028 if ( options.smart_disable || options.smart_enable
4031 || options.set_aam || options.set_apm || options.set_lookahead
4032 || options.set_wcache || options.set_security_freeze || options.set_standby
4033 || options.sct_wcache_reorder_set || options.set_dsn)
4034 pout("\n");
4035
4036 // START OF READ-ONLY OPTIONS APART FROM -V and -i
4037 if ( options.smart_check_status || options.smart_general_values
4038 || options.smart_vendor_attrib || options.smart_error_log
4040 || options.smart_ext_error_log || options.smart_ext_selftest_log
4041 || options.sct_temp_sts || options.sct_temp_hist )
4042 pout("=== START OF READ SMART DATA SECTION ===\n");
4043
4044 // Check SMART status
4045 if (options.smart_check_status) {
4046
4047 switch (ataSmartStatus2(device)) {
4048
4049 case 0:
4050 // The case where the disk health is OK
4051 jout("SMART overall-health self-assessment test result: PASSED\n");
4052 jglb["smart_status"]["passed"] = true;
4053 if (smart_thres_ok && find_failed_attr(&smartval, &smartthres, attribute_defs, 0)) {
4054 if (options.smart_vendor_attrib)
4055 pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
4056 else {
4057 print_on();
4058 pout("Please note the following marginal Attributes:\n");
4059 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format);
4060 }
4061 returnval|=FAILAGE;
4062 }
4063 else
4064 pout("\n");
4065 break;
4066
4067 case 1:
4068 // The case where the disk health is NOT OK
4069 print_on();
4070 jout("SMART overall-health self-assessment test result: FAILED!\n"
4071 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
4072 jglb["smart_status"]["passed"] = false;
4073 print_off();
4074 if (smart_thres_ok && find_failed_attr(&smartval, &smartthres, attribute_defs, 1)) {
4075 returnval|=FAILATTR;
4076 if (options.smart_vendor_attrib)
4077 pout("See vendor-specific Attribute list for failed Attributes.\n\n");
4078 else {
4079 print_on();
4080 pout("Failed Attributes:\n");
4081 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format);
4082 }
4083 }
4084 else
4085 pout("No failed Attributes found.\n\n");
4086 returnval|=FAILSTATUS;
4087 print_off();
4088 break;
4089
4090 case -1:
4091 default:
4092 // Something went wrong with the SMART STATUS command.
4093 // The ATA SMART RETURN STATUS command provides the result in the ATA output
4094 // registers. Buggy ATA/SATA drivers and SAT Layers often do not properly
4095 // return the registers values.
4096 pout("SMART Status %s: %s\n",
4097 (device->is_syscall_unsup() ? "not supported" : "command failed"),
4098 device->get_errmsg());
4099 failuretest(OPTIONAL_CMD, returnval | FAILSMART);
4100 if (!(device->is_syscall_unsup() && smart_val_ok && smart_thres_ok))
4101 returnval |= FAILSMART; // Unknown error or attribute check not possible
4102
4103 if (!(smart_val_ok && smart_thres_ok)) {
4104 print_on();
4105 pout("SMART overall-health self-assessment test result: UNKNOWN!\n"
4106 "SMART Status, Attributes and Thresholds cannot be read.\n\n");
4107 }
4108 else if (find_failed_attr(&smartval, &smartthres, attribute_defs, 1)) {
4109 print_on();
4110 jout("SMART overall-health self-assessment test result: FAILED!\n"
4111 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
4112 jwrn("Warning: This result is based on an Attribute check.\n");
4113 jglb["smart_status"]["passed"] = false;
4114 print_off();
4115 returnval|=FAILATTR;
4116 returnval|=FAILSTATUS;
4117 if (options.smart_vendor_attrib)
4118 pout("See vendor-specific Attribute list for failed Attributes.\n\n");
4119 else {
4120 print_on();
4121 pout("Failed Attributes:\n");
4122 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format);
4123 }
4124 }
4125 else {
4126 jout("SMART overall-health self-assessment test result: PASSED\n");
4127 jwrn("Warning: This result is based on an Attribute check.\n");
4128 jglb["smart_status"]["passed"] = true;
4129 if (find_failed_attr(&smartval, &smartthres, attribute_defs, 0)) {
4130 if (options.smart_vendor_attrib)
4131 pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
4132 else {
4133 print_on();
4134 pout("Please note the following marginal Attributes:\n");
4135 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format);
4136 }
4137 returnval|=FAILAGE;
4138 }
4139 else
4140 pout("\n");
4141 }
4142 print_off();
4143 break;
4144 } // end of switch statement
4145
4146 print_off();
4147 } // end of checking SMART Status
4148
4149 // Print general SMART values
4150 if (smart_val_ok && options.smart_general_values)
4151 PrintGeneralSmartValues(&smartval, &drive, firmwarebugs);
4152
4153 // Print vendor-specific attributes
4154 if (smart_val_ok && options.smart_vendor_attrib) {
4155 print_on();
4156 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm,
4157 (printing_is_switchable ? 2 : 0), options.output_format);
4158 print_off();
4159 }
4160
4161 // If GP Log is supported use smart log directory for
4162 // error and selftest log support check.
4163 bool gp_log_supported = isGeneralPurposeLoggingCapable(&drive);
4164 if ( gp_log_supported
4165 && ( options.smart_error_log || options.smart_selftest_log
4166 || options.retry_error_log || options.retry_selftest_log))
4167 need_smart_logdir = true;
4168
4169 ata_smart_log_directory smartlogdir_buf, gplogdir_buf;
4170 const ata_smart_log_directory * smartlogdir = 0, * gplogdir = 0;
4171
4172 // Read SMART Log directory
4173 if (need_smart_logdir) {
4174 if (firmwarebugs.is_set(BUG_NOLOGDIR))
4175 smartlogdir = fake_logdir(&smartlogdir_buf, options);
4176 else if (ataReadLogDirectory(device, &smartlogdir_buf, false)) {
4177 pout("Read SMART Log Directory failed: %s\n\n", device->get_errmsg());
4178 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4179 }
4180 else
4181 smartlogdir = &smartlogdir_buf;
4182 }
4183
4184 // Read GP Log directory
4185 if (need_gp_logdir) {
4186 if (firmwarebugs.is_set(BUG_NOLOGDIR))
4187 gplogdir = fake_logdir(&gplogdir_buf, options);
4188 else if (!gp_log_supported && !is_permissive()) {
4189 if (options.gp_logdir)
4190 pout("General Purpose Log Directory not supported\n\n");
4191 }
4192 else if (ataReadLogDirectory(device, &gplogdir_buf, true)) {
4193 pout("Read GP Log Directory failed\n\n");
4194 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4195 }
4196 else
4197 gplogdir = &gplogdir_buf;
4198 }
4199
4200 // Print log directories
4201 if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir)) {
4202 if (firmwarebugs.is_set(BUG_NOLOGDIR))
4203 pout("Log Directories not read due to '-F nologdir' option\n\n");
4204 else
4205 PrintLogDirectories(gplogdir, smartlogdir);
4206 }
4207
4208 // Print log pages
4209 for (i = 0; i < options.log_requests.size(); i++) {
4210 const ata_log_request & req = options.log_requests[i];
4211
4212 const char * type;
4213 unsigned max_nsectors;
4214 if (req.gpl) {
4215 type = "General Purpose";
4216 max_nsectors = GetNumLogSectors(gplogdir, req.logaddr, true);
4217 }
4218 else {
4219 type = "SMART";
4220 max_nsectors = GetNumLogSectors(smartlogdir, req.logaddr, false);
4221 }
4222
4223 if (!max_nsectors) {
4224 if (!is_permissive()) {
4225 pout("%s Log 0x%02x does not exist (override with '-T permissive' option)\n", type, req.logaddr);
4226 continue;
4227 }
4228 max_nsectors = req.page+1;
4229 }
4230 if (max_nsectors <= req.page) {
4231 pout("%s Log 0x%02x has only %u sectors, output skipped\n", type, req.logaddr, max_nsectors);
4232 continue;
4233 }
4234
4235 unsigned ns = req.nsectors;
4236 if (ns > max_nsectors - req.page) {
4237 if (req.nsectors != ~0U) // "FIRST-max"
4238 pout("%s Log 0x%02x has only %u sectors, output truncated\n", type, req.logaddr, max_nsectors);
4239 ns = max_nsectors - req.page;
4240 }
4241
4242 // SMART log don't support sector offset, start with first sector
4243 unsigned offs = (req.gpl ? 0 : req.page);
4244
4245 raw_buffer log_buf((offs + ns) * 512);
4246 bool ok;
4247 if (req.gpl)
4248 ok = ataReadLogExt(device, req.logaddr, 0x00, req.page, log_buf.data(), ns);
4249 else
4250 ok = ataReadSmartLog(device, req.logaddr, log_buf.data(), offs + ns);
4251 if (!ok)
4252 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4253 else
4254 PrintLogPages(type, log_buf.data() + offs*512, req.logaddr, req.page, ns, max_nsectors);
4255 }
4256
4257 // Print SMART Extendend Comprehensive Error Log
4258 bool do_smart_error_log = options.smart_error_log;
4259 if (options.smart_ext_error_log) {
4260 bool ok = false;
4261 unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true);
4262 if (!nsectors)
4263 pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n\n");
4264 else {
4265 // Read only first sector to get error count and index
4266 // Print function will read more sectors as needed
4267 ata_smart_exterrlog log_03; memset(&log_03, 0, sizeof(log_03));
4268 if (!ataReadExtErrorLog(device, &log_03, 0, 1, firmwarebugs)) {
4269 pout("Read SMART Extended Comprehensive Error Log failed\n\n");
4270 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4271 }
4272 else {
4273 if (PrintSmartExtErrorLog(device, firmwarebugs, &log_03, nsectors, options.smart_ext_error_log))
4274 returnval |= FAILERR;
4275 ok = true;
4276 }
4277 }
4278
4279 if (!ok) {
4280 if (options.retry_error_log)
4281 do_smart_error_log = true;
4282 else if (!do_smart_error_log)
4283 pout("Try '-l [xerror,]error' to read traditional SMART Error Log\n");
4284 }
4285 }
4286
4287 // Print SMART error log
4288 if (do_smart_error_log) {
4289 if (!( GetNumLogSectors(smartlogdir, 0x01, false)
4290 || ( !(smartlogdir && gp_log_supported)
4291 && isSmartErrorLogCapable(&smartval, &drive))
4292 || is_permissive() )) {
4293 pout("SMART Error Log not supported\n\n");
4294 }
4295 else {
4296 ata_smart_errorlog smarterror; memset(&smarterror, 0, sizeof(smarterror));
4297 if (ataReadErrorLog(device, &smarterror, firmwarebugs)) {
4298 pout("Read SMART Error Log failed: %s\n\n", device->get_errmsg());
4299 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4300 }
4301 else {
4302 // quiet mode is turned on inside PrintSmartErrorLog()
4303 if (PrintSmartErrorlog(&smarterror, firmwarebugs))
4304 returnval|=FAILERR;
4305 print_off();
4306 }
4307 }
4308 }
4309
4310 // Print SMART Extendend Self-test Log
4311 bool do_smart_selftest_log = options.smart_selftest_log;
4312 if (options.smart_ext_selftest_log) {
4313 bool ok = false;
4314 unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true);
4315 if (!nsectors)
4316 pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n\n");
4317 else if (nsectors >= 256)
4318 pout("SMART Extended Self-test Log size %u not supported\n\n", nsectors);
4319 else {
4320 raw_buffer log_07_buf(nsectors * 512);
4321 ata_smart_extselftestlog * log_07 = reinterpret_cast<ata_smart_extselftestlog *>(log_07_buf.data());
4322 if (!ataReadExtSelfTestLog(device, log_07, nsectors)) {
4323 pout("Read SMART Extended Self-test Log failed\n\n");
4324 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4325 }
4326 else {
4327 if (PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log))
4328 returnval |= FAILLOG;
4329 ok = true;
4330 }
4331 }
4332
4333 if (!ok) {
4334 if (options.retry_selftest_log)
4335 do_smart_selftest_log = true;
4336 else if (!do_smart_selftest_log)
4337 pout("Try '-l [xselftest,]selftest' to read traditional SMART Self Test Log\n");
4338 }
4339 }
4340
4341 // Print SMART self-test log
4342 if (do_smart_selftest_log) {
4343 if (!( GetNumLogSectors(smartlogdir, 0x06, false)
4344 || ( !(smartlogdir && gp_log_supported)
4345 && isSmartTestLogCapable(&smartval, &drive))
4346 || is_permissive() )) {
4347 pout("SMART Self-test Log not supported\n\n");
4348 }
4349 else {
4350 ata_smart_selftestlog smartselftest; memset(&smartselftest, 0, sizeof(smartselftest));
4351 if (ataReadSelfTestLog(device, &smartselftest, firmwarebugs)) {
4352 pout("Read SMART Self-test Log failed: %s\n\n", device->get_errmsg());
4353 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4354 }
4355 else {
4356 print_on();
4357 if (ataPrintSmartSelfTestlog(&smartselftest, !printing_is_switchable, firmwarebugs))
4358 returnval |= FAILLOG;
4359 print_off();
4360 pout("\n");
4361 }
4362 }
4363 }
4364
4365 // Print SMART selective self-test log
4366 if (options.smart_selective_selftest_log) {
4368
4369 if (!isSupportSelectiveSelfTest(&smartval))
4370 pout("Selective Self-tests/Logging not supported\n\n");
4371 else if(ataReadSelectiveSelfTestLog(device, &log)) {
4372 pout("Read SMART Selective Self-test Log failed: %s\n\n", device->get_errmsg());
4373 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4374 }
4375 else {
4376 print_on();
4377 // If any errors were found, they are logged in the SMART Self-test log.
4378 // So there is no need to print the Selective Self Test log in silent
4379 // mode.
4381 ataPrintSelectiveSelfTestLog(&log, &smartval);
4382 print_off();
4383 pout("\n");
4384 }
4385 }
4386
4387 // Check if SCT commands available
4388 bool sct_ok = isSCTCapable(&drive);
4389 if ( options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int
4390 || options.sct_erc_get || options.sct_erc_set ) {
4391 if (!sct_ok)
4392 pout("SCT Commands not supported\n\n");
4393 else if (locked) {
4394 pout("SCT Commands not supported if ATA Security is LOCKED\n\n");
4395 sct_ok = false;
4396 }
4397 }
4398
4399 // Print SCT status and temperature history table
4400 if (sct_ok && (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int)) {
4401 for (;;) {
4402 bool sct_temp_hist_ok = isSCTDataTableCapable(&drive);
4404
4405 if (options.sct_temp_sts || (options.sct_temp_hist && sct_temp_hist_ok)) {
4406 // Read SCT status
4407 if (ataReadSCTStatus(device, &sts)) {
4408 pout("\n");
4409 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4410 break;
4411 }
4412 if (options.sct_temp_sts) {
4413 ataPrintSCTStatus(&sts);
4414 pout("\n");
4415 }
4416 }
4417
4418 if (!sct_temp_hist_ok && (options.sct_temp_hist || options.sct_temp_int)) {
4419 pout("SCT Data Table command not supported\n\n");
4420 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4421 break;
4422 }
4423
4424 if (options.sct_temp_hist) {
4425 // Read SCT temperature history,
4426 // requires initial SCT status from above
4428 if (ataReadSCTTempHist(device, &tmh, &sts)) {
4429 pout("Read SCT Temperature History failed\n\n");
4430 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4431 break;
4432 }
4433 ataPrintSCTTempHist(&tmh);
4434 pout("\n");
4435 }
4436
4437 if (options.sct_temp_int) {
4438 // Set new temperature logging interval
4439 if (!isSCTFeatureControlCapable(&drive)) {
4440 pout("SCT Feature Control command not supported\n\n");
4441 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4442 break;
4443 }
4444 if (ataSetSCTTempInterval(device, options.sct_temp_int, options.sct_temp_int_pers)) {
4445 pout("Write Temperature Logging Interval failed\n\n");
4446 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4447 break;
4448 }
4449 pout("Temperature Logging Interval set to %u minute%s (%s)\n",
4450 options.sct_temp_int, (options.sct_temp_int == 1 ? "" : "s"),
4451 (options.sct_temp_int_pers ? "persistent" : "volatile"));
4452 }
4453 break;
4454 }
4455 }
4456
4457 // SCT Error Recovery Control
4458 if (sct_ok && (options.sct_erc_get || options.sct_erc_set)) {
4459 if (!isSCTErrorRecoveryControlCapable(&drive)) {
4460 pout("SCT Error Recovery Control command not supported\n\n");
4461 if (options.sct_erc_set)
4462 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4463 }
4464 else {
4465 int sct_erc_get = options.sct_erc_get;
4466 if (options.sct_erc_set) {
4467 // Set SCT Error Recovery Control
4468 bool set_power_on = (options.sct_erc_set == 2), mfg_default = (options.sct_erc_set == 3);
4469 if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime, set_power_on, mfg_default)
4470 || ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime, set_power_on, mfg_default)) {
4471 pout("SCT (Set) Error Recovery Control command failed\n");
4472 if (!( (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70)
4473 || (options.sct_erc_readtime == 0 && options.sct_erc_writetime == 0)))
4474 pout("Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n");
4475 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4476 sct_erc_get = 0;
4477 }
4478 else if (!sct_erc_get)
4480 options.sct_erc_writetime, set_power_on, mfg_default);
4481 }
4482
4483 if (sct_erc_get) {
4484 // Print SCT Error Recovery Control
4485 bool get_power_on = (sct_erc_get == 2);
4486 unsigned short read_timer, write_timer;
4487 if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer, get_power_on)
4488 || ataGetSCTErrorRecoveryControltime(device, 2, write_timer, get_power_on)) {
4489 pout("SCT (Get) Error Recovery Control command failed\n");
4490 if (options.sct_erc_set == sct_erc_get) {
4491 pout("The previous SCT (Set) Error Recovery Control command succeeded\n");
4493 options.sct_erc_writetime, get_power_on);
4494 }
4495 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4496 }
4497 else
4498 ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer, get_power_on);
4499 }
4500 pout("\n");
4501 }
4502 }
4503
4504 // Print Device Statistics
4505 if (options.devstat_all_pages || options.devstat_ssd_page || !options.devstat_pages.empty()) {
4506 bool use_gplog = true;
4507 unsigned nsectors = 0;
4508 if (gplogdir)
4509 nsectors = GetNumLogSectors(gplogdir, 0x04, true);
4510 else if (smartlogdir){ // for systems without ATA_READ_LOG_EXT
4511 nsectors = GetNumLogSectors(smartlogdir, 0x04, false);
4512 use_gplog = false;
4513 }
4514 if (!nsectors)
4515 pout("Device Statistics (GP/SMART Log 0x04) not supported\n\n");
4516 else if (!print_device_statistics(device, nsectors, options.devstat_pages,
4517 options.devstat_all_pages, options.devstat_ssd_page, use_gplog))
4518 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4519 }
4520
4521 // Print Pending Defects log
4522 if (options.pending_defects_log) {
4523 unsigned nsectors = GetNumLogSectors(gplogdir, 0x0c, true);
4524 if (!nsectors)
4525 pout("Pending Defects log (GP Log 0x0c) not supported\n\n");
4526 else if (!print_pending_defects_log(device, nsectors, options.pending_defects_log))
4527 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4528 }
4529
4530 // Print SATA Phy Event Counters
4531 if (options.sataphy) {
4532 unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true);
4533 // Packet interface devices do not provide a log directory, check support bit
4534 if (!nsectors && (drive.words047_079[76-47] & 0x0401) == 0x0400)
4535 nsectors = 1;
4536 if (!nsectors)
4537 pout("SATA Phy Event Counters (GP Log 0x11) not supported\n\n");
4538 else if (nsectors != 1)
4539 pout("SATA Phy Event Counters with %u sectors not supported\n\n", nsectors);
4540 else {
4541 unsigned char log_11[512] = {0, };
4542 unsigned char features = (options.sataphy_reset ? 0x01 : 0x00);
4543 if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1)) {
4544 pout("Read SATA Phy Event Counters failed\n\n");
4545 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4546 }
4547 else
4549 }
4550 }
4551
4552 // Print ATA FARM log for Seagate ATA drive
4553 if (options.farm_log || options.farm_log_suggest) {
4554 bool farm_supported = true;
4555 // Check if drive is a Seagate drive
4556 if (ataIsSeagate(drive, dbentry)) {
4557 unsigned nsectors = GetNumLogSectors(gplogdir, 0xA6, true);
4558 // Check if the Seagate drive is one that supports FARM
4559 if (!nsectors) {
4560 if (options.farm_log) {
4561 jout("FARM log (GP Log 0xa6) not supported\n\n");
4562 }
4563 farm_supported = false;
4564 } else {
4565 // If -x/-xall or -a/-all is run without explicit -l farm, suggests FARM log
4566 if (options.farm_log_suggest && !options.farm_log) {
4567 jout("Seagate FARM log (GP Log 0xa6) supported [try: -l farm]\n\n");
4568 // Otherwise, actually pull the FARM log
4569 } else {
4570 ataFarmLog farmLog;
4571 if (!ataReadFarmLog(device, farmLog, nsectors)) {
4572 pout("Read FARM log (GP Log 0xa6) failed\n\n");
4573 farm_supported = false;
4574 } else {
4575 ataPrintFarmLog(farmLog);
4576 jout("\n");
4577 }
4578 }
4579 }
4580 } else {
4581 if (options.farm_log) {
4582 jout("FARM log (GP Log 0xa6) not supported for non-Seagate drives\n\n");
4583 }
4584 farm_supported = false;
4585 }
4586 jglb["seagate_farm_log"]["supported"] = farm_supported;
4587 }
4588
4589 // Suggest '-x' if '-a' is specified without any advanced option
4590 if (options.a_option && !not_part_of_a_option)
4591 pout("The above only provides legacy SMART information - try 'smartctl -x' for more\n\n");
4592
4593 // Set to standby (spindown) mode and set standby timer if not done above
4594 // (Above commands may spinup drive)
4595 if (options.set_standby_now) {
4596 if (options.set_standby) {
4597 if (!ata_nodata_command(device, ATA_STANDBY, options.set_standby-1)) {
4598 pout("ATA STANDBY command failed: %s\n", device->get_errmsg());
4599 returnval |= FAILSMART;
4600 }
4601 else {
4602 print_standby_timer("Standby timer set to ", options.set_standby-1, drive);
4603 pout("Device placed in STANDBY mode\n");
4604 }
4605 }
4606 else {
4608 pout("ATA STANDBY IMMEDIATE command failed: %s\n", device->get_errmsg());
4609 returnval |= FAILSMART;
4610 }
4611 else
4612 pout("Device placed in STANDBY mode\n");
4613 }
4614 }
4615
4616 // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN
4617 if (!smart_val_ok || options.smart_selftest_type == -1)
4618 return returnval;
4619
4620 pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
4621 // if doing a self-test, be sure it's supported by the hardware
4622 switch (options.smart_selftest_type) {
4623 case OFFLINE_FULL_SCAN:
4624 if (!isSupportExecuteOfflineImmediate(&smartval)){
4625 pout("Execute Offline Immediate function not supported\n\n");
4626 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4627 }
4628 break;
4629 case ABORT_SELF_TEST:
4630 case SHORT_SELF_TEST:
4631 case EXTEND_SELF_TEST:
4634 if (!isSupportSelfTest(&smartval)){
4635 pout("Self-test functions not supported\n\n");
4636 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4637 }
4638 break;
4641 if (!isSupportConveyanceSelfTest(&smartval)){
4642 pout("Conveyance Self-test functions not supported\n\n");
4643 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4644 }
4645 break;
4648 if (!isSupportSelectiveSelfTest(&smartval)){
4649 pout("Selective Self-test functions not supported\n\n");
4650 failuretest(MANDATORY_CMD, returnval|=FAILSMART);
4651 }
4652 break;
4653 default:
4654 break; // Vendor specific type
4655 }
4656
4657 // Now do the test. Note ataSmartTest prints its own error/success
4658 // messages
4659 if (ataSmartTest(device, options.smart_selftest_type, options.smart_selftest_force,
4660 options.smart_selective_args, &smartval, sizes.sectors ))
4661 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4662 else {
4663 // Tell user how long test will take to complete. This is tricky
4664 // because in the case of an Offline Full Scan, the completion
4665 // timer is volatile, and needs to be read AFTER the command is
4666 // given. If this will interrupt the Offline Full Scan, we don't
4667 // do it, just warn user.
4668 if (options.smart_selftest_type == OFFLINE_FULL_SCAN) {
4669 if (isSupportOfflineAbort(&smartval))
4670 pout("Note: giving further SMART commands will abort Offline testing\n");
4671 else if (ataReadSmartValues(device, &smartval)){
4672 pout("Read SMART Data failed: %s\n\n", device->get_errmsg());
4673 failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
4674 }
4675 }
4676
4677 // Now say how long the test will take to complete
4678 int timewait = TestTime(&smartval, options.smart_selftest_type);
4679 if (timewait) {
4680 time_t t=time(NULL);
4681 if (options.smart_selftest_type == OFFLINE_FULL_SCAN) {
4682 t+=timewait;
4683 pout("Please wait %d seconds for test to complete.\n", (int)timewait);
4684 } else {
4685 t+=timewait*60;
4686 pout("Please wait %d minutes for test to complete.\n", (int)timewait);
4687 }
4688 char comptime[DATEANDEPOCHLEN];
4689 dateandtimezoneepoch(comptime, t);
4690 pout("Test will complete after %s\n", comptime);
4691
4696 pout("Use smartctl -X to abort test.\n");
4697 }
4698 }
4699
4700 return returnval;
4701}
const char * look_up_ata_command(unsigned char c_code, unsigned char f_reg)
bool ata_nodata_command(ata_device *device, unsigned char command, int sector_count)
Definition: atacmds.cpp:787
int ataDisableAutoOffline(ata_device *device)
Definition: atacmds.cpp:1581
unsigned char ata_return_temperature_value(const ata_smart_values *data, const ata_vendor_attr_defs &defs)
Definition: atacmds.cpp:2159
bool isSmartErrorLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
Definition: atacmds.cpp:1731
int ataGetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short &time_limit, bool power_on)
Definition: atacmds.cpp:2510
bool ataReadSmartLog(ata_device *device, unsigned char logaddr, void *data, unsigned nsectors)
Definition: atacmds.cpp:1143
int ata_get_wwn(const ata_identify_device *id, unsigned &oui, uint64_t &unique_id)
Definition: atacmds.cpp:900
int ataSmartTest(ata_device *device, int testtype, bool force, const ata_selective_selftest_args &selargs, const ata_smart_values *sv, uint64_t num_sectors)
Definition: atacmds.cpp:1611
int ataEnableAutoOffline(ata_device *device)
Definition: atacmds.cpp:1570
int ataSmartStatus2(ata_device *device)
Definition: atacmds.cpp:1604
int ataSmartSupport(const ata_identify_device *drive)
Definition: atacmds.cpp:936
int ataDisableAutoSave(ata_device *device)
Definition: atacmds.cpp:1558
int ata_get_rotation_rate(const ata_identify_device *id)
Definition: atacmds.cpp:920
bool ataReadLogExt(ata_device *device, unsigned char logaddr, unsigned char features, unsigned page, void *data, unsigned nsectors)
Definition: atacmds.cpp:1111
int ataEnableAutoSave(ata_device *device)
Definition: atacmds.cpp:1551
int ataReadSelfTestLog(ata_device *device, ata_smart_selftestlog *data, firmwarebug_defs firmwarebugs)
Definition: atacmds.cpp:1013
std::string ata_format_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
Definition: atacmds.cpp:1920
int ataReadSCTTempHist(ata_device *device, ata_sct_temperature_history_table *tmh, ata_sct_status_response *sts)
Definition: atacmds.cpp:2220
int ataReadErrorLog(ata_device *device, ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
Definition: atacmds.cpp:1424
void ata_get_size_info(const ata_identify_device *id, ata_size_info &sizes)
Definition: atacmds.cpp:658
int ata_read_identity(ata_device *device, ata_identify_device *buf, bool fix_swapped_id, unsigned char *raw_buf)
Definition: atacmds.cpp:817
int TestTime(const ata_smart_values *data, int testtype)
Definition: atacmds.cpp:1700
int ataEnableSmart(ata_device *device)
Definition: atacmds.cpp:1536
bool isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
Definition: atacmds.cpp:1769
int ataCheckPowerMode(ata_device *device)
Definition: atacmds.cpp:777
int ataGetSetSCTWriteCacheReordering(ata_device *device, bool enable, bool persistent, bool set)
Definition: atacmds.cpp:2349
unsigned char checksum(const void *data)
Definition: atacmds.cpp:716
bool ataReadExtSelfTestLog(ata_device *device, ata_smart_extselftestlog *log, unsigned nsectors)
Definition: atacmds.cpp:1061
int ataReadSelectiveSelfTestLog(ata_device *device, struct ata_selective_self_test_log *data)
Definition: atacmds.cpp:1184
bool isSmartTestLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
Definition: atacmds.cpp:1750
int ataReadSmartValues(ata_device *device, struct ata_smart_values *data)
Definition: atacmds.cpp:967
int ataSetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default)
Definition: atacmds.cpp:2516
int ataDoesSmartWork(ata_device *device)
Definition: atacmds.cpp:1593
uint64_t ata_get_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
Definition: atacmds.cpp:1846
bool dont_print_serial_number
Definition: atacmds.cpp:37
int ataReadSCTStatus(ata_device *device, ata_sct_status_response *sts)
Definition: atacmds.cpp:2188
bool ataReadExtErrorLog(ata_device *device, ata_smart_exterrlog *log, unsigned page, unsigned nsectors, firmwarebug_defs firmwarebugs)
Definition: atacmds.cpp:1491
int ataDisableSmart(ata_device *device)
Definition: atacmds.cpp:1543
int ataSetSCTTempInterval(ata_device *device, unsigned interval, bool persistent)
Definition: atacmds.cpp:2363
std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs &defs, int rpm)
Definition: atacmds.cpp:2127
int ataGetSetSCTWriteCache(ata_device *device, unsigned short state, bool persistent, bool set)
Definition: atacmds.cpp:2356
int ataReadSmartThresholds(ata_device *device, struct ata_smart_thresholds_pvt *data)
Definition: atacmds.cpp:1518
int ataIsSmartEnabled(const ata_identify_device *drive)
Definition: atacmds.cpp:951
void ata_format_id_string(char *out, const unsigned char *in, int n)
Definition: atacmds.cpp:762
int ataReadLogDirectory(ata_device *device, ata_smart_log_directory *data, bool gpl)
Definition: atacmds.cpp:1164
bool ata_set_features(ata_device *device, unsigned char features, int sector_count)
Definition: atacmds.cpp:799
ata_attr_state ata_get_attr_state(const ata_smart_attribute &attr, int attridx, const ata_smart_threshold_entry *thresholds, const ata_vendor_attr_defs &defs, unsigned char *threshval)
Definition: atacmds.cpp:1796
#define ATA_ENABLE_READ_LOOK_AHEAD
Definition: atacmds.h:72
#define ATTRIBUTE_FLAGS_OTHER(x)
Definition: atacmds.h:192
#define SELECTIVE_FLAG_PENDING
Definition: atacmds.h:500
#define ATA_DISABLE_WRITE_CACHE
Definition: atacmds.h:67
#define ATTRIBUTE_FLAGS_SELFPRESERVING(x)
Definition: atacmds.h:189
bool isSupportSelfTest(const ata_smart_values *data)
Definition: atacmds.h:877
#define ATA_STANDBY
Definition: atacmds.h:61
#define SELECTIVE_SELF_TEST
Definition: atacmds.h:101
bool isSCTErrorRecoveryControlCapable(const ata_identify_device *drive)
Definition: atacmds.h:889
#define ATA_ENABLE_APM
Definition: atacmds.h:70
#define ATA_STANDBY_IMMEDIATE
Definition: atacmds.h:62
bool isSupportOfflineSurfaceScan(const ata_smart_values *data)
Definition: atacmds.h:874
#define ATA_DISABLE_AAM
Definition: atacmds.h:65
#define OFFLINE_FULL_SCAN
Definition: atacmds.h:97
#define SHORT_SELF_TEST
Definition: atacmds.h:98
#define SELECTIVE_FLAG_DOSCAN
Definition: atacmds.h:499
bool isSupportConveyanceSelfTest(const ata_smart_values *data)
Definition: atacmds.h:880
#define ATA_ENABLE_DISABLE_DSN
Definition: atacmds.h:73
#define ATA_IDLE
Definition: atacmds.h:55
void checksumwarning(const char *string)
Definition: smartctl.cpp:1485
@ RAWFMT_MIN2HOUR
Definition: atacmds.h:665
@ RAWFMT_RAW16_OPT_RAW16
Definition: atacmds.h:659
@ RAWFMT_RAW24_OPT_RAW8
Definition: atacmds.h:661
@ RAWFMT_MSEC24_HOUR32
Definition: atacmds.h:667
@ RAWFMT_RAW64
Definition: atacmds.h:657
@ RAWFMT_RAW48
Definition: atacmds.h:653
@ RAWFMT_DEFAULT
Definition: atacmds.h:650
@ RAWFMT_HALFMIN2HOUR
Definition: atacmds.h:666
@ RAWFMT_SEC2HOUR
Definition: atacmds.h:664
#define ATTRIBUTE_FLAGS_EVENTCOUNT(x)
Definition: atacmds.h:186
#define ATTRIBUTE_FLAGS_PERFORMANCE(x)
Definition: atacmds.h:180
bool isSupportAutomaticTimer(const ata_smart_values *data)
Definition: atacmds.h:868
@ ATTRFLAG_NO_WORSTVAL
Definition: atacmds.h:676
#define EXTEND_SELF_TEST
Definition: atacmds.h:99
#define ATA_ENABLE_WRITE_CACHE
Definition: atacmds.h:71
bool isSupportSelectiveSelfTest(const ata_smart_values *data)
Definition: atacmds.h:883
bool isSCTDataTableCapable(const ata_identify_device *drive)
Definition: atacmds.h:895
#define ATA_DISABLE_READ_LOOK_AHEAD
Definition: atacmds.h:68
#define ATTRIBUTE_FLAGS_PREFAILURE(x)
Definition: atacmds.h:164
#define ATA_ENABLE_AAM
Definition: atacmds.h:69
bool isSupportExecuteOfflineImmediate(const ata_smart_values *data)
Definition: atacmds.h:862
bool isSupportOfflineAbort(const ata_smart_values *data)
Definition: atacmds.h:871
#define ABORT_SELF_TEST
Definition: atacmds.h:102
#define SELECTIVE_FLAG_ACTIVE
Definition: atacmds.h:501
#define ATTRIBUTE_FLAGS_ERRORRATE(x)
Definition: atacmds.h:183
#define EXTEND_CAPTIVE_SELF_TEST
Definition: atacmds.h:104
#define CONVEYANCE_CAPTIVE_SELF_TEST
Definition: atacmds.h:105
#define CONVEYANCE_SELF_TEST
Definition: atacmds.h:100
@ BUG_SAMSUNG3
Definition: atacmds.h:717
@ BUG_NOLOGDIR
Definition: atacmds.h:714
@ BUG_SAMSUNG
Definition: atacmds.h:715
@ BUG_SAMSUNG2
Definition: atacmds.h:716
#define ATA_SECURITY_FREEZE_LOCK
Definition: atacmds.h:57
#define SHORT_CAPTIVE_SELF_TEST
Definition: atacmds.h:103
#define ATA_DISABLE_APM
Definition: atacmds.h:66
#define NUMBER_ATA_SMART_ATTRIBUTES
Definition: atacmds.h:110
#define SELECTIVE_CAPTIVE_SELF_TEST
Definition: atacmds.h:106
#define ATTRIBUTE_FLAGS_ONLINE(x)
Definition: atacmds.h:174
bool isSCTFeatureControlCapable(const ata_identify_device *drive)
Definition: atacmds.h:892
bool isSCTCapable(const ata_identify_device *drive)
Definition: atacmds.h:886
ata_attr_state
Definition: atacmds.h:902
@ ATTRSTATE_FAILED_NOW
Definition: atacmds.h:908
@ ATTRSTATE_NON_EXISTING
Definition: atacmds.h:903
@ ATTRSTATE_NO_THRESHOLD
Definition: atacmds.h:905
@ ATTRSTATE_FAILED_PAST
Definition: atacmds.h:907
@ ATTRSTATE_NO_NORMVAL
Definition: atacmds.h:904
void ata_print_identify_data(const void *id, bool all_words, int bit_level)
static void print_standby_timer(const char *msg, int timer, const ata_identify_device &drive)
Definition: ataprint.cpp:3352
static const char * sct_ptemp(signed char x, char(&buf)[20])
Definition: ataprint.cpp:2994
static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer, bool power_on, bool mfg_default=false)
Definition: ataprint.cpp:3203
static void PrintSmartCapability(const ata_smart_values *data)
Definition: ataprint.cpp:1047
static const char * infofound(const char *output)
Definition: ataprint.cpp:40
const char * ataprint_cpp_cvsid
Definition: ataprint.cpp:36
static void ataPrintSCTCapability(const ata_identify_device *drive)
Definition: ataprint.cpp:1378
const devstat_entry_info devstat_info_0x04[]
Definition: ataprint.cpp:1732
static void PrintSmartTotalTimeCompleteOffline(const ata_smart_values *data)
Definition: ataprint.cpp:987
static void print_aam_level(const char *msg, int level, int recommended=-1)
Definition: ataprint.cpp:3228
const devstat_entry_info devstat_info_0x01[]
Definition: ataprint.cpp:1695
static void set_json_globals_from_device_statistics(int page, int offset, int64_t val)
Definition: ataprint.cpp:1798
static void print_sata_version_and_speed(unsigned short word222, unsigned short word076, unsigned short word077)
Definition: ataprint.cpp:621
static void print_ata_security_status(const char *msg, unsigned short state, unsigned short master_password_id)
Definition: ataprint.cpp:3289
static void PrintSmartOfflineCollectCap(const ata_smart_values *data)
Definition: ataprint.cpp:997
int ataPrintMain(ata_device *device, const ata_print_options &options)
Definition: ataprint.cpp:3386
static void PrintSmartOfflineStatus(const ata_smart_values *data)
Definition: ataprint.cpp:862
static void print_drive_info(const ata_identify_device *drive, const ata_size_info &sizes, int rpm, const drive_settings *dbentry, const char *dbversion)
Definition: ataprint.cpp:644
static void PrintSmartSelfExecStatus(const ata_smart_values *data, firmwarebug_defs firmwarebugs)
Definition: ataprint.cpp:890
const int num_devstat_infos
Definition: ataprint.cpp:1787
static const char * get_sata_version(unsigned short word222)
Definition: ataprint.cpp:559
const devstat_entry_info devstat_info_0x03[]
Definition: ataprint.cpp:1719
static void PrintSmartConveyanceSelfTestPollingTime(const ata_smart_values *data)
Definition: ataprint.cpp:1106
static bool is_permissive()
Definition: ataprint.cpp:46
const devstat_entry_info devstat_info_0x02[]
Definition: ataprint.cpp:1712
static int ataPrintSmartSelfTestlog(const ata_smart_selftestlog *log, bool allentries, firmwarebug_defs firmwarebugs)
Definition: ataprint.cpp:2699
static int PrintSmartErrorlog(const ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
Definition: ataprint.cpp:2227
static const char * get_ata_major_version(const ata_identify_device *drive)
Definition: ataprint.cpp:436
static const char * sct_device_state_msg(unsigned char state)
Definition: ataprint.cpp:3032
static const char * sct_pbar(int x, char(&buf)[64])
Definition: ataprint.cpp:3010
static std::string format_st_er_desc(unsigned char CR, unsigned char FR, unsigned char ST, unsigned char ER, unsigned short SC, const ata_smart_errorlog_error_struct *lba28_regs, const ata_smart_exterrlog_error *lba48_regs)
Definition: ataprint.cpp:67
static void ataPrintSelectiveSelfTestLog(const ata_selective_self_test_log *log, const ata_smart_values *sv)
Definition: ataprint.cpp:2851
static const char * get_pata_version(unsigned short word222, char(&buf)[32])
Definition: ataprint.cpp:546
static bool print_pending_defects_log(ata_device *device, unsigned nsectors, unsigned max_entries)
Definition: ataprint.cpp:2055
static void PrintSmartAttribWithThres(const ata_smart_values *data, const ata_smart_thresholds_pvt *thresholds, const ata_vendor_attr_defs &defs, int rpm, int onlyfailed, unsigned char format)
Definition: ataprint.cpp:1220
static void PrintSmartExtendedSelfTestPollingTime(const ata_smart_values *data)
Definition: ataprint.cpp:1093
#define P(n)
static void set_json_globals_from_smart_attrib(int id, const char *name, const ata_vendor_attr_defs &defs, uint8_t normval, uint8_t threshold, uint64_t rawval)
Definition: ataprint.cpp:1143
static void print_device_statistics_page(const json::ref &jref, const unsigned char *data, int page)
Definition: ataprint.cpp:1826
static bool print_device_statistics(ata_device *device, unsigned nsectors, const std::vector< int > &single_pages, bool all_pages, bool ssd_page, bool use_gplog)
Definition: ataprint.cpp:1938
static void PrintSataPhyEventCounters(const unsigned char *data, bool reset)
Definition: ataprint.cpp:2118
static void PrintSmartErrorLogCapability(const ata_smart_values *data, const ata_identify_device *identity)
Definition: ataprint.cpp:1072
static void PrintSmartShortSelfTestPollingTime(const ata_smart_values *data)
Definition: ataprint.cpp:1080
static const char * OfflineDataCollectionStatus(unsigned char status_byte)
Definition: ataprint.cpp:832
static int find_msb(unsigned short word)
Definition: ataprint.cpp:428
static std::string format_milliseconds(unsigned msec)
Definition: ataprint.cpp:2192
static void PrintGeneralSmartValues(const ata_smart_values *data, const ata_identify_device *drive, firmwarebug_defs firmwarebugs)
Definition: ataprint.cpp:1398
static void PrintLogPages(const char *type, const unsigned char *data, unsigned char logaddr, unsigned page, unsigned num_pages, unsigned max_pages)
Definition: ataprint.cpp:1654
static void sct_jtemp2(const json::ref &jref, const char *name, signed char x)
Definition: ataprint.cpp:3002
static unsigned GetNumLogSectors(const ata_smart_log_directory *logdir, unsigned logaddr, bool gpl)
Definition: ataprint.cpp:1434
const ata_smart_log_directory * fake_logdir(ata_smart_log_directory *logdir, const ata_print_options &options)
Definition: ataprint.cpp:1549
static void print_apm_level(const char *msg, int level)
Definition: ataprint.cpp:3259
const devstat_entry_info devstat_info_0x07[]
Definition: ataprint.cpp:1767
static const char * get_error_log_state_desc(unsigned state)
Definition: ataprint.cpp:2211
static int ataPrintSCTTempHist(const ata_sct_temperature_history_table *tmh)
Definition: ataprint.cpp:3131
const devstat_entry_info devstat_info_0x00[]
Definition: ataprint.cpp:1690
static const char * get_log_rw(unsigned logaddr)
Definition: ataprint.cpp:1520
static const char * GetLogName(unsigned logaddr)
Definition: ataprint.cpp:1450
const devstat_entry_info devstat_info_0x05[]
Definition: ataprint.cpp:1741
static int PrintSmartExtSelfTestLog(const ata_smart_extselftestlog *log, unsigned nsectors, unsigned max_entries)
Definition: ataprint.cpp:2767
static void jset_sata_speed(const char *key, int value, int speed, const char *str)
Definition: ataprint.cpp:602
static const char * get_sata_speed(int speed)
Definition: ataprint.cpp:583
static int find_failed_attr(const ata_smart_values *data, const ata_smart_thresholds_pvt *thresholds, const ata_vendor_attr_defs &defs, int onlyfailed)
Definition: ataprint.cpp:1122
static int ataPrintSCTStatus(const ata_sct_status_response *sts)
Definition: ataprint.cpp:3046
static const char * get_device_statistics_page_name(int page)
Definition: ataprint.cpp:1789
const devstat_entry_info devstat_info_0x06[]
Definition: ataprint.cpp:1759
static const char * get_ata_minor_version(const ata_identify_device *drive)
Definition: ataprint.cpp:462
static int ataPrintSmartSelfTestEntry(const json::ref &jref, unsigned testnum, unsigned char test_type, unsigned char test_status, unsigned short timestamp, uint64_t failing_lba, bool print_error_only, bool &print_header)
Definition: ataprint.cpp:2604
static int PrintSmartExtErrorLog(ata_device *device, const firmwarebug_defs &firmwarebugs, const ata_smart_exterrlog *log, unsigned nsectors, unsigned max_errors)
Definition: ataprint.cpp:2383
static void PrintLogDirectories(const ata_smart_log_directory *gplogdir, const ata_smart_log_directory *smartlogdir)
Definition: ataprint.cpp:1565
const devstat_entry_info * devstat_infos[]
Definition: ataprint.cpp:1773
static const char * get_form_factor(unsigned short word168)
Definition: ataprint.cpp:408
#define ATAPRINT_H_CVSID
Definition: ataprint.h:16
ATA device access.
virtual bool ata_identify_is_cached() const
Return true if OS caches ATA identify sector.
bool is_set(firmwarebug_t bug) const
Definition: atacmds.h:728
Reference to a JSON element.
Definition: json.h:105
void set_unsafe_uint64(uint64_t value)
Definition: json.cpp:193
bool is_enabled() const
Return true if enabled.
Definition: json.h:187
unsigned char * data()
Definition: utility.h:148
Wrapper class for POSIX regex(3) or std::regex Supports copy & assignment and is compatible with STL ...
Definition: utility.h:222
bool full_match(const char *str) const
Return true if full string matches pattern.
Definition: utility.cpp:593
int get_errno() const
Get last error number.
const char * get_errmsg() const
Get last error message.
virtual bool is_syscall_unsup() const
Return true if last error indicates an unsupported system call.
void clear_err()
Clear last error info.
bool ataIsSeagate(const ata_identify_device &drive, const drive_settings *dbentry)
Definition: farmcmds.cpp:33
bool ataReadFarmLog(ata_device *device, ataFarmLog &farmLog, unsigned nsectors)
Definition: farmcmds.cpp:56
void ataPrintFarmLog(const ataFarmLog &farmLog)
Definition: farmprint.cpp:150
const drive_settings * lookup_drive_apply_presets(const ata_identify_device *drive, ata_vendor_attr_defs &defs, firmwarebug_defs &firmwarebugs, std::string &dbversion)
void show_presets(const ata_identify_device *drive)
u8 cmd
Definition: megaraid.h:1
u16 flags
Definition: megaraid.h:14
u32 count
Definition: megaraid.h:1
u8 b[12]
Definition: megaraid.h:17
u16 s[6]
Definition: megaraid.h:18
ptr_t data
Definition: megaraid.h:15
u32 size
Definition: megaraid.h:0
uint8_t id
union @43 entry
unsigned char failuretest_permissive
Definition: smartctl.cpp:1457
static uint64_t sg_get_unaligned_le64(const void *p)
Definition: sg_unaligned.h:303
static uint32_t sg_get_unaligned_le32(const void *p)
Definition: sg_unaligned.h:297
void jout_startup_datetime(const char *prefix)
Definition: smartctl.cpp:1450
json jglb
Definition: smartctl.cpp:53
void failuretest(failure_type type, int returnvalue)
Definition: smartctl.cpp:1462
bool printing_is_switchable
Definition: smartctl.cpp:49
#define FAILATTR
Definition: smartctl.h:39
#define FAILERR
Definition: smartctl.h:46
void void jinf(const char *fmt,...) __attribute_format_printf(1
#define FAILID
Definition: smartctl.h:30
#define FAILSTATUS
Definition: smartctl.h:36
#define FAILAGE
Definition: smartctl.h:43
void print_off()
Definition: smartctl.h:79
#define FAILSMART
Definition: smartctl.h:33
void void void jwrn(const char *fmt,...) __attribute_format_printf(1
void void void void jerr(const char *fmt,...) __attribute_format_printf(1
void jout(const char *fmt,...) __attribute_format_printf(1
@ OPTIONAL_CMD
Definition: smartctl.h:57
@ MANDATORY_CMD
Definition: smartctl.h:58
void print_on()
Definition: smartctl.h:74
#define FAILLOG
Definition: smartctl.h:49
void pout(const char *fmt,...)
Definition: smartd.cpp:1335
unsigned char model[40]
Definition: atacmds.h:120
unsigned short minor_rev_num
Definition: atacmds.h:123
unsigned short major_rev_num
Definition: atacmds.h:122
unsigned short words047_079[33]
Definition: atacmds.h:121
unsigned short cfs_enable_1
Definition: atacmds.h:127
unsigned short words088_255[168]
Definition: atacmds.h:130
unsigned short command_set_2
Definition: atacmds.h:125
unsigned short word086
Definition: atacmds.h:128
unsigned char fw_rev[8]
Definition: atacmds.h:119
unsigned short command_set_1
Definition: atacmds.h:124
unsigned char serial_no[20]
Definition: atacmds.h:117
unsigned page
Definition: ataprint.h:25
unsigned char logaddr
Definition: ataprint.h:24
unsigned nsectors
Definition: ataprint.h:26
bool sct_wcache_sct_get
Definition: ataprint.h:101
bool sct_temp_hist
Definition: ataprint.h:54
bool smart_auto_offl_disable
Definition: ataprint.h:61
bool sct_wcache_reorder_get
Definition: ataprint.h:98
bool smart_auto_save_enable
Definition: ataprint.h:62
bool smart_general_values
Definition: ataprint.h:36
unsigned sct_erc_writetime
Definition: ataprint.h:57
bool devstat_all_pages
Definition: ataprint.h:49
bool set_security_freeze
Definition: ataprint.h:95
unsigned pending_defects_log
Definition: ataprint.h:52
bool set_standby_now
Definition: ataprint.h:93
int identify_word_level
Definition: ataprint.h:34
int smart_selftest_type
Definition: ataprint.h:64
bool smart_selftest_log
Definition: ataprint.h:39
int identify_bit_level
Definition: ataprint.h:34
bool smart_disable
Definition: ataprint.h:60
ata_selective_selftest_args smart_selective_args
Definition: ataprint.h:66
unsigned char powerexit
Definition: ataprint.h:82
std::vector< int > devstat_pages
Definition: ataprint.h:50
bool smart_check_status
Definition: ataprint.h:35
bool farm_log_suggest
Definition: ataprint.h:108
unsigned smart_ext_error_log
Definition: ataprint.h:43
bool fix_swapped_id
Definition: ataprint.h:75
unsigned smart_ext_selftest_log
Definition: ataprint.h:44
firmwarebug_defs firmwarebugs
Definition: ataprint.h:74
bool ignore_presets
Definition: ataprint.h:79
unsigned char powermode
Definition: ataprint.h:81
bool get_lookahead
Definition: ataprint.h:90
bool sataphy_reset
Definition: ataprint.h:58
unsigned char output_format
Definition: ataprint.h:72
int sct_wcache_reorder_set
Definition: ataprint.h:99
bool sct_temp_int_pers
Definition: ataprint.h:69
bool smart_selftest_force
Definition: ataprint.h:65
bool smart_selective_selftest_log
Definition: ataprint.h:40
bool devstat_ssd_page
Definition: ataprint.h:49
ata_vendor_attr_defs attribute_defs
Definition: ataprint.h:77
unsigned sct_temp_int
Definition: ataprint.h:68
unsigned sct_erc_readtime
Definition: ataprint.h:57
bool smart_vendor_attrib
Definition: ataprint.h:37
std::vector< ata_log_request > log_requests
Definition: ataprint.h:47
bool sct_wcache_sct_set_pers
Definition: ataprint.h:103
bool retry_error_log
Definition: ataprint.h:45
bool sct_wcache_reorder_set_pers
Definition: ataprint.h:100
bool smart_auto_offl_enable
Definition: ataprint.h:61
bool retry_selftest_log
Definition: ataprint.h:45
bool smart_error_log
Definition: ataprint.h:38
bool smart_auto_save_disable
Definition: ataprint.h:62
int sct_wcache_sct_set
Definition: ataprint.h:102
unsigned int over_limit_count
Definition: atacmds.h:532
unsigned short min_erc_time
Definition: atacmds.h:535
unsigned short sct_version
Definition: atacmds.h:515
unsigned short sct_spec
Definition: atacmds.h:516
unsigned short format_version
Definition: atacmds.h:514
signed char life_max_temp
Definition: atacmds.h:530
unsigned char vendor_specific[32]
Definition: atacmds.h:537
signed char max_temp
Definition: atacmds.h:528
unsigned char device_state
Definition: atacmds.h:518
signed char max_op_limit
Definition: atacmds.h:531
signed char min_temp
Definition: atacmds.h:527
signed char hda_temp
Definition: atacmds.h:526
unsigned int under_limit_count
Definition: atacmds.h:533
signed char life_min_temp
Definition: atacmds.h:529
unsigned short smart_status
Definition: atacmds.h:534
unsigned short sampling_period
Definition: atacmds.h:590
unsigned short flags
Definition: atacmds.h:490
struct test_span span[5]
Definition: atacmds.h:485
unsigned short pendingtime
Definition: atacmds.h:492
unsigned short logversion
Definition: atacmds.h:484
unsigned short currentspan
Definition: atacmds.h:489
unsigned phy_sector_size
Definition: atacmds.h:988
uint64_t capacity
Definition: atacmds.h:986
uint64_t sectors
Definition: atacmds.h:985
unsigned log_sector_offset
Definition: atacmds.h:989
unsigned log_sector_size
Definition: atacmds.h:987
unsigned char id
Definition: atacmds.h:138
unsigned char current
Definition: atacmds.h:142
unsigned short flags
Definition: atacmds.h:141
unsigned char worst
Definition: atacmds.h:143
unsigned char error_register
Definition: atacmds.h:256
struct ata_smart_errorlog_command_struct commands[5]
Definition: atacmds.h:290
struct ata_smart_errorlog_error_struct error_struct
Definition: atacmds.h:291
unsigned char state
Definition: atacmds.h:359
unsigned char device_control_register
Definition: atacmds.h:345
unsigned char lba_low_register_hi
Definition: atacmds.h:350
unsigned char lba_low_register
Definition: atacmds.h:349
unsigned char count_register
Definition: atacmds.h:347
unsigned char error_register
Definition: atacmds.h:346
unsigned char count_register_hi
Definition: atacmds.h:348
unsigned char lba_high_register_hi
Definition: atacmds.h:354
unsigned char device_register
Definition: atacmds.h:355
unsigned char status_register
Definition: atacmds.h:356
unsigned char lba_mid_register
Definition: atacmds.h:351
unsigned char lba_mid_register_hi
Definition: atacmds.h:352
unsigned short timestamp
Definition: atacmds.h:360
unsigned char lba_high_register
Definition: atacmds.h:353
unsigned short error_log_index
Definition: atacmds.h:383
unsigned char reserved1
Definition: atacmds.h:382
ata_smart_exterrlog_error_log error_logs[4]
Definition: atacmds.h:384
unsigned short device_error_count
Definition: atacmds.h:385
unsigned char version
Definition: atacmds.h:381
struct ata_smart_extselftestlog_desc log_descs[19]
Definition: atacmds.h:447
unsigned char version
Definition: atacmds.h:444
unsigned short log_desc_index
Definition: atacmds.h:446
unsigned char reserved1
Definition: atacmds.h:445
struct ata_smart_log_entry entry[255]
Definition: atacmds.h:467
unsigned short int logversion
Definition: atacmds.h:466
unsigned char reserved
Definition: atacmds.h:459
unsigned char numsectors
Definition: atacmds.h:458
unsigned char mostrecenttest
Definition: atacmds.h:412
struct ata_smart_selftestlog_struct selftest_struct[21]
Definition: atacmds.h:410
unsigned short int revnumber
Definition: atacmds.h:409
struct ata_smart_threshold_entry thres_entries[NUMBER_ATA_SMART_ATTRIBUTES]
Definition: atacmds.h:244
unsigned char self_test_exec_status
Definition: atacmds.h:202
unsigned char offline_data_collection_status
Definition: atacmds.h:201
Definition: ataprint.cpp:1685
const char * name
Definition: ataprint.cpp:1687
short size
Definition: ataprint.cpp:1686
const char * modelfamily
Definition: knowndrives.h:19
const char * warningmsg
Definition: knowndrives.h:22
uint64_t start
Definition: atacmds.h:476
uint64_t end
Definition: atacmds.h:477
void dateandtimezoneepoch(char(&buffer)[DATEANDEPOCHLEN], time_t tval)
Definition: utility.cpp:349
const char * format_capacity(char *str, int strsize, uint64_t val, const char *decimal_point)
Definition: utility.cpp:748
const char * format_with_thousands_sep(char *str, int strsize, uint64_t val, const char *thousands_sep)
Definition: utility.cpp:716
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:799
bool nonempty(const void *data, int size)
Definition: utility.cpp:682
const char * packetdevicetype(int type)
Definition: utility.cpp:315
struct tm * time_to_tm_local(struct tm *tp, time_t t)
Definition: utility.cpp:326
#define DATEANDEPOCHLEN
Definition: utility.h:64
bool str_starts_with(const char *str, const char *prefix)
Definition: utility.h:52