All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Marcel Apfelbaum <marcel.a@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH for-1.7] acpi unit-test: add signatures and checksum verification
Date: Wed, 13 Nov 2013 21:36:32 +0200	[thread overview]
Message-ID: <20131113193632.GA6698@redhat.com> (raw)
In-Reply-To: <1384273944-24616-1-git-send-email-marcel.a@redhat.com>

On Tue, Nov 12, 2013 at 06:32:24PM +0200, Marcel Apfelbaum wrote:
> Loaded all ACPI tables from guest, making
> a good environment for further unit tests.
> 
> Checked that ACPI tables are corrected pointed
> within the ACPI tree using their signatures.
> Verified checksum for all the tables.
> 
> Signed-off-by: Marcel Apfelbaum <marcel.a@redhat.com>


Thanks, applied.

> ---
> To be applied on top of: [PATCH v2 2/2] acpi-test: basic acpi unit-test
> 
>  tests/acpi-test.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 252 insertions(+), 20 deletions(-)
> 
> diff --git a/tests/acpi-test.c b/tests/acpi-test.c
> index 468c4f5..d6ff66f 100644
> --- a/tests/acpi-test.c
> +++ b/tests/acpi-test.c
> @@ -13,13 +13,28 @@
>  #include <string.h>
>  #include <stdio.h>
>  #include <glib.h>
> +#include "qemu-common.h"
>  #include "libqtest.h"
> +#include "qemu/compiler.h"
> +#include "hw/i386/acpi-defs.h"
>  
> +/* DSDT and SSDTs format */
>  typedef struct {
> -    const char *args;
> -    uint64_t expected_boot;
> -    uint64_t expected_reboot;
> -} boot_order_test;
> +    AcpiTableHeader header;
> +    uint8_t *aml;
> +    int aml_len;
> +} AcpiSdtTable;
> +
> +typedef struct {
> +    uint32_t rsdp_addr;
> +    AcpiRsdpDescriptor rsdp_table;
> +    AcpiRsdtDescriptorRev1 rsdt_table;
> +    AcpiFadtDescriptorRev1 fadt_table;
> +    uint32_t *rsdt_tables_addr;
> +    int rsdt_tables_nr;
> +    AcpiSdtTable dsdt_table;
> +    AcpiSdtTable *ssdt_tables;
> +} test_data;
>  
>  #define LOW(x) ((x) & 0xff)
>  #define HIGH(x) ((x) >> 8)
> @@ -28,6 +43,51 @@ typedef struct {
>  #define SIGNATURE_OFFSET 0x10
>  #define BOOT_SECTOR_ADDRESS 0x7c00
>  
> +#define ACPI_READ_FIELD(field, addr)           \
> +    do {                                       \
> +        switch (sizeof(field)) {               \
> +        case 1:                                \
> +            field = readb(addr);               \
> +            break;                             \
> +        case 2:                                \
> +            field = le16_to_cpu(readw(addr));  \
> +            break;                             \
> +        case 4:                                \
> +            field = le32_to_cpu(readl(addr));  \
> +            break;                             \
> +        case 8:                                \
> +            field = le64_to_cpu(readq(addr));  \
> +            break;                             \
> +        default:                               \
> +            g_assert(false);                   \
> +        }                                      \
> +        addr += sizeof(field);                  \
> +    } while (0);
> +
> +#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
> +    do {                                        \
> +        int idx;                                \
> +        for (idx = 0; idx < length; ++idx) {    \
> +            ACPI_READ_FIELD(arr[idx], addr);    \
> +        }                                       \
> +    } while (0);
> +
> +#define ACPI_READ_ARRAY(arr, addr)                               \
> +    ACPI_READ_ARRAY_PTR(arr, sizeof(arr)/sizeof(arr[0]), addr)
> +
> +#define ACPI_READ_TABLE_HEADER(table, addr)                      \
> +    do {                                                         \
> +        ACPI_READ_FIELD((table)->signature, addr);               \
> +        ACPI_READ_FIELD((table)->length, addr);                  \
> +        ACPI_READ_FIELD((table)->revision, addr);                \
> +        ACPI_READ_FIELD((table)->checksum, addr);                \
> +        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
> +        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
> +        ACPI_READ_FIELD((table)->oem_revision, addr);            \
> +        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
> +        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
> +    } while (0);
> +
>  /* Boot sector code: write SIGNATURE into memory,
>   * then halt.
>   */
> @@ -57,6 +117,181 @@ static uint8_t boot_sector[0x200] = {
>  
>  static const char *disk = "tests/acpi-test-disk.raw";
>  
> +static uint8_t acpi_checksum(const uint8_t *data, int len)
> +{
> +    int i;
> +    uint8_t sum = 0;
> +
> +    for (i = 0; i < len; i++) {
> +        sum += data[i];
> +    }
> +
> +    return sum;
> +}
> +
> +static void test_acpi_rsdp_address(test_data *data)
> +{
> +    uint32_t off;
> +
> +    /* OK, now find RSDP */
> +    for (off = 0xf0000; off < 0x100000; off += 0x10) {
> +        uint8_t sig[] = "RSD PTR ";
> +        int i;
> +
> +        for (i = 0; i < sizeof sig - 1; ++i) {
> +            sig[i] = readb(off + i);
> +        }
> +
> +        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
> +            break;
> +        }
> +    }
> +
> +    g_assert_cmphex(off, <, 0x100000);
> +    data->rsdp_addr = off;
> +}
> +
> +static void test_acpi_rsdp_table(test_data *data)
> +{
> +    AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table;
> +    uint32_t addr = data->rsdp_addr;
> +
> +    ACPI_READ_FIELD(rsdp_table->signature, addr);
> +    g_assert_cmphex(rsdp_table->signature, ==, ACPI_RSDP_SIGNATURE);
> +
> +    ACPI_READ_FIELD(rsdp_table->checksum, addr);
> +    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
> +    ACPI_READ_FIELD(rsdp_table->revision, addr);
> +    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
> +    ACPI_READ_FIELD(rsdp_table->length, addr);
> +
> +    /* rsdp checksum is not for the whole table, but for the first 20 bytes */
> +    g_assert(!acpi_checksum((uint8_t *)rsdp_table, 20));
> +}
> +
> +static void test_acpi_rsdt_table(test_data *data)
> +{
> +    AcpiRsdtDescriptorRev1 *rsdt_table = &data->rsdt_table;
> +    uint32_t addr = data->rsdp_table.rsdt_physical_address;
> +    uint32_t *tables;
> +    int tables_nr;
> +    uint8_t checksum;
> +
> +    /* read the header */
> +    ACPI_READ_TABLE_HEADER(rsdt_table, addr);
> +    g_assert_cmphex(rsdt_table->signature, ==, ACPI_RSDT_SIGNATURE);
> +
> +    /* compute the table entries in rsdt */
> +    tables_nr = (rsdt_table->length - sizeof(AcpiRsdtDescriptorRev1)) /
> +                sizeof(uint32_t);
> +    g_assert_cmpint(tables_nr, >, 0);
> +
> +    /* get the addresses of the tables pointed by rsdt */
> +    tables = g_new0(uint32_t, tables_nr);
> +    ACPI_READ_ARRAY_PTR(tables, tables_nr, addr);
> +
> +    checksum = acpi_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
> +               acpi_checksum((uint8_t *)tables, tables_nr * sizeof(uint32_t));
> +    g_assert(!checksum);
> +
> +   /* SSDT tables after FADT */
> +    data->rsdt_tables_addr = tables;
> +    data->rsdt_tables_nr = tables_nr;
> +}
> +
> +static void test_acpi_fadt_table(test_data *data)
> +{
> +    AcpiFadtDescriptorRev1 *fadt_table = &data->fadt_table;
> +    uint32_t addr;
> +
> +    /* FADT table comes first */
> +    addr = data->rsdt_tables_addr[0];
> +    ACPI_READ_TABLE_HEADER(fadt_table, addr);
> +
> +    ACPI_READ_FIELD(fadt_table->firmware_ctrl, addr);
> +    ACPI_READ_FIELD(fadt_table->dsdt, addr);
> +    ACPI_READ_FIELD(fadt_table->model, addr);
> +    ACPI_READ_FIELD(fadt_table->reserved1, addr);
> +    ACPI_READ_FIELD(fadt_table->sci_int, addr);
> +    ACPI_READ_FIELD(fadt_table->smi_cmd, addr);
> +    ACPI_READ_FIELD(fadt_table->acpi_enable, addr);
> +    ACPI_READ_FIELD(fadt_table->acpi_disable, addr);
> +    ACPI_READ_FIELD(fadt_table->S4bios_req, addr);
> +    ACPI_READ_FIELD(fadt_table->reserved2, addr);
> +    ACPI_READ_FIELD(fadt_table->pm1a_evt_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->pm1b_evt_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->pm1a_cnt_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->pm1b_cnt_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->pm2_cnt_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->pm_tmr_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->gpe0_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->gpe1_blk, addr);
> +    ACPI_READ_FIELD(fadt_table->pm1_evt_len, addr);
> +    ACPI_READ_FIELD(fadt_table->pm1_cnt_len, addr);
> +    ACPI_READ_FIELD(fadt_table->pm2_cnt_len, addr);
> +    ACPI_READ_FIELD(fadt_table->pm_tmr_len, addr);
> +    ACPI_READ_FIELD(fadt_table->gpe0_blk_len, addr);
> +    ACPI_READ_FIELD(fadt_table->gpe1_blk_len, addr);
> +    ACPI_READ_FIELD(fadt_table->gpe1_base, addr);
> +    ACPI_READ_FIELD(fadt_table->reserved3, addr);
> +    ACPI_READ_FIELD(fadt_table->plvl2_lat, addr);
> +    ACPI_READ_FIELD(fadt_table->plvl3_lat, addr);
> +    ACPI_READ_FIELD(fadt_table->flush_size, addr);
> +    ACPI_READ_FIELD(fadt_table->flush_stride, addr);
> +    ACPI_READ_FIELD(fadt_table->duty_offset, addr);
> +    ACPI_READ_FIELD(fadt_table->duty_width, addr);
> +    ACPI_READ_FIELD(fadt_table->day_alrm, addr);
> +    ACPI_READ_FIELD(fadt_table->mon_alrm, addr);
> +    ACPI_READ_FIELD(fadt_table->century, addr);
> +    ACPI_READ_FIELD(fadt_table->reserved4, addr);
> +    ACPI_READ_FIELD(fadt_table->reserved4a, addr);
> +    ACPI_READ_FIELD(fadt_table->reserved4b, addr);
> +    ACPI_READ_FIELD(fadt_table->flags, addr);
> +
> +    g_assert_cmphex(fadt_table->signature, ==, ACPI_FACP_SIGNATURE);
> +    g_assert(!acpi_checksum((uint8_t *)fadt_table, fadt_table->length));
> +}
> +
> +static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
> +{
> +    uint8_t checksum;
> +
> +    ACPI_READ_TABLE_HEADER(&sdt_table->header, addr);
> +
> +    sdt_table->aml_len = sdt_table->header.length - sizeof(AcpiTableHeader);
> +    sdt_table->aml = g_malloc0(sdt_table->aml_len);
> +    ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
> +
> +    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
> +               acpi_checksum(sdt_table->aml, sdt_table->aml_len);
> +    g_assert(!checksum);
> +}
> +
> +static void test_acpi_dsdt_table(test_data *data)
> +{
> +    AcpiSdtTable *dsdt_table = &data->dsdt_table;
> +    uint32_t addr = data->fadt_table.dsdt;
> +
> +    test_dst_table(dsdt_table, addr);
> +    g_assert_cmphex(dsdt_table->header.signature, ==, ACPI_DSDT_SIGNATURE);
> +}
> +
> +static void test_acpi_ssdt_tables(test_data *data)
> +{
> +    AcpiSdtTable *ssdt_tables;
> +    int ssdt_tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
> +    int i;
> +
> +    ssdt_tables = g_new0(AcpiSdtTable, ssdt_tables_nr);
> +    for (i = 0; i < ssdt_tables_nr; i++) {
> +        AcpiSdtTable *ssdt_table = &ssdt_tables[i];
> +        uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
> +
> +        test_dst_table(ssdt_table, addr);
> +    }
> +    data->ssdt_tables = ssdt_tables;
> +}
> +
>  static void test_acpi_one(const char *params)
>  {
>      char *args;
> @@ -64,9 +299,9 @@ static void test_acpi_one(const char *params)
>      uint8_t signature_high;
>      uint16_t signature;
>      int i;
> -    uint32_t off;
> -
> +    test_data data;
>  
> +    memset(&data, 0, sizeof(data));
>      args = g_strdup_printf("-net none -display none %s %s",
>                             params ? params : "", disk);
>      qtest_start(args);
> @@ -90,22 +325,19 @@ static void test_acpi_one(const char *params)
>      }
>      g_assert_cmphex(signature, ==, SIGNATURE);
>  
> -    /* OK, now find RSDP */
> -    for (off = 0xf0000; off < 0x100000; off += 0x10)
> -    {
> -        uint8_t sig[] = "RSD PTR ";
> -        int i;
> -
> -        for (i = 0; i < sizeof sig - 1; ++i) {
> -            sig[i] = readb(off + i);
> -        }
> +    test_acpi_rsdp_address(&data);
> +    test_acpi_rsdp_table(&data);
> +    test_acpi_rsdt_table(&data);
> +    test_acpi_fadt_table(&data);
> +    test_acpi_dsdt_table(&data);
> +    test_acpi_ssdt_tables(&data);
>  
> -        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
> -            break;
> -        }
> +    g_free(data.rsdt_tables_addr);
> +    for (i = 0; i < (data.rsdt_tables_nr - 1); ++i) {
> +        g_free(data.ssdt_tables[i].aml);
>      }
> -
> -    g_assert_cmphex(off, <, 0x100000);
> +    g_free(data.ssdt_tables);
> +    g_free(data.dsdt_table.aml);
>  
>      qtest_quit(global_qtest);
>      g_free(args);
> -- 
> 1.8.3.1

      reply	other threads:[~2013-11-13 19:33 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-12 16:32 [Qemu-devel] [PATCH for-1.7] acpi unit-test: add signatures and checksum verification Marcel Apfelbaum
2013-11-13 19:36 ` Michael S. Tsirkin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20131113193632.GA6698@redhat.com \
    --to=mst@redhat.com \
    --cc=marcel.a@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.