|
smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
|
00001 /* 00002 * ataprint.cpp 00003 * 00004 * Home page of code is: http://smartmontools.sourceforge.net 00005 * 00006 * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net> 00007 * Copyright (C) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net> 00008 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> 00009 * 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2, or (at your option) 00013 * any later version. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>. 00017 * 00018 * This code was originally developed as a Senior Thesis by Michael Cornwell 00019 * at the Concurrent Systems Laboratory (now part of the Storage Systems 00020 * Research Center), Jack Baskin School of Engineering, University of 00021 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ 00022 * 00023 */ 00024 00025 #include "config.h" 00026 00027 #include <ctype.h> 00028 #include <errno.h> 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 00033 #include "int64.h" 00034 #include "atacmdnames.h" 00035 #include "atacmds.h" 00036 #include "ataidentify.h" 00037 #include "dev_interface.h" 00038 #include "ataprint.h" 00039 #include "smartctl.h" 00040 #include "utility.h" 00041 #include "knowndrives.h" 00042 00043 const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3786 2013-03-07 22:09:17Z chrfranke $" 00044 ATAPRINT_H_CVSID; 00045 00046 00047 static const char * infofound(const char *output) { 00048 return (*output ? output : "[No Information Found]"); 00049 } 00050 00051 // Return true if '-T permissive' is specified, 00052 // used to ignore missing capabilities 00053 static bool is_permissive() 00054 { 00055 if (!failuretest_permissive) 00056 return false; 00057 failuretest_permissive--; 00058 return true; 00059 } 00060 00061 /* For the given Command Register (CR) and Features Register (FR), attempts 00062 * to construct a string that describes the contents of the Status 00063 * Register (ST) and Error Register (ER). If the meanings of the flags of 00064 * the error register are not known for the given command then it returns an 00065 * empty string. 00066 * 00067 * The meanings of the flags of the error register for all commands are 00068 * described in the ATA spec and could all be supported here in theory. 00069 * Currently, only a few commands are supported (those that have been seen 00070 * to produce errors). If many more are to be added then this function 00071 * should probably be redesigned. 00072 */ 00073 00074 static std::string format_st_er_desc( 00075 unsigned char CR, unsigned char FR, 00076 unsigned char ST, unsigned char ER, 00077 unsigned short SC, 00078 const ata_smart_errorlog_error_struct * lba28_regs, 00079 const ata_smart_exterrlog_error * lba48_regs 00080 ) 00081 { 00082 const char *error_flag[8]; 00083 int i, print_lba=0, print_sector=0; 00084 00085 // Set of character strings corresponding to different error codes. 00086 // Please keep in alphabetic order if you add more. 00087 const char *abrt = "ABRT"; // ABORTED 00088 const char *amnf = "AMNF"; // ADDRESS MARK NOT FOUND 00089 const char *ccto = "CCTO"; // COMMAND COMPLETION TIMED OUT 00090 const char *eom = "EOM"; // END OF MEDIA 00091 const char *icrc = "ICRC"; // INTERFACE CRC ERROR 00092 const char *idnf = "IDNF"; // ID NOT FOUND 00093 const char *ili = "ILI"; // MEANING OF THIS BIT IS COMMAND-SET SPECIFIC 00094 const char *mc = "MC"; // MEDIA CHANGED 00095 const char *mcr = "MCR"; // MEDIA CHANGE REQUEST 00096 const char *nm = "NM"; // NO MEDIA 00097 const char *obs = "obs"; // OBSOLETE 00098 const char *tk0nf = "TK0NF"; // TRACK 0 NOT FOUND 00099 const char *unc = "UNC"; // UNCORRECTABLE 00100 const char *wp = "WP"; // WRITE PROTECTED 00101 00102 /* If for any command the Device Fault flag of the status register is 00103 * not used then used_device_fault should be set to 0 (in the CR switch 00104 * below) 00105 */ 00106 int uses_device_fault = 1; 00107 00108 /* A value of NULL means that the error flag isn't used */ 00109 for (i = 0; i < 8; i++) 00110 error_flag[i] = NULL; 00111 00112 std::string str; 00113 00114 switch (CR) { 00115 case 0x10: // RECALIBRATE 00116 error_flag[2] = abrt; 00117 error_flag[1] = tk0nf; 00118 break; 00119 case 0x20: /* READ SECTOR(S) */ 00120 case 0x21: // READ SECTOR(S) 00121 case 0x24: // READ SECTOR(S) EXT 00122 case 0xC4: /* READ MULTIPLE */ 00123 case 0x29: // READ MULTIPLE EXT 00124 error_flag[6] = unc; 00125 error_flag[5] = mc; 00126 error_flag[4] = idnf; 00127 error_flag[3] = mcr; 00128 error_flag[2] = abrt; 00129 error_flag[1] = nm; 00130 error_flag[0] = amnf; 00131 print_lba=1; 00132 break; 00133 case 0x22: // READ LONG (with retries) 00134 case 0x23: // READ LONG (without retries) 00135 error_flag[4] = idnf; 00136 error_flag[2] = abrt; 00137 error_flag[0] = amnf; 00138 print_lba=1; 00139 break; 00140 case 0x2a: // READ STREAM DMA 00141 case 0x2b: // READ STREAM PIO 00142 if (CR==0x2a) 00143 error_flag[7] = icrc; 00144 error_flag[6] = unc; 00145 error_flag[5] = mc; 00146 error_flag[4] = idnf; 00147 error_flag[3] = mcr; 00148 error_flag[2] = abrt; 00149 error_flag[1] = nm; 00150 error_flag[0] = ccto; 00151 print_lba=1; 00152 print_sector=SC; 00153 break; 00154 case 0x3A: // WRITE STREAM DMA 00155 case 0x3B: // WRITE STREAM PIO 00156 if (CR==0x3A) 00157 error_flag[7] = icrc; 00158 error_flag[6] = wp; 00159 error_flag[5] = mc; 00160 error_flag[4] = idnf; 00161 error_flag[3] = mcr; 00162 error_flag[2] = abrt; 00163 error_flag[1] = nm; 00164 error_flag[0] = ccto; 00165 print_lba=1; 00166 print_sector=SC; 00167 break; 00168 case 0x25: // READ DMA EXT 00169 case 0x26: // READ DMA QUEUED EXT 00170 case 0xC7: // READ DMA QUEUED 00171 case 0xC8: // READ DMA (with retries) 00172 case 0xC9: // READ DMA (without retries, obsolete since ATA-5) 00173 case 0x60: // READ FPDMA QUEUED (NCQ) 00174 error_flag[7] = icrc; 00175 error_flag[6] = unc; 00176 error_flag[5] = mc; 00177 error_flag[4] = idnf; 00178 error_flag[3] = mcr; 00179 error_flag[2] = abrt; 00180 error_flag[1] = nm; 00181 error_flag[0] = amnf; 00182 print_lba=1; 00183 if (CR==0x25 || CR==0xC8) 00184 print_sector=SC; 00185 break; 00186 case 0x30: /* WRITE SECTOR(S) */ 00187 case 0x31: // WRITE SECTOR(S) 00188 case 0x34: // WRITE SECTOR(S) EXT 00189 case 0xC5: /* WRITE MULTIPLE */ 00190 case 0x39: // WRITE MULTIPLE EXT 00191 case 0xCE: // WRITE MULTIPLE FUA EXT 00192 error_flag[6] = wp; 00193 error_flag[5] = mc; 00194 error_flag[4] = idnf; 00195 error_flag[3] = mcr; 00196 error_flag[2] = abrt; 00197 error_flag[1] = nm; 00198 print_lba=1; 00199 break; 00200 case 0x32: // WRITE LONG (with retries) 00201 case 0x33: // WRITE LONG (without retries) 00202 error_flag[4] = idnf; 00203 error_flag[2] = abrt; 00204 print_lba=1; 00205 break; 00206 case 0x3C: // WRITE VERIFY 00207 error_flag[6] = unc; 00208 error_flag[4] = idnf; 00209 error_flag[2] = abrt; 00210 error_flag[0] = amnf; 00211 print_lba=1; 00212 break; 00213 case 0x40: // READ VERIFY SECTOR(S) with retries 00214 case 0x41: // READ VERIFY SECTOR(S) without retries 00215 case 0x42: // READ VERIFY SECTOR(S) EXT 00216 error_flag[6] = unc; 00217 error_flag[5] = mc; 00218 error_flag[4] = idnf; 00219 error_flag[3] = mcr; 00220 error_flag[2] = abrt; 00221 error_flag[1] = nm; 00222 error_flag[0] = amnf; 00223 print_lba=1; 00224 break; 00225 case 0xA0: /* PACKET */ 00226 /* Bits 4-7 are all used for sense key (a 'command packet set specific error 00227 * indication' according to the ATA/ATAPI-7 standard), so "Sense key" will 00228 * be repeated in the error description string if more than one of those 00229 * bits is set. 00230 */ 00231 error_flag[7] = "Sense key (bit 3)", 00232 error_flag[6] = "Sense key (bit 2)", 00233 error_flag[5] = "Sense key (bit 1)", 00234 error_flag[4] = "Sense key (bit 0)", 00235 error_flag[2] = abrt; 00236 error_flag[1] = eom; 00237 error_flag[0] = ili; 00238 break; 00239 case 0xA1: /* IDENTIFY PACKET DEVICE */ 00240 case 0xEF: /* SET FEATURES */ 00241 case 0x00: /* NOP */ 00242 case 0xC6: /* SET MULTIPLE MODE */ 00243 error_flag[2] = abrt; 00244 break; 00245 case 0x2F: // READ LOG EXT 00246 error_flag[6] = unc; 00247 error_flag[4] = idnf; 00248 error_flag[2] = abrt; 00249 error_flag[0] = obs; 00250 break; 00251 case 0x3F: // WRITE LOG EXT 00252 error_flag[4] = idnf; 00253 error_flag[2] = abrt; 00254 error_flag[0] = obs; 00255 break; 00256 case 0xB0: /* SMART */ 00257 switch(FR) { 00258 case 0xD0: // SMART READ DATA 00259 case 0xD1: // SMART READ ATTRIBUTE THRESHOLDS 00260 case 0xD5: /* SMART READ LOG */ 00261 error_flag[6] = unc; 00262 error_flag[4] = idnf; 00263 error_flag[2] = abrt; 00264 error_flag[0] = obs; 00265 break; 00266 case 0xD6: /* SMART WRITE LOG */ 00267 error_flag[4] = idnf; 00268 error_flag[2] = abrt; 00269 error_flag[0] = obs; 00270 break; 00271 case 0xD2: // Enable/Disable Attribute Autosave 00272 case 0xD3: // SMART SAVE ATTRIBUTE VALUES (ATA-3) 00273 case 0xD8: // SMART ENABLE OPERATIONS 00274 case 0xD9: /* SMART DISABLE OPERATIONS */ 00275 case 0xDA: /* SMART RETURN STATUS */ 00276 case 0xDB: // Enable/Disable Auto Offline (SFF) 00277 error_flag[2] = abrt; 00278 break; 00279 case 0xD4: // SMART EXECUTE IMMEDIATE OFFLINE 00280 error_flag[4] = idnf; 00281 error_flag[2] = abrt; 00282 break; 00283 default: 00284 return str; // "" 00285 break; 00286 } 00287 break; 00288 case 0xB1: /* DEVICE CONFIGURATION */ 00289 switch (FR) { 00290 case 0xC0: /* DEVICE CONFIGURATION RESTORE */ 00291 error_flag[2] = abrt; 00292 break; 00293 default: 00294 return str; // "" 00295 break; 00296 } 00297 break; 00298 case 0xCA: // WRITE DMA (with retries) 00299 case 0xCB: // WRITE DMA (without retries, obsolete since ATA-5) 00300 case 0x35: // WRITE DMA EXT 00301 case 0x3D: // WRITE DMA FUA EXT 00302 case 0xCC: // WRITE DMA QUEUED 00303 case 0x36: // WRITE DMA QUEUED EXT 00304 case 0x3E: // WRITE DMA QUEUED FUA EXT 00305 case 0x61: // WRITE FPDMA QUEUED (NCQ) 00306 error_flag[7] = icrc; 00307 error_flag[6] = wp; 00308 error_flag[5] = mc; 00309 error_flag[4] = idnf; 00310 error_flag[3] = mcr; 00311 error_flag[2] = abrt; 00312 error_flag[1] = nm; 00313 error_flag[0] = amnf; 00314 print_lba=1; 00315 if (CR==0x35) 00316 print_sector=SC; 00317 break; 00318 case 0xE4: // READ BUFFER 00319 case 0xE8: // WRITE BUFFER 00320 error_flag[2] = abrt; 00321 break; 00322 default: 00323 return str; // "" 00324 } 00325 00326 /* We ignore any status flags other than Device Fault and Error */ 00327 00328 if (uses_device_fault && (ST & (1 << 5))) { 00329 str = "Device Fault"; 00330 if (ST & 1) // Error flag 00331 str += "; "; 00332 } 00333 if (ST & 1) { // Error flag 00334 int count = 0; 00335 00336 str += "Error: "; 00337 for (i = 7; i >= 0; i--) 00338 if ((ER & (1 << i)) && (error_flag[i])) { 00339 if (count++ > 0) 00340 str += ", "; 00341 str += error_flag[i]; 00342 } 00343 } 00344 00345 // If the error was a READ or WRITE error, print the Logical Block 00346 // Address (LBA) at which the read or write failed. 00347 if (print_lba) { 00348 // print number of sectors, if known, and append to print string 00349 if (print_sector) 00350 str += strprintf(" %d sectors", print_sector); 00351 00352 if (lba28_regs) { 00353 unsigned lba; 00354 // bits 24-27: bits 0-3 of DH 00355 lba = 0xf & lba28_regs->drive_head; 00356 lba <<= 8; 00357 // bits 16-23: CH 00358 lba |= lba28_regs->cylinder_high; 00359 lba <<= 8; 00360 // bits 8-15: CL 00361 lba |= lba28_regs->cylinder_low; 00362 lba <<= 8; 00363 // bits 0-7: SN 00364 lba |= lba28_regs->sector_number; 00365 str += strprintf(" at LBA = 0x%08x = %u", lba, lba); 00366 } 00367 else if (lba48_regs) { 00368 // This assumes that upper LBA registers are 0 for 28-bit commands 00369 // (TODO: detect 48-bit commands above) 00370 uint64_t lba48; 00371 lba48 = lba48_regs->lba_high_register_hi; 00372 lba48 <<= 8; 00373 lba48 |= lba48_regs->lba_mid_register_hi; 00374 lba48 <<= 8; 00375 lba48 |= lba48_regs->lba_low_register_hi; 00376 lba48 |= lba48_regs->device_register & 0xf; 00377 lba48 <<= 8; 00378 lba48 |= lba48_regs->lba_high_register; 00379 lba48 <<= 8; 00380 lba48 |= lba48_regs->lba_mid_register; 00381 lba48 <<= 8; 00382 lba48 |= lba48_regs->lba_low_register; 00383 str += strprintf(" at LBA = 0x%08"PRIx64" = %"PRIu64, lba48, lba48); 00384 } 00385 } 00386 00387 return str; 00388 } 00389 00390 static inline std::string format_st_er_desc( 00391 const ata_smart_errorlog_struct * data) 00392 { 00393 return format_st_er_desc( 00394 data->commands[4].commandreg, 00395 data->commands[4].featuresreg, 00396 data->error_struct.status, 00397 data->error_struct.error_register, 00398 data->error_struct.sector_count, 00399 &data->error_struct, (const ata_smart_exterrlog_error *)0); 00400 } 00401 00402 static inline std::string format_st_er_desc( 00403 const ata_smart_exterrlog_error_log * data) 00404 { 00405 return format_st_er_desc( 00406 data->commands[4].command_register, 00407 data->commands[4].features_register, 00408 data->error.status_register, 00409 data->error.error_register, 00410 data->error.count_register_hi << 8 | data->error.count_register, 00411 (const ata_smart_errorlog_error_struct *)0, &data->error); 00412 } 00413 00414 00415 static int find_msb(unsigned short word) 00416 { 00417 for (int bit = 15; bit >= 0; bit--) 00418 if (word & (1 << bit)) 00419 return bit; 00420 return -1; 00421 } 00422 00423 static const char * get_ata_major_version(const ata_identify_device * drive) 00424 { 00425 switch (find_msb(drive->major_rev_num)) { 00426 case 10: return "ACS-3"; 00427 case 9: return "ACS-2"; 00428 case 8: return "ATA8-ACS"; 00429 case 7: return "ATA/ATAPI-7"; 00430 case 6: return "ATA/ATAPI-6"; 00431 case 5: return "ATA/ATAPI-5"; 00432 case 4: return "ATA/ATAPI-4"; 00433 case 3: return "ATA-3"; 00434 case 2: return "ATA-2"; 00435 case 1: return "ATA-1"; 00436 default: return 0; 00437 } 00438 } 00439 00440 static const char * get_ata_minor_version(const ata_identify_device * drive) 00441 { 00442 switch (drive->minor_rev_num) { 00443 case 0x0001: return "ATA-1 X3T9.2/781D prior to revision 4"; 00444 case 0x0002: return "ATA-1 published, ANSI X3.221-1994"; 00445 case 0x0003: return "ATA-1 X3T9.2/781D revision 4"; 00446 case 0x0004: return "ATA-2 published, ANSI X3.279-1996"; 00447 case 0x0005: return "ATA-2 X3T10/948D prior to revision 2k"; 00448 case 0x0006: return "ATA-3 X3T10/2008D revision 1"; 00449 case 0x0007: return "ATA-2 X3T10/948D revision 2k"; 00450 case 0x0008: return "ATA-3 X3T10/2008D revision 0"; 00451 case 0x0009: return "ATA-2 X3T10/948D revision 3"; 00452 case 0x000a: return "ATA-3 published, ANSI X3.298-1997"; 00453 case 0x000b: return "ATA-3 X3T10/2008D revision 6"; // 1st ATA-3 revision with SMART 00454 case 0x000c: return "ATA-3 X3T13/2008D revision 7 and 7a"; 00455 case 0x000d: return "ATA/ATAPI-4 X3T13/1153D revision 6"; 00456 case 0x000e: return "ATA/ATAPI-4 T13/1153D revision 13"; 00457 case 0x000f: return "ATA/ATAPI-4 X3T13/1153D revision 7"; 00458 case 0x0010: return "ATA/ATAPI-4 T13/1153D revision 18"; 00459 case 0x0011: return "ATA/ATAPI-4 T13/1153D revision 15"; 00460 case 0x0012: return "ATA/ATAPI-4 published, ANSI NCITS 317-1998"; 00461 case 0x0013: return "ATA/ATAPI-5 T13/1321D revision 3"; 00462 case 0x0014: return "ATA/ATAPI-4 T13/1153D revision 14"; 00463 case 0x0015: return "ATA/ATAPI-5 T13/1321D revision 1"; 00464 case 0x0016: return "ATA/ATAPI-5 published, ANSI NCITS 340-2000"; 00465 case 0x0017: return "ATA/ATAPI-4 T13/1153D revision 17"; 00466 case 0x0018: return "ATA/ATAPI-6 T13/1410D revision 0"; 00467 case 0x0019: return "ATA/ATAPI-6 T13/1410D revision 3a"; 00468 case 0x001a: return "ATA/ATAPI-7 T13/1532D revision 1"; 00469 case 0x001b: return "ATA/ATAPI-6 T13/1410D revision 2"; 00470 case 0x001c: return "ATA/ATAPI-6 T13/1410D revision 1"; 00471 case 0x001d: return "ATA/ATAPI-7 published, ANSI INCITS 397-2005"; 00472 case 0x001e: return "ATA/ATAPI-7 T13/1532D revision 0"; 00473 case 0x001f: return "ACS-3 T13/2161-D revision 3b"; 00474 00475 case 0x0021: return "ATA/ATAPI-7 T13/1532D revision 4a"; 00476 case 0x0022: return "ATA/ATAPI-6 published, ANSI INCITS 361-2002"; 00477 00478 case 0x0027: return "ATA8-ACS T13/1699-D revision 3c"; 00479 case 0x0028: return "ATA8-ACS T13/1699-D revision 6"; 00480 case 0x0029: return "ATA8-ACS T13/1699-D revision 4"; 00481 00482 case 0x0031: return "ACS-2 T13/2015-D revision 2"; 00483 00484 case 0x0033: return "ATA8-ACS T13/1699-D revision 3e"; 00485 00486 case 0x0039: return "ATA8-ACS T13/1699-D revision 4c"; 00487 00488 case 0x0042: return "ATA8-ACS T13/1699-D revision 3f"; 00489 00490 case 0x0052: return "ATA8-ACS T13/1699-D revision 3b"; 00491 00492 case 0x0107: return "ATA8-ACS T13/1699-D revision 2d"; 00493 00494 case 0x0110: return "ACS-2 T13/2015-D revision 3"; 00495 00496 default: return 0; 00497 } 00498 } 00499 00500 static const char * get_sata_version(const ata_identify_device * drive) 00501 { 00502 unsigned short word222 = drive->words088_255[222-88]; 00503 if ((word222 & 0xf000) != 0x1000) 00504 return 0; 00505 switch (find_msb(word222 & 0x0fff)) { 00506 default: return "SATA >3.1"; 00507 case 6: return "SATA 3.1"; 00508 case 5: return "SATA 3.0"; 00509 case 4: return "SATA 2.6"; 00510 case 3: return "SATA 2.5"; 00511 case 2: return "SATA II Ext"; 00512 case 1: return "SATA 1.0a"; 00513 case 0: return "ATA8-AST"; 00514 case -1: return 0; 00515 } 00516 } 00517 00518 static const char * get_sata_speed(int level) 00519 { 00520 if (level <= 0) 00521 return 0; 00522 switch (level) { 00523 default: return ">6.0 Gb/s"; 00524 case 3: return "6.0 Gb/s"; 00525 case 2: return "3.0 Gb/s"; 00526 case 1: return "1.5 Gb/s"; 00527 } 00528 } 00529 00530 static const char * get_sata_maxspeed(const ata_identify_device * drive) 00531 { 00532 unsigned short word076 = drive->words047_079[76-47]; 00533 if (word076 & 0x0001) 00534 return 0; 00535 return get_sata_speed(find_msb(word076 & 0x00fe)); 00536 } 00537 00538 static const char * get_sata_curspeed(const ata_identify_device * drive) 00539 { 00540 unsigned short word077 = drive->words047_079[77-47]; 00541 if (word077 & 0x0001) 00542 return 0; 00543 return get_sata_speed((word077 >> 1) & 0x7); 00544 } 00545 00546 00547 static void print_drive_info(const ata_identify_device * drive, 00548 const ata_size_info & sizes, int rpm, 00549 const drive_settings * dbentry) 00550 { 00551 // format drive information (with byte swapping as needed) 00552 char model[40+1], serial[20+1], firmware[8+1]; 00553 ata_format_id_string(model, drive->model, sizeof(model)-1); 00554 ata_format_id_string(serial, drive->serial_no, sizeof(serial)-1); 00555 ata_format_id_string(firmware, drive->fw_rev, sizeof(firmware)-1); 00556 00557 // Print model family if known 00558 if (dbentry && *dbentry->modelfamily) 00559 pout("Model Family: %s\n", dbentry->modelfamily); 00560 00561 pout("Device Model: %s\n", infofound(model)); 00562 if (!dont_print_serial_number) { 00563 pout("Serial Number: %s\n", infofound(serial)); 00564 00565 unsigned oui = 0; uint64_t unique_id = 0; 00566 int naa = ata_get_wwn(drive, oui, unique_id); 00567 if (naa >= 0) 00568 pout("LU WWN Device Id: %x %06x %09"PRIx64"\n", naa, oui, unique_id); 00569 00570 // Additional Product Identifier (OEM Id) string in words 170-173 00571 // (e08130r1, added in ACS-2 Revision 1, December 17, 2008) 00572 if (0x2020 <= drive->words088_255[170-88] && drive->words088_255[170-88] <= 0x7e7e) { 00573 char add[8+1]; 00574 ata_format_id_string(add, (const unsigned char *)(drive->words088_255+170-88), sizeof(add)-1); 00575 if (add[0]) 00576 pout("Add. Product Id: %s\n", add); 00577 } 00578 } 00579 pout("Firmware Version: %s\n", infofound(firmware)); 00580 00581 if (sizes.capacity) { 00582 // Print capacity 00583 char num[64], cap[32]; 00584 pout("User Capacity: %s bytes [%s]\n", 00585 format_with_thousands_sep(num, sizeof(num), sizes.capacity), 00586 format_capacity(cap, sizeof(cap), sizes.capacity)); 00587 00588 // Print sector sizes. 00589 if (sizes.phy_sector_size == sizes.log_sector_size) 00590 pout("Sector Size: %u bytes logical/physical\n", sizes.log_sector_size); 00591 else { 00592 pout("Sector Sizes: %u bytes logical, %u bytes physical", 00593 sizes.log_sector_size, sizes.phy_sector_size); 00594 if (sizes.log_sector_offset) 00595 pout(" (offset %u bytes)", sizes.log_sector_offset); 00596 pout("\n"); 00597 } 00598 } 00599 00600 // Print nominal media rotation rate if reported 00601 if (rpm) { 00602 if (rpm == 1) 00603 pout("Rotation Rate: Solid State Device\n"); 00604 else if (rpm > 1) 00605 pout("Rotation Rate: %d rpm\n", rpm); 00606 else 00607 pout("Rotation Rate: Unknown (0x%04x)\n", -rpm); 00608 } 00609 00610 // See if drive is recognized 00611 pout("Device is: %s\n", !dbentry ? 00612 "Not in smartctl database [for details use: -P showall]": 00613 "In smartctl database [for details use: -P show]"); 00614 00615 // Print ATA version 00616 std::string ataver; 00617 if ( (drive->major_rev_num != 0x0000 && drive->major_rev_num != 0xffff) 00618 || (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff)) { 00619 const char * majorver = get_ata_major_version(drive); 00620 const char * minorver = get_ata_minor_version(drive); 00621 00622 if (majorver && minorver && str_starts_with(minorver, majorver)) { 00623 // Major and minor strings match, print minor string only 00624 ataver = minorver; 00625 } 00626 else { 00627 if (majorver) 00628 ataver = majorver; 00629 else 00630 ataver = strprintf("Unknown(0x%04x)", drive->major_rev_num); 00631 00632 if (minorver) 00633 ataver += strprintf(", %s", minorver); 00634 else if (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff) 00635 ataver += strprintf(" (unknown minor revision code: 0x%04x)", drive->minor_rev_num); 00636 else 00637 ataver += " (minor revision not indicated)"; 00638 } 00639 } 00640 pout("ATA Version is: %s\n", infofound(ataver.c_str())); 00641 00642 // If SATA drive print SATA version and speed 00643 const char * sataver = get_sata_version(drive); 00644 if (sataver) { 00645 const char * maxspeed = get_sata_maxspeed(drive); 00646 const char * curspeed = get_sata_curspeed(drive); 00647 pout("SATA Version is: %s%s%s%s%s%s\n", sataver, 00648 (maxspeed ? ", " : ""), (maxspeed ? maxspeed : ""), 00649 (curspeed ? " (current: " : ""), (curspeed ? curspeed : ""), 00650 (curspeed ? ")" : "")); 00651 } 00652 00653 // print current time and date and timezone 00654 char timedatetz[DATEANDEPOCHLEN]; dateandtimezone(timedatetz); 00655 pout("Local Time is: %s\n", timedatetz); 00656 00657 // Print warning message, if there is one 00658 if (dbentry && *dbentry->warningmsg) 00659 pout("\n==> WARNING: %s\n\n", dbentry->warningmsg); 00660 } 00661 00662 static const char *OfflineDataCollectionStatus(unsigned char status_byte) 00663 { 00664 unsigned char stat=status_byte & 0x7f; 00665 00666 switch(stat){ 00667 case 0x00: 00668 return "was never started"; 00669 case 0x02: 00670 return "was completed without error"; 00671 case 0x03: 00672 if (status_byte == 0x03) 00673 return "is in progress"; 00674 else 00675 return "is in a Reserved state"; 00676 case 0x04: 00677 return "was suspended by an interrupting command from host"; 00678 case 0x05: 00679 return "was aborted by an interrupting command from host"; 00680 case 0x06: 00681 return "was aborted by the device with a fatal error"; 00682 default: 00683 if (stat >= 0x40) 00684 return "is in a Vendor Specific state"; 00685 else 00686 return "is in a Reserved state"; 00687 } 00688 } 00689 00690 00691 // prints verbose value Off-line data collection status byte 00692 static void PrintSmartOfflineStatus(const ata_smart_values * data) 00693 { 00694 pout("Offline data collection status: (0x%02x)\t", 00695 (int)data->offline_data_collection_status); 00696 00697 // Off-line data collection status byte is not a reserved 00698 // or vendor specific value 00699 pout("Offline data collection activity\n" 00700 "\t\t\t\t\t%s.\n", OfflineDataCollectionStatus(data->offline_data_collection_status)); 00701 00702 // Report on Automatic Data Collection Status. Only IBM documents 00703 // this bit. See SFF 8035i Revision 2 for details. 00704 if (data->offline_data_collection_status & 0x80) 00705 pout("\t\t\t\t\tAuto Offline Data Collection: Enabled.\n"); 00706 else 00707 pout("\t\t\t\t\tAuto Offline Data Collection: Disabled.\n"); 00708 00709 return; 00710 } 00711 00712 static void PrintSmartSelfExecStatus(const ata_smart_values * data, 00713 firmwarebug_defs firmwarebugs) 00714 { 00715 pout("Self-test execution status: "); 00716 00717 switch (data->self_test_exec_status >> 4) 00718 { 00719 case 0: 00720 pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", 00721 (int)data->self_test_exec_status); 00722 pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n"); 00723 break; 00724 case 1: 00725 pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", 00726 (int)data->self_test_exec_status); 00727 pout("the host.\n"); 00728 break; 00729 case 2: 00730 pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", 00731 (int)data->self_test_exec_status); 00732 pout("by the host with a hard or soft reset.\n"); 00733 break; 00734 case 3: 00735 pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", 00736 (int)data->self_test_exec_status); 00737 pout("occurred while the device was executing\n\t\t\t\t\t"); 00738 pout("its self-test routine and the device \n\t\t\t\t\t"); 00739 pout("was unable to complete the self-test \n\t\t\t\t\t"); 00740 pout("routine.\n"); 00741 break; 00742 case 4: 00743 pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", 00744 (int)data->self_test_exec_status); 00745 pout("a test element that failed and the test\n\t\t\t\t\t"); 00746 pout("element that failed is not known.\n"); 00747 break; 00748 case 5: 00749 pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", 00750 (int)data->self_test_exec_status); 00751 pout("the electrical element of the test\n\t\t\t\t\t"); 00752 pout("failed.\n"); 00753 break; 00754 case 6: 00755 pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", 00756 (int)data->self_test_exec_status); 00757 pout("the servo (and/or seek) element of the \n\t\t\t\t\t"); 00758 pout("test failed.\n"); 00759 break; 00760 case 7: 00761 pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", 00762 (int)data->self_test_exec_status); 00763 pout("the read element of the test failed.\n"); 00764 break; 00765 case 8: 00766 pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", 00767 (int)data->self_test_exec_status); 00768 pout("a test element that failed and the\n\t\t\t\t\t"); 00769 pout("device is suspected of having handling\n\t\t\t\t\t"); 00770 pout("damage.\n"); 00771 break; 00772 case 15: 00773 if (firmwarebugs.is_set(BUG_SAMSUNG3) && data->self_test_exec_status == 0xf0) { 00774 pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", 00775 (int)data->self_test_exec_status); 00776 pout("with unknown result or self-test in\n\t\t\t\t\t"); 00777 pout("progress with less than 10%% remaining.\n"); 00778 } 00779 else { 00780 pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", 00781 (int)data->self_test_exec_status); 00782 pout("%1d0%% of test remaining.\n", 00783 (int)(data->self_test_exec_status & 0x0f)); 00784 } 00785 break; 00786 default: 00787 pout("(%4d)\tReserved.\n", 00788 (int)data->self_test_exec_status); 00789 break; 00790 } 00791 00792 } 00793 00794 static void PrintSmartTotalTimeCompleteOffline (const ata_smart_values * data) 00795 { 00796 pout("Total time to complete Offline \n"); 00797 pout("data collection: \t\t(%5d) seconds.\n", 00798 (int)data->total_time_to_complete_off_line); 00799 } 00800 00801 static void PrintSmartOfflineCollectCap(const ata_smart_values *data) 00802 { 00803 pout("Offline data collection\n"); 00804 pout("capabilities: \t\t\t (0x%02x) ", 00805 (int)data->offline_data_collection_capability); 00806 00807 if (data->offline_data_collection_capability == 0x00){ 00808 pout("\tOffline data collection not supported.\n"); 00809 } 00810 else { 00811 pout( "%s\n", isSupportExecuteOfflineImmediate(data)? 00812 "SMART execute Offline immediate." : 00813 "No SMART execute Offline immediate."); 00814 00815 pout( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)? 00816 "Auto Offline data collection on/off support.": 00817 "No Auto Offline data collection support."); 00818 00819 pout( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data)? 00820 "Abort Offline collection upon new\n\t\t\t\t\tcommand.": 00821 "Suspend Offline collection upon new\n\t\t\t\t\tcommand."); 00822 00823 pout( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)? 00824 "Offline surface scan supported.": 00825 "No Offline surface scan supported."); 00826 00827 pout( "\t\t\t\t\t%s\n", isSupportSelfTest(data)? 00828 "Self-test supported.": 00829 "No Self-test supported."); 00830 00831 pout( "\t\t\t\t\t%s\n", isSupportConveyanceSelfTest(data)? 00832 "Conveyance Self-test supported.": 00833 "No Conveyance Self-test supported."); 00834 00835 pout( "\t\t\t\t\t%s\n", isSupportSelectiveSelfTest(data)? 00836 "Selective Self-test supported.": 00837 "No Selective Self-test supported."); 00838 } 00839 } 00840 00841 static void PrintSmartCapability(const ata_smart_values *data) 00842 { 00843 pout("SMART capabilities: "); 00844 pout("(0x%04x)\t", (int)data->smart_capability); 00845 00846 if (data->smart_capability == 0x00) 00847 { 00848 pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n"); 00849 } 00850 else 00851 { 00852 00853 pout( "%s\n", (data->smart_capability & 0x01)? 00854 "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.": 00855 "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode."); 00856 00857 if ( data->smart_capability & 0x02 ) 00858 { 00859 pout("\t\t\t\t\tSupports SMART auto save timer.\n"); 00860 } 00861 } 00862 } 00863 00864 static void PrintSmartErrorLogCapability(const ata_smart_values * data, const ata_identify_device * identity) 00865 { 00866 pout("Error logging capability: "); 00867 00868 if ( isSmartErrorLogCapable(data, identity) ) 00869 { 00870 pout(" (0x%02x)\tError logging supported.\n", 00871 (int)data->errorlog_capability); 00872 } 00873 else { 00874 pout(" (0x%02x)\tError logging NOT supported.\n", 00875 (int)data->errorlog_capability); 00876 } 00877 } 00878 00879 static void PrintSmartShortSelfTestPollingTime(const ata_smart_values * data) 00880 { 00881 pout("Short self-test routine \n"); 00882 if (isSupportSelfTest(data)) 00883 pout("recommended polling time: \t (%4d) minutes.\n", 00884 (int)data->short_test_completion_time); 00885 else 00886 pout("recommended polling time: \t Not Supported.\n"); 00887 } 00888 00889 static void PrintSmartExtendedSelfTestPollingTime(const ata_smart_values * data) 00890 { 00891 pout("Extended self-test routine\n"); 00892 if (isSupportSelfTest(data)) 00893 pout("recommended polling time: \t (%4d) minutes.\n", 00894 TestTime(data, EXTEND_SELF_TEST)); 00895 else 00896 pout("recommended polling time: \t Not Supported.\n"); 00897 } 00898 00899 static void PrintSmartConveyanceSelfTestPollingTime(const ata_smart_values * data) 00900 { 00901 pout("Conveyance self-test routine\n"); 00902 if (isSupportConveyanceSelfTest(data)) 00903 pout("recommended polling time: \t (%4d) minutes.\n", 00904 (int)data->conveyance_test_completion_time); 00905 else 00906 pout("recommended polling time: \t Not Supported.\n"); 00907 } 00908 00909 // Check SMART attribute table for Threshold failure 00910 // onlyfailed=0: are or were any age or prefailure attributes <= threshold 00911 // onlyfailed=1: are any prefailure attributes <= threshold now 00912 static int find_failed_attr(const ata_smart_values * data, 00913 const ata_smart_thresholds_pvt * thresholds, 00914 const ata_vendor_attr_defs & defs, int onlyfailed) 00915 { 00916 for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { 00917 const ata_smart_attribute & attr = data->vendor_attributes[i]; 00918 00919 ata_attr_state state = ata_get_attr_state(attr, i, thresholds->thres_entries, defs); 00920 00921 if (!onlyfailed) { 00922 if (state >= ATTRSTATE_FAILED_PAST) 00923 return attr.id; 00924 } 00925 else { 00926 if (state == ATTRSTATE_FAILED_NOW && ATTRIBUTE_FLAGS_PREFAILURE(attr.flags)) 00927 return attr.id; 00928 } 00929 } 00930 return 0; 00931 } 00932 00933 // onlyfailed=0 : print all attribute values 00934 // onlyfailed=1: just ones that are currently failed and have prefailure bit set 00935 // onlyfailed=2: ones that are failed, or have failed with or without prefailure bit set 00936 static void PrintSmartAttribWithThres(const ata_smart_values * data, 00937 const ata_smart_thresholds_pvt * thresholds, 00938 const ata_vendor_attr_defs & defs, int rpm, 00939 int onlyfailed, unsigned char format) 00940 { 00941 bool brief = !!(format & ata_print_options::FMT_BRIEF); 00942 bool hexid = !!(format & ata_print_options::FMT_HEX_ID); 00943 bool hexval = !!(format & ata_print_options::FMT_HEX_VAL); 00944 bool needheader = true; 00945 00946 // step through all vendor attributes 00947 for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { 00948 const ata_smart_attribute & attr = data->vendor_attributes[i]; 00949 00950 // Check attribute and threshold 00951 unsigned char threshold = 0; 00952 ata_attr_state state = ata_get_attr_state(attr, i, thresholds->thres_entries, defs, &threshold); 00953 if (state == ATTRSTATE_NON_EXISTING) 00954 continue; 00955 00956 // These break out of the loop if we are only printing certain entries... 00957 if (onlyfailed == 1 && !(ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) && state == ATTRSTATE_FAILED_NOW)) 00958 continue; 00959 00960 if (onlyfailed == 2 && state < ATTRSTATE_FAILED_PAST) 00961 continue; 00962 00963 // print header only if needed 00964 if (needheader) { 00965 if (!onlyfailed) { 00966 pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber); 00967 pout("Vendor Specific SMART Attributes with Thresholds:\n"); 00968 } 00969 if (!brief) 00970 pout("ID#%s ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n", 00971 (!hexid ? "" : " ")); 00972 else 00973 pout("ID#%s ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE\n", 00974 (!hexid ? "" : " ")); 00975 needheader = false; 00976 } 00977 00978 // Format value, worst, threshold 00979 std::string valstr, worstr, threstr; 00980 if (state > ATTRSTATE_NO_NORMVAL) 00981 valstr = (!hexval ? strprintf("%.3d", attr.current) 00982 : strprintf("0x%02x", attr.current)); 00983 else 00984 valstr = (!hexval ? "---" : "----"); 00985 if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL)) 00986 worstr = (!hexval ? strprintf("%.3d", attr.worst) 00987 : strprintf("0x%02x", attr.worst)); 00988 else 00989 worstr = (!hexval ? "---" : "----"); 00990 if (state > ATTRSTATE_NO_THRESHOLD) 00991 threstr = (!hexval ? strprintf("%.3d", threshold) 00992 : strprintf("0x%02x", threshold)); 00993 else 00994 threstr = (!hexval ? "---" : "----"); 00995 00996 // Print line for each valid attribute 00997 std::string idstr = (!hexid ? strprintf("%3d", attr.id) 00998 : strprintf("0x%02x", attr.id)); 00999 std::string attrname = ata_get_smart_attr_name(attr.id, defs, rpm); 01000 std::string rawstr = ata_format_attr_raw_value(attr, defs); 01001 01002 if (!brief) 01003 pout("%s %-24s0x%04x %-4s %-4s %-4s %-10s%-9s%-12s%s\n", 01004 idstr.c_str(), attrname.c_str(), attr.flags, 01005 valstr.c_str(), worstr.c_str(), threstr.c_str(), 01006 (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) ? "Pre-fail" : "Old_age"), 01007 (ATTRIBUTE_FLAGS_ONLINE(attr.flags) ? "Always" : "Offline"), 01008 (state == ATTRSTATE_FAILED_NOW ? "FAILING_NOW" : 01009 state == ATTRSTATE_FAILED_PAST ? "In_the_past" 01010 : " -" ) , 01011 rawstr.c_str()); 01012 else 01013 pout("%s %-24s%c%c%c%c%c%c%c %-4s %-4s %-4s %-5s%s\n", 01014 idstr.c_str(), attrname.c_str(), 01015 (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) ? 'P' : '-'), 01016 (ATTRIBUTE_FLAGS_ONLINE(attr.flags) ? 'O' : '-'), 01017 (ATTRIBUTE_FLAGS_PERFORMANCE(attr.flags) ? 'S' : '-'), 01018 (ATTRIBUTE_FLAGS_ERRORRATE(attr.flags) ? 'R' : '-'), 01019 (ATTRIBUTE_FLAGS_EVENTCOUNT(attr.flags) ? 'C' : '-'), 01020 (ATTRIBUTE_FLAGS_SELFPRESERVING(attr.flags) ? 'K' : '-'), 01021 (ATTRIBUTE_FLAGS_OTHER(attr.flags) ? '+' : ' '), 01022 valstr.c_str(), worstr.c_str(), threstr.c_str(), 01023 (state == ATTRSTATE_FAILED_NOW ? "NOW" : 01024 state == ATTRSTATE_FAILED_PAST ? "Past" 01025 : "-" ), 01026 rawstr.c_str()); 01027 01028 } 01029 01030 if (!needheader) { 01031 if (!onlyfailed && brief) { 01032 int n = (!hexid ? 28 : 29); 01033 pout("%*s||||||_ K auto-keep\n" 01034 "%*s|||||__ C event count\n" 01035 "%*s||||___ R error rate\n" 01036 "%*s|||____ S speed/performance\n" 01037 "%*s||_____ O updated online\n" 01038 "%*s|______ P prefailure warning\n", 01039 n, "", n, "", n, "", n, "", n, "", n, ""); 01040 } 01041 pout("\n"); 01042 } 01043 } 01044 01045 // Print SMART related SCT capabilities 01046 static void ataPrintSCTCapability(const ata_identify_device *drive) 01047 { 01048 unsigned short sctcaps = drive->words088_255[206-88]; 01049 if (!(sctcaps & 0x01)) 01050 return; 01051 pout("SCT capabilities: \t (0x%04x)\tSCT Status supported.\n", sctcaps); 01052 if (sctcaps & 0x08) 01053 pout("\t\t\t\t\tSCT Error Recovery Control supported.\n"); 01054 if (sctcaps & 0x10) 01055 pout("\t\t\t\t\tSCT Feature Control supported.\n"); 01056 if (sctcaps & 0x20) 01057 pout("\t\t\t\t\tSCT Data Table supported.\n"); 01058 } 01059 01060 01061 static void PrintGeneralSmartValues(const ata_smart_values *data, const ata_identify_device *drive, 01062 firmwarebug_defs firmwarebugs) 01063 { 01064 pout("General SMART Values:\n"); 01065 01066 PrintSmartOfflineStatus(data); 01067 01068 if (isSupportSelfTest(data)){ 01069 PrintSmartSelfExecStatus(data, firmwarebugs); 01070 } 01071 01072 PrintSmartTotalTimeCompleteOffline(data); 01073 PrintSmartOfflineCollectCap(data); 01074 PrintSmartCapability(data); 01075 01076 PrintSmartErrorLogCapability(data, drive); 01077 01078 pout( "\t\t\t\t\t%s\n", isGeneralPurposeLoggingCapable(drive)? 01079 "General Purpose Logging supported.": 01080 "No General Purpose Logging support."); 01081 01082 if (isSupportSelfTest(data)){ 01083 PrintSmartShortSelfTestPollingTime (data); 01084 PrintSmartExtendedSelfTestPollingTime (data); 01085 } 01086 if (isSupportConveyanceSelfTest(data)) 01087 PrintSmartConveyanceSelfTestPollingTime (data); 01088 01089 ataPrintSCTCapability(drive); 01090 01091 pout("\n"); 01092 } 01093 01094 // Get # sectors of a log addr, 0 if log does not exist. 01095 static unsigned GetNumLogSectors(const ata_smart_log_directory * logdir, unsigned logaddr, bool gpl) 01096 { 01097 if (!logdir) 01098 return 0; 01099 if (logaddr > 0xff) 01100 return 0; 01101 if (logaddr == 0) 01102 return 1; 01103 unsigned n = logdir->entry[logaddr-1].numsectors; 01104 if (gpl) 01105 // GP logs may have >255 sectors 01106 n |= logdir->entry[logaddr-1].reserved << 8; 01107 return n; 01108 } 01109 01110 // Get name of log. 01111 // Table A.2 of T13/2161-D (ACS-3) Revision 4, September 4, 2012 01112 static const char * GetLogName(unsigned logaddr) 01113 { 01114 switch (logaddr) { 01115 case 0x00: return "Log Directory"; 01116 case 0x01: return "Summary SMART error log"; 01117 case 0x02: return "Comprehensive SMART error log"; 01118 case 0x03: return "Ext. Comprehensive SMART error log"; 01119 case 0x04: return "Device Statistics log"; 01120 case 0x05: return "Reserved for CFA"; // ACS-2 01121 case 0x06: return "SMART self-test log"; 01122 case 0x07: return "Extended self-test log"; 01123 case 0x08: return "Power Conditions log"; // ACS-2 01124 case 0x09: return "Selective self-test log"; 01125 case 0x0a: return "Device Statistics Notification"; // ACS-3 01126 case 0x0b: return "Reserved for CFA"; // ACS-3 01127 01128 case 0x0d: return "LPS Mis-alignment log"; // ACS-2 01129 01130 case 0x10: return "NCQ Command Error log"; 01131 case 0x11: return "SATA Phy Event Counters"; 01132 case 0x12: return "SATA NCQ Queue Management log"; // ACS-3 01133 case 0x13: return "SATA NCQ Send and Receive log"; // ACS-3 01134 case 0x14: 01135 case 0x15: 01136 case 0x16: return "Reserved for Serial ATA"; 01137 01138 case 0x19: return "LBA Status log"; // ACS-3 01139 01140 case 0x20: return "Streaming performance log [OBS-8]"; 01141 case 0x21: return "Write stream error log"; 01142 case 0x22: return "Read stream error log"; 01143 case 0x23: return "Delayed sector log [OBS-8]"; 01144 case 0x24: return "Current Device Internal Status Data log"; // ACS-3 01145 case 0x25: return "Saved Device Internal Status Data log"; // ACS-3 01146 01147 case 0x30: return "IDENTIFY DEVICE data log"; // ACS-3 01148 01149 case 0xe0: return "SCT Command/Status"; 01150 case 0xe1: return "SCT Data Transfer"; 01151 default: 01152 if (0xa0 <= logaddr && logaddr <= 0xdf) 01153 return "Device vendor specific log"; 01154 if (0x80 <= logaddr && logaddr <= 0x9f) 01155 return "Host vendor specific log"; 01156 return "Reserved"; 01157 } 01158 /*NOTREACHED*/ 01159 } 01160 01161 // Get log access permissions 01162 static const char * get_log_rw(unsigned logaddr) 01163 { 01164 if ( ( logaddr <= 0x08) 01165 || (0x0d == logaddr) 01166 || (0x10 <= logaddr && logaddr <= 0x13) 01167 || (0x19 == logaddr) 01168 || (0x20 <= logaddr && logaddr <= 0x25) 01169 || (0x30 == logaddr)) 01170 return "R/O"; 01171 01172 if ( (0x09 <= logaddr && logaddr <= 0x0a) 01173 || (0x80 <= logaddr && logaddr <= 0x9f) 01174 || (0xe0 <= logaddr && logaddr <= 0xe1)) 01175 return "R/W"; 01176 01177 if (0xa0 <= logaddr && logaddr <= 0xdf) 01178 return "VS"; // Vendor specific 01179 01180 return "-"; // Unknown/Reserved 01181 } 01182 01183 // Init a fake log directory, assume that standard logs are supported 01184 const ata_smart_log_directory * fake_logdir(ata_smart_log_directory * logdir, 01185 const ata_print_options & options) 01186 { 01187 memset(logdir, 0, sizeof(*logdir)); 01188 logdir->logversion = 255; 01189 logdir->entry[0x01-1].numsectors = 1; 01190 logdir->entry[0x03-1].numsectors = (options.smart_ext_error_log + (4-1)) / 4; 01191 logdir->entry[0x04-1].numsectors = 8; 01192 logdir->entry[0x06-1].numsectors = 1; 01193 logdir->entry[0x07-1].numsectors = (options.smart_ext_selftest_log + (19-1)) / 19; 01194 logdir->entry[0x09-1].numsectors = 1; 01195 logdir->entry[0x11-1].numsectors = 1; 01196 return logdir; 01197 } 01198 01199 // Print SMART and/or GP Log Directory 01200 static void PrintLogDirectories(const ata_smart_log_directory * gplogdir, 01201 const ata_smart_log_directory * smartlogdir) 01202 { 01203 if (gplogdir) 01204 pout("General Purpose Log Directory Version %u\n", gplogdir->logversion); 01205 if (smartlogdir) 01206 pout("SMART %sLog Directory Version %u%s\n", 01207 (gplogdir ? " " : ""), smartlogdir->logversion, 01208 (smartlogdir->logversion==1 ? " [multi-sector log support]" : "")); 01209 01210 pout("Address Access R/W Size Description\n"); 01211 01212 for (unsigned i = 0; i <= 0xff; i++) { 01213 // Get number of sectors 01214 unsigned smart_numsect = GetNumLogSectors(smartlogdir, i, false); 01215 unsigned gp_numsect = GetNumLogSectors(gplogdir , i, true ); 01216 01217 if (!(smart_numsect || gp_numsect)) 01218 continue; // Log does not exist 01219 01220 const char * acc; unsigned size; 01221 if (smart_numsect == gp_numsect) { 01222 acc = "GPL,SL"; size = gp_numsect; 01223 } 01224 else if (!smart_numsect) { 01225 acc = "GPL"; size = gp_numsect; 01226 } 01227 else if (!gp_numsect) { 01228 acc = " SL"; size = smart_numsect; 01229 } 01230 else { 01231 acc = 0; size = 0; 01232 } 01233 01234 unsigned i2 = i; 01235 if (acc && ((0x80 <= i && i < 0x9f) || (0xa0 <= i && i < 0xdf))) { 01236 // Find range of Host/Device vendor specific logs with same size 01237 unsigned imax = (i < 0x9f ? 0x9f : 0xdf); 01238 for (unsigned j = i+1; j <= imax; j++) { 01239 unsigned sn = GetNumLogSectors(smartlogdir, j, false); 01240 unsigned gn = GetNumLogSectors(gplogdir , j, true ); 01241 01242 if (!(sn == smart_numsect && gn == gp_numsect)) 01243 break; 01244 i2 = j; 01245 } 01246 } 01247 01248 const char * name = GetLogName(i); 01249 const char * rw = get_log_rw(i); 01250 01251 if (i2 > i) { 01252 pout("0x%02x-0x%02x %-6s %-3s %5u %s\n", i, i2, acc, rw, size, name); 01253 i = i2; 01254 } 01255 else if (acc) 01256 pout( "0x%02x %-6s %-3s %5u %s\n", i, acc, rw, size, name); 01257 else { 01258 // GPL and SL support different sizes 01259 pout( "0x%02x %-6s %-3s %5u %s\n", i, "GPL", rw, gp_numsect, name); 01260 pout( "0x%02x %-6s %-3s %5u %s\n", i, "SL", rw, smart_numsect, name); 01261 } 01262 } 01263 pout("\n"); 01264 } 01265 01266 // Print hexdump of log pages. 01267 // Format is compatible with 'xxd -r'. 01268 static void PrintLogPages(const char * type, const unsigned char * data, 01269 unsigned char logaddr, unsigned page, 01270 unsigned num_pages, unsigned max_pages) 01271 { 01272 pout("%s Log 0x%02x [%s], Page %u-%u (of %u)\n", 01273 type, logaddr, GetLogName(logaddr), page, page+num_pages-1, max_pages); 01274 for (unsigned i = 0; i < num_pages * 512; i += 16) { 01275 const unsigned char * p = data+i; 01276 pout("%07x: %02x %02x %02x %02x %02x %02x %02x %02x " 01277 "%02x %02x %02x %02x %02x %02x %02x %02x ", 01278 (page * 512) + i, 01279 p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7], 01280 p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15]); 01281 #define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.') 01282 pout("|%c%c%c%c%c%c%c%c" 01283 "%c%c%c%c%c%c%c%c|\n", 01284 P( 0), P( 1), P( 2), P( 3), P( 4), P( 5), P( 6), P( 7), 01285 P( 8), P( 9), P(10), P(11), P(12), P(13), P(14), P(15)); 01286 #undef P 01287 if ((i & 0x1ff) == 0x1f0) 01288 pout("\n"); 01289 } 01290 } 01291 01292 /////////////////////////////////////////////////////////////////////// 01293 // Device statistics (Log 0x04) 01294 01295 // See Section A.5 of 01296 // ATA/ATAPI Command Set - 3 (ACS-3) 01297 // T13/2161-D Revision 2, February 21, 2012. 01298 01299 struct devstat_entry_info 01300 { 01301 short size; // #bytes of value, -1 for signed char 01302 const char * name; 01303 }; 01304 01305 const devstat_entry_info devstat_info_0x00[] = { 01306 { 2, "List of supported log pages" }, 01307 { 0, 0 } 01308 }; 01309 01310 const devstat_entry_info devstat_info_0x01[] = { 01311 { 2, "General Statistics" }, 01312 { 4, "Lifetime Power-On Resets" }, 01313 { 4, "Power-on Hours" }, // spec says no flags(?) 01314 { 6, "Logical Sectors Written" }, 01315 { 6, "Number of Write Commands" }, 01316 { 6, "Logical Sectors Read" }, 01317 { 6, "Number of Read Commands" }, 01318 { 6, "Date and Time TimeStamp" }, // ACS-3 01319 { 0, 0 } 01320 }; 01321 01322 const devstat_entry_info devstat_info_0x02[] = { 01323 { 2, "Free-Fall Statistics" }, 01324 { 4, "Number of Free-Fall Events Detected" }, 01325 { 4, "Overlimit Shock Events" }, 01326 { 0, 0 } 01327 }; 01328 01329 const devstat_entry_info devstat_info_0x03[] = { 01330 { 2, "Rotating Media Statistics" }, 01331 { 4, "Spindle Motor Power-on Hours" }, 01332 { 4, "Head Flying Hours" }, 01333 { 4, "Head Load Events" }, 01334 { 4, "Number of Reallocated Logical Sectors" }, 01335 { 4, "Read Recovery Attempts" }, 01336 { 4, "Number of Mechanical Start Failures" }, 01337 { 4, "Number of Realloc. Candidate Logical Sectors" }, // ACS-3 01338 { 0, 0 } 01339 }; 01340 01341 const devstat_entry_info devstat_info_0x04[] = { 01342 { 2, "General Errors Statistics" }, 01343 { 4, "Number of Reported Uncorrectable Errors" }, 01344 //{ 4, "Number of Resets Between Command Acceptance and Command Completion" }, 01345 { 4, "Resets Between Cmd Acceptance and Completion" }, 01346 { 0, 0 } 01347 }; 01348 01349 const devstat_entry_info devstat_info_0x05[] = { 01350 { 2, "Temperature Statistics" }, 01351 { -1, "Current Temperature" }, 01352 { -1, "Average Short Term Temperature" }, 01353 { -1, "Average Long Term Temperature" }, 01354 { -1, "Highest Temperature" }, 01355 { -1, "Lowest Temperature" }, 01356 { -1, "Highest Average Short Term Temperature" }, 01357 { -1, "Lowest Average Short Term Temperature" }, 01358 { -1, "Highest Average Long Term Temperature" }, 01359 { -1, "Lowest Average Long Term Temperature" }, 01360 { 4, "Time in Over-Temperature" }, 01361 { -1, "Specified Maximum Operating Temperature" }, 01362 { 4, "Time in Under-Temperature" }, 01363 { -1, "Specified Minimum Operating Temperature" }, 01364 { 0, 0 } 01365 }; 01366 01367 const devstat_entry_info devstat_info_0x06[] = { 01368 { 2, "Transport Statistics" }, 01369 { 4, "Number of Hardware Resets" }, 01370 { 4, "Number of ASR Events" }, 01371 { 4, "Number of Interface CRC Errors" }, 01372 { 0, 0 } 01373 }; 01374 01375 const devstat_entry_info devstat_info_0x07[] = { 01376 { 2, "Solid State Device Statistics" }, 01377 { 1, "Percentage Used Endurance Indicator" }, 01378 { 0, 0 } 01379 }; 01380 01381 const devstat_entry_info * devstat_infos[] = { 01382 devstat_info_0x00, 01383 devstat_info_0x01, 01384 devstat_info_0x02, 01385 devstat_info_0x03, 01386 devstat_info_0x04, 01387 devstat_info_0x05, 01388 devstat_info_0x06, 01389 devstat_info_0x07 01390 }; 01391 01392 const int num_devstat_infos = sizeof(devstat_infos)/sizeof(devstat_infos[0]); 01393 01394 static void print_device_statistics_page(const unsigned char * data, int page, 01395 bool & need_trailer) 01396 { 01397 const devstat_entry_info * info = (page < num_devstat_infos ? devstat_infos[page] : 0); 01398 const char * name = (info ? info[0].name : "Unknown Statistics"); 01399 01400 // Check page number in header 01401 static const char line[] = " ===== = = == "; 01402 if (!data[2]) { 01403 pout("%3d%s%s (empty) ==\n", page, line, name); 01404 return; 01405 } 01406 if (data[2] != page) { 01407 pout("%3d%s%s (invalid page %d in header) ==\n", page, line, name, data[2]); 01408 return; 01409 } 01410 01411 pout("%3d%s%s (rev %d) ==\n", page, line, name, data[0]); 01412 01413 // Print entries 01414 for (int i = 1, offset = 8; offset < 512-7; i++, offset+=8) { 01415 // Check for last known entry 01416 if (info && !info[i].size) 01417 info = 0; 01418 01419 // Skip unsupported entries 01420 unsigned char flags = data[offset+7]; 01421 if (!(flags & 0x80)) 01422 continue; 01423 01424 // Get value size, default to max if unknown 01425 int size = (info ? info[i].size : 7); 01426 01427 // Format value 01428 char valstr[32]; 01429 if (flags & 0x40) { // valid flag 01430 // Get value 01431 int64_t val; 01432 if (size < 0) { 01433 val = (signed char)data[offset]; 01434 } 01435 else { 01436 val = 0; 01437 for (int j = 0; j < size; j++) 01438 val |= (int64_t)data[offset+j] << (j*8); 01439 } 01440 snprintf(valstr, sizeof(valstr), "%"PRId64, val); 01441 } 01442 else { 01443 // Value not known (yet) 01444 valstr[0] = '-'; valstr[1] = 0; 01445 } 01446 01447 pout("%3d 0x%03x %d%c %15s%c %s\n", 01448 page, offset, 01449 abs(size), 01450 (flags & 0x1f ? '+' : ' '), // unknown flags 01451 valstr, 01452 (flags & 0x20 ? '~' : ' '), // normalized flag 01453 (info ? info[i].name : "Unknown")); 01454 if (flags & 0x20) 01455 need_trailer = true; 01456 } 01457 } 01458 01459 static bool print_device_statistics(ata_device * device, unsigned nsectors, 01460 const std::vector<int> & single_pages, bool all_pages, bool ssd_page) 01461 { 01462 // Read list of supported pages from page 0 01463 unsigned char page_0[512] = {0, }; 01464 if (!ataReadLogExt(device, 0x04, 0, 0, page_0, 1)) { 01465 pout("Read Device Statistics page 0 failed\n\n"); 01466 return false; 01467 } 01468 01469 unsigned char nentries = page_0[8]; 01470 if (!(page_0[2] == 0 && nentries > 0)) { 01471 pout("Device Statistics page 0 is invalid (page=%d, nentries=%d)\n\n", page_0[2], nentries); 01472 return false; 01473 } 01474 01475 // Prepare list of pages to print 01476 std::vector<int> pages; 01477 unsigned i; 01478 if (all_pages) { 01479 // Add all supported pages 01480 for (i = 0; i < nentries; i++) { 01481 int page = page_0[8+1+i]; 01482 if (page) 01483 pages.push_back(page); 01484 } 01485 ssd_page = false; 01486 } 01487 // Add manually specified pages 01488 bool print_page_0 = false; 01489 for (i = 0; i < single_pages.size() || ssd_page; i++) { 01490 int page = (i < single_pages.size() ? single_pages[i] : 7); 01491 if (!page) 01492 print_page_0 = true; 01493 else if (page >= (int)nsectors) 01494 pout("Device Statistics Log has only %u pages\n", nsectors); 01495 else 01496 pages.push_back(page); 01497 if (page == 7) 01498 ssd_page = false; 01499 } 01500 01501 // Print list of supported pages if requested 01502 if (print_page_0) { 01503 pout("Device Statistics (GP Log 0x04) supported pages\n"); 01504 pout("Page Description\n"); 01505 for (i = 0; i < nentries; i++) { 01506 int page = page_0[8+1+i]; 01507 pout("%3d %s\n", page, 01508 (page < num_devstat_infos ? devstat_infos[page][0].name : "Unknown Statistics")); 01509 } 01510 pout("\n"); 01511 } 01512 01513 // Read & print pages 01514 if (!pages.empty()) { 01515 pout("Device Statistics (GP Log 0x04)\n"); 01516 pout("Page Offset Size Value Description\n"); 01517 bool need_trailer = false; 01518 01519 for (i = 0; i < pages.size(); i++) { 01520 int page = pages[i]; 01521 unsigned char page_n[512] = {0, }; 01522 if (!ataReadLogExt(device, 0x04, 0, page, page_n, 1)) { 01523 pout("Read Device Statistics page %d failed\n\n", page); 01524 return false; 01525 } 01526 print_device_statistics_page(page_n, page, need_trailer); 01527 } 01528 01529 if (need_trailer) 01530 pout("%30s|_ ~ normalized value\n", ""); 01531 pout("\n"); 01532 } 01533 01534 return true; 01535 } 01536 01537 01538 /////////////////////////////////////////////////////////////////////// 01539 01540 // Print log 0x11 01541 static void PrintSataPhyEventCounters(const unsigned char * data, bool reset) 01542 { 01543 if (checksum(data)) 01544 checksumwarning("SATA Phy Event Counters"); 01545 pout("SATA Phy Event Counters (GP Log 0x11)\n"); 01546 if (data[0] || data[1] || data[2] || data[3]) 01547 pout("[Reserved: 0x%02x 0x%02x 0x%02x 0x%02x]\n", 01548 data[0], data[1], data[2], data[3]); 01549 pout("ID Size Value Description\n"); 01550 01551 for (unsigned i = 4; ; ) { 01552 // Get counter id and size (bits 14:12) 01553 unsigned id = data[i] | (data[i+1] << 8); 01554 unsigned size = ((id >> 12) & 0x7) << 1; 01555 id &= 0x8fff; 01556 01557 // End of counter table ? 01558 if (!id) 01559 break; 01560 i += 2; 01561 01562 if (!(2 <= size && size <= 8 && i + size < 512)) { 01563 pout("0x%04x %u: Invalid entry\n", id, size); 01564 break; 01565 } 01566 01567 // Get value 01568 uint64_t val = 0, max_val = 0; 01569 for (unsigned j = 0; j < size; j+=2) { 01570 val |= (uint64_t)(data[i+j] | (data[i+j+1] << 8)) << (j*8); 01571 max_val |= (uint64_t)0xffffU << (j*8); 01572 } 01573 i += size; 01574 01575 // Get name 01576 const char * name; 01577 switch (id) { 01578 case 0x001: name = "Command failed due to ICRC error"; break; // Mandatory 01579 case 0x002: name = "R_ERR response for data FIS"; break; 01580 case 0x003: name = "R_ERR response for device-to-host data FIS"; break; 01581 case 0x004: name = "R_ERR response for host-to-device data FIS"; break; 01582 case 0x005: name = "R_ERR response for non-data FIS"; break; 01583 case 0x006: name = "R_ERR response for device-to-host non-data FIS"; break; 01584 case 0x007: name = "R_ERR response for host-to-device non-data FIS"; break; 01585 case 0x008: name = "Device-to-host non-data FIS retries"; break; 01586 case 0x009: name = "Transition from drive PhyRdy to drive PhyNRdy"; break; 01587 case 0x00A: name = "Device-to-host register FISes sent due to a COMRESET"; break; // Mandatory 01588 case 0x00B: name = "CRC errors within host-to-device FIS"; break; 01589 case 0x00D: name = "Non-CRC errors within host-to-device FIS"; break; 01590 case 0x00F: name = "R_ERR response for host-to-device data FIS, CRC"; break; 01591 case 0x010: name = "R_ERR response for host-to-device data FIS, non-CRC"; break; 01592 case 0x012: name = "R_ERR response for host-to-device non-data FIS, CRC"; break; 01593 case 0x013: name = "R_ERR response for host-to-device non-data FIS, non-CRC"; break; 01594 default: name = (id & 0x8000 ? "Vendor specific" : "Unknown"); break; 01595 } 01596 01597 // Counters stop at max value, add '+' in this case 01598 pout("0x%04x %u %12"PRIu64"%c %s\n", id, size, val, 01599 (val == max_val ? '+' : ' '), name); 01600 } 01601 if (reset) 01602 pout("All counters reset\n"); 01603 pout("\n"); 01604 } 01605 01606 // Format milliseconds from error log entry as "DAYS+H:M:S.MSEC" 01607 static std::string format_milliseconds(unsigned msec) 01608 { 01609 unsigned days = msec / 86400000U; 01610 msec -= days * 86400000U; 01611 unsigned hours = msec / 3600000U; 01612 msec -= hours * 3600000U; 01613 unsigned min = msec / 60000U; 01614 msec -= min * 60000U; 01615 unsigned sec = msec / 1000U; 01616 msec -= sec * 1000U; 01617 01618 std::string str; 01619 if (days) 01620 str = strprintf("%2ud+", days); 01621 str += strprintf("%02u:%02u:%02u.%03u", hours, min, sec, msec); 01622 return str; 01623 } 01624 01625 // Get description for 'state' value from SMART Error Logs 01626 static const char * get_error_log_state_desc(unsigned state) 01627 { 01628 state &= 0x0f; 01629 switch (state){ 01630 case 0x0: return "in an unknown state"; 01631 case 0x1: return "sleeping"; 01632 case 0x2: return "in standby mode"; 01633 case 0x3: return "active or idle"; 01634 case 0x4: return "doing SMART Offline or Self-test"; 01635 default: 01636 return (state < 0xb ? "in a reserved state" 01637 : "in a vendor specific state"); 01638 } 01639 } 01640 01641 // returns number of errors 01642 static int PrintSmartErrorlog(const ata_smart_errorlog *data, 01643 firmwarebug_defs firmwarebugs) 01644 { 01645 pout("SMART Error Log Version: %d\n", (int)data->revnumber); 01646 01647 // if no errors logged, return 01648 if (!data->error_log_pointer){ 01649 pout("No Errors Logged\n\n"); 01650 return 0; 01651 } 01652 print_on(); 01653 // If log pointer out of range, return 01654 if (data->error_log_pointer>5){ 01655 pout("Invalid Error Log index = 0x%02x (T13/1321D rev 1c " 01656 "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n", 01657 (int)data->error_log_pointer); 01658 return 0; 01659 } 01660 01661 // Some internal consistency checking of the data structures 01662 if ((data->ata_error_count-data->error_log_pointer) % 5 && !firmwarebugs.is_set(BUG_SAMSUNG2)) { 01663 pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n", 01664 data->ata_error_count,data->error_log_pointer); 01665 } 01666 01667 // starting printing error log info 01668 if (data->ata_error_count<=5) 01669 pout( "ATA Error Count: %d\n", (int)data->ata_error_count); 01670 else 01671 pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n", 01672 (int)data->ata_error_count); 01673 print_off(); 01674 pout("\tCR = Command Register [HEX]\n" 01675 "\tFR = Features Register [HEX]\n" 01676 "\tSC = Sector Count Register [HEX]\n" 01677 "\tSN = Sector Number Register [HEX]\n" 01678 "\tCL = Cylinder Low Register [HEX]\n" 01679 "\tCH = Cylinder High Register [HEX]\n" 01680 "\tDH = Device/Head Register [HEX]\n" 01681 "\tDC = Device Command Register [HEX]\n" 01682 "\tER = Error register [HEX]\n" 01683 "\tST = Status register [HEX]\n" 01684 "Powered_Up_Time is measured from power on, and printed as\n" 01685 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n" 01686 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n"); 01687 01688 // now step through the five error log data structures (table 39 of spec) 01689 for (int k = 4; k >= 0; k-- ) { 01690 01691 // The error log data structure entries are a circular buffer 01692 int j, i=(data->error_log_pointer+k)%5; 01693 const ata_smart_errorlog_struct * elog = data->errorlog_struct+i; 01694 const ata_smart_errorlog_error_struct * summary = &(elog->error_struct); 01695 01696 // Spec says: unused error log structures shall be zero filled 01697 if (nonempty(elog, sizeof(*elog))){ 01698 // Table 57 of T13/1532D Volume 1 Revision 3 01699 const char *msgstate = get_error_log_state_desc(summary->state); 01700 int days = (int)summary->timestamp/24; 01701 01702 // See table 42 of ATA5 spec 01703 print_on(); 01704 pout("Error %d occurred at disk power-on lifetime: %d hours (%d days + %d hours)\n", 01705 (int)(data->ata_error_count+k-4), (int)summary->timestamp, days, (int)(summary->timestamp-24*days)); 01706 print_off(); 01707 pout(" When the command that caused the error occurred, the device was %s.\n\n",msgstate); 01708 pout(" After command completion occurred, registers were:\n" 01709 " ER ST SC SN CL CH DH\n" 01710 " -- -- -- -- -- -- --\n" 01711 " %02x %02x %02x %02x %02x %02x %02x", 01712 (int)summary->error_register, 01713 (int)summary->status, 01714 (int)summary->sector_count, 01715 (int)summary->sector_number, 01716 (int)summary->cylinder_low, 01717 (int)summary->cylinder_high, 01718 (int)summary->drive_head); 01719 // Add a description of the contents of the status and error registers 01720 // if possible 01721 std::string st_er_desc = format_st_er_desc(elog); 01722 if (!st_er_desc.empty()) 01723 pout(" %s", st_er_desc.c_str()); 01724 pout("\n\n"); 01725 pout(" Commands leading to the command that caused the error were:\n" 01726 " CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name\n" 01727 " -- -- -- -- -- -- -- -- ---------------- --------------------\n"); 01728 for ( j = 4; j >= 0; j--){ 01729 const ata_smart_errorlog_command_struct * thiscommand = elog->commands+j; 01730 01731 // Spec says: unused data command structures shall be zero filled 01732 if (nonempty(thiscommand, sizeof(*thiscommand))) { 01733 pout(" %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n", 01734 (int)thiscommand->commandreg, 01735 (int)thiscommand->featuresreg, 01736 (int)thiscommand->sector_count, 01737 (int)thiscommand->sector_number, 01738 (int)thiscommand->cylinder_low, 01739 (int)thiscommand->cylinder_high, 01740 (int)thiscommand->drive_head, 01741 (int)thiscommand->devicecontrolreg, 01742 format_milliseconds(thiscommand->timestamp).c_str(), 01743 look_up_ata_command(thiscommand->commandreg, thiscommand->featuresreg)); 01744 } 01745 } 01746 pout("\n"); 01747 } 01748 } 01749 print_on(); 01750 if (printing_is_switchable) 01751 pout("\n"); 01752 print_off(); 01753 return data->ata_error_count; 01754 } 01755 01756 // Print SMART Extended Comprehensive Error Log (GP Log 0x03) 01757 static int PrintSmartExtErrorLog(const ata_smart_exterrlog * log, 01758 unsigned nsectors, unsigned max_errors) 01759 { 01760 pout("SMART Extended Comprehensive Error Log Version: %u (%u sectors)\n", 01761 log->version, nsectors); 01762 01763 if (!log->device_error_count) { 01764 pout("No Errors Logged\n\n"); 01765 return 0; 01766 } 01767 print_on(); 01768 01769 // Check index 01770 unsigned nentries = nsectors * 4; 01771 unsigned erridx = log->error_log_index; 01772 if (!(1 <= erridx && erridx <= nentries)){ 01773 // Some Samsung disks (at least SP1614C/SW100-25, HD300LJ/ZT100-12) use the 01774 // former index from Summary Error Log (byte 1, now reserved) and set byte 2-3 01775 // to 0. 01776 if (!(erridx == 0 && 1 <= log->reserved1 && log->reserved1 <= nentries)) { 01777 pout("Invalid Error Log index = 0x%04x (reserved = 0x%02x)\n", erridx, log->reserved1); 01778 return 0; 01779 } 01780 pout("Invalid Error Log index = 0x%04x, trying reserved byte (0x%02x) instead\n", erridx, log->reserved1); 01781 erridx = log->reserved1; 01782 } 01783 01784 // Index base is not clearly specified by ATA8-ACS (T13/1699-D Revision 6a), 01785 // it is 1-based in practice. 01786 erridx--; 01787 01788 // Calculate #errors to print 01789 unsigned errcnt = log->device_error_count; 01790 01791 if (errcnt <= nentries) 01792 pout("Device Error Count: %u\n", log->device_error_count); 01793 else { 01794 errcnt = nentries; 01795 pout("Device Error Count: %u (device log contains only the most recent %u errors)\n", 01796 log->device_error_count, errcnt); 01797 } 01798 01799 if (max_errors < errcnt) 01800 errcnt = max_errors; 01801 01802 print_off(); 01803 pout("\tCR = Command Register\n" 01804 "\tFEATR = Features Register\n" 01805 "\tCOUNT = Count (was: Sector Count) Register\n" 01806 "\tLBA_48 = Upper bytes of LBA High/Mid/Low Registers ] ATA-8\n" 01807 "\tLH = LBA High (was: Cylinder High) Register ] LBA\n" 01808 "\tLM = LBA Mid (was: Cylinder Low) Register ] Register\n" 01809 "\tLL = LBA Low (was: Sector Number) Register ]\n" 01810 "\tDV = Device (was: Device/Head) Register\n" 01811 "\tDC = Device Control Register\n" 01812 "\tER = Error register\n" 01813 "\tST = Status register\n" 01814 "Powered_Up_Time is measured from power on, and printed as\n" 01815 "DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes,\n" 01816 "SS=sec, and sss=millisec. It \"wraps\" after 49.710 days.\n\n"); 01817 01818 // Iterate through circular buffer in reverse direction 01819 for (unsigned i = 0, errnum = log->device_error_count; 01820 i < errcnt; i++, errnum--, erridx = (erridx > 0 ? erridx - 1 : nentries - 1)) { 01821 01822 const ata_smart_exterrlog_error_log & entry = log[erridx / 4].error_logs[erridx % 4]; 01823 01824 // Skip unused entries 01825 if (!nonempty(&entry, sizeof(entry))) { 01826 pout("Error %u [%u] log entry is empty\n", errnum, erridx); 01827 continue; 01828 } 01829 01830 // Print error information 01831 print_on(); 01832 const ata_smart_exterrlog_error & err = entry.error; 01833 pout("Error %u [%u] occurred at disk power-on lifetime: %u hours (%u days + %u hours)\n", 01834 errnum, erridx, err.timestamp, err.timestamp / 24, err.timestamp % 24); 01835 print_off(); 01836 01837 pout(" When the command that caused the error occurred, the device was %s.\n\n", 01838 get_error_log_state_desc(err.state)); 01839 01840 // Print registers 01841 pout(" After command completion occurred, registers were:\n" 01842 " ER -- ST COUNT LBA_48 LH LM LL DV DC\n" 01843 " -- -- -- == -- == == == -- -- -- -- --\n" 01844 " %02x -- %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", 01845 err.error_register, 01846 err.status_register, 01847 err.count_register_hi, 01848 err.count_register, 01849 err.lba_high_register_hi, 01850 err.lba_mid_register_hi, 01851 err.lba_low_register_hi, 01852 err.lba_high_register, 01853 err.lba_mid_register, 01854 err.lba_low_register, 01855 err.device_register, 01856 err.device_control_register); 01857 01858 // Add a description of the contents of the status and error registers 01859 // if possible 01860 std::string st_er_desc = format_st_er_desc(&entry); 01861 if (!st_er_desc.empty()) 01862 pout(" %s", st_er_desc.c_str()); 01863 pout("\n\n"); 01864 01865 // Print command history 01866 pout(" Commands leading to the command that caused the error were:\n" 01867 " CR FEATR COUNT LBA_48 LH LM LL DV DC Powered_Up_Time Command/Feature_Name\n" 01868 " -- == -- == -- == == == -- -- -- -- -- --------------- --------------------\n"); 01869 for (int ci = 4; ci >= 0; ci--) { 01870 const ata_smart_exterrlog_command & cmd = entry.commands[ci]; 01871 01872 // Skip unused entries 01873 if (!nonempty(&cmd, sizeof(cmd))) 01874 continue; 01875 01876 // Print registers, timestamp and ATA command name 01877 pout(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s %s\n", 01878 cmd.command_register, 01879 cmd.features_register_hi, 01880 cmd.features_register, 01881 cmd.count_register_hi, 01882 cmd.count_register, 01883 cmd.lba_high_register_hi, 01884 cmd.lba_mid_register_hi, 01885 cmd.lba_low_register_hi, 01886 cmd.lba_high_register, 01887 cmd.lba_mid_register, 01888 cmd.lba_low_register, 01889 cmd.device_register, 01890 cmd.device_control_register, 01891 format_milliseconds(cmd.timestamp).c_str(), 01892 look_up_ata_command(cmd.command_register, cmd.features_register)); 01893 } 01894 pout("\n"); 01895 } 01896 01897 print_on(); 01898 if (printing_is_switchable) 01899 pout("\n"); 01900 print_off(); 01901 return log->device_error_count; 01902 } 01903 01904 // Print SMART Extended Self-test Log (GP Log 0x07) 01905 static int PrintSmartExtSelfTestLog(const ata_smart_extselftestlog * log, 01906 unsigned nsectors, unsigned max_entries) 01907 { 01908 pout("SMART Extended Self-test Log Version: %u (%u sectors)\n", 01909 log->version, nsectors); 01910 01911 if (!log->log_desc_index){ 01912 pout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n\n"); 01913 return 0; 01914 } 01915 01916 // Check index 01917 unsigned nentries = nsectors * 19; 01918 unsigned logidx = log->log_desc_index; 01919 if (logidx > nentries) { 01920 pout("Invalid Self-test Log index = 0x%04x (reserved = 0x%02x)\n", logidx, log->reserved1); 01921 return 0; 01922 } 01923 01924 // Index base is not clearly specified by ATA8-ACS (T13/1699-D Revision 6a), 01925 // it is 1-based in practice. 01926 logidx--; 01927 01928 bool print_header = true; 01929 int errcnt = 0, igncnt = 0; 01930 int ext_ok_testnum = -1; 01931 01932 // Iterate through circular buffer in reverse direction 01933 for (unsigned i = 0, testnum = 1; 01934 i < nentries && testnum <= max_entries; 01935 i++, logidx = (logidx > 0 ? logidx - 1 : nentries - 1)) { 01936 01937 const ata_smart_extselftestlog_desc & entry = log[logidx / 19].log_descs[logidx % 19]; 01938 01939 // Skip unused entries 01940 if (!nonempty(&entry, sizeof(entry))) 01941 continue; 01942 01943 // Get LBA 01944 const unsigned char * b = entry.failing_lba; 01945 uint64_t lba48 = b[0] 01946 | ( b[1] << 8) 01947 | ( b[2] << 16) 01948 | ((uint64_t)b[3] << 24) 01949 | ((uint64_t)b[4] << 32) 01950 | ((uint64_t)b[5] << 40); 01951 01952 // Print entry 01953 int state = ataPrintSmartSelfTestEntry(testnum, entry.self_test_type, 01954 entry.self_test_status, entry.timestamp, lba48, 01955 false /*!print_error_only*/, print_header); 01956 01957 if (state < 0) { 01958 // Self-test showed an error 01959 if (ext_ok_testnum < 0) 01960 errcnt++; 01961 else 01962 // Newer successful extended self-test exits 01963 igncnt++; 01964 } 01965 else if (state > 0 && ext_ok_testnum < 0) { 01966 // Latest successful extended self-test 01967 ext_ok_testnum = testnum; 01968 } 01969 testnum++; 01970 } 01971 01972 if (igncnt) 01973 pout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n", 01974 igncnt, igncnt+errcnt, ext_ok_testnum); 01975 01976 pout("\n"); 01977 return errcnt; 01978 } 01979 01980 static void ataPrintSelectiveSelfTestLog(const ata_selective_self_test_log * log, const ata_smart_values * sv) 01981 { 01982 int i,field1,field2; 01983 const char *msg; 01984 char tmp[64]; 01985 uint64_t maxl=0,maxr=0; 01986 uint64_t current=log->currentlba; 01987 uint64_t currentend=current+65535; 01988 01989 // print data structure revision number 01990 pout("SMART Selective self-test log data structure revision number %d\n",(int)log->logversion); 01991 if (1 != log->logversion) 01992 pout("Note: revision number not 1 implies that no selective self-test has ever been run\n"); 01993 01994 switch((sv->self_test_exec_status)>>4){ 01995 case 0:msg="Completed"; 01996 break; 01997 case 1:msg="Aborted_by_host"; 01998 break; 01999 case 2:msg="Interrupted"; 02000 break; 02001 case 3:msg="Fatal_error"; 02002 break; 02003 case 4:msg="Completed_unknown_failure"; 02004 break; 02005 case 5:msg="Completed_electrical_failure"; 02006 break; 02007 case 6:msg="Completed_servo/seek_failure"; 02008 break; 02009 case 7:msg="Completed_read_failure"; 02010 break; 02011 case 8:msg="Completed_handling_damage??"; 02012 break; 02013 case 15:msg="Self_test_in_progress"; 02014 break; 02015 default:msg="Unknown_status "; 02016 break; 02017 } 02018 02019 // find the number of columns needed for printing. If in use, the 02020 // start/end of span being read-scanned... 02021 if (log->currentspan>5) { 02022 maxl=current; 02023 maxr=currentend; 02024 } 02025 for (i=0; i<5; i++) { 02026 uint64_t start=log->span[i].start; 02027 uint64_t end =log->span[i].end; 02028 // ... plus max start/end of each of the five test spans. 02029 if (start>maxl) 02030 maxl=start; 02031 if (end > maxr) 02032 maxr=end; 02033 } 02034 02035 // we need at least 7 characters wide fields to accomodate the 02036 // labels 02037 if ((field1=snprintf(tmp,64, "%"PRIu64, maxl))<7) 02038 field1=7; 02039 if ((field2=snprintf(tmp,64, "%"PRIu64, maxr))<7) 02040 field2=7; 02041 02042 // now print the five test spans 02043 pout(" SPAN %*s %*s CURRENT_TEST_STATUS\n", field1, "MIN_LBA", field2, "MAX_LBA"); 02044 02045 for (i=0; i<5; i++) { 02046 uint64_t start=log->span[i].start; 02047 uint64_t end=log->span[i].end; 02048 02049 if ((i+1)==(int)log->currentspan) 02050 // this span is currently under test 02051 pout(" %d %*"PRIu64" %*"PRIu64" %s [%01d0%% left] (%"PRIu64"-%"PRIu64")\n", 02052 i+1, field1, start, field2, end, msg, 02053 (int)(sv->self_test_exec_status & 0xf), current, currentend); 02054 else 02055 // this span is not currently under test 02056 pout(" %d %*"PRIu64" %*"PRIu64" Not_testing\n", 02057 i+1, field1, start, field2, end); 02058 } 02059 02060 // if we are currently read-scanning, print LBAs and the status of 02061 // the read scan 02062 if (log->currentspan>5) 02063 pout("%5d %*"PRIu64" %*"PRIu64" Read_scanning %s\n", 02064 (int)log->currentspan, field1, current, field2, currentend, 02065 OfflineDataCollectionStatus(sv->offline_data_collection_status)); 02066 02067 /* Print selective self-test flags. Possible flag combinations are 02068 (numbering bits from 0-15): 02069 Bit-1 Bit-3 Bit-4 02070 Scan Pending Active 02071 0 * * Don't scan 02072 1 0 0 Will carry out scan after selective test 02073 1 1 0 Waiting to carry out scan after powerup 02074 1 0 1 Currently scanning 02075 1 1 1 Currently scanning 02076 */ 02077 02078 pout("Selective self-test flags (0x%x):\n", (unsigned int)log->flags); 02079 if (log->flags & SELECTIVE_FLAG_DOSCAN) { 02080 if (log->flags & SELECTIVE_FLAG_ACTIVE) 02081 pout(" Currently read-scanning the remainder of the disk.\n"); 02082 else if (log->flags & SELECTIVE_FLAG_PENDING) 02083 pout(" Read-scan of remainder of disk interrupted; will resume %d min after power-up.\n", 02084 (int)log->pendingtime); 02085 else 02086 pout(" After scanning selected spans, read-scan remainder of disk.\n"); 02087 } 02088 else 02089 pout(" After scanning selected spans, do NOT read-scan remainder of disk.\n"); 02090 02091 // print pending time 02092 pout("If Selective self-test is pending on power-up, resume after %d minute delay.\n", 02093 (int)log->pendingtime); 02094 02095 return; 02096 } 02097 02098 // Format SCT Temperature value 02099 static const char * sct_ptemp(signed char x, char (& buf)[20]) 02100 { 02101 if (x == -128 /*0x80 = unknown*/) 02102 return " ?"; 02103 snprintf(buf, sizeof(buf), "%2d", x); 02104 return buf; 02105 } 02106 02107 static const char * sct_pbar(int x, char (& buf)[64]) 02108 { 02109 if (x <= 19) 02110 x = 0; 02111 else 02112 x -= 19; 02113 bool ov = false; 02114 if (x > 40) { 02115 x = 40; ov = true; 02116 } 02117 if (x > 0) { 02118 memset(buf, '*', x); 02119 if (ov) 02120 buf[x-1] = '+'; 02121 buf[x] = 0; 02122 } 02123 else { 02124 buf[0] = '-'; buf[1] = 0; 02125 } 02126 return buf; 02127 } 02128 02129 static const char * sct_device_state_msg(unsigned char state) 02130 { 02131 switch (state) { 02132 case 0: return "Active"; 02133 case 1: return "Stand-by"; 02134 case 2: return "Sleep"; 02135 case 3: return "DST executing in background"; 02136 case 4: return "SMART Off-line Data Collection executing in background"; 02137 case 5: return "SCT command executing in background"; 02138 default:return "Unknown"; 02139 } 02140 } 02141 02142 // Print SCT Status 02143 static int ataPrintSCTStatus(const ata_sct_status_response * sts) 02144 { 02145 pout("SCT Status Version: %u\n", sts->format_version); 02146 pout("SCT Version (vendor specific): %u (0x%04x)\n", sts->sct_version, sts->sct_version); 02147 pout("SCT Support Level: %u\n", sts->sct_spec); 02148 pout("Device State: %s (%u)\n", 02149 sct_device_state_msg(sts->device_state), sts->device_state); 02150 char buf1[20], buf2[20]; 02151 if ( !sts->min_temp && !sts->life_min_temp 02152 && !sts->under_limit_count && !sts->over_limit_count) { 02153 // "Reserved" fields not set, assume "old" format version 2 02154 // Table 11 of T13/1701DT-N (SMART Command Transport) Revision 5, February 2005 02155 // Table 54 of T13/1699-D (ATA8-ACS) Revision 3e, July 2006 02156 pout("Current Temperature: %s Celsius\n", 02157 sct_ptemp(sts->hda_temp, buf1)); 02158 pout("Power Cycle Max Temperature: %s Celsius\n", 02159 sct_ptemp(sts->max_temp, buf2)); 02160 pout("Lifetime Max Temperature: %s Celsius\n", 02161 sct_ptemp(sts->life_max_temp, buf2)); 02162 } 02163 else { 02164 // Assume "new" format version 2 or version 3 02165 // T13/e06152r0-3 (Additional SCT Temperature Statistics), August - October 2006 02166 // Table 60 of T13/1699-D (ATA8-ACS) Revision 3f, December 2006 (format version 2) 02167 // Table 80 of T13/1699-D (ATA8-ACS) Revision 6a, September 2008 (format version 3) 02168 pout("Current Temperature: %s Celsius\n", 02169 sct_ptemp(sts->hda_temp, buf1)); 02170 pout("Power Cycle Min/Max Temperature: %s/%s Celsius\n", 02171 sct_ptemp(sts->min_temp, buf1), sct_ptemp(sts->max_temp, buf2)); 02172 pout("Lifetime Min/Max Temperature: %s/%s Celsius\n", 02173 sct_ptemp(sts->life_min_temp, buf1), sct_ptemp(sts->life_max_temp, buf2)); 02174 signed char avg = sts->byte205; // Average Temperature from e06152r0-2, removed in e06152r3 02175 if (0 < avg && sts->life_min_temp <= avg && avg <= sts->life_max_temp) 02176 pout("Lifetime Average Temperature: %2d Celsius\n", avg); 02177 pout("Under/Over Temperature Limit Count: %2u/%u\n", 02178 sts->under_limit_count, sts->over_limit_count); 02179 } 02180 return 0; 02181 } 02182 02183 // Print SCT Temperature History Table 02184 static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh) 02185 { 02186 char buf1[20], buf2[20], buf3[64]; 02187 pout("SCT Temperature History Version: %u%s\n", tmh->format_version, 02188 (tmh->format_version != 2 ? " (Unknown, should be 2)" : "")); 02189 pout("Temperature Sampling Period: %u minute%s\n", 02190 tmh->sampling_period, (tmh->sampling_period==1?"":"s")); 02191 pout("Temperature Logging Interval: %u minute%s\n", 02192 tmh->interval, (tmh->interval==1?"":"s")); 02193 pout("Min/Max recommended Temperature: %s/%s Celsius\n", 02194 sct_ptemp(tmh->min_op_limit, buf1), sct_ptemp(tmh->max_op_limit, buf2)); 02195 pout("Min/Max Temperature Limit: %s/%s Celsius\n", 02196 sct_ptemp(tmh->under_limit, buf1), sct_ptemp(tmh->over_limit, buf2)); 02197 pout("Temperature History Size (Index): %u (%u)\n", tmh->cb_size, tmh->cb_index); 02198 02199 if (!(0 < tmh->cb_size && tmh->cb_size <= sizeof(tmh->cb) && tmh->cb_index < tmh->cb_size)) { 02200 if (!tmh->cb_size) 02201 pout("Temperature History is empty\n"); 02202 else 02203 pout("Invalid Temperature History Size or Index\n"); 02204 return 0; 02205 } 02206 02207 // Print table 02208 pout("\nIndex Estimated Time Temperature Celsius\n"); 02209 unsigned n = 0, i = (tmh->cb_index+1) % tmh->cb_size; 02210 unsigned interval = (tmh->interval > 0 ? tmh->interval : 1); 02211 time_t t = time(0) - (tmh->cb_size-1) * interval * 60; 02212 t -= t % (interval * 60); 02213 while (n < tmh->cb_size) { 02214 // Find range of identical temperatures 02215 unsigned n1 = n, n2 = n+1, i2 = (i+1) % tmh->cb_size; 02216 while (n2 < tmh->cb_size && tmh->cb[i2] == tmh->cb[i]) { 02217 n2++; i2 = (i2+1) % tmh->cb_size; 02218 } 02219 // Print range 02220 while (n < n2) { 02221 if (n == n1 || n == n2-1 || n2 <= n1+3) { 02222 char date[30]; 02223 // TODO: Don't print times < boot time 02224 strftime(date, sizeof(date), "%Y-%m-%d %H:%M", localtime(&t)); 02225 pout(" %3u %s %s %s\n", i, date, 02226 sct_ptemp(tmh->cb[i], buf1), sct_pbar(tmh->cb[i], buf3)); 02227 } 02228 else if (n == n1+1) { 02229 pout(" ... ..(%3u skipped). .. %s\n", 02230 n2-n1-2, sct_pbar(tmh->cb[i], buf3)); 02231 } 02232 t += interval * 60; i = (i+1) % tmh->cb_size; n++; 02233 } 02234 } 02235 //assert(n == tmh->cb_size && i == (tmh->cb_index+1) % tmh->cb_size); 02236 02237 return 0; 02238 } 02239 02240 // Print SCT Error Recovery Control timers 02241 static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer) 02242 { 02243 pout("SCT Error Recovery Control%s:\n", (set ? " set to" : "")); 02244 if (!read_timer) 02245 pout(" Read: Disabled\n"); 02246 else 02247 pout(" Read: %6d (%0.1f seconds)\n", read_timer, read_timer/10.0); 02248 if (!write_timer) 02249 pout(" Write: Disabled\n"); 02250 else 02251 pout(" Write: %6d (%0.1f seconds)\n", write_timer, write_timer/10.0); 02252 } 02253 02254 static void print_aam_level(const char * msg, int level, int recommended = -1) 02255 { 02256 // Table 56 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008 02257 // Obsolete since T13/2015-D (ACS-2) Revision 4a, December 9, 2010 02258 const char * s; 02259 if (level == 0) 02260 s = "vendor specific"; 02261 else if (level < 128) 02262 s = "unknown/retired"; 02263 else if (level == 128) 02264 s = "quiet"; 02265 else if (level < 254) 02266 s = "intermediate"; 02267 else if (level == 254) 02268 s = "maximum performance"; 02269 else 02270 s = "reserved"; 02271 02272 if (recommended >= 0) 02273 pout("%s%d (%s), recommended: %d\n", msg, level, s, recommended); 02274 else 02275 pout("%s%d (%s)\n", msg, level, s); 02276 } 02277 02278 static void print_apm_level(const char * msg, int level) 02279 { 02280 // Table 120 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 02281 const char * s; 02282 if (!(1 <= level && level <= 254)) 02283 s = "reserved"; 02284 else if (level == 1) 02285 s = "minimum power consumption with standby"; 02286 else if (level < 128) 02287 s = "intermediate level with standby"; 02288 else if (level == 128) 02289 s = "minimum power consumption without standby"; 02290 else if (level < 254) 02291 s = "intermediate level without standby"; 02292 else 02293 s = "maximum performance"; 02294 02295 pout("%s%d (%s)\n", msg, level, s); 02296 } 02297 02298 static void print_ata_security_status(const char * msg, unsigned short state) 02299 { 02300 const char * s1, * s2 = "", * s3 = "", * s4 = ""; 02301 02302 // Table 6 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 02303 if (!(state & 0x0001)) 02304 s1 = "Unavailable"; 02305 else if (!(state & 0x0002)) { 02306 s1 = "Disabled, "; 02307 if (!(state & 0x0008)) 02308 s2 = "NOT FROZEN [SEC1]"; 02309 else 02310 s2 = "frozen [SEC2]"; 02311 } 02312 else { 02313 s1 = "ENABLED, PW level "; 02314 if (!(state & 0x0020)) 02315 s2 = "HIGH"; 02316 else 02317 s2 = "MAX"; 02318 02319 if (!(state & 0x0004)) { 02320 s3 = ", not locked, "; 02321 if (!(state & 0x0008)) 02322 s4 = "not frozen [SEC5]"; 02323 else 02324 s4 = "frozen [SEC6]"; 02325 } 02326 else { 02327 s3 = ", **LOCKED** [SEC4]"; 02328 if (state & 0x0010) 02329 s4 = ", PW ATTEMPTS EXCEEDED"; 02330 } 02331 } 02332 02333 pout("%s%s%s%s%s\n", msg, s1, s2, s3, s4); 02334 } 02335 02336 static void print_standby_timer(const char * msg, int timer, const ata_identify_device & drive) 02337 { 02338 const char * s1 = 0; 02339 int hours = 0, minutes = 0 , seconds = 0; 02340 02341 // Table 63 of T13/2015-D (ACS-2) Revision 7, June 22, 2011 02342 if (timer == 0) 02343 s1 = "disabled"; 02344 else if (timer <= 240) 02345 seconds = timer * 5, minutes = seconds / 60, seconds %= 60; 02346 else if (timer <= 251) 02347 minutes = (timer - 240) * 30, hours = minutes / 60, minutes %= 60; 02348 else if (timer == 252) 02349 minutes = 21; 02350 else if (timer == 253) 02351 s1 = "between 8 hours and 12 hours"; 02352 else if (timer == 255) 02353 minutes = 21, seconds = 15; 02354 else 02355 s1 = "reserved"; 02356 02357 const char * s2 = "", * s3 = ""; 02358 if (!(drive.words047_079[49-47] & 0x2000)) 02359 s2 = " or vendor-specific"; 02360 if (timer > 0 && (drive.words047_079[50-47] & 0xc001) == 0x4001) 02361 s3 = ", a vendor-specific minimum applies"; 02362 02363 if (s1) 02364 pout("%s%d (%s%s%s)\n", msg, timer, s1, s2, s3); 02365 else 02366 pout("%s%d (%02d:%02d:%02d%s%s)\n", msg, timer, hours, minutes, seconds, s2, s3); 02367 } 02368 02369 02370 int ataPrintMain (ata_device * device, const ata_print_options & options) 02371 { 02372 // If requested, check power mode first 02373 const char * powername = 0; 02374 bool powerchg = false; 02375 if (options.powermode) { 02376 unsigned char powerlimit = 0xff; 02377 int powermode = ataCheckPowerMode(device); 02378 switch (powermode) { 02379 case -1: 02380 if (device->is_syscall_unsup()) { 02381 pout("CHECK POWER MODE not implemented, ignoring -n option\n"); break; 02382 } 02383 powername = "SLEEP"; powerlimit = 2; 02384 break; 02385 case 0: 02386 powername = "STANDBY"; powerlimit = 3; break; 02387 case 0x80: 02388 powername = "IDLE"; powerlimit = 4; break; 02389 case 0xff: 02390 powername = "ACTIVE or IDLE"; break; 02391 default: 02392 pout("CHECK POWER MODE returned unknown value 0x%02x, ignoring -n option\n", powermode); 02393 break; 02394 } 02395 if (powername) { 02396 if (options.powermode >= powerlimit) { 02397 pout("Device is in %s mode, exit(%d)\n", powername, FAILPOWER); 02398 return FAILPOWER; 02399 } 02400 powerchg = (powermode != 0xff); // SMART tests will spin up drives 02401 } 02402 } 02403 02404 // SMART values needed ? 02405 bool need_smart_val = ( 02406 options.smart_check_status 02407 || options.smart_general_values 02408 || options.smart_vendor_attrib 02409 || options.smart_error_log 02410 || options.smart_selftest_log 02411 || options.smart_selective_selftest_log 02412 || options.smart_ext_error_log 02413 || options.smart_ext_selftest_log 02414 || options.smart_auto_offl_enable 02415 || options.smart_auto_offl_disable 02416 || options.smart_selftest_type != -1 02417 ); 02418 02419 // SMART must be enabled ? 02420 bool need_smart_enabled = ( 02421 need_smart_val 02422 || options.smart_auto_save_enable 02423 || options.smart_auto_save_disable 02424 ); 02425 02426 // SMART feature set needed ? 02427 bool need_smart_support = ( 02428 need_smart_enabled 02429 || options.smart_enable 02430 || options.smart_disable 02431 ); 02432 02433 // SMART and GP log directories needed ? 02434 bool need_smart_logdir = options.smart_logdir; 02435 02436 bool need_gp_logdir = ( 02437 options.gp_logdir 02438 || options.smart_ext_error_log 02439 || options.smart_ext_selftest_log 02440 || options.devstat_all_pages 02441 || options.devstat_ssd_page 02442 || !options.devstat_pages.empty() 02443 ); 02444 02445 unsigned i; 02446 for (i = 0; i < options.log_requests.size(); i++) { 02447 if (options.log_requests[i].gpl) 02448 need_gp_logdir = true; 02449 else 02450 need_smart_logdir = true; 02451 } 02452 02453 // SCT commands needed ? 02454 bool need_sct_support = ( 02455 options.sct_temp_sts 02456 || options.sct_temp_hist 02457 || options.sct_temp_int 02458 || options.sct_erc_get 02459 || options.sct_erc_set 02460 ); 02461 02462 // Exit if no further options specified 02463 if (!( options.drive_info || options.show_presets 02464 || need_smart_support || need_smart_logdir 02465 || need_gp_logdir || need_sct_support 02466 || options.sataphy 02467 || options.identify_word_level >= 0 02468 || options.get_set_used )) { 02469 if (powername) 02470 pout("Device is in %s mode\n", powername); 02471 else 02472 pout("ATA device successfully opened\n\n" 02473 "Use 'smartctl -a' (or '-x') to print SMART (and more) information\n\n"); 02474 return 0; 02475 } 02476 02477 // Start by getting Drive ID information. We need this, to know if SMART is supported. 02478 int returnval = 0; 02479 ata_identify_device drive; memset(&drive, 0, sizeof(drive)); 02480 unsigned char raw_drive[sizeof(drive)]; memset(&raw_drive, 0, sizeof(raw_drive)); 02481 02482 device->clear_err(); 02483 int retid = ata_read_identity(device, &drive, options.fix_swapped_id, raw_drive); 02484 if (retid < 0) { 02485 pout("Read Device Identity failed: %s\n\n", 02486 (device->get_errno() ? device->get_errmsg() : "Unknown error")); 02487 failuretest(MANDATORY_CMD, returnval|=FAILID); 02488 } 02489 else if (!nonempty(&drive, sizeof(drive))) { 02490 pout("Read Device Identity failed: empty IDENTIFY data\n\n"); 02491 failuretest(MANDATORY_CMD, returnval|=FAILID); 02492 } 02493 02494 // If requested, show which presets would be used for this drive and exit. 02495 if (options.show_presets) { 02496 show_presets(&drive); 02497 return 0; 02498 } 02499 02500 // Use preset vendor attribute options unless user has requested otherwise. 02501 ata_vendor_attr_defs attribute_defs = options.attribute_defs; 02502 firmwarebug_defs firmwarebugs = options.firmwarebugs; 02503 const drive_settings * dbentry = 0; 02504 if (!options.ignore_presets) 02505 dbentry = lookup_drive_apply_presets(&drive, attribute_defs, 02506 firmwarebugs); 02507 02508 // Get capacity, sector sizes and rotation rate 02509 ata_size_info sizes; 02510 ata_get_size_info(&drive, sizes); 02511 int rpm = ata_get_rotation_rate(&drive); 02512 02513 // Print ATA IDENTIFY info if requested 02514 if (options.identify_word_level >= 0) { 02515 pout("=== ATA IDENTIFY DATA ===\n"); 02516 // Pass raw data without endianness adjustments 02517 ata_print_identify_data(raw_drive, (options.identify_word_level > 0), options.identify_bit_level); 02518 } 02519 02520 // Print most drive identity information if requested 02521 if (options.drive_info) { 02522 pout("=== START OF INFORMATION SECTION ===\n"); 02523 print_drive_info(&drive, sizes, rpm, dbentry); 02524 } 02525 02526 // Check and print SMART support and state 02527 int smart_supported = -1, smart_enabled = -1; 02528 if (need_smart_support || options.drive_info) { 02529 02530 // Packet device ? 02531 if (retid > 0) { 02532 pout("SMART support is: Unavailable - Packet Interface Devices [this device: %s] don't support ATA SMART\n", 02533 packetdevicetype(retid-1)); 02534 } 02535 else { 02536 // Disk device: SMART supported and enabled ? 02537 smart_supported = ataSmartSupport(&drive); 02538 smart_enabled = ataIsSmartEnabled(&drive); 02539 02540 if (smart_supported < 0) 02541 pout("SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 82-83 don't show if SMART supported.\n"); 02542 if (smart_supported && smart_enabled < 0) { 02543 pout("SMART support is: Ambiguous - ATA IDENTIFY DEVICE words 85-87 don't show if SMART is enabled.\n"); 02544 if (need_smart_support) { 02545 failuretest(MANDATORY_CMD, returnval|=FAILSMART); 02546 // check SMART support by trying a command 02547 pout(" Checking to be sure by trying SMART RETURN STATUS command.\n"); 02548 if (ataDoesSmartWork(device)) 02549 smart_supported = smart_enabled = 1; 02550 } 02551 } 02552 else if (smart_supported < 0 && (smart_enabled > 0 || dbentry)) 02553 // Assume supported if enabled or in drive database 02554 smart_supported = 1; 02555 02556 if (smart_supported < 0) 02557 pout("SMART support is: Unknown - Try option -s with argument 'on' to enable it."); 02558 else if (!smart_supported) 02559 pout("SMART support is: Unavailable - device lacks SMART capability.\n"); 02560 else { 02561 if (options.drive_info) 02562 pout("SMART support is: Available - device has SMART capability.\n"); 02563 if (smart_enabled >= 0) { 02564 if (device->ata_identify_is_cached()) { 02565 if (options.drive_info) 02566 pout(" %sabled status cached by OS, trying SMART RETURN STATUS cmd.\n", 02567 (smart_enabled?"En":"Dis")); 02568 smart_enabled = ataDoesSmartWork(device); 02569 } 02570 if (options.drive_info) 02571 pout("SMART support is: %s\n", 02572 (smart_enabled ? "Enabled" : "Disabled")); 02573 } 02574 } 02575 } 02576 } 02577 02578 // Print AAM status 02579 if (options.get_aam) { 02580 if ((drive.command_set_2 & 0xc200) != 0x4200) // word083 02581 pout("AAM feature is: Unavailable\n"); 02582 else if (!(drive.word086 & 0x0200)) 02583 pout("AAM feature is: Disabled\n"); 02584 else 02585 print_aam_level("AAM level is: ", drive.words088_255[94-88] & 0xff, 02586 drive.words088_255[94-88] >> 8); 02587 } 02588 02589 // Print APM status 02590 if (options.get_apm) { 02591 if ((drive.command_set_2 & 0xc008) != 0x4008) // word083 02592 pout("APM feature is: Unavailable\n"); 02593 else if (!(drive.word086 & 0x0008)) 02594 pout("APM feature is: Disabled\n"); 02595 else 02596 print_apm_level("APM level is: ", drive.words088_255[91-88] & 0xff); 02597 } 02598 02599 // Print read look-ahead status 02600 if (options.get_lookahead) { 02601 pout("Rd look-ahead is: %s\n", 02602 ( (drive.command_set_2 & 0xc000) != 0x4000 // word083 02603 || !(drive.command_set_1 & 0x0040)) ? "Unavailable" : // word082 02604 !(drive.cfs_enable_1 & 0x0040) ? "Disabled" : "Enabled"); // word085 02605 } 02606 02607 // Print write cache status 02608 if (options.get_wcache) { 02609 pout("Write cache is: %s\n", 02610 ( (drive.command_set_2 & 0xc000) != 0x4000 // word083 02611 || !(drive.command_set_1 & 0x0020)) ? "Unavailable" : // word082 02612 !(drive.cfs_enable_1 & 0x0020) ? "Disabled" : "Enabled"); // word085 02613 } 02614 02615 // Print ATA security status 02616 if (options.get_security) 02617 print_ata_security_status("ATA Security is: ", drive.words088_255[128-88]); 02618 02619 // Print remaining drive info 02620 if (options.drive_info) { 02621 // Print the (now possibly changed) power mode if available 02622 if (powername) 02623 pout("Power mode %s %s\n", (powerchg?"was:":"is: "), powername); 02624 pout("\n"); 02625 } 02626 02627 // Exit if SMART is not supported but must be available to proceed 02628 if (smart_supported <= 0 && need_smart_support) 02629 failuretest(MANDATORY_CMD, returnval|=FAILSMART); 02630 02631 // START OF THE ENABLE/DISABLE SECTION OF THE CODE 02632 if ( options.smart_disable || options.smart_enable 02633 || options.smart_auto_save_disable || options.smart_auto_save_enable 02634 || options.smart_auto_offl_disable || options.smart_auto_offl_enable) 02635 pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n"); 02636 02637 // Enable/Disable AAM 02638 if (options.set_aam) { 02639 if (options.set_aam > 0) { 02640 if (!ata_set_features(device, ATA_ENABLE_AAM, options.set_aam-1)) { 02641 pout("AAM enable failed: %s\n", device->get_errmsg()); 02642 returnval |= FAILSMART; 02643 } 02644 else 02645 print_aam_level("AAM set to level ", options.set_aam-1); 02646 } 02647 else { 02648 if (!ata_set_features(device, ATA_DISABLE_AAM)) { 02649 pout("AAM disable failed: %s\n", device->get_errmsg()); 02650 returnval |= FAILSMART; 02651 } 02652 else 02653 pout("AAM disabled\n"); 02654 } 02655 } 02656 02657 // Enable/Disable APM 02658 if (options.set_apm) { 02659 if (options.set_apm > 0) { 02660 if (!ata_set_features(device, ATA_ENABLE_APM, options.set_apm-1)) { 02661 pout("APM enable failed: %s\n", device->get_errmsg()); 02662 returnval |= FAILSMART; 02663 } 02664 else 02665 print_apm_level("APM set to level ", options.set_apm-1); 02666 } 02667 else { 02668 if (!ata_set_features(device, ATA_DISABLE_APM)) { 02669 pout("APM disable failed: %s\n", device->get_errmsg()); 02670 returnval |= FAILSMART; 02671 } 02672 else 02673 pout("APM disabled\n"); 02674 } 02675 } 02676 02677 // Enable/Disable read look-ahead 02678 if (options.set_lookahead) { 02679 bool enable = (options.set_lookahead > 0); 02680 if (!ata_set_features(device, (enable ? ATA_ENABLE_READ_LOOK_AHEAD : ATA_DISABLE_READ_LOOK_AHEAD))) { 02681 pout("Read look-ahead %sable failed: %s\n", (enable ? "en" : "dis"), device->get_errmsg()); 02682 returnval |= FAILSMART; 02683 } 02684 else 02685 pout("Read look-ahead %sabled\n", (enable ? "en" : "dis")); 02686 } 02687 02688 // Enable/Disable write cache 02689 if (options.set_wcache) { 02690 bool enable = (options.set_wcache > 0); 02691 if (!ata_set_features(device, (enable ? ATA_ENABLE_WRITE_CACHE : ATA_DISABLE_WRITE_CACHE))) { 02692 pout("Write cache %sable failed: %s\n", (enable ? "en" : "dis"), device->get_errmsg()); 02693 returnval |= FAILSMART; 02694 } 02695 else 02696 pout("Write cache %sabled\n", (enable ? "en" : "dis")); 02697 } 02698 02699 // Freeze ATA security 02700 if (options.set_security_freeze) { 02701 if (!ata_nodata_command(device, ATA_SECURITY_FREEZE_LOCK)) { 02702 pout("ATA SECURITY FREEZE LOCK failed: %s\n", device->get_errmsg()); 02703 returnval |= FAILSMART; 02704 } 02705 else 02706 pout("ATA Security set to frozen mode\n"); 02707 } 02708 02709 // Set standby timer 02710 if (options.set_standby) { 02711 if (!ata_nodata_command(device, ATA_IDLE, options.set_standby-1)) { 02712 pout("ATA IDLE command failed: %s\n", device->get_errmsg()); 02713 returnval |= FAILSMART; 02714 } 02715 else 02716 print_standby_timer("Standby timer set to ", options.set_standby-1, drive); 02717 } 02718 02719 // Enable/Disable SMART commands 02720 if (options.smart_enable) { 02721 if (ataEnableSmart(device)) { 02722 pout("SMART Enable failed: %s\n\n", device->get_errmsg()); 02723 failuretest(MANDATORY_CMD, returnval|=FAILSMART); 02724 } 02725 else { 02726 pout("SMART Enabled.\n"); 02727 smart_enabled = 1; 02728 } 02729 } 02730 02731 // Turn off SMART on device 02732 if (options.smart_disable) { 02733 if (ataDisableSmart(device)) { 02734 pout("SMART Disable failed: %s\n\n", device->get_errmsg()); 02735 failuretest(MANDATORY_CMD,returnval|=FAILSMART); 02736 } 02737 } 02738 02739 // Exit if SMART is disabled but must be enabled to proceed 02740 if (options.smart_disable || (smart_enabled <= 0 && need_smart_enabled && !is_permissive())) { 02741 pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n"); 02742 if (!options.smart_disable) 02743 pout("(override with '-T permissive' option)\n"); 02744 return returnval; 02745 } 02746 02747 // Enable/Disable Auto-save attributes 02748 if (options.smart_auto_save_enable) { 02749 if (ataEnableAutoSave(device)){ 02750 pout("SMART Enable Attribute Autosave failed: %s\n\n", device->get_errmsg()); 02751 failuretest(MANDATORY_CMD, returnval|=FAILSMART); 02752 } 02753 else 02754 pout("SMART Attribute Autosave Enabled.\n"); 02755 } 02756 02757 if (options.smart_auto_save_disable) { 02758 if (ataDisableAutoSave(device)){ 02759 pout("SMART Disable Attribute Autosave failed: %s\n\n", device->get_errmsg()); 02760 failuretest(MANDATORY_CMD, returnval|=FAILSMART); 02761 } 02762 else 02763 pout("SMART Attribute Autosave Disabled.\n"); 02764 } 02765 02766 // Read SMART values and thresholds if necessary 02767 ata_smart_values smartval; memset(&smartval, 0, sizeof(smartval)); 02768 ata_smart_thresholds_pvt smartthres; memset(&smartthres, 0, sizeof(smartthres)); 02769 bool smart_val_ok = false, smart_thres_ok = false; 02770 02771 if (need_smart_val) { 02772 if (ataReadSmartValues(device, &smartval)) { 02773 pout("Read SMART Data failed: %s\n\n", device->get_errmsg()); 02774 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02775 } 02776 else { 02777 smart_val_ok = true; 02778 02779 if (options.smart_check_status || options.smart_vendor_attrib) { 02780 if (ataReadSmartThresholds(device, &smartthres)){ 02781 pout("Read SMART Thresholds failed: %s\n\n", device->get_errmsg()); 02782 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02783 } 02784 else 02785 smart_thres_ok = true; 02786 } 02787 } 02788 } 02789 02790 // Enable/Disable Off-line testing 02791 bool needupdate = false; 02792 if (options.smart_auto_offl_enable) { 02793 if (!isSupportAutomaticTimer(&smartval)){ 02794 pout("SMART Automatic Timers not supported\n\n"); 02795 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02796 } 02797 needupdate = smart_val_ok; 02798 if (ataEnableAutoOffline(device)){ 02799 pout("SMART Enable Automatic Offline failed: %s\n\n", device->get_errmsg()); 02800 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02801 } 02802 else 02803 pout("SMART Automatic Offline Testing Enabled every four hours.\n"); 02804 } 02805 02806 if (options.smart_auto_offl_disable) { 02807 if (!isSupportAutomaticTimer(&smartval)){ 02808 pout("SMART Automatic Timers not supported\n\n"); 02809 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02810 } 02811 needupdate = smart_val_ok; 02812 if (ataDisableAutoOffline(device)){ 02813 pout("SMART Disable Automatic Offline failed: %s\n\n", device->get_errmsg()); 02814 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02815 } 02816 else 02817 pout("SMART Automatic Offline Testing Disabled.\n"); 02818 } 02819 02820 if (needupdate && ataReadSmartValues(device, &smartval)){ 02821 pout("Read SMART Data failed: %s\n\n", device->get_errmsg()); 02822 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02823 smart_val_ok = false; 02824 } 02825 02826 // all this for a newline! 02827 if ( options.smart_disable || options.smart_enable 02828 || options.smart_auto_save_disable || options.smart_auto_save_enable 02829 || options.smart_auto_offl_disable || options.smart_auto_offl_enable) 02830 pout("\n"); 02831 02832 // START OF READ-ONLY OPTIONS APART FROM -V and -i 02833 if ( options.smart_check_status || options.smart_general_values 02834 || options.smart_vendor_attrib || options.smart_error_log 02835 || options.smart_selftest_log || options.smart_selective_selftest_log 02836 || options.smart_ext_error_log || options.smart_ext_selftest_log 02837 || options.sct_temp_sts || options.sct_temp_hist ) 02838 pout("=== START OF READ SMART DATA SECTION ===\n"); 02839 02840 // Check SMART status 02841 if (options.smart_check_status) { 02842 02843 switch (ataSmartStatus2(device)) { 02844 02845 case 0: 02846 // The case where the disk health is OK 02847 pout("SMART overall-health self-assessment test result: PASSED\n"); 02848 if (smart_thres_ok && find_failed_attr(&smartval, &smartthres, attribute_defs, 0)) { 02849 if (options.smart_vendor_attrib) 02850 pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); 02851 else { 02852 print_on(); 02853 pout("Please note the following marginal Attributes:\n"); 02854 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format); 02855 } 02856 returnval|=FAILAGE; 02857 } 02858 else 02859 pout("\n"); 02860 break; 02861 02862 case 1: 02863 // The case where the disk health is NOT OK 02864 print_on(); 02865 pout("SMART overall-health self-assessment test result: FAILED!\n" 02866 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); 02867 print_off(); 02868 if (smart_thres_ok && find_failed_attr(&smartval, &smartthres, attribute_defs, 1)) { 02869 returnval|=FAILATTR; 02870 if (options.smart_vendor_attrib) 02871 pout("See vendor-specific Attribute list for failed Attributes.\n\n"); 02872 else { 02873 print_on(); 02874 pout("Failed Attributes:\n"); 02875 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format); 02876 } 02877 } 02878 else 02879 pout("No failed Attributes found.\n\n"); 02880 returnval|=FAILSTATUS; 02881 print_off(); 02882 break; 02883 02884 case -1: 02885 default: 02886 // Something went wrong with the SMART STATUS command. 02887 // The ATA SMART RETURN STATUS command provides the result in the ATA output 02888 // registers. Buggy ATA/SATA drivers and SAT Layers often do not properly 02889 // return the registers values. 02890 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02891 if (!(smart_val_ok && smart_thres_ok)) { 02892 print_on(); 02893 pout("SMART overall-health self-assessment test result: UNKNOWN!\n" 02894 "SMART Status, Attributes and Thresholds cannot be read.\n\n"); 02895 } 02896 else if (find_failed_attr(&smartval, &smartthres, attribute_defs, 1)) { 02897 print_on(); 02898 pout("SMART overall-health self-assessment test result: FAILED!\n" 02899 "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); 02900 print_off(); 02901 returnval|=FAILATTR; 02902 returnval|=FAILSTATUS; 02903 if (options.smart_vendor_attrib) 02904 pout("See vendor-specific Attribute list for failed Attributes.\n\n"); 02905 else { 02906 print_on(); 02907 pout("Failed Attributes:\n"); 02908 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format); 02909 } 02910 } 02911 else { 02912 pout("SMART overall-health self-assessment test result: PASSED\n"); 02913 pout("Warning: This result is based on an Attribute check.\n"); 02914 if (find_failed_attr(&smartval, &smartthres, attribute_defs, 0)) { 02915 if (options.smart_vendor_attrib) 02916 pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); 02917 else { 02918 print_on(); 02919 pout("Please note the following marginal Attributes:\n"); 02920 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format); 02921 } 02922 returnval|=FAILAGE; 02923 } 02924 else 02925 pout("\n"); 02926 } 02927 print_off(); 02928 break; 02929 } // end of switch statement 02930 02931 print_off(); 02932 } // end of checking SMART Status 02933 02934 // Print general SMART values 02935 if (smart_val_ok && options.smart_general_values) 02936 PrintGeneralSmartValues(&smartval, &drive, firmwarebugs); 02937 02938 // Print vendor-specific attributes 02939 if (smart_val_ok && options.smart_vendor_attrib) { 02940 print_on(); 02941 PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 02942 (printing_is_switchable ? 2 : 0), options.output_format); 02943 print_off(); 02944 } 02945 02946 // If GP Log is supported use smart log directory for 02947 // error and selftest log support check. 02948 if ( isGeneralPurposeLoggingCapable(&drive) 02949 && ( options.smart_error_log || options.smart_selftest_log 02950 || options.retry_error_log || options.retry_selftest_log)) 02951 need_smart_logdir = true; 02952 02953 ata_smart_log_directory smartlogdir_buf, gplogdir_buf; 02954 const ata_smart_log_directory * smartlogdir = 0, * gplogdir = 0; 02955 02956 // Read SMART Log directory 02957 if (need_smart_logdir) { 02958 if (firmwarebugs.is_set(BUG_NOLOGDIR)) 02959 smartlogdir = fake_logdir(&smartlogdir_buf, options); 02960 else if (ataReadLogDirectory(device, &smartlogdir_buf, false)) { 02961 pout("Read SMART Log Directory failed: %s\n\n", device->get_errmsg()); 02962 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02963 } 02964 else 02965 smartlogdir = &smartlogdir_buf; 02966 } 02967 02968 // Read GP Log directory 02969 if (need_gp_logdir) { 02970 if (firmwarebugs.is_set(BUG_NOLOGDIR)) 02971 gplogdir = fake_logdir(&gplogdir_buf, options); 02972 else if (ataReadLogDirectory(device, &gplogdir_buf, true)) { 02973 pout("Read GP Log Directory failed\n\n"); 02974 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 02975 } 02976 else 02977 gplogdir = &gplogdir_buf; 02978 } 02979 02980 // Print log directories 02981 if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir)) { 02982 if (firmwarebugs.is_set(BUG_NOLOGDIR)) 02983 pout("Log Directories not read due to '-F nologdir' option\n\n"); 02984 else 02985 PrintLogDirectories(gplogdir, smartlogdir); 02986 } 02987 02988 // Print log pages 02989 for (i = 0; i < options.log_requests.size(); i++) { 02990 const ata_log_request & req = options.log_requests[i]; 02991 02992 const char * type; 02993 unsigned max_nsectors; 02994 if (req.gpl) { 02995 type = "General Purpose"; 02996 max_nsectors = GetNumLogSectors(gplogdir, req.logaddr, true); 02997 } 02998 else { 02999 type = "SMART"; 03000 max_nsectors = GetNumLogSectors(smartlogdir, req.logaddr, false); 03001 } 03002 03003 if (!max_nsectors) { 03004 if (!is_permissive()) { 03005 pout("%s Log 0x%02x does not exist (override with '-T permissive' option)\n", type, req.logaddr); 03006 continue; 03007 } 03008 max_nsectors = req.page+1; 03009 } 03010 if (max_nsectors <= req.page) { 03011 pout("%s Log 0x%02x has only %u sectors, output skipped\n", type, req.logaddr, max_nsectors); 03012 continue; 03013 } 03014 03015 unsigned ns = req.nsectors; 03016 if (ns > max_nsectors - req.page) { 03017 if (req.nsectors != ~0U) // "FIRST-max" 03018 pout("%s Log 0x%02x has only %u sectors, output truncated\n", type, req.logaddr, max_nsectors); 03019 ns = max_nsectors - req.page; 03020 } 03021 03022 // SMART log don't support sector offset, start with first sector 03023 unsigned offs = (req.gpl ? 0 : req.page); 03024 03025 raw_buffer log_buf((offs + ns) * 512); 03026 bool ok; 03027 if (req.gpl) 03028 ok = ataReadLogExt(device, req.logaddr, 0x00, req.page, log_buf.data(), ns); 03029 else 03030 ok = ataReadSmartLog(device, req.logaddr, log_buf.data(), offs + ns); 03031 if (!ok) 03032 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03033 else 03034 PrintLogPages(type, log_buf.data() + offs*512, req.logaddr, req.page, ns, max_nsectors); 03035 } 03036 03037 // Print SMART Extendend Comprehensive Error Log 03038 bool do_smart_error_log = options.smart_error_log; 03039 if (options.smart_ext_error_log) { 03040 bool ok = false; 03041 unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true); 03042 if (!nsectors) 03043 pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n\n"); 03044 else if (nsectors >= 256) 03045 pout("SMART Extended Comprehensive Error Log size %u not supported\n\n", nsectors); 03046 else { 03047 raw_buffer log_03_buf(nsectors * 512); 03048 ata_smart_exterrlog * log_03 = (ata_smart_exterrlog *)log_03_buf.data(); 03049 if (!ataReadExtErrorLog(device, log_03, nsectors, firmwarebugs)) { 03050 pout("Read SMART Extended Comprehensive Error Log failed\n\n"); 03051 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03052 } 03053 else { 03054 if (PrintSmartExtErrorLog(log_03, nsectors, options.smart_ext_error_log)) 03055 returnval |= FAILERR; 03056 ok = true; 03057 } 03058 } 03059 03060 if (!ok) { 03061 if (options.retry_error_log) 03062 do_smart_error_log = true; 03063 else if (!do_smart_error_log) 03064 pout("Try '-l [xerror,]error' to read traditional SMART Error Log\n"); 03065 } 03066 } 03067 03068 // Print SMART error log 03069 if (do_smart_error_log) { 03070 if (!( ( smartlogdir && GetNumLogSectors(smartlogdir, 0x01, false)) 03071 || (!smartlogdir && isSmartErrorLogCapable(&smartval, &drive) ) 03072 || is_permissive() )) { 03073 pout("SMART Error Log not supported\n\n"); 03074 } 03075 else { 03076 ata_smart_errorlog smarterror; memset(&smarterror, 0, sizeof(smarterror)); 03077 if (ataReadErrorLog(device, &smarterror, firmwarebugs)) { 03078 pout("Read SMART Error Log failed: %s\n\n", device->get_errmsg()); 03079 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03080 } 03081 else { 03082 // quiet mode is turned on inside PrintSmartErrorLog() 03083 if (PrintSmartErrorlog(&smarterror, firmwarebugs)) 03084 returnval|=FAILERR; 03085 print_off(); 03086 } 03087 } 03088 } 03089 03090 // Print SMART Extendend Self-test Log 03091 bool do_smart_selftest_log = options.smart_selftest_log; 03092 if (options.smart_ext_selftest_log) { 03093 bool ok = false; 03094 unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true); 03095 if (!nsectors) 03096 pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n\n"); 03097 else if (nsectors >= 256) 03098 pout("SMART Extended Self-test Log size %u not supported\n\n", nsectors); 03099 else { 03100 raw_buffer log_07_buf(nsectors * 512); 03101 ata_smart_extselftestlog * log_07 = (ata_smart_extselftestlog *)log_07_buf.data(); 03102 if (!ataReadExtSelfTestLog(device, log_07, nsectors)) { 03103 pout("Read SMART Extended Self-test Log failed\n\n"); 03104 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03105 } 03106 else { 03107 if (PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log)) 03108 returnval |= FAILLOG; 03109 ok = true; 03110 } 03111 } 03112 03113 if (!ok) { 03114 if (options.retry_selftest_log) 03115 do_smart_selftest_log = true; 03116 else if (!do_smart_selftest_log) 03117 pout("Try '-l [xselftest,]selftest' to read traditional SMART Self Test Log\n"); 03118 } 03119 } 03120 03121 // Print SMART self-test log 03122 if (do_smart_selftest_log) { 03123 if (!( ( smartlogdir && GetNumLogSectors(smartlogdir, 0x06, false)) 03124 || (!smartlogdir && isSmartTestLogCapable(&smartval, &drive) ) 03125 || is_permissive() )) { 03126 pout("SMART Self-test Log not supported\n\n"); 03127 } 03128 else { 03129 ata_smart_selftestlog smartselftest; memset(&smartselftest, 0, sizeof(smartselftest)); 03130 if (ataReadSelfTestLog(device, &smartselftest, firmwarebugs)) { 03131 pout("Read SMART Self-test Log failed: %s\n\n", device->get_errmsg()); 03132 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03133 } 03134 else { 03135 print_on(); 03136 if (ataPrintSmartSelfTestlog(&smartselftest, !printing_is_switchable, firmwarebugs)) 03137 returnval |= FAILLOG; 03138 print_off(); 03139 pout("\n"); 03140 } 03141 } 03142 } 03143 03144 // Print SMART selective self-test log 03145 if (options.smart_selective_selftest_log) { 03146 ata_selective_self_test_log log; 03147 03148 if (!isSupportSelectiveSelfTest(&smartval)) 03149 pout("Selective Self-tests/Logging not supported\n\n"); 03150 else if(ataReadSelectiveSelfTestLog(device, &log)) { 03151 pout("Read SMART Selective Self-test Log failed: %s\n\n", device->get_errmsg()); 03152 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03153 } 03154 else { 03155 print_on(); 03156 // If any errors were found, they are logged in the SMART Self-test log. 03157 // So there is no need to print the Selective Self Test log in silent 03158 // mode. 03159 if (!printing_is_switchable) 03160 ataPrintSelectiveSelfTestLog(&log, &smartval); 03161 print_off(); 03162 pout("\n"); 03163 } 03164 } 03165 03166 // SCT commands 03167 bool sct_ok = false; 03168 if (need_sct_support) { 03169 if (!isSCTCapable(&drive)) { 03170 pout("SCT Commands not supported\n\n"); 03171 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03172 } 03173 else 03174 sct_ok = true; 03175 } 03176 03177 // Print SCT status and temperature history table 03178 if (sct_ok && (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int)) { 03179 for (;;) { 03180 if (options.sct_temp_sts || options.sct_temp_hist) { 03181 ata_sct_status_response sts; 03182 ata_sct_temperature_history_table tmh; 03183 if (!options.sct_temp_hist) { 03184 // Read SCT status only 03185 if (ataReadSCTStatus(device, &sts)) { 03186 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03187 break; 03188 } 03189 } 03190 else { 03191 if (!isSCTDataTableCapable(&drive)) { 03192 pout("SCT Data Table command not supported\n\n"); 03193 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03194 break; 03195 } 03196 // Read SCT status and temperature history 03197 if (ataReadSCTTempHist(device, &tmh, &sts)) { 03198 pout("Read SCT Temperature History failed\n\n"); 03199 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03200 break; 03201 } 03202 } 03203 if (options.sct_temp_sts) 03204 ataPrintSCTStatus(&sts); 03205 if (options.sct_temp_hist) 03206 ataPrintSCTTempHist(&tmh); 03207 pout("\n"); 03208 } 03209 if (options.sct_temp_int) { 03210 // Set new temperature logging interval 03211 if (!isSCTFeatureControlCapable(&drive)) { 03212 pout("SCT Feature Control command not supported\n\n"); 03213 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03214 break; 03215 } 03216 if (ataSetSCTTempInterval(device, options.sct_temp_int, options.sct_temp_int_pers)) { 03217 pout("Write Temperature Logging Interval failed\n\n"); 03218 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03219 break; 03220 } 03221 pout("Temperature Logging Interval set to %u minute%s (%s)\n", 03222 options.sct_temp_int, (options.sct_temp_int == 1 ? "" : "s"), 03223 (options.sct_temp_int_pers ? "persistent" : "volatile")); 03224 } 03225 break; 03226 } 03227 } 03228 03229 // SCT Error Recovery Control 03230 if (sct_ok && (options.sct_erc_get || options.sct_erc_set)) { 03231 if (!isSCTErrorRecoveryControlCapable(&drive)) { 03232 pout("SCT Error Recovery Control command not supported\n\n"); 03233 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03234 } 03235 else { 03236 bool sct_erc_get = options.sct_erc_get; 03237 if (options.sct_erc_set) { 03238 // Set SCT Error Recovery Control 03239 if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime ) 03240 || ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime)) { 03241 pout("SCT (Set) Error Recovery Control command failed\n"); 03242 if (!( (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70) 03243 || (options.sct_erc_readtime == 0 && options.sct_erc_writetime == 0))) 03244 pout("Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n"); 03245 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03246 sct_erc_get = false; 03247 } 03248 else if (!sct_erc_get) 03249 ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, 03250 options.sct_erc_writetime); 03251 } 03252 03253 if (sct_erc_get) { 03254 // Print SCT Error Recovery Control 03255 unsigned short read_timer, write_timer; 03256 if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer ) 03257 || ataGetSCTErrorRecoveryControltime(device, 2, write_timer)) { 03258 pout("SCT (Get) Error Recovery Control command failed\n"); 03259 if (options.sct_erc_set) { 03260 pout("The previous SCT (Set) Error Recovery Control command succeeded\n"); 03261 ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, 03262 options.sct_erc_writetime); 03263 } 03264 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03265 } 03266 else 03267 ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer); 03268 } 03269 pout("\n"); 03270 } 03271 } 03272 03273 // Print Device Statistics 03274 if (options.devstat_all_pages || options.devstat_ssd_page || !options.devstat_pages.empty()) { 03275 unsigned nsectors = GetNumLogSectors(gplogdir, 0x04, true); 03276 if (!nsectors) 03277 pout("Device Statistics (GP Log 0x04) not supported\n\n"); 03278 else if (!print_device_statistics(device, nsectors, options.devstat_pages, 03279 options.devstat_all_pages, options.devstat_ssd_page)) 03280 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03281 } 03282 03283 // Print SATA Phy Event Counters 03284 if (options.sataphy) { 03285 unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true); 03286 // Packet interface devices do not provide a log directory, check support bit 03287 if (!nsectors && (drive.words047_079[76-47] & 0x0401) == 0x0400) 03288 nsectors = 1; 03289 if (!nsectors) 03290 pout("SATA Phy Event Counters (GP Log 0x11) not supported\n\n"); 03291 else if (nsectors != 1) 03292 pout("SATA Phy Event Counters with %u sectors not supported\n\n", nsectors); 03293 else { 03294 unsigned char log_11[512] = {0, }; 03295 unsigned char features = (options.sataphy_reset ? 0x01 : 0x00); 03296 if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1)) { 03297 pout("Read SATA Phy Event Counters failed\n\n"); 03298 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03299 } 03300 else 03301 PrintSataPhyEventCounters(log_11, options.sataphy_reset); 03302 } 03303 } 03304 03305 // Set to standby (spindown) mode 03306 // (Above commands may spinup drive) 03307 if (options.set_standby_now) { 03308 if (!ata_nodata_command(device, ATA_STANDBY_IMMEDIATE)) { 03309 pout("ATA STANDBY IMMEDIATE command failed: %s\n", device->get_errmsg()); 03310 returnval |= FAILSMART; 03311 } 03312 else 03313 pout("Device placed in STANDBY mode\n"); 03314 } 03315 03316 // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN 03317 if (!smart_val_ok || options.smart_selftest_type == -1) 03318 return returnval; 03319 03320 pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); 03321 // if doing a self-test, be sure it's supported by the hardware 03322 switch (options.smart_selftest_type) { 03323 case OFFLINE_FULL_SCAN: 03324 if (!isSupportExecuteOfflineImmediate(&smartval)){ 03325 pout("Execute Offline Immediate function not supported\n\n"); 03326 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03327 } 03328 break; 03329 case ABORT_SELF_TEST: 03330 case SHORT_SELF_TEST: 03331 case EXTEND_SELF_TEST: 03332 case SHORT_CAPTIVE_SELF_TEST: 03333 case EXTEND_CAPTIVE_SELF_TEST: 03334 if (!isSupportSelfTest(&smartval)){ 03335 pout("Self-test functions not supported\n\n"); 03336 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03337 } 03338 break; 03339 case CONVEYANCE_SELF_TEST: 03340 case CONVEYANCE_CAPTIVE_SELF_TEST: 03341 if (!isSupportConveyanceSelfTest(&smartval)){ 03342 pout("Conveyance Self-test functions not supported\n\n"); 03343 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03344 } 03345 break; 03346 case SELECTIVE_SELF_TEST: 03347 case SELECTIVE_CAPTIVE_SELF_TEST: 03348 if (!isSupportSelectiveSelfTest(&smartval)){ 03349 pout("Selective Self-test functions not supported\n\n"); 03350 failuretest(MANDATORY_CMD, returnval|=FAILSMART); 03351 } 03352 break; 03353 default: 03354 break; // Vendor specific type 03355 } 03356 03357 // Now do the test. Note ataSmartTest prints its own error/success 03358 // messages 03359 if (ataSmartTest(device, options.smart_selftest_type, options.smart_selftest_force, 03360 options.smart_selective_args, &smartval, sizes.sectors )) 03361 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03362 else { 03363 // Tell user how long test will take to complete. This is tricky 03364 // because in the case of an Offline Full Scan, the completion 03365 // timer is volatile, and needs to be read AFTER the command is 03366 // given. If this will interrupt the Offline Full Scan, we don't 03367 // do it, just warn user. 03368 if (options.smart_selftest_type == OFFLINE_FULL_SCAN) { 03369 if (isSupportOfflineAbort(&smartval)) 03370 pout("Note: giving further SMART commands will abort Offline testing\n"); 03371 else if (ataReadSmartValues(device, &smartval)){ 03372 pout("Read SMART Data failed: %s\n\n", device->get_errmsg()); 03373 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 03374 } 03375 } 03376 03377 // Now say how long the test will take to complete 03378 int timewait = TestTime(&smartval, options.smart_selftest_type); 03379 if (timewait) { 03380 time_t t=time(NULL); 03381 if (options.smart_selftest_type == OFFLINE_FULL_SCAN) { 03382 t+=timewait; 03383 pout("Please wait %d seconds for test to complete.\n", (int)timewait); 03384 } else { 03385 t+=timewait*60; 03386 pout("Please wait %d minutes for test to complete.\n", (int)timewait); 03387 } 03388 pout("Test will complete after %s\n", ctime(&t)); 03389 03390 if ( options.smart_selftest_type != SHORT_CAPTIVE_SELF_TEST 03391 && options.smart_selftest_type != EXTEND_CAPTIVE_SELF_TEST 03392 && options.smart_selftest_type != CONVEYANCE_CAPTIVE_SELF_TEST 03393 && options.smart_selftest_type != SELECTIVE_CAPTIVE_SELF_TEST ) 03394 pout("Use smartctl -X to abort test.\n"); 03395 } 03396 } 03397 03398 return returnval; 03399 }
1.7.4