diff mbox

[2/6] acpi: method: re-order method test functions

Message ID 1348052021-1714-3-git-send-email-colin.king@canonical.com
State Rejected
Headers show

Commit Message

Colin Ian King Sept. 19, 2012, 10:53 a.m. UTC
From: Colin Ian King <colin.king@canonical.com>

The test functions were systematically randomized which
made it a complete headache to maintain.  Re-order them
in order of the ACPI specific sections and also tidy
up some white spaces.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 src/acpi/method/method.c | 2220 +++++++++++++++++++++++++---------------------
 1 file changed, 1218 insertions(+), 1002 deletions(-)

Comments

Keng-Yu Lin Sept. 20, 2012, 9:54 a.m. UTC | #1
On Wed, Sep 19, 2012 at 6:53 PM, Colin King <colin.king@canonical.com> wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> The test functions were systematically randomized which
> made it a complete headache to maintain.  Re-order them
> in order of the ACPI specific sections and also tidy
> up some white spaces.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>  src/acpi/method/method.c | 2220 +++++++++++++++++++++++++---------------------
>  1 file changed, 1218 insertions(+), 1002 deletions(-)
>
> diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
> index afba21f..b706a56 100644
> --- a/src/acpi/method/method.c
> +++ b/src/acpi/method/method.c
> @@ -261,6 +261,15 @@ static int method_test ## name(fwts_framework *fw) \
>
>  typedef void (*method_test_return)(fwts_framework *fw, char *name, ACPI_BUFFER *ret_buff, ACPI_OBJECT *ret_obj, void *private);
>
> +
> +
> +
> +/*
> + * Helper functions to facilitate the evaluations
> + */
> +
> +/****************************************************************************/
> +
>  static int method_init(fwts_framework *fw)
>  {
>         fwts_acpi_table_info *info;
> @@ -492,591 +501,990 @@ static void method_test_passed_failed_return(fwts_framework *fw, char *name, ACP
>         }
>  }
>
> -/* Section 10.1.1.1 Smart Battery */
> -
> -static void method_test_SBS_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static void method_test_polling_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
>  {
> -       static char *sbs_info[] = {
> -               "Maximum 1 Smart Battery, system manager/selector not present",
> -               "Maximum 1 Smart Battery, system manager/selector present",
> -               "Maximum 2 Smart Batteries, system manager/selector present",
> -               "Maximum 3 Smart Batteries, system manager/selector present",
> -               "Maximum 4 Smart Batteries, system manager/selector present"
> -       };
> -
>         if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
> -               switch (obj->Integer.Value) {
> -               case 0 ... 4:
> -                       fwts_passed(fw, "_SBS correctly returned value %d %s",
> -                               (uint32_t)obj->Integer.Value,
> -                               sbs_info[obj->Integer.Value]);
> -                       break;
> -               default:
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SBSReturn", "_SBS returned %d, should be between 0 and 4.",
> -                               (uint32_t)obj->Integer.Value);
> +               char *method = (char *)private;
> +               if (obj->Integer.Value < 36000) {
> +                       fwts_passed(fw, "%s correctly returned sane looking value %f seconds",
> +                               method, (float)obj->Integer.Value / 10.0);
> +               } else {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodPollTimeTooLong",
> +                               "%s returned a value %f seconds > (1 hour) which is probably incorrect.",
> +                               method, (float)obj->Integer.Value / 10.0);
>                         fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       fwts_advice(fw, "Smart Battery _SBS is incorrectly informing the OS about the smart battery "
> -                                       "configuration. This is a bug and needs to be fixed.");
> -                       break;
> +                       fwts_advice(fw, "The method is returning a polling interval which is very long and hence "
> +                                       "most probably incorrect.");
>                 }
>         }
>  }
>
> -static int method_test_SBS(fwts_framework *fw)
> +/****************************************************************************/
> +
> +/*
> + * Section 5.6 ACPI Event Programming Model
> + */
> +static int method_test_AEI(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_SBS", NULL, 0, method_test_SBS_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_AEI", NULL, 0, method_test_buffer_return, NULL);
>  }
>
> +/*
> + * Section 6.1 Device Identification Objects
> + */
> +static int method_test_SUN(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_SUN", NULL, 0, method_test_integer_return, NULL);
> +}
>
> -/* Section 10.2.2 Battery Control Methods */
> +static void method_test_UID_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
> +{
> +       if (obj == NULL){
> +               fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodReturnNullObj", "Method %s returned a NULL object, and did not return a buffer or integer.", name);
> +               return;
> +       }
> +       switch (obj->Type) {
> +       case ACPI_TYPE_STRING:
> +               if (obj->String.Pointer)
> +                       fwts_passed(fw, "Object _UID returned a string '%s' as expected.",
> +                               obj->String.Pointer);
> +               else {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDNullString",
> +                               "Object _UID returned a NULL string.");
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +               }
> +               break;
> +       case ACPI_TYPE_INTEGER:
> +               fwts_passed(fw, "Object _UID returned am integer 0x%8.8llx.",
> +                       (unsigned long long)obj->Integer.Value);
> +               break;
> +       default:
> +               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDBadReturnType",
> +                       "Method _UID did not return a string or an integer.");
> +               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +               break;
> +       }
> +}
>
> -static void method_test_BIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static int method_test_UID(fwts_framework *fw)
>  {
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> -               int i;
> -               int failed = 0;
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_UID", NULL, 0, method_test_UID_return, NULL);
> +}
>
> -               fwts_method_dump_object(fw, obj);
>
> -               if (obj->Package.Count != 13) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFElementCount", "_BIF package should return 13 elements, got %d instead.",
> -                               obj->Package.Count);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -               }
> +/*
> + *  Section 6.2 Device Configurations Objects
> + */
> +static int method_test_CRS(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_MANDITORY,
> +               "_CRS", NULL, 0, method_test_buffer_return, NULL);
> +}
>
> -               for (i=0;(i<9) && (i<obj->Package.Count);i++) {
> -                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type DWORD Integer.", i);
> -                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                               failed++;
> -                       }
> -               }
> -               for (i=9;(i<13) && (i<obj->Package.Count);i++) {
> -                       if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type STRING.", i);
> -                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                               failed++;
> -                       }
> -               }
> +static int method_test_DMA(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DMA", NULL, 0, method_test_buffer_return, NULL);
> +}
>
> -               /* Sanity check each field */
> -               /* Power Unit */
> -               if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadUnits", "_BIF: Expected Power Unit (Element 0) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[0].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#ifdef FWTS_METHOD_PEDANDTIC
> -               /*
> -                * Since this information may be evaluated by communicating with
> -                * the EC we skip these checks as we can't do this from userspace
> -                */
> -               /* Design Capacity */
> -               if (obj->Package.Elements[1].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFBadCapacity", "_BIF: Design Capacity (Element 1) is unknown: 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[1].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Last Full Charge Capacity */
> -               if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFChargeCapacity", "_BIF: Last Full Charge Capacity (Element 2) is unknown: 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[2].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#endif
> -               /* Battery Technology */
> -               if (obj->Package.Elements[3].Integer.Value > 0x00000002) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBatTechUnit", "_BIF: Expected Battery Technology Unit (Element 3) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[3].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#ifdef FWTS_METHOD_PEDANDTIC
> -               /*
> -                * Since this information may be evaluated by communicating with
> -                * the EC we skip these checks as we can't do this from userspace
> -                */
> -               /* Design Voltage */
> -               if (obj->Package.Elements[4].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignVoltage", "_BIF: Design Voltage (Element 4) is unknown: 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[4].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Design capacity warning */
> -               if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE5", "_BIF: Design Capacity Warning (Element 5) is unknown: 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[5].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Design capacity low */
> -               if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE6", "_BIF: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[6].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#endif
> -               if (failed)
> -                       fwts_advice(fw, "Battery _BIF package contains errors. It is worth running the "
> -                                       "firmware test suite interactive 'battery' test to see if this "
> -                                       "is problematic.  This is a bug an needs to be fixed.");
> -               else
> -                       fwts_passed(fw, "Battery _BIF package looks sane.");
> -       }
> +static int method_test_DIS(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DIS", NULL, 0, method_test_NULL_return, NULL);
>  }
>
> -static int method_test_BIF(fwts_framework *fw)
> +static int method_test_PXM(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_BIF", NULL, 0, method_test_BIF_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_PXM", NULL, 0, method_test_integer_return, NULL);
>  }
>
> -static void method_test_BIX_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +
> +/*
> + * Section 6.3 Device Insertion, Removal and Status Objects
> + */
> +static int method_test_EJD(fwts_framework *fw)
>  {
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> -               int i;
> -               int failed = 0;
> +       return method_evaluate_method(fw, METHOD_OPTIONAL, "_EJD", NULL, 0, method_test_string_return, NULL);
> +}
>
> -               fwts_method_dump_object(fw, obj);
> +#define method_test_EJx(name)                          \
> +static int method_test ## name(fwts_framework *fw)     \
> +{                                                      \
> +       ACPI_OBJECT arg[1];                             \
> +                                                       \
> +       arg[0].Type = ACPI_TYPE_INTEGER;                \
> +       arg[0].Integer.Value = 1;                       \
> +                                                       \
> +       return method_evaluate_method(fw, METHOD_OPTIONAL, # name, arg, 1, method_test_NULL_return, # name); \
> +}
>
> -               if (obj->Package.Count != 16) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXElementCount", "_BIX package should return 16 elements, got %d instead.",
> -                               obj->Package.Count);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> +method_test_EJx(_EJ0)
> +method_test_EJx(_EJ1)
> +method_test_EJx(_EJ2)
> +method_test_EJx(_EJ3)
> +method_test_EJx(_EJ4)
>
> -               for (i=0;(i<16) && (i<obj->Package.Count);i++) {
> -                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type DWORD Integer.", i);
> -                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                               failed++;
> -                       }
> -               }
> -               for (i=16;(i<20) && (i<obj->Package.Count);i++) {
> -                       if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type STRING.", i);
> -                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                               failed++;
> -                       }
> -               }
> +static int method_test_LCK(fwts_framework *fw)
> +{
> +       ACPI_OBJECT arg[1];
>
> -               /* Sanity check each field */
> -               /* Power Unit */
> -               if (obj->Package.Elements[1].Integer.Value > 0x00000002) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXPowerUnit",
> -                               "_BIX: Expected Power Unit (Element 1) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[1].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#ifdef FWTS_METHOD_PEDANDTIC
> -               /*
> -                * Since this information may be evaluated by communicating with
> -                * the EC we skip these checks as we can't do this from userspace
> -                */
> -               /* Design Capacity */
> -               if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacity",
> -                               "_BIX: Design Capacity (Element 2) is unknown: 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[2].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Last Full Charge Capacity */
> -               if (obj->Package.Elements[3].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXFullChargeCapacity",
> -                               "_BIX: Last Full Charge Capacity (Element 3) is unknown: 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[3].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#endif
> -               /* Battery Technology */
> -               if (obj->Package.Elements[4].Integer.Value > 0x00000002) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBatteryTechUnit",
> -                               "_BIX: Expected Battery Technology Unit (Element 4) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[4].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#ifdef FWTS_METHOD_PEDANDTIC
> -               /*
> -                * Since this information may be evaluated by communicating with
> -                * the EC we skip these checks as we can't do this from userspace
> -                */
> -               /* Design Voltage */
> -               if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignVoltage",
> -                               "_BIX: Design Voltage (Element 5) is unknown: 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[5].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Design capacity warning */
> -               if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE6",
> -                               "_BIX: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[6].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Design capacity low */
> -               if (obj->Package.Elements[7].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE7",
> -                                "_BIX: Design Capacity Warning (Element 7) is unknown: 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[7].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Cycle Count */
> -               if (obj->Package.Elements[10].Integer.Value > 0x7fffffff) {
> -                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXCyleCount",
> -                               "_BIX: Cycle Count (Element 10) is unknown: 0x%8.8x.",
> -                               (uint32_t)obj->Package.Elements[10].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -#endif
> -               if (failed)
> -                       fwts_advice(fw, "Battery _BIX package contains errors. It is worth running the "
> -                                       "firmware test suite interactive 'battery' test to see if this "
> -                                       "is problematic.  This is a bug an needs to be fixed.");
> -               else
> -                       fwts_passed(fw, "Battery _BIX package looks sane.");
> -       }
> -}
> -
> -static int method_test_BIX(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_BIX", NULL, 0, method_test_BIX_return, NULL);
> -}
> -
> -static int method_test_BMA(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[1];
>         arg[0].Type = ACPI_TYPE_INTEGER;
>         arg[0].Integer.Value = 1;
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_BMA", arg, 1, method_test_integer_return, NULL);
> -}
>
> -static int method_test_BMS(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[1];
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_BMS", arg, 1, method_test_integer_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL, "_LCK", arg, 1, method_test_NULL_return, NULL);
>  }
>
> -static void method_test_BST_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> -{
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> -               int i;
> -               int failed = 0;
> -
> -               fwts_method_dump_object(fw, obj);
> -
> -               if (obj->Package.Count != 4) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTElementCount", "_BST package should return 4 elements, got %d instead.",
> -                               obj->Package.Count);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -
> -               for (i=0;(i<4) && (i<obj->Package.Count);i++) {
> -                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadType",
> -                                       "_BST package element %d is not of type DWORD Integer.", i);
> -                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                               failed++;
> -                       }
> -               }
>
> -               /* Sanity check each field */
> -               /* Battery State */
> -               if ((obj->Package.Elements[0].Integer.Value) > 7) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
> -                                       "_BST: Expected Battery State (Element 0) to be 0..7, got 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[0].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Ensure bits 0 (discharging) and 1 (charging) are not both set, see 10.2.2.6 */
> -               if (((obj->Package.Elements[0].Integer.Value) & 3) == 3) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
> -                                       "_BST: Battery State (Element 0) is indicating both charging "
> -                                       "and discharginng which is not allowed. Got value 0x%8.8x.",
> -                                       (uint32_t)obj->Package.Elements[0].Integer.Value);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> -               /* Battery Present Rate - cannot check, pulled from EC */
> -               /* Battery Remaining Capacity - cannot check, pulled from EC */
> -               /* Battery Present Voltage - cannot check, pulled from EC */
> -               if (failed)
> -                       fwts_advice(fw, "Battery _BST package contains errors. It is worth running the "
> -                                       "firmware test suite interactive 'battery' test to see if this "
> -                                       "is problematic.  This is a bug an needs to be fixed.");
> -               else
> -                       fwts_passed(fw, "Battery _BST package looks sane.");
> -       }
> +/*
> + * Section 6.5 Other Objects and Controls
> + */
> +static int method_test_BBN(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL, "_BBN",
> +               NULL, 0, method_test_integer_return, "_BBN");
>  }
>
> -static int method_test_BST(fwts_framework *fw)
> +static int method_test_BDN(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_BST", NULL, 0, method_test_BST_return, NULL);
> +       return method_evaluate_method(fw, METHOD_MOBILE, "_BDN",
> +               NULL, 0, method_test_integer_return, "_BDN");
>  }
>
> -static int method_test_BTP(fwts_framework *fw)
> +static int method_test_DCK(fwts_framework *fw)
>  {
> -       static int values[] = { 0, 1, 100, 200, 0x7fffffff };
>         int i;
>
> -       for (i=0;i<5;i++) {
> +       for (i=0;i<=1;i++) {    /* Undock, Dock */
>                 ACPI_OBJECT arg[1];
>                 arg[0].Type = ACPI_TYPE_INTEGER;
> -               arg[0].Integer.Value = values[i];
> -               if (method_evaluate_method(fw, METHOD_MOBILE, "_BTP", arg, 1,
> -                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> +               arg[0].Integer.Value = i;
> +               if (method_evaluate_method(fw, METHOD_MOBILE, "_DCK", arg, 1, method_test_passed_failed_return, "_DCK") != FWTS_OK)
>                         break;
>                 fwts_log_nl(fw);
>         }
>         return FWTS_OK;
>  }
>
> -static void method_test_PCL_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> -{
> -       /* FIXME */
> -}
>
> -static int method_test_PCL(fwts_framework *fw)
> +/*
> + * Section 7.1 Declaring a Power Resource Object
> + */
> +static int method_test_ON(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_PCL", NULL, 0, method_test_PCL_return, "_PCL");
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_ON", NULL, 0, method_test_NULL_return, NULL);
>  }
>
> -static int method_test_BTM(fwts_framework *fw)
> +static int method_test_OFF(fwts_framework *fw)
>  {
> -       static int values[] = { 0, 1, 100, 200, 0x7fffffff };
> -       int i;
> -
> -       for (i=0;i<5;i++) {
> -               ACPI_OBJECT arg[1];
> -               arg[0].Type = ACPI_TYPE_INTEGER;
> -               arg[0].Integer.Value = values[i];
> -               if (method_evaluate_method(fw, METHOD_MOBILE, "_BTM", arg, 1,
> -                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> -                       break;
> -               fwts_log_nl(fw);
> -       }
> -       return FWTS_OK;
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_OFF", NULL, 0, method_test_NULL_return, NULL);
>  }
>
> -static void method_test_BMD_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +
> +/*
> + * Section 7.2  Device Power Management Objects
> + */
> +static int method_test_DSW(fwts_framework *fw)
>  {
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> -               int i;
> -               int failed = 0;
> +       ACPI_OBJECT arg[3];
>
> -               fwts_method_dump_object(fw, obj);
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;
> +       arg[1].Type = ACPI_TYPE_INTEGER;
> +       arg[1].Integer.Value = 0;
> +       arg[2].Type = ACPI_TYPE_INTEGER;
> +       arg[2].Integer.Value = 3;
>
> -               if (obj->Package.Count != 5) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDElementCount", "_BMD package should return 4 elements, got %d instead.",
> -                               obj->Package.Count);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed++;
> -               }
> +       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DSW",
> +               arg, 3, method_test_NULL_return, NULL);
> +}
>
> -               for (i=0;(i<4) && (i<obj->Package.Count);i++) {
> -                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDBadType", "_BMD package element %d is not of type DWORD Integer.", i);
> -                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                               failed++;
> -                       }
> -               }
> -               /* TODO: check return values */
> -       }
> +#define method_test_PSx(name)                                          \
> +static int method_test ## name(fwts_framework *fw)                     \
> +{                                                                      \
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,              \
> +               # name, NULL, 0, method_test_NULL_return, # name);      \
>  }
>
> -static int method_test_BMD(fwts_framework *fw)
> +method_test_PSx(_PS0)
> +method_test_PSx(_PS1)
> +method_test_PSx(_PS2)
> +method_test_PSx(_PS3)
> +
> +static int method_test_PSC(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_BMD", NULL, 0, method_test_BMD_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_PSC", NULL, 0, method_test_integer_return, NULL);
>  }
>
> -static int method_test_BMC(fwts_framework *fw)
> +static int method_test_PSE(fwts_framework *fw)
>  {
> -       static int values[] = { 0, 1, 2, 4 };
> -       int i;
> +       ACPI_OBJECT arg[1];
>
> -       for (i=0;i<4;i++) {
> -               ACPI_OBJECT arg[1];
> -               arg[0].Type = ACPI_TYPE_INTEGER;
> -               arg[0].Integer.Value = values[i];
> -               if (method_evaluate_method(fw, METHOD_MOBILE, "_BMC", arg, 1,
> -                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> -                       break;
> -               fwts_log_nl(fw);
> -       }
> -       return FWTS_OK;
> -}
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;
>
> -/* Section 15, Waking and Sleeping */
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_PSE", arg, 1, method_test_NULL_return, NULL);
> +}
>
> -static int method_test_PTS(fwts_framework *fw)
> +static void method_test_PRE_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         int i;
>
> -       for (i=1; i<6; i++) {
> -               ACPI_OBJECT arg[1];
> -
> -               arg[0].Type = ACPI_TYPE_INTEGER;
> -               arg[0].Integer.Value = i;
> -
> -               fwts_log_info(fw, "Test _PTS(%d).", i);
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
> +               return;
>
> -               if (method_evaluate_method(fw, METHOD_MANDITORY, "_PTS", arg, 1,
> -                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST) {
> -                       fwts_advice(fw, "Could not find _PTS. This method provides a mechanism to "
> -                                       "do housekeeping functions, such as write sleep state to the "
> -                                       "embedded controller before entering a sleep state. If the "
> -                                       "machine cannot suspend (S3), hibernate (S4) or shutdown (S5) "
> -                                       "then it could be because _PTS is missing.");
> -                       break;
> +       /* All elements in the package must be references */
> +       for (i=0; i < obj->Package.Count; i++) {
> +               if (obj->Package.Elements[i].Type != ACPI_TYPE_LOCAL_REFERENCE) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PREElementType",
> +                       "_PRE package element %d was not a reference.", i);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
>                 }
> -               fwts_log_nl(fw);
>         }
> -       return FWTS_OK;
>  }
>
> -static int method_test_TTS(fwts_framework *fw)
> +static int method_test_PRE(fwts_framework *fw)
>  {
> -       int i;
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_PRE", NULL, 0, method_test_PRE_return, NULL);
> +}
>
> -       if (fwts_method_exists("_BFS") != NULL) {
> -               for (i=1; i<6; i++) {
> -                       ACPI_OBJECT arg[1];
> +static int method_test_PSW(fwts_framework *fw)
> +{
> +       ACPI_OBJECT arg[1];
> +
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;
> +
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_PSW", arg, 1, method_test_NULL_return, NULL);
> +}
> +
> +static int method_test_IRC(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_IRC", NULL, 0, method_test_NULL_return, NULL);
> +}
> +
> +
> +/*
> + * Section 8.4 Declaring Processors
> + */
> +static void method_test_PSS_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
> +{
> +       int i;
> +       bool failed = false;
> +       uint32_t max_freq = 0;
> +       uint32_t prev_power = 0;
> +       bool max_freq_valid = false;
> +
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
> +               return;
> +
> +       /* Something is really wrong if we don't have any elements in _PSS */
> +       if (obj->Package.Count < 1) {
> +               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementCount",
> +                       "_PSS should return package of at least 1 element, "
> +                       "got %d elements instead.",
> +                       obj->Package.Count);
> +               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +               return;
> +       }
> +
> +       for (i=0; i < obj->Package.Count; i++) {
> +               ACPI_OBJECT *pstate;
> +
> +               if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementType",
> +                       "_PSS package element %d was not a package.", i);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed = true;
> +                       continue;       /* Skip processing sub-package */
> +               }
> +
> +               pstate = &obj->Package.Elements[i];
> +               if (pstate->Package.Count != 6) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementCount",
> +                               "_PSS P-State sub-package %d was expected to have "
> +                               "6 elements, got %d elements instead.",
> +                               i, obj->Package.Count);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed = true;
> +                       continue;       /* Skip processing sub-package */
> +               }
> +
> +               /* Elements need to be all ACPI integer types */
> +               if ((pstate->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
> +                   (pstate->Package.Elements[1].Type != ACPI_TYPE_INTEGER) ||
> +                   (pstate->Package.Elements[2].Type != ACPI_TYPE_INTEGER) ||
> +                   (pstate->Package.Elements[3].Type != ACPI_TYPE_INTEGER) ||
> +                   (pstate->Package.Elements[4].Type != ACPI_TYPE_INTEGER) ||
> +                   (pstate->Package.Elements[5].Type != ACPI_TYPE_INTEGER)) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementType",
> +                               "_PSS P-State sub-package %d was expected to have "
> +                               "6 Integer elements but didn't", i);
> +                       failed = true;
> +                       continue;
> +               }
> +
> +               fwts_log_info(fw, "P-State %d: CPU %ld Mhz, %lu mW, latency %lu us, bus master latency %lu us.",
> +                       i,
> +                       (unsigned long)pstate->Package.Elements[0].Integer.Value,
> +                       (unsigned long)pstate->Package.Elements[1].Integer.Value,
> +                       (unsigned long)pstate->Package.Elements[2].Integer.Value,
> +                       (unsigned long)pstate->Package.Elements[3].Integer.Value);
> +
> +               /*
> +                * Collect maximum frequency.  The sub-packages are sorted in
> +                * descending power dissipation order, so one would assume that
> +                * the highest frequency is first.  However, it is not clear
> +                * from the ACPI spec that this is necessarily an assumption we
> +                * should make, so instead we should probably scan through all
> +                * the valid sub-packages and find the highest frequency.
> +                */
> +               if (max_freq < pstate->Package.Elements[0].Integer.Value) {
> +                       max_freq = pstate->Package.Elements[0].Integer.Value;
> +                       max_freq_valid = true;
> +               }
> +
> +               /* Sanity check descending power dissipation levels */
> +               if ((i > 0) && (prev_power != 0) &&
> +                   (pstate->Package.Elements[1].Integer.Value > prev_power)) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackagePowerNotDecending",
> +                               "_PSS P-State sub-package %d has a larger power dissipation "
> +                               "setting than the previous sub-package.", i);
> +                       fwts_advice(fw, "_PSS P-States must be ordered in decending order of "
> +                               "power dissipation, so that the zero'th entry has the highest "
> +                               "power dissipation level and the Nth has the lowest.");
> +                       failed = true;
> +               }
> +               prev_power = pstate->Package.Elements[1].Integer.Value;
> +       }
> +
> +       /*
> +        * Sanity check maximum frequency.  We could also check the DMI data
> +        * for a BIOS date (but this can be wrong) or check the CPU identity
> +        * (which requires adding in new CPU identity checks) to make a decision
> +        * on when it is reasonable to assume a CPU is modern and hence clocked
> +        * incorrectly.  For now, just flag up a low level error that the
> +        * frequency looks rather low rather than try to be intelligent (and
> +        * possibly make a mistake).  I'd rather flag up a few false positives
> +        * on older machines than miss flagging up bad _PSS settings on new
> +        * machines.
> +        */
> +       if (max_freq_valid && max_freq < 1000) {
> +               fwts_failed(fw, LOG_LEVEL_LOW, "Method_PSSSubPackageLowFreq",
> +                       "Maximum CPU frequency is %dHz and this is low for "
> +                       "a modern processor. This may indicate the _PSS P-States "
> +                       "are incorrect\n", max_freq);
> +               fwts_advice(fw,
> +                       "The _PSS P-States are used by the Linux CPU frequency "
> +                       "driver to set the CPU frequencies according to system "
> +                       "load.  Sometimes the firmware sets these incorrectly "
> +                       "and the machine runs at a sub-optimal speed.  One can "
> +                       "view the firmware defined CPU frequencies via "
> +                       "/sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies");
> +               failed = true;
> +       }
> +
> +       if (!failed)
> +               fwts_passed(fw, "_PSS correctly returned sane looking package.");
> +}
> +
> +static int method_test_PSS(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSS", NULL, 0, method_test_PSS_return, NULL);
> +}
> +
> +
> +/*
> + * Section 9.2 Ambient Light Sensor Device
> + */
> +method_test_integer(_ALC, METHOD_OPTIONAL)
> +method_test_integer(_ALI, METHOD_OPTIONAL)
> +method_test_integer(_ALT, METHOD_OPTIONAL)
> +
> +/* TODO _ALR */
> +
> +static int method_test_ALP(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_ALP", NULL, 0, method_test_polling_return, "_ALP");
> +}
> +
> +
> +/*
> + * Section 9.4 Lid control
> + */
> +static void method_test_LID_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +{
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK)
> +               fwts_passed(fw, "_LID correctly returned sane looking value 0x%8.8x", (uint32_t)obj->Integer.Value);
> +}
> +
> +static int method_test_LID(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_LID", NULL, 0, method_test_LID_return, NULL);
> +}
> +
> +
> +/*
> + * Section 9.18 Wake Alarm Device
> + */
> +static int method_test_STP(fwts_framework *fw)
> +{
> +       ACPI_OBJECT arg[2];
> +
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;       /* DC timer */
> +       arg[1].Type = ACPI_TYPE_INTEGER;
> +       arg[1].Integer.Value = 0;       /* wake up instantly */
> +
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_STP", arg, 2, method_test_passed_failed_return, "_STP");
> +}
> +
> +static int method_test_STV(fwts_framework *fw)
> +{
> +       ACPI_OBJECT arg[2];
> +
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;       /* DC timer */
> +       arg[1].Type = ACPI_TYPE_INTEGER;
> +       arg[1].Integer.Value = 100;     /* timer value */
> +
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_STV", arg, 2, method_test_passed_failed_return, "_STV");
> +}
> +
> +static int method_test_TIP(fwts_framework *fw)
> +{
> +       ACPI_OBJECT arg[1];
> +
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;       /* DC timer */
> +
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_TIP", arg, 1, method_test_integer_return, NULL);
> +}
> +
> +static int method_test_TIV(fwts_framework *fw)
> +{
> +       ACPI_OBJECT arg[1];
> +
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;       /* DC timer */
> +
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_TIV", arg, 1, method_test_integer_return, NULL);
> +}
> +
> +
> +/*
> + * Section 10.1 Smart Battery
> + */
> +static void method_test_SBS_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
> +{
> +       static char *sbs_info[] = {
> +               "Maximum 1 Smart Battery, system manager/selector not present",
> +               "Maximum 1 Smart Battery, system manager/selector present",
> +               "Maximum 2 Smart Batteries, system manager/selector present",
> +               "Maximum 3 Smart Batteries, system manager/selector present",
> +               "Maximum 4 Smart Batteries, system manager/selector present"
> +       };
> +
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
> +               switch (obj->Integer.Value) {
> +               case 0 ... 4:
> +                       fwts_passed(fw, "_SBS correctly returned value %d %s",
> +                               (uint32_t)obj->Integer.Value,
> +                               sbs_info[obj->Integer.Value]);
> +                       break;
> +               default:
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SBSReturn", "_SBS returned %d, should be between 0 and 4.",
> +                               (uint32_t)obj->Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       fwts_advice(fw, "Smart Battery _SBS is incorrectly informing the OS about the smart battery "
> +                                       "configuration. This is a bug and needs to be fixed.");
> +                       break;
> +               }
> +       }
> +}
> +
> +static int method_test_SBS(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_SBS", NULL, 0, method_test_SBS_return, NULL);
> +}
> +
> +
> +/*
> + * Section 10.2 Battery Control Methods
> + */
> +static void method_test_BIF_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
> +{
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> +               int i;
> +               int failed = 0;
> +
> +               fwts_method_dump_object(fw, obj);
> +
> +               if (obj->Package.Count != 13) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFElementCount", "_BIF package should return 13 elements, got %d instead.",
> +                               obj->Package.Count);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +               }
> +
> +               for (i=0;(i<9) && (i<obj->Package.Count);i++) {
> +                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type DWORD Integer.", i);
> +                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                               failed++;
> +                       }
> +               }
> +               for (i=9;(i<13) && (i<obj->Package.Count);i++) {
> +                       if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type STRING.", i);
> +                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                               failed++;
> +                       }
> +               }
> +
> +               /* Sanity check each field */
> +               /* Power Unit */
> +               if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadUnits", "_BIF: Expected Power Unit (Element 0) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[0].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#ifdef FWTS_METHOD_PEDANDTIC
> +               /*
> +                * Since this information may be evaluated by communicating with
> +                * the EC we skip these checks as we can't do this from userspace
> +                */
> +               /* Design Capacity */
> +               if (obj->Package.Elements[1].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFBadCapacity", "_BIF: Design Capacity (Element 1) is unknown: 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[1].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Last Full Charge Capacity */
> +               if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFChargeCapacity", "_BIF: Last Full Charge Capacity (Element 2) is unknown: 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[2].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#endif
> +               /* Battery Technology */
> +               if (obj->Package.Elements[3].Integer.Value > 0x00000002) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBatTechUnit", "_BIF: Expected Battery Technology Unit (Element 3) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[3].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#ifdef FWTS_METHOD_PEDANDTIC
> +               /*
> +                * Since this information may be evaluated by communicating with
> +                * the EC we skip these checks as we can't do this from userspace
> +                */
> +               /* Design Voltage */
> +               if (obj->Package.Elements[4].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignVoltage", "_BIF: Design Voltage (Element 4) is unknown: 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[4].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Design capacity warning */
> +               if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE5", "_BIF: Design Capacity Warning (Element 5) is unknown: 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[5].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Design capacity low */
> +               if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE6", "_BIF: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[6].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#endif
> +               if (failed)
> +                       fwts_advice(fw, "Battery _BIF package contains errors. It is worth running the "
> +                                       "firmware test suite interactive 'battery' test to see if this "
> +                                       "is problematic.  This is a bug an needs to be fixed.");
> +               else
> +                       fwts_passed(fw, "Battery _BIF package looks sane.");
> +       }
> +}
>
> -                       arg[0].Type = ACPI_TYPE_INTEGER;
> -                       arg[0].Integer.Value = i;
> +static int method_test_BIF(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_BIF", NULL, 0, method_test_BIF_return, NULL);
> +}
>
> -                       fwts_log_info(fw, "Test _TTS(%d) Transition To State S%d.", i, i);
> +static void method_test_BIX_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
> +{
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> +               int i;
> +               int failed = 0;
>
> -                       if (method_evaluate_method(fw, METHOD_MANDITORY, "_TTS", arg, 1,
> -                                                 method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> -                               break;
> -                       fwts_log_nl(fw);
> +               fwts_method_dump_object(fw, obj);
> +
> +               if (obj->Package.Count != 16) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXElementCount", "_BIX package should return 16 elements, got %d instead.",
> +                               obj->Package.Count);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
>                 }
> +
> +               for (i=0;(i<16) && (i<obj->Package.Count);i++) {
> +                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type DWORD Integer.", i);
> +                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                               failed++;
> +                       }
> +               }
> +               for (i=16;(i<20) && (i<obj->Package.Count);i++) {
> +                       if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type STRING.", i);
> +                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                               failed++;
> +                       }
> +               }
> +
> +               /* Sanity check each field */
> +               /* Power Unit */
> +               if (obj->Package.Elements[1].Integer.Value > 0x00000002) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXPowerUnit",
> +                               "_BIX: Expected Power Unit (Element 1) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[1].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#ifdef FWTS_METHOD_PEDANDTIC
> +               /*
> +                * Since this information may be evaluated by communicating with
> +                * the EC we skip these checks as we can't do this from userspace
> +                */
> +               /* Design Capacity */
> +               if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacity",
> +                               "_BIX: Design Capacity (Element 2) is unknown: 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[2].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Last Full Charge Capacity */
> +               if (obj->Package.Elements[3].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXFullChargeCapacity",
> +                               "_BIX: Last Full Charge Capacity (Element 3) is unknown: 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[3].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#endif
> +               /* Battery Technology */
> +               if (obj->Package.Elements[4].Integer.Value > 0x00000002) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBatteryTechUnit",
> +                               "_BIX: Expected Battery Technology Unit (Element 4) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[4].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#ifdef FWTS_METHOD_PEDANDTIC
> +               /*
> +                * Since this information may be evaluated by communicating with
> +                * the EC we skip these checks as we can't do this from userspace
> +                */
> +               /* Design Voltage */
> +               if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignVoltage",
> +                               "_BIX: Design Voltage (Element 5) is unknown: 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[5].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Design capacity warning */
> +               if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE6",
> +                               "_BIX: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[6].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Design capacity low */
> +               if (obj->Package.Elements[7].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE7",
> +                                "_BIX: Design Capacity Warning (Element 7) is unknown: 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[7].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Cycle Count */
> +               if (obj->Package.Elements[10].Integer.Value > 0x7fffffff) {
> +                       fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXCyleCount",
> +                               "_BIX: Cycle Count (Element 10) is unknown: 0x%8.8x.",
> +                               (uint32_t)obj->Package.Elements[10].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +#endif
> +               if (failed)
> +                       fwts_advice(fw, "Battery _BIX package contains errors. It is worth running the "
> +                                       "firmware test suite interactive 'battery' test to see if this "
> +                                       "is problematic.  This is a bug an needs to be fixed.");
> +               else
> +                       fwts_passed(fw, "Battery _BIX package looks sane.");
>         }
> -       else {
> -               fwts_skipped(fw, "Optional control method _TTS does not exist.");
> -       }
> -       return FWTS_OK;
>  }
>
> -static void method_test_Sx_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static int method_test_BIX(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_BIX", NULL, 0, method_test_BIX_return, NULL);
> +}
> +
> +static int method_test_BMA(fwts_framework *fw)
>  {
> -       char *method = (char *)private;
> +       ACPI_OBJECT arg[1];
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;
> +
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_BMA", arg, 1, method_test_integer_return, NULL);
> +}
> +
> +static int method_test_BMS(fwts_framework *fw)
> +{
> +       ACPI_OBJECT arg[1];
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 1;
>
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_BMS", arg, 1, method_test_integer_return, NULL);
> +}
> +
> +static void method_test_BST_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
> +{
>         if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> +               int i;
> +               int failed = 0;
> +
>                 fwts_method_dump_object(fw, obj);
>
> -               if (obj->Package.Count != 3) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SElementCount", "%s should return package of 3 integers, got %d elements instead.", method,
> +               if (obj->Package.Count != 4) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTElementCount", "_BST package should return 4 elements, got %d instead.",
>                                 obj->Package.Count);
>                         fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +
> +               for (i=0;(i<4) && (i<obj->Package.Count);i++) {
> +                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadType",
> +                                       "_BST package element %d is not of type DWORD Integer.", i);
> +                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                               failed++;
> +                       }
> +               }
> +
> +               /* Sanity check each field */
> +               /* Battery State */
> +               if ((obj->Package.Elements[0].Integer.Value) > 7) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
> +                                       "_BST: Expected Battery State (Element 0) to be 0..7, got 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[0].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               }
> +               /* Ensure bits 0 (discharging) and 1 (charging) are not both set, see 10.2.2.6 */
> +               if (((obj->Package.Elements[0].Integer.Value) & 3) == 3) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
> +                                       "_BST: Battery State (Element 0) is indicating both charging "
> +                                       "and discharginng which is not allowed. Got value 0x%8.8x.",
> +                                       (uint32_t)obj->Package.Elements[0].Integer.Value);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
>                 }
> +               /* Battery Present Rate - cannot check, pulled from EC */
> +               /* Battery Remaining Capacity - cannot check, pulled from EC */
> +               /* Battery Present Voltage - cannot check, pulled from EC */
> +               if (failed)
> +                       fwts_advice(fw, "Battery _BST package contains errors. It is worth running the "
> +                                       "firmware test suite interactive 'battery' test to see if this "
> +                                       "is problematic.  This is a bug an needs to be fixed.");
> +               else
> +                       fwts_passed(fw, "Battery _BST package looks sane.");
>         }
>  }
>
> -#define method_test_Sx(name)                           \
> -static int method_test ## name(fwts_framework *fw)     \
> -{                                                      \
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, # name, NULL, 0, method_test_Sx_return, # name); \
> +static int method_test_BST(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_BST", NULL, 0, method_test_BST_return, NULL);
> +}
> +
> +static int method_test_BTP(fwts_framework *fw)
> +{
> +       static int values[] = { 0, 1, 100, 200, 0x7fffffff };
> +       int i;
> +
> +       for (i=0;i<5;i++) {
> +               ACPI_OBJECT arg[1];
> +               arg[0].Type = ACPI_TYPE_INTEGER;
> +               arg[0].Integer.Value = values[i];
> +               if (method_evaluate_method(fw, METHOD_MOBILE, "_BTP", arg, 1,
> +                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> +                       break;
> +               fwts_log_nl(fw);
> +       }
> +       return FWTS_OK;
> +}
> +
> +static void method_test_PCL_return(fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
> +{
> +       /* FIXME */
> +}
> +
> +static int method_test_PCL(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_PCL", NULL, 0, method_test_PCL_return, "_PCL");
> +}
> +
> +static int method_test_BTM(fwts_framework *fw)
> +{
> +       static int values[] = { 0, 1, 100, 200, 0x7fffffff };
> +       int i;
> +
> +       for (i=0;i<5;i++) {
> +               ACPI_OBJECT arg[1];
> +               arg[0].Type = ACPI_TYPE_INTEGER;
> +               arg[0].Integer.Value = values[i];
> +               if (method_evaluate_method(fw, METHOD_MOBILE, "_BTM", arg, 1,
> +                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> +                       break;
> +               fwts_log_nl(fw);
> +       }
> +       return FWTS_OK;
>  }
>
> -method_test_Sx(_S0)
> -method_test_Sx(_S1)
> -method_test_Sx(_S2)
> -method_test_Sx(_S3)
> -method_test_Sx(_S4)
> -method_test_Sx(_S5)
> -
> -static void method_test_WAK_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static void method_test_BMD_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
> -       uint32_t Sstate = *(uint32_t*)private;
> -       int failed = 0;
> -
>         if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> +               int i;
> +               int failed = 0;
> +
>                 fwts_method_dump_object(fw, obj);
>
> -               if (obj->Package.Count != 2) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKElementCount", "_WAK should return package of 2 integers, got %d elements instead.",
> +               if (obj->Package.Count != 5) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDElementCount", "_BMD package should return 4 elements, got %d instead.",
>                                 obj->Package.Count);
>                         fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
>                         failed++;
> -               } else {
> -                       if ((obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
> -                           (obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER))  {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBadType", "_WAK should return package of 2 integers, got %d instead.",
> -                                       obj->Package.Count);
> +               }
> +
> +               for (i=0;(i<4) && (i<obj->Package.Count);i++) {
> +                       if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDBadType", "_BMD package element %d is not of type DWORD Integer.", i);
>                                 fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
>                                 failed++;
>                         }
> -                       else {
> -                               if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
> -                                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBitField",
> -                                               "_WAK: expecting condition bit-field (element 0) of packages to be in range, got 0x%8.8x.",
> -                                               (uint32_t)obj->Package.Elements[0].Integer.Value);
> -                                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                                       failed++;
> -                               }
> -                               if (!(
> -                                   ((obj->Package.Elements[1].Integer.Value == Sstate) && (obj->Package.Elements[0].Integer.Value == 0)) ||
> -                                    ((obj->Package.Elements[1].Integer.Value == 0) && (obj->Package.Elements[0].Integer.Value != 0)) )) {
> -                                       fwts_warning(fw,
> -                                               "_WAK: expecting power supply S-state (element 1) of packages to be 0x%8.8x, got 0x%8.8x.",
> -                                               Sstate, (uint32_t)obj->Package.Elements[0].Integer.Value);
> -                                       fwts_advice(fw, "_WAK should return 0 if the wake failed and was unsuccessful (i.e. element[0] "
> -                                                       "is non-zero) OR should return the S-state. "
> -                                                       "This can confuse the operating system as this _WAK return indicates that the "
> -                                                       "S-state was not entered because of too much current being drawn from the "
> -                                                       "power supply, however, the BIOS may have actually entered this state and the "
> -                                                       "_WAK method is misinforming the operating system. Currently Linux does not "
> -                                                       "check for the return type from _WAK, so it should theoretically not affect the "
> -                                                       "operation of suspend/resume.");
> -
> -                                       failed++;
> -                               }
> -                       }
>                 }
> -               if (!failed)
> -                       fwts_passed(fw, "_WAK correctly returned sane looking package.");
> +               /* TODO: check return values */
>         }
>  }
>
> -static int method_test_WAK(fwts_framework *fw)
> +static int method_test_BMD(fwts_framework *fw)
>  {
> -       uint32_t i;
> +       return method_evaluate_method(fw, METHOD_MOBILE,
> +               "_BMD", NULL, 0, method_test_BMD_return, NULL);
> +}
>
> -       for (i=1; i<6; i++) {
> +static int method_test_BMC(fwts_framework *fw)
> +{
> +       static int values[] = { 0, 1, 2, 4 };
> +       int i;
> +
> +       for (i=0;i<4;i++) {
>                 ACPI_OBJECT arg[1];
>                 arg[0].Type = ACPI_TYPE_INTEGER;
> -               arg[0].Integer.Value = i;
> -               fwts_log_info(fw, "Test _WAK(%d) System Wake, State S%d.", i, i);
> -               if (method_evaluate_method(fw, METHOD_MANDITORY, "_WAK", arg, 1,
> -                                         method_test_WAK_return, &i) == FWTS_NOT_EXIST)
> +               arg[0].Integer.Value = values[i];
> +               if (method_evaluate_method(fw, METHOD_MOBILE, "_BMC", arg, 1,
> +                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
>                         break;
>                 fwts_log_nl(fw);
>         }
>         return FWTS_OK;
>  }
>
> -/* Section 10.3 AC Adapters and Power Sources Objects */
>
> -static void method_test_PSR_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +/*
> + * Section 10.3 AC Adapters and Power Sources Objects
> + */
> +static void method_test_PSR_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
>                 if (obj->Integer.Value > 2) {
> @@ -1090,12 +1498,17 @@ static void method_test_PSR_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>
>  static int method_test_PSR(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSR", NULL, 0, method_test_PSR_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_PSR", NULL, 0, method_test_PSR_return, NULL);
>  }
>
> -static void method_test_PIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static void method_test_PIF_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
> -
>         if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
>                 fwts_method_dump_object(fw, obj);
>
> @@ -1123,26 +1536,20 @@ static void method_test_PIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>
>  static int method_test_PIF(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PIF", NULL, 0, method_test_PIF_return, NULL);
> -}
> -
> -
> -/* Section 9.4.1 Lid control */
> -
> -static void method_test_LID_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> -{
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK)
> -               fwts_passed(fw, "_LID correctly returned sane looking value 0x%8.8x", (uint32_t)obj->Integer.Value);
> -}
> -
> -static int method_test_LID(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_LID", NULL, 0, method_test_LID_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_PIF", NULL, 0, method_test_PIF_return, NULL);
>  }
>
> -/* Section 11.3 Fan Devices */
>
> -static void method_test_FIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +/*
> + * Section 11.3 Fan Devices
> + */
> +static void method_test_FIF_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
>                 fwts_method_dump_object(fw, obj);
> @@ -1172,7 +1579,8 @@ static void method_test_FIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>
>  static int method_test_FIF(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_FIF", NULL, 0, method_test_FIF_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_FIF", NULL, 0, method_test_FIF_return, NULL);
>  }
>
>  static int method_test_FSL(fwts_framework *fw)
> @@ -1181,7 +1589,8 @@ static int method_test_FSL(fwts_framework *fw)
>         arg[0].Type = ACPI_TYPE_INTEGER;
>         arg[0].Integer.Value = 50;
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_FSL", arg, 1, method_test_NULL_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_FSL", arg, 1, method_test_NULL_return, NULL);
>  }
>
>  static void method_test_FST_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> @@ -1213,22 +1622,30 @@ static void method_test_FST_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>
>  static int method_test_FST(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_FST", NULL, 0, method_test_FST_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_FST", NULL, 0, method_test_FST_return, NULL);
>  }
>
> -/* Section 11.4 Thermal */
>
> -static void method_test_THERM_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +/*
> + * Section 11.4 Thermal
> + */
> +static void method_test_THERM_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
>                 char *method = (char*)private;
> -
> +
>                 if (fwts_acpi_region_handler_called_get()) {
>                         /*
>                          *  We accessed some memory or I/O region during the evaluation
>                          *  which returns spoofed values, so we should not test the value
>                          *  being returned. In this case, just pass this as a valid
> -                        *  return type.
> +                        *  return type.
>                          */
>                         fwts_passed(fw, "%s correctly returned sane looking return type.", name);
>                 } else {
> @@ -1267,7 +1684,8 @@ static void method_test_THERM_return(fwts_framework *fw, char *name, ACPI_BUFFER
>  static int method_test ## name(fwts_framework *fw)     \
>  {                                                      \
>         fwts_acpi_region_handler_called_set(false);     \
> -       return method_evaluate_method(fw, type, # name, NULL, 0, method_test_THERM_return, # name);     \
> +       return method_evaluate_method(fw, type, # name, \
> +               NULL, 0, method_test_THERM_return, # name);     \
>  }
>
>  method_test_THERM(_CRT, METHOD_OPTIONAL)
> @@ -1277,7 +1695,18 @@ method_test_THERM(_NTT, METHOD_OPTIONAL)
>  method_test_THERM(_PSV, METHOD_OPTIONAL)
>  method_test_THERM(_TST, METHOD_OPTIONAL)
>
> -static void method_test_TCx_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static int method_test_TSP(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_TSP", NULL, 0, method_test_polling_return, "_TSP");
> +}
> +
> +static void method_test_TCx_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
>                 char *method = (char *)private;
> @@ -1287,12 +1716,14 @@ static void method_test_TCx_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>
>  static int method_test_TC1(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_TC1", NULL, 0, method_test_TCx_return, "_TC1");
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_TC1", NULL, 0, method_test_TCx_return, "_TC1");
>  }
>
>  static int method_test_TC2(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_TC2", NULL, 0, method_test_TCx_return, "_TC1");
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_TC2", NULL, 0, method_test_TCx_return, "_TC1");
>  }
>
>  static int method_test_ACx(fwts_framework *fw)
> @@ -1302,7 +1733,8 @@ static int method_test_ACx(fwts_framework *fw)
>         for (i=0;i<10;i++) {
>                 char buffer[5];
>                 snprintf(buffer, sizeof(buffer), "AC%d", i);
> -               method_evaluate_method(fw, METHOD_OPTIONAL, buffer, NULL, 0, method_test_THERM_return, buffer);
> +               method_evaluate_method(fw, METHOD_OPTIONAL,
> +                       buffer, NULL, 0, method_test_THERM_return, buffer);
>                 fwts_log_nl(fw);
>         }
>         return FWTS_OK;
> @@ -1313,7 +1745,9 @@ static int method_test_DTI(fwts_framework *fw)
>         ACPI_OBJECT arg[1];
>         arg[0].Type = ACPI_TYPE_INTEGER;
>         arg[0].Integer.Value = 2732 + 800; /* 80 degrees C */
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DTI", arg, 1, method_test_NULL_return, NULL);
> +
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DTI", arg, 1, method_test_NULL_return, NULL);
>  }
>
>  static int method_test_SCP(fwts_framework *fw)
> @@ -1329,7 +1763,9 @@ static int method_test_SCP(fwts_framework *fw)
>                 arg[1].Integer.Value = 5;               /* Acoustic limit */
>                 arg[2].Type = ACPI_TYPE_INTEGER;
>                 arg[2].Integer.Value = 5;               /* Power limit */
> -               if (method_evaluate_method(fw, METHOD_OPTIONAL, "_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> +
> +               if (method_evaluate_method(fw, METHOD_OPTIONAL,
> +                       "_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
>                         break;
>                 fwts_log_nl(fw);
>
> @@ -1339,14 +1775,20 @@ static int method_test_SCP(fwts_framework *fw)
>                 arg[1].Integer.Value = 1;               /* Acoustic limit */
>                 arg[2].Type = ACPI_TYPE_INTEGER;
>                 arg[2].Integer.Value = 1;               /* Power limit */
> -               if (method_evaluate_method(fw, METHOD_OPTIONAL, "_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> +
> +               if (method_evaluate_method(fw, METHOD_OPTIONAL,
> +                       "_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
>                         break;
>         }
>         return FWTS_OK;
>  }
>
> -
> -static void method_test_RTV_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static void method_test_RTV_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK)
>                 fwts_passed(fw, "_RTV correctly returned sane looking value 0x%8.8x", (uint32_t)obj->Integer.Value);
> @@ -1354,7 +1796,8 @@ static void method_test_RTV_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>
>  static int method_test_RTV(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_RTV", NULL, 0, method_test_RTV_return, "_RTV");
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_RTV", NULL, 0, method_test_RTV_return, "_RTV");
>  }
>
>  static int method_test_TPT(fwts_framework *fw)
> @@ -1362,139 +1805,206 @@ static int method_test_TPT(fwts_framework *fw)
>         ACPI_OBJECT arg[1];
>         arg[0].Type = ACPI_TYPE_INTEGER;
>         arg[0].Integer.Value = 2732 + 900; /* 90 degrees C */
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_TPT", arg, 1, method_test_NULL_return, NULL);
> -}
> -
> -static void method_test_polling_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> -{
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
> -               char *method = (char *)private;
> -               if (obj->Integer.Value < 36000) {
> -                       fwts_passed(fw, "%s correctly returned sane looking value %f seconds",
> -                               method, (float)obj->Integer.Value / 10.0);
> -               } else {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodPollTimeTooLong",
> -                               "%s returned a value %f seconds > (1 hour) which is probably incorrect.",
> -                               method, (float)obj->Integer.Value / 10.0);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       fwts_advice(fw, "The method is returning a polling interval which is very long and hence "
> -                                       "most probably incorrect.");
> -               }
> -       }
> -}
>
> -static int method_test_TSP(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_TSP", NULL, 0, method_test_polling_return, "_TSP");
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_TPT", arg, 1, method_test_NULL_return, NULL);
>  }
>
>  static int method_test_TZP(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_TZP", NULL, 0, method_test_polling_return, "_TZP");
> -}
> -
> -/* Section 9.2, Ambient Light Sensor Device */
> -
> -method_test_integer(_ALC, METHOD_OPTIONAL)
> -method_test_integer(_ALI, METHOD_OPTIONAL)
> -method_test_integer(_ALT, METHOD_OPTIONAL)
> -
> -/* TODO _ALR */
> -
> -static int method_test_ALP(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_ALP", NULL, 0, method_test_polling_return, "_ALP");
> -}
> -
> -
> -/* Section 6.5 Other Objects and Control Methods */
> -
> -static int method_test_BBN(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_BBN", NULL, 0, method_test_integer_return, "_BBN");
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_TZP", NULL, 0, method_test_polling_return, "_TZP");
>  }
>
> -static int method_test_BDN(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_MOBILE, "_BDN", NULL, 0, method_test_integer_return, "_BDN");
> -}
>
> -static int method_test_DCK(fwts_framework *fw)
> +/*
> + * Section 16 Waking and Sleeping
> + */
> +static int method_test_PTS(fwts_framework *fw)
>  {
>         int i;
>
> -       for (i=0;i<=1;i++) {    /* Undock, Dock */
> +       for (i=1; i<6; i++) {
>                 ACPI_OBJECT arg[1];
> +
>                 arg[0].Type = ACPI_TYPE_INTEGER;
>                 arg[0].Integer.Value = i;
> -               if (method_evaluate_method(fw, METHOD_MOBILE, "_DCK", arg, 1, method_test_passed_failed_return, "_DCK") != FWTS_OK)
> +
> +               fwts_log_info(fw, "Test _PTS(%d).", i);
> +
> +               if (method_evaluate_method(fw, METHOD_MANDITORY, "_PTS", arg, 1,
> +                                         method_test_NULL_return, NULL) == FWTS_NOT_EXIST) {
> +                       fwts_advice(fw, "Could not find _PTS. This method provides a mechanism to "
> +                                       "do housekeeping functions, such as write sleep state to the "
> +                                       "embedded controller before entering a sleep state. If the "
> +                                       "machine cannot suspend (S3), hibernate (S4) or shutdown (S5) "
> +                                       "then it could be because _PTS is missing.");
>                         break;
> +               }
>                 fwts_log_nl(fw);
>         }
>         return FWTS_OK;
>  }
>
> -/* Section 9.18 Wake Alarm Device */
> +static int method_test_TTS(fwts_framework *fw)
> +{
> +       int i;
>
> +       if (fwts_method_exists("_BFS") != NULL) {
> +               for (i=1; i<6; i++) {
> +                       ACPI_OBJECT arg[1];
>
> -static int method_test_STP(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[2];
> +                       arg[0].Type = ACPI_TYPE_INTEGER;
> +                       arg[0].Integer.Value = i;
>
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;       /* DC timer */
> -       arg[1].Type = ACPI_TYPE_INTEGER;
> -       arg[1].Integer.Value = 0;       /* wake up instantly */
> +                       fwts_log_info(fw, "Test _TTS(%d) Transition To State S%d.", i, i);
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_STP", arg, 2, method_test_passed_failed_return, "_STP");
> +                       if (method_evaluate_method(fw, METHOD_MANDITORY, "_TTS", arg, 1,
> +                               method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
> +                               break;
> +                       fwts_log_nl(fw);
> +               }
> +       }
> +       else {
> +               fwts_skipped(fw, "Optional control method _TTS does not exist.");
> +       }
> +       return FWTS_OK;
>  }
>
> -static int method_test_STV(fwts_framework *fw)
> +static void method_test_Sx_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
> -       ACPI_OBJECT arg[2];
> +       char *method = (char *)private;
>
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;       /* DC timer */
> -       arg[1].Type = ACPI_TYPE_INTEGER;
> -       arg[1].Integer.Value = 100;     /* timer value */
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> +               fwts_method_dump_object(fw, obj);
> +
> +               if (obj->Package.Count != 3) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SElementCount", "%s should return package of 3 integers, got %d elements instead.", method,
> +                               obj->Package.Count);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +               }
> +       }
> +}
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_STV", arg, 2, method_test_passed_failed_return, "_STV");
> +#define method_test_Sx(name)                                   \
> +static int method_test ## name(fwts_framework *fw)             \
> +{                                                              \
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,      \
> +               # name, NULL, 0, method_test_Sx_return, # name);\
>  }
>
> -static int method_test_TIP(fwts_framework *fw)
> +method_test_Sx(_S0)
> +method_test_Sx(_S1)
> +method_test_Sx(_S2)
> +method_test_Sx(_S3)
> +method_test_Sx(_S4)
> +method_test_Sx(_S5)
> +
> +static void method_test_WAK_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
> -       ACPI_OBJECT arg[1];
> +       uint32_t Sstate = *(uint32_t*)private;
> +       int failed = 0;
>
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;       /* DC timer */
> +       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
> +               fwts_method_dump_object(fw, obj);
> +
> +               if (obj->Package.Count != 2) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKElementCount", "_WAK should return package of 2 integers, got %d elements instead.",
> +                               obj->Package.Count);
> +                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       failed++;
> +               } else {
> +                       if ((obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
> +                           (obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER))  {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBadType", "_WAK should return package of 2 integers, got %d instead.",
> +                                       obj->Package.Count);
> +                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                               failed++;
> +                       }
> +                       else {
> +                               if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
> +                                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBitField",
> +                                               "_WAK: expecting condition bit-field (element 0) of packages to be in range, got 0x%8.8x.",
> +                                               (uint32_t)obj->Package.Elements[0].Integer.Value);
> +                                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                                       failed++;
> +                               }
> +                               if (!(
> +                                   ((obj->Package.Elements[1].Integer.Value == Sstate) && (obj->Package.Elements[0].Integer.Value == 0)) ||
> +                                    ((obj->Package.Elements[1].Integer.Value == 0) && (obj->Package.Elements[0].Integer.Value != 0)) )) {
> +                                       fwts_warning(fw,
> +                                               "_WAK: expecting power supply S-state (element 1) of packages to be 0x%8.8x, got 0x%8.8x.",
> +                                               Sstate, (uint32_t)obj->Package.Elements[0].Integer.Value);
> +                                       fwts_advice(fw, "_WAK should return 0 if the wake failed and was unsuccessful (i.e. element[0] "
> +                                                       "is non-zero) OR should return the S-state. "
> +                                                       "This can confuse the operating system as this _WAK return indicates that the "
> +                                                       "S-state was not entered because of too much current being drawn from the "
> +                                                       "power supply, however, the BIOS may have actually entered this state and the "
> +                                                       "_WAK method is misinforming the operating system. Currently Linux does not "
> +                                                       "check for the return type from _WAK, so it should theoretically not affect the "
> +                                                       "operation of suspend/resume.");
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_TIP", arg, 1, method_test_integer_return, NULL);
> +                                       failed++;
> +                               }
> +                       }
> +               }
> +               if (!failed)
> +                       fwts_passed(fw, "_WAK correctly returned sane looking package.");
> +       }
>  }
>
> -static int method_test_TIV(fwts_framework *fw)
> +static int method_test_WAK(fwts_framework *fw)
>  {
> -       ACPI_OBJECT arg[1];
> -
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;       /* DC timer */
> +       uint32_t i;
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_TIV", arg, 1, method_test_integer_return, NULL);
> +       for (i=1; i<6; i++) {
> +               ACPI_OBJECT arg[1];
> +               arg[0].Type = ACPI_TYPE_INTEGER;
> +               arg[0].Integer.Value = i;
> +               fwts_log_info(fw, "Test _WAK(%d) System Wake, State S%d.", i, i);
> +               if (method_evaluate_method(fw, METHOD_MANDITORY, "_WAK", arg, 1,
> +                                         method_test_WAK_return, &i) == FWTS_NOT_EXIST)
> +                       break;
> +               fwts_log_nl(fw);
> +       }
> +       return FWTS_OK;
>  }
>
> -/* Appendix B, ACPI Extensions for Display Adapters */
>
> +/*
> + * Appendix B ACPI Extensions for Display Adapters
> + */
>  static int method_test_DOS(fwts_framework *fw)
>  {
>         ACPI_OBJECT arg[1];
>
>         arg[0].Type = ACPI_TYPE_INTEGER;
>         arg[0].Integer.Value = 0 << 2 | 1;
> -               /* BIOS should toggle active display, BIOS controls brightness of LCD on AC/DC power changes */
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DOS", arg, 1, method_test_NULL_return, NULL);
> +       /*
> +        * BIOS should toggle active display, BIOS controls brightness of
> +        * LCD on AC/DC power changes
> +        */
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DOS", arg, 1, method_test_NULL_return, NULL);
>  }
>
> -static void method_test_DOD_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static void method_test_DOD_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         int failed = 0;
>         static char *dod_type[] = {
> @@ -1554,10 +2064,16 @@ static void method_test_DOD_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>
>  static int method_test_DOD(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DOD", NULL, 0, method_test_DOD_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DOD", NULL, 0, method_test_DOD_return, NULL);
>  }
>
> -static void method_test_ROM_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static void method_test_ROM_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         method_check_type(fw, name, buf, ACPI_TYPE_BUFFER);
>  }
> @@ -1571,12 +2087,14 @@ static int method_test_ROM(fwts_framework *fw)
>         arg[1].Type = ACPI_TYPE_INTEGER;
>         arg[1].Integer.Value = 4096;
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_ROM", arg, 2, method_test_ROM_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_ROM", arg, 2, method_test_ROM_return, NULL);
>  }
>
>  static int method_test_GPD(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_GPD", NULL, 0, method_test_integer_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_GPD", NULL, 0, method_test_integer_return, NULL);
>  }
>
>  static int method_test_SPD(fwts_framework *fw)
> @@ -1588,7 +2106,8 @@ static int method_test_SPD(fwts_framework *fw)
>                 arg[0].Type = ACPI_TYPE_INTEGER;
>                 arg[0].Integer.Value = i;       /* bits 00..11, post device */
>
> -               if (method_evaluate_method(fw, METHOD_OPTIONAL, "_SPD", arg, 1, method_test_passed_failed_return, NULL) == FWTS_NOT_EXIST)
> +               if (method_evaluate_method(fw, METHOD_OPTIONAL,
> +                       "_SPD", arg, 1, method_test_passed_failed_return, NULL) == FWTS_NOT_EXIST)
>                         break;
>         }
>         return FWTS_OK;
> @@ -1596,15 +2115,22 @@ static int method_test_SPD(fwts_framework *fw)
>
>  static int method_test_VPO(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_VPO", NULL, 0, method_test_integer_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_VPO", NULL, 0, method_test_integer_return, NULL);
>  }
>
>  static int method_test_ADR(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_ADR", NULL, 0, method_test_integer_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_ADR", NULL, 0, method_test_integer_return, NULL);
>  }
>
> -static void method_test_BCL_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static void method_test_BCL_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
>         if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
>                 int i;
> @@ -1620,467 +2146,157 @@ static void method_test_BCL_return(fwts_framework *fw, char *name, ACPI_BUFFER *
>                         fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLNoPackage",
>                                 "Method _BCL did not return a package of %d integers.", obj->Package.Count);
>                 } else {
> -                       if (obj->Package.Count < 3) {
> -                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLElementCount",
> -                                       "Method _BCL should return a package of more than 2 integers, got just %d.", obj->Package.Count);
> -                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       } else {
> -                               bool ascending_levels = false;
> -
> -                               if (obj->Package.Elements[0].Integer.Value <
> -                                   obj->Package.Elements[1].Integer.Value) {
> -                                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLMaxLevel",
> -                                               "Brightness level when on full power (%d) is less than "
> -                                                       "brightness level when on battery power (%d).",
> -                                               (uint32_t)obj->Package.Elements[0].Integer.Value,
> -                                               (uint32_t)obj->Package.Elements[1].Integer.Value);
> -                                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                                       failed++;
> -                               }
> -
> -                               for (i=2;i<obj->Package.Count-1;i++) {
> -                                       if (obj->Package.Elements[i].Integer.Value >
> -                                           obj->Package.Elements[i+1].Integer.Value) {
> -                                               fwts_log_info(fw, "Brightness level %d (index %d) is greater than "
> -                                                       "brightness level %d (index %d), should be in ascending order.",
> -                                                       (uint32_t)obj->Package.Elements[i].Integer.Value, i,
> -                                                       (uint32_t)obj->Package.Elements[i+1].Integer.Value, i+1);
> -                                               ascending_levels = true;
> -                                               failed++;
> -                                       }
> -                               }
> -                               if (ascending_levels) {
> -                                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLAscendingOrder",
> -                                               "Some or all of the brightness level are not in ascending order which "
> -                                               "should be fixed in the firmware.");
> -                                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                               }
> -
> -                               if (failed)
> -                                       fwts_advice(fw, "Method _BCL seems to be misconfigured and is returning incorrect brightness levels."
> -                                                       "It is worth sanity checking this with the firmware test suite interactive test "
> -                                                       "'brightness' to see how broken this is. As it is, _BCL is broken and needs to be "
> -                                                       "fixed.");
> -                               else
> -                                       fwts_passed(fw, "Method _BCL returned a sane package of %d integers.", obj->Package.Count);
> -                       }
> -               }
> -       }
> -}
> -
> -static int method_test_BCL(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_BCL", NULL, 0, method_test_BCL_return, NULL);
> -}
> -
> -static int method_test_BCM(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[1];
> -
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 0;
> -
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_BCM", arg, 1, method_test_NULL_return, NULL);
> -}
> -
> -static int method_test_BQC(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_BQC", NULL, 0, method_test_integer_return, NULL);
> -}
> -
> -static void method_test_DDC_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> -{
> -       uint32_t requested = *(uint32_t*)private;
> -
> -       if (obj == NULL){
> -               fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodReturnNullObj", "Method %s returned a NULL object, and did not return a buffer or integer.", name);
> -               return;
> -       }
> -       switch (obj->Type) {
> -       case ACPI_TYPE_BUFFER:
> -               if (requested != obj->Buffer.Length) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCElementCount",
> -                               "Method _DDC returned a buffer of %d items, expected %d.",
> -                               obj->Buffer.Length, requested);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -               } else
> -                       fwts_passed(fw, "Method _DDC returned a buffer of %d items as expected.",
> -                               obj->Buffer.Length);
> -               break;
> -       case ACPI_TYPE_INTEGER:
> -                       fwts_passed(fw, "Method _DDC could not return a buffer of %d items"
> -                                       "and instead returned an error status.",
> -                               obj->Buffer.Length);
> -               break;
> -       default:
> -               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCBadReturnType",
> -                       "Method _DDC did not return a buffer or an integer.");
> -               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -               break;
> -       }
> -}
> -
> -static int method_test_DDC(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[1];
> -       uint32_t i;
> -
> -       for (i=128; i<=256; i <<= 1) {
> -               arg[0].Type = ACPI_TYPE_INTEGER;
> -               arg[0].Integer.Value = 128;
> -
> -               if (method_evaluate_method(fw, METHOD_OPTIONAL, "_DDC", arg, 1, method_test_DDC_return, &i) == FWTS_NOT_EXIST)
> -                       break;
> -       }
> -       return FWTS_OK;
> -}
> -
> -static int method_test_DCS(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DCS", NULL, 0, method_test_integer_return, NULL);
> -}
> -
> -static int method_test_DGS(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DGS", NULL, 0, method_test_integer_return, NULL);
> -}
> -
> -static int method_test_DSS(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[1];
> -
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 0;
> -
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DSS", arg, 1, method_test_NULL_return, NULL);
> -}
> -
> -/* Section 6.5 Other Objects and Controls */
> -
> -static int method_test_CRS(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_MANDITORY, "_CRS", NULL, 0, method_test_buffer_return, NULL);
> -}
> -
> -static int method_test_DMA(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DMA", NULL, 0, method_test_buffer_return, NULL);
> -}
> -
> -static int method_test_DIS(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DIS", NULL, 0, method_test_NULL_return, NULL);
> -}
> -
> -static int method_test_PXM(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PXM", NULL, 0, method_test_integer_return, NULL);
> -}
> -
> -/* Section 7.2 */
> -
> -static int method_test_DSW(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[3];
> -
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;
> -       arg[1].Type = ACPI_TYPE_INTEGER;
> -       arg[1].Integer.Value = 0;
> -       arg[2].Type = ACPI_TYPE_INTEGER;
> -       arg[2].Integer.Value = 3;
> -
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_DSW", arg, 3, method_test_NULL_return, NULL);
> -}
> -
> -#define method_test_PSx(name)                          \
> -static int method_test ## name(fwts_framework *fw)     \
> -{                                                      \
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, # name, NULL, 0, method_test_NULL_return, # name); \
> -}
> -
> -method_test_PSx(_PS0)
> -method_test_PSx(_PS1)
> -method_test_PSx(_PS2)
> -method_test_PSx(_PS3)
> -
> -static int method_test_PSC(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSC", NULL, 0, method_test_integer_return, NULL);
> -}
> -
> -static int method_test_PSE(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[1];
> -
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;
> -
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSE", arg, 1, method_test_NULL_return, NULL);
> -}
> -
> -static void method_test_PRE_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> -{
> -       int i;
> -
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
> -               return;
> -
> -       /* All elements in the package must be references */
> -       for (i=0; i < obj->Package.Count; i++) {
> -               if (obj->Package.Elements[i].Type != ACPI_TYPE_LOCAL_REFERENCE) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PREElementType",
> -                       "_PRE package element %d was not a reference.", i);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -               }
> -       }
> -}
> -
> -static int method_test_PRE(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PRE", NULL, 0, method_test_PRE_return, NULL);
> -}
> -
> -static int method_test_PSW(fwts_framework *fw)
> -{
> -       ACPI_OBJECT arg[1];
> +                       if (obj->Package.Count < 3) {
> +                               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLElementCount",
> +                                       "Method _BCL should return a package of more than 2 integers, got just %d.", obj->Package.Count);
> +                               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                       } else {
> +                               bool ascending_levels = false;
>
> -       arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;
> +                               if (obj->Package.Elements[0].Integer.Value <
> +                                   obj->Package.Elements[1].Integer.Value) {
> +                                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLMaxLevel",
> +                                               "Brightness level when on full power (%d) is less than "
> +                                                       "brightness level when on battery power (%d).",
> +                                               (uint32_t)obj->Package.Elements[0].Integer.Value,
> +                                               (uint32_t)obj->Package.Elements[1].Integer.Value);
> +                                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                                       failed++;
> +                               }
>
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSW", arg, 1, method_test_NULL_return, NULL);
> -}
> +                               for (i=2;i<obj->Package.Count-1;i++) {
> +                                       if (obj->Package.Elements[i].Integer.Value >
> +                                           obj->Package.Elements[i+1].Integer.Value) {
> +                                               fwts_log_info(fw, "Brightness level %d (index %d) is greater than "
> +                                                       "brightness level %d (index %d), should be in ascending order.",
> +                                                       (uint32_t)obj->Package.Elements[i].Integer.Value, i,
> +                                                       (uint32_t)obj->Package.Elements[i+1].Integer.Value, i+1);
> +                                               ascending_levels = true;
> +                                               failed++;
> +                                       }
> +                               }
> +                               if (ascending_levels) {
> +                                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLAscendingOrder",
> +                                               "Some or all of the brightness level are not in ascending order which "
> +                                               "should be fixed in the firmware.");
> +                                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> +                               }
>
> -static int method_test_IRC(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_IRC", NULL, 0, method_test_NULL_return, NULL);
> +                               if (failed)
> +                                       fwts_advice(fw, "Method _BCL seems to be misconfigured and is returning incorrect brightness levels."
> +                                                       "It is worth sanity checking this with the firmware test suite interactive test "
> +                                                       "'brightness' to see how broken this is. As it is, _BCL is broken and needs to be "
> +                                                       "fixed.");
> +                               else
> +                                       fwts_passed(fw, "Method _BCL returned a sane package of %d integers.", obj->Package.Count);
> +                       }
> +               }
> +       }
>  }
>
> -/* Section 6.3 */
> -
> -static int method_test_EJD(fwts_framework *fw)
> +static int method_test_BCL(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_EJD", NULL, 0, method_test_string_return, NULL);
> -}
> -
> -#define method_test_EJx(name)                          \
> -static int method_test ## name(fwts_framework *fw)     \
> -{                                                      \
> -       ACPI_OBJECT arg[1];                             \
> -                                                       \
> -       arg[0].Type = ACPI_TYPE_INTEGER;                \
> -       arg[0].Integer.Value = 1;                       \
> -                                                       \
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, # name, arg, 1, method_test_NULL_return, # name); \
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_BCL", NULL, 0, method_test_BCL_return, NULL);
>  }
>
> -method_test_EJx(_EJ0)
> -method_test_EJx(_EJ1)
> -method_test_EJx(_EJ2)
> -method_test_EJx(_EJ3)
> -method_test_EJx(_EJ4)
> -
> -static int method_test_LCK(fwts_framework *fw)
> +static int method_test_BCM(fwts_framework *fw)
>  {
>         ACPI_OBJECT arg[1];
>
>         arg[0].Type = ACPI_TYPE_INTEGER;
> -       arg[0].Integer.Value = 1;
> -
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_LCK", arg, 1, method_test_NULL_return, NULL);
> -}
> -
> -/* Section 7.1 */
> +       arg[0].Integer.Value = 0;
>
> -static int method_test_ON(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_ON", NULL, 0, method_test_NULL_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_BCM", arg, 1, method_test_NULL_return, NULL);
>  }
>
> -static int method_test_OFF(fwts_framework *fw)
> +static int method_test_BQC(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_OFF", NULL, 0, method_test_NULL_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_BQC", NULL, 0, method_test_integer_return, NULL);
>  }
>
> -/* Section 6.1 */
> -
> -static int method_test_SUN(fwts_framework *fw)
> +static void method_test_DDC_return(
> +       fwts_framework *fw,
> +       char *name,
> +       ACPI_BUFFER *buf,
> +       ACPI_OBJECT *obj,
> +       void *private)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_SUN", NULL, 0, method_test_integer_return, NULL);
> -}
> +       uint32_t requested = *(uint32_t*)private;
>
> -static void method_test_UID_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> -{
>         if (obj == NULL){
>                 fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodReturnNullObj", "Method %s returned a NULL object, and did not return a buffer or integer.", name);
>                 return;
>         }
>         switch (obj->Type) {
> -       case ACPI_TYPE_STRING:
> -               if (obj->String.Pointer)
> -                       fwts_passed(fw, "Object _UID returned a string '%s' as expected.",
> -                               obj->String.Pointer);
> -               else {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDNullString",
> -                               "Object _UID returned a NULL string.");
> +       case ACPI_TYPE_BUFFER:
> +               if (requested != obj->Buffer.Length) {
> +                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCElementCount",
> +                               "Method _DDC returned a buffer of %d items, expected %d.",
> +                               obj->Buffer.Length, requested);
>                         fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -               }
> +               } else
> +                       fwts_passed(fw, "Method _DDC returned a buffer of %d items as expected.",
> +                               obj->Buffer.Length);
>                 break;
>         case ACPI_TYPE_INTEGER:
> -               fwts_passed(fw, "Object _UID returned am integer 0x%8.8llx.",
> -                       (unsigned long long)obj->Integer.Value);
> +                       fwts_passed(fw, "Method _DDC could not return a buffer of %d items"
> +                                       "and instead returned an error status.",
> +                               obj->Buffer.Length);
>                 break;
>         default:
> -               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDBadReturnType",
> -                       "Method _UID did not return a string or an integer.");
> +               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCBadReturnType",
> +                       "Method _DDC did not return a buffer or an integer.");
>                 fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
>                 break;
>         }
>  }
>
> -static int method_test_UID(fwts_framework *fw)
> -{
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_UID", NULL, 0, method_test_UID_return, NULL);
> -}
> -
> -
> -/* Section 8.4 */
> -
> -static void method_test_PSS_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
> +static int method_test_DDC(fwts_framework *fw)
>  {
> -       int i;
> -       bool failed = false;
> -       uint32_t max_freq = 0;
> -       uint32_t prev_power = 0;
> -       bool max_freq_valid = false;
> -
> -       if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
> -               return;
> -
> -       /* Something is really wrong if we don't have any elements in _PSS */
> -       if (obj->Package.Count < 1) {
> -               fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementCount",
> -                       "_PSS should return package of at least 1 element, "
> -                       "got %d elements instead.",
> -                       obj->Package.Count);
> -               fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -               return;
> -       }
> -
> -       for (i=0; i < obj->Package.Count; i++) {
> -               ACPI_OBJECT *pstate;
> -
> -               if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementType",
> -                       "_PSS package element %d was not a package.", i);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed = true;
> -                       continue;       /* Skip processing sub-package */
> -               }
> -
> -               pstate = &obj->Package.Elements[i];
> -               if (pstate->Package.Count != 6) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementCount",
> -                               "_PSS P-State sub-package %d was expected to have "
> -                               "6 elements, got %d elements instead.",
> -                               i, obj->Package.Count);
> -                       fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
> -                       failed = true;
> -                       continue;       /* Skip processing sub-package */
> -               }
> -
> -               /* Elements need to be all ACPI integer types */
> -               if ((pstate->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
> -                   (pstate->Package.Elements[1].Type != ACPI_TYPE_INTEGER) ||
> -                   (pstate->Package.Elements[2].Type != ACPI_TYPE_INTEGER) ||
> -                   (pstate->Package.Elements[3].Type != ACPI_TYPE_INTEGER) ||
> -                   (pstate->Package.Elements[4].Type != ACPI_TYPE_INTEGER) ||
> -                   (pstate->Package.Elements[5].Type != ACPI_TYPE_INTEGER)) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementType",
> -                               "_PSS P-State sub-package %d was expected to have "
> -                               "6 Integer elements but didn't", i);
> -                       failed = true;
> -                       continue;
> -               }
> -
> -               fwts_log_info(fw, "P-State %d: CPU %ld Mhz, %lu mW, latency %lu us, bus master latency %lu us.",
> -                       i,
> -                       (unsigned long)pstate->Package.Elements[0].Integer.Value,
> -                       (unsigned long)pstate->Package.Elements[1].Integer.Value,
> -                       (unsigned long)pstate->Package.Elements[2].Integer.Value,
> -                       (unsigned long)pstate->Package.Elements[3].Integer.Value);
> -
> -               /*
> -                * Collect maximum frequency.  The sub-packages are sorted in
> -                * descending power dissipation order, so one would assume that
> -                * the highest frequency is first.  However, it is not clear
> -                * from the ACPI spec that this is necessarily an assumption we
> -                * should make, so instead we should probably scan through all
> -                * the valid sub-packages and find the highest frequency.
> -                */
> -               if (max_freq < pstate->Package.Elements[0].Integer.Value) {
> -                       max_freq = pstate->Package.Elements[0].Integer.Value;
> -                       max_freq_valid = true;
> -               }
> +       ACPI_OBJECT arg[1];
> +       uint32_t i;
>
> -               /* Sanity check descending power dissipation levels */
> -               if ((i > 0) && (prev_power != 0) &&
> -                   (pstate->Package.Elements[1].Integer.Value > prev_power)) {
> -                       fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackagePowerNotDecending",
> -                               "_PSS P-State sub-package %d has a larger power dissipation "
> -                               "setting than the previous sub-package.", i);
> -                       fwts_advice(fw, "_PSS P-States must be ordered in decending order of "
> -                               "power dissipation, so that the zero'th entry has the highest "
> -                               "power dissipation level and the Nth has the lowest.");
> -                       failed = true;
> -               }
> -               prev_power = pstate->Package.Elements[1].Integer.Value;
> -       }
> +       for (i=128; i<=256; i <<= 1) {
> +               arg[0].Type = ACPI_TYPE_INTEGER;
> +               arg[0].Integer.Value = 128;
>
> -       /*
> -        * Sanity check maximum frequency.  We could also check the DMI data
> -        * for a BIOS date (but this can be wrong) or check the CPU identity
> -        * (which requires adding in new CPU identity checks) to make a decision
> -        * on when it is reasonable to assume a CPU is modern and hence clocked
> -        * incorrectly.  For now, just flag up a low level error that the
> -        * frequency looks rather low rather than try to be intelligent (and
> -        * possibly make a mistake).  I'd rather flag up a few false positives
> -        * on older machines than miss flagging up bad _PSS settings on new
> -        * machines.
> -        */
> -       if (max_freq_valid && max_freq < 1000) {
> -               fwts_failed(fw, LOG_LEVEL_LOW, "Method_PSSSubPackageLowFreq",
> -                       "Maximum CPU frequency is %dHz and this is low for "
> -                       "a modern processor. This may indicate the _PSS P-States "
> -                       "are incorrect\n", max_freq);
> -               fwts_advice(fw,
> -                       "The _PSS P-States are used by the Linux CPU frequency "
> -                       "driver to set the CPU frequencies according to system "
> -                       "load.  Sometimes the firmware sets these incorrectly "
> -                       "and the machine runs at a sub-optimal speed.  One can "
> -                       "view the firmware defined CPU frequencies via "
> -                       "/sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies");
> -               failed = true;
> +               if (method_evaluate_method(fw, METHOD_OPTIONAL,
> +                       "_DDC", arg, 1, method_test_DDC_return, &i) == FWTS_NOT_EXIST)
> +                       break;
>         }
> -
> -       if (!failed)
> -               fwts_passed(fw, "_PSS correctly returned sane looking package.");
> +       return FWTS_OK;
>  }
>
> -static int method_test_PSS(fwts_framework *fw)
> +static int method_test_DCS(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSS", NULL, 0, method_test_PSS_return, NULL);
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DCS", NULL, 0, method_test_integer_return, NULL);
>  }
>
> -/* Section 5.6 */
> +static int method_test_DGS(fwts_framework *fw)
> +{
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DGS", NULL, 0, method_test_integer_return, NULL);
> +}
>
> -static int method_test_AEI(fwts_framework *fw)
> +static int method_test_DSS(fwts_framework *fw)
>  {
> -       return method_evaluate_method(fw, METHOD_OPTIONAL, "_AEI", NULL, 0, method_test_buffer_return, NULL);
> +       ACPI_OBJECT arg[1];
> +
> +       arg[0].Type = ACPI_TYPE_INTEGER;
> +       arg[0].Integer.Value = 0;
> +
> +       return method_evaluate_method(fw, METHOD_OPTIONAL,
> +               "_DSS", arg, 1, method_test_NULL_return, NULL);
>  }
>
> -/* Tests */
>
> +/*
> + * Tests
> + */
>  static fwts_framework_minor_test method_tests[] = {
>         { method_name_check, "Check Method Names." },
>
> --
> 1.7.10.4
>
Acked-by: Keng-Yu Lin <kengyu@canonical.com>
diff mbox

Patch

diff --git a/src/acpi/method/method.c b/src/acpi/method/method.c
index afba21f..b706a56 100644
--- a/src/acpi/method/method.c
+++ b/src/acpi/method/method.c
@@ -261,6 +261,15 @@  static int method_test ## name(fwts_framework *fw)	\
 
 typedef void (*method_test_return)(fwts_framework *fw, char *name, ACPI_BUFFER *ret_buff, ACPI_OBJECT *ret_obj, void *private);
 
+
+
+
+/*
+ * Helper functions to facilitate the evaluations
+ */
+
+/****************************************************************************/
+
 static int method_init(fwts_framework *fw)
 {
 	fwts_acpi_table_info *info;
@@ -492,591 +501,990 @@  static void method_test_passed_failed_return(fwts_framework *fw, char *name, ACP
 	}
 }
 
-/* Section 10.1.1.1 Smart Battery */
-
-static void method_test_SBS_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static void method_test_polling_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
 {
-	static char *sbs_info[] = {
-		"Maximum 1 Smart Battery, system manager/selector not present",
-		"Maximum 1 Smart Battery, system manager/selector present",
-		"Maximum 2 Smart Batteries, system manager/selector present",
-		"Maximum 3 Smart Batteries, system manager/selector present",
-		"Maximum 4 Smart Batteries, system manager/selector present"
-	};
-
 	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
-		switch (obj->Integer.Value) {
-		case 0 ... 4:
-			fwts_passed(fw, "_SBS correctly returned value %d %s",
-				(uint32_t)obj->Integer.Value,
-				sbs_info[obj->Integer.Value]);
-			break;
-		default:
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SBSReturn", "_SBS returned %d, should be between 0 and 4.",
-				(uint32_t)obj->Integer.Value);
+		char *method = (char *)private;
+		if (obj->Integer.Value < 36000) {
+			fwts_passed(fw, "%s correctly returned sane looking value %f seconds",
+				method, (float)obj->Integer.Value / 10.0);
+		} else {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodPollTimeTooLong",
+				"%s returned a value %f seconds > (1 hour) which is probably incorrect.",
+				method, (float)obj->Integer.Value / 10.0);
 			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			fwts_advice(fw, "Smart Battery _SBS is incorrectly informing the OS about the smart battery "
-					"configuration. This is a bug and needs to be fixed.");
-			break;
+			fwts_advice(fw, "The method is returning a polling interval which is very long and hence "
+					"most probably incorrect.");
 		}
 	}
 }
 
