Statistics
| Branch: | Revision:

root / tests / acpi-test.c @ feature-archipelago

History | View | Annotate | Download (19.7 kB)

1
/*
2
 * Boot order test cases.
3
 *
4
 * Copyright (c) 2013 Red Hat Inc.
5
 *
6
 * Authors:
7
 *  Michael S. Tsirkin <mst@redhat.com>,
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10
 * See the COPYING file in the top-level directory.
11
 */
12

    
13
#include <string.h>
14
#include <stdio.h>
15
#include <glib.h>
16
#include <glib/gstdio.h>
17
#include "qemu-common.h"
18
#include "libqtest.h"
19
#include "qemu/compiler.h"
20
#include "hw/i386/acpi-defs.h"
21

    
22
#define MACHINE_PC "pc"
23
#define MACHINE_Q35 "q35"
24

    
25
#define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
26
#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
27

    
28
/* DSDT and SSDTs format */
29
typedef struct {
30
    AcpiTableHeader header;
31
    gchar *aml;            /* aml bytecode from guest */
32
    gsize aml_len;
33
    gchar *aml_file;
34
    gchar *asl;            /* asl code generated from aml */
35
    gsize asl_len;
36
    gchar *asl_file;
37
    bool asl_file_retain;   /* do not delete the temp asl */
38
} QEMU_PACKED AcpiSdtTable;
39

    
40
typedef struct {
41
    const char *machine;
42
    uint32_t rsdp_addr;
43
    AcpiRsdpDescriptor rsdp_table;
44
    AcpiRsdtDescriptorRev1 rsdt_table;
45
    AcpiFadtDescriptorRev1 fadt_table;
46
    AcpiFacsDescriptorRev1 facs_table;
47
    uint32_t *rsdt_tables_addr;
48
    int rsdt_tables_nr;
49
    GArray *tables;
50
} test_data;
51

    
52
#define LOW(x) ((x) & 0xff)
53
#define HIGH(x) ((x) >> 8)
54

    
55
#define SIGNATURE 0xdead
56
#define SIGNATURE_OFFSET 0x10
57
#define BOOT_SECTOR_ADDRESS 0x7c00
58

    
59
#define ACPI_READ_FIELD(field, addr)           \
60
    do {                                       \
61
        switch (sizeof(field)) {               \
62
        case 1:                                \
63
            field = readb(addr);               \
64
            break;                             \
65
        case 2:                                \
66
            field = readw(addr);               \
67
            break;                             \
68
        case 4:                                \
69
            field = readl(addr);               \
70
            break;                             \
71
        case 8:                                \
72
            field = readq(addr);               \
73
            break;                             \
74
        default:                               \
75
            g_assert(false);                   \
76
        }                                      \
77
        addr += sizeof(field);                  \
78
    } while (0);
79

    
80
#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
81
    do {                                        \
82
        int idx;                                \
83
        for (idx = 0; idx < length; ++idx) {    \
84
            ACPI_READ_FIELD(arr[idx], addr);    \
85
        }                                       \
86
    } while (0);
87

    
88
#define ACPI_READ_ARRAY(arr, addr)                               \
89
    ACPI_READ_ARRAY_PTR(arr, sizeof(arr)/sizeof(arr[0]), addr)
90

    
91
#define ACPI_READ_TABLE_HEADER(table, addr)                      \
92
    do {                                                         \
93
        ACPI_READ_FIELD((table)->signature, addr);               \
94
        ACPI_READ_FIELD((table)->length, addr);                  \
95
        ACPI_READ_FIELD((table)->revision, addr);                \
96
        ACPI_READ_FIELD((table)->checksum, addr);                \
97
        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
98
        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
99
        ACPI_READ_FIELD((table)->oem_revision, addr);            \
100
        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
101
        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
102
    } while (0);
103

    
104
/* Boot sector code: write SIGNATURE into memory,
105
 * then halt.
106
 * Q35 machine requires a minimum 0x7e000 bytes disk.
107
 * (bug or feature?)
108
 */
