15#define __STDC_FORMAT_MACROS 1
40#define SMART_CYL_LOW 0x4F
41#define SMART_CYL_HI 0xC2
47#define SRET_STATUS_HI_EXCEEDED 0x2C
48#define SRET_STATUS_MID_EXCEEDED 0xF4
56 unsigned char id = (!offline ? 197 : 198);
60 else if (def.
name.empty() || (
id == 198 && def.
name ==
"Offline_Scan_UNC_SectCt"))
74const char *SelfTestFailureCodeName(
unsigned char which){
82 return "Servo_Random";
86 return "Handling_Damage";
129 {
"9,halfminutes" ,
"9,halfmin2hour,Power_On_Half_Minutes"},
130 {
"9,minutes" ,
"9,min2hour,Power_On_Minutes"},
131 {
"9,seconds" ,
"9,sec2hour,Power_On_Seconds"},
132 {
"9,temp" ,
"9,tempminmax,Temperature_Celsius"},
133 {
"192,emergencyretractcyclect" ,
"192,raw48,Emerg_Retract_Cycle_Ct"},
134 {
"193,loadunload" ,
"193,raw24/raw24"},
135 {
"194,10xCelsius" ,
"194,temp10x,Temperature_Celsius_x10"},
136 {
"194,unknown" ,
"194,raw48,Unknown_Attribute"},
137 {
"197,increasing" ,
"197,raw48+,Total_Pending_Sectors"},
138 {
"198,offlinescanuncsectorct" ,
"198,raw48,Offline_Scan_UNC_SectCt"},
139 {
"198,increasing" ,
"198,raw48+,Total_Offl_Uncorrectabl"},
140 {
"200,writeerrorcount" ,
"200,raw48,Write_Error_Count"},
141 {
"201,detectedtacount" ,
"201,raw48,Detected_TA_Count"},
142 {
"220,temp" ,
"220,tempminmax,Temperature_Celsius"},
162 int len = strlen(opt);
163 int id = 0, n1 = -1, n2 = -1;
164 char fmtname[32+1], attrname[32+1], hddssd[3+1];
165 attrname[0] = hddssd[0] = 0;
169 if (!( sscanf(opt,
"N,%32[^,]%n,%32[^,]%n", fmtname, &n1, attrname, &n2) >= 1
170 && (n1 == len || n2 == len)))
176 if (!( sscanf(opt,
"%d,%32[^,]%n,%32[^,]%n,%3[DHS]%n",
177 &
id, fmtname, &n1, attrname, &n2, hddssd, &n3) >= 2
178 && 1 <=
id &&
id <= 255
179 && ( n1 == len || n2 == len
187 if (fmtname[strlen(fmtname)-1] ==
'+') {
188 fmtname[strlen(fmtname)-1] = 0;
193 char byteorder[8+1] =
"";
194 if (strchr(fmtname,
':')) {
199 if (!( sscanf(fmtname,
"%*[^:]%n:%8[012345rvwz]%n", &n1, byteorder, &n2) >= 1
200 && n2 == (
int)strlen(fmtname)))
203 if (strchr(byteorder,
'v'))
205 if (strchr(byteorder,
'w'))
224 if (!strcmp(hddssd,
"HDD"))
226 else if (!strcmp(hddssd,
"SSD"))
235 if (defs[i].priority >= priority)
238 defs[i].name = attrname;
239 defs[i].priority = priority;
240 defs[i].raw_format = format;
241 defs[i].flags =
flags;
242 snprintf(defs[i].byteorder,
sizeof(defs[i].byteorder),
"%s", byteorder);
245 else if (defs[
id].priority <= priority) {
248 defs[
id].name = attrname;
249 defs[
id].raw_format = format;
250 defs[
id].priority = priority;
252 snprintf(defs[
id].byteorder,
sizeof(defs[
id].byteorder),
"%s", byteorder);
267 s +=
strprintf(
"%s\tN,%s[:012345rvwz][,ATTR_NAME]",
279 if (!strcmp(opt,
"none"))
281 else if (!strcmp(opt,
"nologdir"))
283 else if (!strcmp(opt,
"samsung"))
285 else if (!strcmp(opt,
"samsung2"))
287 else if (!strcmp(opt,
"samsung3"))
289 else if (!strcmp(opt,
"xerrorlba"))
299 return "none, nologdir, samsung, samsung2, samsung3, xerrorlba";
306 *location=*(location+1);
314 *location=*(location+3);
323 *location=*(location+7);
326 *(location+1)=*(location+6);
338 {
swapx(&x);
return x; }
340#define SWAPV(x) ((x) = get_swapx_val(x))
345 unsigned char sum = 0;
347 for (i = 0; i <
sizeof(
id->serial_no); i++) {
348 sum +=
id->serial_no[i]; sum -=
id->serial_no[i] =
'X';
350 unsigned char *
b = (
unsigned char *)
id;
351 for (i = 2*108; i < 2*112; i++) {
352 sum +=
b[i]; sum -=
b[i] = 0x00;
356 SWAPV(
id->words088_255[255-88]);
357 if ((
id->words088_255[255-88] & 0x00ff) == 0x00a5)
358 id->words088_255[255-88] += sum << 8;
360 SWAPV(
id->words088_255[255-88]);
366 "SMART AUTOMATIC ATTRIBUTE SAVE",
367 "SMART IMMEDIATE OFFLINE",
368 "SMART AUTO OFFLINE",
370 "SMART STATUS CHECK",
371 "SMART READ ATTRIBUTE VALUES",
372 "SMART READ ATTRIBUTE THRESHOLDS",
375 "IDENTIFY PACKET DEVICE",
378 "WARNING (UNDEFINED COMMAND -- CONTACT DEVELOPERS AT " PACKAGE_BUGREPORT
")\n"
387 snprintf(buf,
sizeof(buf),
"0x%02x", r.
val());
394 pout(
"%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix,
403 pout(
"%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix,
410 pout(
"\n===== [%s] DATA START (BASE-16) =====\n", name);
411 for (
int i=0; i<512; i+=16, p+=16)
412#define
P(n) (
' ' <= p[n] && p[n] <=
'~' ? (int)p[n] :
'.')
414 pout(
"%03d-%03d: %02x %02x %02x %02x %02x %02x %02x %02x "
415 "%02x %02x %02x %02x %02x %02x %02x %02x"
416 " |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c|"
419 p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
420 p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15],
421 P( 0),
P( 1),
P( 2),
P( 3),
P( 4),
P( 5),
P( 6),
P( 7),
422 P( 8),
P( 9),
P(10),
P(11),
P(12),
P(13),
P(14),
P(15),
425 pout(
"===== [%s] DATA END (512 Bytes) =====\n\n", name);
454 pout(
" InputParameter=%d\n", select);
459 if ((getsdata || sendsdata) && !
data){
460 pout(
"REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n",
commandstrings[command]);
471 memset(
data,
'\0', 512);
553 pout(
"Unrecognized command %d in smartcommandhandler()\n"
554 "Please contact " PACKAGE_BUGREPORT
"\n", command);
570 if (start_usec >= 0) {
572 if (duration_usec > 0)
573 pout(
" [Duration: %.6fs]\n", duration_usec / 1000000.0);
579 if (ok)
switch (command) {
589 pout(
"CHECK POWER MODE: incomplete response, ATA output registers missing\n");
606 pout(
"SMART STATUS RETURN: half healthy response sequence, "
607 "probable SAT/USB truncation\n");
611 pout(
"SMART STATUS RETURN: half unhealthy response sequence, "
612 "probable SAT/USB truncation\n");
615 device->
set_err(ENOSYS,
"Incomplete response, ATA output registers missing");
620 pout(
"SMART Status command failed\n");
621 pout(
"Please get assistance from %s\n", PACKAGE_URL);
622 pout(
"Register values returned from SMART Status command are:\n");
624 device->
set_err(ENOSYS,
"Invalid ATA output register values");
638 pout(
"REPORT-IOCTL: Device=%s Command=%s returned %d errno=%d [%s]\n",
642 pout(
"REPORT-IOCTL: Device=%s Command=%s returned %d\n",
648 pout(
"Sector Count Register (BASE-16): %02x\n", (
unsigned char)(*
data));
665 if (!(
id->words047_079[49-47] & 0x0200))
669 unsigned lba28 = (unsigned)
id->words047_079[61-47] << 16
670 | (
unsigned)
id->words047_079[60-47] ;
674 if ((
id->command_set_2 & 0xc400) == 0x4400)
675 lba48 = (uint64_t)
id->words088_255[103-88] << 48
676 | (uint64_t)
id->words088_255[102-88] << 32
677 | (uint64_t)
id->words088_255[101-88] << 16
678 | (uint64_t)
id->words088_255[100-88] ;
681 if (!(lba28 || lba48))
687 unsigned short word106 =
id->words088_255[106-88];
688 if ((word106 & 0xc000) == 0x4000) {
690 if (word106 & 0x1000)
693 ((
id->words088_255[118-88] << 16) |
id->words088_255[117-88]) << 1;
695 if (word106 & 0x2000)
699 unsigned short word209 =
id->words088_255[209-88];
700 if ((word209 & 0xc000) == 0x4000)
718 unsigned char sum = 0;
719 for (
int i = 0; i < 512; i++)
720 sum += ((
const unsigned char *)
data)[i];
726static void swapbytes(
char * out,
const char * in,
size_t n)
728 for (
size_t i = 0; i < n; i += 2) {
735static void trim(
char * out,
const char * in)
740 for (i = 0; in[i]; i++)
741 if (!isspace((
int)in[i])) {
753 for (i = strlen(in)-1; i >= first && isspace((
int)in[i]); i--)
757 strncpy(out, in+first, last-first+1);
758 out[last-first+1] =
'\0';
778 unsigned char result;
792 if (sector_count >= 0)
805 if (sector_count >= 0)
818 unsigned char * raw_buf )
835 for (i = 0; i <
sizeof(buf->
serial_no)-1; i += 2)
837 for (i = 0; i <
sizeof(buf->
fw_rev)-1; i += 2)
839 for (i = 0; i <
sizeof(buf->
model)-1; i += 2)
845 memcpy(raw_buf, buf,
sizeof(*buf));
848 unsigned char * rawbyte = (
unsigned char *)buf;
849 if (rawbyte[512-2] == 0xa5 &&
checksum(rawbyte))
858 for (i=80; i<=87; i++)
859 swap2((
char *)(rawbyte+2*i));
860 for (i=0; i<168; i++)
885 if (!packet && rawbyte[1] == 0x84 && rawbyte[0] == 0x8a)
889 if (rawbyte[1] & 0x80)
890 return 1+(rawbyte[1] & 0x1f);
903 unsigned short word087 =
id->csf_default;
904 if ((word087 & 0xc100) != 0x4100)
907 unsigned short word108 =
id->words088_255[108-88];
908 unsigned short word109 =
id->words088_255[109-88];
909 unsigned short word110 =
id->words088_255[110-88];
910 unsigned short word111 =
id->words088_255[111-88];
912 oui = ((word108 & 0x0fff) << 12) | (word109 >> 4);
913 unique_id = ((uint64_t)(word109 & 0xf) << 32)
914 | (
unsigned)((word110 << 16) | word111);
915 return (word108 >> 12);
924 unsigned short word217 =
id->words088_255[217-88];
925 if (word217 == 0x0000 || word217 == 0xffff)
927 else if (word217 == 0x0001)
929 else if (word217 > 0x0400)
932 return -(int)word217;
942 if ((word83>>14) == 0x01)
944 return word82 & 0x0001;
957 if ((word87>>14) == 0x01)
959 return word85 & 0x0001;
981 swap2((
char *)&(
data->total_time_to_complete_off_line));
982 swap2((
char *)&(
data->smart_capability));
983 SWAPV(
data->extend_test_completion_time_w);
1006 for (
int i = 0; i < 21; i++)
1007 swap2((
char *)&(
data->selftest_struct[i].selftestnumber));
1034 for (i=0; i<21; i++){
1048 for (
unsigned i = 0; i < nsectors; i++) {
1070 for (
unsigned i = 0; i < nsectors; i++) {
1071 SWAPV(log[i].log_desc_index);
1072 for (
unsigned j = 0; j < 19; j++)
1081 unsigned page,
void *
data,
unsigned nsectors)
1092 if (nsectors <= 1) {
1093 pout(
"ATA_WRITE_LOG_EXT (addr=0x%02x, page=%u, n=%u) failed: %s\n",
1094 logaddr, page, nsectors, device->
get_errmsg());
1100 for (
unsigned i = 0; i < nsectors; i++) {
1102 (
char *)
data + 512*i, 1))
1112 unsigned char features,
unsigned page,
1113 void *
data,
unsigned nsectors)
1123 if (nsectors <= 1) {
1124 pout(
"ATA_READ_LOG_EXT (addr=0x%02x:0x%02x, page=%u, n=%u) failed: %s\n",
1125 logaddr, features, page, nsectors, device->
get_errmsg());
1131 for (
unsigned i = 0; i < nsectors; i++) {
1134 (
char *)
data + 512*i, 1))
1144 void *
data,
unsigned nsectors)
1219 pout(
"Disk size is unknown, unable to check selective self-test spans\n");
1225 unsigned char *ptr=(
unsigned char *)
data;
1227 pout(
"SMART Read Selective Self-test Log failed: %s\n", device->
get_errmsg());
1228 pout(
"Since Read failed, will not attempt to WRITE Selective Self-test Log\n");
1233 data->logversion = 1;
1238 pout(
"SMART Selective or other Self-test in progress\n");
1247 uint64_t end = args.
span[i].
end;
1251 pout(
"Continue Selective Self-Test: Redo last span\n");
1255 pout(
"Continue Selective Self-Test: Start next span\n");
1262 && prev_args && i < prev_args->num_spans
1263 && !
data->span[i].start && !
data->span[i].end) {
1275 start =
data->span[i].start;
1277 end--; end += start;
1280 end =
data->span[i].end;
1283 if (
data->span[i].end == 0) {
1284 start = end = 0;
break;
1286 start =
data->span[i].end + 1;
1287 if (start >= num_sectors)
1290 end--; end += start;
1293 uint64_t oldsize =
data->span[i].end -
data->span[i].start + 1;
1294 end = start + oldsize - 1;
1295 if (end >= num_sectors) {
1297 uint64_t spans = (num_sectors + oldsize-1) / oldsize;
1298 uint64_t newsize = (num_sectors + spans-1) / spans;
1299 uint64_t newstart = num_sectors - newsize, newend = num_sectors - 1;
1300 pout(
"Span %d changed from %" PRIu64
"-%" PRIu64
" (%" PRIu64
" sectors)\n",
1301 i, start, end, oldsize);
1302 pout(
" to %" PRIu64
"-%" PRIu64
" (%" PRIu64
" sectors) (%" PRIu64
" spans)\n",
1303 newstart, newend, newsize, spans);
1304 start = newstart; end = newend;
1309 pout(
"ataWriteSelectiveSelfTestLog: Invalid mode %d\n", mode);
1313 if (start < num_sectors && num_sectors <= end) {
1314 if (end != ~(uint64_t)0)
1315 pout(
"Size of self-test span %d decreased according to disk size\n", i);
1316 end = num_sectors - 1;
1318 if (!(start <= end && end < num_sectors)) {
1319 pout(
"Invalid selective self-test span %d: %" PRIu64
"-%" PRIu64
" (%" PRIu64
" sectors)\n",
1320 i, start, end, num_sectors);
1341 data->currentspan=0;
1346 data->flags &= ~SELECTIVE_FLAG_DOSCAN;
1361 unsigned char cksum=0;
1362 for (i=0; i<512; i++)
1366 data->checksum=cksum;
1371 for (
int b = 0;
b < 5;
b++) {
1383 pout(
"Write Selective Self-test Log failed: %s\n", device->
get_errmsg());
1396 swap2((
char *)&(
data->ata_error_count));
1400 for (
int i = 0; i < 5; i++){
1402 for (
int j = 0; j < 5; j++)
1405 swap4((
char *)&(
data->errorlog_struct[i].commands[j].timestamp));
1408 swap2((
char *)&(
data->errorlog_struct[i].error_struct.timestamp));
1417 swap2((
char *)&(
data->ata_error_count));
1449 swap2((
char *)&(
data->ata_error_count));
1452 for (i=0; i<5; i++){
1456 swap4((
char *)&(
data->errorlog_struct[i].commands[j].timestamp));
1458 swap2((
char *)&(
data->errorlog_struct[i].error_struct.timestamp));
1472 cmd.lba_mid_register_hi = org.lba_high_register;
1473 cmd.lba_low_register_hi = org.lba_mid_register_hi;
1474 cmd.lba_high_register = org.lba_mid_register;
1475 cmd.lba_mid_register = org.lba_low_register_hi;
1480 for (
unsigned i = 0; i < nsectors; i++) {
1481 for (
int ei = 0; ei < 4; ei++) {
1484 for (
int ci = 0; ci < 5; ci++)
1494 if (!
ataReadLogExt(device, 0x03, 0x00, page, log, nsectors))
1502 for (
unsigned i = 0; i < nsectors; i++) {
1503 for (
unsigned j = 0; j < 4; j++) {
1504 for (
unsigned k = 0; k < 5; k++)
1505 SWAPV(log[i].error_logs[j].commands[k].timestamp);
1506 SWAPV(log[i].error_logs[j].error.timestamp);
1615 char cmdmsg[128];
const char *type, *captive;
1616 int cap, retval, select=0;
1630 type=
"Short self-test";
1632 type=
"Extended self-test";
1634 type=
"Conveyance self-test";
1636 type=
"Selective self-test";
1643 pout(
"Can't start self-test without aborting current test (%d0%% remaining),\n"
1644 "%srun 'smartctl -X' to abort test.\n",
1646 (!select ?
"add '-t force' option to override, or " :
""));
1658 pout(
"Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");
1664 snprintf(cmdmsg,
sizeof(cmdmsg),
"Abort SMART off-line mode self-test routine");
1666 snprintf(cmdmsg,
sizeof(cmdmsg),
"SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype);
1668 snprintf(cmdmsg,
sizeof(cmdmsg),
"Execute SMART %s routine immediately in %s mode", type, captive);
1669 pout(
"Sending command: \"%s\".\n",cmdmsg);
1673 pout(
"SPAN STARTING_LBA ENDING_LBA\n");
1674 for (i = 0; i < selargs_io.
num_spans; i++)
1675 pout(
" %d %20" PRId64
" %20" PRId64
"\n", i,
1682 if (!(cap && device->
get_errno() == EIO)) {
1683 pout(
"Command \"%s\" failed: %s\n", cmdmsg, device->
get_errmsg());
1690 pout(
"Self-testing aborted!\n");
1692 pout(
"Drive command \"%s\" successful.\n", cmdmsg);
1694 pout(
"Testing has begun%s.\n", (force ?
" (previous test aborted)" :
""));
1704 return (
int)
data->total_time_to_complete_off_line;
1707 return (
int)
data->short_test_completion_time;
1710 if (
data->extend_test_completion_time_b == 0xff
1711 &&
data->extend_test_completion_time_w != 0x0000
1712 &&
data->extend_test_completion_time_w != 0xffff)
1713 return data->extend_test_completion_time_w;
1715 return data->extend_test_completion_time_b;
1718 return (
int)
data->conveyance_test_completion_time;
1738 if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x01))
1741 if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x01))
1745 return !!(
data->errorlog_capability & 0x01);
1757 if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x02))
1760 if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x02))
1765 return !!(
data->errorlog_capability & 0x01);
1778 if ((word84>>14) == 0x01)
1781 return !!(word84 & (0x01 << 5));
1786 if ((word87>>14) == 0x01)
1789 return !!(word87 & (0x01 << 5));
1800 unsigned char * threshval )
1813 if (thresholds[i].
id != attr.
id) {
1815 for (i = 0; thresholds[i].
id != attr.
id; ) {
1821 unsigned char threshold = thresholds[i].
threshold;
1825 *threshval = threshold;
1835 if (attr.
current <= threshold)
1858 byteorder =
"543210wv";
break;
1863 byteorder =
"r543210";
break;
1865 byteorder =
"543210";
break;
1870 uint64_t rawvalue = 0;
1871 for (
int i = 0; byteorder[i]; i++) {
1873 switch (byteorder[i]) {
1874 case '0':
b = attr.
raw[0];
break;
1875 case '1':
b = attr.
raw[1];
break;
1876 case '2':
b = attr.
raw[2];
break;
1877 case '3':
b = attr.
raw[3];
break;
1878 case '4':
b = attr.
raw[4];
break;
1879 case '5':
b = attr.
raw[5];
break;
1880 case 'r':
b = attr.
reserv;
break;
1882 case 'w':
b = attr.
worst;
break;
1883 default :
b = 0;
break;
1885 rawvalue <<= 8; rawvalue |=
b;
1906 int t1 = (
signed char)ut1, t2 = (
signed char)ut2;
1908 int tx = t1; t1 = t2; t2 = tx;
1911 if ( -60 <= t1 && t1 <= t && t <= t2 && t2 <= 120
1912 && !(t1 == -1 && t2 <= 0) ) {
1927 unsigned char raw[6];
1928 raw[0] = (
unsigned char) rawvalue;
1929 raw[1] = (
unsigned char)(rawvalue >> 8);
1930 raw[2] = (
unsigned char)(rawvalue >> 16);
1931 raw[3] = (
unsigned char)(rawvalue >> 24);
1932 raw[4] = (
unsigned char)(rawvalue >> 32);
1933 raw[5] = (
unsigned char)(rawvalue >> 40);
1935 word[0] =
raw[0] | (
raw[1] << 8);
1936 word[1] =
raw[2] | (
raw[3] << 8);
1937 word[2] =
raw[4] | (
raw[5] << 8);
1958 s =
strprintf(
"%u %u %u", word[2], word[1], word[0]);
1981 if (word[1] || word[2])
1982 s +=
strprintf(
" (%u %u)", word[2], word[1]);
1992 s =
strprintf(
"%u", (
unsigned)(rawvalue & 0x00ffffffULL));
1999 (
unsigned)(rawvalue >> 24), (
unsigned)(rawvalue & 0x00ffffffULL));
2004 (
unsigned)(rawvalue >> 32), (
unsigned)(rawvalue & 0xffffffffULL));
2010 int64_t temp = word[0]+(word[1]<<16);
2011 int64_t tmp1 = temp/60;
2012 int64_t tmp2 = temp%60;
2013 s =
strprintf(
"%" PRIu64
"h+%02" PRIu64
"m", tmp1, tmp2);
2022 int64_t hours = rawvalue/3600;
2023 int64_t minutes = (rawvalue-3600*hours)/60;
2024 int64_t seconds = rawvalue%60;
2025 s =
strprintf(
"%" PRIu64
"h+%02" PRIu64
"m+%02" PRIu64
"s", hours, minutes, seconds);
2032 int64_t hours = rawvalue/120;
2033 int64_t minutes = (rawvalue-120*hours)/2;
2034 s +=
strprintf(
"%" PRIu64
"h+%02" PRIu64
"m", hours, minutes);
2041 unsigned hours = (unsigned)(rawvalue & 0xffffffffULL);
2042 unsigned milliseconds = (unsigned)(rawvalue >> 32);
2043 unsigned seconds = milliseconds / 1000;
2045 hours, seconds / 60, seconds % 60, milliseconds % 1000);
2062 int t = (
signed char)
raw[0];
2068 if (!word[1] && ctw0)
2085 else if ( word[2] < 0x7fff
2100 case 1:
case 2:
case 3:
2101 s =
strprintf(
"%d (Min/Max %d/%d)", t, lo, hi);
2104 s =
strprintf(
"%d (Min/Max %d/%d #%d)", t, lo, hi, word[2]);
2115 s =
strprintf(
"%d.%d", word[0]/10, word[0]%10);
2130 if (!defs[
id].name.empty())
2131 return defs[
id].name;
2134 if (def.
name.empty())
2135 return "Unknown_Attribute";
2137 return "Unknown_SSD_Attribute";
2139 return "Unknown_HDD_Attribute";
2161 for (
int i = 0; i < 4; i++) {
2162 static const unsigned char ids[4] = {194, 190, 9, 220};
2163 unsigned char id = ids[i];
2175 temp = ((
unsigned short)
raw + 5) / 10;
2177 temp = (
unsigned char)
raw;
2178 if (!(0 < temp && temp < 128))
2191 memset(sts, 0,
sizeof(*sts));
2213 pout(
"Unknown SCT Status format version %u, should be 2 or 3.\n", sts->
format_version);
2227 pout(
"Another SCT command is executing, abort Read Data Table\n"
2228 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2235 cmd.action_code = 5;
2236 cmd.function_code = 1;
2253 memset(tmh, 0,
sizeof(*tmh));
2264 pout(
"Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2283 unsigned short state,
bool persistent,
bool set)
2292 pout(
"Another SCT command is executing, abort Feature Control\n"
2293 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2300 cmd.action_code = 4;
2301 cmd.function_code = (set ? 1 : 2);
2302 cmd.feature_code = feature_code;
2304 cmd.option_flags = (persistent ? 0x01 : 0x00);
2330 pout(
"Write SCT (%cet) Feature Control Command failed: %s\n",
2341 pout(
"Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2352 (enable ? 1 : 2), persistent, set);
2359 state, persistent, set);
2372 pout(
"Another SCT command is executing, abort Feature Control\n"
2373 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2380 cmd.action_code = 4;
2381 cmd.function_code = 1;
2382 cmd.feature_code = 3;
2383 cmd.state = interval;
2384 cmd.option_flags = (persistent ? 0x01 : 0x00);
2397 pout(
"Write SCT Feature Control Command failed: %s\n", device->
get_errmsg());
2406 pout(
"Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2415 bool set,
unsigned short & time_limit,
2416 bool power_on,
bool mfg_default)
2425 pout(
"Another SCT command is executing, abort Error Recovery Control\n"
2426 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2433 cmd.action_code = 3;
2437 cmd.function_code = 5;
2438 }
else if (power_on) {
2439 cmd.function_code = (set ? 3 : 4);
2441 cmd.function_code = (set ? 1 : 2);
2443 unsigned short saved_function_code =
cmd.function_code;
2445 cmd.selection_code = type;
2447 cmd.time_limit = time_limit;
2472 pout(
"Write SCT (%cet) Error Recovery Control Command failed: %s\n",
2482 pout(
"Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2492 pout(
"SMART WRITE LOG does not return COUNT and LBA_LOW register\n");
2498 pout(
"SMART WRITE LOG returns COUNT and LBA_LOW register unchanged\n");
2517 bool power_on,
bool mfg_default)
2537 virtual bool is_open()
const;
2539 virtual bool open();
2541 virtual bool close();
2543 virtual bool ata_identify_is_cached()
const;
2558 enum { max_num_commands = 32 };
2569 for (
s += strcspn(
s,
"\r\n"); *
s ==
'\r' || *
s ==
'\n';
s++) {
2570 if (*
s ==
'\r' &&
s[1] ==
'\n')
2589 if (srcmatch.rm_so < 0)
2591 size_t n = srcmatch.rm_eo - srcmatch.rm_so;
2594 memcpy(dest, src + srcmatch.rm_so, n);
2601 if (srcmatch.rm_so < 0)
2603 return atoi(src + srcmatch.rm_so);
2609 m_next_replay_command(0),
2610 m_replay_out_of_sync(false),
2611 m_ata_identify_is_cached(false)
2630 if (strcmp(pathname,
"-"))
2632 pathname =
"<stdin>";
2643 return set_err(ENOENT,
"%s: Unexpected EOF", pathname);
2645 return set_err(EIO,
"%s: Buffer overflow", pathname);
2649 static const char pattern[] =
"^"
2651 "REPORT-IOCTL: DeviceF?D?=[^ ]+ Command=([A-Z ]*[A-Z])"
2653 "( InputParameter=([0-9]+))?"
2655 "( returned (-?[0-9]+)( errno=([0-9]+)[^\r\n]*)?)"
2659 "===== \\[([A-Z ]*[A-Z])\\] DATA START "
2661 " *(En|Dis)abled status cached by OS, "
2668 const char * errmsg = 0;
2669 int i = -1, state = 0, lineno = 1;
2670 for (
const char * line =
buffer; *line; line =
nextline(line, lineno)) {
2672 if (!(line[0] ==
'R' || line[0] ==
'=' || line[0] ==
' '))
2674 const int nmatch = 1+11;
2683 errmsg =
"Unknown ATA command name";
break;
2685 if (
match[7].rm_so < 0) {
2687 if (!(state == 0 || state == 2)) {
2688 errmsg =
"Missing REPORT-IOCTL result";
break;
2691 errmsg =
"Too many ATA commands";
break;
2700 errmsg =
"Missing REPORT-IOCTL start";
break;
2707 else if (
matchcpy(cmdname,
sizeof(cmdname), line,
match[10])) {
2711 errmsg =
"Unexpected DATA START";
break;
2714 char *
data = (
char *)malloc(512);
2716 for (j = 0; j < 32; j++) {
2718 unsigned u1, u2;
int n1 = -1;
2719 if (!(sscanf(line,
"%3u-%3u: "
2720 "%2x %2x %2x %2x %2x %2x %2x %2x "
2721 "%2x %2x %2x %2x %2x %2x %2x %2x%n",
2723 b+ 0,
b+ 1,
b+ 2,
b+ 3,
b+ 4,
b+ 5,
b+ 6,
b+ 7,
2724 b+ 8,
b+ 9,
b+10,
b+11,
b+12,
b+13,
b+14,
b+15, &n1) == 18
2725 && n1 >= 56 && u1 == j*16 && u2 == j*16+15))
2727 for (
unsigned k = 0; k < 16; k++)
2728 data[j*16+k] =
b[k];
2733 errmsg =
"Incomplete sector hex dump";
break;
2739 else if (
match[11].rm_so > 0) {
2744 if (!(state == 0 || state == 2))
2745 errmsg =
"Missing REPORT-IOCTL result";
2747 if (!errmsg && i < 0)
2748 errmsg =
"No information found";
2756 return set_err(EIO,
"%s(%d): Syntax error: %s", pathname, lineno, errmsg);
2765 pout(
"REPLAY-IOCTL: Warning: commands replayed out of sync\n");
2792 for (
int j = 0; ; j++) {
2794 pout(
"REPLAY-IOCTL: Warning: Command not found\n");
2802 pout(
"REPLAY-IOCTL: Warning: Command #%d is out of sync\n", i+1);
2823 pout(
"REPLAY-IOCTL: Warning: WRITE LOG data does not match\n");
2826 data[0] = (char)0xff;
2840 return new parsed_ata_device(intf, dev_name);
void swap8(char *location)
static const char *const commandstrings[]
static int ataGetSetSCTErrorRecoveryControltime(ata_device *device, unsigned type, bool set, unsigned short &time_limit, bool power_on, bool mfg_default)
bool ata_nodata_command(ata_device *device, unsigned char command, int sector_count)
int ataDisableAutoOffline(ata_device *device)
unsigned char ata_return_temperature_value(const ata_smart_values *data, const ata_vendor_attr_defs &defs)
bool isSmartErrorLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
static void fixsamsungselftestlog(ata_smart_selftestlog *data)
int ataGetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short &time_limit, bool power_on)
bool ataReadSmartLog(ata_device *device, unsigned char logaddr, void *data, unsigned nsectors)
int ata_get_wwn(const ata_identify_device *id, unsigned &oui, uint64_t &unique_id)
static void fixsamsungerrorlog2(ata_smart_errorlog *data)
void swap4(char *location)
static const char * preg(const ata_register &r, char(&buf)[8])
ata_device * get_parsed_ata_device(smart_interface *intf, const char *dev_name)
int ataSmartTest(ata_device *device, int testtype, bool force, const ata_selective_selftest_args &selargs, const ata_smart_values *sv, uint64_t num_sectors)
int ataEnableAutoOffline(ata_device *device)
int ataSmartStatus2(ata_device *device)
static void check_multi_sector_sum(const void *data, unsigned nsectors, const char *msg)
const unsigned num_old_vendor_opts
static int ataGetSetSCTFeatureControl(ata_device *device, unsigned short feature_code, unsigned short state, bool persistent, bool set)
int ataSmartSupport(const ata_identify_device *drive)
int ataDisableAutoSave(ata_device *device)
const unsigned num_format_names
int ata_get_rotation_rate(const ata_identify_device *id)
unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs &defs, bool &increase)
bool ataWriteLogExt(ata_device *device, unsigned char logaddr, unsigned page, void *data, unsigned nsectors)
bool ataReadLogExt(ata_device *device, unsigned char logaddr, unsigned char features, unsigned page, void *data, unsigned nsectors)
bool parse_attribute_def(const char *opt, ata_vendor_attr_defs &defs, ata_vendor_def_prior priority)
int ataEnableAutoSave(ata_device *device)
int ataReadSelfTestLog(ata_device *device, ata_smart_selftestlog *data, firmwarebug_defs firmwarebugs)
std::string ata_format_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
int ataReadSCTTempHist(ata_device *device, ata_sct_temperature_history_table *tmh, ata_sct_status_response *sts)
const char *const map_old_vendor_opts[][2]
#define SRET_STATUS_HI_EXCEEDED
int ata_find_attr_index(unsigned char id, const ata_smart_values &smartval)
int ataReadErrorLog(ata_device *device, ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
void ata_get_size_info(const ata_identify_device *id, ata_size_info &sizes)
int ata_read_identity(ata_device *device, ata_identify_device *buf, bool fix_swapped_id, unsigned char *raw_buf)
static void invalidate_serno(ata_identify_device *id)
static void trim(char *out, const char *in)
int TestTime(const ata_smart_values *data, int testtype)
int ataEnableSmart(ata_device *device)
int smartcommandhandler(ata_device *device, smart_command_set command, int select, char *data)
bool isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
int ataCheckPowerMode(ata_device *device)
int ataGetSetSCTWriteCacheReordering(ata_device *device, bool enable, bool persistent, bool set)
unsigned char checksum(const void *data)
bool ataReadExtSelfTestLog(ata_device *device, ata_smart_extselftestlog *log, unsigned nsectors)
static void prettyprint(const unsigned char *p, const char *name)
static void fix_exterrlog_lba(ata_smart_exterrlog *log, unsigned nsectors)
int ataReadSelectiveSelfTestLog(ata_device *device, struct ata_selective_self_test_log *data)
std::string create_vendor_attribute_arg_list()
static void print_regs(const char *prefix, const ata_in_regs &r, const char *suffix="\n")
bool isSmartTestLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
int ataReadSmartValues(ata_device *device, struct ata_smart_values *data)
static T get_swapx_val(T x)
bool parse_firmwarebug_def(const char *opt, firmwarebug_defs &firmwarebugs)
static bool check_temp_range(int t, unsigned char ut1, unsigned char ut2, int &lo, int &hi)
int ataSetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default)
static int check_temp_word(unsigned word)
unsigned char ata_debugmode
#define SRET_STATUS_MID_EXCEEDED
int ataDoesSmartWork(ata_device *device)
const char * get_valid_firmwarebug_args()
uint64_t ata_get_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
void swap2(char *location)
bool dont_print_serial_number
int ataReadSCTStatus(ata_device *device, ata_sct_status_response *sts)
bool ataReadExtErrorLog(ata_device *device, ata_smart_exterrlog *log, unsigned page, unsigned nsectors, firmwarebug_defs firmwarebugs)
const format_name_entry format_names[]
int ataDisableSmart(ata_device *device)
int ataWriteSelectiveSelfTestLog(ata_device *device, ata_selective_selftest_args &args, const ata_smart_values *sv, uint64_t num_sectors, const ata_selective_selftest_args *prev_args)
int ataSetSCTTempInterval(ata_device *device, unsigned interval, bool persistent)
std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs &defs, int rpm)
const char * atacmds_cpp_cvsid
int ataGetSetSCTWriteCache(ata_device *device, unsigned short state, bool persistent, bool set)
static void swapbytes(char *out, const char *in, size_t n)
int ataReadSmartThresholds(ata_device *device, struct ata_smart_thresholds_pvt *data)
static void fixsamsungerrorlog(ata_smart_errorlog *data)
int ataIsSmartEnabled(const ata_identify_device *drive)
void ata_format_id_string(char *out, const unsigned char *in, int n)
int ataReadLogDirectory(ata_device *device, ata_smart_log_directory *data, bool gpl)
static void fix_exterrlog_lba_cmd(T &cmd)
bool ata_set_features(ata_device *device, unsigned char features, int sector_count)
ata_attr_state ata_get_attr_state(const ata_smart_attribute &attr, int attridx, const ata_smart_threshold_entry *thresholds, const ata_vendor_attr_defs &defs, unsigned char *threshval)
#define ATA_SMART_AUTO_OFFLINE
#define SELECTIVE_FLAG_PENDING
#define ATA_IDENTIFY_DEVICE
#define ATA_SMART_WRITE_LOG_SECTOR
#define ATA_IDENTIFY_PACKET_DEVICE
#define SELECTIVE_SELF_TEST
#define MAX_ATTRIBUTE_NUM
#define OFFLINE_FULL_SCAN
#define SELECTIVE_FLAG_DOSCAN
#define ATA_SMART_READ_VALUES
void checksumwarning(const char *string)
#define ATA_SMART_READ_THRESHOLDS
#define ATA_SMART_READ_LOG_SECTOR
#define ATA_SMART_IMMEDIATE_OFFLINE
#define SELECTIVE_FLAG_ACTIVE
#define ATA_WRITE_LOG_EXT
#define EXTEND_CAPTIVE_SELF_TEST
#define CONVEYANCE_CAPTIVE_SELF_TEST
#define CONVEYANCE_SELF_TEST
#define SHORT_CAPTIVE_SELF_TEST
#define NUMBER_ATA_SMART_ATTRIBUTES
#define SELECTIVE_CAPTIVE_SELF_TEST
#define ATA_SMART_AUTOSAVE
#define ATA_SMART_DISABLE
#define ATA_CHECK_POWER_MODE
parsed_ata_command m_command_table[max_num_commands]
int m_next_replay_command
virtual ~parsed_ata_device()
virtual int ata_command_interface(smart_command_set command, int select, char *data)
Old ATA interface called by ata_pass_through()
virtual bool is_open() const
Return true if device is open.
bool m_ata_identify_is_cached
bool m_replay_out_of_sync
virtual bool ata_identify_is_cached() const
Return true if OS caches ATA identify sector.
virtual bool close()
Close device, return false on error.
virtual bool open()
Open device, return false on error.
Adapter class to implement new ATA pass through old interface.
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)=0
ATA pass through.
ATA register value and info whether it has ever been set.
unsigned char val() const
void set(firmwarebug_t bug)
bool is_set(firmwarebug_t bug) const
Wrapper class for POSIX regex(3) or std::regex Supports copy & assignment and is compatible with STL ...
bool execute(const char *str, unsigned nmatch, match_range *pmatch) const
Return true if substring matches pattern, fill match_range array.
Base class for all devices.
int get_errno() const
Get last error number.
const error_info & get_err() const
Get last error info struct.
const char * get_errmsg() const
Get last error message.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
const char * get_dev_name() const
Get device (path)name.
The platform interface abstraction.
int ata_command_interface(int device, smart_command_set command, int select, char *data)
static bool match(const char *pattern, const char *str)
const ata_vendor_attr_defs & get_default_attr_defs()
static const char * nextline(const char *s, int &lineno)
static bool matchcpy(char *dest, size_t size, const char *src, const regular_expression::match_range &srcmatch)
static int matchtoi(const char *src, const regular_expression::match_range &srcmatch, int defval)
static int name2command(const char *s)
const bool fix_swapped_id
void pout(const char *fmt,...)
smart_command_set command
ATA pass through input parameters.
enum ata_cmd_in::@29 direction
I/O direction.
void set_data_out(const void *buf, unsigned nsectors)
Prepare for 28-bit DATA OUT command.
void set_data_in_48bit(void *buf, unsigned nsectors)
Prepare for 48-bit DATA IN command.
ata_in_regs_48bit in_regs
Input registers.
ata_out_regs_flags out_needed
True if output register value needed.
void set_data_in(void *buf, unsigned nsectors)
Prepare for 28-bit DATA IN command.
ATA pass through output parameters.
ata_out_regs_48bit out_regs
Output registers.
unsigned short major_rev_num
unsigned short words047_079[33]
unsigned short cfs_enable_1
unsigned short words088_255[168]
unsigned short csf_default
unsigned short command_set_2
unsigned short command_set_1
unsigned char serial_no[20]
unsigned short command_set_extension
ata_reg_alias_16 lba_mid_16
ATA Input registers (for 28-bit commands)
ata_register sector_count
ATA Output registers (for 28-bit commands)
ata_register sector_count
bool is_set() const
Return true if any register is set.
unsigned int over_limit_count
unsigned short action_code
unsigned short min_erc_time
unsigned short sct_version
unsigned short format_version
unsigned short ext_status_code
unsigned short function_code
unsigned int under_limit_count
unsigned short smart_status
unsigned short sampling_period
unsigned short format_version
unsigned log_sector_offset
unsigned short error_log_index
ata_smart_exterrlog_error_log error_logs[4]
unsigned short device_error_count
unsigned int lbafirstfailure
unsigned short int timestamp
unsigned char self_test_exec_status
struct ata_smart_attribute vendor_attributes[NUMBER_ATA_SMART_ATTRIBUTES]
ata_attr_raw_format raw_format
ata_attr_raw_format format
Error (number,message) pair.
long long get_timer_usec()
Get microseconds since some unspecified starting point.
std::string strprintf(const char *fmt,...)
void swapx(unsigned short *p)