-static int method_test_SBS(fwts_framework *fw)
+/****************************************************************************/
+
+/*
+ * Section 5.6 ACPI Event Programming Model
+ */
+static int method_test_AEI(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_MOBILE, "_SBS", NULL, 0, method_test_SBS_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_AEI", NULL, 0, method_test_buffer_return, NULL);
 }
 
+/*
+ * Section 6.1 Device Identification Objects
+ */
+static int method_test_SUN(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_SUN", NULL, 0, method_test_integer_return, NULL);
+}
 
-/* Section 10.2.2 Battery Control Methods */
+static void method_test_UID_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
+	if (obj == NULL){
+		fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodReturnNullObj", "Method %s returned a NULL object, and did not return a buffer or integer.", name);
+		return;
+	}
+	switch (obj->Type) {
+	case ACPI_TYPE_STRING:
+		if (obj->String.Pointer)
+			fwts_passed(fw, "Object _UID returned a string '%s' as expected.",
+				obj->String.Pointer);
+		else {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDNullString",
+				"Object _UID returned a NULL string.");
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+		}
+		break;
+	case ACPI_TYPE_INTEGER:
+		fwts_passed(fw, "Object _UID returned am integer 0x%8.8llx.",
+			(unsigned long long)obj->Integer.Value);
+		break;
+	default:
+		fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDBadReturnType",
+			"Method _UID did not return a string or an integer.");
+		fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+		break;
+	}
+}
 