109
static uint8_t boot_sector[0x7e000] = {
110
    /* 7c00: mov $0xdead,%ax */
111
    [0x00] = 0xb8,
112
    [0x01] = LOW(SIGNATURE),
113
    [0x02] = HIGH(SIGNATURE),
114
    /* 7c03:  mov %ax,0x7c10 */
115
    [0x03] = 0xa3,
116
    [0x04] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
117
    [0x05] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
118
    /* 7c06: cli */
119
    [0x06] = 0xfa,
120
    /* 7c07: hlt */
121
    [0x07] = 0xf4,
122
    /* 7c08: jmp 0x7c07=0x7c0a-3 */
123
    [0x08] = 0xeb,
124
    [0x09] = LOW(-3),
125
    /* We mov 0xdead here: set value to make debugging easier */
126
    [SIGNATURE_OFFSET] = LOW(0xface),
127
    [SIGNATURE_OFFSET + 1] = HIGH(0xface),
128
    /* End of boot sector marker */
129
    [0x1FE] = 0x55,
130
    [0x1FF] = 0xAA,
131
};
132

    
133
static const char *disk = "tests/acpi-test-disk.raw";
134
static const char *data_dir = "tests/acpi-test-data";
135
#ifdef CONFIG_IASL
136
static const char *iasl = stringify(CONFIG_IASL);
137
#else
138
static const char *iasl;
139
#endif
140

    
141
static void free_test_data(test_data *data)
142
{
143
    AcpiSdtTable *temp;
144
    int i;
145

    
146
    if (data->rsdt_tables_addr) {
147
        g_free(data->rsdt_tables_addr);
148
    }
149

    
150
    for (i = 0; i < data->tables->len; ++i) {
151
        temp = &g_array_index(data->tables, AcpiSdtTable, i);
152
        if (temp->aml) {
153
            g_free(temp->aml);
154
        }
155
        if (temp->aml_file) {
156
            if (g_strstr_len(temp->aml_file, -1, "aml-")) {
157
                unlink(temp->aml_file);
158
            }
159
            g_free(temp->aml_file);
160
        }
161
        if (temp->asl) {
162
            g_free(temp->asl);
163
        }
164
        if (temp->asl_file) {
165
            if (!temp->asl_file_retain) {
166
                unlink(temp->asl_file);
167
            }
168
            g_free(temp->asl_file);
169
        }
170
    }
171

    
172
    g_array_free(data->tables, false);
173
}
174

    
175
static uint8_t acpi_checksum(const uint8_t *data, int len)
176
{
177
    int i;
178
    uint8_t sum = 0;
179

    
180
    for (i = 0; i < len; i++) {
181
        sum += data[i];
182
    }
183

    
184
    return sum;
185
}
186

    
187
static void test_acpi_rsdp_address(test_data *data)
188
{
189
    uint32_t off;
190

    
191
    /* OK, now find RSDP */
192
    for (off = 0xf0000; off < 0x100000; off += 0x10) {
193
        uint8_t sig[] = "RSD PTR ";
194
        int i;
195

    
196
        for (i = 0; i < sizeof sig - 1; ++i) {
197
            sig[i] = readb(off + i);
198
        }
199

    
200
        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
201
            break;
202
        }
203
    }
204

    
205
    g_assert_cmphex(off, <, 0x100000);
206
    data->rsdp_addr = off;
