diff --git a/plugins/sed/sed.c b/plugins/sed/sed.c index 695ed94169..b4ac0377c7 100644 --- a/plugins/sed/sed.c +++ b/plugins/sed/sed.c @@ -110,7 +110,7 @@ static int sed_opal_initialize(int argc, char **argv, struct command *cmd, return err; err = sedopal_cmd_initialize(dev->direct.fd); - if (err != 0) + if ((err != 0) && (err != -EOPNOTSUPP)) fprintf(stderr, "initialize: SED error - %s\n", sedopal_error_to_text(err)); @@ -130,7 +130,7 @@ static int sed_opal_revert(int argc, char **argv, struct command *cmd, return err; err = sedopal_cmd_revert(dev->direct.fd); - if (err != 0) + if ((err != 0) && (err != -EOPNOTSUPP)) fprintf(stderr, "revert: SED error - %s\n", sedopal_error_to_text(err)); @@ -150,7 +150,7 @@ static int sed_opal_lock(int argc, char **argv, struct command *cmd, return err; err = sedopal_cmd_lock(dev->direct.fd); - if (err != 0) + if ((err != 0) && (err != -EOPNOTSUPP)) fprintf(stderr, "lock: SED error - %s\n", sedopal_error_to_text(err)); @@ -170,7 +170,7 @@ static int sed_opal_unlock(int argc, char **argv, struct command *cmd, return err; err = sedopal_cmd_unlock(dev->direct.fd); - if (err != 0) + if ((err != 0) && (err != -EOPNOTSUPP)) fprintf(stderr, "unlock: SED error - %s\n", sedopal_error_to_text(err)); diff --git a/plugins/sed/sedopal_cmd.c b/plugins/sed/sedopal_cmd.c index 9d62d66114..8d931b9ab5 100644 --- a/plugins/sed/sedopal_cmd.c +++ b/plugins/sed/sedopal_cmd.c @@ -49,6 +49,11 @@ bool sedopal_discovery_verbose; */ bool sedopal_discovery_udev; +/* + * level 0 discovery buffer + */ +char level0_discovery_buf[4096]; + struct sedopal_feature_parser { uint32_t features; void *tper_desc; @@ -205,6 +210,15 @@ int sedopal_cmd_initialize(int fd) struct opal_lr_act lr_act = {}; struct opal_user_lr_setup lr_setup = {}; struct opal_new_pw new_pw = {}; + uint8_t locking_state; + + locking_state = sedopal_locking_state(fd); + + if (locking_state & OPAL_FEATURE_LOCKING_ENABLED) { + fprintf(stderr, + "Error: cannot initialize an initialized drive\n"); + return -EOPNOTSUPP; + } sedopal_ask_key = true; sedopal_ask_new_key = true; @@ -319,6 +333,15 @@ int sedopal_lock_unlock(int fd, int lock_state) { int rc; struct opal_lock_unlock opal_lu = {}; + uint8_t locking_state; + + locking_state = sedopal_locking_state(fd); + + if (!(locking_state & OPAL_FEATURE_LOCKING_ENABLED)) { + fprintf(stderr, + "Error: cannot lock/unlock an uninitialized drive\n"); + return -EOPNOTSUPP; + } rc = sedopal_set_key(&opal_lu.session.opal_key); if (rc != 0) @@ -433,6 +456,21 @@ int sedopal_cmd_revert(int fd) } else { #ifdef IOC_OPAL_REVERT_LSP struct opal_revert_lsp revert_lsp; + uint8_t locking_state; + + locking_state = sedopal_locking_state(fd); + + if (!(locking_state & OPAL_FEATURE_LOCKING_ENABLED)) { + fprintf(stderr, + "Error: can't revert an uninitialized drive\n"); + return -EOPNOTSUPP; + } + + if (locking_state & OPAL_FEATURE_LOCKED) { + fprintf(stderr, + "Error: cannot revert drive while locked\n"); + return -EOPNOTSUPP; + } rc = sedopal_set_key(&revert_lsp.key); if (rc != 0) @@ -958,22 +996,18 @@ void sedopal_print_features(struct sedopal_feature_parser *sfp) } /* - * Query a drive to determine if it's SED Opal capable and - * it's current locking status. + * Query a drive to retrieve it's level 0 features. */ -int sedopal_cmd_discover(int fd) +int sedopal_discover_device(int fd, struct level_0_discovery_features **feat, + struct level_0_discovery_features **feat_end) { #ifdef IOC_OPAL_DISCOVERY - int rc, feat_length; + int rc; struct opal_discovery discover; struct level_0_discovery_header *dh; - struct level_0_discovery_features *feat; - struct level_0_discovery_features *feat_end; - char buf[4096]; - struct sedopal_feature_parser sfp = {}; - discover.data = (uintptr_t)buf; - discover.size = sizeof(buf); + discover.data = (uintptr_t)level0_discovery_buf; + discover.size = sizeof(level0_discovery_buf); rc = ioctl(fd, IOC_OPAL_DISCOVERY, &discover); if (rc < 0) { @@ -987,10 +1021,33 @@ int sedopal_cmd_discover(int fd) * * TCG Opal Specification v2.0.2 section 3.1.1 */ - dh = (struct level_0_discovery_header *)buf; - feat = (struct level_0_discovery_features *)(dh + 1); - feat_end = (struct level_0_discovery_features *) - (buf + be32toh(dh->parameter_length)); + dh = (struct level_0_discovery_header *)level0_discovery_buf; + *feat = (struct level_0_discovery_features *)(dh + 1); + *feat_end = (struct level_0_discovery_features *) + (level0_discovery_buf + be32toh(dh->parameter_length)); + + return 0 + ; +#else /* IOC_OPAL_DISCOVERY */ + fprintf(stderr, "ERROR : NVMe device discovery is not supported\n"); + return -EOPNOTSUPP; +#endif +} + +/* + * Query a drive to determine if it's SED Opal capable and + * it's current locking status. + */ +int sedopal_cmd_discover(int fd) +{ + int rc, feat_length; + struct level_0_discovery_features *feat; + struct level_0_discovery_features *feat_end; + struct sedopal_feature_parser sfp = {}; + + rc = sedopal_discover_device(fd, &feat, &feat_end); + if (rc != 0) + return rc; /* * iterate through all the features that were returned @@ -1016,8 +1073,37 @@ int sedopal_cmd_discover(int fd) return rc; -#else /* IOC_OPAL_DISCOVERY */ - fprintf(stderr, "ERROR : NVMe device discovery is not supported\n"); - return -EOPNOTSUPP; -#endif +} + +/* + * Query a drive to determine its locking state + */ +int sedopal_locking_state(int fd) +{ + int rc, feat_length; + struct level_0_discovery_features *feat; + struct level_0_discovery_features *feat_end; + + rc = sedopal_discover_device(fd, &feat, &feat_end); + if (rc != 0) + return rc; + + /* + * iterate through all the features that were returned + */ + while (feat < feat_end) { + uint16_t code = be16toh(feat->code); + + if (code == OPAL_FEATURE_CODE_LOCKING) { + struct locking_desc *ld = (struct locking_desc *) (feat + 1); + + return ld->features; + } + + feat_length = feat->length + 4 /* hdr */; + feat = (struct level_0_discovery_features *) + ((char *)feat + feat_length); + } + + return 0; } diff --git a/plugins/sed/sedopal_cmd.h b/plugins/sed/sedopal_cmd.h index 2efa6bce76..32d1cfb087 100644 --- a/plugins/sed/sedopal_cmd.h +++ b/plugins/sed/sedopal_cmd.h @@ -54,5 +54,6 @@ int sedopal_cmd_discover(int fd); int sedopal_open_nvme_device(char *device); int sedopal_lock_unlock(int fd, int lock_state); const char *sedopal_error_to_text(int code); +int sedopal_locking_state(int fd); #endif /* _SED_OPAL_CMD_H */