-static void method_test_BIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static int method_test_UID(fwts_framework *fw)
 {
-	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
-		int i;
-		int failed = 0;
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_UID", NULL, 0, method_test_UID_return, NULL);
+}
 
-		fwts_method_dump_object(fw, obj);
 
-		if (obj->Package.Count != 13) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFElementCount", "_BIF package should return 13 elements, got %d instead.",
-				obj->Package.Count);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-		}
+/*
+ *  Section 6.2 Device Configurations Objects
+ */
+static int method_test_CRS(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_MANDITORY,
+		"_CRS", NULL, 0, method_test_buffer_return, NULL);
+}
 
-		for (i=0;(i<9) && (i<obj->Package.Count);i++) {
-			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type DWORD Integer.", i);
-				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-				failed++;
-			}
-		}
-		for (i=9;(i<13) && (i<obj->Package.Count);i++) {
-			if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type STRING.", i);
-				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-				failed++;
-			}
-		}
+static int method_test_DMA(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DMA", NULL, 0, method_test_buffer_return, NULL);
+}
 
-		/* Sanity check each field */
-		/* Power Unit */
-		if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadUnits", "_BIF: Expected Power Unit (Element 0) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[0].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#ifdef FWTS_METHOD_PEDANDTIC
-		/*
-		 * Since this information may be evaluated by communicating with
-		 * the EC we skip these checks as we can't do this from userspace
-	 	 */
-		/* Design Capacity */
-		if (obj->Package.Elements[1].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFBadCapacity", "_BIF: Design Capacity (Element 1) is unknown: 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[1].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Last Full Charge Capacity */
-		if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFChargeCapacity", "_BIF: Last Full Charge Capacity (Element 2) is unknown: 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[2].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#endif
-		/* Battery Technology */
-		if (obj->Package.Elements[3].Integer.Value > 0x00000002) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBatTechUnit", "_BIF: Expected Battery Technology Unit (Element 3) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[3].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#ifdef FWTS_METHOD_PEDANDTIC
-		/*
-		 * Since this information may be evaluated by communicating with
-		 * the EC we skip these checks as we can't do this from userspace
-	 	 */
-		/* Design Voltage */
-		if (obj->Package.Elements[4].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignVoltage", "_BIF: Design Voltage (Element 4) is unknown: 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[4].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Design capacity warning */
-		if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE5", "_BIF: Design Capacity Warning (Element 5) is unknown: 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[5].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Design capacity low */
-		if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE6", "_BIF: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[6].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#endif
-		if (failed)
-			fwts_advice(fw, "Battery _BIF package contains errors. It is worth running the "
-					"firmware test suite interactive 'battery' test to see if this "
-					"is problematic.  This is a bug an needs to be fixed.");
-		else
-			fwts_passed(fw, "Battery _BIF package looks sane.");
-	}
+static int method_test_DIS(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DIS", NULL, 0, method_test_NULL_return, NULL);
 }
 
-static int method_test_BIF(fwts_framework *fw)
+static int method_test_PXM(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_MOBILE, "_BIF", NULL, 0, method_test_BIF_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_PXM", NULL, 0, method_test_integer_return, NULL);
 }
 
-static void method_test_BIX_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+
+/*
+ * Section 6.3 Device Insertion, Removal and Status Objects
+ */
+static int method_test_EJD(fwts_framework *fw)
 {
-	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
-		int i;
-		int failed = 0;
+	return method_evaluate_method(fw, METHOD_OPTIONAL, "_EJD", NULL, 0, method_test_string_return, NULL);
+}
 
-		fwts_method_dump_object(fw, obj);
+#define method_test_EJx(name)				\
+static int method_test ## name(fwts_framework *fw)	\
+{							\
+	ACPI_OBJECT arg[1];				\
+							\
+	arg[0].Type = ACPI_TYPE_INTEGER;		\
+	arg[0].Integer.Value = 1;			\
+							\
+	return method_evaluate_method(fw, METHOD_OPTIONAL, # name, arg, 1, method_test_NULL_return, # name); \
+}
 
-		if (obj->Package.Count != 16) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXElementCount", "_BIX package should return 16 elements, got %d instead.",
-				obj->Package.Count);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
+method_test_EJx(_EJ0)
+method_test_EJx(_EJ1)
+method_test_EJx(_EJ2)
+method_test_EJx(_EJ3)
+method_test_EJx(_EJ4)
 
-		for (i=0;(i<16) && (i<obj->Package.Count);i++) {
-			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type DWORD Integer.", i);
-				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-				failed++;
-			}
-		}
-		for (i=16;(i<20) && (i<obj->Package.Count);i++) {
-			if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type STRING.", i);
-				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-				failed++;
-			}
-		}
+static int method_test_LCK(fwts_framework *fw)
+{
+	ACPI_OBJECT arg[1];
 
-		/* Sanity check each field */
-		/* Power Unit */
-		if (obj->Package.Elements[1].Integer.Value > 0x00000002) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXPowerUnit",
-				"_BIX: Expected Power Unit (Element 1) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[1].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#ifdef FWTS_METHOD_PEDANDTIC
-		/*
-		 * Since this information may be evaluated by communicating with
-		 * the EC we skip these checks as we can't do this from userspace
-	 	 */
-		/* Design Capacity */
-		if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacity",
-				"_BIX: Design Capacity (Element 2) is unknown: 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[2].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Last Full Charge Capacity */
-		if (obj->Package.Elements[3].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXFullChargeCapacity",
-				"_BIX: Last Full Charge Capacity (Element 3) is unknown: 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[3].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#endif
-		/* Battery Technology */
-		if (obj->Package.Elements[4].Integer.Value > 0x00000002) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBatteryTechUnit",
-				"_BIX: Expected Battery Technology Unit (Element 4) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[4].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#ifdef FWTS_METHOD_PEDANDTIC
-		/*
-		 * Since this information may be evaluated by communicating with
-		 * the EC we skip these checks as we can't do this from userspace
-	 	 */
-		/* Design Voltage */
-		if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignVoltage",
-				"_BIX: Design Voltage (Element 5) is unknown: 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[5].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Design capacity warning */
-		if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE6",
-				"_BIX: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[6].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Design capacity low */
-		if (obj->Package.Elements[7].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE7",
-				 "_BIX: Design Capacity Warning (Element 7) is unknown: 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[7].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Cycle Count */
-		if (obj->Package.Elements[10].Integer.Value > 0x7fffffff) {
-			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXCyleCount",
-				"_BIX: Cycle Count (Element 10) is unknown: 0x%8.8x.",
-				(uint32_t)obj->Package.Elements[10].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-#endif
-		if (failed)
-			fwts_advice(fw, "Battery _BIX package contains errors. It is worth running the "
-					"firmware test suite interactive 'battery' test to see if this "
-					"is problematic.  This is a bug an needs to be fixed.");
-		else
-			fwts_passed(fw, "Battery _BIX package looks sane.");
-	}
-}
-
-static int method_test_BIX(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_MOBILE, "_BIX", NULL, 0, method_test_BIX_return, NULL);
-}
-
-static int method_test_BMA(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[1];
 	arg[0].Type = ACPI_TYPE_INTEGER;
 	arg[0].Integer.Value = 1;
-	return method_evaluate_method(fw, METHOD_MOBILE, "_BMA", arg, 1, method_test_integer_return, NULL);
-}
 
-static int method_test_BMS(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[1];
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;
-	return method_evaluate_method(fw, METHOD_MOBILE, "_BMS", arg, 1, method_test_integer_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL, "_LCK", arg, 1, method_test_NULL_return, NULL);
 }
 
-static void method_test_BST_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
-{
-	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
-		int i;
-		int failed = 0;
-
-		fwts_method_dump_object(fw, obj);
-
-		if (obj->Package.Count != 4) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTElementCount", "_BST package should return 4 elements, got %d instead.",
-				obj->Package.Count);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-
-		for (i=0;(i<4) && (i<obj->Package.Count);i++) {
-			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadType",
-					"_BST package element %d is not of type DWORD Integer.", i);
-				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-				failed++;
-			}
-		}
 