207
}
208

    
209
static void test_acpi_rsdp_table(test_data *data)
210
{
211
    AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table;
212
    uint32_t addr = data->rsdp_addr;
213

    
214
    ACPI_READ_FIELD(rsdp_table->signature, addr);
215
    g_assert_cmphex(rsdp_table->signature, ==, ACPI_RSDP_SIGNATURE);
216

    
217
    ACPI_READ_FIELD(rsdp_table->checksum, addr);
218
    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
219
    ACPI_READ_FIELD(rsdp_table->revision, addr);
220
    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
221
    ACPI_READ_FIELD(rsdp_table->length, addr);
222

    
223
    /* rsdp checksum is not for the whole table, but for the first 20 bytes */
224
    g_assert(!acpi_checksum((uint8_t *)rsdp_table, 20));
225
}
226

    
227
static void test_acpi_rsdt_table(test_data *data)
228
{
229
    AcpiRsdtDescriptorRev1 *rsdt_table = &data->rsdt_table;
230
    uint32_t addr = data->rsdp_table.rsdt_physical_address;
231
    uint32_t *tables;
232
    int tables_nr;
233
    uint8_t checksum;
234

    
235
    /* read the header */
236
    ACPI_READ_TABLE_HEADER(rsdt_table, addr);
237
    g_assert_cmphex(rsdt_table->signature, ==, ACPI_RSDT_SIGNATURE);
238

    
239
    /* compute the table entries in rsdt */
240
    tables_nr = (rsdt_table->length - sizeof(AcpiRsdtDescriptorRev1)) /
241
                sizeof(uint32_t);
242
    g_assert_cmpint(tables_nr, >, 0);
243

    
244
    /* get the addresses of the tables pointed by rsdt */
245
    tables = g_new0(uint32_t, tables_nr);
246
    ACPI_READ_ARRAY_PTR(tables, tables_nr, addr);
247

    
248
    checksum = acpi_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
249
               acpi_checksum((uint8_t *)tables, tables_nr * sizeof(uint32_t));
250
    g_assert(!checksum);
251

    
252
   /* SSDT tables after FADT */
253
    data->rsdt_tables_addr = tables;
254
    data->rsdt_tables_nr = tables_nr;
255
}
256

    
257
static void test_acpi_fadt_table(test_data *data)
258
{
259
    AcpiFadtDescriptorRev1 *fadt_table = &data->fadt_table;
260
    uint32_t addr;
261

    
262
    /* FADT table comes first */
263
    addr = data->rsdt_tables_addr[0];
264
    ACPI_READ_TABLE_HEADER(fadt_table, addr);
265

    
266
    ACPI_READ_FIELD(fadt_table->firmware_ctrl, addr);
267
    ACPI_READ_FIELD(fadt_table->dsdt, addr);
268
    ACPI_READ_FIELD(fadt_table->model, addr);
269
    ACPI_READ_FIELD(fadt_table->reserved1, addr);
270
    ACPI_READ_FIELD(fadt_table->sci_int, addr);
271
    ACPI_READ_FIELD(fadt_table->smi_cmd, addr);
272
    ACPI_READ_FIELD(fadt_table->acpi_enable, addr);
273
    ACPI_READ_FIELD(fadt_table->acpi_disable, addr);
274
    ACPI_READ_FIELD(fadt_table->S4bios_req, addr);
275
    ACPI_READ_FIELD(fadt_table->reserved2, addr);
276
    ACPI_READ_FIELD(fadt_table->pm1a_evt_blk, addr);
277
    ACPI_READ_FIELD(fadt_table->pm1b_evt_blk, addr);
278
    ACPI_READ_FIELD(fadt_table->pm1a_cnt_blk, addr);
279
    ACPI_READ_FIELD(fadt_table->pm1b_cnt_blk, addr);
280
    ACPI_READ_FIELD(fadt_table->pm2_cnt_blk, addr);
281
    ACPI_READ_FIELD(fadt_table->pm_tmr_blk, addr);
282
    ACPI_READ_FIELD(fadt_table->gpe0_blk, addr);
283
    ACPI_READ_FIELD(fadt_table->gpe1_blk, addr);
284
    ACPI_READ_FIELD(fadt_table->pm1_evt_len, addr);
285
    ACPI_READ_FIELD(fadt_table->pm1_cnt_len, addr);
286
    ACPI_READ_FIELD(fadt_table->pm2_cnt_len, addr);
287
    ACPI_READ_FIELD(fadt_table->pm_tmr_len, addr);
288
    ACPI_READ_FIELD(fadt_table->gpe0_blk_len, addr);
289
    ACPI_READ_FIELD(fadt_table->gpe1_blk_len, addr);
290
    ACPI_READ_FIELD(fadt_table->gpe1_base, addr);
291
    ACPI_READ_FIELD(fadt_table->reserved3, addr);
292
    ACPI_READ_FIELD(fadt_table->plvl2_lat, addr);
293
    ACPI_READ_FIELD(fadt_table->plvl3_lat, addr);
294
    ACPI_READ_FIELD(fadt_table->flush_size, addr);
295
    ACPI_READ_FIELD(fadt_table->flush_stride, addr);
296
    ACPI_READ_FIELD(fadt_table->duty_offset, addr);
297
    ACPI_READ_FIELD(fadt_table->duty_width, addr);
298
    ACPI_READ_FIELD(fadt_table->day_alrm, addr);
299
    ACPI_READ_FIELD(fadt_table->mon_alrm, addr);
300
    ACPI_READ_FIELD(fadt_table->century, addr);
301
    ACPI_READ_FIELD(fadt_table->reserved4, addr);
302
    ACPI_READ_FIELD(fadt_table->reserved4a, addr);
303
    ACPI_READ_FIELD(fadt_table->reserved4b, addr);
304
    ACPI_READ_FIELD(fadt_table->flags, addr);
305

    
306
    g_assert_cmphex(fadt_table->signature, ==, ACPI_FACP_SIGNATURE);
307
    g_assert(!acpi_checksum((uint8_t *)fadt_table, fadt_table->length));
308
}
309

    
310
static void test_acpi_facs_table(test_data *data)
311
{
312
    AcpiFacsDescriptorRev1 *facs_table = &data->facs_table;
313
    uint32_t addr = data->fadt_table.firmware_ctrl;
314

    
315
    ACPI_READ_FIELD(facs_table->signature, addr);
316
    ACPI_READ_FIELD(facs_table->length, addr);
317
    ACPI_READ_FIELD(facs_table->hardware_signature, addr);
318
    ACPI_READ_FIELD(facs_table->firmware_waking_vector, addr);
319
    ACPI_READ_FIELD(facs_table->global_lock, addr);
320
    ACPI_READ_FIELD(facs_table->flags, addr);
321
    ACPI_READ_ARRAY(facs_table->resverved3, addr);
322

    
323
    g_assert_cmphex(facs_table->signature, ==, ACPI_FACS_SIGNATURE);
324
}
325

    
326
static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
327
{
328
    uint8_t checksum;
329

    
330
    ACPI_READ_TABLE_HEADER(&sdt_table->header, addr);
331

    
332
    sdt_table->aml_len = sdt_table->header.length - sizeof(AcpiTableHeader);
333
    sdt_table->aml = g_malloc0(sdt_table->aml_len);
334
    ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
335

    
336
    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
337
               acpi_checksum((uint8_t *)sdt_table->aml, sdt_table->aml_len);
338
    g_assert(!checksum);
339
}
340

    
341
static void test_acpi_dsdt_table(test_data *data)
342
{
343
    AcpiSdtTable dsdt_table;
344
    uint32_t addr = data->fadt_table.dsdt;
345

    
346
    memset(&dsdt_table, 0, sizeof(dsdt_table));
347
    data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
348

    
349
    test_dst_table(&dsdt_table, addr);
350
    g_assert_cmphex(dsdt_table.header.signature, ==, ACPI_DSDT_SIGNATURE);
351

    
352
    /* Place DSDT first */
353
    g_array_append_val(data->tables, dsdt_table);
354
}
355

    
356
static void test_acpi_tables(test_data *data)
357
{
358
    int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
359
    int i;
360

    
361
    for (i = 0; i < tables_nr; i++) {
362
        AcpiSdtTable ssdt_table;
363

    
364
        memset(&ssdt_table, 0 , sizeof(ssdt_table));
365
        uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
366
        test_dst_table(&ssdt_table, addr);
367
        g_array_append_val(data->tables, ssdt_table);
368
    }
369
}
370

    
371
static void dump_aml_files(test_data *data, bool rebuild)
372
{
373
    AcpiSdtTable *sdt;
374
    GError *error = NULL;
375
    gchar *aml_file = NULL;
376
    gint fd;
377
    ssize_t ret;
378
    int i;
379

    
380
    for (i = 0; i < data->tables->len; ++i) {
381
        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
382
        g_assert(sdt->aml);
383

    
384
        if (rebuild) {
385
            aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
386
                                       (gchar *)&sdt->header.signature);
387
            fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
388
                        S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
389
        } else {
390
            fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
391
            g_assert_no_error(error);
392
        }
393
        g_assert(fd >= 0);
394

    
395
        ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader));
