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