-		/* Sanity check each field */
-		/* Battery State */
-		if ((obj->Package.Elements[0].Integer.Value) > 7) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
-					"_BST: Expected Battery State (Element 0) to be 0..7, got 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[0].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Ensure bits 0 (discharging) and 1 (charging) are not both set, see 10.2.2.6 */
-		if (((obj->Package.Elements[0].Integer.Value) & 3) == 3) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
-					"_BST: Battery State (Element 0) is indicating both charging "
-					"and discharginng which is not allowed. Got value 0x%8.8x.",
-					(uint32_t)obj->Package.Elements[0].Integer.Value);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
-		/* Battery Present Rate - cannot check, pulled from EC */
-		/* Battery Remaining Capacity - cannot check, pulled from EC */
-		/* Battery Present Voltage - cannot check, pulled from EC */
-		if (failed)
-			fwts_advice(fw, "Battery _BST package contains errors. It is worth running the "
-					"firmware test suite interactive 'battery' test to see if this "
-					"is problematic.  This is a bug an needs to be fixed.");
-		else
-			fwts_passed(fw, "Battery _BST package looks sane.");
-	}
+/*
+ * Section 6.5 Other Objects and Controls
+ */
+static int method_test_BBN(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL, "_BBN",
+		NULL, 0, method_test_integer_return, "_BBN");
 }
 