396
        g_assert(ret == sizeof(AcpiTableHeader));
397
        ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
398
        g_assert(ret == sdt->aml_len);
399

    
400
        close(fd);
401

    
402
        if (aml_file) {
403
            g_free(aml_file);
404
        }
405
    }
406
}
407

    
408
static bool compare_signature(AcpiSdtTable *sdt, uint32_t signature)
409
{
410
   return sdt->header.signature == signature;
411
}
412

    
413
static void load_asl(GArray *sdts, AcpiSdtTable *sdt)
414
{
415
    AcpiSdtTable *temp;
416
    GError *error = NULL;
417
    GString *command_line = g_string_new(iasl);
418
    gint fd;
419
    gchar *out, *out_err;
420
    gboolean ret;
421
    int i;
422

    
423
    fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error);
424
    g_assert_no_error(error);
425
    close(fd);
426

    
427
    /* build command line */
428
    g_string_append_printf(command_line, " -p %s ", sdt->asl_file);
429
    if (compare_signature(sdt, ACPI_DSDT_SIGNATURE) ||
430
        compare_signature(sdt, ACPI_SSDT_SIGNATURE)) {
431
        for (i = 0; i < sdts->len; ++i) {
432
            temp = &g_array_index(sdts, AcpiSdtTable, i);
433
            if (compare_signature(temp, ACPI_DSDT_SIGNATURE) ||
434
                compare_signature(temp, ACPI_SSDT_SIGNATURE)) {
435
                g_string_append_printf(command_line, "-e %s ", temp->aml_file);
436
            }
437
        }
438
    }
