1 /* $NetBSD: atactl.c,v 1.69 2013/02/08 03:58:36 jakllsch Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Ken Hornstein. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * atactl(8) - a program to control ATA devices. 34 */ 35 #include <sys/cdefs.h> 36 37 #ifndef lint 38 __RCSID("$NetBSD: atactl.c,v 1.69 2013/02/08 03:58:36 jakllsch Exp $"); 39 #endif 40 41 42 #include <sys/param.h> 43 #include <sys/ioctl.h> 44 #include <err.h> 45 #include <errno.h> 46 #include <fcntl.h> 47 #include <pwd.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 #include <util.h> 53 54 #include <dev/ata/atareg.h> 55 #include <sys/ataio.h> 56 57 struct ata_smart_error { 58 struct { 59 uint8_t device_control; 60 uint8_t features; 61 uint8_t sector_count; 62 uint8_t sector_number; 63 uint8_t cylinder_low; 64 uint8_t cylinder_high; 65 uint8_t device_head; 66 uint8_t command; 67 uint8_t timestamp[4]; 68 } command[5]; 69 struct { 70 uint8_t reserved; 71 uint8_t error; 72 uint8_t sector_count; 73 uint8_t sector_number; 74 uint8_t cylinder_low; 75 uint8_t cylinder_high; 76 uint8_t device_head; 77 uint8_t status; 78 uint8_t extended_error[19]; 79 uint8_t state; 80 uint8_t lifetime[2]; 81 } error_data; 82 } __packed; 83 84 struct ata_smart_errorlog { 85 uint8_t data_structure_revision; 86 uint8_t mostrecenterror; 87 struct ata_smart_error log_entries[5]; 88 uint16_t device_error_count; 89 uint8_t reserved[57]; 90 uint8_t checksum; 91 } __packed; 92 93 struct command { 94 const char *cmd_name; 95 const char *arg_names; 96 void (*cmd_func)(int, char *[]); 97 }; 98 99 struct bitinfo { 100 u_int bitmask; 101 const char *string; 102 }; 103 104 __dead static void usage(void); 105 static void ata_command(struct atareq *); 106 static void print_bitinfo(const char *, const char *, u_int, 107 const struct bitinfo *); 108 static void print_bitinfo2(const char *, const char *, u_int, u_int, 109 const struct bitinfo *); 110 static void print_smart_status(void *, void *); 111 static void print_error_entry(int, const struct ata_smart_error *); 112 static void print_selftest_entry(int, const struct ata_smart_selftest *); 113 114 static void print_error(const void *); 115 static void print_selftest(const void *); 116 117 static const struct ataparams *getataparams(void); 118 119 static int is_smart(void); 120 121 static int fd; /* file descriptor for device */ 122 static const char *dvname; /* device name */ 123 static char dvname_store[MAXPATHLEN]; /* for opendisk(3) */ 124 static const char *cmdname; /* command user issued */ 125 126 static void device_identify(int, char *[]); 127 static void device_setidle(int, char *[]); 128 static void device_idle(int, char *[]); 129 static void device_apm(int, char *[]); 130 static void device_checkpower(int, char *[]); 131 static void device_smart(int, char *[]); 132 static void device_security(int, char *[]); 133 134 static void device_smart_temp(const struct ata_smart_attr *, uint64_t); 135 136 static const struct command device_commands[] = { 137 { "identify", "", device_identify }, 138 { "setidle", "idle-timer", device_setidle }, 139 { "apm", "disable|set #", device_apm }, 140 { "setstandby", "standby-timer", device_setidle }, 141 { "idle", "", device_idle }, 142 { "standby", "", device_idle }, 143 { "sleep", "", device_idle }, 144 { "checkpower", "", device_checkpower }, 145 { "smart", 146 "enable|disable|status|offline #|error-log|selftest-log", 147 device_smart }, 148 { "security", 149 "status|freeze|[setpass|unlock|disable|erase] [user|master]", 150 device_security }, 151 { NULL, NULL, NULL }, 152 }; 153 154 static void bus_reset(int, char *[]); 155 156 static const struct command bus_commands[] = { 157 { "reset", "", bus_reset }, 158 { NULL, NULL, NULL }, 159 }; 160 161 /* 162 * Tables containing bitmasks used for error reporting and 163 * device identification. 164 */ 165 166 static const struct bitinfo ata_caps[] = { 167 { WDC_CAP_DMA, "DMA" }, 168 { WDC_CAP_LBA, "LBA" }, 169 { ATA_CAP_STBY, "ATA standby timer values" }, 170 { WDC_CAP_IORDY, "IORDY operation" }, 171 { WDC_CAP_IORDY_DSBL, "IORDY disabling" }, 172 { 0, NULL }, 173 }; 174 175 static const struct bitinfo ata_vers[] = { 176 { WDC_VER_ATA1, "ATA-1" }, 177 { WDC_VER_ATA2, "ATA-2" }, 178 { WDC_VER_ATA3, "ATA-3" }, 179 { WDC_VER_ATA4, "ATA-4" }, 180 { WDC_VER_ATA5, "ATA-5" }, 181 { WDC_VER_ATA6, "ATA-6" }, 182 { WDC_VER_ATA7, "ATA-7" }, 183 { WDC_VER_ATA8, "ATA-8" }, 184 { 0, NULL }, 185 }; 186 187 static const struct bitinfo ata_cmd_set1[] = { 188 { WDC_CMD1_NOP, "NOP command" }, 189 { WDC_CMD1_RB, "READ BUFFER command" }, 190 { WDC_CMD1_WB, "WRITE BUFFER command" }, 191 { WDC_CMD1_HPA, "Host Protected Area feature set" }, 192 { WDC_CMD1_DVRST, "DEVICE RESET command" }, 193 { WDC_CMD1_SRV, "SERVICE interrupt" }, 194 { WDC_CMD1_RLSE, "release interrupt" }, 195 { WDC_CMD1_AHEAD, "look-ahead" }, 196 { WDC_CMD1_CACHE, "write cache" }, 197 { WDC_CMD1_PKT, "PACKET command feature set" }, 198 { WDC_CMD1_PM, "Power Management feature set" }, 199 { WDC_CMD1_REMOV, "Removable Media feature set" }, 200 { WDC_CMD1_SEC, "Security Mode feature set" }, 201 { WDC_CMD1_SMART, "SMART feature set" }, 202 { 0, NULL }, 203 }; 204 205 static const struct bitinfo ata_cmd_set2[] = { 206 { ATA_CMD2_FCE, "FLUSH CACHE EXT command" }, 207 { WDC_CMD2_FC, "FLUSH CACHE command" }, 208 { WDC_CMD2_DCO, "Device Configuration Overlay feature set" }, 209 { ATA_CMD2_LBA48, "48-bit Address feature set" }, 210 { WDC_CMD2_AAM, "Automatic Acoustic Management feature set" }, 211 { WDC_CMD2_SM, "SET MAX security extension" }, 212 { WDC_CMD2_SFREQ, "SET FEATURES required to spin-up after power-up" }, 213 { WDC_CMD2_PUIS, "Power-Up In Standby feature set" }, 214 { WDC_CMD2_RMSN, "Removable Media Status Notification feature set" }, 215 { ATA_CMD2_APM, "Advanced Power Management feature set" }, 216 { ATA_CMD2_CFA, "CFA feature set" }, 217 { ATA_CMD2_RWQ, "READ/WRITE DMA QUEUED commands" }, 218 { WDC_CMD2_DM, "DOWNLOAD MICROCODE command" }, 219 { 0, NULL }, 220 }; 221 222 static const struct bitinfo ata_cmd_ext[] = { 223 { ATA_CMDE_TLCONT, "Time-limited R/W feature set R/W Continuous mode" }, 224 { ATA_CMDE_TL, "Time-limited Read/Write" }, 225 { ATA_CMDE_URGW, "URG bit for WRITE STREAM DMA/PIO" }, 226 { ATA_CMDE_URGR, "URG bit for READ STREAM DMA/PIO" }, 227 { ATA_CMDE_WWN, "World Wide Name" }, 228 { ATA_CMDE_WQFE, "WRITE DMA QUEUED FUA EXT command" }, 229 { ATA_CMDE_WFE, "WRITE DMA/MULTIPLE FUA EXT commands" }, 230 { ATA_CMDE_GPL, "General Purpose Logging feature set" }, 231 { ATA_CMDE_STREAM, "Streaming feature set" }, 232 { ATA_CMDE_MCPTC, "Media Card Pass Through Command feature set" }, 233 { ATA_CMDE_MS, "Media serial number" }, 234 { ATA_CMDE_SST, "SMART self-test" }, 235 { ATA_CMDE_SEL, "SMART error logging" }, 236 { 0, NULL }, 237 }; 238 239 static const struct bitinfo ata_sata_caps[] = { 240 { SATA_SIGNAL_GEN1, "1.5Gb/s signaling" }, 241 { SATA_SIGNAL_GEN2, "3.0Gb/s signaling" }, 242 { SATA_SIGNAL_GEN3, "6.0Gb/s signaling" }, 243 { SATA_NATIVE_CMDQ, "Native Command Queuing" }, 244 { SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" }, 245 { SATA_PHY_EVNT_CNT, "PHY Event Counters" }, 246 { 0, NULL }, 247 }; 248 249 static const struct bitinfo ata_sata_feat[] = { 250 { SATA_NONZERO_OFFSETS, "Non-zero Offset DMA" }, 251 { SATA_DMA_SETUP_AUTO, "DMA Setup Auto Activate" }, 252 { SATA_DRIVE_PWR_MGMT, "Device-Initiated Interface Power Managment" }, 253 { SATA_IN_ORDER_DATA, "In-order Data Delivery" }, 254 { SATA_SW_STTNGS_PRS, "Software Settings Preservation" }, 255 { 0, NULL }, 256 }; 257 258 static const struct { 259 const int id; 260 const char *name; 261 void (*special)(const struct ata_smart_attr *, uint64_t); 262 } smart_attrs[] = { 263 { 1, "Raw read error rate", NULL }, 264 { 2, "Throughput performance", NULL }, 265 { 3, "Spin-up time", NULL }, 266 { 4, "Start/stop count", NULL }, 267 { 5, "Reallocated sector count", NULL }, 268 { 6, "Read channel margin", NULL }, 269 { 7, "Seek error rate", NULL }, 270 { 8, "Seek time performance", NULL }, 271 { 9, "Power-on hours count", NULL }, 272 { 10, "Spin retry count", NULL }, 273 { 11, "Calibration retry count", NULL }, 274 { 12, "Device power cycle count", NULL }, 275 { 13, "Soft read error rate", NULL }, 276 { 187, "Reported uncorrect", NULL }, 277 { 189, "High Fly Writes", NULL }, 278 { 190, "Airflow Temperature", device_smart_temp }, 279 { 191, "G-sense error rate", NULL }, 280 { 192, "Power-off retract count", NULL }, 281 { 193, "Load cycle count", NULL }, 282 { 194, "Temperature", device_smart_temp}, 283 { 195, "Hardware ECC Recovered", NULL }, 284 { 196, "Reallocated event count", NULL }, 285 { 197, "Current pending sector", NULL }, 286 { 198, "Offline uncorrectable", NULL }, 287 { 199, "Ultra DMA CRC error count", NULL }, 288 { 200, "Write error rate", NULL }, 289 { 201, "Soft read error rate", NULL }, 290 { 202, "Data address mark errors", NULL }, 291 { 203, "Run out cancel", NULL }, 292 { 204, "Soft ECC correction", NULL }, 293 { 205, "Thermal asperity check", NULL }, 294 { 206, "Flying height", NULL }, 295 { 207, "Spin high current", NULL }, 296 { 208, "Spin buzz", NULL }, 297 { 209, "Offline seek performance", NULL }, 298 { 220, "Disk shift", NULL }, 299 { 221, "G-Sense error rate", NULL }, 300 { 222, "Loaded hours", NULL }, 301 { 223, "Load/unload retry count", NULL }, 302 { 224, "Load friction", NULL }, 303 { 225, "Load/unload cycle count", NULL }, 304 { 226, "Load-in time", NULL }, 305 { 227, "Torque amplification count", NULL }, 306 { 228, "Power-off retract count", NULL }, 307 { 230, "GMR head amplitude", NULL }, 308 { 231, "Temperature", device_smart_temp }, 309 { 240, "Head flying hours", NULL }, 310 { 250, "Read error retry rate", NULL }, 311 { 0, "Unknown", NULL }, 312 }; 313 314 static const struct bitinfo ata_sec_st[] = { 315 { WDC_SEC_SUPP, "supported" }, 316 { WDC_SEC_EN, "enabled" }, 317 { WDC_SEC_LOCKED, "locked" }, 318 { WDC_SEC_FROZEN, "frozen" }, 319 { WDC_SEC_EXP, "expired" }, 320 { WDC_SEC_ESE_SUPP, "enhanced erase support" }, 321 { WDC_SEC_LEV_MAX, "maximum level" }, 322 { 0, NULL }, 323 }; 324 325 int 326 main(int argc, char *argv[]) 327 { 328 int i; 329 const struct command *commands = NULL; 330 331 /* Must have at least: device command */ 332 if (argc < 3) 333 usage(); 334 335 /* Skip program name, get and skip device name and command. */ 336 dvname = argv[1]; 337 cmdname = argv[2]; 338 argv += 3; 339 argc -= 3; 340 341 /* 342 * Open the device 343 */ 344 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0); 345 if (fd == -1) { 346 if (errno == ENOENT) { 347 /* 348 * Device doesn't exist. Probably trying to open 349 * a device which doesn't use disk semantics for 350 * device name. Try again, specifying "cooked", 351 * which leaves off the "r" in front of the device's 352 * name. 353 */ 354 fd = opendisk(dvname, O_RDWR, dvname_store, 355 sizeof(dvname_store), 1); 356 if (fd == -1) 357 err(1, "%s", dvname); 358 } else 359 err(1, "%s", dvname); 360 } 361 362 /* 363 * Point the dvname at the actual device name that opendisk() opened. 364 */ 365 dvname = dvname_store; 366 367 /* Look up and call the command. */ 368 for (i = 0; device_commands[i].cmd_name != NULL; i++) { 369 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) { 370 commands = &device_commands[i]; 371 break; 372 } 373 } 374 if (commands == NULL) { 375 for (i = 0; bus_commands[i].cmd_name != NULL; i++) { 376 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) { 377 commands = &bus_commands[i]; 378 break; 379 } 380 } 381 } 382 if (commands == NULL) 383 errx(1, "unknown command: %s", cmdname); 384 385 (*commands->cmd_func)(argc, argv); 386 exit(0); 387 } 388 389 static void 390 usage(void) 391 { 392 int i; 393 394 fprintf(stderr, "usage: %s device command [arg [...]]\n", 395 getprogname()); 396 397 fprintf(stderr, " Available device commands:\n"); 398 for (i=0; device_commands[i].cmd_name != NULL; i++) 399 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name, 400 device_commands[i].arg_names); 401 402 fprintf(stderr, " Available bus commands:\n"); 403 for (i=0; bus_commands[i].cmd_name != NULL; i++) 404 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name, 405 bus_commands[i].arg_names); 406 407 exit(1); 408 } 409 410 /* 411 * Wrapper that calls ATAIOCCOMMAND and checks for errors 412 */ 413 414 static void 415 ata_command(struct atareq *req) 416 { 417 int error; 418 419 error = ioctl(fd, ATAIOCCOMMAND, req); 420 421 if (error == -1) 422 err(1, "ATAIOCCOMMAND failed"); 423 424 switch (req->retsts) { 425 426 case ATACMD_OK: 427 return; 428 case ATACMD_TIMEOUT: 429 fprintf(stderr, "ATA command timed out\n"); 430 exit(1); 431 case ATACMD_DF: 432 fprintf(stderr, "ATA device returned a Device Fault\n"); 433 exit(1); 434 case ATACMD_ERROR: 435 if (req->error & WDCE_ABRT) 436 fprintf(stderr, "ATA device returned Aborted " 437 "Command\n"); 438 else 439 fprintf(stderr, "ATA device returned error register " 440 "%0x\n", req->error); 441 exit(1); 442 default: 443 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code " 444 "%d\n", req->retsts); 445 exit(1); 446 } 447 } 448 449 /* 450 * Print out strings associated with particular bitmasks 451 */ 452 453 static void 454 print_bitinfo(const char *bf, const char *af, u_int bits, 455 const struct bitinfo *binfo) 456 { 457 458 for (; binfo->bitmask != 0; binfo++) 459 if (bits & binfo->bitmask) 460 printf("%s%s%s", bf, binfo->string, af); 461 } 462 463 static void 464 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables, 465 const struct bitinfo *binfo) 466 { 467 468 for (; binfo->bitmask != 0; binfo++) 469 if (bits & binfo->bitmask) 470 printf("%s%s (%s)%s", bf, binfo->string, 471 (enables & binfo->bitmask) ? "enabled" : "disabled", 472 af); 473 } 474 475 476 /* 477 * Try to print SMART temperature field 478 */ 479 480 static void 481 device_smart_temp(const struct ata_smart_attr *attr, uint64_t raw_value) 482 { 483 printf("%" PRIu8, attr->raw[0]); 484 if (attr->raw[0] != raw_value) 485 printf(" Lifetime min/max %" PRIu8 "/%" PRIu8, 486 attr->raw[2], attr->raw[4]); 487 } 488 489 490 /* 491 * Print out SMART attribute thresholds and values 492 */ 493 494 static void 495 print_smart_status(void *vbuf, void *tbuf) 496 { 497 const struct ata_smart_attributes *value_buf = vbuf; 498 const struct ata_smart_thresholds *threshold_buf = tbuf; 499 const struct ata_smart_attr *attr; 500 uint64_t raw_value; 501 int flags; 502 int i, j; 503 int aid; 504 uint8_t checksum; 505 506 for (i = checksum = 0; i < 512; i++) 507 checksum += ((const uint8_t *) value_buf)[i]; 508 if (checksum != 0) { 509 fprintf(stderr, "SMART attribute values checksum error\n"); 510 return; 511 } 512 513 for (i = checksum = 0; i < 512; i++) 514 checksum += ((const uint8_t *) threshold_buf)[i]; 515 if (checksum != 0) { 516 fprintf(stderr, "SMART attribute thresholds checksum error\n"); 517 return; 518 } 519 520 printf("id value thresh crit collect reliability description" 521 "\t\t\traw\n"); 522 for (i = 0; i < 256; i++) { 523 int thresh = 0; 524 525 attr = NULL; 526 527 for (j = 0; j < 30; j++) { 528 if (value_buf->attributes[j].id == i) 529 attr = &value_buf->attributes[j]; 530 if (threshold_buf->thresholds[j].id == i) 531 thresh = threshold_buf->thresholds[j].value; 532 } 533 534 if (thresh && attr == NULL) 535 errx(1, "threshold but not attr %d", i); 536 if (attr == NULL) 537 continue; 538 539 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF) 540 continue; 541 542 for (aid = 0; 543 smart_attrs[aid].id != i && smart_attrs[aid].id != 0; 544 aid++) 545 ; 546 547 flags = le16toh(attr->flags); 548 549 printf("%3d %3d %3d %-3s %-7s %stive %-24s\t", 550 i, attr->value, thresh, 551 flags & WDSM_ATTR_ADVISORY ? "yes" : "no", 552 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline", 553 attr->value > thresh ? "posi" : "nega", 554 smart_attrs[aid].name); 555 556 for (j = 0, raw_value = 0; j < 6; j++) 557 raw_value += ((uint64_t)attr->raw[j]) << (8*j); 558 559 if (smart_attrs[aid].special) 560 (*smart_attrs[aid].special)(attr, raw_value); 561 else 562 printf("%" PRIu64, raw_value); 563 printf("\n"); 564 } 565 } 566 567 static const struct { 568 int number; 569 const char *name; 570 } selftest_name[] = { 571 { 0, "Off-line" }, 572 { 1, "Short off-line" }, 573 { 2, "Extended off-line" }, 574 { 127, "Abort off-line test" }, 575 { 129, "Short captive" }, 576 { 130, "Extended captive" }, 577 { 256, "Unknown test" }, /* larger then uint8_t */ 578 { 0, NULL } 579 }; 580 581 static const char *selftest_status[] = { 582 "No error", 583 "Aborted by the host", 584 "Interrupted by the host by reset", 585 "Fatal error or unknown test error", 586 "Unknown test element failed", 587 "Electrical test element failed", 588 "The Servo (and/or seek) test element failed", 589 "Read element of test failed", 590 "Reserved", 591 "Reserved", 592 "Reserved", 593 "Reserved", 594 "Reserved", 595 "Reserved", 596 "Reserved", 597 "Self-test in progress" 598 }; 599 600 static void 601 print_error_entry(int num, const struct ata_smart_error *le) 602 { 603 int i; 604 605 printf("Log entry: %d\n", num); 606 607 for (i = 0; i < 5; i++) 608 printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x " 609 "ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i, 610 le->command[i].device_control, 611 le->command[i].features, 612 le->command[i].sector_count, 613 le->command[i].sector_number, 614 le->command[i].cylinder_low, 615 le->command[i].cylinder_high, 616 le->command[i].device_head, 617 le->command[i].command, 618 le->command[i].timestamp[3], 619 le->command[i].timestamp[2], 620 le->command[i].timestamp[1], 621 le->command[i].timestamp[0]); 622 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x " 623 "status=%02x state=%02x lifetime=%02x%02x\n", 624 le->error_data.error, 625 le->error_data.sector_count, 626 le->error_data.sector_number, 627 le->error_data.cylinder_low, 628 le->error_data.cylinder_high, 629 le->error_data.device_head, 630 le->error_data.status, 631 le->error_data.state, 632 le->error_data.lifetime[1], 633 le->error_data.lifetime[0]); 634 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " 635 "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 636 le->error_data.extended_error[0], 637 le->error_data.extended_error[1], 638 le->error_data.extended_error[2], 639 le->error_data.extended_error[3], 640 le->error_data.extended_error[4], 641 le->error_data.extended_error[5], 642 le->error_data.extended_error[6], 643 le->error_data.extended_error[7], 644 le->error_data.extended_error[8], 645 le->error_data.extended_error[9], 646 le->error_data.extended_error[10], 647 le->error_data.extended_error[11], 648 le->error_data.extended_error[12], 649 le->error_data.extended_error[13], 650 le->error_data.extended_error[14], 651 le->error_data.extended_error[15], 652 le->error_data.extended_error[15], 653 le->error_data.extended_error[17], 654 le->error_data.extended_error[18]); 655 } 656 657 static void 658 print_error(const void *buf) 659 { 660 const struct ata_smart_errorlog *erlog = buf; 661 uint8_t checksum; 662 int i; 663 664 for (i = checksum = 0; i < 512; i++) 665 checksum += ((const uint8_t *) buf)[i]; 666 if (checksum != 0) { 667 fprintf(stderr, "SMART error log checksum error\n"); 668 return; 669 } 670 671 if (erlog->data_structure_revision != 1) { 672 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n", 673 erlog->data_structure_revision); 674 return; 675 } 676 677 if (erlog->mostrecenterror == 0) { 678 printf("No errors have been logged\n"); 679 return; 680 } 681 682 if (erlog->mostrecenterror > 5) { 683 fprintf(stderr, "Most recent error is too large\n"); 684 return; 685 } 686 687 for (i = erlog->mostrecenterror; i < 5; i++) 688 print_error_entry(i, &erlog->log_entries[i]); 689 for (i = 0; i < erlog->mostrecenterror; i++) 690 print_error_entry(i, &erlog->log_entries[i]); 691 printf("device error count: %d\n", erlog->device_error_count); 692 } 693 694 static void 695 print_selftest_entry(int num, const struct ata_smart_selftest *le) 696 { 697 const unsigned char *p; 698 size_t i; 699 700 /* check if all zero */ 701 for (p = (const void *)le, i = 0; i < sizeof(*le); i++) 702 if (p[i] != 0) 703 break; 704 if (i == sizeof(*le)) 705 return; 706 707 printf("Log entry: %d\n", num); 708 709 /* Get test name */ 710 for (i = 0; selftest_name[i].name != NULL; i++) 711 if (selftest_name[i].number == le->number) 712 break; 713 714 if (selftest_name[i].name == NULL) 715 printf("\tName: (%d)\n", le->number); 716 else 717 printf("\tName: %s\n", selftest_name[i].name); 718 printf("\tStatus: %s\n", selftest_status[le->status >> 4]); 719 /* XXX This generally should not be set when a self-test is completed, 720 and at any rate is useless. - mycroft */ 721 if (le->status >> 4 == 15) 722 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf); 723 else if (le->status >> 4 != 0) 724 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error)); 725 } 726 727 static void 728 print_selftest(const void *buf) 729 { 730 const struct ata_smart_selftestlog *stlog = buf; 731 uint8_t checksum; 732 int i; 733 734 for (i = checksum = 0; i < 512; i++) 735 checksum += ((const uint8_t *) buf)[i]; 736 if (checksum != 0) { 737 fprintf(stderr, "SMART selftest log checksum error\n"); 738 return; 739 } 740 741 if (le16toh(stlog->data_structure_revision) != 1) { 742 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n", 743 le16toh(stlog->data_structure_revision)); 744 return; 745 } 746 747 if (stlog->mostrecenttest == 0) { 748 printf("No self-tests have been logged\n"); 749 return; 750 } 751 752 if (stlog->mostrecenttest > 22) { 753 fprintf(stderr, "Most recent test is too large\n"); 754 return; 755 } 756 757 for (i = stlog->mostrecenttest; i < 22; i++) 758 print_selftest_entry(i, &stlog->log_entries[i]); 759 for (i = 0; i < stlog->mostrecenttest; i++) 760 print_selftest_entry(i, &stlog->log_entries[i]); 761 } 762 763 static const struct ataparams * 764 getataparams(void) 765 { 766 struct atareq req; 767 static union { 768 unsigned char inbuf[DEV_BSIZE]; 769 struct ataparams inqbuf; 770 } inbuf; 771 772 memset(&inbuf, 0, sizeof(inbuf)); 773 memset(&req, 0, sizeof(req)); 774 775 req.flags = ATACMD_READ; 776 req.command = WDCC_IDENTIFY; 777 req.databuf = &inbuf; 778 req.datalen = sizeof(inbuf); 779 req.timeout = 1000; 780 781 ata_command(&req); 782 783 return (&inbuf.inqbuf); 784 } 785 786 /* 787 * is_smart: 788 * 789 * Detect whether device supports SMART and SMART is enabled. 790 */ 791 792 static int 793 is_smart(void) 794 { 795 int retval = 0; 796 const struct ataparams *inqbuf; 797 const char *status; 798 799 inqbuf = getataparams(); 800 801 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) { 802 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) { 803 fprintf(stderr, "SMART unsupported\n"); 804 } else { 805 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 || 806 inqbuf->atap_cmd_set2 == 0xffff || 807 inqbuf->atap_cmd_set2 == 0x0000) { 808 status = "status unknown"; 809 retval = 2; 810 } else { 811 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) { 812 status = "enabled"; 813 retval = 1; 814 } else { 815 status = "disabled"; 816 retval = 3; 817 } 818 } 819 printf("SMART supported, SMART %s\n", status); 820 } 821 } 822 return retval; 823 } 824 825 /* 826 * extract_string: copy a block of bytes out of ataparams and make 827 * a proper string out of it, truncating trailing spaces and preserving 828 * strict typing. And also, not doing unaligned accesses. 829 */ 830 static void 831 extract_string(char *buf, size_t bufmax, 832 const uint8_t *bytes, size_t numbytes, 833 int needswap) 834 { 835 unsigned i; 836 size_t j; 837 unsigned char ch1, ch2; 838 839 for (i = 0, j = 0; i < numbytes; i += 2) { 840 ch1 = bytes[i]; 841 ch2 = bytes[i+1]; 842 if (needswap && j < bufmax-1) { 843 buf[j++] = ch2; 844 } 845 if (j < bufmax-1) { 846 buf[j++] = ch1; 847 } 848 if (!needswap && j < bufmax-1) { 849 buf[j++] = ch2; 850 } 851 } 852 while (j > 0 && buf[j-1] == ' ') { 853 j--; 854 } 855 buf[j] = '\0'; 856 } 857 858 static void 859 compute_capacity(const struct ataparams *inqbuf, uint64_t *capacityp, 860 uint64_t *sectorsp, uint32_t *secsizep) 861 { 862 uint64_t capacity; 863 uint64_t sectors; 864 uint32_t secsize; 865 866 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff && 867 inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) { 868 sectors = 869 ((uint64_t)inqbuf->atap_max_lba[3] << 48) | 870 ((uint64_t)inqbuf->atap_max_lba[2] << 32) | 871 ((uint64_t)inqbuf->atap_max_lba[1] << 16) | 872 ((uint64_t)inqbuf->atap_max_lba[0] << 0); 873 } else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) { 874 sectors = (inqbuf->atap_capacity[1] << 16) | 875 inqbuf->atap_capacity[0]; 876 } else { 877 sectors = inqbuf->atap_cylinders * 878 inqbuf->atap_heads * inqbuf->atap_sectors; 879 } 880 881 secsize = 512; 882 883 if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) { 884 if (inqbuf->atap_secsz & ATA_SECSZ_LLS) { 885 secsize = 2 * /* words to bytes */ 886 (inqbuf->atap_lls_secsz[1] << 16 | 887 inqbuf->atap_lls_secsz[0] << 0); 888 } 889 } 890 891 capacity = sectors * secsize; 892 893 if (capacityp) 894 *capacityp = capacity; 895 if (sectorsp) 896 *sectorsp = sectors; 897 if (secsizep) 898 *secsizep = secsize; 899 } 900 901 /* 902 * DEVICE COMMANDS 903 */ 904 905 /* 906 * device_identify: 907 * 908 * Display the identity of the device 909 */ 910 static void 911 device_identify(int argc, char *argv[]) 912 { 913 const struct ataparams *inqbuf; 914 char model[sizeof(inqbuf->atap_model)+1]; 915 char revision[sizeof(inqbuf->atap_revision)+1]; 916 char serial[sizeof(inqbuf->atap_serial)+1]; 917 char hnum[12]; 918 uint64_t capacity; 919 uint64_t sectors; 920 uint32_t secsize; 921 int lb_per_pb; 922 int needswap = 0; 923 int i; 924 uint8_t checksum; 925 926 /* No arguments. */ 927 if (argc != 0) 928 usage(); 929 930 inqbuf = getataparams(); 931 932 if ((inqbuf->atap_integrity & WDC_INTEGRITY_MAGIC_MASK) == 933 WDC_INTEGRITY_MAGIC) { 934 for (i = checksum = 0; i < 512; i++) 935 checksum += ((const uint8_t *)inqbuf)[i]; 936 if (checksum != 0) 937 puts("IDENTIFY DEVICE data checksum invalid\n"); 938 } 939 940 #if BYTE_ORDER == LITTLE_ENDIAN 941 /* 942 * On little endian machines, we need to shuffle the string 943 * byte order. However, we don't have to do this for NEC or 944 * Mitsumi ATAPI devices 945 */ 946 947 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 948 ((inqbuf->atap_model[0] == 'N' && 949 inqbuf->atap_model[1] == 'E') || 950 (inqbuf->atap_model[0] == 'F' && 951 inqbuf->atap_model[1] == 'X')))) { 952 needswap = 1; 953 } 954 #endif 955 956 /* 957 * Copy the info strings out, stripping off blanks. 958 */ 959 extract_string(model, sizeof(model), 960 inqbuf->atap_model, sizeof(inqbuf->atap_model), 961 needswap); 962 extract_string(revision, sizeof(revision), 963 inqbuf->atap_revision, sizeof(inqbuf->atap_revision), 964 needswap); 965 extract_string(serial, sizeof(serial), 966 inqbuf->atap_serial, sizeof(inqbuf->atap_serial), 967 needswap); 968 969 printf("Model: %s, Rev: %s, Serial #: %s\n", 970 model, revision, serial); 971 972 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff && 973 inqbuf->atap_cmd_ext & ATA_CMDE_WWN) 974 printf("World Wide Name: %016" PRIX64 "\n", 975 ((uint64_t)inqbuf->atap_wwn[0] << 48) | 976 ((uint64_t)inqbuf->atap_wwn[1] << 32) | 977 ((uint64_t)inqbuf->atap_wwn[2] << 16) | 978 ((uint64_t)inqbuf->atap_wwn[3] << 0)); 979 980 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 981 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 982 "removable"); 983 984 compute_capacity(inqbuf, &capacity, §ors, &secsize); 985 986 humanize_number(hnum, sizeof(hnum), capacity, "bytes", 987 HN_AUTOSCALE, HN_DIVISOR_1000); 988 989 printf("Capacity %s, %" PRIu64 " sectors, %" PRIu32 " bytes/sector\n", 990 hnum, sectors, secsize); 991 992 printf("Cylinders: %d, heads: %d, sec/track: %d\n", 993 inqbuf->atap_cylinders, inqbuf->atap_heads, 994 inqbuf->atap_sectors); 995 996 lb_per_pb = 1; 997 998 if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) { 999 if (inqbuf->atap_secsz & ATA_SECSZ_LPS) { 1000 lb_per_pb <<= inqbuf->atap_secsz & ATA_SECSZ_LPS_SZMSK; 1001 printf("Physical sector size: %d bytes\n", 1002 lb_per_pb * secsize); 1003 if ((inqbuf->atap_logical_align & 1004 ATA_LA_VALID_MASK) == ATA_LA_VALID) { 1005 printf("First physically aligned sector: %d\n", 1006 lb_per_pb - (inqbuf->atap_logical_align & 1007 ATA_LA_MASK)); 1008 } 1009 } 1010 } 1011 1012 if (((inqbuf->atap_sata_caps & SATA_NATIVE_CMDQ) || 1013 (inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ)) && 1014 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK)) 1015 printf("Command queue depth: %d\n", 1016 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1); 1017 1018 printf("Device capabilities:\n"); 1019 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps); 1020 1021 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 1022 printf("Device supports following standards:\n"); 1023 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers); 1024 printf("\n"); 1025 } 1026 1027 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 1028 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 1029 printf("Command set support:\n"); 1030 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff) 1031 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1, 1032 inqbuf->atap_cmd1_en, ata_cmd_set1); 1033 else 1034 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1, 1035 ata_cmd_set1); 1036 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff) 1037 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2, 1038 inqbuf->atap_cmd2_en, ata_cmd_set2); 1039 else 1040 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2, 1041 ata_cmd_set2); 1042 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff) 1043 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext, 1044 ata_cmd_ext); 1045 } 1046 1047 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) { 1048 printf("Serial ATA capabilities:\n"); 1049 print_bitinfo("\t", "\n", 1050 inqbuf->atap_sata_caps, ata_sata_caps); 1051 1052 } 1053 1054 if (inqbuf->atap_sata_features_supp != 0 && 1055 inqbuf->atap_sata_features_supp != 0xffff) { 1056 printf("Serial ATA features:\n"); 1057 if (inqbuf->atap_sata_features_en != 0 && 1058 inqbuf->atap_sata_features_en != 0xffff) 1059 print_bitinfo2("\t", "\n", 1060 inqbuf->atap_sata_features_supp, 1061 inqbuf->atap_sata_features_en, ata_sata_feat); 1062 else 1063 print_bitinfo("\t", "\n", 1064 inqbuf->atap_sata_features_supp, ata_sata_feat); 1065 } 1066 1067 if ((inqbuf->atap_ata_major & WDC_VER_ATA8) && 1068 (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM)) 1069 printf("TRIM supported\n"); 1070 1071 return; 1072 } 1073 1074 /* 1075 * device idle: 1076 * 1077 * issue the IDLE IMMEDIATE command to the drive 1078 */ 1079 static void 1080 device_idle(int argc, char *argv[]) 1081 { 1082 struct atareq req; 1083 1084 /* No arguments. */ 1085 if (argc != 0) 1086 usage(); 1087 1088 memset(&req, 0, sizeof(req)); 1089 1090 if (strcmp(cmdname, "idle") == 0) 1091 req.command = WDCC_IDLE_IMMED; 1092 else if (strcmp(cmdname, "standby") == 0) 1093 req.command = WDCC_STANDBY_IMMED; 1094 else 1095 req.command = WDCC_SLEEP; 1096 1097 req.timeout = 1000; 1098 1099 ata_command(&req); 1100 1101 return; 1102 } 1103 1104 /* 1105 * device apm: 1106 * 1107 * enable/disable/control the APM feature of the drive 1108 */ 1109 static void 1110 device_apm(int argc, char *argv[]) 1111 { 1112 struct atareq req; 1113 long l; 1114 1115 memset(&req, 0, sizeof(req)); 1116 if (argc >= 1) { 1117 req.command = SET_FEATURES; 1118 req.timeout = 1000; 1119 1120 if (strcmp(argv[0], "disable") == 0) 1121 req.features = WDSF_APM_DS; 1122 else if (strcmp(argv[0], "set") == 0 && argc >= 2 && 1123 (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) { 1124 1125 req.features = WDSF_APM_EN; 1126 req.sec_count = l + 1; 1127 } else 1128 usage(); 1129 } else 1130 usage(); 1131 1132 ata_command(&req); 1133 } 1134 1135 1136 /* 1137 * Set the idle timer on the disk. Set it for either idle mode or 1138 * standby mode, depending on how we were invoked. 1139 */ 1140 1141 static void 1142 device_setidle(int argc, char *argv[]) 1143 { 1144 unsigned long idle; 1145 struct atareq req; 1146 char *end; 1147 1148 /* Only one argument */ 1149 if (argc != 1) 1150 usage(); 1151 1152 idle = strtoul(argv[0], &end, 0); 1153 1154 if (*end != '\0') { 1155 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]); 1156 exit(1); 1157 } 1158 1159 if (idle > 19800) { 1160 fprintf(stderr, "Idle time has a maximum value of 5.5 " 1161 "hours\n"); 1162 exit(1); 1163 } 1164 1165 if (idle != 0 && idle < 5) { 1166 fprintf(stderr, "Idle timer must be at least 5 seconds\n"); 1167 exit(1); 1168 } 1169 1170 memset(&req, 0, sizeof(req)); 1171 1172 if (idle <= 240*5) 1173 req.sec_count = idle / 5; 1174 else 1175 req.sec_count = idle / (30*60) + 240; 1176 1177 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE; 1178 req.timeout = 1000; 1179 1180 ata_command(&req); 1181 1182 return; 1183 } 1184 1185 /* 1186 * Query the device for the current power mode 1187 */ 1188 1189 static void 1190 device_checkpower(int argc, char *argv[]) 1191 { 1192 struct atareq req; 1193 1194 /* No arguments. */ 1195 if (argc != 0) 1196 usage(); 1197 1198 memset(&req, 0, sizeof(req)); 1199 1200 req.command = WDCC_CHECK_PWR; 1201 req.timeout = 1000; 1202 req.flags = ATACMD_READREG; 1203 1204 ata_command(&req); 1205 1206 printf("Current power status: "); 1207 1208 switch (req.sec_count) { 1209 case 0x00: 1210 printf("Standby mode\n"); 1211 break; 1212 case 0x80: 1213 printf("Idle mode\n"); 1214 break; 1215 case 0xff: 1216 printf("Active mode\n"); 1217 break; 1218 default: 1219 printf("Unknown power code (%02x)\n", req.sec_count); 1220 } 1221 1222 return; 1223 } 1224 1225 /* 1226 * device_smart: 1227 * 1228 * Display SMART status 1229 */ 1230 static void 1231 device_smart(int argc, char *argv[]) 1232 { 1233 struct atareq req; 1234 unsigned char inbuf[DEV_BSIZE]; 1235 unsigned char inbuf2[DEV_BSIZE]; 1236 1237 if (argc < 1) 1238 usage(); 1239 1240 if (strcmp(argv[0], "enable") == 0) { 1241 memset(&req, 0, sizeof(req)); 1242 1243 req.features = WDSM_ENABLE_OPS; 1244 req.command = WDCC_SMART; 1245 req.cylinder = WDSMART_CYL; 1246 req.timeout = 1000; 1247 1248 ata_command(&req); 1249 1250 is_smart(); 1251 } else if (strcmp(argv[0], "disable") == 0) { 1252 memset(&req, 0, sizeof(req)); 1253 1254 req.features = WDSM_DISABLE_OPS; 1255 req.command = WDCC_SMART; 1256 req.cylinder = WDSMART_CYL; 1257 req.timeout = 1000; 1258 1259 ata_command(&req); 1260 1261 is_smart(); 1262 } else if (strcmp(argv[0], "status") == 0) { 1263 int rv; 1264 1265 rv = is_smart(); 1266 1267 if (!rv) { 1268 fprintf(stderr, "SMART not supported\n"); 1269 return; 1270 } else if (rv == 3) 1271 return; 1272 1273 memset(&inbuf, 0, sizeof(inbuf)); 1274 memset(&req, 0, sizeof(req)); 1275 1276 req.features = WDSM_STATUS; 1277 req.command = WDCC_SMART; 1278 req.cylinder = WDSMART_CYL; 1279 req.timeout = 1000; 1280 1281 ata_command(&req); 1282 1283 if (req.cylinder != WDSMART_CYL) { 1284 fprintf(stderr, "Threshold exceeds condition\n"); 1285 } 1286 1287 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional 1288 * features, the following ata_command()'s may error 1289 * and exit(). 1290 */ 1291 1292 memset(&inbuf, 0, sizeof(inbuf)); 1293 memset(&req, 0, sizeof(req)); 1294 1295 req.flags = ATACMD_READ; 1296 req.features = WDSM_RD_DATA; 1297 req.command = WDCC_SMART; 1298 req.databuf = (caddr_t) inbuf; 1299 req.datalen = sizeof(inbuf); 1300 req.cylinder = WDSMART_CYL; 1301 req.timeout = 1000; 1302 1303 ata_command(&req); 1304 1305 memset(&inbuf2, 0, sizeof(inbuf2)); 1306 memset(&req, 0, sizeof(req)); 1307 1308 req.flags = ATACMD_READ; 1309 req.features = WDSM_RD_THRESHOLDS; 1310 req.command = WDCC_SMART; 1311 req.databuf = (caddr_t) inbuf2; 1312 req.datalen = sizeof(inbuf2); 1313 req.cylinder = WDSMART_CYL; 1314 req.timeout = 1000; 1315 1316 ata_command(&req); 1317 1318 print_smart_status(inbuf, inbuf2); 1319 1320 } else if (strcmp(argv[0], "offline") == 0) { 1321 if (argc != 2) 1322 usage(); 1323 if (!is_smart()) { 1324 fprintf(stderr, "SMART not supported\n"); 1325 return; 1326 } 1327 1328 memset(&req, 0, sizeof(req)); 1329 1330 req.features = WDSM_EXEC_OFFL_IMM; 1331 req.command = WDCC_SMART; 1332 req.cylinder = WDSMART_CYL; 1333 req.sec_num = atol(argv[1]); 1334 req.timeout = 10000; 1335 1336 ata_command(&req); 1337 } else if (strcmp(argv[0], "error-log") == 0) { 1338 if (!is_smart()) { 1339 fprintf(stderr, "SMART not supported\n"); 1340 return; 1341 } 1342 1343 memset(&inbuf, 0, sizeof(inbuf)); 1344 memset(&req, 0, sizeof(req)); 1345 1346 req.flags = ATACMD_READ; 1347 req.features = WDSM_RD_LOG; 1348 req.sec_count = 1; 1349 req.sec_num = 1; 1350 req.command = WDCC_SMART; 1351 req.databuf = (caddr_t) inbuf; 1352 req.datalen = sizeof(inbuf); 1353 req.cylinder = WDSMART_CYL; 1354 req.timeout = 1000; 1355 1356 ata_command(&req); 1357 1358 print_error(inbuf); 1359 } else if (strcmp(argv[0], "selftest-log") == 0) { 1360 if (!is_smart()) { 1361 fprintf(stderr, "SMART not supported\n"); 1362 return; 1363 } 1364 1365 memset(&inbuf, 0, sizeof(inbuf)); 1366 memset(&req, 0, sizeof(req)); 1367 1368 req.flags = ATACMD_READ; 1369 req.features = WDSM_RD_LOG; 1370 req.sec_count = 1; 1371 req.sec_num = 6; 1372 req.command = WDCC_SMART; 1373 req.databuf = (caddr_t) inbuf; 1374 req.datalen = sizeof(inbuf); 1375 req.cylinder = WDSMART_CYL; 1376 req.timeout = 1000; 1377 1378 ata_command(&req); 1379 1380 print_selftest(inbuf); 1381 1382 } else { 1383 usage(); 1384 } 1385 return; 1386 } 1387 1388 static void 1389 device_security(int argc, char *argv[]) 1390 { 1391 struct atareq req; 1392 const struct ataparams *inqbuf; 1393 unsigned char data[DEV_BSIZE]; 1394 char *pass; 1395 1396 /* need subcommand */ 1397 if (argc < 1) 1398 usage(); 1399 1400 memset(&req, 0, sizeof(req)); 1401 if (strcmp(argv[0], "status") == 0) { 1402 inqbuf = getataparams(); 1403 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st); 1404 } else if (strcmp(argv[0], "freeze") == 0) { 1405 req.command = WDCC_SECURITY_FREEZE; 1406 req.timeout = 1000; 1407 ata_command(&req); 1408 } else if ((strcmp(argv[0], "setpass") == 0) || 1409 (strcmp(argv[0], "unlock") == 0) || 1410 (strcmp(argv[0], "disable") == 0) || 1411 (strcmp(argv[0], "erase") == 0)) { 1412 if (argc != 2) 1413 usage(); 1414 if (strcmp(argv[1], "user") != 0) { 1415 if (strcmp(argv[1], "master") == 0) { 1416 fprintf(stderr, 1417 "Master passwords not supported\n"); 1418 exit(1); 1419 } else { 1420 usage(); 1421 } 1422 } 1423 1424 pass = getpass("Password:"); 1425 if (strlen(pass) > 32) { 1426 fprintf(stderr, "Password must be <=32 characters\n"); 1427 exit(1); 1428 } 1429 1430 req.flags |= ATACMD_WRITE; 1431 req.timeout = 1000; 1432 req.databuf = data; 1433 req.datalen = sizeof(data); 1434 memset(data, 0, sizeof(data)); 1435 strlcpy((void *)&data[2], pass, 32 + 1); 1436 1437 if (strcmp(argv[0], "setpass") == 0) { 1438 char orig[32 + 1]; 1439 strlcpy(orig, pass, 32 + 1); 1440 pass = getpass("Confirm password:"); 1441 if (0 != strcmp(orig, pass)) { 1442 fprintf(stderr, "Passwords do not match\n"); 1443 exit(1); 1444 } 1445 req.command = WDCC_SECURITY_SET_PASSWORD; 1446 } else if (strcmp(argv[0], "unlock") == 0) { 1447 req.command = WDCC_SECURITY_UNLOCK; 1448 } else if (strcmp(argv[0], "disable") == 0) { 1449 req.command = WDCC_SECURITY_DISABLE_PASSWORD; 1450 } else if (strcmp(argv[0], "erase") == 0) { 1451 struct atareq prepare; 1452 1453 inqbuf = getataparams(); 1454 1455 /* 1456 * XXX Any way to lock the device to make sure 1457 * this really is the command preceding the 1458 * SECURITY ERASE UNIT command? This would 1459 * probably have to be moved into the kernel to 1460 * do that. 1461 */ 1462 memset(&prepare, 0, sizeof(prepare)); 1463 prepare.command = WDCC_SECURITY_ERASE_PREPARE; 1464 prepare.timeout = 1000; 1465 ata_command(&prepare); 1466 1467 req.command = WDCC_SECURITY_ERASE_UNIT; 1468 1469 /* 1470 * Enable enhanced erase if it's supported. 1471 * 1472 * XXX should be a command-line option 1473 */ 1474 if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) { 1475 data[0] |= 0x2; 1476 req.timeout = (inqbuf->atap_eseu_time & 0xff) 1477 * 2 * 60 * 1000; 1478 } else { 1479 req.timeout = (inqbuf->atap_seu_time & 0xff) 1480 * 2 * 60 * 1000; 1481 } 1482 1483 /* 1484 * If the estimated time was 0xff (* 2 * 60 * 1485 * 1000 = 30600000), that means `>508 minutes'. 1486 * Estimate that we can handle 16 MB/sec, a 1487 * rate I just pulled out of my arse. 1488 */ 1489 if (req.timeout == 30600000) { 1490 uint64_t bytes, timeout; 1491 compute_capacity(inqbuf, &bytes, NULL, NULL); 1492 timeout = (bytes / (16 * 1024 * 1024)) * 1000; 1493 if (timeout > (uint64_t)INT_MAX) 1494 req.timeout = INT_MAX; 1495 else 1496 req.timeout = timeout; 1497 } 1498 1499 printf("Erasing may take up to %dh %dm %ds...\n", 1500 (req.timeout / 1000 / 60) / 60, 1501 (req.timeout / 1000 / 60) % 60, 1502 req.timeout % 60); 1503 } else { 1504 abort(); 1505 } 1506 1507 ata_command(&req); 1508 } else { 1509 usage(); 1510 } 1511 } 1512 1513 /* 1514 * bus_reset: 1515 * Reset an ATA bus (will reset all devices on the bus) 1516 */ 1517 static void 1518 bus_reset(int argc, char *argv[]) 1519 { 1520 int error; 1521 1522 /* no args */ 1523 if (argc != 0) 1524 usage(); 1525 1526 error = ioctl(fd, ATABUSIORESET, NULL); 1527 1528 if (error == -1) 1529 err(1, "ATABUSIORESET failed"); 1530 } 1531