-static int method_test_BST(fwts_framework *fw)
+static int method_test_BDN(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_MOBILE, "_BST", NULL, 0, method_test_BST_return, NULL);
+	return method_evaluate_method(fw, METHOD_MOBILE, "_BDN",
+		NULL, 0, method_test_integer_return, "_BDN");
 }
 
-static int method_test_BTP(fwts_framework *fw)
+static int method_test_DCK(fwts_framework *fw)
 {
-	static int values[] = { 0, 1, 100, 200, 0x7fffffff };
 	int i;
 
-	for (i=0;i<5;i++) {
+	for (i=0;i<=1;i++) {	/* Undock, Dock */
 		ACPI_OBJECT arg[1];
 		arg[0].Type = ACPI_TYPE_INTEGER;
-		arg[0].Integer.Value = values[i];
-		if (method_evaluate_method(fw, METHOD_MOBILE, "_BTP", arg, 1,
-					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
+		arg[0].Integer.Value = i;
+		if (method_evaluate_method(fw, METHOD_MOBILE, "_DCK", arg, 1, method_test_passed_failed_return, "_DCK") != FWTS_OK)
 			break;
 		fwts_log_nl(fw);
 	}
 	return FWTS_OK;
 }
 
-static void method_test_PCL_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
-{
-	/* FIXME */
-}
 
-static int method_test_PCL(fwts_framework *fw)
+/*
+ * Section 7.1 Declaring a Power Resource Object
+ */
+static int method_test_ON(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_MOBILE, "_PCL", NULL, 0, method_test_PCL_return, "_PCL");
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_ON", NULL, 0, method_test_NULL_return, NULL);
 }
 
-static int method_test_BTM(fwts_framework *fw)
+static int method_test_OFF(fwts_framework *fw)
 {
-	static int values[] = { 0, 1, 100, 200, 0x7fffffff };
-	int i;
-
-	for (i=0;i<5;i++) {
-		ACPI_OBJECT arg[1];
-		arg[0].Type = ACPI_TYPE_INTEGER;
-		arg[0].Integer.Value = values[i];
-		if (method_evaluate_method(fw, METHOD_MOBILE, "_BTM", arg, 1,
-					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
-			break;
-		fwts_log_nl(fw);
-	}
-	return FWTS_OK;
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_OFF", NULL, 0, method_test_NULL_return, NULL);
 }
 
-static void method_test_BMD_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+
+/*
+ * Section 7.2  Device Power Management Objects
+ */
+static int method_test_DSW(fwts_framework *fw)
 {
-	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
-		int i;
-		int failed = 0;
+	ACPI_OBJECT arg[3];
 
-		fwts_method_dump_object(fw, obj);
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;
+	arg[1].Type = ACPI_TYPE_INTEGER;
+	arg[1].Integer.Value = 0;
+	arg[2].Type = ACPI_TYPE_INTEGER;
+	arg[2].Integer.Value = 3;
 
-		if (obj->Package.Count != 5) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDElementCount", "_BMD package should return 4 elements, got %d instead.",
-				obj->Package.Count);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed++;
-		}
+	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DSW",
+		arg, 3, method_test_NULL_return, NULL);
+}
 
-		for (i=0;(i<4) && (i<obj->Package.Count);i++) {
-			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDBadType", "_BMD package element %d is not of type DWORD Integer.", i);
-				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-				failed++;
-			}
-		}
-		/* TODO: check return values */
-	}
+#define method_test_PSx(name)						\
+static int method_test ## name(fwts_framework *fw)			\
+{									\
+	return method_evaluate_method(fw, METHOD_OPTIONAL,		\
+		# name, NULL, 0, method_test_NULL_return, # name);	\
 }
 
-static int method_test_BMD(fwts_framework *fw)
+method_test_PSx(_PS0)
+method_test_PSx(_PS1)
+method_test_PSx(_PS2)
+method_test_PSx(_PS3)
+
+static int method_test_PSC(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_MOBILE, "_BMD", NULL, 0, method_test_BMD_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_PSC", NULL, 0, method_test_integer_return, NULL);
 }
 
-static int method_test_BMC(fwts_framework *fw)
+static int method_test_PSE(fwts_framework *fw)
 {
-	static int values[] = { 0, 1, 2, 4 };
-	int i;
+	ACPI_OBJECT arg[1];
 
-	for (i=0;i<4;i++) {
-		ACPI_OBJECT arg[1];
-		arg[0].Type = ACPI_TYPE_INTEGER;
-		arg[0].Integer.Value = values[i];
-		if (method_evaluate_method(fw, METHOD_MOBILE, "_BMC", arg, 1,
-					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
-			break;
-		fwts_log_nl(fw);
-	}
-	return FWTS_OK;
-}
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;
 
-/* Section 15, Waking and Sleeping */
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_PSE", arg, 1, method_test_NULL_return, NULL);
+}
 
-static int method_test_PTS(fwts_framework *fw)
+static void method_test_PRE_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	int i;
 
-	for (i=1; i<6; i++) {
-		ACPI_OBJECT arg[1];
-
-		arg[0].Type = ACPI_TYPE_INTEGER;
-		arg[0].Integer.Value = i;
-
-		fwts_log_info(fw, "Test _PTS(%d).", i);
+	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
+		return;
 
-		if (method_evaluate_method(fw, METHOD_MANDITORY, "_PTS", arg, 1,
-					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST) {
-			fwts_advice(fw, "Could not find _PTS. This method provides a mechanism to "
-					"do housekeeping functions, such as write sleep state to the "
-					"embedded controller before entering a sleep state. If the "
-					"machine cannot suspend (S3), hibernate (S4) or shutdown (S5) "
-					"then it could be because _PTS is missing.");
-			break;
+	/* All elements in the package must be references */
+	for (i=0; i < obj->Package.Count; i++) {
+		if (obj->Package.Elements[i].Type != ACPI_TYPE_LOCAL_REFERENCE) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PREElementType",
+			"_PRE package element %d was not a reference.", i);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
 		}
-		fwts_log_nl(fw);
 	}
-	return FWTS_OK;
 }
 
-static int method_test_TTS(fwts_framework *fw)
+static int method_test_PRE(fwts_framework *fw)
 {
-	int i;
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_PRE", NULL, 0, method_test_PRE_return, NULL);
+}
 
-	if (fwts_method_exists("_BFS") != NULL) {
-		for (i=1; i<6; i++) {
-			ACPI_OBJECT arg[1];
+static int method_test_PSW(fwts_framework *fw)
+{
+	ACPI_OBJECT arg[1];
+
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;
+
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_PSW", arg, 1, method_test_NULL_return, NULL);
+}
+
+static int method_test_IRC(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_IRC", NULL, 0, method_test_NULL_return, NULL);
+}
+
+
+/*
+ * Section 8.4 Declaring Processors
+ */
+static void method_test_PSS_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
+	int i;
+	bool failed = false;
+	uint32_t max_freq = 0;
+	uint32_t prev_power = 0;
+	bool max_freq_valid = false;
+
+	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
+		return;
+
+	/* Something is really wrong if we don't have any elements in _PSS */
+	if (obj->Package.Count < 1) {
+		fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementCount",
+			"_PSS should return package of at least 1 element, "
+			"got %d elements instead.",
+			obj->Package.Count);
+		fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+		return;
+	}
+
+	for (i=0; i < obj->Package.Count; i++) {
+		ACPI_OBJECT *pstate;
+
+		if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementType",
+			"_PSS package element %d was not a package.", i);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed = true;
+			continue;	/* Skip processing sub-package */
+		}
+
+		pstate = &obj->Package.Elements[i];
+		if (pstate->Package.Count != 6) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementCount",
+				"_PSS P-State sub-package %d was expected to have "
+				"6 elements, got %d elements instead.",
+				i, obj->Package.Count);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed = true;
+			continue;	/* Skip processing sub-package */
+		}
+
+		/* Elements need to be all ACPI integer types */
+		if ((pstate->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
+		    (pstate->Package.Elements[1].Type != ACPI_TYPE_INTEGER) ||
+		    (pstate->Package.Elements[2].Type != ACPI_TYPE_INTEGER) ||
+		    (pstate->Package.Elements[3].Type != ACPI_TYPE_INTEGER) ||
+		    (pstate->Package.Elements[4].Type != ACPI_TYPE_INTEGER) ||
+		    (pstate->Package.Elements[5].Type != ACPI_TYPE_INTEGER)) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementType",
+				"_PSS P-State sub-package %d was expected to have "
+				"6 Integer elements but didn't", i);
+			failed = true;
+			continue;
+		}
+
+		fwts_log_info(fw, "P-State %d: CPU %ld Mhz, %lu mW, latency %lu us, bus master latency %lu us.",
+			i,
+			(unsigned long)pstate->Package.Elements[0].Integer.Value,
+			(unsigned long)pstate->Package.Elements[1].Integer.Value,
+			(unsigned long)pstate->Package.Elements[2].Integer.Value,
+			(unsigned long)pstate->Package.Elements[3].Integer.Value);
+
+		/*
+		 * Collect maximum frequency.  The sub-packages are sorted in
+		 * descending power dissipation order, so one would assume that
+		 * the highest frequency is first.  However, it is not clear
+		 * from the ACPI spec that this is necessarily an assumption we
+		 * should make, so instead we should probably scan through all
+		 * the valid sub-packages and find the highest frequency.
+		 */
+		if (max_freq < pstate->Package.Elements[0].Integer.Value) {
+			max_freq = pstate->Package.Elements[0].Integer.Value;
+			max_freq_valid = true;
+		}
+
+		/* Sanity check descending power dissipation levels */
+		if ((i > 0) && (prev_power != 0) &&
+		    (pstate->Package.Elements[1].Integer.Value > prev_power)) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackagePowerNotDecending",
+				"_PSS P-State sub-package %d has a larger power dissipation "
+				"setting than the previous sub-package.", i);
+			fwts_advice(fw, "_PSS P-States must be ordered in decending order of "
+				"power dissipation, so that the zero'th entry has the highest "
+				"power dissipation level and the Nth has the lowest.");
+			failed = true;
+		}
+		prev_power = pstate->Package.Elements[1].Integer.Value;
+	}
+
+	/*
+	 * Sanity check maximum frequency.  We could also check the DMI data
+	 * for a BIOS date (but this can be wrong) or check the CPU identity
+	 * (which requires adding in new CPU identity checks) to make a decision
+	 * on when it is reasonable to assume a CPU is modern and hence clocked
+	 * incorrectly.  For now, just flag up a low level error that the
+	 * frequency looks rather low rather than try to be intelligent (and
+	 * possibly make a mistake).  I'd rather flag up a few false positives
+	 * on older machines than miss flagging up bad _PSS settings on new
+	 * machines.
+	 */
+	if (max_freq_valid && max_freq < 1000) {
+		fwts_failed(fw, LOG_LEVEL_LOW, "Method_PSSSubPackageLowFreq",
+			"Maximum CPU frequency is %dHz and this is low for "
+			"a modern processor. This may indicate the _PSS P-States "
+			"are incorrect\n", max_freq);
+		fwts_advice(fw,
+			"The _PSS P-States are used by the Linux CPU frequency "
+			"driver to set the CPU frequencies according to system "
+			"load.  Sometimes the firmware sets these incorrectly "
+			"and the machine runs at a sub-optimal speed.  One can "
+			"view the firmware defined CPU frequencies via "
+			"/sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies");
+		failed = true;
+	}
+
+	if (!failed)
+		fwts_passed(fw, "_PSS correctly returned sane looking package.");
+}
+
+static int method_test_PSS(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSS", NULL, 0, method_test_PSS_return, NULL);
+}
+
+
+/*
+ * Section 9.2 Ambient Light Sensor Device
+ */
+method_test_integer(_ALC, METHOD_OPTIONAL)
+method_test_integer(_ALI, METHOD_OPTIONAL)
+method_test_integer(_ALT, METHOD_OPTIONAL)
+
+/* TODO _ALR */
+
+static int method_test_ALP(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_ALP", NULL, 0, method_test_polling_return, "_ALP");
+}
+
+
+/*
+ * Section 9.4 Lid control
+ */
+static void method_test_LID_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+{
+	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK)
+		fwts_passed(fw, "_LID correctly returned sane looking value 0x%8.8x", (uint32_t)obj->Integer.Value);
+}
+
+static int method_test_LID(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_LID", NULL, 0, method_test_LID_return, NULL);
+}
+
+
+/*
+ * Section 9.18 Wake Alarm Device
+ */
+static int method_test_STP(fwts_framework *fw)
+{
+	ACPI_OBJECT arg[2];
+
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;	/* DC timer */
+	arg[1].Type = ACPI_TYPE_INTEGER;
+	arg[1].Integer.Value = 0;	/* wake up instantly */
+
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_STP", arg, 2, method_test_passed_failed_return, "_STP");
+}
+
+static int method_test_STV(fwts_framework *fw)
+{
+	ACPI_OBJECT arg[2];
+
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;	/* DC timer */
+	arg[1].Type = ACPI_TYPE_INTEGER;
+	arg[1].Integer.Value = 100;	/* timer value */
+
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_STV", arg, 2, method_test_passed_failed_return, "_STV");
+}
+
+static int method_test_TIP(fwts_framework *fw)
+{
+	ACPI_OBJECT arg[1];
+
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;	/* DC timer */
+
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_TIP", arg, 1, method_test_integer_return, NULL);
+}
+
+static int method_test_TIV(fwts_framework *fw)
+{
+	ACPI_OBJECT arg[1];
+
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;	/* DC timer */
+
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_TIV", arg, 1, method_test_integer_return, NULL);
+}
+
+
+/*
+ * Section 10.1 Smart Battery
+ */
+static void method_test_SBS_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
+	static char *sbs_info[] = {
+		"Maximum 1 Smart Battery, system manager/selector not present",
+		"Maximum 1 Smart Battery, system manager/selector present",
+		"Maximum 2 Smart Batteries, system manager/selector present",
+		"Maximum 3 Smart Batteries, system manager/selector present",
+		"Maximum 4 Smart Batteries, system manager/selector present"
+	};
+
+	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
+		switch (obj->Integer.Value) {
+		case 0 ... 4:
+			fwts_passed(fw, "_SBS correctly returned value %d %s",
+				(uint32_t)obj->Integer.Value,
+				sbs_info[obj->Integer.Value]);
+			break;
+		default:
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SBSReturn", "_SBS returned %d, should be between 0 and 4.",
+				(uint32_t)obj->Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			fwts_advice(fw, "Smart Battery _SBS is incorrectly informing the OS about the smart battery "
+					"configuration. This is a bug and needs to be fixed.");
+			break;
+		}
+	}
+}
+
+static int method_test_SBS(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_SBS", NULL, 0, method_test_SBS_return, NULL);
+}
+
+
+/*
+ * Section 10.2 Battery Control Methods
+ */
+static void method_test_BIF_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
+	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
+		int i;
+		int failed = 0;
+
+		fwts_method_dump_object(fw, obj);
+
+		if (obj->Package.Count != 13) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFElementCount", "_BIF package should return 13 elements, got %d instead.",
+				obj->Package.Count);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+		}
+
+		for (i=0;(i<9) && (i<obj->Package.Count);i++) {
+			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type DWORD Integer.", i);
+				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+				failed++;
+			}
+		}
+		for (i=9;(i<13) && (i<obj->Package.Count);i++) {
+			if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadType", "_BIF package element %d is not of type STRING.", i);
+				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+				failed++;
+			}
+		}
+
+		/* Sanity check each field */
+		/* Power Unit */
+		if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBadUnits", "_BIF: Expected Power Unit (Element 0) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[0].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#ifdef FWTS_METHOD_PEDANDTIC
+		/*
+		 * Since this information may be evaluated by communicating with
+		 * the EC we skip these checks as we can't do this from userspace
+	 	 */
+		/* Design Capacity */
+		if (obj->Package.Elements[1].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFBadCapacity", "_BIF: Design Capacity (Element 1) is unknown: 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[1].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Last Full Charge Capacity */
+		if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFChargeCapacity", "_BIF: Last Full Charge Capacity (Element 2) is unknown: 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[2].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#endif
+		/* Battery Technology */
+		if (obj->Package.Elements[3].Integer.Value > 0x00000002) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIFBatTechUnit", "_BIF: Expected Battery Technology Unit (Element 3) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[3].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#ifdef FWTS_METHOD_PEDANDTIC
+		/*
+		 * Since this information may be evaluated by communicating with
+		 * the EC we skip these checks as we can't do this from userspace
+	 	 */
+		/* Design Voltage */
+		if (obj->Package.Elements[4].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignVoltage", "_BIF: Design Voltage (Element 4) is unknown: 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[4].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Design capacity warning */
+		if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE5", "_BIF: Design Capacity Warning (Element 5) is unknown: 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[5].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Design capacity low */
+		if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIFDesignCapacityE6", "_BIF: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[6].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#endif
+		if (failed)
+			fwts_advice(fw, "Battery _BIF package contains errors. It is worth running the "
+					"firmware test suite interactive 'battery' test to see if this "
+					"is problematic.  This is a bug an needs to be fixed.");
+		else
+			fwts_passed(fw, "Battery _BIF package looks sane.");
+	}
+}
 