439
    g_string_append_printf(command_line, "-d %s", sdt->aml_file);
440

    
441
    /* pass 'out' and 'out_err' in order to be redirected */
442
    g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error);
443
    g_assert_no_error(error);
444

    
445
    ret = g_file_get_contents(sdt->asl_file, (gchar **)&sdt->asl,
446
                              &sdt->asl_len, &error);
447
    g_assert(ret);
448
    g_assert_no_error(error);
449
    g_assert(sdt->asl_len);
450

    
451
    g_free(out);
452
    g_free(out_err);
453
    g_string_free(command_line, true);
454
}
455

    
456
#define COMMENT_END "*/"
457
#define DEF_BLOCK "DefinitionBlock ("
458
#define BLOCK_NAME_END ".aml"
459

    
460
static GString *normalize_asl(gchar *asl_code)
461
{
462
    GString *asl = g_string_new(asl_code);
463
    gchar *comment, *block_name;
464

    
465
    /* strip comments (different generation days) */
466
    comment = g_strstr_len(asl->str, asl->len, COMMENT_END);
467
    if (comment) {
468
        asl = g_string_erase(asl, 0, comment + sizeof(COMMENT_END) - asl->str);
469
    }
470

    
471
    /* strip def block name (it has file path in it) */
472
    if (g_str_has_prefix(asl->str, DEF_BLOCK)) {
473
        block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END);
474
        g_assert(block_name);
475
        asl = g_string_erase(asl, 0,
476
                             block_name + sizeof(BLOCK_NAME_END) - asl->str);
477
    }
478

    
479
    return asl;
