Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sbin/atactl Add some ATA SECURITY commands to atactl(8).
details: https://anonhg.NetBSD.org/src/rev/0d8b4b94afde
branches: trunk
changeset: 783816:0d8b4b94afde
user: riastradh <riastradh%NetBSD.org@localhost>
date: Wed Jan 09 21:58:23 2013 +0000
description:
Add some ATA SECURITY commands to atactl(8).
diffstat:
sbin/atactl/atactl.8 | 71 +++++++++++++++++-
sbin/atactl/atactl.c | 196 +++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 225 insertions(+), 42 deletions(-)
diffs (truncated from 371 to 300 lines):
diff -r 5e107895d95c -r 0d8b4b94afde sbin/atactl/atactl.8
--- a/sbin/atactl/atactl.8 Wed Jan 09 18:19:09 2013 +0000
+++ b/sbin/atactl/atactl.8 Wed Jan 09 21:58:23 2013 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: atactl.8,v 1.23 2008/04/30 13:10:52 martin Exp $
+.\" $NetBSD: atactl.8,v 1.24 2013/01/09 21:58:23 riastradh Exp $
.\"
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd November 18, 2007
+.Dd January 9, 2013
.Dt ATACTL 8
.Os
.Sh NAME
@@ -160,7 +160,7 @@
.It Ar selftest-log
Prints the self-test log.
.El
-.It Cm security Bq Ar freeze | status
+.It Cm security Bq Ar status | freeze | setpass | unlock | disable | erase
Controls
.Dq security
(password protection) features of modern ATA drives.
@@ -175,11 +175,46 @@
.Dq freeze
command early in the boot process.
.Bl -tag -width freezeXX
+.It Ar status
+displays the drive's security status
.It Ar freeze
freezes the drive's security status
-.It Ar status
-displays the drive's security status
+.It Ar setpass Bq user | master
+sets the drive's user or master password
+.It Ar unlock Bq user | master
+unlocks a password-protected drive
+.It Ar disable Bq user | master
+disables password protection
+.It Ar erase Bq user | master
+erases the device and clears security state, using enhanced erasure if
+the drive supports it; may take a long time to run
.El
+.Pp
+Note that to erase a drive, it must have a password set and be
+unfrozen.
+If you can't persuade your firmware to leave the drive unfrozen on
+boot, but it is a SATA drive, say
+.Pa wd2
+at
+.Pa atabus3 ,
+that you can safely physically disconnect and reconnect, then you may
+be able to use SATA hot-plug to work around this: first run
+.Bd -literal -offset indent
+# drvctl -d wd2
+.Ed
+.Pp
+Then physically disconnect and reconnect the drive, and run
+.Bd -literal -offset indent
+# drvctl -r -a ata_hl atabus3
+.Ed
+.Pp
+After this, check that the security status does not list
+.Dq frozen :
+.Bd -literal -offset indent
+# atactl wd2 security status
+ supported
+#
+.Ed
.El
.Sh BUS COMMANDS
The following commands may be used on IDE and ATA busses.
@@ -190,10 +225,29 @@
This will reset all ATA devices present on the bus.
Any ATAPI device with pending commands will also be reset.
.El
+.Sh EXAMPLES
+To erase
+.Pa wd2
+which is currently unfrozen and has no password set:
+.Bd -literal -offset indent
+# atactl wd2 security status
+ supported
+# atactl wd2 security setpass user
+Password:
+Confirm password:
+# atactl wd2 security status
+ supported
+ enabled
+# atactl wd2 security erase user
+Password:
+Erasing may take up to 0h 2m 0s...
+#
+.Ed
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr wd 4 ,
.Xr dkctl 8 ,
+.Xr drvctl 8 ,
.Xr scsictl 8
.Sh HISTORY
The
@@ -211,3 +265,10 @@
The output from the
.Cm identify
command is rather ugly.
+.Pp
+Support for master passwords is not implemented.
+.Pp
+The
+.Nx
+kernel behaves poorly with drives that have passwords set and are
+locked.
diff -r 5e107895d95c -r 0d8b4b94afde sbin/atactl/atactl.c
--- a/sbin/atactl/atactl.c Wed Jan 09 18:19:09 2013 +0000
+++ b/sbin/atactl/atactl.c Wed Jan 09 21:58:23 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atactl.c,v 1.67 2012/10/19 17:09:07 drochner Exp $ */
+/* $NetBSD: atactl.c,v 1.68 2013/01/09 21:58:23 riastradh Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: atactl.c,v 1.67 2012/10/19 17:09:07 drochner Exp $");
+__RCSID("$NetBSD: atactl.c,v 1.68 2013/01/09 21:58:23 riastradh Exp $");
#endif
@@ -44,6 +44,7 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -144,7 +145,9 @@
{ "smart",
"enable|disable|status|offline #|error-log|selftest-log",
device_smart },
- { "security", "freeze|status", device_security },
+ { "security",
+ "status|freeze|[setpass|unlock|disable|erase] [user|master]",
+ device_security },
{ NULL, NULL, NULL },
};
@@ -851,6 +854,49 @@
buf[j] = '\0';
}
+static void
+compute_capacity(const struct ataparams *inqbuf, uint64_t *capacityp,
+ uint64_t *sectorsp, uint32_t *secsizep)
+{
+ uint64_t capacity;
+ uint64_t sectors;
+ uint32_t secsize;
+
+ if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&
+ inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {
+ sectors =
+ ((uint64_t)inqbuf->atap_max_lba[3] << 48) |
+ ((uint64_t)inqbuf->atap_max_lba[2] << 32) |
+ ((uint64_t)inqbuf->atap_max_lba[1] << 16) |
+ ((uint64_t)inqbuf->atap_max_lba[0] << 0);
+ } else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {
+ sectors = (inqbuf->atap_capacity[1] << 16) |
+ inqbuf->atap_capacity[0];
+ } else {
+ sectors = inqbuf->atap_cylinders *
+ inqbuf->atap_heads * inqbuf->atap_sectors;
+ }
+
+ secsize = 512;
+
+ if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
+ if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {
+ secsize = 2 * /* words to bytes */
+ (inqbuf->atap_lls_secsz[1] << 16 |
+ inqbuf->atap_lls_secsz[0] << 0);
+ }
+ }
+
+ capacity = sectors * secsize;
+
+ if (capacityp)
+ *capacityp = capacity;
+ if (sectorsp)
+ *sectorsp = sectors;
+ if (secsizep)
+ *secsizep = secsize;
+}
+
/*
* DEVICE COMMANDS
*/
@@ -934,32 +980,7 @@
"ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
"removable");
- if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&
- inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {
- sectors =
- ((uint64_t)inqbuf->atap_max_lba[3] << 48) |
- ((uint64_t)inqbuf->atap_max_lba[2] << 32) |
- ((uint64_t)inqbuf->atap_max_lba[1] << 16) |
- ((uint64_t)inqbuf->atap_max_lba[0] << 0);
- } else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {
- sectors = (inqbuf->atap_capacity[1] << 16) |
- inqbuf->atap_capacity[0];
- } else {
- sectors = inqbuf->atap_cylinders *
- inqbuf->atap_heads * inqbuf->atap_sectors;
- }
-
- secsize = 512;
-
- if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
- if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {
- secsize = 2 * /* words to bytes */
- (inqbuf->atap_lls_secsz[1] << 16 |
- inqbuf->atap_lls_secsz[0] << 0);
- }
- }
-
- capacity = sectors * secsize;
+ compute_capacity(inqbuf, &capacity, §ors, &secsize);
humanize_number(hnum, sizeof(hnum), capacity, "bytes",
HN_AUTOSCALE, HN_DIVISOR_1000);
@@ -1368,23 +1389,124 @@
{
struct atareq req;
const struct ataparams *inqbuf;
+ unsigned char data[DEV_BSIZE];
+ char *pass;
/* need subcommand */
if (argc < 1)
usage();
- if (strcmp(argv[0], "freeze") == 0) {
- memset(&req, 0, sizeof(req));
+ memset(&req, 0, sizeof(req));
+ if (strcmp(argv[0], "status") == 0) {
+ inqbuf = getataparams();
+ print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
+ } else if (strcmp(argv[0], "freeze") == 0) {
req.command = WDCC_SECURITY_FREEZE;
req.timeout = 1000;
ata_command(&req);
- } else if (strcmp(argv[0], "status") == 0) {
- inqbuf = getataparams();
- print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
- } else
+ } else if ((strcmp(argv[0], "setpass") == 0) ||
+ (strcmp(argv[0], "unlock") == 0) ||
+ (strcmp(argv[0], "disable") == 0) ||
+ (strcmp(argv[0], "erase") == 0)) {
+ if (argc != 2)
+ usage();
+ if (strcmp(argv[1], "user") != 0) {
+ if (strcmp(argv[1], "master") == 0) {
+ fprintf(stderr,
+ "Master passwords not supported\n");
+ exit(1);
+ } else {
+ usage();
+ }
+ }
+
+ pass = getpass("Password:");
+ if (strlen(pass) > 32) {
+ fprintf(stderr, "Password must be <=32 characters\n");
+ exit(1);
+ }
+
+ req.flags |= ATACMD_WRITE;
+ req.timeout = 1000;
+ req.databuf = data;
+ req.datalen = sizeof(data);
+ memset(data, 0, sizeof(data));
+ strlcpy((void *)&data[2], pass, 32 + 1);
+
+ if (strcmp(argv[0], "setpass") == 0) {
+ char orig[32 + 1];
+ strlcpy(orig, pass, 32 + 1);
+ pass = getpass("Confirm password:");
+ if (0 != strcmp(orig, pass)) {
+ fprintf(stderr, "Passwords do not match\n");
+ exit(1);
+ }
Home |
Main Index |
Thread Index |
Old Index