-			arg[0].Type = ACPI_TYPE_INTEGER;
-			arg[0].Integer.Value = i;
+static int method_test_BIF(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_BIF", NULL, 0, method_test_BIF_return, NULL);
+}
 
-			fwts_log_info(fw, "Test _TTS(%d) Transition To State S%d.", i, i);
+static void method_test_BIX_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
+	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
+		int i;
+		int failed = 0;
 
-			if (method_evaluate_method(fw, METHOD_MANDITORY, "_TTS", arg, 1,
-						  method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
-				break;
-			fwts_log_nl(fw);
+		fwts_method_dump_object(fw, obj);
+
+		if (obj->Package.Count != 16) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXElementCount", "_BIX package should return 16 elements, got %d instead.",
+				obj->Package.Count);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
 		}
+
+		for (i=0;(i<16) && (i<obj->Package.Count);i++) {
+			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type DWORD Integer.", i);
+				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+				failed++;
+			}
+		}
+		for (i=16;(i<20) && (i<obj->Package.Count);i++) {
+			if (obj->Package.Elements[i].Type != ACPI_TYPE_STRING) {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBadType", "_BIX package element %d is not of type STRING.", i);
+				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+				failed++;
+			}
+		}
+
+		/* Sanity check each field */
+		/* Power Unit */
+		if (obj->Package.Elements[1].Integer.Value > 0x00000002) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXPowerUnit",
+				"_BIX: Expected Power Unit (Element 1) to be 0 (mWh) or 1 (mAh), got 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[1].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#ifdef FWTS_METHOD_PEDANDTIC
+		/*
+		 * Since this information may be evaluated by communicating with
+		 * the EC we skip these checks as we can't do this from userspace
+	 	 */
+		/* Design Capacity */
+		if (obj->Package.Elements[2].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacity",
+				"_BIX: Design Capacity (Element 2) is unknown: 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[2].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Last Full Charge Capacity */
+		if (obj->Package.Elements[3].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXFullChargeCapacity",
+				"_BIX: Last Full Charge Capacity (Element 3) is unknown: 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[3].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#endif
+		/* Battery Technology */
+		if (obj->Package.Elements[4].Integer.Value > 0x00000002) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BIXBatteryTechUnit",
+				"_BIX: Expected Battery Technology Unit (Element 4) to be 0 (Primary) or 1 (Secondary), got 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[4].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#ifdef FWTS_METHOD_PEDANDTIC
+		/*
+		 * Since this information may be evaluated by communicating with
+		 * the EC we skip these checks as we can't do this from userspace
+	 	 */
+		/* Design Voltage */
+		if (obj->Package.Elements[5].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignVoltage",
+				"_BIX: Design Voltage (Element 5) is unknown: 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[5].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Design capacity warning */
+		if (obj->Package.Elements[6].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE6",
+				"_BIX: Design Capacity Warning (Element 6) is unknown: 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[6].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Design capacity low */
+		if (obj->Package.Elements[7].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXDesignCapacityE7",
+				 "_BIX: Design Capacity Warning (Element 7) is unknown: 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[7].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Cycle Count */
+		if (obj->Package.Elements[10].Integer.Value > 0x7fffffff) {
+			fwts_failed(fw, LOG_LEVEL_LOW, "Method_BIXCyleCount",
+				"_BIX: Cycle Count (Element 10) is unknown: 0x%8.8x.",
+				(uint32_t)obj->Package.Elements[10].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+#endif
+		if (failed)
+			fwts_advice(fw, "Battery _BIX package contains errors. It is worth running the "
+					"firmware test suite interactive 'battery' test to see if this "
+					"is problematic.  This is a bug an needs to be fixed.");
+		else
+			fwts_passed(fw, "Battery _BIX package looks sane.");
 	}
-	else {
-		fwts_skipped(fw, "Optional control method _TTS does not exist.");
-	}
-	return FWTS_OK;
 }
 
-static void method_test_Sx_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static int method_test_BIX(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_BIX", NULL, 0, method_test_BIX_return, NULL);
+}
+
+static int method_test_BMA(fwts_framework *fw)
 {
-	char *method = (char *)private;
+	ACPI_OBJECT arg[1];
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;
+
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_BMA", arg, 1, method_test_integer_return, NULL);
+}
+
+static int method_test_BMS(fwts_framework *fw)
+{
+	ACPI_OBJECT arg[1];
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 1;
 
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_BMS", arg, 1, method_test_integer_return, NULL);
+}
+
+static void method_test_BST_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
 	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
+		int i;
+		int failed = 0;
+
 		fwts_method_dump_object(fw, obj);
 
-		if (obj->Package.Count != 3) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SElementCount", "%s should return package of 3 integers, got %d elements instead.", method,
+		if (obj->Package.Count != 4) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTElementCount", "_BST package should return 4 elements, got %d instead.",
 				obj->Package.Count);
 			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+
+		for (i=0;(i<4) && (i<obj->Package.Count);i++) {
+			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadType",
+					"_BST package element %d is not of type DWORD Integer.", i);
+				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+				failed++;
+			}
+		}
+
+		/* Sanity check each field */
+		/* Battery State */
+		if ((obj->Package.Elements[0].Integer.Value) > 7) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
+					"_BST: Expected Battery State (Element 0) to be 0..7, got 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[0].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		}
+		/* Ensure bits 0 (discharging) and 1 (charging) are not both set, see 10.2.2.6 */
+		if (((obj->Package.Elements[0].Integer.Value) & 3) == 3) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BSTBadState",
+					"_BST: Battery State (Element 0) is indicating both charging "
+					"and discharginng which is not allowed. Got value 0x%8.8x.",
+					(uint32_t)obj->Package.Elements[0].Integer.Value);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
 		}
+		/* Battery Present Rate - cannot check, pulled from EC */
+		/* Battery Remaining Capacity - cannot check, pulled from EC */
+		/* Battery Present Voltage - cannot check, pulled from EC */
+		if (failed)
+			fwts_advice(fw, "Battery _BST package contains errors. It is worth running the "
+					"firmware test suite interactive 'battery' test to see if this "
+					"is problematic.  This is a bug an needs to be fixed.");
+		else
+			fwts_passed(fw, "Battery _BST package looks sane.");
 	}
 }
 