480
}
481

    
482
static GArray *load_expected_aml(test_data *data)
483
{
484
    int i;
485
    AcpiSdtTable *sdt;
486
    gchar *aml_file;
487
    GError *error = NULL;
488
    gboolean ret;
489

    
490
    GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
491
    for (i = 0; i < data->tables->len; ++i) {
492
        AcpiSdtTable exp_sdt;
493
        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
494

    
495
        memset(&exp_sdt, 0, sizeof(exp_sdt));
496
        exp_sdt.header.signature = sdt->header.signature;
497

    
498
        aml_file = g_strdup_printf("%s/%s/%.4s", data_dir, data->machine,
499
                                   (gchar *)&exp_sdt.header.signature);
500
        exp_sdt.aml_file = aml_file;
501
        g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
502
        ret = g_file_get_contents(aml_file, &exp_sdt.aml,
503
                                  &exp_sdt.aml_len, &error);
504
        g_assert(ret);
505
        g_assert_no_error(error);
506
        g_assert(exp_sdt.aml);
507
        g_assert(exp_sdt.aml_len);
508

    
509
        g_array_append_val(exp_tables, exp_sdt);
510
    }
511

    
512
    return exp_tables;
513
}
514

    
515
static void test_acpi_asl(test_data *data)
516
{
517
    int i;
518
    AcpiSdtTable *sdt, *exp_sdt;
519
    test_data exp_data;
520

    
521
    memset(&exp_data, 0, sizeof(exp_data));
522
    exp_data.tables = load_expected_aml(data);
523
    dump_aml_files(data, false);
524
    for (i = 0; i < data->tables->len; ++i) {
525
        GString *asl, *exp_asl;
526

    
527
        sdt = &g_array_index(data->tables, AcpiSdtTable, i);
528
        exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
529

    
530
        load_asl(data->tables, sdt);
531
        asl = normalize_asl(sdt->asl);
532

    
533
        load_asl(exp_data.tables, exp_sdt);
534
        exp_asl = normalize_asl(exp_sdt->asl);
535

    
536
        if (g_strcmp0(asl->str, exp_asl->str)) {
537
            sdt->asl_file_retain = true;
538
            exp_sdt->asl_file_retain = true;
539
            fprintf(stderr,
540
                    "acpi-test: Warning! %.4s mismatch. "
541
                    "Orig asl: %s, expected asl %s.\n",
542
                    (gchar *)&exp_sdt->header.signature,
543
                    sdt->asl_file, exp_sdt->asl_file);
544
        }
545
        g_string_free(asl, true);
546
        g_string_free(exp_asl, true);
547
    }
548

    
549
    free_test_data(&exp_data);
550
}
551

    
552
static void test_acpi_one(const char *params, test_data *data)
553
{
554
    char *args;
555
    uint8_t signature_low;
556
    uint8_t signature_high;
557
    uint16_t signature;
558
    int i;
559
    const char *device = "";
560

    
561
    if (!g_strcmp0(data->machine, MACHINE_Q35)) {
562
        device = ",id=hd -device ide-hd,drive=hd";
563
    }
564

    
565
    args = g_strdup_printf("-net none -display none %s -drive file=%s%s,",
566
                           params ? params : "", disk, device);
567
    qtest_start(args);
568

    
569
   /* Wait at most 1 minute */
570
#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
571
#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
572

    
573
    /* Poll until code has run and modified memory.  Once it has we know BIOS
574
     * initialization is done.  TODO: check that IP reached the halt
575
     * instruction.
576
     */
577
    for (i = 0; i < TEST_CYCLES; ++i) {
578
        signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
579
        signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
580
        signature = (signature_high << 8) | signature_low;
581
        if (signature == SIGNATURE) {
582
            break;
583
        }
584
        g_usleep(TEST_DELAY);
585
    }
586
    g_assert_cmphex(signature, ==, SIGNATURE);
587

    
588
    test_acpi_rsdp_address(data);
589
    test_acpi_rsdp_table(data);
590
    test_acpi_rsdt_table(data);
591
    test_acpi_fadt_table(data);
592
    test_acpi_facs_table(data);
593
    test_acpi_dsdt_table(data);
594
    test_acpi_tables(data);
595

    
596
    if (iasl) {
597
        if (getenv(ACPI_REBUILD_EXPECTED_AML)) {
598
            dump_aml_files(data, true);
599
        } else {
600
            test_acpi_asl(data);
601
        }
602
    }
603

    
604
    qtest_quit(global_qtest);
605
    g_free(args);
606
}
607

    
608
static void test_acpi_tcg(void)
609
{
610
    test_data data;
611

    
612
    /* Supplying -machine accel argument overrides the default (qtest).
613
     * This is to make guest actually run.
614
     */
615
    memset(&data, 0, sizeof(data));
616
    data.machine = MACHINE_PC;
617
    test_acpi_one("-machine accel=tcg", &data);
618
    free_test_data(&data);
619

    
620
    memset(&data, 0, sizeof(data));
621
    data.machine = MACHINE_Q35;
622
    test_acpi_one("-machine q35,accel=tcg", &data);
623
    free_test_data(&data);
624
}
625

    
626
int main(int argc, char *argv[])
627
{
628
    const char *arch = qtest_get_arch();
629
    FILE *f = fopen(disk, "w");
630
    int ret;
631
    fwrite(boot_sector, 1, sizeof boot_sector, f);
632
    fclose(f);
633

    
634
    g_test_init(&argc, &argv, NULL);
635

    
636
    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
637
        qtest_add_func("acpi/tcg", test_acpi_tcg);
638
    }
639
    ret = g_test_run();
640
    unlink(disk);
641
    return ret;
642
}