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