-#define method_test_Sx(name)				\
-static int method_test ## name(fwts_framework *fw)	\
-{							\
-	return method_evaluate_method(fw, METHOD_OPTIONAL, # name, NULL, 0, method_test_Sx_return, # name); \
+static int method_test_BST(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_BST", NULL, 0, method_test_BST_return, NULL);
+}
+
+static int method_test_BTP(fwts_framework *fw)
+{
+	static int values[] = { 0, 1, 100, 200, 0x7fffffff };
+	int i;
+
+	for (i=0;i<5;i++) {
+		ACPI_OBJECT arg[1];
+		arg[0].Type = ACPI_TYPE_INTEGER;
+		arg[0].Integer.Value = values[i];
+		if (method_evaluate_method(fw, METHOD_MOBILE, "_BTP", arg, 1,
+					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
+			break;
+		fwts_log_nl(fw);
+	}
+	return FWTS_OK;
+}
+
+static void method_test_PCL_return(fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
+{
+	/* FIXME */
+}
+
+static int method_test_PCL(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_PCL", NULL, 0, method_test_PCL_return, "_PCL");
+}
+
+static int method_test_BTM(fwts_framework *fw)
+{
+	static int values[] = { 0, 1, 100, 200, 0x7fffffff };
+	int i;
+
+	for (i=0;i<5;i++) {
+		ACPI_OBJECT arg[1];
+		arg[0].Type = ACPI_TYPE_INTEGER;
+		arg[0].Integer.Value = values[i];
+		if (method_evaluate_method(fw, METHOD_MOBILE, "_BTM", arg, 1,
+					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
+			break;
+		fwts_log_nl(fw);
+	}
+	return FWTS_OK;
 }
 
-method_test_Sx(_S0)
-method_test_Sx(_S1)
-method_test_Sx(_S2)
-method_test_Sx(_S3)
-method_test_Sx(_S4)
-method_test_Sx(_S5)
-
-static void method_test_WAK_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static void method_test_BMD_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
-	uint32_t Sstate = *(uint32_t*)private;
-	int failed = 0;
-
 	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
+		int i;
+		int failed = 0;
+
 		fwts_method_dump_object(fw, obj);
 
-		if (obj->Package.Count != 2) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKElementCount", "_WAK should return package of 2 integers, got %d elements instead.",
+		if (obj->Package.Count != 5) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDElementCount", "_BMD package should return 4 elements, got %d instead.",
 				obj->Package.Count);
 			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
 			failed++;
-		} else {
-			if ((obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
-			    (obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER))  {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBadType", "_WAK should return package of 2 integers, got %d instead.",
-					obj->Package.Count);
+		}
+
+		for (i=0;(i<4) && (i<obj->Package.Count);i++) {
+			if (obj->Package.Elements[i].Type != ACPI_TYPE_INTEGER) {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BMDBadType", "_BMD package element %d is not of type DWORD Integer.", i);
 				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
 				failed++;
 			}
-			else {
-				if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
-					fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBitField",
-						"_WAK: expecting condition bit-field (element 0) of packages to be in range, got 0x%8.8x.",
-						(uint32_t)obj->Package.Elements[0].Integer.Value);
-					fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-					failed++;
-				}
-				if (!(
-				    ((obj->Package.Elements[1].Integer.Value == Sstate) && (obj->Package.Elements[0].Integer.Value == 0)) ||
-                                    ((obj->Package.Elements[1].Integer.Value == 0) && (obj->Package.Elements[0].Integer.Value != 0)) )) {
-					fwts_warning(fw,
-						"_WAK: expecting power supply S-state (element 1) of packages to be 0x%8.8x, got 0x%8.8x.",
-						Sstate, (uint32_t)obj->Package.Elements[0].Integer.Value);
-					fwts_advice(fw, "_WAK should return 0 if the wake failed and was unsuccessful (i.e. element[0] "
-							"is non-zero) OR should return the S-state. "
-							"This can confuse the operating system as this _WAK return indicates that the "
-							"S-state was not entered because of too much current being drawn from the "
-							"power supply, however, the BIOS may have actually entered this state and the "
-							"_WAK method is misinforming the operating system. Currently Linux does not "
-							"check for the return type from _WAK, so it should theoretically not affect the "
-							"operation of suspend/resume.");
-
-					failed++;
-				}
-			}
 		}
-		if (!failed)
-			fwts_passed(fw, "_WAK correctly returned sane looking package.");
+		/* TODO: check return values */
 	}
 }
 
-static int method_test_WAK(fwts_framework *fw)
+static int method_test_BMD(fwts_framework *fw)
 {
-	uint32_t i;
+	return method_evaluate_method(fw, METHOD_MOBILE,
+		"_BMD", NULL, 0, method_test_BMD_return, NULL);
+}
 
-	for (i=1; i<6; i++) {
+static int method_test_BMC(fwts_framework *fw)
+{
+	static int values[] = { 0, 1, 2, 4 };
+	int i;
+
+	for (i=0;i<4;i++) {
 		ACPI_OBJECT arg[1];
 		arg[0].Type = ACPI_TYPE_INTEGER;
-		arg[0].Integer.Value = i;
-		fwts_log_info(fw, "Test _WAK(%d) System Wake, State S%d.", i, i);
-		if (method_evaluate_method(fw, METHOD_MANDITORY, "_WAK", arg, 1,
-					  method_test_WAK_return, &i) == FWTS_NOT_EXIST)
+		arg[0].Integer.Value = values[i];
+		if (method_evaluate_method(fw, METHOD_MOBILE, "_BMC", arg, 1,
+					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
 			break;
 		fwts_log_nl(fw);
 	}
 	return FWTS_OK;
 }
 
-/* Section 10.3 AC Adapters and Power Sources Objects */
 
-static void method_test_PSR_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+/*
+ * Section 10.3 AC Adapters and Power Sources Objects
+ */
+static void method_test_PSR_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
 		if (obj->Integer.Value > 2) {
@@ -1090,12 +1498,17 @@  static void method_test_PSR_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 
 static int method_test_PSR(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSR", NULL, 0, method_test_PSR_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_PSR", NULL, 0, method_test_PSR_return, NULL);
 }
 
-static void method_test_PIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static void method_test_PIF_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
-
 	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
 		fwts_method_dump_object(fw, obj);
 
@@ -1123,26 +1536,20 @@  static void method_test_PIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 
 static int method_test_PIF(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PIF", NULL, 0, method_test_PIF_return, NULL);
-}
-
-
-/* Section 9.4.1 Lid control */
-
-static void method_test_LID_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
-{
-	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK)
-		fwts_passed(fw, "_LID correctly returned sane looking value 0x%8.8x", (uint32_t)obj->Integer.Value);
-}
-
-static int method_test_LID(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_MOBILE, "_LID", NULL, 0, method_test_LID_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_PIF", NULL, 0, method_test_PIF_return, NULL);
 }
 
-/* Section 11.3 Fan Devices */
 
-static void method_test_FIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+/*
+ * Section 11.3 Fan Devices
+ */
+static void method_test_FIF_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
 		fwts_method_dump_object(fw, obj);
@@ -1172,7 +1579,8 @@  static void method_test_FIF_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 
 static int method_test_FIF(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_FIF", NULL, 0, method_test_FIF_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_FIF", NULL, 0, method_test_FIF_return, NULL);
 }
 
 static int method_test_FSL(fwts_framework *fw)
@@ -1181,7 +1589,8 @@  static int method_test_FSL(fwts_framework *fw)
 	arg[0].Type = ACPI_TYPE_INTEGER;
 	arg[0].Integer.Value = 50;
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_FSL", arg, 1, method_test_NULL_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_FSL", arg, 1, method_test_NULL_return, NULL);
 }
 
 static void method_test_FST_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
@@ -1213,22 +1622,30 @@  static void method_test_FST_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 
 static int method_test_FST(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_FST", NULL, 0, method_test_FST_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_FST", NULL, 0, method_test_FST_return, NULL);
 }
 
-/* Section 11.4 Thermal */
 
-static void method_test_THERM_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+/*
+ * Section 11.4 Thermal
+ */
+static void method_test_THERM_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
 		char *method = (char*)private;
-		
+
 		if (fwts_acpi_region_handler_called_get()) {
 			/*
 			 *  We accessed some memory or I/O region during the evaluation
 			 *  which returns spoofed values, so we should not test the value
 			 *  being returned. In this case, just pass this as a valid
-			 *  return type. 
+			 *  return type.
 			 */
 			fwts_passed(fw, "%s correctly returned sane looking return type.", name);
 		} else {
@@ -1267,7 +1684,8 @@  static void method_test_THERM_return(fwts_framework *fw, char *name, ACPI_BUFFER
 static int method_test ## name(fwts_framework *fw)	\
 {							\
 	fwts_acpi_region_handler_called_set(false);	\
-	return method_evaluate_method(fw, type, # name, NULL, 0, method_test_THERM_return, # name);	\
+	return method_evaluate_method(fw, type, # name, \
+		NULL, 0, method_test_THERM_return, # name);	\
 }
 
 method_test_THERM(_CRT, METHOD_OPTIONAL)
@@ -1277,7 +1695,18 @@  method_test_THERM(_NTT, METHOD_OPTIONAL)
 method_test_THERM(_PSV, METHOD_OPTIONAL)
 method_test_THERM(_TST, METHOD_OPTIONAL)
 
-static void method_test_TCx_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static int method_test_TSP(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_TSP", NULL, 0, method_test_polling_return, "_TSP");
+}
+
+static void method_test_TCx_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
 		char *method = (char *)private;
@@ -1287,12 +1716,14 @@  static void method_test_TCx_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 
 static int method_test_TC1(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_TC1", NULL, 0, method_test_TCx_return, "_TC1");
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_TC1", NULL, 0, method_test_TCx_return, "_TC1");
 }
 
 static int method_test_TC2(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_TC2", NULL, 0, method_test_TCx_return, "_TC1");
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_TC2", NULL, 0, method_test_TCx_return, "_TC1");
 }
 
 static int method_test_ACx(fwts_framework *fw)
@@ -1302,7 +1733,8 @@  static int method_test_ACx(fwts_framework *fw)
 	for (i=0;i<10;i++) {
 		char buffer[5];
 		snprintf(buffer, sizeof(buffer), "AC%d", i);
-		method_evaluate_method(fw, METHOD_OPTIONAL, buffer, NULL, 0, method_test_THERM_return, buffer);
+		method_evaluate_method(fw, METHOD_OPTIONAL,
+			buffer, NULL, 0, method_test_THERM_return, buffer);
 		fwts_log_nl(fw);
 	}
 	return FWTS_OK;
@@ -1313,7 +1745,9 @@  static int method_test_DTI(fwts_framework *fw)
 	ACPI_OBJECT arg[1];
 	arg[0].Type = ACPI_TYPE_INTEGER;
 	arg[0].Integer.Value = 2732 + 800; /* 80 degrees C */
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DTI", arg, 1, method_test_NULL_return, NULL);
+
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DTI", arg, 1, method_test_NULL_return, NULL);
 }
 
 static int method_test_SCP(fwts_framework *fw)
@@ -1329,7 +1763,9 @@  static int method_test_SCP(fwts_framework *fw)
 		arg[1].Integer.Value = 5;		/* Acoustic limit */
 		arg[2].Type = ACPI_TYPE_INTEGER;
 		arg[2].Integer.Value = 5;		/* Power limit */
-		if (method_evaluate_method(fw, METHOD_OPTIONAL, "_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
+
+		if (method_evaluate_method(fw, METHOD_OPTIONAL,
+			"_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
 			break;
 		fwts_log_nl(fw);
 
@@ -1339,14 +1775,20 @@  static int method_test_SCP(fwts_framework *fw)
 		arg[1].Integer.Value = 1;		/* Acoustic limit */
 		arg[2].Type = ACPI_TYPE_INTEGER;
 		arg[2].Integer.Value = 1;		/* Power limit */
-		if (method_evaluate_method(fw, METHOD_OPTIONAL, "_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
+
+		if (method_evaluate_method(fw, METHOD_OPTIONAL,
+			"_DTI", arg, 1, method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
 			break;
 	}
 	return FWTS_OK;
 }
 
-
-static void method_test_RTV_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static void method_test_RTV_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK)
 		fwts_passed(fw, "_RTV correctly returned sane looking value 0x%8.8x", (uint32_t)obj->Integer.Value);
@@ -1354,7 +1796,8 @@  static void method_test_RTV_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 
 static int method_test_RTV(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_RTV", NULL, 0, method_test_RTV_return, "_RTV");
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_RTV", NULL, 0, method_test_RTV_return, "_RTV");
 }
 
 static int method_test_TPT(fwts_framework *fw)
@@ -1362,139 +1805,206 @@  static int method_test_TPT(fwts_framework *fw)
 	ACPI_OBJECT arg[1];
 	arg[0].Type = ACPI_TYPE_INTEGER;
 	arg[0].Integer.Value = 2732 + 900; /* 90 degrees C */
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_TPT", arg, 1, method_test_NULL_return, NULL);
-}
-
-static void method_test_polling_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
-{
-	if (method_check_type(fw, name, buf, ACPI_TYPE_INTEGER) == FWTS_OK) {
-		char *method = (char *)private;
-		if (obj->Integer.Value < 36000) {
-			fwts_passed(fw, "%s correctly returned sane looking value %f seconds",
-				method, (float)obj->Integer.Value / 10.0);
-		} else {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodPollTimeTooLong",
-				"%s returned a value %f seconds > (1 hour) which is probably incorrect.",
-				method, (float)obj->Integer.Value / 10.0);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			fwts_advice(fw, "The method is returning a polling interval which is very long and hence "
-					"most probably incorrect.");
-		}
-	}
-}
 
-static int method_test_TSP(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_TSP", NULL, 0, method_test_polling_return, "_TSP");
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_TPT", arg, 1, method_test_NULL_return, NULL);
 }
 
 static int method_test_TZP(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_TZP", NULL, 0, method_test_polling_return, "_TZP");
-}
-
-/* Section 9.2, Ambient Light Sensor Device */
-
-method_test_integer(_ALC, METHOD_OPTIONAL)
-method_test_integer(_ALI, METHOD_OPTIONAL)
-method_test_integer(_ALT, METHOD_OPTIONAL)
-
-/* TODO _ALR */
-
-static int method_test_ALP(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_ALP", NULL, 0, method_test_polling_return, "_ALP");
-}
-
-
-/* Section 6.5 Other Objects and Control Methods */
-
-static int method_test_BBN(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_BBN", NULL, 0, method_test_integer_return, "_BBN");
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_TZP", NULL, 0, method_test_polling_return, "_TZP");
 }
 
-static int method_test_BDN(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_MOBILE, "_BDN", NULL, 0, method_test_integer_return, "_BDN");
-}
 
-static int method_test_DCK(fwts_framework *fw)
+/*
+ * Section 16 Waking and Sleeping
+ */
+static int method_test_PTS(fwts_framework *fw)
 {
 	int i;
 
-	for (i=0;i<=1;i++) {	/* Undock, Dock */
+	for (i=1; i<6; i++) {
 		ACPI_OBJECT arg[1];
+
 		arg[0].Type = ACPI_TYPE_INTEGER;
 		arg[0].Integer.Value = i;
-		if (method_evaluate_method(fw, METHOD_MOBILE, "_DCK", arg, 1, method_test_passed_failed_return, "_DCK") != FWTS_OK)
+
+		fwts_log_info(fw, "Test _PTS(%d).", i);
+
+		if (method_evaluate_method(fw, METHOD_MANDITORY, "_PTS", arg, 1,
+					  method_test_NULL_return, NULL) == FWTS_NOT_EXIST) {
+			fwts_advice(fw, "Could not find _PTS. This method provides a mechanism to "
+					"do housekeeping functions, such as write sleep state to the "
+					"embedded controller before entering a sleep state. If the "
+					"machine cannot suspend (S3), hibernate (S4) or shutdown (S5) "
+					"then it could be because _PTS is missing.");
 			break;
+		}
 		fwts_log_nl(fw);
 	}
 	return FWTS_OK;
 }
 
-/* Section 9.18 Wake Alarm Device */
+static int method_test_TTS(fwts_framework *fw)
+{
+	int i;
 
+	if (fwts_method_exists("_BFS") != NULL) {
+		for (i=1; i<6; i++) {
+			ACPI_OBJECT arg[1];
 
-static int method_test_STP(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[2];
+			arg[0].Type = ACPI_TYPE_INTEGER;
+			arg[0].Integer.Value = i;
 
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;	/* DC timer */
-	arg[1].Type = ACPI_TYPE_INTEGER;
-	arg[1].Integer.Value = 0;	/* wake up instantly */
+			fwts_log_info(fw, "Test _TTS(%d) Transition To State S%d.", i, i);
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_STP", arg, 2, method_test_passed_failed_return, "_STP");
+			if (method_evaluate_method(fw, METHOD_MANDITORY, "_TTS", arg, 1,
+				method_test_NULL_return, NULL) == FWTS_NOT_EXIST)
+				break;
+			fwts_log_nl(fw);
+		}
+	}
+	else {
+		fwts_skipped(fw, "Optional control method _TTS does not exist.");
+	}
+	return FWTS_OK;
 }
 
-static int method_test_STV(fwts_framework *fw)
+static void method_test_Sx_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
-	ACPI_OBJECT arg[2];
+	char *method = (char *)private;
 
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;	/* DC timer */
-	arg[1].Type = ACPI_TYPE_INTEGER;
-	arg[1].Integer.Value = 100;	/* timer value */
+	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
+		fwts_method_dump_object(fw, obj);
+
+		if (obj->Package.Count != 3) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_SElementCount", "%s should return package of 3 integers, got %d elements instead.", method,
+				obj->Package.Count);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+		}
+	}
+}
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_STV", arg, 2, method_test_passed_failed_return, "_STV");
+#define method_test_Sx(name)					\
+static int method_test ## name(fwts_framework *fw)		\
+{								\
+	return method_evaluate_method(fw, METHOD_OPTIONAL,	\
+		# name, NULL, 0, method_test_Sx_return, # name);\
 }
 
-static int method_test_TIP(fwts_framework *fw)
+method_test_Sx(_S0)
+method_test_Sx(_S1)
+method_test_Sx(_S2)
+method_test_Sx(_S3)
+method_test_Sx(_S4)
+method_test_Sx(_S5)
+
+static void method_test_WAK_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
-	ACPI_OBJECT arg[1];
+	uint32_t Sstate = *(uint32_t*)private;
+	int failed = 0;
 
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;	/* DC timer */
+	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
+		fwts_method_dump_object(fw, obj);
+
+		if (obj->Package.Count != 2) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKElementCount", "_WAK should return package of 2 integers, got %d elements instead.",
+				obj->Package.Count);
+			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			failed++;
+		} else {
+			if ((obj->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
+			    (obj->Package.Elements[1].Type != ACPI_TYPE_INTEGER))  {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBadType", "_WAK should return package of 2 integers, got %d instead.",
+					obj->Package.Count);
+				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+				failed++;
+			}
+			else {
+				if (obj->Package.Elements[0].Integer.Value > 0x00000002) {
+					fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_WAKBitField",
+						"_WAK: expecting condition bit-field (element 0) of packages to be in range, got 0x%8.8x.",
+						(uint32_t)obj->Package.Elements[0].Integer.Value);
+					fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+					failed++;
+				}
+				if (!(
+				    ((obj->Package.Elements[1].Integer.Value == Sstate) && (obj->Package.Elements[0].Integer.Value == 0)) ||
+                                    ((obj->Package.Elements[1].Integer.Value == 0) && (obj->Package.Elements[0].Integer.Value != 0)) )) {
+					fwts_warning(fw,
+						"_WAK: expecting power supply S-state (element 1) of packages to be 0x%8.8x, got 0x%8.8x.",
+						Sstate, (uint32_t)obj->Package.Elements[0].Integer.Value);
+					fwts_advice(fw, "_WAK should return 0 if the wake failed and was unsuccessful (i.e. element[0] "
+							"is non-zero) OR should return the S-state. "
+							"This can confuse the operating system as this _WAK return indicates that the "
+							"S-state was not entered because of too much current being drawn from the "
+							"power supply, however, the BIOS may have actually entered this state and the "
+							"_WAK method is misinforming the operating system. Currently Linux does not "
+							"check for the return type from _WAK, so it should theoretically not affect the "
+							"operation of suspend/resume.");
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_TIP", arg, 1, method_test_integer_return, NULL);
+					failed++;
+				}
+			}
+		}
+		if (!failed)
+			fwts_passed(fw, "_WAK correctly returned sane looking package.");
+	}
 }
 
-static int method_test_TIV(fwts_framework *fw)
+static int method_test_WAK(fwts_framework *fw)
 {
-	ACPI_OBJECT arg[1];
-
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;	/* DC timer */
+	uint32_t i;
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_TIV", arg, 1, method_test_integer_return, NULL);
+	for (i=1; i<6; i++) {
+		ACPI_OBJECT arg[1];
+		arg[0].Type = ACPI_TYPE_INTEGER;
+		arg[0].Integer.Value = i;
+		fwts_log_info(fw, "Test _WAK(%d) System Wake, State S%d.", i, i);
+		if (method_evaluate_method(fw, METHOD_MANDITORY, "_WAK", arg, 1,
+					  method_test_WAK_return, &i) == FWTS_NOT_EXIST)
+			break;
+		fwts_log_nl(fw);
+	}
+	return FWTS_OK;
 }
 
-/* Appendix B, ACPI Extensions for Display Adapters */
 
+/*
+ * Appendix B ACPI Extensions for Display Adapters
+ */
 static int method_test_DOS(fwts_framework *fw)
 {
 	ACPI_OBJECT arg[1];
 
 	arg[0].Type = ACPI_TYPE_INTEGER;
 	arg[0].Integer.Value = 0 << 2 | 1;
-		/* BIOS should toggle active display, BIOS controls brightness of LCD on AC/DC power changes */
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DOS", arg, 1, method_test_NULL_return, NULL);
+	/*
+	 * BIOS should toggle active display, BIOS controls brightness of
+	 * LCD on AC/DC power changes
+ 	 */
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DOS", arg, 1, method_test_NULL_return, NULL);
 }
 
-static void method_test_DOD_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static void method_test_DOD_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	int failed = 0;
 	static char *dod_type[] = {
@@ -1554,10 +2064,16 @@  static void method_test_DOD_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 
 static int method_test_DOD(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DOD", NULL, 0, method_test_DOD_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DOD", NULL, 0, method_test_DOD_return, NULL);
 }
 
-static void method_test_ROM_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static void method_test_ROM_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	method_check_type(fw, name, buf, ACPI_TYPE_BUFFER);
 }
@@ -1571,12 +2087,14 @@  static int method_test_ROM(fwts_framework *fw)
 	arg[1].Type = ACPI_TYPE_INTEGER;
 	arg[1].Integer.Value = 4096;
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_ROM", arg, 2, method_test_ROM_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_ROM", arg, 2, method_test_ROM_return, NULL);
 }
 
 static int method_test_GPD(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_GPD", NULL, 0, method_test_integer_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_GPD", NULL, 0, method_test_integer_return, NULL);
 }
 
 static int method_test_SPD(fwts_framework *fw)
