Message ID | 20190212054236.5221-1-alex.hung@canonical.com |
---|---|
State | Accepted |
Headers | show |
Series | [V2] acpi/method: add tests for NVDIMM control methods for ACPI 6.3 | expand |
On 12/02/2019 05:42, Alex Hung wrote: > Signed-off-by: Alex Hung <alex.hung@canonical.com> > --- > src/acpi/method/method.c | 286 ++++++++++++++++++++++++ > src/lib/include/fwts_acpi_object_eval.h | 40 ++++ > 2 files changed, 326 insertions(+) > > diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c > index 654112d9..48a5c039 100644 > --- a/src/acpi/method/method.c > +++ b/src/acpi/method/method.c > @@ -138,6 +138,11 @@ > * _MSG Y > * _MSM N > * _MTL Y > + * _NBS Y > + * _NCH Y > + * _NIC Y > + * _NIH Y > + * _NIG Y > * _NTT Y > * _OFF Y > * _ON_ Y > @@ -3574,6 +3579,280 @@ static int method_test_TIV(fwts_framework *fw) > "_TIV", arg, 1, fwts_method_test_integer_return, NULL); > } > > +/* > + * Section 9.20 NVDIMM Devices > + */ > +static void check_nvdimm_status( > + fwts_framework *fw, > + char *name, > + uint16_t status, > + bool *failed) > +{ > + if (status > 6) { > + *failed = true; > + fwts_failed(fw, LOG_LEVEL_MEDIUM, > + "MethodBadStatus", > + "%s: Expected Status to be 0..6, got %" PRIx16, > + name, status); > + } > +} > + > +static void check_nvdimm_extended_status( > + fwts_framework *fw, > + char *name, > + uint16_t ext_status, > + uint16_t expected, > + bool *failed) > +{ > + if (ext_status != expected) { > + *failed = true; > + fwts_failed(fw, LOG_LEVEL_MEDIUM, > + "MethodBadExtendedStatus", > + "%s: Expected Extended Status to be %" PRIx16 > + ", got %" PRIx16, name, expected, ext_status); > + } > +} > + > +static void method_test_NBS_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nbs_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NBSBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nbs_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NBS", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 1, 15, &failed); > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NBS(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NBS", NULL, 0, method_test_NBS_return, NULL); > +} > + > +static void method_test_NCH_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nch_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NCHBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nch_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Validation Flags", ret->extended_status, sizeof(uint16_t), 2, 15, &failed); > + > + /* Health Status Flags [2..7], [11.15], [19..31] are reserved */ > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 2, 7, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 11, 15, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 19, 31, &failed); > + > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Attributes", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NCH(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NCH", NULL, 0, method_test_NCH_return, NULL); > +} > + > +static void method_test_NIC_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nic_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NICBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nic_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + > + /* Health Error Injection Capabilities [2..7], [11.15], [19..31] are reserved */ > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 2, 7, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 11, 15, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 19, 31, &failed); > + > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Status Attributes Capabilities", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NIC(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NIC", NULL, 0, method_test_NIC_return, NULL); > +} > + > +static void method_test_NIH_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nih_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NIHBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nih_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 1, &failed); > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NIH(fwts_framework *fw) > +{ > + ACPI_OBJECT arg0; > + char data[64]; > + int result; > + int i, j; > + > + memset(data, 0, sizeof(data)); > + arg0.Type = ACPI_TYPE_BUFFER; > + arg0.Buffer.Length = 64; > + arg0.Buffer.Pointer = (void *)data; > + > + /* not permanent (j = 0) and permanent (j = 1) errors */ > + for (j = 0; j <= 1; j++) { > + /* inject (i = 1) and clear (i = 2) errors */ > + for (i = 1; i <= 2; i++) { > + data[0] = i; > + data[4] = 3; > + data[5] = 7; > + data[6] = 7; > + data[8] = j; > + > + result = method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NIH", &arg0, 1, method_test_NIH_return, NULL); > + > + if (result != FWTS_OK) > + return result; > + } > + } > + > + return FWTS_OK; > +} > + > +static void method_test_NIG_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nig_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NIGBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nig_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 2, 15, &failed); > + > + /* Injected Health Status Errors [2..7], [11.15], [19..31] are reserved */ > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 2, 7, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 11, 15, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 19, 31, &failed); > + > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Health Status Attributes of Injected Errors", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NIG(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NIG", NULL, 0, method_test_NIG_return, NULL); > +} > > /* > * Section 10.1 Smart Battery > @@ -5896,6 +6175,13 @@ static fwts_framework_minor_test method_tests[] = { > { method_test_TIP, "Test _TIP (Expired Timer Wake Policy)." }, > { method_test_TIV, "Test _TIV (Timer Values)." }, > > + /* Section 9.20 NVDIMM Devices */ > + { method_test_NBS, "Test _NBS (NVDIMM Boot Status)." }, > + { method_test_NCH, "Test _NCH (NVDIMM Current Health Information)." }, > + { method_test_NIC, "Test _NIC (NVDIMM Health Error Injection Capabilities)." }, > + { method_test_NIH, "Test _NIH (NVDIMM Inject/Clear Health Errors)." }, > + { method_test_NIG, "Test _NIG (NVDIMM Inject Health Error Status)." }, > + > /* Section 10.1 Smart Battery */ > > { method_test_SBS, "Test _SBS (Smart Battery Subsystem)." }, > diff --git a/src/lib/include/fwts_acpi_object_eval.h b/src/lib/include/fwts_acpi_object_eval.h > index 4a7c5ed9..565af728 100644 > --- a/src/lib/include/fwts_acpi_object_eval.h > +++ b/src/lib/include/fwts_acpi_object_eval.h > @@ -66,6 +66,46 @@ typedef struct { > uint8_t pad2[3]; > } __attribute__ ((packed)) fwts_acpi_time_buffer; > > +/* Returns for NVDIMM control methods */ > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint16_t validation_flags; > + uint32_t health_status_flags; > + uint32_t health_status_attributes; > + uint8_t reserved[50]; > +} __attribute__ ((packed)) nch_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint16_t validation_flags; > + uint32_t data_loss_count; > + uint8_t reserved[54]; > +} __attribute__ ((packed)) nbs_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint32_t health_error_injection; > + uint32_t health_status_attributes; > + uint8_t reserved[52]; > +} __attribute__ ((packed)) nic_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > +} __attribute__ ((packed)) nih_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint16_t validation_flags; > + uint32_t health_status_errors; > + uint32_t health_status_attributes; > + uint8_t reserved[50]; > +} __attribute__ ((packed)) nig_return_t; > + > #define fwts_method_check_type(fw, name, buf, type) \ > fwts_method_check_type__(fw, name, buf, type, #type) > > Thanks Alex Acked-by: Colin Ian King <colin.king@canonical.com>
On 2/12/19 1:42 PM, Alex Hung wrote: > Signed-off-by: Alex Hung <alex.hung@canonical.com> > --- > src/acpi/method/method.c | 286 ++++++++++++++++++++++++ > src/lib/include/fwts_acpi_object_eval.h | 40 ++++ > 2 files changed, 326 insertions(+) > > diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c > index 654112d9..48a5c039 100644 > --- a/src/acpi/method/method.c > +++ b/src/acpi/method/method.c > @@ -138,6 +138,11 @@ > * _MSG Y > * _MSM N > * _MTL Y > + * _NBS Y > + * _NCH Y > + * _NIC Y > + * _NIH Y > + * _NIG Y > * _NTT Y > * _OFF Y > * _ON_ Y > @@ -3574,6 +3579,280 @@ static int method_test_TIV(fwts_framework *fw) > "_TIV", arg, 1, fwts_method_test_integer_return, NULL); > } > > +/* > + * Section 9.20 NVDIMM Devices > + */ > +static void check_nvdimm_status( > + fwts_framework *fw, > + char *name, > + uint16_t status, > + bool *failed) > +{ > + if (status > 6) { > + *failed = true; > + fwts_failed(fw, LOG_LEVEL_MEDIUM, > + "MethodBadStatus", > + "%s: Expected Status to be 0..6, got %" PRIx16, > + name, status); > + } > +} > + > +static void check_nvdimm_extended_status( > + fwts_framework *fw, > + char *name, > + uint16_t ext_status, > + uint16_t expected, > + bool *failed) > +{ > + if (ext_status != expected) { > + *failed = true; > + fwts_failed(fw, LOG_LEVEL_MEDIUM, > + "MethodBadExtendedStatus", > + "%s: Expected Extended Status to be %" PRIx16 > + ", got %" PRIx16, name, expected, ext_status); > + } > +} > + > +static void method_test_NBS_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nbs_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NBSBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nbs_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NBS", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 1, 15, &failed); Should check the rest return bytes are reserved? > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NBS(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NBS", NULL, 0, method_test_NBS_return, NULL); > +} > + > +static void method_test_NCH_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nch_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NCHBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nch_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Validation Flags", ret->extended_status, sizeof(uint16_t), 2, 15, &failed); > + > + /* Health Status Flags [2..7], [11.15], [19..31] are reserved */ > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 2, 7, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 11, 15, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 19, 31, &failed); > + > + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Attributes", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); > + Should check the rest return bytes are reserved? > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NCH(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NCH", NULL, 0, method_test_NCH_return, NULL); > +} > + > +static void method_test_NIC_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nic_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NICBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nic_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + > + /* Health Error Injection Capabilities [2..7], [11.15], [19..31] are reserved */ > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 2, 7, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 11, 15, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 19, 31, &failed); > + > + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Status Attributes Capabilities", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); same here. > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NIC(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NIC", NULL, 0, method_test_NIC_return, NULL); > +} > + > +static void method_test_NIH_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nih_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NIHBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nih_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 1, &failed); > + > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NIH(fwts_framework *fw) > +{ > + ACPI_OBJECT arg0; > + char data[64]; > + int result; > + int i, j; > + > + memset(data, 0, sizeof(data)); > + arg0.Type = ACPI_TYPE_BUFFER; > + arg0.Buffer.Length = 64; > + arg0.Buffer.Pointer = (void *)data; > + > + /* not permanent (j = 0) and permanent (j = 1) errors */ > + for (j = 0; j <= 1; j++) { > + /* inject (i = 1) and clear (i = 2) errors */ > + for (i = 1; i <= 2; i++) { > + data[0] = i; > + data[4] = 3; > + data[5] = 7; > + data[6] = 7; > + data[8] = j; > + > + result = method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NIH", &arg0, 1, method_test_NIH_return, NULL); > + > + if (result != FWTS_OK) > + return result; > + } > + } > + > + return FWTS_OK; > +} > + > +static void method_test_NIG_return( > + fwts_framework *fw, > + char *name, > + ACPI_BUFFER *buf, > + ACPI_OBJECT *obj, > + void *private) > +{ > + bool failed = false; > + nig_return_t *ret; > + > + FWTS_UNUSED(private); > + > + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) > + return; > + > + if (obj->Buffer.Length != 64) { > + failed = true; > + fwts_failed(fw, LOG_LEVEL_CRITICAL, > + "Method_NIGBadBufferSize", > + "%s should return a buffer of 64 bytes, but " > + "instead just returned %" PRIu32, > + name, obj->Buffer.Length); > + } > + > + ret = (nig_return_t *) obj->Buffer.Pointer; > + check_nvdimm_status(fw, name, ret->status, &failed); > + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 2, 15, &failed); > + > + /* Injected Health Status Errors [2..7], [11.15], [19..31] are reserved */ > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 2, 7, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 11, 15, &failed); > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 19, 31, &failed); > + > + fwts_acpi_reserved_bits_check(fw, "_NIG", "Health Status Attributes of Injected Errors", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); > + same here. > + if (!failed) > + fwts_method_passed_sane(fw, name, "buffer"); > +} > + > +static int method_test_NIG(fwts_framework *fw) > +{ > + return method_evaluate_method(fw, METHOD_OPTIONAL, > + "_NIG", NULL, 0, method_test_NIG_return, NULL); > +} > > /* > * Section 10.1 Smart Battery > @@ -5896,6 +6175,13 @@ static fwts_framework_minor_test method_tests[] = { > { method_test_TIP, "Test _TIP (Expired Timer Wake Policy)." }, > { method_test_TIV, "Test _TIV (Timer Values)." }, > > + /* Section 9.20 NVDIMM Devices */ > + { method_test_NBS, "Test _NBS (NVDIMM Boot Status)." }, > + { method_test_NCH, "Test _NCH (NVDIMM Current Health Information)." }, > + { method_test_NIC, "Test _NIC (NVDIMM Health Error Injection Capabilities)." }, > + { method_test_NIH, "Test _NIH (NVDIMM Inject/Clear Health Errors)." }, > + { method_test_NIG, "Test _NIG (NVDIMM Inject Health Error Status)." }, > + > /* Section 10.1 Smart Battery */ > > { method_test_SBS, "Test _SBS (Smart Battery Subsystem)." }, > diff --git a/src/lib/include/fwts_acpi_object_eval.h b/src/lib/include/fwts_acpi_object_eval.h > index 4a7c5ed9..565af728 100644 > --- a/src/lib/include/fwts_acpi_object_eval.h > +++ b/src/lib/include/fwts_acpi_object_eval.h > @@ -66,6 +66,46 @@ typedef struct { > uint8_t pad2[3]; > } __attribute__ ((packed)) fwts_acpi_time_buffer; > > +/* Returns for NVDIMM control methods */ > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint16_t validation_flags; > + uint32_t health_status_flags; > + uint32_t health_status_attributes; > + uint8_t reserved[50]; > +} __attribute__ ((packed)) nch_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint16_t validation_flags; > + uint32_t data_loss_count; > + uint8_t reserved[54]; > +} __attribute__ ((packed)) nbs_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint32_t health_error_injection; > + uint32_t health_status_attributes; > + uint8_t reserved[52]; > +} __attribute__ ((packed)) nic_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > +} __attribute__ ((packed)) nih_return_t; > + > +typedef struct { > + uint16_t status; > + uint16_t extended_status; > + uint16_t validation_flags; > + uint32_t health_status_errors; > + uint32_t health_status_attributes; > + uint8_t reserved[50]; > +} __attribute__ ((packed)) nig_return_t; > + > #define fwts_method_check_type(fw, name, buf, type) \ > fwts_method_check_type__(fw, name, buf, type, #type) >
On 2/18/19 6:09 PM, ivanhu wrote: > On 2/12/19 1:42 PM, Alex Hung wrote: >> Signed-off-by: Alex Hung <alex.hung@canonical.com> >> --- >> src/acpi/method/method.c | 286 ++++++++++++++++++++++++ >> src/lib/include/fwts_acpi_object_eval.h | 40 ++++ >> 2 files changed, 326 insertions(+) >> >> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c >> index 654112d9..48a5c039 100644 >> --- a/src/acpi/method/method.c >> +++ b/src/acpi/method/method.c >> @@ -138,6 +138,11 @@ >> * _MSG Y >> * _MSM N >> * _MTL Y >> + * _NBS Y >> + * _NCH Y >> + * _NIC Y >> + * _NIH Y >> + * _NIG Y >> * _NTT Y >> * _OFF Y >> * _ON_ Y >> @@ -3574,6 +3579,280 @@ static int method_test_TIV(fwts_framework *fw) >> "_TIV", arg, 1, fwts_method_test_integer_return, NULL); >> } >> >> +/* >> + * Section 9.20 NVDIMM Devices >> + */ >> +static void check_nvdimm_status( >> + fwts_framework *fw, >> + char *name, >> + uint16_t status, >> + bool *failed) >> +{ >> + if (status > 6) { >> + *failed = true; >> + fwts_failed(fw, LOG_LEVEL_MEDIUM, >> + "MethodBadStatus", >> + "%s: Expected Status to be 0..6, got %" PRIx16, >> + name, status); >> + } >> +} >> + >> +static void check_nvdimm_extended_status( >> + fwts_framework *fw, >> + char *name, >> + uint16_t ext_status, >> + uint16_t expected, >> + bool *failed) >> +{ >> + if (ext_status != expected) { >> + *failed = true; >> + fwts_failed(fw, LOG_LEVEL_MEDIUM, >> + "MethodBadExtendedStatus", >> + "%s: Expected Extended Status to be %" PRIx16 >> + ", got %" PRIx16, name, expected, ext_status); >> + } >> +} >> + >> +static void method_test_NBS_return( >> + fwts_framework *fw, >> + char *name, >> + ACPI_BUFFER *buf, >> + ACPI_OBJECT *obj, >> + void *private) >> +{ >> + bool failed = false; >> + nbs_return_t *ret; >> + >> + FWTS_UNUSED(private); >> + >> + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) >> + return; >> + >> + if (obj->Buffer.Length != 64) { >> + failed = true; >> + fwts_failed(fw, LOG_LEVEL_CRITICAL, >> + "Method_NBSBadBufferSize", >> + "%s should return a buffer of 64 bytes, but " >> + "instead just returned %" PRIu32, >> + name, obj->Buffer.Length); >> + } >> + >> + ret = (nbs_return_t *) obj->Buffer.Pointer; >> + check_nvdimm_status(fw, name, ret->status, &failed); >> + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NBS", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 1, 15, &failed); > Should check the rest return bytes are reserved? >> + >> + if (!failed) >> + fwts_method_passed_sane(fw, name, "buffer"); >> +} >> + >> +static int method_test_NBS(fwts_framework *fw) >> +{ >> + return method_evaluate_method(fw, METHOD_OPTIONAL, >> + "_NBS", NULL, 0, method_test_NBS_return, NULL); >> +} >> + >> +static void method_test_NCH_return( >> + fwts_framework *fw, >> + char *name, >> + ACPI_BUFFER *buf, >> + ACPI_OBJECT *obj, >> + void *private) >> +{ >> + bool failed = false; >> + nch_return_t *ret; >> + >> + FWTS_UNUSED(private); >> + >> + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) >> + return; >> + >> + if (obj->Buffer.Length != 64) { >> + failed = true; >> + fwts_failed(fw, LOG_LEVEL_CRITICAL, >> + "Method_NCHBadBufferSize", >> + "%s should return a buffer of 64 bytes, but " >> + "instead just returned %" PRIu32, >> + name, obj->Buffer.Length); >> + } >> + >> + ret = (nch_return_t *) obj->Buffer.Pointer; >> + check_nvdimm_status(fw, name, ret->status, &failed); >> + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NCH", "Validation Flags", ret->extended_status, sizeof(uint16_t), 2, 15, &failed); >> + >> + /* Health Status Flags [2..7], [11.15], [19..31] are reserved */ >> + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 2, 7, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 11, 15, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 19, 31, &failed); >> + >> + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Attributes", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); >> + > Should check the rest return bytes are reserved? >> + if (!failed) >> + fwts_method_passed_sane(fw, name, "buffer"); >> +} >> + >> +static int method_test_NCH(fwts_framework *fw) >> +{ >> + return method_evaluate_method(fw, METHOD_OPTIONAL, >> + "_NCH", NULL, 0, method_test_NCH_return, NULL); >> +} >> + >> +static void method_test_NIC_return( >> + fwts_framework *fw, >> + char *name, >> + ACPI_BUFFER *buf, >> + ACPI_OBJECT *obj, >> + void *private) >> +{ >> + bool failed = false; >> + nic_return_t *ret; >> + >> + FWTS_UNUSED(private); >> + >> + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) >> + return; >> + >> + if (obj->Buffer.Length != 64) { >> + failed = true; >> + fwts_failed(fw, LOG_LEVEL_CRITICAL, >> + "Method_NICBadBufferSize", >> + "%s should return a buffer of 64 bytes, but " >> + "instead just returned %" PRIu32, >> + name, obj->Buffer.Length); >> + } >> + >> + ret = (nic_return_t *) obj->Buffer.Pointer; >> + check_nvdimm_status(fw, name, ret->status, &failed); >> + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); >> + >> + /* Health Error Injection Capabilities [2..7], [11.15], [19..31] are reserved */ >> + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 2, 7, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 11, 15, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 19, 31, &failed); >> + >> + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Status Attributes Capabilities", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); > same here. >> + >> + if (!failed) >> + fwts_method_passed_sane(fw, name, "buffer"); >> +} >> + >> +static int method_test_NIC(fwts_framework *fw) >> +{ >> + return method_evaluate_method(fw, METHOD_OPTIONAL, >> + "_NIC", NULL, 0, method_test_NIC_return, NULL); >> +} >> + >> +static void method_test_NIH_return( >> + fwts_framework *fw, >> + char *name, >> + ACPI_BUFFER *buf, >> + ACPI_OBJECT *obj, >> + void *private) >> +{ >> + bool failed = false; >> + nih_return_t *ret; >> + >> + FWTS_UNUSED(private); >> + >> + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) >> + return; >> + >> + if (obj->Buffer.Length != 64) { >> + failed = true; >> + fwts_failed(fw, LOG_LEVEL_CRITICAL, >> + "Method_NIHBadBufferSize", >> + "%s should return a buffer of 64 bytes, but " >> + "instead just returned %" PRIu32, >> + name, obj->Buffer.Length); >> + } >> + >> + ret = (nih_return_t *) obj->Buffer.Pointer; >> + check_nvdimm_status(fw, name, ret->status, &failed); >> + check_nvdimm_extended_status(fw, name, ret->extended_status, 1, &failed); >> + >> + if (!failed) >> + fwts_method_passed_sane(fw, name, "buffer"); >> +} >> + >> +static int method_test_NIH(fwts_framework *fw) >> +{ >> + ACPI_OBJECT arg0; >> + char data[64]; >> + int result; >> + int i, j; >> + >> + memset(data, 0, sizeof(data)); >> + arg0.Type = ACPI_TYPE_BUFFER; >> + arg0.Buffer.Length = 64; >> + arg0.Buffer.Pointer = (void *)data; >> + >> + /* not permanent (j = 0) and permanent (j = 1) errors */ >> + for (j = 0; j <= 1; j++) { >> + /* inject (i = 1) and clear (i = 2) errors */ >> + for (i = 1; i <= 2; i++) { >> + data[0] = i; >> + data[4] = 3; >> + data[5] = 7; >> + data[6] = 7; >> + data[8] = j; >> + >> + result = method_evaluate_method(fw, METHOD_OPTIONAL, >> + "_NIH", &arg0, 1, method_test_NIH_return, NULL); >> + >> + if (result != FWTS_OK) >> + return result; >> + } >> + } >> + >> + return FWTS_OK; >> +} >> + >> +static void method_test_NIG_return( >> + fwts_framework *fw, >> + char *name, >> + ACPI_BUFFER *buf, >> + ACPI_OBJECT *obj, >> + void *private) >> +{ >> + bool failed = false; >> + nig_return_t *ret; >> + >> + FWTS_UNUSED(private); >> + >> + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) >> + return; >> + >> + if (obj->Buffer.Length != 64) { >> + failed = true; >> + fwts_failed(fw, LOG_LEVEL_CRITICAL, >> + "Method_NIGBadBufferSize", >> + "%s should return a buffer of 64 bytes, but " >> + "instead just returned %" PRIu32, >> + name, obj->Buffer.Length); >> + } >> + >> + ret = (nig_return_t *) obj->Buffer.Pointer; >> + check_nvdimm_status(fw, name, ret->status, &failed); >> + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NIG", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 2, 15, &failed); >> + >> + /* Injected Health Status Errors [2..7], [11.15], [19..31] are reserved */ >> + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 2, 7, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 11, 15, &failed); >> + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 19, 31, &failed); >> + >> + fwts_acpi_reserved_bits_check(fw, "_NIG", "Health Status Attributes of Injected Errors", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); >> + > same here. >> + if (!failed) >> + fwts_method_passed_sane(fw, name, "buffer"); >> +} >> + >> +static int method_test_NIG(fwts_framework *fw) >> +{ >> + return method_evaluate_method(fw, METHOD_OPTIONAL, >> + "_NIG", NULL, 0, method_test_NIG_return, NULL); >> +} >> >> /* >> * Section 10.1 Smart Battery >> @@ -5896,6 +6175,13 @@ static fwts_framework_minor_test method_tests[] = { >> { method_test_TIP, "Test _TIP (Expired Timer Wake Policy)." }, >> { method_test_TIV, "Test _TIV (Timer Values)." }, >> >> + /* Section 9.20 NVDIMM Devices */ >> + { method_test_NBS, "Test _NBS (NVDIMM Boot Status)." }, >> + { method_test_NCH, "Test _NCH (NVDIMM Current Health Information)." }, >> + { method_test_NIC, "Test _NIC (NVDIMM Health Error Injection Capabilities)." }, >> + { method_test_NIH, "Test _NIH (NVDIMM Inject/Clear Health Errors)." }, >> + { method_test_NIG, "Test _NIG (NVDIMM Inject Health Error Status)." }, >> + >> /* Section 10.1 Smart Battery */ >> >> { method_test_SBS, "Test _SBS (Smart Battery Subsystem)." }, >> diff --git a/src/lib/include/fwts_acpi_object_eval.h b/src/lib/include/fwts_acpi_object_eval.h >> index 4a7c5ed9..565af728 100644 >> --- a/src/lib/include/fwts_acpi_object_eval.h >> +++ b/src/lib/include/fwts_acpi_object_eval.h >> @@ -66,6 +66,46 @@ typedef struct { >> uint8_t pad2[3]; >> } __attribute__ ((packed)) fwts_acpi_time_buffer; >> >> +/* Returns for NVDIMM control methods */ >> +typedef struct { >> + uint16_t status; >> + uint16_t extended_status; >> + uint16_t validation_flags; >> + uint32_t health_status_flags; >> + uint32_t health_status_attributes; >> + uint8_t reserved[50]; >> +} __attribute__ ((packed)) nch_return_t; >> + >> +typedef struct { >> + uint16_t status; >> + uint16_t extended_status; >> + uint16_t validation_flags; >> + uint32_t data_loss_count; >> + uint8_t reserved[54]; >> +} __attribute__ ((packed)) nbs_return_t; >> + >> +typedef struct { >> + uint16_t status; >> + uint16_t extended_status; >> + uint32_t health_error_injection; >> + uint32_t health_status_attributes; >> + uint8_t reserved[52]; >> +} __attribute__ ((packed)) nic_return_t; >> + >> +typedef struct { >> + uint16_t status; >> + uint16_t extended_status; >> +} __attribute__ ((packed)) nih_return_t; >> + >> +typedef struct { >> + uint16_t status; >> + uint16_t extended_status; >> + uint16_t validation_flags; >> + uint32_t health_status_errors; >> + uint32_t health_status_attributes; >> + uint8_t reserved[50]; >> +} __attribute__ ((packed)) nig_return_t; >> + >> #define fwts_method_check_type(fw, name, buf, type) \ >> fwts_method_check_type__(fw, name, buf, type, #type) Ack this patch first, can do the reserved return size on next patch. Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c index 654112d9..48a5c039 100644 --- a/src/acpi/method/method.c +++ b/src/acpi/method/method.c @@ -138,6 +138,11 @@ * _MSG Y * _MSM N * _MTL Y + * _NBS Y + * _NCH Y + * _NIC Y + * _NIH Y + * _NIG Y * _NTT Y * _OFF Y * _ON_ Y @@ -3574,6 +3579,280 @@ static int method_test_TIV(fwts_framework *fw) "_TIV", arg, 1, fwts_method_test_integer_return, NULL); } +/* + * Section 9.20 NVDIMM Devices + */ +static void check_nvdimm_status( + fwts_framework *fw, + char *name, + uint16_t status, + bool *failed) +{ + if (status > 6) { + *failed = true; + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "MethodBadStatus", + "%s: Expected Status to be 0..6, got %" PRIx16, + name, status); + } +} + +static void check_nvdimm_extended_status( + fwts_framework *fw, + char *name, + uint16_t ext_status, + uint16_t expected, + bool *failed) +{ + if (ext_status != expected) { + *failed = true; + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "MethodBadExtendedStatus", + "%s: Expected Extended Status to be %" PRIx16 + ", got %" PRIx16, name, expected, ext_status); + } +} + +static void method_test_NBS_return( + fwts_framework *fw, + char *name, + ACPI_BUFFER *buf, + ACPI_OBJECT *obj, + void *private) +{ + bool failed = false; + nbs_return_t *ret; + + FWTS_UNUSED(private); + + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) + return; + + if (obj->Buffer.Length != 64) { + failed = true; + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "Method_NBSBadBufferSize", + "%s should return a buffer of 64 bytes, but " + "instead just returned %" PRIu32, + name, obj->Buffer.Length); + } + + ret = (nbs_return_t *) obj->Buffer.Pointer; + check_nvdimm_status(fw, name, ret->status, &failed); + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); + fwts_acpi_reserved_bits_check(fw, "_NBS", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 1, 15, &failed); + + if (!failed) + fwts_method_passed_sane(fw, name, "buffer"); +} + +static int method_test_NBS(fwts_framework *fw) +{ + return method_evaluate_method(fw, METHOD_OPTIONAL, + "_NBS", NULL, 0, method_test_NBS_return, NULL); +} + +static void method_test_NCH_return( + fwts_framework *fw, + char *name, + ACPI_BUFFER *buf, + ACPI_OBJECT *obj, + void *private) +{ + bool failed = false; + nch_return_t *ret; + + FWTS_UNUSED(private); + + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) + return; + + if (obj->Buffer.Length != 64) { + failed = true; + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "Method_NCHBadBufferSize", + "%s should return a buffer of 64 bytes, but " + "instead just returned %" PRIu32, + name, obj->Buffer.Length); + } + + ret = (nch_return_t *) obj->Buffer.Pointer; + check_nvdimm_status(fw, name, ret->status, &failed); + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); + fwts_acpi_reserved_bits_check(fw, "_NCH", "Validation Flags", ret->extended_status, sizeof(uint16_t), 2, 15, &failed); + + /* Health Status Flags [2..7], [11.15], [19..31] are reserved */ + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 2, 7, &failed); + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 11, 15, &failed); + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Flags", ret->health_status_flags, sizeof(uint32_t), 19, 31, &failed); + + fwts_acpi_reserved_bits_check(fw, "_NCH", "Health Status Attributes", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); + + if (!failed) + fwts_method_passed_sane(fw, name, "buffer"); +} + +static int method_test_NCH(fwts_framework *fw) +{ + return method_evaluate_method(fw, METHOD_OPTIONAL, + "_NCH", NULL, 0, method_test_NCH_return, NULL); +} + +static void method_test_NIC_return( + fwts_framework *fw, + char *name, + ACPI_BUFFER *buf, + ACPI_OBJECT *obj, + void *private) +{ + bool failed = false; + nic_return_t *ret; + + FWTS_UNUSED(private); + + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) + return; + + if (obj->Buffer.Length != 64) { + failed = true; + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "Method_NICBadBufferSize", + "%s should return a buffer of 64 bytes, but " + "instead just returned %" PRIu32, + name, obj->Buffer.Length); + } + + ret = (nic_return_t *) obj->Buffer.Pointer; + check_nvdimm_status(fw, name, ret->status, &failed); + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); + + /* Health Error Injection Capabilities [2..7], [11.15], [19..31] are reserved */ + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 2, 7, &failed); + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 11, 15, &failed); + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Error Injection Capabilities", ret->health_error_injection, sizeof(uint32_t), 19, 31, &failed); + + fwts_acpi_reserved_bits_check(fw, "_NIC", "Health Status Attributes Capabilities", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); + + if (!failed) + fwts_method_passed_sane(fw, name, "buffer"); +} + +static int method_test_NIC(fwts_framework *fw) +{ + return method_evaluate_method(fw, METHOD_OPTIONAL, + "_NIC", NULL, 0, method_test_NIC_return, NULL); +} + +static void method_test_NIH_return( + fwts_framework *fw, + char *name, + ACPI_BUFFER *buf, + ACPI_OBJECT *obj, + void *private) +{ + bool failed = false; + nih_return_t *ret; + + FWTS_UNUSED(private); + + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) + return; + + if (obj->Buffer.Length != 64) { + failed = true; + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "Method_NIHBadBufferSize", + "%s should return a buffer of 64 bytes, but " + "instead just returned %" PRIu32, + name, obj->Buffer.Length); + } + + ret = (nih_return_t *) obj->Buffer.Pointer; + check_nvdimm_status(fw, name, ret->status, &failed); + check_nvdimm_extended_status(fw, name, ret->extended_status, 1, &failed); + + if (!failed) + fwts_method_passed_sane(fw, name, "buffer"); +} + +static int method_test_NIH(fwts_framework *fw) +{ + ACPI_OBJECT arg0; + char data[64]; + int result; + int i, j; + + memset(data, 0, sizeof(data)); + arg0.Type = ACPI_TYPE_BUFFER; + arg0.Buffer.Length = 64; + arg0.Buffer.Pointer = (void *)data; + + /* not permanent (j = 0) and permanent (j = 1) errors */ + for (j = 0; j <= 1; j++) { + /* inject (i = 1) and clear (i = 2) errors */ + for (i = 1; i <= 2; i++) { + data[0] = i; + data[4] = 3; + data[5] = 7; + data[6] = 7; + data[8] = j; + + result = method_evaluate_method(fw, METHOD_OPTIONAL, + "_NIH", &arg0, 1, method_test_NIH_return, NULL); + + if (result != FWTS_OK) + return result; + } + } + + return FWTS_OK; +} + +static void method_test_NIG_return( + fwts_framework *fw, + char *name, + ACPI_BUFFER *buf, + ACPI_OBJECT *obj, + void *private) +{ + bool failed = false; + nig_return_t *ret; + + FWTS_UNUSED(private); + + if (fwts_method_check_type(fw, name, buf, ACPI_TYPE_BUFFER) != FWTS_OK) + return; + + if (obj->Buffer.Length != 64) { + failed = true; + fwts_failed(fw, LOG_LEVEL_CRITICAL, + "Method_NIGBadBufferSize", + "%s should return a buffer of 64 bytes, but " + "instead just returned %" PRIu32, + name, obj->Buffer.Length); + } + + ret = (nig_return_t *) obj->Buffer.Pointer; + check_nvdimm_status(fw, name, ret->status, &failed); + check_nvdimm_extended_status(fw, name, ret->extended_status, 0, &failed); + fwts_acpi_reserved_bits_check(fw, "_NIG", "Validation Flags", ret->validation_flags, sizeof(uint16_t), 2, 15, &failed); + + /* Injected Health Status Errors [2..7], [11.15], [19..31] are reserved */ + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 2, 7, &failed); + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 11, 15, &failed); + fwts_acpi_reserved_bits_check(fw, "_NIG", "Injected Health Status Errors", ret->health_status_errors, sizeof(uint32_t), 19, 31, &failed); + + fwts_acpi_reserved_bits_check(fw, "_NIG", "Health Status Attributes of Injected Errors", ret->health_status_attributes, sizeof(uint32_t), 1, 31, &failed); + + if (!failed) + fwts_method_passed_sane(fw, name, "buffer"); +} + +static int method_test_NIG(fwts_framework *fw) +{ + return method_evaluate_method(fw, METHOD_OPTIONAL, + "_NIG", NULL, 0, method_test_NIG_return, NULL); +} /* * Section 10.1 Smart Battery @@ -5896,6 +6175,13 @@ static fwts_framework_minor_test method_tests[] = { { method_test_TIP, "Test _TIP (Expired Timer Wake Policy)." }, { method_test_TIV, "Test _TIV (Timer Values)." }, + /* Section 9.20 NVDIMM Devices */ + { method_test_NBS, "Test _NBS (NVDIMM Boot Status)." }, + { method_test_NCH, "Test _NCH (NVDIMM Current Health Information)." }, + { method_test_NIC, "Test _NIC (NVDIMM Health Error Injection Capabilities)." }, + { method_test_NIH, "Test _NIH (NVDIMM Inject/Clear Health Errors)." }, + { method_test_NIG, "Test _NIG (NVDIMM Inject Health Error Status)." }, + /* Section 10.1 Smart Battery */ { method_test_SBS, "Test _SBS (Smart Battery Subsystem)." }, diff --git a/src/lib/include/fwts_acpi_object_eval.h b/src/lib/include/fwts_acpi_object_eval.h index 4a7c5ed9..565af728 100644 --- a/src/lib/include/fwts_acpi_object_eval.h +++ b/src/lib/include/fwts_acpi_object_eval.h @@ -66,6 +66,46 @@ typedef struct { uint8_t pad2[3]; } __attribute__ ((packed)) fwts_acpi_time_buffer; +/* Returns for NVDIMM control methods */ +typedef struct { + uint16_t status; + uint16_t extended_status; + uint16_t validation_flags; + uint32_t health_status_flags; + uint32_t health_status_attributes; + uint8_t reserved[50]; +} __attribute__ ((packed)) nch_return_t; + +typedef struct { + uint16_t status; + uint16_t extended_status; + uint16_t validation_flags; + uint32_t data_loss_count; + uint8_t reserved[54]; +} __attribute__ ((packed)) nbs_return_t; + +typedef struct { + uint16_t status; + uint16_t extended_status; + uint32_t health_error_injection; + uint32_t health_status_attributes; + uint8_t reserved[52]; +} __attribute__ ((packed)) nic_return_t; + +typedef struct { + uint16_t status; + uint16_t extended_status; +} __attribute__ ((packed)) nih_return_t; + +typedef struct { + uint16_t status; + uint16_t extended_status; + uint16_t validation_flags; + uint32_t health_status_errors; + uint32_t health_status_attributes; + uint8_t reserved[50]; +} __attribute__ ((packed)) nig_return_t; + #define fwts_method_check_type(fw, name, buf, type) \ fwts_method_check_type__(fw, name, buf, type, #type)
Signed-off-by: Alex Hung <alex.hung@canonical.com> --- src/acpi/method/method.c | 286 ++++++++++++++++++++++++ src/lib/include/fwts_acpi_object_eval.h | 40 ++++ 2 files changed, 326 insertions(+)