|
|
|
@@ -142,6 +142,10 @@ static u32 handle[] = {
|
|
|
|
|
|
|
|
|
|
static unsigned long dimm_fail_cmd_flags[ARRAY_SIZE(handle)];
|
|
|
|
|
static int dimm_fail_cmd_code[ARRAY_SIZE(handle)];
|
|
|
|
|
struct nfit_test_sec {
|
|
|
|
|
u8 state;
|
|
|
|
|
u8 passphrase[32];
|
|
|
|
|
} dimm_sec_info[NUM_DCR];
|
|
|
|
|
|
|
|
|
|
static const struct nd_intel_smart smart_def = {
|
|
|
|
|
.flags = ND_INTEL_SMART_HEALTH_VALID
|
|
|
|
@@ -933,6 +937,138 @@ static int override_return_code(int dimm, unsigned int func, int rc)
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nd_intel_test_cmd_security_status(struct nfit_test *t,
|
|
|
|
|
struct nd_intel_get_security_state *nd_cmd,
|
|
|
|
|
unsigned int buf_len, int dimm)
|
|
|
|
|
{
|
|
|
|
|
struct device *dev = &t->pdev.dev;
|
|
|
|
|
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
|
|
|
|
|
|
|
|
|
|
nd_cmd->status = 0;
|
|
|
|
|
nd_cmd->state = sec->state;
|
|
|
|
|
dev_dbg(dev, "security state (%#x) returned\n", nd_cmd->state);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nd_intel_test_cmd_unlock_unit(struct nfit_test *t,
|
|
|
|
|
struct nd_intel_unlock_unit *nd_cmd,
|
|
|
|
|
unsigned int buf_len, int dimm)
|
|
|
|
|
{
|
|
|
|
|
struct device *dev = &t->pdev.dev;
|
|
|
|
|
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
|
|
|
|
|
|
|
|
|
|
if (!(sec->state & ND_INTEL_SEC_STATE_LOCKED) ||
|
|
|
|
|
(sec->state & ND_INTEL_SEC_STATE_FROZEN)) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
|
|
|
|
|
dev_dbg(dev, "unlock unit: invalid state: %#x\n",
|
|
|
|
|
sec->state);
|
|
|
|
|
} else if (memcmp(nd_cmd->passphrase, sec->passphrase,
|
|
|
|
|
ND_INTEL_PASSPHRASE_SIZE) != 0) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
|
|
|
|
|
dev_dbg(dev, "unlock unit: invalid passphrase\n");
|
|
|
|
|
} else {
|
|
|
|
|
nd_cmd->status = 0;
|
|
|
|
|
sec->state = ND_INTEL_SEC_STATE_ENABLED;
|
|
|
|
|
dev_dbg(dev, "Unit unlocked\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev_dbg(dev, "unlocking status returned: %#x\n", nd_cmd->status);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nd_intel_test_cmd_set_pass(struct nfit_test *t,
|
|
|
|
|
struct nd_intel_set_passphrase *nd_cmd,
|
|
|
|
|
unsigned int buf_len, int dimm)
|
|
|
|
|
{
|
|
|
|
|
struct device *dev = &t->pdev.dev;
|
|
|
|
|
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
|
|
|
|
|
|
|
|
|
|
if (sec->state & ND_INTEL_SEC_STATE_FROZEN) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
|
|
|
|
|
dev_dbg(dev, "set passphrase: wrong security state\n");
|
|
|
|
|
} else if (memcmp(nd_cmd->old_pass, sec->passphrase,
|
|
|
|
|
ND_INTEL_PASSPHRASE_SIZE) != 0) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
|
|
|
|
|
dev_dbg(dev, "set passphrase: wrong passphrase\n");
|
|
|
|
|
} else {
|
|
|
|
|
memcpy(sec->passphrase, nd_cmd->new_pass,
|
|
|
|
|
ND_INTEL_PASSPHRASE_SIZE);
|
|
|
|
|
sec->state |= ND_INTEL_SEC_STATE_ENABLED;
|
|
|
|
|
nd_cmd->status = 0;
|
|
|
|
|
dev_dbg(dev, "passphrase updated\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nd_intel_test_cmd_freeze_lock(struct nfit_test *t,
|
|
|
|
|
struct nd_intel_freeze_lock *nd_cmd,
|
|
|
|
|
unsigned int buf_len, int dimm)
|
|
|
|
|
{
|
|
|
|
|
struct device *dev = &t->pdev.dev;
|
|
|
|
|
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
|
|
|
|
|
|
|
|
|
|
if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED)) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
|
|
|
|
|
dev_dbg(dev, "freeze lock: wrong security state\n");
|
|
|
|
|
} else {
|
|
|
|
|
sec->state |= ND_INTEL_SEC_STATE_FROZEN;
|
|
|
|
|
nd_cmd->status = 0;
|
|
|
|
|
dev_dbg(dev, "security frozen\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nd_intel_test_cmd_disable_pass(struct nfit_test *t,
|
|
|
|
|
struct nd_intel_disable_passphrase *nd_cmd,
|
|
|
|
|
unsigned int buf_len, int dimm)
|
|
|
|
|
{
|
|
|
|
|
struct device *dev = &t->pdev.dev;
|
|
|
|
|
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
|
|
|
|
|
|
|
|
|
|
if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) ||
|
|
|
|
|
(sec->state & ND_INTEL_SEC_STATE_FROZEN)) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
|
|
|
|
|
dev_dbg(dev, "disable passphrase: wrong security state\n");
|
|
|
|
|
} else if (memcmp(nd_cmd->passphrase, sec->passphrase,
|
|
|
|
|
ND_INTEL_PASSPHRASE_SIZE) != 0) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
|
|
|
|
|
dev_dbg(dev, "disable passphrase: wrong passphrase\n");
|
|
|
|
|
} else {
|
|
|
|
|
memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE);
|
|
|
|
|
sec->state = 0;
|
|
|
|
|
dev_dbg(dev, "disable passphrase: done\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nd_intel_test_cmd_secure_erase(struct nfit_test *t,
|
|
|
|
|
struct nd_intel_secure_erase *nd_cmd,
|
|
|
|
|
unsigned int buf_len, int dimm)
|
|
|
|
|
{
|
|
|
|
|
struct device *dev = &t->pdev.dev;
|
|
|
|
|
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
|
|
|
|
|
|
|
|
|
|
if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) ||
|
|
|
|
|
(sec->state & ND_INTEL_SEC_STATE_FROZEN)) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
|
|
|
|
|
dev_dbg(dev, "secure erase: wrong security state\n");
|
|
|
|
|
} else if (memcmp(nd_cmd->passphrase, sec->passphrase,
|
|
|
|
|
ND_INTEL_PASSPHRASE_SIZE) != 0) {
|
|
|
|
|
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
|
|
|
|
|
dev_dbg(dev, "secure erase: wrong passphrase\n");
|
|
|
|
|
} else {
|
|
|
|
|
memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE);
|
|
|
|
|
sec->state = 0;
|
|
|
|
|
dev_dbg(dev, "secure erase: done\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
@@ -980,6 +1116,30 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
|
|
|
|
return i;
|
|
|
|
|
|
|
|
|
|
switch (func) {
|
|
|
|
|
case NVDIMM_INTEL_GET_SECURITY_STATE:
|
|
|
|
|
rc = nd_intel_test_cmd_security_status(t,
|
|
|
|
|
buf, buf_len, i);
|
|
|
|
|
break;
|
|
|
|
|
case NVDIMM_INTEL_UNLOCK_UNIT:
|
|
|
|
|
rc = nd_intel_test_cmd_unlock_unit(t,
|
|
|
|
|
buf, buf_len, i);
|
|
|
|
|
break;
|
|
|
|
|
case NVDIMM_INTEL_SET_PASSPHRASE:
|
|
|
|
|
rc = nd_intel_test_cmd_set_pass(t,
|
|
|
|
|
buf, buf_len, i);
|
|
|
|
|
break;
|
|
|
|
|
case NVDIMM_INTEL_DISABLE_PASSPHRASE:
|
|
|
|
|
rc = nd_intel_test_cmd_disable_pass(t,
|
|
|
|
|
buf, buf_len, i);
|
|
|
|
|
break;
|
|
|
|
|
case NVDIMM_INTEL_FREEZE_LOCK:
|
|
|
|
|
rc = nd_intel_test_cmd_freeze_lock(t,
|
|
|
|
|
buf, buf_len, i);
|
|
|
|
|
break;
|
|
|
|
|
case NVDIMM_INTEL_SECURE_ERASE:
|
|
|
|
|
rc = nd_intel_test_cmd_secure_erase(t,
|
|
|
|
|
buf, buf_len, i);
|
|
|
|
|
break;
|
|
|
|
|
case ND_INTEL_ENABLE_LSS_STATUS:
|
|
|
|
|
rc = nd_intel_test_cmd_set_lss_status(t,
|
|
|
|
|
buf, buf_len);
|
|
|
|
@@ -1313,10 +1473,22 @@ static ssize_t fail_cmd_code_store(struct device *dev, struct device_attribute *
|
|
|
|
|
}
|
|
|
|
|
static DEVICE_ATTR_RW(fail_cmd_code);
|
|
|
|
|
|
|
|
|
|
static ssize_t lock_dimm_store(struct device *dev,
|
|
|
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
|
|
|
{
|
|
|
|
|
int dimm = dimm_name_to_id(dev);
|
|
|
|
|
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
|
|
|
|
|
|
|
|
|
|
sec->state = ND_INTEL_SEC_STATE_ENABLED | ND_INTEL_SEC_STATE_LOCKED;
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
static DEVICE_ATTR_WO(lock_dimm);
|
|
|
|
|
|
|
|
|
|
static struct attribute *nfit_test_dimm_attributes[] = {
|
|
|
|
|
&dev_attr_fail_cmd.attr,
|
|
|
|
|
&dev_attr_fail_cmd_code.attr,
|
|
|
|
|
&dev_attr_handle.attr,
|
|
|
|
|
&dev_attr_lock_dimm.attr,
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -2195,6 +2367,14 @@ static void nfit_test0_setup(struct nfit_test *t)
|
|
|
|
|
set_bit(ND_INTEL_FW_FINISH_UPDATE, &acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(ND_INTEL_FW_FINISH_QUERY, &acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(ND_INTEL_ENABLE_LSS_STATUS, &acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(NVDIMM_INTEL_GET_SECURITY_STATE,
|
|
|
|
|
&acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(NVDIMM_INTEL_SET_PASSPHRASE, &acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE,
|
|
|
|
|
&acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(NVDIMM_INTEL_UNLOCK_UNIT, &acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(NVDIMM_INTEL_FREEZE_LOCK, &acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
set_bit(NVDIMM_INTEL_SECURE_ERASE, &acpi_desc->dimm_cmd_force_en);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void nfit_test1_setup(struct nfit_test *t)
|
|
|
|
|