[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH for-1.7] acpi unit-test: add signatures and chec
From: |
Michael S. Tsirkin |
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 |
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 <address@hidden>
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