@@ -1588,7 +2106,8 @@  static int method_test_SPD(fwts_framework *fw)
 		arg[0].Type = ACPI_TYPE_INTEGER;
 		arg[0].Integer.Value = i;	/* bits 00..11, post device */
 
-		if (method_evaluate_method(fw, METHOD_OPTIONAL, "_SPD", arg, 1, method_test_passed_failed_return, NULL) == FWTS_NOT_EXIST)
+		if (method_evaluate_method(fw, METHOD_OPTIONAL,
+			"_SPD", arg, 1, method_test_passed_failed_return, NULL) == FWTS_NOT_EXIST)
 			break;
 	}
 	return FWTS_OK;
@@ -1596,15 +2115,22 @@  static int method_test_SPD(fwts_framework *fw)
 
 static int method_test_VPO(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_VPO", NULL, 0, method_test_integer_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_VPO", NULL, 0, method_test_integer_return, NULL);
 }
 
 static int method_test_ADR(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_ADR", NULL, 0, method_test_integer_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_ADR", NULL, 0, method_test_integer_return, NULL);
 }
 
-static void method_test_BCL_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static void method_test_BCL_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
 	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) == FWTS_OK) {
 		int i;
@@ -1620,467 +2146,157 @@  static void method_test_BCL_return(fwts_framework *fw, char *name, ACPI_BUFFER *
 			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLNoPackage",
 				"Method _BCL did not return a package of %d integers.", obj->Package.Count);
 		} else {
-			if (obj->Package.Count < 3) {
-				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLElementCount",
-					"Method _BCL should return a package of more than 2 integers, got just %d.", obj->Package.Count);
-				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			} else {
-				bool ascending_levels = false;
-
-				if (obj->Package.Elements[0].Integer.Value <
-				    obj->Package.Elements[1].Integer.Value) {
-					fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLMaxLevel",
-						"Brightness level when on full power (%d) is less than "
-						 	"brightness level when on battery power (%d).",
-						(uint32_t)obj->Package.Elements[0].Integer.Value,
-						(uint32_t)obj->Package.Elements[1].Integer.Value);
-					fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-					failed++;
-				}
-
-				for (i=2;i<obj->Package.Count-1;i++) {
-					if (obj->Package.Elements[i].Integer.Value >
-					    obj->Package.Elements[i+1].Integer.Value) {
-						fwts_log_info(fw, "Brightness level %d (index %d) is greater than "
-						 	"brightness level %d (index %d), should be in ascending order.",
-							(uint32_t)obj->Package.Elements[i].Integer.Value, i,
-							(uint32_t)obj->Package.Elements[i+1].Integer.Value, i+1);
-						ascending_levels = true;
-						failed++;
-					}
-				}
-				if (ascending_levels) {
-					fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLAscendingOrder",
-						"Some or all of the brightness level are not in ascending order which "
-						"should be fixed in the firmware.");
-					fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-				}
-
-				if (failed)
-					fwts_advice(fw, "Method _BCL seems to be misconfigured and is returning incorrect brightness levels."
-							"It is worth sanity checking this with the firmware test suite interactive test "
-							"'brightness' to see how broken this is. As it is, _BCL is broken and needs to be "
-							"fixed.");
-				else
-					fwts_passed(fw, "Method _BCL returned a sane package of %d integers.", obj->Package.Count);
-			}
-		}
-	}
-}
-
-static int method_test_BCL(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_BCL", NULL, 0, method_test_BCL_return, NULL);
-}
-
-static int method_test_BCM(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[1];
-
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 0;
-
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_BCM", arg, 1, method_test_NULL_return, NULL);
-}
-
-static int method_test_BQC(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_BQC", NULL, 0, method_test_integer_return, NULL);
-}
-
-static void method_test_DDC_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
-{
-	uint32_t requested = *(uint32_t*)private;
-
-	if (obj == NULL){
-		fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodReturnNullObj", "Method %s returned a NULL object, and did not return a buffer or integer.", name);
-		return;
-	}
-	switch (obj->Type) {
-	case ACPI_TYPE_BUFFER:
-		if (requested != obj->Buffer.Length) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCElementCount",
-				"Method _DDC returned a buffer of %d items, expected %d.",
-				obj->Buffer.Length, requested);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-		} else
-			fwts_passed(fw, "Method _DDC returned a buffer of %d items as expected.",
-				obj->Buffer.Length);
-		break;
-	case ACPI_TYPE_INTEGER:
-			fwts_passed(fw, "Method _DDC could not return a buffer of %d items"
-					"and instead returned an error status.",
-				obj->Buffer.Length);
-		break;
-	default:
-		fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCBadReturnType",
-			"Method _DDC did not return a buffer or an integer.");
-		fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-		break;
-	}
-}
-
-static int method_test_DDC(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[1];
-	uint32_t i;
-
-	for (i=128; i<=256; i <<= 1) {
-		arg[0].Type = ACPI_TYPE_INTEGER;
-		arg[0].Integer.Value = 128;
-
-		if (method_evaluate_method(fw, METHOD_OPTIONAL, "_DDC", arg, 1, method_test_DDC_return, &i) == FWTS_NOT_EXIST)
-			break;
-	}
-	return FWTS_OK;
-}
-
-static int method_test_DCS(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DCS", NULL, 0, method_test_integer_return, NULL);
-}
-
-static int method_test_DGS(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DGS", NULL, 0, method_test_integer_return, NULL);
-}
-
-static int method_test_DSS(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[1];
-
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 0;
-
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DSS", arg, 1, method_test_NULL_return, NULL);
-}
-
-/* Section 6.5 Other Objects and Controls */
-
-static int method_test_CRS(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_MANDITORY, "_CRS", NULL, 0, method_test_buffer_return, NULL);
-}
-
-static int method_test_DMA(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DMA", NULL, 0, method_test_buffer_return, NULL);
-}
-
-static int method_test_DIS(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DIS", NULL, 0, method_test_NULL_return, NULL);
-}
-
-static int method_test_PXM(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PXM", NULL, 0, method_test_integer_return, NULL);
-}
-
-/* Section 7.2 */
-
-static int method_test_DSW(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[3];
-
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;
-	arg[1].Type = ACPI_TYPE_INTEGER;
-	arg[1].Integer.Value = 0;
-	arg[2].Type = ACPI_TYPE_INTEGER;
-	arg[2].Integer.Value = 3;
-
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_DSW", arg, 3, method_test_NULL_return, NULL);
-}
-
-#define method_test_PSx(name)				\
-static int method_test ## name(fwts_framework *fw)	\
-{							\
-	return method_evaluate_method(fw, METHOD_OPTIONAL, # name, NULL, 0, method_test_NULL_return, # name); \
-}
-
-method_test_PSx(_PS0)
-method_test_PSx(_PS1)
-method_test_PSx(_PS2)
-method_test_PSx(_PS3)
-
-static int method_test_PSC(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSC", NULL, 0, method_test_integer_return, NULL);
-}
-
-static int method_test_PSE(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[1];
-
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;
-
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSE", arg, 1, method_test_NULL_return, NULL);
-}
-
-static void method_test_PRE_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
-{
-	int i;
-
-	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
-		return;
-
-	/* All elements in the package must be references */
-	for (i=0; i < obj->Package.Count; i++) {
-		if (obj->Package.Elements[i].Type != ACPI_TYPE_LOCAL_REFERENCE) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PREElementType",
-			"_PRE package element %d was not a reference.", i);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-		}
-	}
-}
-
-static int method_test_PRE(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PRE", NULL, 0, method_test_PRE_return, NULL);
-}
-
-static int method_test_PSW(fwts_framework *fw)
-{
-	ACPI_OBJECT arg[1];
+			if (obj->Package.Count < 3) {
+				fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLElementCount",
+					"Method _BCL should return a package of more than 2 integers, got just %d.", obj->Package.Count);
+				fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+			} else {
+				bool ascending_levels = false;
 
-	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;
+				if (obj->Package.Elements[0].Integer.Value <
+				    obj->Package.Elements[1].Integer.Value) {
+					fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLMaxLevel",
+						"Brightness level when on full power (%d) is less than "
+						 	"brightness level when on battery power (%d).",
+						(uint32_t)obj->Package.Elements[0].Integer.Value,
+						(uint32_t)obj->Package.Elements[1].Integer.Value);
+					fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+					failed++;
+				}
 
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSW", arg, 1, method_test_NULL_return, NULL);
-}
+				for (i=2;i<obj->Package.Count-1;i++) {
+					if (obj->Package.Elements[i].Integer.Value >
+					    obj->Package.Elements[i+1].Integer.Value) {
+						fwts_log_info(fw, "Brightness level %d (index %d) is greater than "
+						 	"brightness level %d (index %d), should be in ascending order.",
+							(uint32_t)obj->Package.Elements[i].Integer.Value, i,
+							(uint32_t)obj->Package.Elements[i+1].Integer.Value, i+1);
+						ascending_levels = true;
+						failed++;
+					}
+				}
+				if (ascending_levels) {
+					fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_BCLAscendingOrder",
+						"Some or all of the brightness level are not in ascending order which "
+						"should be fixed in the firmware.");
+					fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
+				}
 
-static int method_test_IRC(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_IRC", NULL, 0, method_test_NULL_return, NULL);
+				if (failed)
+					fwts_advice(fw, "Method _BCL seems to be misconfigured and is returning incorrect brightness levels."
+							"It is worth sanity checking this with the firmware test suite interactive test "
+							"'brightness' to see how broken this is. As it is, _BCL is broken and needs to be "
+							"fixed.");
+				else
+					fwts_passed(fw, "Method _BCL returned a sane package of %d integers.", obj->Package.Count);
+			}
+		}
+	}
 }
 
-/* Section 6.3 */
-
-static int method_test_EJD(fwts_framework *fw)
+static int method_test_BCL(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_EJD", NULL, 0, method_test_string_return, NULL);
-}
-
-#define method_test_EJx(name)				\
-static int method_test ## name(fwts_framework *fw)	\
-{							\
-	ACPI_OBJECT arg[1];				\
-							\
-	arg[0].Type = ACPI_TYPE_INTEGER;		\
-	arg[0].Integer.Value = 1;			\
-							\
-	return method_evaluate_method(fw, METHOD_OPTIONAL, # name, arg, 1, method_test_NULL_return, # name); \
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_BCL", NULL, 0, method_test_BCL_return, NULL);
 }
 
-method_test_EJx(_EJ0)
-method_test_EJx(_EJ1)
-method_test_EJx(_EJ2)
-method_test_EJx(_EJ3)
-method_test_EJx(_EJ4)
-
-static int method_test_LCK(fwts_framework *fw)
+static int method_test_BCM(fwts_framework *fw)
 {
 	ACPI_OBJECT arg[1];
 
 	arg[0].Type = ACPI_TYPE_INTEGER;
-	arg[0].Integer.Value = 1;
-
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_LCK", arg, 1, method_test_NULL_return, NULL);
-}
-
-/* Section 7.1 */
+	arg[0].Integer.Value = 0;
 
-static int method_test_ON(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_ON", NULL, 0, method_test_NULL_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_BCM", arg, 1, method_test_NULL_return, NULL);
 }
 
-static int method_test_OFF(fwts_framework *fw)
+static int method_test_BQC(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_OFF", NULL, 0, method_test_NULL_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_BQC", NULL, 0, method_test_integer_return, NULL);
 }
 
-/* Section 6.1 */
-
-static int method_test_SUN(fwts_framework *fw)
+static void method_test_DDC_return(
+	fwts_framework *fw,
+	char *name,
+	ACPI_BUFFER *buf,
+	ACPI_OBJECT *obj,
+	void *private)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_SUN", NULL, 0, method_test_integer_return, NULL);
-}
+	uint32_t requested = *(uint32_t*)private;
 
-static void method_test_UID_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
-{
 	if (obj == NULL){
 		fwts_failed(fw, LOG_LEVEL_MEDIUM, "MethodReturnNullObj", "Method %s returned a NULL object, and did not return a buffer or integer.", name);
 		return;
 	}
 	switch (obj->Type) {
-	case ACPI_TYPE_STRING:
-		if (obj->String.Pointer)
-			fwts_passed(fw, "Object _UID returned a string '%s' as expected.",
-				obj->String.Pointer);
-		else {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDNullString",
-				"Object _UID returned a NULL string.");
+	case ACPI_TYPE_BUFFER:
+		if (requested != obj->Buffer.Length) {
+			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCElementCount",
+				"Method _DDC returned a buffer of %d items, expected %d.",
+				obj->Buffer.Length, requested);
 			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-		}
+		} else
+			fwts_passed(fw, "Method _DDC returned a buffer of %d items as expected.",
+				obj->Buffer.Length);
 		break;
 	case ACPI_TYPE_INTEGER:
-		fwts_passed(fw, "Object _UID returned am integer 0x%8.8llx.",
-			(unsigned long long)obj->Integer.Value);
+			fwts_passed(fw, "Method _DDC could not return a buffer of %d items"
+					"and instead returned an error status.",
+				obj->Buffer.Length);
 		break;
 	default:
-		fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_UIDBadReturnType",
-			"Method _UID did not return a string or an integer.");
+		fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_DDCBadReturnType",
+			"Method _DDC did not return a buffer or an integer.");
 		fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
 		break;
 	}
 }
 
-static int method_test_UID(fwts_framework *fw)
-{
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_UID", NULL, 0, method_test_UID_return, NULL);
-}
-
-
-/* Section 8.4 */
-
-static void method_test_PSS_return(fwts_framework *fw, char *name, ACPI_BUFFER *buf, ACPI_OBJECT *obj, void *private)
+static int method_test_DDC(fwts_framework *fw)
 {
-	int i;
-	bool failed = false;
-	uint32_t max_freq = 0;
-	uint32_t prev_power = 0;
-	bool max_freq_valid = false;
-
-	if (method_check_type(fw, name, buf, ACPI_TYPE_PACKAGE) != FWTS_OK)
-		return;
-
-	/* Something is really wrong if we don't have any elements in _PSS */
-	if (obj->Package.Count < 1) {
-		fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementCount",
-			"_PSS should return package of at least 1 element, "
-			"got %d elements instead.",
-			obj->Package.Count);
-		fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-		return;
-	}
-
-	for (i=0; i < obj->Package.Count; i++) {
-		ACPI_OBJECT *pstate;
-
-		if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSElementType",
-			"_PSS package element %d was not a package.", i);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed = true;
-			continue;	/* Skip processing sub-package */
-		}
-
-		pstate = &obj->Package.Elements[i];
-		if (pstate->Package.Count != 6) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementCount",
-				"_PSS P-State sub-package %d was expected to have "
-				"6 elements, got %d elements instead.",
-				i, obj->Package.Count);
-			fwts_tag_failed(fw, FWTS_TAG_ACPI_METHOD_RETURN);
-			failed = true;
-			continue;	/* Skip processing sub-package */
-		}
-
-		/* Elements need to be all ACPI integer types */
-		if ((pstate->Package.Elements[0].Type != ACPI_TYPE_INTEGER) ||
-		    (pstate->Package.Elements[1].Type != ACPI_TYPE_INTEGER) ||
-		    (pstate->Package.Elements[2].Type != ACPI_TYPE_INTEGER) ||
-		    (pstate->Package.Elements[3].Type != ACPI_TYPE_INTEGER) ||
-		    (pstate->Package.Elements[4].Type != ACPI_TYPE_INTEGER) ||
-		    (pstate->Package.Elements[5].Type != ACPI_TYPE_INTEGER)) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackageElementType",
-				"_PSS P-State sub-package %d was expected to have "
-				"6 Integer elements but didn't", i);
-			failed = true;
-			continue;
-		}
-
-		fwts_log_info(fw, "P-State %d: CPU %ld Mhz, %lu mW, latency %lu us, bus master latency %lu us.",
-			i,
-			(unsigned long)pstate->Package.Elements[0].Integer.Value,
-			(unsigned long)pstate->Package.Elements[1].Integer.Value,
-			(unsigned long)pstate->Package.Elements[2].Integer.Value,
-			(unsigned long)pstate->Package.Elements[3].Integer.Value);
-
-		/*
-		 * Collect maximum frequency.  The sub-packages are sorted in
-		 * descending power dissipation order, so one would assume that
-		 * the highest frequency is first.  However, it is not clear
-		 * from the ACPI spec that this is necessarily an assumption we
-		 * should make, so instead we should probably scan through all
-		 * the valid sub-packages and find the highest frequency.
-		 */
-		if (max_freq < pstate->Package.Elements[0].Integer.Value) {
-			max_freq = pstate->Package.Elements[0].Integer.Value;
-			max_freq_valid = true;
-		}
+	ACPI_OBJECT arg[1];
+	uint32_t i;
 
-		/* Sanity check descending power dissipation levels */
-		if ((i > 0) && (prev_power != 0) &&
-		    (pstate->Package.Elements[1].Integer.Value > prev_power)) {
-			fwts_failed(fw, LOG_LEVEL_MEDIUM, "Method_PSSSubPackagePowerNotDecending",
-				"_PSS P-State sub-package %d has a larger power dissipation "
-				"setting than the previous sub-package.", i);
-			fwts_advice(fw, "_PSS P-States must be ordered in decending order of "
-				"power dissipation, so that the zero'th entry has the highest "
-				"power dissipation level and the Nth has the lowest.");
-			failed = true;
-		}
-		prev_power = pstate->Package.Elements[1].Integer.Value;
-	}
+	for (i=128; i<=256; i <<= 1) {
+		arg[0].Type = ACPI_TYPE_INTEGER;
+		arg[0].Integer.Value = 128;
 
-	/*
-	 * Sanity check maximum frequency.  We could also check the DMI data
-	 * for a BIOS date (but this can be wrong) or check the CPU identity
-	 * (which requires adding in new CPU identity checks) to make a decision
-	 * on when it is reasonable to assume a CPU is modern and hence clocked
-	 * incorrectly.  For now, just flag up a low level error that the
-	 * frequency looks rather low rather than try to be intelligent (and
-	 * possibly make a mistake).  I'd rather flag up a few false positives
-	 * on older machines than miss flagging up bad _PSS settings on new
-	 * machines.
-	 */
-	if (max_freq_valid && max_freq < 1000) {
-		fwts_failed(fw, LOG_LEVEL_LOW, "Method_PSSSubPackageLowFreq",
-			"Maximum CPU frequency is %dHz and this is low for "
-			"a modern processor. This may indicate the _PSS P-States "
-			"are incorrect\n", max_freq);
-		fwts_advice(fw,
-			"The _PSS P-States are used by the Linux CPU frequency "
-			"driver to set the CPU frequencies according to system "
-			"load.  Sometimes the firmware sets these incorrectly "
-			"and the machine runs at a sub-optimal speed.  One can "
-			"view the firmware defined CPU frequencies via "
-			"/sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies");
-		failed = true;
+		if (method_evaluate_method(fw, METHOD_OPTIONAL,
+			"_DDC", arg, 1, method_test_DDC_return, &i) == FWTS_NOT_EXIST)
+			break;
 	}
-
-	if (!failed)
-		fwts_passed(fw, "_PSS correctly returned sane looking package.");
+	return FWTS_OK;
 }
 
-static int method_test_PSS(fwts_framework *fw)
+static int method_test_DCS(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_PSS", NULL, 0, method_test_PSS_return, NULL);
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DCS", NULL, 0, method_test_integer_return, NULL);
 }
 
-/* Section 5.6 */
+static int method_test_DGS(fwts_framework *fw)
+{
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DGS", NULL, 0, method_test_integer_return, NULL);
+}
 
-static int method_test_AEI(fwts_framework *fw)
+static int method_test_DSS(fwts_framework *fw)
 {
-	return method_evaluate_method(fw, METHOD_OPTIONAL, "_AEI", NULL, 0, method_test_buffer_return, NULL);
+	ACPI_OBJECT arg[1];
+
+	arg[0].Type = ACPI_TYPE_INTEGER;
+	arg[0].Integer.Value = 0;
+
+	return method_evaluate_method(fw, METHOD_OPTIONAL,
+		"_DSS", arg, 1, method_test_NULL_return, NULL);
 }
 
-/* Tests */
 
+/*
+ * Tests
+ */
 static fwts_framework_minor_test method_tests[] = {
 	{ method_name_check, "Check Method Names." },