]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - atacmds.cpp
Stop passing arguments to dh_installinit
[mirror_smartmontools-debian.git] / atacmds.cpp
CommitLineData
832b75ed 1/*
4d59bff9 2 * atacmds.cpp
832b75ed 3 *
6b80b4d2 4 * Home page of code is: http://www.smartmontools.org
832b75ed 5 *
6b80b4d2
JD
6 * Copyright (C) 2002-11 Bruce Allen
7 * Copyright (C) 2008-15 Christian Franke
832b75ed
GG
8 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
9 * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * You should have received a copy of the GNU General Public License
ee38a438 17 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
832b75ed
GG
18 *
19 * This code was originally developed as a Senior Thesis by Michael Cornwell
20 * at the Concurrent Systems Laboratory (now part of the Storage Systems
21 * Research Center), Jack Baskin School of Engineering, University of
22 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
23 *
24 */
25
26#include <stdio.h>
27#include <string.h>
28#include <errno.h>
29#include <stdlib.h>
30#include <ctype.h>
31
32#include "config.h"
33#include "int64.h"
34#include "atacmds.h"
6b80b4d2 35#include "knowndrives.h" // get_default_attr_defs()
832b75ed 36#include "utility.h"
2127e193 37#include "dev_ata_cmd_set.h" // for parsed_ata_device
832b75ed 38
6b80b4d2 39const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 4178 2015-11-23 18:44:27Z chrfranke $"
2127e193 40 ATACMDS_H_CVSID;
832b75ed 41
cfbba5b9
GI
42// Print ATA debug messages?
43unsigned char ata_debugmode = 0;
44
45// Suppress serial number?
46// (also used in scsiprint.cpp)
47bool dont_print_serial_number = false;
48
832b75ed 49
2127e193
GI
50#define SMART_CYL_LOW 0x4F
51#define SMART_CYL_HI 0xC2
52
53// SMART RETURN STATUS yields SMART_CYL_HI,SMART_CYL_LOW to indicate drive
54// is healthy and SRET_STATUS_HI_EXCEEDED,SRET_STATUS_MID_EXCEEDED to
55// indicate that a threshhold exceeded condition has been detected.
56// Those values (byte pairs) are placed in ATA register "LBA 23:8".
57#define SRET_STATUS_HI_EXCEEDED 0x2C
58#define SRET_STATUS_MID_EXCEEDED 0xF4
59
cfbba5b9 60
2127e193
GI
61// Get ID and increase flag of current pending or offline
62// uncorrectable attribute.
bed94269 63unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs,
2127e193
GI
64 bool & increase)
65{
66 unsigned char id = (!offline ? 197 : 198);
e9583e0c
GI
67 const ata_vendor_attr_defs::entry & def = defs[id];
68 if (def.flags & ATTRFLAG_INCREASING)
69 increase = true; // '-v 19[78],increasing' option
70 else if (def.name.empty() || (id == 198 && def.name == "Offline_Scan_UNC_SectCt"))
71 increase = false; // no or '-v 198,offlinescanuncsectorct' option
72 else
73 id = 0; // other '-v 19[78],...' option
2127e193
GI
74 return id;
75}
76
bed94269 77#if 0 // TODO: never used
832b75ed
GG
78// This are the meanings of the Self-test failure checkpoint byte.
79// This is in the self-test log at offset 4 bytes into the self-test
80// descriptor and in the SMART READ DATA structure at byte offset
81// 371. These codes are not well documented. The meanings returned by
82// this routine are used (at least) by Maxtor and IBM. Returns NULL if
83// not recognized. Currently the maximum length is 15 bytes.
84const char *SelfTestFailureCodeName(unsigned char which){
85
86 switch (which) {
87 case 0:
88 return "Write_Test";
89 case 1:
90 return "Servo_Basic";
91 case 2:
92 return "Servo_Random";
93 case 3:
94 return "G-list_Scan";
95 case 4:
96 return "Handling_Damage";
97 case 5:
98 return "Read_Scan";
99 default:
100 return NULL;
101 }
102}
bed94269
GI
103#endif
104
832b75ed 105
bed94269
GI
106// Table of raw print format names
107struct format_name_entry
832b75ed 108{
bed94269
GI
109 const char * name;
110 ata_attr_raw_format format;
111};
112
113const format_name_entry format_names[] = {
114 {"raw8" , RAWFMT_RAW8},
115 {"raw16" , RAWFMT_RAW16},
116 {"raw48" , RAWFMT_RAW48},
117 {"hex48" , RAWFMT_HEX48},
e165493d
GI
118 {"raw56" , RAWFMT_RAW56},
119 {"hex56" , RAWFMT_HEX56},
bed94269
GI
120 {"raw64" , RAWFMT_RAW64},
121 {"hex64" , RAWFMT_HEX64},
122 {"raw16(raw16)" , RAWFMT_RAW16_OPT_RAW16},
123 {"raw16(avg16)" , RAWFMT_RAW16_OPT_AVG16},
e165493d 124 {"raw24(raw8)" , RAWFMT_RAW24_OPT_RAW8},
cfbba5b9
GI
125 {"raw24/raw24" , RAWFMT_RAW24_DIV_RAW24},
126 {"raw24/raw32" , RAWFMT_RAW24_DIV_RAW32},
bed94269
GI
127 {"sec2hour" , RAWFMT_SEC2HOUR},
128 {"min2hour" , RAWFMT_MIN2HOUR},
129 {"halfmin2hour" , RAWFMT_HALFMIN2HOUR},
cfbba5b9 130 {"msec24hour32" , RAWFMT_MSEC24_HOUR32},
bed94269
GI
131 {"tempminmax" , RAWFMT_TEMPMINMAX},
132 {"temp10x" , RAWFMT_TEMP10X},
133};
134
135const unsigned num_format_names = sizeof(format_names)/sizeof(format_names[0]);
136
137// Table to map old to new '-v' option arguments
d2e702cf 138const char * const map_old_vendor_opts[][2] = {
bed94269
GI
139 { "9,halfminutes" , "9,halfmin2hour,Power_On_Half_Minutes"},
140 { "9,minutes" , "9,min2hour,Power_On_Minutes"},
141 { "9,seconds" , "9,sec2hour,Power_On_Seconds"},
142 { "9,temp" , "9,tempminmax,Temperature_Celsius"},
143 {"192,emergencyretractcyclect" , "192,raw48,Emerg_Retract_Cycle_Ct"},
144 {"193,loadunload" , "193,raw24/raw24"},
145 {"194,10xCelsius" , "194,temp10x,Temperature_Celsius_x10"},
146 {"194,unknown" , "194,raw48,Unknown_Attribute"},
147 {"197,increasing" , "197,raw48+,Total_Pending_Sectors"}, // '+' sets flag
e9583e0c 148 {"198,offlinescanuncsectorct" , "198,raw48,Offline_Scan_UNC_SectCt"}, // see also get_unc_attr_id() above
bed94269
GI
149 {"198,increasing" , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag
150 {"200,writeerrorcount" , "200,raw48,Write_Error_Count"},
151 {"201,detectedtacount" , "201,raw48,Detected_TA_Count"},
ee38a438 152 {"220,temp" , "220,tempminmax,Temperature_Celsius"},
bed94269
GI
153};
154
155const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]);
156
157// Parse vendor attribute display def (-v option).
158// Return false on error.
159bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
160 ata_vendor_def_prior priority)
161{
162 // Map old -> new options
163 unsigned i;
164 for (i = 0; i < num_old_vendor_opts; i++) {
165 if (!strcmp(opt, map_old_vendor_opts[i][0])) {
166 opt = map_old_vendor_opts[i][1];
167 break;
168 }
169 }
170
171 // Parse option
172 int len = strlen(opt);
173 int id = 0, n1 = -1, n2 = -1;
6b80b4d2
JD
174 char fmtname[32+1], attrname[32+1], hddssd[3+1];
175 attrname[0] = hddssd[0] = 0;
176
bed94269 177 if (opt[0] == 'N') {
d2e702cf 178 // "N,format[,name]"
bed94269
GI
179 if (!( sscanf(opt, "N,%32[^,]%n,%32[^,]%n", fmtname, &n1, attrname, &n2) >= 1
180 && (n1 == len || n2 == len)))
181 return false;
2127e193
GI
182 }
183 else {
6b80b4d2
JD
184 // "id,format[+][,name[,HDD|SSD]]"
185 int n3 = -1;
186 if (!( sscanf(opt, "%d,%32[^,]%n,%32[^,]%n,%3[DHS]%n",
187 &id, fmtname, &n1, attrname, &n2, hddssd, &n3) >= 2
188 && 1 <= id && id <= 255
189 && ( n1 == len || n2 == len
190 // ",HDD|SSD" for DEFAULT settings only
191 || (n3 == len && priority == PRIOR_DEFAULT))))
bed94269 192 return false;
2127e193
GI
193 }
194
bed94269
GI
195 unsigned flags = 0;
196 // For "-v 19[78],increasing" above
197 if (fmtname[strlen(fmtname)-1] == '+') {
198 fmtname[strlen(fmtname)-1] = 0;
199 flags = ATTRFLAG_INCREASING;
200 }
201
a23d5117
GI
202 // Split "format[:byteorder]"
203 char byteorder[8+1] = "";
204 if (strchr(fmtname, ':')) {
6b80b4d2
JD
205 if (priority == PRIOR_DEFAULT)
206 // TODO: Allow Byteorder in DEFAULT entry
207 return false;
d2e702cf 208 n1 = n2 = -1;
a23d5117
GI
209 if (!( sscanf(fmtname, "%*[^:]%n:%8[012345rvwz]%n", &n1, byteorder, &n2) >= 1
210 && n2 == (int)strlen(fmtname)))
211 return false;
212 fmtname[n1] = 0;
213 if (strchr(byteorder, 'v'))
214 flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
215 if (strchr(byteorder, 'w'))
216 flags |= ATTRFLAG_NO_WORSTVAL;
217 }
218
bed94269 219 // Find format name
2127e193 220 for (i = 0; ; i++) {
bed94269
GI
221 if (i >= num_format_names)
222 return false; // Not found
223 if (!strcmp(fmtname, format_names[i].name))
2127e193 224 break;
832b75ed 225 }
bed94269
GI
226 ata_attr_raw_format format = format_names[i].format;
227
a23d5117
GI
228 // 64-bit formats use the normalized and worst value bytes.
229 if (!*byteorder && (format == RAWFMT_RAW64 || format == RAWFMT_HEX64))
230 flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
832b75ed 231
6b80b4d2
JD
232 // ",HDD|SSD" suffix for DEFAULT settings
233 if (hddssd[0]) {
234 if (!strcmp(hddssd, "HDD"))
235 flags |= ATTRFLAG_HDD_ONLY;
236 else if (!strcmp(hddssd, "SSD"))
237 flags |= ATTRFLAG_SSD_ONLY;
238 else
239 return false;
240 }
241
2127e193 242 if (!id) {
bed94269
GI
243 // "N,format" -> set format for all entries
244 for (i = 0; i < MAX_ATTRIBUTE_NUM; i++) {
245 if (defs[i].priority >= priority)
246 continue;
247 if (attrname[0])
248 defs[i].name = attrname;
249 defs[i].priority = priority;
250 defs[i].raw_format = format;
251 defs[i].flags = flags;
ee38a438 252 snprintf(defs[i].byteorder, sizeof(defs[i].byteorder), "%s", byteorder);
bed94269
GI
253 }
254 }
255 else if (defs[id].priority <= priority) {
256 // "id,format[,name]"
257 if (attrname[0])
258 defs[id].name = attrname;
259 defs[id].raw_format = format;
260 defs[id].priority = priority;
261 defs[id].flags = flags;
ee38a438 262 snprintf(defs[id].byteorder, sizeof(defs[id].byteorder), "%s", byteorder);
832b75ed
GG
263 }
264
bed94269 265 return true;
832b75ed
GG
266}
267
bed94269 268
2127e193
GI
269// Return a multiline string containing a list of valid arguments for
270// parse_attribute_def(). The strings are preceeded by tabs and followed
832b75ed 271// (except for the last) by newlines.
2127e193
GI
272std::string create_vendor_attribute_arg_list()
273{
274 std::string s;
bed94269
GI
275 unsigned i;
276 for (i = 0; i < num_format_names; i++)
a23d5117 277 s += strprintf("%s\tN,%s[:012345rvwz][,ATTR_NAME]",
bed94269
GI
278 (i>0 ? "\n" : ""), format_names[i].name);
279 for (i = 0; i < num_old_vendor_opts; i++)
280 s += strprintf("\n\t%s", map_old_vendor_opts[i][0]);
832b75ed
GG
281 return s;
282}
283
ee38a438
GI
284
285// Parse firmwarebug def (-F option).
286// Return false on error.
287bool parse_firmwarebug_def(const char * opt, firmwarebug_defs & firmwarebugs)
288{
289 if (!strcmp(opt, "none"))
290 firmwarebugs.set(BUG_NONE);
291 else if (!strcmp(opt, "nologdir"))
292 firmwarebugs.set(BUG_NOLOGDIR);
293 else if (!strcmp(opt, "samsung"))
294 firmwarebugs.set(BUG_SAMSUNG);
295 else if (!strcmp(opt, "samsung2"))
296 firmwarebugs.set(BUG_SAMSUNG2);
297 else if (!strcmp(opt, "samsung3"))
298 firmwarebugs.set(BUG_SAMSUNG3);
299 else if (!strcmp(opt, "xerrorlba"))
300 firmwarebugs.set(BUG_XERRORLBA);
301 else
302 return false;
303 return true;
304}
305
306// Return a string of valid argument words for parse_firmwarebug_def()
307const char * get_valid_firmwarebug_args()
308{
309 return "none, nologdir, samsung, samsung2, samsung3, xerrorlba";
310}
311
312
832b75ed
GG
313// swap two bytes. Point to low address
314void swap2(char *location){
315 char tmp=*location;
316 *location=*(location+1);
317 *(location+1)=tmp;
318 return;
319}
320
321// swap four bytes. Point to low address
322void swap4(char *location){
323 char tmp=*location;
324 *location=*(location+3);
325 *(location+3)=tmp;
326 swap2(location+1);
327 return;
328}
329
330// swap eight bytes. Points to low address
331void swap8(char *location){
332 char tmp=*location;
333 *location=*(location+7);
334 *(location+7)=tmp;
335 tmp=*(location+1);
336 *(location+1)=*(location+6);
337 *(location+6)=tmp;
338 swap4(location+2);
339 return;
340}
341
a7e8ffec
GI
342// Invalidate serial number and WWN and adjust checksum in IDENTIFY data
343static void invalidate_serno(ata_identify_device * id)
344{
a37e7145 345 unsigned char sum = 0;
a7e8ffec
GI
346 unsigned i;
347 for (i = 0; i < sizeof(id->serial_no); i++) {
a37e7145
GG
348 sum += id->serial_no[i]; sum -= id->serial_no[i] = 'X';
349 }
a7e8ffec
GI
350 unsigned char * b = (unsigned char *)id;
351 for (i = 2*108; i < 2*112; i++) { // words108-111: WWN
352 sum += b[i]; sum -= b[i] = 0x00;
353 }
354
a37e7145
GG
355#ifndef __NetBSD__
356 bool must_swap = !!isbigendian();
357 if (must_swap)
358 swapx(id->words088_255+255-88);
359#endif
360 if ((id->words088_255[255-88] & 0x00ff) == 0x00a5)
361 id->words088_255[255-88] += sum << 8;
362#ifndef __NetBSD__
363 if (must_swap)
364 swapx(id->words088_255+255-88);
365#endif
366}
367
2127e193 368static const char * const commandstrings[]={
832b75ed
GG
369 "SMART ENABLE",
370 "SMART DISABLE",
371 "SMART AUTOMATIC ATTRIBUTE SAVE",
372 "SMART IMMEDIATE OFFLINE",
373 "SMART AUTO OFFLINE",
374 "SMART STATUS",
375 "SMART STATUS CHECK",
376 "SMART READ ATTRIBUTE VALUES",
377 "SMART READ ATTRIBUTE THRESHOLDS",
378 "SMART READ LOG",
379 "IDENTIFY DEVICE",
380 "IDENTIFY PACKET DEVICE",
381 "CHECK POWER MODE",
382 "SMART WRITE LOG",
383 "WARNING (UNDEFINED COMMAND -- CONTACT DEVELOPERS AT " PACKAGE_BUGREPORT ")\n"
384};
385
2127e193 386
ee38a438 387static const char * preg(const ata_register & r, char (& buf)[8])
2127e193
GI
388{
389 if (!r.is_set())
390 //return "n/a ";
391 return "....";
ee38a438
GI
392 snprintf(buf, sizeof(buf), "0x%02x", r.val());
393 return buf;
2127e193
GI
394}
395
cfbba5b9 396static void print_regs(const char * prefix, const ata_in_regs & r, const char * suffix = "\n")
2127e193 397{
ee38a438 398 char bufs[7][8];
2127e193
GI
399 pout("%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix,
400 preg(r.features, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
401 preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
402 preg(r.command, bufs[6]), suffix);
403}
404
cfbba5b9 405static void print_regs(const char * prefix, const ata_out_regs & r, const char * suffix = "\n")
2127e193 406{
ee38a438 407 char bufs[7][8];
2127e193
GI
408 pout("%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix,
409 preg(r.error, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
410 preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
411 preg(r.status, bufs[6]), suffix);
412}
413
a37e7145 414static void prettyprint(const unsigned char *p, const char *name){
832b75ed 415 pout("\n===== [%s] DATA START (BASE-16) =====\n", name);
a37e7145 416 for (int i=0; i<512; i+=16, p+=16)
d008864d 417#define P(n) (' ' <= p[n] && p[n] <= '~' ? (int)p[n] : '.')
a37e7145
GG
418 // print complete line to avoid slow tty output and extra lines in syslog.
419 pout("%03d-%03d: %02x %02x %02x %02x %02x %02x %02x %02x "
a23d5117
GI
420 "%02x %02x %02x %02x %02x %02x %02x %02x"
421 " |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c|"
422 "%c",
a37e7145
GG
423 i, i+16-1,
424 p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
a23d5117
GI
425 p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15],
426 P( 0), P( 1), P( 2), P( 3), P( 4), P( 5), P( 6), P( 7),
427 P( 8), P( 9), P(10), P(11), P(12), P(13), P(14), P(15),
428 '\n');
429#undef P
832b75ed
GG
430 pout("===== [%s] DATA END (512 Bytes) =====\n\n", name);
431}
432
433// This function provides the pretty-print reporting for SMART
434// commands: it implements the various -r "reporting" options for ATA
435// ioctls.
2127e193
GI
436int smartcommandhandler(ata_device * device, smart_command_set command, int select, char *data){
437 // TODO: Rework old stuff below
832b75ed
GG
438 // This conditional is true for commands that return data
439 int getsdata=(command==PIDENTIFY ||
440 command==IDENTIFY ||
441 command==READ_LOG ||
442 command==READ_THRESHOLDS ||
443 command==READ_VALUES ||
4d59bff9 444 command==CHECK_POWER_MODE);
832b75ed
GG
445
446 int sendsdata=(command==WRITE_LOG);
447
448 // If reporting is enabled, say what the command will be before it's executed
cfbba5b9 449 if (ata_debugmode) {
832b75ed
GG
450 // conditional is true for commands that use parameters
451 int usesparam=(command==READ_LOG ||
452 command==AUTO_OFFLINE ||
453 command==AUTOSAVE ||
454 command==IMMEDIATE_OFFLINE ||
455 command==WRITE_LOG);
456
2127e193 457 pout("\nREPORT-IOCTL: Device=%s Command=%s", device->get_dev_name(), commandstrings[command]);
832b75ed
GG
458 if (usesparam)
459 pout(" InputParameter=%d\n", select);
460 else
461 pout("\n");
462 }
463
464 if ((getsdata || sendsdata) && !data){
465 pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]);
466 return -1;
467 }
468
469 // The reporting is cleaner, and we will find coding bugs faster, if
470 // the commands that failed clearly return empty (zeroed) data
471 // structures
472 if (getsdata) {
473 if (command==CHECK_POWER_MODE)
474 data[0]=0;
475 else
476 memset(data, '\0', 512);
477 }
478
479
a37e7145 480 // if requested, pretty-print the input data structure
cfbba5b9 481 if (ata_debugmode > 1 && sendsdata)
2127e193 482 //pout("REPORT-IOCTL: Device=%s Command=%s\n", device->get_dev_name(), commandstrings[command]);
a37e7145 483 prettyprint((unsigned char *)data, commandstrings[command]);
832b75ed 484
832b75ed 485 // now execute the command
2127e193
GI
486 int retval = -1;
487 {
488 ata_cmd_in in;
489 // Set common register values
490 switch (command) {
491 default: // SMART commands
492 in.in_regs.command = ATA_SMART_CMD;
493 in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
494 break;
495 case IDENTIFY: case PIDENTIFY: case CHECK_POWER_MODE: // Non SMART commands
496 break;
497 }
498 // Set specific values
499 switch (command) {
500 case IDENTIFY:
501 in.in_regs.command = ATA_IDENTIFY_DEVICE;
502 in.set_data_in(data, 1);
503 break;
504 case PIDENTIFY:
505 in.in_regs.command = ATA_IDENTIFY_PACKET_DEVICE;
506 in.set_data_in(data, 1);
507 break;
508 case CHECK_POWER_MODE:
509 in.in_regs.command = ATA_CHECK_POWER_MODE;
510 in.out_needed.sector_count = true; // Powermode returned here
511 break;
512 case READ_VALUES:
513 in.in_regs.features = ATA_SMART_READ_VALUES;
514 in.set_data_in(data, 1);
515 break;
516 case READ_THRESHOLDS:
517 in.in_regs.features = ATA_SMART_READ_THRESHOLDS;
518 in.in_regs.lba_low = 1; // TODO: CORRECT ???
519 in.set_data_in(data, 1);
520 break;
521 case READ_LOG:
522 in.in_regs.features = ATA_SMART_READ_LOG_SECTOR;
523 in.in_regs.lba_low = select;
524 in.set_data_in(data, 1);
525 break;
526 case WRITE_LOG:
527 in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
528 in.in_regs.lba_low = select;
529 in.set_data_out(data, 1);
530 break;
531 case ENABLE:
532 in.in_regs.features = ATA_SMART_ENABLE;
533 in.in_regs.lba_low = 1; // TODO: CORRECT ???
534 break;
535 case DISABLE:
536 in.in_regs.features = ATA_SMART_DISABLE;
537 in.in_regs.lba_low = 1; // TODO: CORRECT ???
538 break;
539 case STATUS_CHECK:
540 in.out_needed.lba_high = in.out_needed.lba_mid = true; // Status returned here
541 case STATUS:
542 in.in_regs.features = ATA_SMART_STATUS;
543 break;
544 case AUTO_OFFLINE:
545 in.in_regs.features = ATA_SMART_AUTO_OFFLINE;
546 in.in_regs.sector_count = select; // Caution: Non-DATA command!
547 break;
548 case AUTOSAVE:
549 in.in_regs.features = ATA_SMART_AUTOSAVE;
550 in.in_regs.sector_count = select; // Caution: Non-DATA command!
551 break;
552 case IMMEDIATE_OFFLINE:
553 in.in_regs.features = ATA_SMART_IMMEDIATE_OFFLINE;
554 in.in_regs.lba_low = select;
555 break;
556 default:
557 pout("Unrecognized command %d in smartcommandhandler()\n"
558 "Please contact " PACKAGE_BUGREPORT "\n", command);
559 device->set_err(ENOSYS);
2127e193
GI
560 return -1;
561 }
562
cfbba5b9 563 if (ata_debugmode)
2127e193
GI
564 print_regs(" Input: ", in.in_regs,
565 (in.direction==ata_cmd_in::data_in ? " IN\n":
566 in.direction==ata_cmd_in::data_out ? " OUT\n":"\n"));
567
568 ata_cmd_out out;
e165493d
GI
569
570 int64_t start_usec = -1;
571 if (ata_debugmode)
572 start_usec = smi()->get_timer_usec();
573
2127e193
GI
574 bool ok = device->ata_pass_through(in, out);
575
e165493d
GI
576 if (start_usec >= 0) {
577 int64_t duration_usec = smi()->get_timer_usec() - start_usec;
578 if (duration_usec >= 500)
579 pout(" [Duration: %.3fs]\n", duration_usec / 1000000.0);
580 }
581
cfbba5b9 582 if (ata_debugmode && out.out_regs.is_set())
2127e193
GI
583 print_regs(" Output: ", out.out_regs);
584
585 if (ok) switch (command) {
586 default:
587 retval = 0;
588 break;
589 case CHECK_POWER_MODE:
a7e8ffec
GI
590 if (out.out_regs.sector_count.is_set()) {
591 data[0] = out.out_regs.sector_count;
592 retval = 0;
593 }
594 else {
595 pout("CHECK POWER MODE: incomplete response, ATA output registers missing\n");
596 device->set_err(ENOSYS);
597 retval = -1;
598 }
2127e193
GI
599 break;
600 case STATUS_CHECK:
601 // Cyl low and Cyl high unchanged means "Good SMART status"
602 if ((out.out_regs.lba_high == SMART_CYL_HI) &&
603 (out.out_regs.lba_mid == SMART_CYL_LOW))
604 retval = 0;
605 // These values mean "Bad SMART status"
606 else if ((out.out_regs.lba_high == SRET_STATUS_HI_EXCEEDED) &&
607 (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED))
608 retval = 1;
609 else if (out.out_regs.lba_mid == SMART_CYL_LOW) {
610 retval = 0;
cfbba5b9 611 if (ata_debugmode)
2127e193
GI
612 pout("SMART STATUS RETURN: half healthy response sequence, "
613 "probable SAT/USB truncation\n");
614 } else if (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED) {
615 retval = 1;
cfbba5b9 616 if (ata_debugmode)
2127e193
GI
617 pout("SMART STATUS RETURN: half unhealthy response sequence, "
618 "probable SAT/USB truncation\n");
a7e8ffec
GI
619 }
620 else if (!out.out_regs.is_set()) {
d2e702cf 621 device->set_err(ENOSYS, "Incomplete response, ATA output registers missing");
a7e8ffec
GI
622 retval = -1;
623 }
624 else {
2127e193 625 // We haven't gotten output that makes sense; print out some debugging info
ee38a438 626 pout("SMART Status command failed\n");
a23d5117
GI
627 pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE);
628 pout("Register values returned from SMART Status command are:\n");
629 print_regs(" ", out.out_regs);
d2e702cf 630 device->set_err(ENOSYS, "Invalid ATA output register values");
2127e193
GI
631 retval = -1;
632 }
633 break;
634 }
832b75ed
GG
635 }
636
a37e7145 637 // If requested, invalidate serial number before any printing is done
cfbba5b9 638 if ((command == IDENTIFY || command == PIDENTIFY) && !retval && dont_print_serial_number)
6b80b4d2 639 invalidate_serno( reinterpret_cast<ata_identify_device *>(data) );
a37e7145 640
832b75ed 641 // If reporting is enabled, say what output was produced by the command
cfbba5b9 642 if (ata_debugmode) {
2127e193
GI
643 if (device->get_errno())
644 pout("REPORT-IOCTL: Device=%s Command=%s returned %d errno=%d [%s]\n",
645 device->get_dev_name(), commandstrings[command], retval,
646 device->get_errno(), device->get_errmsg());
832b75ed 647 else
2127e193
GI
648 pout("REPORT-IOCTL: Device=%s Command=%s returned %d\n",
649 device->get_dev_name(), commandstrings[command], retval);
832b75ed
GG
650
651 // if requested, pretty-print the output data structure
cfbba5b9 652 if (ata_debugmode > 1 && getsdata) {
832b75ed
GG
653 if (command==CHECK_POWER_MODE)
654 pout("Sector Count Register (BASE-16): %02x\n", (unsigned char)(*data));
655 else
656 prettyprint((unsigned char *)data, commandstrings[command]);
657 }
658 }
2127e193 659
832b75ed
GG
660 return retval;
661}
662
a7e8ffec
GI
663// Get capacity and sector sizes from IDENTIFY data
664void ata_get_size_info(const ata_identify_device * id, ata_size_info & sizes)
2127e193 665{
a7e8ffec
GI
666 sizes.sectors = sizes.capacity = 0;
667 sizes.log_sector_size = sizes.phy_sector_size = 0;
668 sizes.log_sector_offset = 0;
669
670 // Return if no LBA support
671 if (!(id->words047_079[49-47] & 0x0200))
672 return;
673
674 // Determine 28-bit LBA capacity
675 unsigned lba28 = (unsigned)id->words047_079[61-47] << 16
676 | (unsigned)id->words047_079[60-47] ;
677
678 // Determine 48-bit LBA capacity if supported
679 uint64_t lba48 = 0;
680 if ((id->command_set_2 & 0xc400) == 0x4400)
681 lba48 = (uint64_t)id->words088_255[103-88] << 48
682 | (uint64_t)id->words088_255[102-88] << 32
683 | (uint64_t)id->words088_255[101-88] << 16
684 | (uint64_t)id->words088_255[100-88] ;
685
686 // Return if capacity unknown (ATAPI CD/DVD)
687 if (!(lba28 || lba48))
688 return;
689
690 // Determine sector sizes
691 sizes.log_sector_size = sizes.phy_sector_size = 512;
692
693 unsigned short word106 = id->words088_255[106-88];
694 if ((word106 & 0xc000) == 0x4000) {
695 // Long Logical/Physical Sectors (LLS/LPS) ?
696 if (word106 & 0x1000)
697 // Logical sector size is specified in 16-bit words
698 sizes.log_sector_size = sizes.phy_sector_size =
699 ((id->words088_255[118-88] << 16) | id->words088_255[117-88]) << 1;
700
701 if (word106 & 0x2000)
702 // Physical sector size is multiple of logical sector size
703 sizes.phy_sector_size <<= (word106 & 0x0f);
704
705 unsigned short word209 = id->words088_255[209-88];
706 if ((word209 & 0xc000) == 0x4000)
707 sizes.log_sector_offset = (word209 & 0x3fff) * sizes.log_sector_size;
708 }
709
710 // Some early 4KiB LLS disks (Samsung N3U-3) return bogus lba28 value
711 if (lba48 >= lba28 || (lba48 && sizes.log_sector_size > 512))
712 sizes.sectors = lba48;
713 else
714 sizes.sectors = lba28;
715
716 sizes.capacity = sizes.sectors * sizes.log_sector_size;
2127e193 717}
832b75ed
GG
718
719// This function computes the checksum of a single disk sector (512
720// bytes). Returns zero if checksum is OK, nonzero if the checksum is
721// incorrect. The size (512) is correct for all SMART structures.
2127e193
GI
722unsigned char checksum(const void * data)
723{
724 unsigned char sum = 0;
725 for (int i = 0; i < 512; i++)
726 sum += ((const unsigned char *)data)[i];
727 return sum;
728}
729
730// Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents
731// bytes.
732static void swapbytes(char * out, const char * in, size_t n)
733{
734 for (size_t i = 0; i < n; i += 2) {
735 out[i] = in[i+1];
736 out[i+1] = in[i];
737 }
738}
739
740// Copies in to out, but removes leading and trailing whitespace.
741static void trim(char * out, const char * in)
742{
743 // Find the first non-space character (maybe none).
744 int first = -1;
832b75ed 745 int i;
2127e193
GI
746 for (i = 0; in[i]; i++)
747 if (!isspace((int)in[i])) {
748 first = i;
749 break;
750 }
832b75ed 751
2127e193
GI
752 if (first == -1) {
753 // There are no non-space characters.
754 out[0] = '\0';
755 return;
756 }
757
758 // Find the last non-space character.
759 for (i = strlen(in)-1; i >= first && isspace((int)in[i]); i--)
760 ;
761 int last = i;
762
763 strncpy(out, in+first, last-first+1);
764 out[last-first+1] = '\0';
765}
766
767// Convenience function for formatting strings from ata_identify_device
cfbba5b9 768void ata_format_id_string(char * out, const unsigned char * in, int n)
2127e193 769{
cfbba5b9 770 bool must_swap = true;
2127e193
GI
771#ifdef __NetBSD__
772 /* NetBSD kernel delivers IDENTIFY data in host byte order (but all else is LE) */
cfbba5b9 773 // TODO: Handle NetBSD case in os_netbsd.cpp
2127e193
GI
774 if (isbigendian())
775 must_swap = !must_swap;
776#endif
777
778 char tmp[65];
779 n = n > 64 ? 64 : n;
780 if (!must_swap)
cfbba5b9 781 strncpy(tmp, (const char *)in, n);
2127e193 782 else
cfbba5b9 783 swapbytes(tmp, (const char *)in, n);
2127e193
GI
784 tmp[n] = '\0';
785 trim(out, tmp);
832b75ed
GG
786}
787
788// returns -1 if command fails or the device is in Sleep mode, else
789// value of Sector Count register. Sector Count result values:
790// 00h device is in Standby mode.
791// 80h device is in Idle mode.
792// FFh device is in Active mode or Idle mode.
793
2127e193 794int ataCheckPowerMode(ata_device * device) {
832b75ed
GG
795 unsigned char result;
796
797 if ((smartcommandhandler(device, CHECK_POWER_MODE, 0, (char *)&result)))
798 return -1;
799
800 if (result!=0 && result!=0x80 && result!=0xff)
801 pout("ataCheckPowerMode(): ATA CHECK POWER MODE returned unknown Sector Count Register value %02x\n", result);
802
803 return (int)result;
804}
805
d008864d
GI
806// Issue a no-data ATA command with optional sector count register value
807bool ata_nodata_command(ata_device * device, unsigned char command,
808 int sector_count /* = -1 */)
809{
810 ata_cmd_in in;
811 in.in_regs.command = command;
812 if (sector_count >= 0)
813 in.in_regs.sector_count = sector_count;
814
815 return device->ata_pass_through(in);
816}
817
818// Issue SET FEATURES command with optional sector count register value
819bool ata_set_features(ata_device * device, unsigned char features,
820 int sector_count /* = -1 */)
821{
822 ata_cmd_in in;
823 in.in_regs.command = ATA_SET_FEATURES;
824 in.in_regs.features = features;
825 if (sector_count >= 0)
826 in.in_regs.sector_count = sector_count;
827
828 return device->ata_pass_through(in);
829}
830
832b75ed
GG
831// Reads current Device Identity info (512 bytes) into buf. Returns 0
832// if all OK. Returns -1 if no ATA Device identity can be
833// established. Returns >0 if Device is ATA Packet Device (not SMART
834// capable). The value of the integer helps identify the type of
835// Packet device, which is useful so that the user can connect the
836// formal device number with whatever object is inside their computer.
ee38a438
GI
837int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id,
838 unsigned char * raw_buf /* = 0 */)
cfbba5b9 839{
832b75ed
GG
840 unsigned short *rawshort=(unsigned short *)buf;
841 unsigned char *rawbyte =(unsigned char *)buf;
842
843 // See if device responds either to IDENTIFY DEVICE or IDENTIFY
844 // PACKET DEVICE
cfbba5b9 845 bool packet = false;
832b75ed
GG
846 if ((smartcommandhandler(device, IDENTIFY, 0, (char *)buf))){
847 if (smartcommandhandler(device, PIDENTIFY, 0, (char *)buf)){
848 return -1;
849 }
cfbba5b9
GI
850 packet = true;
851 }
852
cfbba5b9
GI
853 if (fix_swapped_id) {
854 // Swap ID strings
6b80b4d2 855 unsigned i;
cfbba5b9
GI
856 for (i = 0; i < sizeof(buf->serial_no)-1; i += 2)
857 swap2((char *)(buf->serial_no+i));
858 for (i = 0; i < sizeof(buf->fw_rev)-1; i += 2)
859 swap2((char *)(buf->fw_rev+i));
860 for (i = 0; i < sizeof(buf->model)-1; i += 2)
861 swap2((char *)(buf->model+i));
832b75ed
GG
862 }
863
ee38a438
GI
864 // If requested, save raw data before endianness adjustments
865 if (raw_buf)
866 memcpy(raw_buf, buf, sizeof(*buf));
867
832b75ed
GG
868#ifndef __NetBSD__
869 // if machine is big-endian, swap byte order as needed
a37e7145 870 // NetBSD kernel delivers IDENTIFY data in host byte order
cfbba5b9 871 // TODO: Handle NetBSD case in os_netbsd.cpp
832b75ed 872 if (isbigendian()){
832b75ed 873 // swap various capability words that are needed
6b80b4d2 874 unsigned i;
832b75ed
GG
875 for (i=0; i<33; i++)
876 swap2((char *)(buf->words047_079+i));
832b75ed
GG
877 for (i=80; i<=87; i++)
878 swap2((char *)(rawshort+i));
832b75ed
GG
879 for (i=0; i<168; i++)
880 swap2((char *)(buf->words088_255+i));
881 }
882#endif
883
884 // If there is a checksum there, validate it
885 if ((rawshort[255] & 0x00ff) == 0x00a5 && checksum(rawbyte))
886 checksumwarning("Drive Identity Structure");
cfbba5b9
GI
887
888 // AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
889 // T13/1699-D Revision 6a (Final Draft), September 6, 2008.
890 // Sections 7.16.7 and 7.17.6:
891 //
892 // Word 0 of IDENTIFY DEVICE data:
893 // Bit 15 = 0 : ATA device
894 //
895 // Word 0 of IDENTIFY PACKET DEVICE data:
896 // Bits 15:14 = 10b : ATAPI device
897 // Bits 15:14 = 11b : Reserved
898 // Bits 12:8 : Device type (SPC-4, e.g 0x05 = CD/DVD)
899
900 // CF+ and CompactFlash Specification Revision 4.0, May 24, 2006.
901 // Section 6.2.1.6:
902 //
903 // Word 0 of IDENTIFY DEVICE data:
904 // 848Ah = Signature for CompactFlash Storage Card
905 // 044Ah = Alternate value turns on ATA device while preserving all retired bits
906 // 0040h = Alternate value turns on ATA device while zeroing all retired bits
907
908 // Assume ATA if IDENTIFY DEVICE returns CompactFlash Signature
909 if (!packet && rawbyte[1] == 0x84 && rawbyte[0] == 0x8a)
910 return 0;
911
832b75ed
GG
912 // If this is a PACKET DEVICE, return device type
913 if (rawbyte[1] & 0x80)
914 return 1+(rawbyte[1] & 0x1f);
915
916 // Not a PACKET DEVICE
917 return 0;
918}
919
a7e8ffec
GI
920// Get World Wide Name (WWN) fields.
921// Return NAA field or -1 if WWN is unsupported.
922// Table 34 of T13/1699-D Revision 6a (ATA8-ACS), September 6, 2008.
923// (WWN was introduced in ATA/ATAPI-7 and is mandatory since ATA8-ACS Revision 3b)
924int ata_get_wwn(const ata_identify_device * id, unsigned & oui, uint64_t & unique_id)
925{
926 // Don't use word 84 to be compatible with some older ATA-7 disks
927 unsigned short word087 = id->csf_default;
928 if ((word087 & 0xc100) != 0x4100)
929 return -1; // word not valid or WWN support bit 8 not set
930
931 unsigned short word108 = id->words088_255[108-88];
932 unsigned short word109 = id->words088_255[109-88];
933 unsigned short word110 = id->words088_255[110-88];
934 unsigned short word111 = id->words088_255[111-88];
935
936 oui = ((word108 & 0x0fff) << 12) | (word109 >> 4);
937 unique_id = ((uint64_t)(word109 & 0xf) << 32)
938 | (unsigned)((word110 << 16) | word111);
939 return (word108 >> 12);
940}
941
ee38a438
GI
942// Get nominal media rotation rate.
943// Returns: 0 = not reported, 1 = SSD, >1 = HDD rpm, < 0 = -(Unknown value)
944int ata_get_rotation_rate(const ata_identify_device * id)
945{
946 // Table 37 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
947 // Table A.31 of T13/2161-D (ACS-3) Revision 3b, August 25, 2012
948 unsigned short word217 = id->words088_255[217-88];
949 if (word217 == 0x0000 || word217 == 0xffff)
950 return 0;
951 else if (word217 == 0x0001)
952 return 1;
953 else if (word217 > 0x0400)
954 return word217;
955 else
956 return -(int)word217;
957}
958
832b75ed 959// returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
2127e193
GI
960int ataSmartSupport(const ata_identify_device * drive)
961{
832b75ed
GG
962 unsigned short word82=drive->command_set_1;
963 unsigned short word83=drive->command_set_2;
964
965 // check if words 82/83 contain valid info
966 if ((word83>>14) == 0x01)
967 // return value of SMART support bit
968 return word82 & 0x0001;
969
970 // since we can're rely on word 82, we don't know if SMART supported
971 return -1;
972}
973
974// returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
2127e193
GI
975int ataIsSmartEnabled(const ata_identify_device * drive)
976{
832b75ed
GG
977 unsigned short word85=drive->cfs_enable_1;
978 unsigned short word87=drive->csf_default;
979
980 // check if words 85/86/87 contain valid info
981 if ((word87>>14) == 0x01)
982 // return value of SMART enabled bit
983 return word85 & 0x0001;
984
985 // Since we can't rely word85, we don't know if SMART is enabled.
986 return -1;
987}
988
989
990// Reads SMART attributes into *data
2127e193 991int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){
832b75ed
GG
992
993 if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){
832b75ed
GG
994 return -1;
995 }
996
997 // compute checksum
2127e193 998 if (checksum(data))
832b75ed
GG
999 checksumwarning("SMART Attribute Data Structure");
1000
a37e7145 1001 // swap endian order if needed
832b75ed
GG
1002 if (isbigendian()){
1003 int i;
1004 swap2((char *)&(data->revnumber));
1005 swap2((char *)&(data->total_time_to_complete_off_line));
1006 swap2((char *)&(data->smart_capability));
d008864d 1007 swapx(&data->extend_test_completion_time_w);
832b75ed
GG
1008 for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
1009 struct ata_smart_attribute *x=data->vendor_attributes+i;
1010 swap2((char *)&(x->flags));
1011 }
1012 }
1013
1014 return 0;
1015}
1016
1017
1018// This corrects some quantities that are byte reversed in the SMART
1019// SELF TEST LOG
2127e193
GI
1020static void fixsamsungselftestlog(ata_smart_selftestlog * data)
1021{
832b75ed
GG
1022 // bytes 508/509 (numbered from 0) swapped (swap of self-test index
1023 // with one byte of reserved.
1024 swap2((char *)&(data->mostrecenttest));
1025
1026 // LBA low register (here called 'selftestnumber", containing
1027 // information about the TYPE of the self-test) is byte swapped with
1028 // Self-test execution status byte. These are bytes N, N+1 in the
1029 // entries.
2127e193 1030 for (int i = 0; i < 21; i++)
832b75ed
GG
1031 swap2((char *)&(data->selftest_struct[i].selftestnumber));
1032
1033 return;
1034}
1035
1036// Reads the Self Test Log (log #6)
2127e193 1037int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data,
ee38a438 1038 firmwarebug_defs firmwarebugs)
2127e193 1039{
832b75ed
GG
1040
1041 // get data from device
1042 if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){
832b75ed
GG
1043 return -1;
1044 }
1045
1046 // compute its checksum, and issue a warning if needed
2127e193 1047 if (checksum(data))
832b75ed
GG
1048 checksumwarning("SMART Self-Test Log Structure");
1049
1050 // fix firmware bugs in self-test log
ee38a438 1051 if (firmwarebugs.is_set(BUG_SAMSUNG))
832b75ed
GG
1052 fixsamsungselftestlog(data);
1053
a37e7145 1054 // swap endian order if needed
832b75ed
GG
1055 if (isbigendian()){
1056 int i;
1057 swap2((char*)&(data->revnumber));
1058 for (i=0; i<21; i++){
1059 struct ata_smart_selftestlog_struct *x=data->selftest_struct+i;
1060 swap2((char *)&(x->timestamp));
1061 swap4((char *)&(x->lbafirstfailure));
1062 }
1063 }
1064
1065 return 0;
1066}
1067
2127e193
GI
1068// Print checksum warning for multi sector log
1069static void check_multi_sector_sum(const void * data, unsigned nsectors, const char * msg)
1070{
1071 unsigned errs = 0;
1072 for (unsigned i = 0; i < nsectors; i++) {
1073 if (checksum((const unsigned char *)data + i*512))
1074 errs++;
1075 }
1076 if (errs > 0) {
1077 if (nsectors == 1)
1078 checksumwarning(msg);
1079 else
1080 checksumwarning(strprintf("%s (%u/%u)", msg, errs, nsectors).c_str());
1081 }
1082}
832b75ed 1083
2127e193
GI
1084// Read SMART Extended Self-test Log
1085bool ataReadExtSelfTestLog(ata_device * device, ata_smart_extselftestlog * log,
1086 unsigned nsectors)
1087{
1088 if (!ataReadLogExt(device, 0x07, 0x00, 0, log, nsectors))
1089 return false;
1090
1091 check_multi_sector_sum(log, nsectors, "SMART Extended Self-test Log Structure");
1092
1093 if (isbigendian()) {
1094 swapx(&log->log_desc_index);
1095 for (unsigned i = 0; i < nsectors; i++) {
1096 for (unsigned j = 0; j < 19; j++)
1097 swapx(&log->log_descs[i].timestamp);
1098 }
832b75ed 1099 }
2127e193
GI
1100 return true;
1101}
832b75ed 1102
2127e193
GI
1103
1104// Read GP Log page(s)
1105bool ataReadLogExt(ata_device * device, unsigned char logaddr,
1106 unsigned char features, unsigned page,
1107 void * data, unsigned nsectors)
1108{
1109 ata_cmd_in in;
1110 in.in_regs.command = ATA_READ_LOG_EXT;
1111 in.in_regs.features = features; // log specific
1112 in.set_data_in_48bit(data, nsectors);
1113 in.in_regs.lba_low = logaddr;
1114 in.in_regs.lba_mid_16 = page;
1115
1116 if (!device->ata_pass_through(in)) { // TODO: Debug output
1117 if (nsectors <= 1) {
1118 pout("ATA_READ_LOG_EXT (addr=0x%02x:0x%02x, page=%u, n=%u) failed: %s\n",
1119 logaddr, features, page, nsectors, device->get_errmsg());
1120 return false;
1121 }
1122
1123 // Recurse to retry with single sectors,
1124 // multi-sector reads may not be supported by ioctl.
1125 for (unsigned i = 0; i < nsectors; i++) {
1126 if (!ataReadLogExt(device, logaddr,
1127 features, page + i,
1128 (char *)data + 512*i, 1))
1129 return false;
1130 }
832b75ed 1131 }
2127e193
GI
1132
1133 return true;
1134}
1135
1136// Read SMART Log page(s)
1137bool ataReadSmartLog(ata_device * device, unsigned char logaddr,
1138 void * data, unsigned nsectors)
1139{
1140 ata_cmd_in in;
1141 in.in_regs.command = ATA_SMART_CMD;
1142 in.in_regs.features = ATA_SMART_READ_LOG_SECTOR;
1143 in.set_data_in(data, nsectors);
1144 in.in_regs.lba_high = SMART_CYL_HI;
1145 in.in_regs.lba_mid = SMART_CYL_LOW;
1146 in.in_regs.lba_low = logaddr;
1147
1148 if (!device->ata_pass_through(in)) { // TODO: Debug output
1149 pout("ATA_SMART_READ_LOG failed: %s\n", device->get_errmsg());
1150 return false;
1151 }
1152 return true;
1153}
1154
1155
1156
1157// Reads the SMART or GPL Log Directory (log #0)
1158int ataReadLogDirectory(ata_device * device, ata_smart_log_directory * data, bool gpl)
1159{
1160 if (!gpl) { // SMART Log directory
1161 if (smartcommandhandler(device, READ_LOG, 0x00, (char *)data))
1162 return -1;
1163 }
1164 else { // GP Log directory
1165 if (!ataReadLogExt(device, 0x00, 0x00, 0, data, 1))
1166 return -1;
1167 }
1168
1169 // swap endian order if needed
1170 if (isbigendian())
1171 swapx(&data->logversion);
1172
832b75ed
GG
1173 return 0;
1174}
1175
1176
1177// Reads the selective self-test log (log #9)
2127e193 1178int ataReadSelectiveSelfTestLog(ata_device * device, struct ata_selective_self_test_log *data){
832b75ed
GG
1179
1180 // get data from device
1181 if (smartcommandhandler(device, READ_LOG, 0x09, (char *)data)){
832b75ed
GG
1182 return -1;
1183 }
1184
1185 // compute its checksum, and issue a warning if needed
2127e193 1186 if (checksum(data))
832b75ed
GG
1187 checksumwarning("SMART Selective Self-Test Log Structure");
1188
1189 // swap endian order if needed
1190 if (isbigendian()){
1191 int i;
1192 swap2((char *)&(data->logversion));
1193 for (i=0;i<5;i++){
1194 swap8((char *)&(data->span[i].start));
1195 swap8((char *)&(data->span[i].end));
1196 }
1197 swap8((char *)&(data->currentlba));
1198 swap2((char *)&(data->currentspan));
1199 swap2((char *)&(data->flags));
1200 swap2((char *)&(data->pendingtime));
1201 }
1202
832b75ed
GG
1203 return 0;
1204}
1205
1206// Writes the selective self-test log (log #9)
2127e193 1207int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_args & args,
cfbba5b9
GI
1208 const ata_smart_values * sv, uint64_t num_sectors,
1209 const ata_selective_selftest_args * prev_args)
2127e193 1210{
a37e7145
GG
1211 // Disk size must be known
1212 if (!num_sectors) {
1213 pout("Disk size is unknown, unable to check selective self-test spans\n");
1214 return -1;
1215 }
1216
1217 // Read log
832b75ed 1218 struct ata_selective_self_test_log sstlog, *data=&sstlog;
832b75ed 1219 unsigned char *ptr=(unsigned char *)data;
832b75ed 1220 if (ataReadSelectiveSelfTestLog(device, data)) {
ee38a438 1221 pout("SMART Read Selective Self-test Log failed: %s\n", device->get_errmsg());
832b75ed
GG
1222 pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n");
1223 return -1;
1224 }
1225
2127e193
GI
1226 // Set log version
1227 data->logversion = 1;
832b75ed
GG
1228
1229 // Host is NOT allowed to write selective self-test log if a selective
1230 // self-test is in progress.
1231 if (0<data->currentspan && data->currentspan<6 && ((sv->self_test_exec_status)>>4)==15) {
ee38a438 1232 pout("SMART Selective or other Self-test in progress\n");
832b75ed
GG
1233 return -4;
1234 }
a37e7145
GG
1235
1236 // Set start/end values based on old spans for special -t select,... options
1237 int i;
2127e193
GI
1238 for (i = 0; i < args.num_spans; i++) {
1239 int mode = args.span[i].mode;
1240 uint64_t start = args.span[i].start;
1241 uint64_t end = args.span[i].end;
a37e7145
GG
1242 if (mode == SEL_CONT) {// redo or next dependig on last test status
1243 switch (sv->self_test_exec_status >> 4) {
1244 case 1: case 2: // Aborted/Interrupted by host
1245 pout("Continue Selective Self-Test: Redo last span\n");
1246 mode = SEL_REDO;
1247 break;
1248 default: // All others
1249 pout("Continue Selective Self-Test: Start next span\n");
1250 mode = SEL_NEXT;
1251 break;
1252 }
1253 }
cfbba5b9
GI
1254
1255 if ( (mode == SEL_REDO || mode == SEL_NEXT)
1256 && prev_args && i < prev_args->num_spans
1257 && !data->span[i].start && !data->span[i].end) {
1258 // Some drives do not preserve the selective self-test log accross
1259 // power-cyles. If old span on drive is cleared use span provided
1260 // by caller. This is used by smartd (first span only).
1261 data->span[i].start = prev_args->span[i].start;
1262 data->span[i].end = prev_args->span[i].end;
1263 }
1264
a37e7145
GG
1265 switch (mode) {
1266 case SEL_RANGE: // -t select,START-END
1267 break;
1268 case SEL_REDO: // -t select,redo... => Redo current
1269 start = data->span[i].start;
1270 if (end > 0) { // -t select,redo+SIZE
1271 end--; end += start; // [oldstart, oldstart+SIZE)
1272 }
1273 else // -t select,redo
1274 end = data->span[i].end; // [oldstart, oldend]
1275 break;
1276 case SEL_NEXT: // -t select,next... => Do next
1277 if (data->span[i].end == 0) {
1278 start = end = 0; break; // skip empty spans
1279 }
1280 start = data->span[i].end + 1;
1281 if (start >= num_sectors)
1282 start = 0; // wrap around
1283 if (end > 0) { // -t select,next+SIZE
1284 end--; end += start; // (oldend, oldend+SIZE]
1285 }
1286 else { // -t select,next
1287 uint64_t oldsize = data->span[i].end - data->span[i].start + 1;
1288 end = start + oldsize - 1; // (oldend, oldend+oldsize]
1289 if (end >= num_sectors) {
1290 // Adjust size to allow round-robin testing without future size decrease
1291 uint64_t spans = (num_sectors + oldsize-1) / oldsize;
1292 uint64_t newsize = (num_sectors + spans-1) / spans;
1293 uint64_t newstart = num_sectors - newsize, newend = num_sectors - 1;
d2e702cf 1294 pout("Span %d changed from %" PRIu64 "-%" PRIu64 " (%" PRIu64 " sectors)\n",
2127e193 1295 i, start, end, oldsize);
d2e702cf 1296 pout(" to %" PRIu64 "-%" PRIu64 " (%" PRIu64 " sectors) (%" PRIu64 " spans)\n",
2127e193 1297 newstart, newend, newsize, spans);
a37e7145
GG
1298 start = newstart; end = newend;
1299 }
1300 }
1301 break;
1302 default:
1303 pout("ataWriteSelectiveSelfTestLog: Invalid mode %d\n", mode);
1304 return -1;
1305 }
1306 // Range check
1307 if (start < num_sectors && num_sectors <= end) {
1308 if (end != ~(uint64_t)0) // -t select,N-max
1309 pout("Size of self-test span %d decreased according to disk size\n", i);
1310 end = num_sectors - 1;
1311 }
1312 if (!(start <= end && end < num_sectors)) {
d2e702cf 1313 pout("Invalid selective self-test span %d: %" PRIu64 "-%" PRIu64 " (%" PRIu64 " sectors)\n",
a37e7145
GG
1314 i, start, end, num_sectors);
1315 return -1;
1316 }
2127e193
GI
1317 // Return the actual mode and range to caller.
1318 args.span[i].mode = mode;
1319 args.span[i].start = start;
1320 args.span[i].end = end;
a37e7145
GG
1321 }
1322
832b75ed
GG
1323 // Clear spans
1324 for (i=0; i<5; i++)
1325 memset(data->span+i, 0, sizeof(struct test_span));
1326
1327 // Set spans for testing
2127e193
GI
1328 for (i = 0; i < args.num_spans; i++){
1329 data->span[i].start = args.span[i].start;
1330 data->span[i].end = args.span[i].end;
832b75ed
GG
1331 }
1332
1333 // host must initialize to zero before initiating selective self-test
1334 data->currentlba=0;
1335 data->currentspan=0;
1336
1337 // Perform off-line scan after selective test?
2127e193 1338 if (args.scan_after_select == 1)
832b75ed
GG
1339 // NO
1340 data->flags &= ~SELECTIVE_FLAG_DOSCAN;
2127e193 1341 else if (args.scan_after_select == 2)
832b75ed
GG
1342 // YES
1343 data->flags |= SELECTIVE_FLAG_DOSCAN;
1344
1345 // Must clear active and pending flags before writing
1346 data->flags &= ~(SELECTIVE_FLAG_ACTIVE);
1347 data->flags &= ~(SELECTIVE_FLAG_PENDING);
1348
1349 // modify pending time?
2127e193
GI
1350 if (args.pending_time)
1351 data->pendingtime = (unsigned short)(args.pending_time-1);
832b75ed
GG
1352
1353 // Set checksum to zero, then compute checksum
1354 data->checksum=0;
a37e7145 1355 unsigned char cksum=0;
832b75ed
GG
1356 for (i=0; i<512; i++)
1357 cksum+=ptr[i];
1358 cksum=~cksum;
1359 cksum+=1;
1360 data->checksum=cksum;
1361
a37e7145 1362 // swap endian order if needed
832b75ed 1363 if (isbigendian()){
832b75ed 1364 swap2((char *)&(data->logversion));
cfbba5b9
GI
1365 for (int b = 0; b < 5; b++) {
1366 swap8((char *)&(data->span[b].start));
1367 swap8((char *)&(data->span[b].end));
832b75ed
GG
1368 }
1369 swap8((char *)&(data->currentlba));
1370 swap2((char *)&(data->currentspan));
1371 swap2((char *)&(data->flags));
1372 swap2((char *)&(data->pendingtime));
1373 }
1374
1375 // write new selective self-test log
1376 if (smartcommandhandler(device, WRITE_LOG, 0x09, (char *)data)){
ee38a438 1377 pout("Write Selective Self-test Log failed: %s\n", device->get_errmsg());
832b75ed
GG
1378 return -3;
1379 }
1380
1381 return 0;
1382}
1383
1384// This corrects some quantities that are byte reversed in the SMART
1385// ATA ERROR LOG.
2127e193
GI
1386static void fixsamsungerrorlog(ata_smart_errorlog * data)
1387{
832b75ed
GG
1388 // FIXED IN SAMSUNG -25 FIRMWARE???
1389 // Device error count in bytes 452-3
1390 swap2((char *)&(data->ata_error_count));
1391
1392 // FIXED IN SAMSUNG -22a FIRMWARE
1393 // step through 5 error log data structures
2127e193 1394 for (int i = 0; i < 5; i++){
832b75ed 1395 // step through 5 command data structures
2127e193 1396 for (int j = 0; j < 5; j++)
832b75ed
GG
1397 // Command data structure 4-byte millisec timestamp. These are
1398 // bytes (N+8, N+9, N+10, N+11).
1399 swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp));
1400 // Error data structure two-byte hour life timestamp. These are
1401 // bytes (N+28, N+29).
1402 swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp));
1403 }
1404 return;
1405}
1406
1407// NEEDED ONLY FOR SAMSUNG -22 (some) -23 AND -24?? FIRMWARE
2127e193
GI
1408static void fixsamsungerrorlog2(ata_smart_errorlog * data)
1409{
832b75ed
GG
1410 // Device error count in bytes 452-3
1411 swap2((char *)&(data->ata_error_count));
1412 return;
1413}
1414
1415// Reads the Summary SMART Error Log (log #1). The Comprehensive SMART
1416// Error Log is #2, and the Extended Comprehensive SMART Error log is
1417// #3
2127e193 1418int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
ee38a438 1419 firmwarebug_defs firmwarebugs)
2127e193 1420{
832b75ed
GG
1421
1422 // get data from device
1423 if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){
832b75ed
GG
1424 return -1;
1425 }
1426
1427 // compute its checksum, and issue a warning if needed
2127e193 1428 if (checksum(data))
832b75ed
GG
1429 checksumwarning("SMART ATA Error Log Structure");
1430
1431 // Some disks have the byte order reversed in some SMART Summary
1432 // Error log entries
ee38a438 1433 if (firmwarebugs.is_set(BUG_SAMSUNG))
832b75ed 1434 fixsamsungerrorlog(data);
ee38a438 1435 else if (firmwarebugs.is_set(BUG_SAMSUNG2))
832b75ed
GG
1436 fixsamsungerrorlog2(data);
1437
a37e7145 1438 // swap endian order if needed
832b75ed
GG
1439 if (isbigendian()){
1440 int i,j;
1441
1442 // Device error count in bytes 452-3
1443 swap2((char *)&(data->ata_error_count));
1444
1445 // step through 5 error log data structures
1446 for (i=0; i<5; i++){
1447 // step through 5 command data structures
1448 for (j=0; j<5; j++)
1449 // Command data structure 4-byte millisec timestamp
1450 swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp));
1451 // Error data structure life timestamp
1452 swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp));
1453 }
1454 }
1455
1456 return 0;
1457}
1458
ee38a438
GI
1459
1460// Fix LBA byte ordering of Extended Comprehensive Error Log
1461// if little endian instead of ATA register ordering is provided
1462template <class T>
1463static inline void fix_exterrlog_lba_cmd(T & cmd)
1464{
1465 T org = cmd;
1466 cmd.lba_mid_register_hi = org.lba_high_register;
1467 cmd.lba_low_register_hi = org.lba_mid_register_hi;
1468 cmd.lba_high_register = org.lba_mid_register;
1469 cmd.lba_mid_register = org.lba_low_register_hi;
1470}
1471
1472static void fix_exterrlog_lba(ata_smart_exterrlog * log, unsigned nsectors)
1473{
1474 for (unsigned i = 0; i < nsectors; i++) {
1475 for (int ei = 0; ei < 4; ei++) {
1476 ata_smart_exterrlog_error_log & entry = log[i].error_logs[ei];
1477 fix_exterrlog_lba_cmd(entry.error);
1478 for (int ci = 0; ci < 5; ci++)
1479 fix_exterrlog_lba_cmd(entry.commands[ci]);
1480 }
1481 }
1482}
1483
2127e193
GI
1484// Read Extended Comprehensive Error Log
1485bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log,
293b5ab8 1486 unsigned page, unsigned nsectors, firmwarebug_defs firmwarebugs)
2127e193 1487{
293b5ab8 1488 if (!ataReadLogExt(device, 0x03, 0x00, page, log, nsectors))
2127e193
GI
1489 return false;
1490
1491 check_multi_sector_sum(log, nsectors, "SMART Extended Comprehensive Error Log Structure");
1492
1493 if (isbigendian()) {
1494 swapx(&log->device_error_count);
1495 swapx(&log->error_log_index);
2127e193 1496 for (unsigned i = 0; i < nsectors; i++) {
d2e702cf
GI
1497 for (unsigned j = 0; j < 4; j++) {
1498 for (unsigned k = 0; k < 5; k++)
1499 swapx(&log[i].error_logs[j].commands[k].timestamp);
1500 swapx(&log[i].error_logs[j].error.timestamp);
1501 }
2127e193
GI
1502 }
1503 }
1504
ee38a438
GI
1505 if (firmwarebugs.is_set(BUG_XERRORLBA))
1506 fix_exterrlog_lba(log, nsectors);
1507
2127e193
GI
1508 return true;
1509}
1510
1511
1512int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt *data){
832b75ed
GG
1513
1514 // get data from device
1515 if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){
832b75ed
GG
1516 return -1;
1517 }
1518
1519 // compute its checksum, and issue a warning if needed
2127e193 1520 if (checksum(data))
832b75ed
GG
1521 checksumwarning("SMART Attribute Thresholds Structure");
1522
a37e7145 1523 // swap endian order if needed
832b75ed
GG
1524 if (isbigendian())
1525 swap2((char *)&(data->revnumber));
1526
1527 return 0;
1528}
1529
2127e193 1530int ataEnableSmart (ata_device * device ){
832b75ed 1531 if (smartcommandhandler(device, ENABLE, 0, NULL)){
832b75ed
GG
1532 return -1;
1533 }
1534 return 0;
1535}
1536
2127e193 1537int ataDisableSmart (ata_device * device ){
832b75ed
GG
1538
1539 if (smartcommandhandler(device, DISABLE, 0, NULL)){
832b75ed
GG
1540 return -1;
1541 }
1542 return 0;
1543}
1544
2127e193 1545int ataEnableAutoSave(ata_device * device){
832b75ed 1546 if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){
832b75ed
GG
1547 return -1;
1548 }
1549 return 0;
1550}
1551
2127e193 1552int ataDisableAutoSave(ata_device * device){
832b75ed
GG
1553
1554 if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){
832b75ed
GG
1555 return -1;
1556 }
1557 return 0;
1558}
1559
1560// In *ALL* ATA standards the Enable/Disable AutoOffline command is
1561// marked "OBSOLETE". It is defined in SFF-8035i Revision 2, and most
1562// vendors still support it for backwards compatibility. IBM documents
1563// it for some drives.
2127e193 1564int ataEnableAutoOffline (ata_device * device){
832b75ed
GG
1565
1566 /* timer hard coded to 4 hours */
1567 if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){
832b75ed
GG
1568 return -1;
1569 }
1570 return 0;
1571}
1572
1573// Another Obsolete Command. See comments directly above, associated
1574// with the corresponding Enable command.
2127e193 1575int ataDisableAutoOffline (ata_device * device){
832b75ed
GG
1576
1577 if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){
832b75ed
GG
1578 return -1;
1579 }
1580 return 0;
1581}
1582
1583// If SMART is enabled, supported, and working, then this call is
1584// guaranteed to return 1, else zero. Note that it should return 1
1585// regardless of whether the disk's SMART status is 'healthy' or
1586// 'failing'.
2127e193 1587int ataDoesSmartWork(ata_device * device){
832b75ed
GG
1588 int retval=smartcommandhandler(device, STATUS, 0, NULL);
1589
1590 if (-1 == retval)
1591 return 0;
1592
1593 return 1;
1594}
1595
1596// This function uses a different interface (DRIVE_TASK) than the
1597// other commands in this file.
2127e193 1598int ataSmartStatus2(ata_device * device){
832b75ed
GG
1599 return smartcommandhandler(device, STATUS_CHECK, 0, NULL);
1600}
1601
1602// This is the way to execute ALL tests: offline, short self-test,
1603// extended self test, with and without captive mode, etc.
2127e193 1604// TODO: Move to ataprint.cpp ?
d008864d
GI
1605int ataSmartTest(ata_device * device, int testtype, bool force,
1606 const ata_selective_selftest_args & selargs,
2127e193 1607 const ata_smart_values * sv, uint64_t num_sectors)
a37e7145 1608{
2127e193 1609 char cmdmsg[128]; const char *type, *captive;
a7e8ffec 1610 int cap, retval, select=0;
832b75ed
GG
1611
1612 // Boolean, if set, says test is captive
1613 cap=testtype & CAPTIVE_MASK;
1614
1615 // Set up strings that describe the type of test
1616 if (cap)
1617 captive="captive";
1618 else
1619 captive="off-line";
1620
1621 if (testtype==OFFLINE_FULL_SCAN)
1622 type="off-line";
1623 else if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST)
1624 type="Short self-test";
1625 else if (testtype==EXTEND_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST)
1626 type="Extended self-test";
1627 else if (testtype==CONVEYANCE_SELF_TEST || testtype==CONVEYANCE_CAPTIVE_SELF_TEST)
1628 type="Conveyance self-test";
1629 else if ((select=(testtype==SELECTIVE_SELF_TEST || testtype==SELECTIVE_CAPTIVE_SELF_TEST)))
1630 type="Selective self-test";
1631 else
cfbba5b9 1632 type = 0;
d008864d
GI
1633
1634 // Check whether another test is already running
1635 if (type && (sv->self_test_exec_status >> 4) == 0xf) {
1636 if (!force) {
1637 pout("Can't start self-test without aborting current test (%d0%% remaining),\n"
1638 "%srun 'smartctl -X' to abort test.\n",
1639 sv->self_test_exec_status & 0x0f,
1640 (!select ? "add '-t force' option to override, or " : ""));
1641 return -1;
1642 }
1643 }
1644 else
1645 force = false;
1646
832b75ed
GG
1647 // If doing a selective self-test, first use WRITE_LOG to write the
1648 // selective self-test log.
2127e193
GI
1649 ata_selective_selftest_args selargs_io = selargs; // filled with info about actual spans
1650 if (select && (retval = ataWriteSelectiveSelfTestLog(device, selargs_io, sv, num_sectors))) {
832b75ed
GG
1651 if (retval==-4)
1652 pout("Can't start selective self-test without aborting current test: use '-X' option to smartctl.\n");
1653 return retval;
1654 }
1655
1656 // Print ouf message that we are sending the command to test
1657 if (testtype==ABORT_SELF_TEST)
ee38a438 1658 snprintf(cmdmsg, sizeof(cmdmsg), "Abort SMART off-line mode self-test routine");
cfbba5b9 1659 else if (!type)
ee38a438 1660 snprintf(cmdmsg, sizeof(cmdmsg), "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype);
832b75ed 1661 else
ee38a438 1662 snprintf(cmdmsg, sizeof(cmdmsg), "Execute SMART %s routine immediately in %s mode", type, captive);
832b75ed
GG
1663 pout("Sending command: \"%s\".\n",cmdmsg);
1664
1665 if (select) {
1666 int i;
1667 pout("SPAN STARTING_LBA ENDING_LBA\n");
2127e193 1668 for (i = 0; i < selargs_io.num_spans; i++)
d2e702cf 1669 pout(" %d %20" PRId64 " %20" PRId64 "\n", i,
2127e193
GI
1670 selargs_io.span[i].start,
1671 selargs_io.span[i].end);
832b75ed
GG
1672 }
1673
1674 // Now send the command to test
a7e8ffec
GI
1675 if (smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL)) {
1676 if (!(cap && device->get_errno() == EIO)) {
1677 pout("Command \"%s\" failed: %s\n", cmdmsg, device->get_errmsg());
1678 return -1;
1679 }
832b75ed
GG
1680 }
1681
1682 // Since the command succeeded, tell user
1683 if (testtype==ABORT_SELF_TEST)
1684 pout("Self-testing aborted!\n");
cfbba5b9
GI
1685 else {
1686 pout("Drive command \"%s\" successful.\n", cmdmsg);
1687 if (type)
d008864d 1688 pout("Testing has begun%s.\n", (force ? " (previous test aborted)" : ""));
cfbba5b9 1689 }
832b75ed
GG
1690 return 0;
1691}
1692
1693/* Test Time Functions */
2127e193
GI
1694int TestTime(const ata_smart_values *data, int testtype)
1695{
832b75ed
GG
1696 switch (testtype){
1697 case OFFLINE_FULL_SCAN:
1698 return (int) data->total_time_to_complete_off_line;
1699 case SHORT_SELF_TEST:
1700 case SHORT_CAPTIVE_SELF_TEST:
1701 return (int) data->short_test_completion_time;
1702 case EXTEND_SELF_TEST:
1703 case EXTEND_CAPTIVE_SELF_TEST:
d008864d
GI
1704 if (data->extend_test_completion_time_b == 0xff
1705 && data->extend_test_completion_time_w != 0x0000
1706 && data->extend_test_completion_time_w != 0xffff)
1707 return data->extend_test_completion_time_w; // ATA-8
1708 else
1709 return data->extend_test_completion_time_b;
832b75ed
GG
1710 case CONVEYANCE_SELF_TEST:
1711 case CONVEYANCE_CAPTIVE_SELF_TEST:
1712 return (int) data->conveyance_test_completion_time;
1713 default:
1714 return 0;
1715 }
1716}
1717
1718// This function tells you both about the ATA error log and the
1719// self-test error log capability (introduced in ATA-5). The bit is
1720// poorly documented in the ATA/ATAPI standard. Starting with ATA-6,
1721// SMART error logging is also indicated in bit 0 of DEVICE IDENTIFY
1722// word 84 and 87. Top two bits must match the pattern 01. BEFORE
1723// ATA-6 these top two bits still had to match the pattern 01, but the
1724// remaining bits were reserved (==0).
2127e193
GI
1725int isSmartErrorLogCapable (const ata_smart_values * data, const ata_identify_device * identity)
1726{
832b75ed
GG
1727 unsigned short word84=identity->command_set_extension;
1728 unsigned short word87=identity->csf_default;
1729 int isata6=identity->major_rev_num & (0x01<<6);
1730 int isata7=identity->major_rev_num & (0x01<<7);
1731
1732 if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x01))
1733 return 1;
1734
1735 if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x01))
1736 return 1;
1737
1738 // otherwise we'll use the poorly documented capability bit
1739 return data->errorlog_capability & 0x01;
1740}
1741
1742// See previous function. If the error log exists then the self-test
1743// log should (must?) also exist.
2127e193
GI
1744int isSmartTestLogCapable (const ata_smart_values * data, const ata_identify_device *identity)
1745{
832b75ed
GG
1746 unsigned short word84=identity->command_set_extension;
1747 unsigned short word87=identity->csf_default;
1748 int isata6=identity->major_rev_num & (0x01<<6);
1749 int isata7=identity->major_rev_num & (0x01<<7);
1750
1751 if ((isata6 || isata7) && (word84>>14) == 0x01 && (word84 & 0x02))
1752 return 1;
1753
1754 if ((isata6 || isata7) && (word87>>14) == 0x01 && (word87 & 0x02))
1755 return 1;
1756
1757
1758 // otherwise we'll use the poorly documented capability bit
2127e193 1759 return data->errorlog_capability & 0x01;
832b75ed
GG
1760}
1761
1762
2127e193
GI
1763int isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
1764{
832b75ed
GG
1765 unsigned short word84=identity->command_set_extension;
1766 unsigned short word87=identity->csf_default;
1767
1768 // If bit 14 of word 84 is set to one and bit 15 of word 84 is
1769 // cleared to zero, the contents of word 84 contains valid support
1770 // information. If not, support information is not valid in this
1771 // word.
1772 if ((word84>>14) == 0x01)
1773 // If bit 5 of word 84 is set to one, the device supports the
1774 // General Purpose Logging feature set.
1775 return (word84 & (0x01 << 5));
1776
1777 // If bit 14 of word 87 is set to one and bit 15 of word 87 is
1778 // cleared to zero, the contents of words (87:85) contain valid
1779 // information. If not, information is not valid in these words.
1780 if ((word87>>14) == 0x01)
1781 // If bit 5 of word 87 is set to one, the device supports
1782 // the General Purpose Logging feature set.
1783 return (word87 & (0x01 << 5));
1784
1785 // not capable
1786 return 0;
1787}
1788
1789
1790// SMART self-test capability is also indicated in bit 1 of DEVICE
1791// IDENTIFY word 87 (if top two bits of word 87 match pattern 01).
1792// However this was only introduced in ATA-6 (but self-test log was in
1793// ATA-5).
2127e193
GI
1794int isSupportExecuteOfflineImmediate(const ata_smart_values *data)
1795{
1796 return data->offline_data_collection_capability & 0x01;
832b75ed 1797}
2127e193 1798
832b75ed
GG
1799// Note in the ATA-5 standard, the following bit is listed as "Vendor
1800// Specific". So it may not be reliable. The only use of this that I
1801// have found is in IBM drives, where it is well-documented. See for
1802// example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
1803// hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
2127e193
GI
1804int isSupportAutomaticTimer(const ata_smart_values * data)
1805{
1806 return data->offline_data_collection_capability & 0x02;
832b75ed 1807}
2127e193
GI
1808int isSupportOfflineAbort(const ata_smart_values *data)
1809{
1810 return data->offline_data_collection_capability & 0x04;
832b75ed 1811}
2127e193
GI
1812int isSupportOfflineSurfaceScan(const ata_smart_values * data)
1813{
832b75ed
GG
1814 return data->offline_data_collection_capability & 0x08;
1815}
2127e193
GI
1816int isSupportSelfTest (const ata_smart_values * data)
1817{
832b75ed
GG
1818 return data->offline_data_collection_capability & 0x10;
1819}
2127e193
GI
1820int isSupportConveyanceSelfTest(const ata_smart_values * data)
1821{
832b75ed
GG
1822 return data->offline_data_collection_capability & 0x20;
1823}
2127e193
GI
1824int isSupportSelectiveSelfTest(const ata_smart_values * data)
1825{
832b75ed
GG
1826 return data->offline_data_collection_capability & 0x40;
1827}
1828
bed94269
GI
1829// Get attribute state
1830ata_attr_state ata_get_attr_state(const ata_smart_attribute & attr,
cfbba5b9
GI
1831 int attridx,
1832 const ata_smart_threshold_entry * thresholds,
1833 const ata_vendor_attr_defs & defs,
1834 unsigned char * threshval /* = 0 */)
bed94269
GI
1835{
1836 if (!attr.id)
1837 return ATTRSTATE_NON_EXISTING;
832b75ed 1838
bed94269
GI
1839 // Normalized values (current,worst,threshold) not valid
1840 // if specified by '-v' option.
1841 // (Some SSD disks uses these bytes to store raw value).
1842 if (defs[attr.id].flags & ATTRFLAG_NO_NORMVAL)
1843 return ATTRSTATE_NO_NORMVAL;
832b75ed 1844
cfbba5b9
GI
1845 // Normally threshold is at same index as attribute
1846 int i = attridx;
1847 if (thresholds[i].id != attr.id) {
1848 // Find threshold id in table
1849 for (i = 0; thresholds[i].id != attr.id; ) {
1850 if (++i >= NUMBER_ATA_SMART_ATTRIBUTES)
1851 // Threshold id missing or thresholds cannot be read
1852 return ATTRSTATE_NO_THRESHOLD;
1853 }
1854 }
1855 unsigned char threshold = thresholds[i].threshold;
832b75ed 1856
cfbba5b9
GI
1857 // Return threshold if requested
1858 if (threshval)
1859 *threshval = threshold;
832b75ed 1860
bed94269
GI
1861 // Don't report a failed attribute if its threshold is 0.
1862 // ATA-3 (X3T13/2008D Revision 7b) declares 0x00 as the "always passing"
1863 // threshold (Later ATA versions declare all thresholds as "obsolete").
1864 // In practice, threshold value 0 is often used for usage attributes.
cfbba5b9 1865 if (!threshold)
bed94269 1866 return ATTRSTATE_OK;
832b75ed 1867
bed94269 1868 // Failed now if current value is below threshold
cfbba5b9 1869 if (attr.current <= threshold)
bed94269 1870 return ATTRSTATE_FAILED_NOW;
832b75ed 1871
a23d5117 1872 // Failed in the past if worst value is below threshold
cfbba5b9 1873 if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL) && attr.worst <= threshold)
bed94269 1874 return ATTRSTATE_FAILED_PAST;
832b75ed 1875
bed94269 1876 return ATTRSTATE_OK;
832b75ed
GG
1877}
1878
bed94269
GI
1879// Get attribute raw value.
1880uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr,
1881 const ata_vendor_attr_defs & defs)
1882{
a23d5117 1883 const ata_vendor_attr_defs::entry & def = defs[attr.id];
6b80b4d2 1884 // TODO: Allow Byteorder in DEFAULT entry
a23d5117
GI
1885
1886 // Use default byteorder if not specified
1887 const char * byteorder = def.byteorder;
1888 if (!*byteorder) {
cfbba5b9
GI
1889 switch (def.raw_format) {
1890 case RAWFMT_RAW64:
1891 case RAWFMT_HEX64:
1892 byteorder = "543210wv"; break;
e165493d
GI
1893 case RAWFMT_RAW56:
1894 case RAWFMT_HEX56:
cfbba5b9
GI
1895 case RAWFMT_RAW24_DIV_RAW32:
1896 case RAWFMT_MSEC24_HOUR32:
1897 byteorder = "r543210"; break;
1898 default:
1899 byteorder = "543210"; break;
1900 }
a23d5117
GI
1901 }
1902
1903 // Build 64-bit value from selected bytes
1904 uint64_t rawvalue = 0;
1905 for (int i = 0; byteorder[i]; i++) {
1906 unsigned char b;
1907 switch (byteorder[i]) {
1908 case '0': b = attr.raw[0]; break;
1909 case '1': b = attr.raw[1]; break;
1910 case '2': b = attr.raw[2]; break;
1911 case '3': b = attr.raw[3]; break;
1912 case '4': b = attr.raw[4]; break;
1913 case '5': b = attr.raw[5]; break;
1914 case 'r': b = attr.reserv; break;
1915 case 'v': b = attr.current; break;
1916 case 'w': b = attr.worst; break;
1917 default : b = 0; break;
1918 }
1919 rawvalue <<= 8; rawvalue |= b;
a37e7145 1920 }
a23d5117 1921
bed94269 1922 return rawvalue;
a37e7145
GG
1923}
1924
d2e702cf
GI
1925// Helper functions for RAWFMT_TEMPMINMAX
1926static inline int check_temp_word(unsigned word)
1927{
1928 if (word <= 0x7f)
1929 return 0x11; // >= 0, signed byte or word
1930 if (word <= 0xff)
1931 return 0x01; // < 0, signed byte
1932 if (0xff80 <= word)
1933 return 0x10; // < 0, signed word
1934 return 0x00;
1935}
1936
1937static bool check_temp_range(int t, unsigned char ut1, unsigned char ut2,
1938 int & lo, int & hi)
1939{
1940 int t1 = (signed char)ut1, t2 = (signed char)ut2;
1941 if (t1 > t2) {
1942 int tx = t1; t1 = t2; t2 = tx;
1943 }
1944
1945 if ( -60 <= t1 && t1 <= t && t <= t2 && t2 <= 120
1946 && !(t1 == -1 && t2 <= 0) ) {
1947 lo = t1; hi = t2;
1948 return true;
1949 }
1950 return false;
1951}
a37e7145 1952
bed94269
GI
1953// Format attribute raw value.
1954std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
1955 const ata_vendor_attr_defs & defs)
1956{
a23d5117 1957 // Get 48 bit or 64 bit raw value
bed94269 1958 uint64_t rawvalue = ata_get_attr_raw_value(attr, defs);
832b75ed 1959
a7e8ffec
GI
1960 // Split into bytes and words
1961 unsigned char raw[6];
1962 raw[0] = (unsigned char) rawvalue;
1963 raw[1] = (unsigned char)(rawvalue >> 8);
1964 raw[2] = (unsigned char)(rawvalue >> 16);
1965 raw[3] = (unsigned char)(rawvalue >> 24);
1966 raw[4] = (unsigned char)(rawvalue >> 32);
1967 raw[5] = (unsigned char)(rawvalue >> 40);
832b75ed 1968 unsigned word[3];
bed94269
GI
1969 word[0] = raw[0] | (raw[1] << 8);
1970 word[1] = raw[2] | (raw[3] << 8);
1971 word[2] = raw[4] | (raw[5] << 8);
832b75ed 1972
bed94269
GI
1973 // Get print format
1974 ata_attr_raw_format format = defs[attr.id].raw_format;
6b80b4d2
JD
1975 if (format == RAWFMT_DEFAULT) {
1976 // Get format from DEFAULT entry
1977 format = get_default_attr_defs()[attr.id].raw_format;
1978 if (format == RAWFMT_DEFAULT)
1979 // Unknown Attribute
1980 format = RAWFMT_RAW48;
1981 }
bed94269
GI
1982
1983 // Print
1984 std::string s;
1985 switch (format) {
1986 case RAWFMT_RAW8:
1987 s = strprintf("%d %d %d %d %d %d",
1988 raw[5], raw[4], raw[3], raw[2], raw[1], raw[0]);
832b75ed 1989 break;
bed94269
GI
1990
1991 case RAWFMT_RAW16:
1992 s = strprintf("%u %u %u", word[2], word[1], word[0]);
1993 break;
1994
1995 case RAWFMT_RAW48:
e165493d 1996 case RAWFMT_RAW56:
a23d5117 1997 case RAWFMT_RAW64:
d2e702cf 1998 s = strprintf("%" PRIu64, rawvalue);
bed94269
GI
1999 break;
2000
2001 case RAWFMT_HEX48:
d2e702cf 2002 s = strprintf("0x%012" PRIx64, rawvalue);
bed94269
GI
2003 break;
2004
e165493d 2005 case RAWFMT_HEX56:
d2e702cf 2006 s = strprintf("0x%014" PRIx64, rawvalue);
e165493d
GI
2007 break;
2008
bed94269 2009 case RAWFMT_HEX64:
d2e702cf 2010 s = strprintf("0x%016" PRIx64, rawvalue);
bed94269
GI
2011 break;
2012
2013 case RAWFMT_RAW16_OPT_RAW16:
2014 s = strprintf("%u", word[0]);
2127e193 2015 if (word[1] || word[2])
e165493d 2016 s += strprintf(" (%u %u)", word[2], word[1]);
2127e193 2017 break;
bed94269
GI
2018
2019 case RAWFMT_RAW16_OPT_AVG16:
2020 s = strprintf("%u", word[0]);
2021 if (word[1])
2022 s += strprintf(" (Average %u)", word[1]);
2023 break;
2024
e165493d
GI
2025 case RAWFMT_RAW24_OPT_RAW8:
2026 s = strprintf("%u", (unsigned)(rawvalue & 0x00ffffffULL));
2027 if (raw[3] || raw[4] || raw[5])
2028 s += strprintf(" (%d %d %d)", raw[5], raw[4], raw[3]);
2029 break;
2030
cfbba5b9
GI
2031 case RAWFMT_RAW24_DIV_RAW24:
2032 s = strprintf("%u/%u",
2033 (unsigned)(rawvalue >> 24), (unsigned)(rawvalue & 0x00ffffffULL));
2034 break;
2035
2036 case RAWFMT_RAW24_DIV_RAW32:
2037 s = strprintf("%u/%u",
2038 (unsigned)(rawvalue >> 32), (unsigned)(rawvalue & 0xffffffffULL));
bed94269
GI
2039 break;
2040
2041 case RAWFMT_MIN2HOUR:
2042 {
832b75ed 2043 // minutes
bed94269
GI
2044 int64_t temp = word[0]+(word[1]<<16);
2045 int64_t tmp1 = temp/60;
2046 int64_t tmp2 = temp%60;
d2e702cf 2047 s = strprintf("%" PRIu64 "h+%02" PRIu64 "m", tmp1, tmp2);
2127e193 2048 if (word[2])
bed94269 2049 s += strprintf(" (%u)", word[2]);
832b75ed 2050 }
bed94269
GI
2051 break;
2052
2053 case RAWFMT_SEC2HOUR:
2054 {
832b75ed 2055 // seconds
bed94269
GI
2056 int64_t hours = rawvalue/3600;
2057 int64_t minutes = (rawvalue-3600*hours)/60;
2058 int64_t seconds = rawvalue%60;
d2e702cf 2059 s = strprintf("%" PRIu64 "h+%02" PRIu64 "m+%02" PRIu64 "s", hours, minutes, seconds);
832b75ed 2060 }
a37e7145 2061 break;
bed94269
GI
2062
2063 case RAWFMT_HALFMIN2HOUR:
2064 {
2065 // 30-second counter
2066 int64_t hours = rawvalue/120;
2067 int64_t minutes = (rawvalue-120*hours)/2;
d2e702cf 2068 s += strprintf("%" PRIu64 "h+%02" PRIu64 "m", hours, minutes);
832b75ed 2069 }
832b75ed 2070 break;
bed94269 2071
cfbba5b9
GI
2072 case RAWFMT_MSEC24_HOUR32:
2073 {
2074 // hours + milliseconds
2075 unsigned hours = (unsigned)(rawvalue & 0xffffffffULL);
2076 unsigned milliseconds = (unsigned)(rawvalue >> 32);
2077 unsigned seconds = milliseconds / 1000;
2078 s = strprintf("%uh+%02um+%02u.%03us",
2079 hours, seconds / 60, seconds % 60, milliseconds % 1000);
2080 }
2081 break;
2082
bed94269 2083 case RAWFMT_TEMPMINMAX:
832b75ed 2084 // Temperature
d008864d
GI
2085 {
2086 // Search for possible min/max values
d2e702cf
GI
2087 // [5][4][3][2][1][0] raw[]
2088 // [ 2 ] [ 1 ] [ 0 ] word[]
2089 // xx HH xx LL xx TT (Hitachi/HGST)
2090 // xx LL xx HH xx TT (Kingston SSDs)
2091 // 00 00 HH LL xx TT (Maxtor, Samsung, Seagate, Toshiba)
d008864d 2092 // 00 00 00 HH LL TT (WDC)
d2e702cf
GI
2093 // CC CC HH LL xx TT (WDC, CCCC=over temperature count)
2094 // (xx = 00/ff, possibly sign extension of lower byte)
2095
2096 int t = (signed char)raw[0];
2097 int lo = 0, hi = 0;
2098
2099 int tformat;
2100 int ctw0 = check_temp_word(word[0]);
2101 if (!word[2]) {
2102 if (!word[1] && ctw0)
2103 // 00 00 00 00 xx TT
2104 tformat = 0;
2105 else if (ctw0 && check_temp_range(t, raw[2], raw[3], lo, hi))
2106 // 00 00 HL LH xx TT
2107 tformat = 1;
2108 else if (!raw[3] && check_temp_range(t, raw[1], raw[2], lo, hi))
2109 // 00 00 00 HL LH TT
2110 tformat = 2;
2111 else
2112 tformat = -1;
2113 }
2114 else if (ctw0) {
2115 if ( (ctw0 & check_temp_word(word[1]) & check_temp_word(word[2])) != 0x00
2116 && check_temp_range(t, raw[2], raw[4], lo, hi) )
2117 // xx HL xx LH xx TT
2118 tformat = 3;
2119 else if ( word[2] < 0x7fff
2120 && check_temp_range(t, raw[2], raw[3], lo, hi)
2121 && hi >= 40 )
2122 // CC CC HL LH xx TT
2123 tformat = 4;
2124 else
2125 tformat = -2;
bed94269 2126 }
bed94269 2127 else
d2e702cf
GI
2128 tformat = -3;
2129
2130 switch (tformat) {
2131 case 0:
2132 s = strprintf("%d", t);
2133 break;
2134 case 1: case 2: case 3:
2135 s = strprintf("%d (Min/Max %d/%d)", t, lo, hi);
2136 break;
2137 case 4:
2138 s = strprintf("%d (Min/Max %d/%d #%d)", t, lo, hi, word[2]);
2139 break;
2140 default:
2141 s = strprintf("%d (%d %d %d %d %d)", raw[0], raw[5], raw[4], raw[3], raw[2], raw[1]);
2142 break;
2143 }
832b75ed 2144 }
832b75ed 2145 break;
bed94269
GI
2146
2147 case RAWFMT_TEMP10X:
2148 // ten times temperature in Celsius
2149 s = strprintf("%d.%d", word[0]/10, word[0]%10);
2127e193 2150 break;
bed94269 2151
832b75ed 2152 default:
bed94269
GI
2153 s = "?"; // Should not happen
2154 break;
832b75ed 2155 }
832b75ed 2156
bed94269
GI
2157 return s;
2158}
832b75ed 2159
bed94269 2160// Get attribute name
ee38a438
GI
2161std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs,
2162 int rpm /* = 0 */)
2127e193 2163{
bed94269
GI
2164 if (!defs[id].name.empty())
2165 return defs[id].name;
6b80b4d2
JD
2166 else {
2167 const ata_vendor_attr_defs::entry & def = get_default_attr_defs()[id];
2168 if (def.name.empty())
2169 return "Unknown_Attribute";
2170 else if ((def.flags & ATTRFLAG_HDD_ONLY) && rpm == 1)
2171 return "Unknown_SSD_Attribute";
2172 else if ((def.flags & ATTRFLAG_SSD_ONLY) && rpm > 1)
2173 return "Unknown_HDD_Attribute";
2174 else
2175 return def.name;
2176 }
bed94269
GI
2177}
2178
2179// Find attribute index for attribute id, -1 if not found.
2180int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval)
2181{
2182 if (!id)
832b75ed 2183 return -1;
2127e193 2184 for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
bed94269
GI
2185 if (smartval.vendor_attributes[i].id == id)
2186 return i;
2187 }
832b75ed
GG
2188 return -1;
2189}
2190
4d59bff9
GG
2191// Return Temperature Attribute raw value selected according to possible
2192// non-default interpretations. If the Attribute does not exist, return 0
bed94269 2193unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs)
2127e193 2194{
ee38a438
GI
2195 for (int i = 0; i < 4; i++) {
2196 static const unsigned char ids[4] = {194, 190, 9, 220};
4d59bff9 2197 unsigned char id = ids[i];
bed94269 2198 const ata_attr_raw_format format = defs[id].raw_format;
ee38a438 2199 if (!( ((id == 194 || id == 190) && format == RAWFMT_DEFAULT)
bed94269 2200 || format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X))
4d59bff9 2201 continue;
bed94269
GI
2202 int idx = ata_find_attr_index(id, *data);
2203 if (idx < 0)
4d59bff9 2204 continue;
bed94269 2205 uint64_t raw = ata_get_attr_raw_value(data->vendor_attributes[idx], defs);
d008864d
GI
2206 unsigned temp;
2207 // ignore possible min/max values in high words
bed94269 2208 if (format == RAWFMT_TEMP10X) // -v N,temp10x
d008864d
GI
2209 temp = ((unsigned short)raw + 5) / 10;
2210 else
2211 temp = (unsigned char)raw;
2212 if (!(0 < temp && temp < 128))
4d59bff9
GG
2213 continue;
2214 return temp;
2215 }
2216 // No valid attribute found
2217 return 0;
2218}
a37e7145 2219
2127e193 2220
a37e7145 2221// Read SCT Status
2127e193 2222int ataReadSCTStatus(ata_device * device, ata_sct_status_response * sts)
a37e7145
GG
2223{
2224 // read SCT status via SMART log 0xe0
2225 memset(sts, 0, sizeof(*sts));
2226 if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){
ee38a438 2227 pout("Read SCT Status failed: %s\n", device->get_errmsg());
a37e7145
GG
2228 return -1;
2229 }
2230
2231 // swap endian order if needed
2232 if (isbigendian()){
2233 swapx(&sts->format_version);
2234 swapx(&sts->sct_version);
2235 swapx(&sts->sct_spec);
2236 swapx(&sts->ext_status_code);
2237 swapx(&sts->action_code);
2238 swapx(&sts->function_code);
2239 swapx(&sts->over_limit_count);
2240 swapx(&sts->under_limit_count);
1d06b804 2241 swapx(&sts->smart_status);
a37e7145
GG
2242 }
2243
2244 // Check format version
2245 if (!(sts->format_version == 2 || sts->format_version == 3)) {
ee38a438 2246 pout("Unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version);
a37e7145
GG
2247 return -1;
2248 }
2249 return 0;
2250}
2251
d2e702cf 2252// Read SCT Temperature History Table
2127e193 2253int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table * tmh,
a37e7145
GG
2254 ata_sct_status_response * sts)
2255{
d2e702cf 2256 // Initial SCT status must be provided by caller
a37e7145
GG
2257
2258 // Do nothing if other SCT command is executing
2259 if (sts->ext_status_code == 0xffff) {
2260 pout("Another SCT command is executing, abort Read Data Table\n"
2261 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2262 sts->ext_status_code, sts->action_code, sts->function_code);
2263 return -1;
2264 }
2265
2266 ata_sct_data_table_command cmd; memset(&cmd, 0, sizeof(cmd));
2267 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2268 cmd.action_code = 5; // Data table command
2269 cmd.function_code = 1; // Read table
2270 cmd.table_id = 2; // Temperature History Table
2271
7f0798ef
GI
2272 // swap endian order if needed
2273 if (isbigendian()) {
2274 swapx(&cmd.action_code);
2275 swapx(&cmd.function_code);
2276 swapx(&cmd.table_id);
2277 }
2278
a37e7145
GG
2279 // write command via SMART log page 0xe0
2280 if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
ee38a438 2281 pout("Write SCT Data Table failed: %s\n", device->get_errmsg());
a37e7145
GG
2282 return -1;
2283 }
2284
2285 // read SCT data via SMART log page 0xe1
2286 memset(tmh, 0, sizeof(*tmh));
2287 if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){
ee38a438 2288 pout("Read SCT Data Table failed: %s\n", device->get_errmsg());
a37e7145
GG
2289 return -1;
2290 }
2291
2292 // re-read and check SCT status
2293 if (ataReadSCTStatus(device, sts))
2294 return -1;
2295
2296 if (!(sts->ext_status_code == 0 && sts->action_code == 5 && sts->function_code == 1)) {
ee38a438 2297 pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
a37e7145
GG
2298 sts->ext_status_code, sts->action_code, sts->function_code);
2299 return -1;
2300 }
2301
2302 // swap endian order if needed
2303 if (isbigendian()){
2304 swapx(&tmh->format_version);
2305 swapx(&tmh->sampling_period);
2306 swapx(&tmh->interval);
ee38a438
GI
2307 swapx(&tmh->cb_index);
2308 swapx(&tmh->cb_size);
a37e7145
GG
2309 }
2310 return 0;
2311}
2312
3d17a85c
GI
2313// Get/Set Write Cache Reordering
2314int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool persistent, bool set)
2315{
2316 // Check initial status
2317 ata_sct_status_response sts;
2318 if (ataReadSCTStatus(device, &sts))
2319 return -1;
2320
2321 // Do nothing if other SCT command is executing
2322 if (sts.ext_status_code == 0xffff) {
2323 pout("Another SCT command is executing, abort Feature Control\n"
2324 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2325 sts.ext_status_code, sts.action_code, sts.function_code);
2326 return -1;
2327 }
2328
2329 ata_sct_feature_control_command cmd; memset(&cmd, 0, sizeof(cmd));
2330 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2331 cmd.action_code = 4; // Feature Control command
2332 cmd.function_code = (set ? 1 : 2); // 1=Set, 2=Get
2333 cmd.feature_code = 2; // Enable/Disable Write Cache Reordering
2334 cmd.state = (enable ? 1 : 2); // 1 enable, 2 disable
2335 cmd.option_flags = (persistent ? 0x01 : 0x00);
2336
2337 // swap endian order if needed
2338 if (isbigendian()) {
2339 swapx(&cmd.action_code);
2340 swapx(&cmd.function_code);
2341 swapx(&cmd.feature_code);
2342 swapx(&cmd.state);
2343 swapx(&cmd.option_flags);
2344 }
2345
2346 // write command via SMART log page 0xe0
2347 // TODO: Debug output
2348 ata_cmd_in in;
2349 in.in_regs.command = ATA_SMART_CMD;
2350 in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
2351 in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
2352 in.in_regs.lba_low = 0xe0;
2353 in.set_data_out(&cmd, 1);
2354
2355 if (!set)
2356 // Time limit returned in ATA registers
2357 in.out_needed.sector_count = in.out_needed.lba_low = true;
2358
2359 ata_cmd_out out;
2360 if (!device->ata_pass_through(in, out)) {
d2e702cf 2361 pout("Write SCT (%cet) Feature Control Command failed: %s\n",
3d17a85c
GI
2362 (!set ? 'G' : 'S'), device->get_errmsg());
2363 return -1;
2364 }
2365 int state = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
2366
2367 // re-read and check SCT status
2368 if (ataReadSCTStatus(device, &sts))
2369 return -1;
2370
2371 if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == (set ? 1 : 2))) {
2372 pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
2373 sts.ext_status_code, sts.action_code, sts.function_code);
2374 return -1;
2375 }
2376 return state;
2377}
2378
2379
a37e7145 2380// Set SCT Temperature Logging Interval
2127e193 2381int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent)
a37e7145
GG
2382{
2383 // Check initial status
2384 ata_sct_status_response sts;
2385 if (ataReadSCTStatus(device, &sts))
2386 return -1;
2387
2388 // Do nothing if other SCT command is executing
2389 if (sts.ext_status_code == 0xffff) {
2390 pout("Another SCT command is executing, abort Feature Control\n"
2391 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2392 sts.ext_status_code, sts.action_code, sts.function_code);
2393 return -1;
2394 }
2395
2396 ata_sct_feature_control_command cmd; memset(&cmd, 0, sizeof(cmd));
2397 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2398 cmd.action_code = 4; // Feature Control command
2399 cmd.function_code = 1; // Set state
2400 cmd.feature_code = 3; // Temperature logging interval
2401 cmd.state = interval;
2402 cmd.option_flags = (persistent ? 0x01 : 0x00);
2403
7f0798ef
GI
2404 // swap endian order if needed
2405 if (isbigendian()) {
2406 swapx(&cmd.action_code);
2407 swapx(&cmd.function_code);
2408 swapx(&cmd.feature_code);
2409 swapx(&cmd.state);
2410 swapx(&cmd.option_flags);
2411 }
2412
a37e7145
GG
2413 // write command via SMART log page 0xe0
2414 if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
ee38a438 2415 pout("Write SCT Feature Control Command failed: %s\n", device->get_errmsg());
a37e7145
GG
2416 return -1;
2417 }
2418
2419 // re-read and check SCT status
2420 if (ataReadSCTStatus(device, &sts))
2421 return -1;
2422
2423 if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == 1)) {
ee38a438 2424 pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
a37e7145
GG
2425 sts.ext_status_code, sts.action_code, sts.function_code);
2426 return -1;
2427 }
2428 return 0;
2429}
2430
7f0798ef
GI
2431// Get/Set SCT Error Recovery Control
2432static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned type,
2433 bool set, unsigned short & time_limit)
2434{
2435 // Check initial status
2436 ata_sct_status_response sts;
2437 if (ataReadSCTStatus(device, &sts))
2438 return -1;
2439
2440 // Do nothing if other SCT command is executing
2441 if (sts.ext_status_code == 0xffff) {
2442 pout("Another SCT command is executing, abort Error Recovery Control\n"
2443 "(SCT ext_status_code 0x%04x, action_code=%u, function_code=%u)\n",
2444 sts.ext_status_code, sts.action_code, sts.function_code);
2445 return -1;
2446 }
2447
2448 ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd));
2449 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
2450 cmd.action_code = 3; // Error Recovery Control command
2451 cmd.function_code = (set ? 1 : 2); // 1=Set timer, 2=Get timer
2452 cmd.selection_code = type; // 1=Read timer, 2=Write timer
2453 if (set)
2454 cmd.time_limit = time_limit;
2455
2456 // swap endian order if needed
2457 if (isbigendian()) {
2458 swapx(&cmd.action_code);
2459 swapx(&cmd.function_code);
2460 swapx(&cmd.selection_code);
2461 swapx(&cmd.time_limit);
2462 }
2463
2464 // write command via SMART log page 0xe0
2465 // TODO: Debug output
2466 ata_cmd_in in;
2467 in.in_regs.command = ATA_SMART_CMD;
2468 in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
2469 in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
2470 in.in_regs.lba_low = 0xe0;
2471 in.set_data_out(&cmd, 1);
2472
2473 if (!set)
2474 // Time limit returned in ATA registers
2475 in.out_needed.sector_count = in.out_needed.lba_low = true;
2476
2477 ata_cmd_out out;
2478 if (!device->ata_pass_through(in, out)) {
ee38a438 2479 pout("Write SCT (%cet) Error Recovery Control Command failed: %s\n",
cfbba5b9 2480 (!set ? 'G' : 'S'), device->get_errmsg());
7f0798ef
GI
2481 return -1;
2482 }
2483
2484 // re-read and check SCT status
2485 if (ataReadSCTStatus(device, &sts))
2486 return -1;
2487
2488 if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) {
ee38a438 2489 pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
7f0798ef
GI
2490 sts.ext_status_code, sts.action_code, sts.function_code);
2491 return -1;
2492 }
2493
2494 if (!set) {
2495 // Check whether registers are properly returned by ioctl()
2496 if (!(out.out_regs.sector_count.is_set() && out.out_regs.lba_low.is_set())) {
2497 // TODO: Output register support should be checked within each ata_pass_through()
2498 // implementation before command is issued.
ee38a438
GI
2499 pout("SMART WRITE LOG does not return COUNT and LBA_LOW register\n");
2500 return -1;
2501 }
2502 if ( out.out_regs.sector_count == in.in_regs.sector_count
2503 && out.out_regs.lba_low == in.in_regs.lba_low ) {
2504 // 0xe001 (5734.5s) - this is most likely a broken ATA pass-through implementation
2505 pout("SMART WRITE LOG returns COUNT and LBA_LOW register unchanged\n");
7f0798ef
GI
2506 return -1;
2507 }
ee38a438 2508
7f0798ef
GI
2509 // Return value to caller
2510 time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
2511 }
2512
2513 return 0;
2514}
2515
2516// Get SCT Error Recovery Control
2517int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit)
2518{
2519 return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit);
2520}
2521
2522// Set SCT Error Recovery Control
2523int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit)
2524{
2525 return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit);
2526}
2527
2528
2127e193 2529// Print one self-test log entry.
cfbba5b9
GI
2530// Returns:
2531// -1: self-test failed
2532// 1: extended self-test completed without error
2533// 0: otherwise
2534int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
2535 unsigned char test_status,
2536 unsigned short timestamp,
2537 uint64_t failing_lba,
2538 bool print_error_only, bool & print_header)
2539{
2540 // Check status and type for return value
2541 int retval = 0;
2542 switch (test_status >> 4) {
2543 case 0x0:
2544 if ((test_type & 0x0f) == 0x02)
2545 retval = 1; // extended self-test completed without error
2546 break;
2547 case 0x3: case 0x4:
2548 case 0x5: case 0x6:
2549 case 0x7: case 0x8:
2550 retval = -1; // self-test failed
2551 break;
2552 }
2553
2554 if (retval >= 0 && print_error_only)
2555 return retval;
2556
2557 std::string msgtest;
2127e193
GI
2558 switch (test_type) {
2559 case 0x00: msgtest = "Offline"; break;
2560 case 0x01: msgtest = "Short offline"; break;
2561 case 0x02: msgtest = "Extended offline"; break;
2562 case 0x03: msgtest = "Conveyance offline"; break;
2563 case 0x04: msgtest = "Selective offline"; break;
2564 case 0x7f: msgtest = "Abort offline test"; break;
2565 case 0x81: msgtest = "Short captive"; break;
2566 case 0x82: msgtest = "Extended captive"; break;
2567 case 0x83: msgtest = "Conveyance captive"; break;
2568 case 0x84: msgtest = "Selective captive"; break;
2569 default:
2570 if ((0x40 <= test_type && test_type <= 0x7e) || 0x90 <= test_type)
cfbba5b9 2571 msgtest = strprintf("Vendor (0x%02x)", test_type);
2127e193 2572 else
cfbba5b9 2573 msgtest = strprintf("Reserved (0x%02x)", test_type);
2127e193
GI
2574 }
2575
cfbba5b9 2576 std::string msgstat;
2127e193
GI
2577 switch (test_status >> 4) {
2578 case 0x0: msgstat = "Completed without error"; break;
2579 case 0x1: msgstat = "Aborted by host"; break;
2580 case 0x2: msgstat = "Interrupted (host reset)"; break;
cfbba5b9
GI
2581 case 0x3: msgstat = "Fatal or unknown error"; break;
2582 case 0x4: msgstat = "Completed: unknown failure"; break;
2583 case 0x5: msgstat = "Completed: electrical failure"; break;
2584 case 0x6: msgstat = "Completed: servo/seek failure"; break;
2585 case 0x7: msgstat = "Completed: read failure"; break;
2586 case 0x8: msgstat = "Completed: handling damage??"; break;
2127e193 2587 case 0xf: msgstat = "Self-test routine in progress"; break;
cfbba5b9 2588 default: msgstat = strprintf("Unknown status (0x%x)", test_status >> 4);
2127e193
GI
2589 }
2590
2127e193
GI
2591 // Print header once
2592 if (print_header) {
2593 print_header = false;
2594 pout("Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n");
2595 }
2596
2597 char msglba[32];
cfbba5b9 2598 if (retval < 0 && failing_lba < 0xffffffffffffULL)
d2e702cf 2599 snprintf(msglba, sizeof(msglba), "%" PRIu64, failing_lba);
ee38a438
GI
2600 else {
2601 msglba[0] = '-'; msglba[1] = 0;
2602 }
2127e193 2603
cfbba5b9
GI
2604 pout("#%2u %-19s %-29s %1d0%% %8u %s\n", testnum,
2605 msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
2127e193 2606
cfbba5b9 2607 return retval;
2127e193
GI
2608}
2609
2610// Print Smart self-test log, used by smartctl and smartd.
2611// return value is:
2612// bottom 8 bits: number of entries found where self-test showed an error
2613// remaining bits: if nonzero, power on hours of last self-test where error was found
2614int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
ee38a438 2615 firmwarebug_defs firmwarebugs)
2127e193
GI
2616{
2617 if (allentries)
2618 pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber);
ee38a438 2619 if (data->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG))
2127e193
GI
2620 pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
2621 if (data->mostrecenttest==0){
2622 if (allentries)
d2e702cf 2623 pout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n");
2127e193
GI
2624 return 0;
2625 }
2626
2627 bool noheaderprinted = true;
cfbba5b9
GI
2628 int errcnt = 0, hours = 0, igncnt = 0;
2629 int testno = 0, ext_ok_testno = -1;
2127e193
GI
2630
2631 // print log
2632 for (int i = 20; i >= 0; i--) {
2633 // log is a circular buffer
2634 int j = (i+data->mostrecenttest)%21;
2635 const ata_smart_selftestlog_struct * log = data->selftest_struct+j;
2636
2637 if (nonempty(log, sizeof(*log))) {
2638 // count entry based on non-empty structures -- needed for
2639 // Seagate only -- other vendors don't have blank entries 'in
2640 // the middle'
2641 testno++;
2642
2643 // T13/1321D revision 1c: (Data structure Rev #1)
2644
2645 //The failing LBA shall be the LBA of the uncorrectable sector
2646 //that caused the test to fail. If the device encountered more
2647 //than one uncorrectable sector during the test, this field
2648 //shall indicate the LBA of the first uncorrectable sector
2649 //encountered. If the test passed or the test failed for some
2650 //reason other than an uncorrectable sector, the value of this
2651 //field is undefined.
2652
2653 // This is true in ALL ATA-5 specs
2654 uint64_t lba48 = (log->lbafirstfailure < 0xffffffff ? log->lbafirstfailure : 0xffffffffffffULL);
2655
2656 // Print entry
cfbba5b9
GI
2657 int state = ataPrintSmartSelfTestEntry(testno,
2658 log->selftestnumber, log->selfteststatus,
2659 log->timestamp, lba48, !allentries, noheaderprinted);
2127e193 2660
cfbba5b9 2661 if (state < 0) {
f4ebf3d1 2662 // Self-test showed an error
cfbba5b9
GI
2663 if (ext_ok_testno < 0) {
2664 errcnt++;
f4ebf3d1 2665
cfbba5b9
GI
2666 // keep track of time of most recent error
2667 if (!hours)
2668 hours = log->timestamp;
2669 }
2670 else
2671 // Newer successful extended self-test exits
2672 igncnt++;
2673 }
2674 else if (state > 0 && ext_ok_testno < 0) {
2675 // Latest successful extended self-test
2676 ext_ok_testno = testno;
f4ebf3d1 2677 }
2127e193
GI
2678 }
2679 }
cfbba5b9
GI
2680
2681 if (igncnt)
2682 pout("%d of %d failed self-tests are outdated by newer successful extended offline self-test #%2d\n",
2683 igncnt, igncnt+errcnt, ext_ok_testno);
2684
2685 if (!allentries && !noheaderprinted)
2127e193
GI
2686 pout("\n");
2687
cfbba5b9 2688 return ((hours << 8) | errcnt);
2127e193
GI
2689}
2690
a37e7145
GG
2691
2692/////////////////////////////////////////////////////////////////////////////
2693// Pseudo-device to parse "smartctl -r ataioctl,2 ..." output and simulate
2694// an ATA device with same behaviour
2695
2127e193
GI
2696namespace {
2697
2698class parsed_ata_device
2699: public /*implements*/ ata_device_with_command_set
2700{
2701public:
2702 parsed_ata_device(smart_interface * intf, const char * dev_name);
2703
2704 virtual ~parsed_ata_device() throw();
2705
2706 virtual bool is_open() const;
2707
2708 virtual bool open();
a37e7145 2709
2127e193 2710 virtual bool close();
a37e7145 2711
2127e193
GI
2712 virtual bool ata_identify_is_cached() const;
2713
2714protected:
2715 virtual int ata_command_interface(smart_command_set command, int select, char * data);
2716
2717private:
2718 // Table of parsed commands, return value, data
2719 struct parsed_ata_command
2720 {
2721 smart_command_set command;
2722 int select;
2723 int retval, errval;
2724 char * data;
2725 };
2726
2727 enum { max_num_commands = 32 };
2728 parsed_ata_command m_command_table[max_num_commands];
2729
2730 int m_num_commands;
2731 int m_next_replay_command;
2732 bool m_replay_out_of_sync;
2733 bool m_ata_identify_is_cached;
2734};
a37e7145
GG
2735
2736static const char * nextline(const char * s, int & lineno)
2737{
2738 for (s += strcspn(s, "\r\n"); *s == '\r' || *s == '\n'; s++) {
2739 if (*s == '\r' && s[1] == '\n')
2740 s++;
2741 lineno++;
2742 }
2743 return s;
2744}
2745
2746static int name2command(const char * s)
2747{
2748 for (int i = 0; i < (int)(sizeof(commandstrings)/sizeof(commandstrings[0])); i++) {
2749 if (!strcmp(s, commandstrings[i]))
2750 return i;
2751 }
2752 return -1;
2753}
2754
2755static bool matchcpy(char * dest, size_t size, const char * src, const regmatch_t & srcmatch)
2756{
2757 if (srcmatch.rm_so < 0)
2758 return false;
2759 size_t n = srcmatch.rm_eo - srcmatch.rm_so;
2760 if (n >= size)
2761 n = size-1;
2762 memcpy(dest, src + srcmatch.rm_so, n);
2763 dest[n] = 0;
2764 return true;
2765}
2766
2767static inline int matchtoi(const char * src, const regmatch_t & srcmatch, int defval)
2768{
2769 if (srcmatch.rm_so < 0)
2770 return defval;
2771 return atoi(src + srcmatch.rm_so);
2772}
2773
2127e193
GI
2774parsed_ata_device::parsed_ata_device(smart_interface * intf, const char * dev_name)
2775: smart_device(intf, dev_name, "ata", ""),
2776 m_num_commands(0),
2777 m_next_replay_command(0),
2778 m_replay_out_of_sync(false),
2779 m_ata_identify_is_cached(false)
2780{
2781 memset(m_command_table, 0, sizeof(m_command_table));
2782}
2783
2784parsed_ata_device::~parsed_ata_device() throw()
2785{
2786 close();
2787}
2788
2789bool parsed_ata_device::is_open() const
2790{
2791 return (m_num_commands > 0);
2792}
a37e7145
GG
2793
2794// Parse stdin and build command table
2127e193 2795bool parsed_ata_device::open()
a37e7145 2796{
2127e193
GI
2797 const char * pathname = get_dev_name();
2798 if (strcmp(pathname, "-"))
2799 return set_err(EINVAL);
a37e7145
GG
2800 pathname = "<stdin>";
2801 // Fill buffer
2802 char buffer[64*1024];
2803 int size = 0;
2804 while (size < (int)sizeof(buffer)) {
2805 int nr = fread(buffer, 1, sizeof(buffer), stdin);
2806 if (nr <= 0)
2807 break;
2808 size += nr;
2809 }
2127e193
GI
2810 if (size <= 0)
2811 return set_err(ENOENT, "%s: Unexpected EOF", pathname);
2812 if (size >= (int)sizeof(buffer))
2813 return set_err(EIO, "%s: Buffer overflow", pathname);
a37e7145
GG
2814 buffer[size] = 0;
2815
2816 // Regex to match output from "-r ataioctl,2"
2817 static const char pattern[] = "^"
2818 "(" // (1
2127e193 2819 "REPORT-IOCTL: DeviceF?D?=[^ ]+ Command=([A-Z ]*[A-Z])" // (2)
a37e7145
GG
2820 "(" // (3
2821 "( InputParameter=([0-9]+))?" // (4 (5))
2822 "|"
2823 "( returned (-?[0-9]+)( errno=([0-9]+)[^\r\n]*)?)" // (6 (7) (8 (9)))
2824 ")" // )
2825 "[\r\n]" // EOL match necessary to match optional parts above
2826 "|"
2827 "===== \\[([A-Z ]*[A-Z])\\] DATA START " // (10)
2127e193
GI
2828 "|"
2829 " *(En|Dis)abled status cached by OS, " // (11)
a37e7145
GG
2830 ")"; // )
2831
2832 // Compile regex
cfbba5b9 2833 const regular_expression regex(pattern, REG_EXTENDED);
a37e7145
GG
2834
2835 // Parse buffer
2836 const char * errmsg = 0;
2837 int i = -1, state = 0, lineno = 1;
2838 for (const char * line = buffer; *line; line = nextline(line, lineno)) {
2839 // Match line
2127e193 2840 if (!(line[0] == 'R' || line[0] == '=' || line[0] == ' '))
a37e7145 2841 continue;
2127e193 2842 const int nmatch = 1+11;
a37e7145 2843 regmatch_t match[nmatch];
2127e193 2844 if (!regex.execute(line, nmatch, match))
a37e7145
GG
2845 continue;
2846
2847 char cmdname[40];
2848 if (matchcpy(cmdname, sizeof(cmdname), line, match[2])) { // "REPORT-IOCTL:... Command=%s ..."
2849 int nc = name2command(cmdname);
2850 if (nc < 0) {
2851 errmsg = "Unknown ATA command name"; break;
2852 }
2853 if (match[7].rm_so < 0) { // "returned %d"
2854 // Start of command
2855 if (!(state == 0 || state == 2)) {
2856 errmsg = "Missing REPORT-IOCTL result"; break;
2857 }
2127e193 2858 if (++i >= max_num_commands) {
a37e7145
GG
2859 errmsg = "Too many ATA commands"; break;
2860 }
2127e193
GI
2861 m_command_table[i].command = (smart_command_set)nc;
2862 m_command_table[i].select = matchtoi(line, match[5], 0); // "InputParameter=%d"
a37e7145
GG
2863 state = 1;
2864 }
2865 else {
2866 // End of command
2127e193 2867 if (!(state == 1 && (int)m_command_table[i].command == nc)) {
a37e7145
GG
2868 errmsg = "Missing REPORT-IOCTL start"; break;
2869 }
2127e193
GI
2870 m_command_table[i].retval = matchtoi(line, match[7], -1); // "returned %d"
2871 m_command_table[i].errval = matchtoi(line, match[9], 0); // "errno=%d"
a37e7145
GG
2872 state = 2;
2873 }
2874 }
2875 else if (matchcpy(cmdname, sizeof(cmdname), line, match[10])) { // "===== [%s] DATA START "
2876 // Start of sector hexdump
2877 int nc = name2command(cmdname);
2127e193 2878 if (!(state == (nc == WRITE_LOG ? 1 : 2) && (int)m_command_table[i].command == nc)) {
a37e7145
GG
2879 errmsg = "Unexpected DATA START"; break;
2880 }
2881 line = nextline(line, lineno);
2882 char * data = (char *)malloc(512);
2883 unsigned j;
2884 for (j = 0; j < 32; j++) {
2885 unsigned b[16];
2886 unsigned u1, u2; int n1 = -1;
2887 if (!(sscanf(line, "%3u-%3u: "
2888 "%2x %2x %2x %2x %2x %2x %2x %2x "
2889 "%2x %2x %2x %2x %2x %2x %2x %2x%n",
2890 &u1, &u2,
2891 b+ 0, b+ 1, b+ 2, b+ 3, b+ 4, b+ 5, b+ 6, b+ 7,
2892 b+ 8, b+ 9, b+10, b+11, b+12, b+13, b+14, b+15, &n1) == 18
2893 && n1 >= 56 && u1 == j*16 && u2 == j*16+15))
2894 break;
2895 for (unsigned k = 0; k < 16; k++)
2896 data[j*16+k] = b[k];
2897 line = nextline(line, lineno);
2898 }
2899 if (j < 32) {
2900 free(data);
2901 errmsg = "Incomplete sector hex dump"; break;
2902 }
2127e193 2903 m_command_table[i].data = data;
a37e7145
GG
2904 if (nc != WRITE_LOG)
2905 state = 0;
2906 }
2127e193
GI
2907 else if (match[11].rm_so > 0) { // "(En|Dis)abled status cached by OS"
2908 m_ata_identify_is_cached = true;
2909 }
a37e7145
GG
2910 }
2911
2912 if (!(state == 0 || state == 2))
2913 errmsg = "Missing REPORT-IOCTL result";
2914
2915 if (!errmsg && i < 0)
2916 errmsg = "No information found";
2917
2127e193
GI
2918 m_num_commands = i+1;
2919 m_next_replay_command = 0;
2920 m_replay_out_of_sync = false;
a37e7145
GG
2921
2922 if (errmsg) {
2127e193
GI
2923 close();
2924 return set_err(EIO, "%s(%d): Syntax error: %s", pathname, lineno, errmsg);
a37e7145 2925 }
2127e193 2926 return true;
a37e7145
GG
2927}
2928
2929// Report warnings and free command table
2127e193 2930bool parsed_ata_device::close()
a37e7145 2931{
2127e193 2932 if (m_replay_out_of_sync)
a37e7145 2933 pout("REPLAY-IOCTL: Warning: commands replayed out of sync\n");
2127e193
GI
2934 else if (m_next_replay_command != 0)
2935 pout("REPLAY-IOCTL: Warning: %d command(s) not replayed\n", m_num_commands-m_next_replay_command);
a37e7145 2936
2127e193
GI
2937 for (int i = 0; i < m_num_commands; i++) {
2938 if (m_command_table[i].data) {
2939 free(m_command_table[i].data); m_command_table[i].data = 0;
a37e7145
GG
2940 }
2941 }
2127e193
GI
2942 m_num_commands = 0;
2943 m_next_replay_command = 0;
2944 m_replay_out_of_sync = false;
2945 return true;
2946}
2947
2948
2949bool parsed_ata_device::ata_identify_is_cached() const
2950{
2951 return m_ata_identify_is_cached;
a37e7145
GG
2952}
2953
2127e193 2954
a37e7145 2955// Simulate ATA command from command table
2127e193 2956int parsed_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
a37e7145 2957{
2127e193
GI
2958 // Find command, try round-robin if out of sync
2959 int i = m_next_replay_command;
a37e7145 2960 for (int j = 0; ; j++) {
2127e193 2961 if (j >= m_num_commands) {
a37e7145
GG
2962 pout("REPLAY-IOCTL: Warning: Command not found\n");
2963 errno = ENOSYS;
2964 return -1;
2965 }
2127e193 2966 if (m_command_table[i].command == command && m_command_table[i].select == select)
a37e7145 2967 break;
2127e193
GI
2968 if (!m_replay_out_of_sync) {
2969 m_replay_out_of_sync = true;
a37e7145
GG
2970 pout("REPLAY-IOCTL: Warning: Command #%d is out of sync\n", i+1);
2971 }
2127e193 2972 if (++i >= m_num_commands)
a37e7145
GG
2973 i = 0;
2974 }
2127e193
GI
2975 m_next_replay_command = i;
2976 if (++m_next_replay_command >= m_num_commands)
2977 m_next_replay_command = 0;
a37e7145
GG
2978
2979 // Return command data
2980 switch (command) {
2981 case IDENTIFY:
2982 case PIDENTIFY:
2983 case READ_VALUES:
2984 case READ_THRESHOLDS:
2985 case READ_LOG:
2127e193
GI
2986 if (m_command_table[i].data)
2987 memcpy(data, m_command_table[i].data, 512);
a37e7145
GG
2988 break;
2989 case WRITE_LOG:
2127e193 2990 if (!(m_command_table[i].data && !memcmp(data, m_command_table[i].data, 512)))
a37e7145
GG
2991 pout("REPLAY-IOCTL: Warning: WRITE LOG data does not match\n");
2992 break;
2993 case CHECK_POWER_MODE:
2994 data[0] = (char)0xff;
2995 default:
2996 break;
2997 }
2998
2127e193
GI
2999 if (m_command_table[i].errval)
3000 errno = m_command_table[i].errval;
3001 return m_command_table[i].retval;
3002}
3003
3004} // namespace
3005
3006ata_device * get_parsed_ata_device(smart_interface * intf, const char * dev_name)
3007{
3008 return new parsed_ata_device(intf, dev_name);
a37e7145 3009}