1 /* $NetBSD: atactl.c,v 1.71 2013/08/06 19:13:13 soren 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.71 2013/08/06 19:13:13 soren 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 { 184, "End-to-end error", NULL }, 277 { 187, "Reported uncorrect", NULL }, 278 { 189, "High Fly Writes", NULL }, 279 { 190, "Airflow Temperature", device_smart_temp }, 280 { 191, "G-sense error rate", NULL }, 281 { 192, "Power-off retract count", NULL }, 282 { 193, "Load cycle count", NULL }, 283 { 194, "Temperature", device_smart_temp}, 284 { 195, "Hardware ECC Recovered", NULL }, 285 { 196, "Reallocated event count", NULL }, 286 { 197, "Current pending sector", NULL }, 287 { 198, "Offline uncorrectable", NULL }, 288 { 199, "Ultra DMA CRC error count", NULL }, 289 { 200, "Write error rate", NULL }, 290 { 201, "Soft read error rate", NULL }, 291 { 202, "Data address mark errors", NULL }, 292 { 203, "Run out cancel", NULL }, 293 { 204, "Soft ECC correction", NULL }, 294 { 205, "Thermal asperity check", NULL }, 295 { 206, "Flying height", NULL }, 296 { 207, "Spin high current", NULL }, 297 { 208, "Spin buzz", NULL }, 298 { 209, "Offline seek performance", NULL }, 299 { 220, "Disk shift", NULL }, 300 { 221, "G-Sense error rate", NULL }, 301 { 222, "Loaded hours", NULL }, 302 { 223, "Load/unload retry count", NULL }, 303 { 224, "Load friction", NULL }, 304 { 225, "Load/unload cycle count", NULL }, 305 { 226, "Load-in time", NULL }, 306 { 227, "Torque amplification count", NULL }, 307 { 228, "Power-off retract count", NULL }, 308 { 230, "GMR head amplitude", NULL }, 309 { 231, "Temperature", device_smart_temp }, 310 { 232, "Available reserved space", NULL }, 311 { 233, "Media wearout indicator", NULL }, 312 { 240, "Head flying hours", NULL }, 313 { 250, "Read error retry rate", NULL }, 314 { 0, "Unknown", NULL }, 315 }; 316 317 static const struct bitinfo ata_sec_st[] = { 318 { WDC_SEC_SUPP, "supported" }, 319 { WDC_SEC_EN, "enabled" }, 320 { WDC_SEC_LOCKED, "locked" }, 321 { WDC_SEC_FROZEN, "frozen" }, 322 { WDC_SEC_EXP, "expired" }, 323 { WDC_SEC_ESE_SUPP, "enhanced erase support" }, 324 { WDC_SEC_LEV_MAX, "maximum level" }, 325 { 0, NULL }, 326 }; 327 328 int 329 main(int argc, char *argv[]) 330 { 331 int i; 332 const struct command *commands = NULL; 333 334 /* Must have at least: device command */ 335 if (argc < 3) 336 usage(); 337 338 /* Skip program name, get and skip device name and command. */ 339 dvname = argv[1]; 340 cmdname = argv[2]; 341 argv += 3; 342 argc -= 3; 343 344 /* 345 * Open the device 346 */ 347 fd = opendisk(dvname, O_RDWR, dvname_store, sizeof(dvname_store), 0); 348 if (fd == -1) { 349 if (errno == ENOENT) { 350 /* 351 * Device doesn't exist. Probably trying to open 352 * a device which doesn't use disk semantics for 353 * device name. Try again, specifying "cooked", 354 * which leaves off the "r" in front of the device's 355 * name. 356 */ 357 fd = opendisk(dvname, O_RDWR, dvname_store, 358 sizeof(dvname_store), 1); 359 if (fd == -1) 360 err(1, "%s", dvname); 361 } else 362 err(1, "%s", dvname); 363 } 364 365 /* 366 * Point the dvname at the actual device name that opendisk() opened. 367 */ 368 dvname = dvname_store; 369 370 /* Look up and call the command. */ 371 for (i = 0; device_commands[i].cmd_name != NULL; i++) { 372 if (strcmp(cmdname, device_commands[i].cmd_name) == 0) { 373 commands = &device_commands[i]; 374 break; 375 } 376 } 377 if (commands == NULL) { 378 for (i = 0; bus_commands[i].cmd_name != NULL; i++) { 379 if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) { 380 commands = &bus_commands[i]; 381 break; 382 } 383 } 384 } 385 if (commands == NULL) 386 errx(1, "unknown command: %s", cmdname); 387 388 (*commands->cmd_func)(argc, argv); 389 exit(0); 390 } 391 392 static void 393 usage(void) 394 { 395 int i; 396 397 fprintf(stderr, "usage: %s device command [arg [...]]\n", 398 getprogname()); 399 400 fprintf(stderr, " Available device commands:\n"); 401 for (i=0; device_commands[i].cmd_name != NULL; i++) 402 fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name, 403 device_commands[i].arg_names); 404 405 fprintf(stderr, " Available bus commands:\n"); 406 for (i=0; bus_commands[i].cmd_name != NULL; i++) 407 fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name, 408 bus_commands[i].arg_names); 409 410 exit(1); 411 } 412 413 /* 414 * Wrapper that calls ATAIOCCOMMAND and checks for errors 415 */ 416 417 static void 418 ata_command(struct atareq *req) 419 { 420 int error; 421 422 error = ioctl(fd, ATAIOCCOMMAND, req); 423 424 if (error == -1) 425 err(1, "ATAIOCCOMMAND failed"); 426 427 switch (req->retsts) { 428 429 case ATACMD_OK: 430 return; 431 case ATACMD_TIMEOUT: 432 fprintf(stderr, "ATA command timed out\n"); 433 exit(1); 434 case ATACMD_DF: 435 fprintf(stderr, "ATA device returned a Device Fault\n"); 436 exit(1); 437 case ATACMD_ERROR: 438 if (req->error & WDCE_ABRT) 439 fprintf(stderr, "ATA device returned Aborted " 440 "Command\n"); 441 else 442 fprintf(stderr, "ATA device returned error register " 443 "%0x\n", req->error); 444 exit(1); 445 default: 446 fprintf(stderr, "ATAIOCCOMMAND returned unknown result code " 447 "%d\n", req->retsts); 448 exit(1); 449 } 450 } 451 452 /* 453 * Print out strings associated with particular bitmasks 454 */ 455 456 static void 457 print_bitinfo(const char *bf, const char *af, u_int bits, 458 const struct bitinfo *binfo) 459 { 460 461 for (; binfo->bitmask != 0; binfo++) 462 if (bits & binfo->bitmask) 463 printf("%s%s%s", bf, binfo->string, af); 464 } 465 466 static void 467 print_bitinfo2(const char *bf, const char *af, u_int bits, u_int enables, 468 const struct bitinfo *binfo) 469 { 470 471 for (; binfo->bitmask != 0; binfo++) 472 if (bits & binfo->bitmask) 473 printf("%s%s (%s)%s", bf, binfo->string, 474 (enables & binfo->bitmask) ? "enabled" : "disabled", 475 af); 476 } 477 478 479 /* 480 * Try to print SMART temperature field 481 */ 482 483 static void 484 device_smart_temp(const struct ata_smart_attr *attr, uint64_t raw_value) 485 { 486 printf("%" PRIu8, attr->raw[0]); 487 if (attr->raw[0] != raw_value) 488 printf(" Lifetime min/max %" PRIu8 "/%" PRIu8, 489 attr->raw[2], attr->raw[4]); 490 } 491 492 493 /* 494 * Print out SMART attribute thresholds and values 495 */ 496 497 static void 498 print_smart_status(void *vbuf, void *tbuf) 499 { 500 const struct ata_smart_attributes *value_buf = vbuf; 501 const struct ata_smart_thresholds *threshold_buf = tbuf; 502 const struct ata_smart_attr *attr; 503 uint64_t raw_value; 504 int flags; 505 int i, j; 506 int aid; 507 uint8_t checksum; 508 509 for (i = checksum = 0; i < 512; i++) 510 checksum += ((const uint8_t *) value_buf)[i]; 511 if (checksum != 0) { 512 fprintf(stderr, "SMART attribute values checksum error\n"); 513 return; 514 } 515 516 for (i = checksum = 0; i < 512; i++) 517 checksum += ((const uint8_t *) threshold_buf)[i]; 518 if (checksum != 0) { 519 fprintf(stderr, "SMART attribute thresholds checksum error\n"); 520 return; 521 } 522 523 printf("id value thresh crit collect reliability description" 524 " raw\n"); 525 for (i = 0; i < 256; i++) { 526 int thresh = 0; 527 528 attr = NULL; 529 530 for (j = 0; j < 30; j++) { 531 if (value_buf->attributes[j].id == i) 532 attr = &value_buf->attributes[j]; 533 if (threshold_buf->thresholds[j].id == i) 534 thresh = threshold_buf->thresholds[j].value; 535 } 536 537 if (thresh && attr == NULL) 538 errx(1, "threshold but not attr %d", i); 539 if (attr == NULL) 540 continue; 541 542 if (attr->value == 0||attr->value == 0xFE||attr->value == 0xFF) 543 continue; 544 545 for (aid = 0; 546 smart_attrs[aid].id != i && smart_attrs[aid].id != 0; 547 aid++) 548 ; 549 550 flags = le16toh(attr->flags); 551 552 printf("%3d %3d %3d %-3s %-7s %stive %-27s ", 553 i, attr->value, thresh, 554 flags & WDSM_ATTR_ADVISORY ? "yes" : "no", 555 flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline", 556 attr->value > thresh ? "posi" : "nega", 557 smart_attrs[aid].name); 558 559 for (j = 0, raw_value = 0; j < 6; j++) 560 raw_value += ((uint64_t)attr->raw[j]) << (8*j); 561 562 if (smart_attrs[aid].special) 563 (*smart_attrs[aid].special)(attr, raw_value); 564 else 565 printf("%" PRIu64, raw_value); 566 printf("\n"); 567 } 568 } 569 570 static const struct { 571 int number; 572 const char *name; 573 } selftest_name[] = { 574 { 0, "Off-line" }, 575 { 1, "Short off-line" }, 576 { 2, "Extended off-line" }, 577 { 127, "Abort off-line test" }, 578 { 129, "Short captive" }, 579 { 130, "Extended captive" }, 580 { 256, "Unknown test" }, /* larger then uint8_t */ 581 { 0, NULL } 582 }; 583 584 static const char *selftest_status[] = { 585 "No error", 586 "Aborted by the host", 587 "Interrupted by the host by reset", 588 "Fatal error or unknown test error", 589 "Unknown test element failed", 590 "Electrical test element failed", 591 "The Servo (and/or seek) test element failed", 592 "Read element of test failed", 593 "Reserved", 594 "Reserved", 595 "Reserved", 596 "Reserved", 597 "Reserved", 598 "Reserved", 599 "Reserved", 600 "Self-test in progress" 601 }; 602 603 static void 604 print_error_entry(int num, const struct ata_smart_error *le) 605 { 606 int i; 607 608 printf("Log entry: %d\n", num); 609 610 for (i = 0; i < 5; i++) 611 printf("\tCommand %d: dc=%02x sf=%02x sc=%02x sn=%02x cl=%02x " 612 "ch=%02x dh=%02x cmd=%02x time=%02x%02x%02x%02x\n", i, 613 le->command[i].device_control, 614 le->command[i].features, 615 le->command[i].sector_count, 616 le->command[i].sector_number, 617 le->command[i].cylinder_low, 618 le->command[i].cylinder_high, 619 le->command[i].device_head, 620 le->command[i].command, 621 le->command[i].timestamp[3], 622 le->command[i].timestamp[2], 623 le->command[i].timestamp[1], 624 le->command[i].timestamp[0]); 625 printf("\tError: err=%02x sc=%02x sn=%02x cl=%02x ch=%02x dh=%02x " 626 "status=%02x state=%02x lifetime=%02x%02x\n", 627 le->error_data.error, 628 le->error_data.sector_count, 629 le->error_data.sector_number, 630 le->error_data.cylinder_low, 631 le->error_data.cylinder_high, 632 le->error_data.device_head, 633 le->error_data.status, 634 le->error_data.state, 635 le->error_data.lifetime[1], 636 le->error_data.lifetime[0]); 637 printf("\tExtended: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " 638 "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 639 le->error_data.extended_error[0], 640 le->error_data.extended_error[1], 641 le->error_data.extended_error[2], 642 le->error_data.extended_error[3], 643 le->error_data.extended_error[4], 644 le->error_data.extended_error[5], 645 le->error_data.extended_error[6], 646 le->error_data.extended_error[7], 647 le->error_data.extended_error[8], 648 le->error_data.extended_error[9], 649 le->error_data.extended_error[10], 650 le->error_data.extended_error[11], 651 le->error_data.extended_error[12], 652 le->error_data.extended_error[13], 653 le->error_data.extended_error[14], 654 le->error_data.extended_error[15], 655 le->error_data.extended_error[15], 656 le->error_data.extended_error[17], 657 le->error_data.extended_error[18]); 658 } 659 660 static void 661 print_error(const void *buf) 662 { 663 const struct ata_smart_errorlog *erlog = buf; 664 uint8_t checksum; 665 int i; 666 667 for (i = checksum = 0; i < 512; i++) 668 checksum += ((const uint8_t *) buf)[i]; 669 if (checksum != 0) { 670 fprintf(stderr, "SMART error log checksum error\n"); 671 return; 672 } 673 674 if (erlog->data_structure_revision != 1) { 675 fprintf(stderr, "Error log revision not 1 (found 0x%04x)\n", 676 erlog->data_structure_revision); 677 return; 678 } 679 680 if (erlog->mostrecenterror == 0) { 681 printf("No errors have been logged\n"); 682 return; 683 } 684 685 if (erlog->mostrecenterror > 5) { 686 fprintf(stderr, "Most recent error is too large\n"); 687 return; 688 } 689 690 for (i = erlog->mostrecenterror; i < 5; i++) 691 print_error_entry(i, &erlog->log_entries[i]); 692 for (i = 0; i < erlog->mostrecenterror; i++) 693 print_error_entry(i, &erlog->log_entries[i]); 694 printf("device error count: %d\n", erlog->device_error_count); 695 } 696 697 static void 698 print_selftest_entry(int num, const struct ata_smart_selftest *le) 699 { 700 const unsigned char *p; 701 size_t i; 702 703 /* check if all zero */ 704 for (p = (const void *)le, i = 0; i < sizeof(*le); i++) 705 if (p[i] != 0) 706 break; 707 if (i == sizeof(*le)) 708 return; 709 710 printf("Log entry: %d\n", num); 711 712 /* Get test name */ 713 for (i = 0; selftest_name[i].name != NULL; i++) 714 if (selftest_name[i].number == le->number) 715 break; 716 717 if (selftest_name[i].name == NULL) 718 printf("\tName: (%d)\n", le->number); 719 else 720 printf("\tName: %s\n", selftest_name[i].name); 721 printf("\tStatus: %s\n", selftest_status[le->status >> 4]); 722 /* XXX This generally should not be set when a self-test is completed, 723 and at any rate is useless. - mycroft */ 724 if (le->status >> 4 == 15) 725 printf("\tPercent of test remaining: %1d0\n", le->status & 0xf); 726 else if (le->status >> 4 != 0) 727 printf("\tLBA first error: %d\n", le32toh(le->lba_first_error)); 728 } 729 730 static void 731 print_selftest(const void *buf) 732 { 733 const struct ata_smart_selftestlog *stlog = buf; 734 uint8_t checksum; 735 int i; 736 737 for (i = checksum = 0; i < 512; i++) 738 checksum += ((const uint8_t *) buf)[i]; 739 if (checksum != 0) { 740 fprintf(stderr, "SMART selftest log checksum error\n"); 741 return; 742 } 743 744 if (le16toh(stlog->data_structure_revision) != 1) { 745 fprintf(stderr, "Self-test log revision not 1 (found 0x%04x)\n", 746 le16toh(stlog->data_structure_revision)); 747 return; 748 } 749 750 if (stlog->mostrecenttest == 0) { 751 printf("No self-tests have been logged\n"); 752 return; 753 } 754 755 if (stlog->mostrecenttest > 22) { 756 fprintf(stderr, "Most recent test is too large\n"); 757 return; 758 } 759 760 for (i = stlog->mostrecenttest; i < 22; i++) 761 print_selftest_entry(i, &stlog->log_entries[i]); 762 for (i = 0; i < stlog->mostrecenttest; i++) 763 print_selftest_entry(i, &stlog->log_entries[i]); 764 } 765 766 static const struct ataparams * 767 getataparams(void) 768 { 769 struct atareq req; 770 static union { 771 unsigned char inbuf[DEV_BSIZE]; 772 struct ataparams inqbuf; 773 } inbuf; 774 775 memset(&inbuf, 0, sizeof(inbuf)); 776 memset(&req, 0, sizeof(req)); 777 778 req.flags = ATACMD_READ; 779 req.command = WDCC_IDENTIFY; 780 req.databuf = &inbuf; 781 req.datalen = sizeof(inbuf); 782 req.timeout = 1000; 783 784 ata_command(&req); 785 786 return (&inbuf.inqbuf); 787 } 788 789 /* 790 * is_smart: 791 * 792 * Detect whether device supports SMART and SMART is enabled. 793 */ 794 795 static int 796 is_smart(void) 797 { 798 int retval = 0; 799 const struct ataparams *inqbuf; 800 const char *status; 801 802 inqbuf = getataparams(); 803 804 if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) { 805 if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) { 806 fprintf(stderr, "SMART unsupported\n"); 807 } else { 808 if (inqbuf->atap_ata_major <= WDC_VER_ATA5 || 809 inqbuf->atap_cmd_set2 == 0xffff || 810 inqbuf->atap_cmd_set2 == 0x0000) { 811 status = "status unknown"; 812 retval = 2; 813 } else { 814 if (inqbuf->atap_cmd1_en & WDC_CMD1_SMART) { 815 status = "enabled"; 816 retval = 1; 817 } else { 818 status = "disabled"; 819 retval = 3; 820 } 821 } 822 printf("SMART supported, SMART %s\n", status); 823 } 824 } 825 return retval; 826 } 827 828 /* 829 * extract_string: copy a block of bytes out of ataparams and make 830 * a proper string out of it, truncating trailing spaces and preserving 831 * strict typing. And also, not doing unaligned accesses. 832 */ 833 static void 834 extract_string(char *buf, size_t bufmax, 835 const uint8_t *bytes, size_t numbytes, 836 int needswap) 837 { 838 unsigned i; 839 size_t j; 840 unsigned char ch1, ch2; 841 842 for (i = 0, j = 0; i < numbytes; i += 2) { 843 ch1 = bytes[i]; 844 ch2 = bytes[i+1]; 845 if (needswap && j < bufmax-1) { 846 buf[j++] = ch2; 847 } 848 if (j < bufmax-1) { 849 buf[j++] = ch1; 850 } 851 if (!needswap && j < bufmax-1) { 852 buf[j++] = ch2; 853 } 854 } 855 while (j > 0 && buf[j-1] == ' ') { 856 j--; 857 } 858 buf[j] = '\0'; 859 } 860 861 static void 862 compute_capacity(const struct ataparams *inqbuf, uint64_t *capacityp, 863 uint64_t *sectorsp, uint32_t *secsizep) 864 { 865 uint64_t capacity; 866 uint64_t sectors; 867 uint32_t secsize; 868 869 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff && 870 inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) { 871 sectors = 872 ((uint64_t)inqbuf->atap_max_lba[3] << 48) | 873 ((uint64_t)inqbuf->atap_max_lba[2] << 32) | 874 ((uint64_t)inqbuf->atap_max_lba[1] << 16) | 875 ((uint64_t)inqbuf->atap_max_lba[0] << 0); 876 } else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) { 877 sectors = (inqbuf->atap_capacity[1] << 16) | 878 inqbuf->atap_capacity[0]; 879 } else { 880 sectors = inqbuf->atap_cylinders * 881 inqbuf->atap_heads * inqbuf->atap_sectors; 882 } 883 884 secsize = 512; 885 886 if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) { 887 if (inqbuf->atap_secsz & ATA_SECSZ_LLS) { 888 secsize = 2 * /* words to bytes */ 889 (inqbuf->atap_lls_secsz[1] << 16 | 890 inqbuf->atap_lls_secsz[0] << 0); 891 } 892 } 893 894 capacity = sectors * secsize; 895 896 if (capacityp) 897 *capacityp = capacity; 898 if (sectorsp) 899 *sectorsp = sectors; 900 if (secsizep) 901 *secsizep = secsize; 902 } 903 904 /* 905 * DEVICE COMMANDS 906 */ 907 908 /* 909 * device_identify: 910 * 911 * Display the identity of the device 912 */ 913 static void 914 device_identify(int argc, char *argv[]) 915 { 916 const struct ataparams *inqbuf; 917 char model[sizeof(inqbuf->atap_model)+1]; 918 char revision[sizeof(inqbuf->atap_revision)+1]; 919 char serial[sizeof(inqbuf->atap_serial)+1]; 920 char hnum[12]; 921 uint64_t capacity; 922 uint64_t sectors; 923 uint32_t secsize; 924 int lb_per_pb; 925 int needswap = 0; 926 int i; 927 uint8_t checksum; 928 929 /* No arguments. */ 930 if (argc != 0) 931 usage(); 932 933 inqbuf = getataparams(); 934 935 if ((inqbuf->atap_integrity & WDC_INTEGRITY_MAGIC_MASK) == 936 WDC_INTEGRITY_MAGIC) { 937 for (i = checksum = 0; i < 512; i++) 938 checksum += ((const uint8_t *)inqbuf)[i]; 939 if (checksum != 0) 940 puts("IDENTIFY DEVICE data checksum invalid\n"); 941 } 942 943 #if BYTE_ORDER == LITTLE_ENDIAN 944 /* 945 * On little endian machines, we need to shuffle the string 946 * byte order. However, we don't have to do this for NEC or 947 * Mitsumi ATAPI devices 948 */ 949 950 if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI && 951 ((inqbuf->atap_model[0] == 'N' && 952 inqbuf->atap_model[1] == 'E') || 953 (inqbuf->atap_model[0] == 'F' && 954 inqbuf->atap_model[1] == 'X')))) { 955 needswap = 1; 956 } 957 #endif 958 959 /* 960 * Copy the info strings out, stripping off blanks. 961 */ 962 extract_string(model, sizeof(model), 963 inqbuf->atap_model, sizeof(inqbuf->atap_model), 964 needswap); 965 extract_string(revision, sizeof(revision), 966 inqbuf->atap_revision, sizeof(inqbuf->atap_revision), 967 needswap); 968 extract_string(serial, sizeof(serial), 969 inqbuf->atap_serial, sizeof(inqbuf->atap_serial), 970 needswap); 971 972 printf("Model: %s, Rev: %s, Serial #: %s\n", 973 model, revision, serial); 974 975 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff && 976 inqbuf->atap_cmd_ext & ATA_CMDE_WWN) 977 printf("World Wide Name: %016" PRIX64 "\n", 978 ((uint64_t)inqbuf->atap_wwn[0] << 48) | 979 ((uint64_t)inqbuf->atap_wwn[1] << 32) | 980 ((uint64_t)inqbuf->atap_wwn[2] << 16) | 981 ((uint64_t)inqbuf->atap_wwn[3] << 0)); 982 983 printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ? 984 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : 985 "removable"); 986 987 compute_capacity(inqbuf, &capacity, §ors, &secsize); 988 989 humanize_number(hnum, sizeof(hnum), capacity, "bytes", 990 HN_AUTOSCALE, HN_DIVISOR_1000); 991 992 printf("Capacity %s, %" PRIu64 " sectors, %" PRIu32 " bytes/sector\n", 993 hnum, sectors, secsize); 994 995 printf("Cylinders: %d, heads: %d, sec/track: %d\n", 996 inqbuf->atap_cylinders, inqbuf->atap_heads, 997 inqbuf->atap_sectors); 998 999 lb_per_pb = 1; 1000 1001 if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) { 1002 if (inqbuf->atap_secsz & ATA_SECSZ_LPS) { 1003 lb_per_pb <<= inqbuf->atap_secsz & ATA_SECSZ_LPS_SZMSK; 1004 printf("Physical sector size: %d bytes\n", 1005 lb_per_pb * secsize); 1006 if ((inqbuf->atap_logical_align & 1007 ATA_LA_VALID_MASK) == ATA_LA_VALID) { 1008 printf("First physically aligned sector: %d\n", 1009 lb_per_pb - (inqbuf->atap_logical_align & 1010 ATA_LA_MASK)); 1011 } 1012 } 1013 } 1014 1015 if (((inqbuf->atap_sata_caps & SATA_NATIVE_CMDQ) || 1016 (inqbuf->atap_cmd_set2 & ATA_CMD2_RWQ)) && 1017 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK)) 1018 printf("Command queue depth: %d\n", 1019 (inqbuf->atap_queuedepth & WDC_QUEUE_DEPTH_MASK) + 1); 1020 1021 printf("Device capabilities:\n"); 1022 print_bitinfo("\t", "\n", inqbuf->atap_capabilities1, ata_caps); 1023 1024 if (inqbuf->atap_ata_major != 0 && inqbuf->atap_ata_major != 0xffff) { 1025 printf("Device supports following standards:\n"); 1026 print_bitinfo("", " ", inqbuf->atap_ata_major, ata_vers); 1027 printf("\n"); 1028 } 1029 1030 if (inqbuf->atap_cmd_set1 != 0 && inqbuf->atap_cmd_set1 != 0xffff && 1031 inqbuf->atap_cmd_set2 != 0 && inqbuf->atap_cmd_set2 != 0xffff) { 1032 printf("Command set support:\n"); 1033 if (inqbuf->atap_cmd1_en != 0 && inqbuf->atap_cmd1_en != 0xffff) 1034 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set1, 1035 inqbuf->atap_cmd1_en, ata_cmd_set1); 1036 else 1037 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set1, 1038 ata_cmd_set1); 1039 if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff) 1040 print_bitinfo2("\t", "\n", inqbuf->atap_cmd_set2, 1041 inqbuf->atap_cmd2_en, ata_cmd_set2); 1042 else 1043 print_bitinfo("\t", "\n", inqbuf->atap_cmd_set2, 1044 ata_cmd_set2); 1045 if (inqbuf->atap_cmd_ext != 0 && inqbuf->atap_cmd_ext != 0xffff) 1046 print_bitinfo("\t", "\n", inqbuf->atap_cmd_ext, 1047 ata_cmd_ext); 1048 } 1049 1050 if (inqbuf->atap_sata_caps != 0 && inqbuf->atap_sata_caps != 0xffff) { 1051 printf("Serial ATA capabilities:\n"); 1052 print_bitinfo("\t", "\n", 1053 inqbuf->atap_sata_caps, ata_sata_caps); 1054 1055 } 1056 1057 if (inqbuf->atap_sata_features_supp != 0 && 1058 inqbuf->atap_sata_features_supp != 0xffff) { 1059 printf("Serial ATA features:\n"); 1060 if (inqbuf->atap_sata_features_en != 0 && 1061 inqbuf->atap_sata_features_en != 0xffff) 1062 print_bitinfo2("\t", "\n", 1063 inqbuf->atap_sata_features_supp, 1064 inqbuf->atap_sata_features_en, ata_sata_feat); 1065 else 1066 print_bitinfo("\t", "\n", 1067 inqbuf->atap_sata_features_supp, ata_sata_feat); 1068 } 1069 1070 if ((inqbuf->atap_ata_major & WDC_VER_ATA7) && 1071 (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM)) 1072 printf("TRIM supported\n"); 1073 1074 return; 1075 } 1076 1077 /* 1078 * device idle: 1079 * 1080 * issue the IDLE IMMEDIATE command to the drive 1081 */ 1082 static void 1083 device_idle(int argc, char *argv[]) 1084 { 1085 struct atareq req; 1086 1087 /* No arguments. */ 1088 if (argc != 0) 1089 usage(); 1090 1091 memset(&req, 0, sizeof(req)); 1092 1093 if (strcmp(cmdname, "idle") == 0) 1094 req.command = WDCC_IDLE_IMMED; 1095 else if (strcmp(cmdname, "standby") == 0) 1096 req.command = WDCC_STANDBY_IMMED; 1097 else 1098 req.command = WDCC_SLEEP; 1099 1100 req.timeout = 1000; 1101 1102 ata_command(&req); 1103 1104 return; 1105 } 1106 1107 /* 1108 * device apm: 1109 * 1110 * enable/disable/control the APM feature of the drive 1111 */ 1112 static void 1113 device_apm(int argc, char *argv[]) 1114 { 1115 struct atareq req; 1116 long l; 1117 1118 memset(&req, 0, sizeof(req)); 1119 if (argc >= 1) { 1120 req.command = SET_FEATURES; 1121 req.timeout = 1000; 1122 1123 if (strcmp(argv[0], "disable") == 0) 1124 req.features = WDSF_APM_DS; 1125 else if (strcmp(argv[0], "set") == 0 && argc >= 2 && 1126 (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) { 1127 1128 req.features = WDSF_APM_EN; 1129 req.sec_count = l + 1; 1130 } else 1131 usage(); 1132 } else 1133 usage(); 1134 1135 ata_command(&req); 1136 } 1137 1138 1139 /* 1140 * Set the idle timer on the disk. Set it for either idle mode or 1141 * standby mode, depending on how we were invoked. 1142 */ 1143 1144 static void 1145 device_setidle(int argc, char *argv[]) 1146 { 1147 unsigned long idle; 1148 struct atareq req; 1149 char *end; 1150 1151 /* Only one argument */ 1152 if (argc != 1) 1153 usage(); 1154 1155 idle = strtoul(argv[0], &end, 0); 1156 1157 if (*end != '\0') { 1158 fprintf(stderr, "Invalid idle time: \"%s\"\n", argv[0]); 1159 exit(1); 1160 } 1161 1162 if (idle > 19800) { 1163 fprintf(stderr, "Idle time has a maximum value of 5.5 " 1164 "hours\n"); 1165 exit(1); 1166 } 1167 1168 if (idle != 0 && idle < 5) { 1169 fprintf(stderr, "Idle timer must be at least 5 seconds\n"); 1170 exit(1); 1171 } 1172 1173 memset(&req, 0, sizeof(req)); 1174 1175 if (idle <= 240*5) 1176 req.sec_count = idle / 5; 1177 else 1178 req.sec_count = idle / (30*60) + 240; 1179 1180 req.command = cmdname[3] == 's' ? WDCC_STANDBY : WDCC_IDLE; 1181 req.timeout = 1000; 1182 1183 ata_command(&req); 1184 1185 return; 1186 } 1187 1188 /* 1189 * Query the device for the current power mode 1190 */ 1191 1192 static void 1193 device_checkpower(int argc, char *argv[]) 1194 { 1195 struct atareq req; 1196 1197 /* No arguments. */ 1198 if (argc != 0) 1199 usage(); 1200 1201 memset(&req, 0, sizeof(req)); 1202 1203 req.command = WDCC_CHECK_PWR; 1204 req.timeout = 1000; 1205 req.flags = ATACMD_READREG; 1206 1207 ata_command(&req); 1208 1209 printf("Current power status: "); 1210 1211 switch (req.sec_count) { 1212 case 0x00: 1213 printf("Standby mode\n"); 1214 break; 1215 case 0x80: 1216 printf("Idle mode\n"); 1217 break; 1218 case 0xff: 1219 printf("Active mode\n"); 1220 break; 1221 default: 1222 printf("Unknown power code (%02x)\n", req.sec_count); 1223 } 1224 1225 return; 1226 } 1227 1228 /* 1229 * device_smart: 1230 * 1231 * Display SMART status 1232 */ 1233 static void 1234 device_smart(int argc, char *argv[]) 1235 { 1236 struct atareq req; 1237 unsigned char inbuf[DEV_BSIZE]; 1238 unsigned char inbuf2[DEV_BSIZE]; 1239 1240 if (argc < 1) 1241 usage(); 1242 1243 if (strcmp(argv[0], "enable") == 0) { 1244 memset(&req, 0, sizeof(req)); 1245 1246 req.features = WDSM_ENABLE_OPS; 1247 req.command = WDCC_SMART; 1248 req.cylinder = WDSMART_CYL; 1249 req.timeout = 1000; 1250 1251 ata_command(&req); 1252 1253 is_smart(); 1254 } else if (strcmp(argv[0], "disable") == 0) { 1255 memset(&req, 0, sizeof(req)); 1256 1257 req.features = WDSM_DISABLE_OPS; 1258 req.command = WDCC_SMART; 1259 req.cylinder = WDSMART_CYL; 1260 req.timeout = 1000; 1261 1262 ata_command(&req); 1263 1264 is_smart(); 1265 } else if (strcmp(argv[0], "status") == 0) { 1266 int rv; 1267 1268 rv = is_smart(); 1269 1270 if (!rv) { 1271 fprintf(stderr, "SMART not supported\n"); 1272 return; 1273 } else if (rv == 3) 1274 return; 1275 1276 memset(&inbuf, 0, sizeof(inbuf)); 1277 memset(&req, 0, sizeof(req)); 1278 1279 req.features = WDSM_STATUS; 1280 req.command = WDCC_SMART; 1281 req.cylinder = WDSMART_CYL; 1282 req.timeout = 1000; 1283 1284 ata_command(&req); 1285 1286 if (req.cylinder != WDSMART_CYL) { 1287 fprintf(stderr, "Threshold exceeds condition\n"); 1288 } 1289 1290 /* WDSM_RD_DATA and WDSM_RD_THRESHOLDS are optional 1291 * features, the following ata_command()'s may error 1292 * and exit(). 1293 */ 1294 1295 memset(&inbuf, 0, sizeof(inbuf)); 1296 memset(&req, 0, sizeof(req)); 1297 1298 req.flags = ATACMD_READ; 1299 req.features = WDSM_RD_DATA; 1300 req.command = WDCC_SMART; 1301 req.databuf = (caddr_t) inbuf; 1302 req.datalen = sizeof(inbuf); 1303 req.cylinder = WDSMART_CYL; 1304 req.timeout = 1000; 1305 1306 ata_command(&req); 1307 1308 memset(&inbuf2, 0, sizeof(inbuf2)); 1309 memset(&req, 0, sizeof(req)); 1310 1311 req.flags = ATACMD_READ; 1312 req.features = WDSM_RD_THRESHOLDS; 1313 req.command = WDCC_SMART; 1314 req.databuf = (caddr_t) inbuf2; 1315 req.datalen = sizeof(inbuf2); 1316 req.cylinder = WDSMART_CYL; 1317 req.timeout = 1000; 1318 1319 ata_command(&req); 1320 1321 print_smart_status(inbuf, inbuf2); 1322 1323 } else if (strcmp(argv[0], "offline") == 0) { 1324 if (argc != 2) 1325 usage(); 1326 if (!is_smart()) { 1327 fprintf(stderr, "SMART not supported\n"); 1328 return; 1329 } 1330 1331 memset(&req, 0, sizeof(req)); 1332 1333 req.features = WDSM_EXEC_OFFL_IMM; 1334 req.command = WDCC_SMART; 1335 req.cylinder = WDSMART_CYL; 1336 req.sec_num = atol(argv[1]); 1337 req.timeout = 10000; 1338 1339 ata_command(&req); 1340 } else if (strcmp(argv[0], "error-log") == 0) { 1341 if (!is_smart()) { 1342 fprintf(stderr, "SMART not supported\n"); 1343 return; 1344 } 1345 1346 memset(&inbuf, 0, sizeof(inbuf)); 1347 memset(&req, 0, sizeof(req)); 1348 1349 req.flags = ATACMD_READ; 1350 req.features = WDSM_RD_LOG; 1351 req.sec_count = 1; 1352 req.sec_num = 1; 1353 req.command = WDCC_SMART; 1354 req.databuf = (caddr_t) inbuf; 1355 req.datalen = sizeof(inbuf); 1356 req.cylinder = WDSMART_CYL; 1357 req.timeout = 1000; 1358 1359 ata_command(&req); 1360 1361 print_error(inbuf); 1362 } else if (strcmp(argv[0], "selftest-log") == 0) { 1363 if (!is_smart()) { 1364 fprintf(stderr, "SMART not supported\n"); 1365 return; 1366 } 1367 1368 memset(&inbuf, 0, sizeof(inbuf)); 1369 memset(&req, 0, sizeof(req)); 1370 1371 req.flags = ATACMD_READ; 1372 req.features = WDSM_RD_LOG; 1373 req.sec_count = 1; 1374 req.sec_num = 6; 1375 req.command = WDCC_SMART; 1376 req.databuf = (caddr_t) inbuf; 1377 req.datalen = sizeof(inbuf); 1378 req.cylinder = WDSMART_CYL; 1379 req.timeout = 1000; 1380 1381 ata_command(&req); 1382 1383 print_selftest(inbuf); 1384 1385 } else { 1386 usage(); 1387 } 1388 return; 1389 } 1390 1391 static void 1392 device_security(int argc, char *argv[]) 1393 { 1394 struct atareq req; 1395 const struct ataparams *inqbuf; 1396 unsigned char data[DEV_BSIZE]; 1397 char *pass; 1398 1399 /* need subcommand */ 1400 if (argc < 1) 1401 usage(); 1402 1403 memset(&req, 0, sizeof(req)); 1404 if (strcmp(argv[0], "status") == 0) { 1405 inqbuf = getataparams(); 1406 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st); 1407 } else if (strcmp(argv[0], "freeze") == 0) { 1408 req.command = WDCC_SECURITY_FREEZE; 1409 req.timeout = 1000; 1410 ata_command(&req); 1411 } else if ((strcmp(argv[0], "setpass") == 0) || 1412 (strcmp(argv[0], "unlock") == 0) || 1413 (strcmp(argv[0], "disable") == 0) || 1414 (strcmp(argv[0], "erase") == 0)) { 1415 if (argc != 2) 1416 usage(); 1417 if (strcmp(argv[1], "user") != 0) { 1418 if (strcmp(argv[1], "master") == 0) { 1419 fprintf(stderr, 1420 "Master passwords not supported\n"); 1421 exit(1); 1422 } else { 1423 usage(); 1424 } 1425 } 1426 1427 pass = getpass("Password:"); 1428 if (strlen(pass) > 32) { 1429 fprintf(stderr, "Password must be <=32 characters\n"); 1430 exit(1); 1431 } 1432 1433 req.flags |= ATACMD_WRITE; 1434 req.timeout = 1000; 1435 req.databuf = data; 1436 req.datalen = sizeof(data); 1437 memset(data, 0, sizeof(data)); 1438 strlcpy((void *)&data[2], pass, 32 + 1); 1439 1440 if (strcmp(argv[0], "setpass") == 0) { 1441 char orig[32 + 1]; 1442 strlcpy(orig, pass, 32 + 1); 1443 pass = getpass("Confirm password:"); 1444 if (0 != strcmp(orig, pass)) { 1445 fprintf(stderr, "Passwords do not match\n"); 1446 exit(1); 1447 } 1448 req.command = WDCC_SECURITY_SET_PASSWORD; 1449 } else if (strcmp(argv[0], "unlock") == 0) { 1450 req.command = WDCC_SECURITY_UNLOCK; 1451 } else if (strcmp(argv[0], "disable") == 0) { 1452 req.command = WDCC_SECURITY_DISABLE_PASSWORD; 1453 } else if (strcmp(argv[0], "erase") == 0) { 1454 struct atareq prepare; 1455 1456 inqbuf = getataparams(); 1457 1458 /* 1459 * XXX Any way to lock the device to make sure 1460 * this really is the command preceding the 1461 * SECURITY ERASE UNIT command? This would 1462 * probably have to be moved into the kernel to 1463 * do that. 1464 */ 1465 memset(&prepare, 0, sizeof(prepare)); 1466 prepare.command = WDCC_SECURITY_ERASE_PREPARE; 1467 prepare.timeout = 1000; 1468 ata_command(&prepare); 1469 1470 req.command = WDCC_SECURITY_ERASE_UNIT; 1471 1472 /* 1473 * Enable enhanced erase if it's supported. 1474 * 1475 * XXX should be a command-line option 1476 */ 1477 if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) { 1478 data[0] |= 0x2; 1479 req.timeout = (inqbuf->atap_eseu_time & 0xff) 1480 * 2 * 60 * 1000; 1481 } else { 1482 req.timeout = (inqbuf->atap_seu_time & 0xff) 1483 * 2 * 60 * 1000; 1484 } 1485 1486 /* 1487 * If the estimated time was 0xff (* 2 * 60 * 1488 * 1000 = 30600000), that means `>508 minutes'. 1489 * Estimate that we can handle 16 MB/sec, a 1490 * rate I just pulled out of my arse. 1491 */ 1492 if (req.timeout == 30600000) { 1493 uint64_t bytes, timeout; 1494 compute_capacity(inqbuf, &bytes, NULL, NULL); 1495 timeout = (bytes / (16 * 1024 * 1024)) * 1000; 1496 if (timeout > (uint64_t)INT_MAX) 1497 req.timeout = INT_MAX; 1498 else 1499 req.timeout = timeout; 1500 } 1501 1502 printf("Erasing may take up to %dh %dm %ds...\n", 1503 (req.timeout / 1000 / 60) / 60, 1504 (req.timeout / 1000 / 60) % 60, 1505 req.timeout % 60); 1506 } else { 1507 abort(); 1508 } 1509 1510 ata_command(&req); 1511 } else { 1512 usage(); 1513 } 1514 } 1515 1516 /* 1517 * bus_reset: 1518 * Reset an ATA bus (will reset all devices on the bus) 1519 */ 1520 static void 1521 bus_reset(int argc, char *argv[]) 1522 { 1523 int error; 1524 1525 /* no args */ 1526 if (argc != 0) 1527 usage(); 1528 1529 error = ioctl(fd, ATABUSIORESET, NULL); 1530 1531 if (error == -1) 1532 err(1, "ATABUSIORESET failed"); 1533 } 1534