]> Git Repo - qemu.git/blob - tests/bios-tables-test.c
iotests: Add preallocated growth test for qcow2
[qemu.git] / tests / bios-tables-test.c
1 /*
2  * Boot order test cases.
3  *
4  * Copyright (c) 2013 Red Hat Inc.
5  *
6  * Authors:
7  *  Michael S. Tsirkin <[email protected]>,
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 "qemu/osdep.h"
14 #include <glib/gstdio.h>
15 #include "qemu-common.h"
16 #include "hw/smbios/smbios.h"
17 #include "qemu/bitmap.h"
18 #include "acpi-utils.h"
19 #include "boot-sector.h"
20
21 #define MACHINE_PC "pc"
22 #define MACHINE_Q35 "q35"
23
24 #define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
25
26 typedef struct {
27     const char *machine;
28     const char *variant;
29     uint32_t rsdp_addr;
30     AcpiRsdpDescriptor rsdp_table;
31     AcpiRsdtDescriptorRev1 rsdt_table;
32     AcpiFadtDescriptorRev3 fadt_table;
33     AcpiFacsDescriptorRev1 facs_table;
34     uint32_t *rsdt_tables_addr;
35     int rsdt_tables_nr;
36     GArray *tables;
37     uint32_t smbios_ep_addr;
38     struct smbios_21_entry_point smbios_ep_table;
39     uint8_t *required_struct_types;
40     int required_struct_types_len;
41 } test_data;
42
43 static char disk[] = "tests/acpi-test-disk-XXXXXX";
44 static const char *data_dir = "tests/acpi-test-data";
45 #ifdef CONFIG_IASL
46 static const char *iasl = stringify(CONFIG_IASL);
47 #else
48 static const char *iasl;
49 #endif
50
51 static void free_test_data(test_data *data)
52 {
53     AcpiSdtTable *temp;
54     int i;
55
56     g_free(data->rsdt_tables_addr);
57
58     for (i = 0; i < data->tables->len; ++i) {
59         temp = &g_array_index(data->tables, AcpiSdtTable, i);
60         g_free(temp->aml);
61         if (temp->aml_file &&
62             !temp->tmp_files_retain &&
63             g_strstr_len(temp->aml_file, -1, "aml-")) {
64             unlink(temp->aml_file);
65         }
66         g_free(temp->aml_file);
67         g_free(temp->asl);
68         if (temp->asl_file &&
69             !temp->tmp_files_retain) {
70             unlink(temp->asl_file);
71         }
72         g_free(temp->asl_file);
73     }
74
75     g_array_free(data->tables, true);
76 }
77
78 static void test_acpi_rsdp_address(test_data *data)
79 {
80     uint32_t off = acpi_find_rsdp_address();
81     g_assert_cmphex(off, <, 0x100000);
82     data->rsdp_addr = off;
83 }
84
85 static void test_acpi_rsdp_table(test_data *data)
86 {
87     AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table;
88     uint32_t addr = data->rsdp_addr;
89
90     acpi_parse_rsdp_table(addr, rsdp_table);
91
92     /* rsdp checksum is not for the whole table, but for the first 20 bytes */
93     g_assert(!acpi_calc_checksum((uint8_t *)rsdp_table, 20));
94 }
95
96 static void test_acpi_rsdt_table(test_data *data)
97 {
98     AcpiRsdtDescriptorRev1 *rsdt_table = &data->rsdt_table;
99     uint32_t addr = data->rsdp_table.rsdt_physical_address;
100     uint32_t *tables;
101     int tables_nr;
102     uint8_t checksum;
103
104     /* read the header */
105     ACPI_READ_TABLE_HEADER(rsdt_table, addr);
106     ACPI_ASSERT_CMP(rsdt_table->signature, "RSDT");
107
108     /* compute the table entries in rsdt */
109     tables_nr = (rsdt_table->length - sizeof(AcpiRsdtDescriptorRev1)) /
110                 sizeof(uint32_t);
111     g_assert_cmpint(tables_nr, >, 0);
112
113     /* get the addresses of the tables pointed by rsdt */
114     tables = g_new0(uint32_t, tables_nr);
115     ACPI_READ_ARRAY_PTR(tables, tables_nr, addr);
116
117     checksum = acpi_calc_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
118                acpi_calc_checksum((uint8_t *)tables,
119                                   tables_nr * sizeof(uint32_t));
120     g_assert(!checksum);
121
122    /* SSDT tables after FADT */
123     data->rsdt_tables_addr = tables;
124     data->rsdt_tables_nr = tables_nr;
125 }
126
127 static void test_acpi_fadt_table(test_data *data)
128 {
129     AcpiFadtDescriptorRev3 *fadt_table = &data->fadt_table;
130     uint32_t addr;
131
132     /* FADT table comes first */
133     addr = data->rsdt_tables_addr[0];
134     ACPI_READ_TABLE_HEADER(fadt_table, addr);
135
136     ACPI_READ_FIELD(fadt_table->firmware_ctrl, addr);
137     ACPI_READ_FIELD(fadt_table->dsdt, addr);
138     ACPI_READ_FIELD(fadt_table->model, addr);
139     ACPI_READ_FIELD(fadt_table->reserved1, addr);
140     ACPI_READ_FIELD(fadt_table->sci_int, addr);
141     ACPI_READ_FIELD(fadt_table->smi_cmd, addr);
142     ACPI_READ_FIELD(fadt_table->acpi_enable, addr);
143     ACPI_READ_FIELD(fadt_table->acpi_disable, addr);
144     ACPI_READ_FIELD(fadt_table->S4bios_req, addr);
145     ACPI_READ_FIELD(fadt_table->reserved2, addr);
146     ACPI_READ_FIELD(fadt_table->pm1a_evt_blk, addr);
147     ACPI_READ_FIELD(fadt_table->pm1b_evt_blk, addr);
148     ACPI_READ_FIELD(fadt_table->pm1a_cnt_blk, addr);
149     ACPI_READ_FIELD(fadt_table->pm1b_cnt_blk, addr);
150     ACPI_READ_FIELD(fadt_table->pm2_cnt_blk, addr);
151     ACPI_READ_FIELD(fadt_table->pm_tmr_blk, addr);
152     ACPI_READ_FIELD(fadt_table->gpe0_blk, addr);
153     ACPI_READ_FIELD(fadt_table->gpe1_blk, addr);
154     ACPI_READ_FIELD(fadt_table->pm1_evt_len, addr);
155     ACPI_READ_FIELD(fadt_table->pm1_cnt_len, addr);
156     ACPI_READ_FIELD(fadt_table->pm2_cnt_len, addr);
157     ACPI_READ_FIELD(fadt_table->pm_tmr_len, addr);
158     ACPI_READ_FIELD(fadt_table->gpe0_blk_len, addr);
159     ACPI_READ_FIELD(fadt_table->gpe1_blk_len, addr);
160     ACPI_READ_FIELD(fadt_table->gpe1_base, addr);
161     ACPI_READ_FIELD(fadt_table->reserved3, addr);
162     ACPI_READ_FIELD(fadt_table->plvl2_lat, addr);
163     ACPI_READ_FIELD(fadt_table->plvl3_lat, addr);
164     ACPI_READ_FIELD(fadt_table->flush_size, addr);
165     ACPI_READ_FIELD(fadt_table->flush_stride, addr);
166     ACPI_READ_FIELD(fadt_table->duty_offset, addr);
167     ACPI_READ_FIELD(fadt_table->duty_width, addr);
168     ACPI_READ_FIELD(fadt_table->day_alrm, addr);
169     ACPI_READ_FIELD(fadt_table->mon_alrm, addr);
170     ACPI_READ_FIELD(fadt_table->century, addr);
171     ACPI_READ_FIELD(fadt_table->boot_flags, addr);
172     ACPI_READ_FIELD(fadt_table->reserved, addr);
173     ACPI_READ_FIELD(fadt_table->flags, addr);
174     ACPI_READ_GENERIC_ADDRESS(fadt_table->reset_register, addr);
175     ACPI_READ_FIELD(fadt_table->reset_value, addr);
176     ACPI_READ_FIELD(fadt_table->arm_boot_flags, addr);
177     ACPI_READ_FIELD(fadt_table->minor_revision, addr);
178     ACPI_READ_FIELD(fadt_table->x_facs, addr);
179     ACPI_READ_FIELD(fadt_table->x_dsdt, addr);
180     ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm1a_event_block, addr);
181     ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm1b_event_block, addr);
182     ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm1a_control_block, addr);
183     ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm1b_control_block, addr);
184     ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm2_control_block, addr);
185     ACPI_READ_GENERIC_ADDRESS(fadt_table->xpm_timer_block, addr);
186     ACPI_READ_GENERIC_ADDRESS(fadt_table->xgpe0_block, addr);
187     ACPI_READ_GENERIC_ADDRESS(fadt_table->xgpe1_block, addr);
188
189     ACPI_ASSERT_CMP(fadt_table->signature, "FACP");
190     g_assert(!acpi_calc_checksum((uint8_t *)fadt_table, fadt_table->length));
191 }
192
193 static void test_acpi_facs_table(test_data *data)
194 {
195     AcpiFacsDescriptorRev1 *facs_table = &data->facs_table;
196     uint32_t addr = data->fadt_table.firmware_ctrl;
197
198     ACPI_READ_FIELD(facs_table->signature, addr);
199     ACPI_READ_FIELD(facs_table->length, addr);
200     ACPI_READ_FIELD(facs_table->hardware_signature, addr);
201     ACPI_READ_FIELD(facs_table->firmware_waking_vector, addr);
202     ACPI_READ_FIELD(facs_table->global_lock, addr);
203     ACPI_READ_FIELD(facs_table->flags, addr);
204     ACPI_READ_ARRAY(facs_table->resverved3, addr);
205
206     ACPI_ASSERT_CMP(facs_table->signature, "FACS");
207 }
208
209 static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
210 {
211     uint8_t checksum;
212
213     ACPI_READ_TABLE_HEADER(&sdt_table->header, addr);
214
215     sdt_table->aml_len = sdt_table->header.length - sizeof(AcpiTableHeader);
216     sdt_table->aml = g_malloc0(sdt_table->aml_len);
217     ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
218
219     checksum = acpi_calc_checksum((uint8_t *)sdt_table,
220                                   sizeof(AcpiTableHeader)) +
221                acpi_calc_checksum((uint8_t *)sdt_table->aml,
222                                   sdt_table->aml_len);
223     g_assert(!checksum);
224 }
225
226 static void test_acpi_dsdt_table(test_data *data)
227 {
228     AcpiSdtTable dsdt_table;
229     uint32_t addr = data->fadt_table.dsdt;
230
231     memset(&dsdt_table, 0, sizeof(dsdt_table));
232     data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
233
234     test_dst_table(&dsdt_table, addr);
235     ACPI_ASSERT_CMP(dsdt_table.header.signature, "DSDT");
236
237     /* Place DSDT first */
238     g_array_append_val(data->tables, dsdt_table);
239 }
240
241 static void test_acpi_tables(test_data *data)
242 {
243     int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */
244     int i;
245
246     for (i = 0; i < tables_nr; i++) {
247         AcpiSdtTable ssdt_table;
248
249         memset(&ssdt_table, 0, sizeof(ssdt_table));
250         uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */
251         test_dst_table(&ssdt_table, addr);
252         g_array_append_val(data->tables, ssdt_table);
253     }
254 }
255
256 static void dump_aml_files(test_data *data, bool rebuild)
257 {
258     AcpiSdtTable *sdt;
259     GError *error = NULL;
260     gchar *aml_file = NULL;
261     gint fd;
262     ssize_t ret;
263     int i;
264
265     for (i = 0; i < data->tables->len; ++i) {
266         const char *ext = data->variant ? data->variant : "";
267         sdt = &g_array_index(data->tables, AcpiSdtTable, i);
268         g_assert(sdt->aml);
269
270         if (rebuild) {
271             uint32_t signature = cpu_to_le32(sdt->header.signature);
272             aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine,
273                                        (gchar *)&signature, ext);
274             fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
275                         S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
276         } else {
277             fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
278             g_assert_no_error(error);
279         }
280         g_assert(fd >= 0);
281
282         ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader));
283         g_assert(ret == sizeof(AcpiTableHeader));
284         ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
285         g_assert(ret == sdt->aml_len);
286
287         close(fd);
288
289         g_free(aml_file);
290     }
291 }
292
293 static bool compare_signature(AcpiSdtTable *sdt, const char *signature)
294 {
295    return !memcmp(&sdt->header.signature, signature, 4);
296 }
297
298 static bool load_asl(GArray *sdts, AcpiSdtTable *sdt)
299 {
300     AcpiSdtTable *temp;
301     GError *error = NULL;
302     GString *command_line = g_string_new(iasl);
303     gint fd;
304     gchar *out, *out_err;
305     gboolean ret;
306     int i;
307
308     fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error);
309     g_assert_no_error(error);
310     close(fd);
311
312     /* build command line */
313     g_string_append_printf(command_line, " -p %s ", sdt->asl_file);
314     if (compare_signature(sdt, "DSDT") ||
315         compare_signature(sdt, "SSDT")) {
316         for (i = 0; i < sdts->len; ++i) {
317             temp = &g_array_index(sdts, AcpiSdtTable, i);
318             if (compare_signature(temp, "DSDT") ||
319                 compare_signature(temp, "SSDT")) {
320                 g_string_append_printf(command_line, "-e %s ", temp->aml_file);
321             }
322         }
323     }
324     g_string_append_printf(command_line, "-d %s", sdt->aml_file);
325
326     /* pass 'out' and 'out_err' in order to be redirected */
327     ret = g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error);
328     g_assert_no_error(error);
329     if (ret) {
330         ret = g_file_get_contents(sdt->asl_file, (gchar **)&sdt->asl,
331                                   &sdt->asl_len, &error);
332         g_assert(ret);
333         g_assert_no_error(error);
334         ret = (sdt->asl_len > 0);
335     }
336
337     g_free(out);
338     g_free(out_err);
339     g_string_free(command_line, true);
340
341     return !ret;
342 }
343
344 #define COMMENT_END "*/"
345 #define DEF_BLOCK "DefinitionBlock ("
346 #define BLOCK_NAME_END ","
347
348 static GString *normalize_asl(gchar *asl_code)
349 {
350     GString *asl = g_string_new(asl_code);
351     gchar *comment, *block_name;
352
353     /* strip comments (different generation days) */
354     comment = g_strstr_len(asl->str, asl->len, COMMENT_END);
355     if (comment) {
356         comment += strlen(COMMENT_END);
357         while (*comment == '\n') {
358             comment++;
359         }
360         asl = g_string_erase(asl, 0, comment - asl->str);
361     }
362
363     /* strip def block name (it has file path in it) */
364     if (g_str_has_prefix(asl->str, DEF_BLOCK)) {
365         block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END);
366         g_assert(block_name);
367         asl = g_string_erase(asl, 0,
368                              block_name + sizeof(BLOCK_NAME_END) - asl->str);
369     }
370
371     return asl;
372 }
373
374 static GArray *load_expected_aml(test_data *data)
375 {
376     int i;
377     AcpiSdtTable *sdt;
378     GError *error = NULL;
379     gboolean ret;
380
381     GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable));
382     for (i = 0; i < data->tables->len; ++i) {
383         AcpiSdtTable exp_sdt;
384         uint32_t signature;
385         gchar *aml_file = NULL;
386         const char *ext = data->variant ? data->variant : "";
387
388         sdt = &g_array_index(data->tables, AcpiSdtTable, i);
389
390         memset(&exp_sdt, 0, sizeof(exp_sdt));
391         exp_sdt.header.signature = sdt->header.signature;
392
393         signature = cpu_to_le32(sdt->header.signature);
394
395 try_again:
396         aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine,
397                                    (gchar *)&signature, ext);
398         if (getenv("V")) {
399             fprintf(stderr, "\nLooking for expected file '%s'\n", aml_file);
400         }
401         if (g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
402             exp_sdt.aml_file = aml_file;
403         } else if (*ext != '\0') {
404             /* try fallback to generic (extention less) expected file */
405             ext = "";
406             g_free(aml_file);
407             goto try_again;
408         }
409         g_assert(exp_sdt.aml_file);
410         if (getenv("V")) {
411             fprintf(stderr, "\nUsing expected file '%s'\n", aml_file);
412         }
413         ret = g_file_get_contents(aml_file, &exp_sdt.aml,
414                                   &exp_sdt.aml_len, &error);
415         g_assert(ret);
416         g_assert_no_error(error);
417         g_assert(exp_sdt.aml);
418         g_assert(exp_sdt.aml_len);
419
420         g_array_append_val(exp_tables, exp_sdt);
421     }
422
423     return exp_tables;
424 }
425
426 static void test_acpi_asl(test_data *data)
427 {
428     int i;
429     AcpiSdtTable *sdt, *exp_sdt;
430     test_data exp_data;
431     gboolean exp_err, err;
432
433     memset(&exp_data, 0, sizeof(exp_data));
434     exp_data.tables = load_expected_aml(data);
435     dump_aml_files(data, false);
436     for (i = 0; i < data->tables->len; ++i) {
437         GString *asl, *exp_asl;
438
439         sdt = &g_array_index(data->tables, AcpiSdtTable, i);
440         exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
441
442         err = load_asl(data->tables, sdt);
443         asl = normalize_asl(sdt->asl);
444
445         exp_err = load_asl(exp_data.tables, exp_sdt);
446         exp_asl = normalize_asl(exp_sdt->asl);
447
448         /* TODO: check for warnings */
449         g_assert(!err || exp_err);
450
451         if (g_strcmp0(asl->str, exp_asl->str)) {
452             if (exp_err) {
453                 fprintf(stderr,
454                         "Warning! iasl couldn't parse the expected aml\n");
455             } else {
456                 uint32_t signature = cpu_to_le32(exp_sdt->header.signature);
457                 sdt->tmp_files_retain = true;
458                 exp_sdt->tmp_files_retain = true;
459                 fprintf(stderr,
460                         "acpi-test: Warning! %.4s mismatch. "
461                         "Actual [asl:%s, aml:%s], Expected [asl:%s, aml:%s].\n",
462                         (gchar *)&signature,
463                         sdt->asl_file, sdt->aml_file,
464                         exp_sdt->asl_file, exp_sdt->aml_file);
465                 if (getenv("V")) {
466                     const char *diff_cmd = getenv("DIFF");
467                     if (diff_cmd) {
468                         int ret G_GNUC_UNUSED;
469                         char *diff = g_strdup_printf("%s %s %s", diff_cmd,
470                             exp_sdt->asl_file, sdt->asl_file);
471                         ret = system(diff) ;
472                         g_free(diff);
473                     } else {
474                         fprintf(stderr, "acpi-test: Warning. not showing "
475                             "difference since no diff utility is specified. "
476                             "Set 'DIFF' environment variable to a preferred "
477                             "diff utility and run 'make V=1 check' again to "
478                             "see ASL difference.");
479                     }
480                 }
481           }
482         }
483         g_string_free(asl, true);
484         g_string_free(exp_asl, true);
485     }
486
487     free_test_data(&exp_data);
488 }
489
490 static bool smbios_ep_table_ok(test_data *data)
491 {
492     struct smbios_21_entry_point *ep_table = &data->smbios_ep_table;
493     uint32_t addr = data->smbios_ep_addr;
494
495     ACPI_READ_ARRAY(ep_table->anchor_string, addr);
496     if (memcmp(ep_table->anchor_string, "_SM_", 4)) {
497         return false;
498     }
499     ACPI_READ_FIELD(ep_table->checksum, addr);
500     ACPI_READ_FIELD(ep_table->length, addr);
501     ACPI_READ_FIELD(ep_table->smbios_major_version, addr);
502     ACPI_READ_FIELD(ep_table->smbios_minor_version, addr);
503     ACPI_READ_FIELD(ep_table->max_structure_size, addr);
504     ACPI_READ_FIELD(ep_table->entry_point_revision, addr);
505     ACPI_READ_ARRAY(ep_table->formatted_area, addr);
506     ACPI_READ_ARRAY(ep_table->intermediate_anchor_string, addr);
507     if (memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5)) {
508         return false;
509     }
510     ACPI_READ_FIELD(ep_table->intermediate_checksum, addr);
511     ACPI_READ_FIELD(ep_table->structure_table_length, addr);
512     if (ep_table->structure_table_length == 0) {
513         return false;
514     }
515     ACPI_READ_FIELD(ep_table->structure_table_address, addr);
516     ACPI_READ_FIELD(ep_table->number_of_structures, addr);
517     if (ep_table->number_of_structures == 0) {
518         return false;
519     }
520     ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
521     if (acpi_calc_checksum((uint8_t *)ep_table, sizeof *ep_table) ||
522         acpi_calc_checksum((uint8_t *)ep_table + 0x10,
523                            sizeof *ep_table - 0x10)) {
524         return false;
525     }
526     return true;
527 }
528
529 static void test_smbios_entry_point(test_data *data)
530 {
531     uint32_t off;
532
533     /* find smbios entry point structure */
534     for (off = 0xf0000; off < 0x100000; off += 0x10) {
535         uint8_t sig[] = "_SM_";
536         int i;
537
538         for (i = 0; i < sizeof sig - 1; ++i) {
539             sig[i] = readb(off + i);
540         }
541
542         if (!memcmp(sig, "_SM_", sizeof sig)) {
543             /* signature match, but is this a valid entry point? */
544             data->smbios_ep_addr = off;
545             if (smbios_ep_table_ok(data)) {
546                 break;
547             }
548         }
549     }
550
551     g_assert_cmphex(off, <, 0x100000);
552 }
553
554 static inline bool smbios_single_instance(uint8_t type)
555 {
556     switch (type) {
557     case 0:
558     case 1:
559     case 2:
560     case 3:
561     case 16:
562     case 32:
563     case 127:
564         return true;
565     default:
566         return false;
567     }
568 }
569
570 static void test_smbios_structs(test_data *data)
571 {
572     DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 };
573     struct smbios_21_entry_point *ep_table = &data->smbios_ep_table;
574     uint32_t addr = ep_table->structure_table_address;
575     int i, len, max_len = 0;
576     uint8_t type, prv, crt;
577
578     /* walk the smbios tables */
579     for (i = 0; i < ep_table->number_of_structures; i++) {
580
581         /* grab type and formatted area length from struct header */
582         type = readb(addr);
583         g_assert_cmpuint(type, <=, SMBIOS_MAX_TYPE);
584         len = readb(addr + 1);
585
586         /* single-instance structs must not have been encountered before */
587         if (smbios_single_instance(type)) {
588             g_assert(!test_bit(type, struct_bitmap));
589         }
590         set_bit(type, struct_bitmap);
591
592         /* seek to end of unformatted string area of this struct ("\0\0") */
593         prv = crt = 1;
594         while (prv || crt) {
595             prv = crt;
596             crt = readb(addr + len);
597             len++;
598         }
599
600         /* keep track of max. struct size */
601         if (max_len < len) {
602             max_len = len;
603             g_assert_cmpuint(max_len, <=, ep_table->max_structure_size);
604         }
605
606         /* start of next structure */
607         addr += len;
608     }
609
610     /* total table length and max struct size must match entry point values */
611     g_assert_cmpuint(ep_table->structure_table_length, ==,
612                      addr - ep_table->structure_table_address);
613     g_assert_cmpuint(ep_table->max_structure_size, ==, max_len);
614
615     /* required struct types must all be present */
616     for (i = 0; i < data->required_struct_types_len; i++) {
617         g_assert(test_bit(data->required_struct_types[i], struct_bitmap));
618     }
619 }
620
621 static void test_acpi_one(const char *params, test_data *data)
622 {
623     char *args;
624
625     /* Disable kernel irqchip to be able to override apic irq0. */
626     args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
627                            "-net none -display none %s "
628                            "-drive id=hd0,if=none,file=%s,format=raw "
629                            "-device ide-hd,drive=hd0 ",
630                            data->machine, "kvm:tcg",
631                            params ? params : "", disk);
632
633     qtest_start(args);
634
635     boot_sector_test();
636
637     test_acpi_rsdp_address(data);
638     test_acpi_rsdp_table(data);
639     test_acpi_rsdt_table(data);
640     test_acpi_fadt_table(data);
641     test_acpi_facs_table(data);
642     test_acpi_dsdt_table(data);
643     test_acpi_tables(data);
644
645     if (iasl) {
646         if (getenv(ACPI_REBUILD_EXPECTED_AML)) {
647             dump_aml_files(data, true);
648         } else {
649             test_acpi_asl(data);
650         }
651     }
652
653     test_smbios_entry_point(data);
654     test_smbios_structs(data);
655
656     qtest_quit(global_qtest);
657     g_free(args);
658 }
659
660 static uint8_t base_required_struct_types[] = {
661     0, 1, 3, 4, 16, 17, 19, 32, 127
662 };
663
664 static void test_acpi_piix4_tcg(void)
665 {
666     test_data data;
667
668     /* Supplying -machine accel argument overrides the default (qtest).
669      * This is to make guest actually run.
670      */
671     memset(&data, 0, sizeof(data));
672     data.machine = MACHINE_PC;
673     data.required_struct_types = base_required_struct_types;
674     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
675     test_acpi_one(NULL, &data);
676     free_test_data(&data);
677 }
678
679 static void test_acpi_piix4_tcg_bridge(void)
680 {
681     test_data data;
682
683     memset(&data, 0, sizeof(data));
684     data.machine = MACHINE_PC;
685     data.variant = ".bridge";
686     data.required_struct_types = base_required_struct_types;
687     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
688     test_acpi_one("-device pci-bridge,chassis_nr=1", &data);
689     free_test_data(&data);
690 }
691
692 static void test_acpi_q35_tcg(void)
693 {
694     test_data data;
695
696     memset(&data, 0, sizeof(data));
697     data.machine = MACHINE_Q35;
698     data.required_struct_types = base_required_struct_types;
699     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
700     test_acpi_one(NULL, &data);
701     free_test_data(&data);
702 }
703
704 static void test_acpi_q35_tcg_bridge(void)
705 {
706     test_data data;
707
708     memset(&data, 0, sizeof(data));
709     data.machine = MACHINE_Q35;
710     data.variant = ".bridge";
711     data.required_struct_types = base_required_struct_types;
712     data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
713     test_acpi_one("-device pci-bridge,chassis_nr=1",
714                   &data);
715     free_test_data(&data);
716 }
717
718 static void test_acpi_piix4_tcg_cphp(void)
719 {
720     test_data data;
721
722     memset(&data, 0, sizeof(data));
723     data.machine = MACHINE_PC;
724     data.variant = ".cphp";
725     test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6"
726                   " -numa node -numa node"
727                   " -numa dist,src=0,dst=1,val=21",
728                   &data);
729     free_test_data(&data);
730 }
731
732 static void test_acpi_q35_tcg_cphp(void)
733 {
734     test_data data;
735
736     memset(&data, 0, sizeof(data));
737     data.machine = MACHINE_Q35;
738     data.variant = ".cphp";
739     test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6"
740                   " -numa node -numa node"
741                   " -numa dist,src=0,dst=1,val=21",
742                   &data);
743     free_test_data(&data);
744 }
745
746 static uint8_t ipmi_required_struct_types[] = {
747     0, 1, 3, 4, 16, 17, 19, 32, 38, 127
748 };
749
750 static void test_acpi_q35_tcg_ipmi(void)
751 {
752     test_data data;
753
754     memset(&data, 0, sizeof(data));
755     data.machine = MACHINE_Q35;
756     data.variant = ".ipmibt";
757     data.required_struct_types = ipmi_required_struct_types;
758     data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types);
759     test_acpi_one("-device ipmi-bmc-sim,id=bmc0"
760                   " -device isa-ipmi-bt,bmc=bmc0",
761                   &data);
762     free_test_data(&data);
763 }
764
765 static void test_acpi_piix4_tcg_ipmi(void)
766 {
767     test_data data;
768
769     /* Supplying -machine accel argument overrides the default (qtest).
770      * This is to make guest actually run.
771      */
772     memset(&data, 0, sizeof(data));
773     data.machine = MACHINE_PC;
774     data.variant = ".ipmikcs";
775     data.required_struct_types = ipmi_required_struct_types;
776     data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types);
777     test_acpi_one("-device ipmi-bmc-sim,id=bmc0"
778                   " -device isa-ipmi-kcs,irq=0,bmc=bmc0",
779                   &data);
780     free_test_data(&data);
781 }
782
783 static void test_acpi_q35_tcg_memhp(void)
784 {
785     test_data data;
786
787     memset(&data, 0, sizeof(data));
788     data.machine = MACHINE_Q35;
789     data.variant = ".memhp";
790     test_acpi_one(" -m 128,slots=3,maxmem=1G"
791                   " -numa node -numa node"
792                   " -numa dist,src=0,dst=1,val=21",
793                   &data);
794     free_test_data(&data);
795 }
796
797 static void test_acpi_piix4_tcg_memhp(void)
798 {
799     test_data data;
800
801     memset(&data, 0, sizeof(data));
802     data.machine = MACHINE_PC;
803     data.variant = ".memhp";
804     test_acpi_one(" -m 128,slots=3,maxmem=1G"
805                   " -numa node -numa node"
806                   " -numa dist,src=0,dst=1,val=21",
807                   &data);
808     free_test_data(&data);
809 }
810
811 int main(int argc, char *argv[])
812 {
813     const char *arch = qtest_get_arch();
814     int ret;
815
816     ret = boot_sector_init(disk);
817     if(ret)
818         return ret;
819
820     g_test_init(&argc, &argv, NULL);
821
822     if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
823         qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
824         qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
825         qtest_add_func("acpi/q35", test_acpi_q35_tcg);
826         qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge);
827         qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi);
828         qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi);
829         qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp);
830         qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp);
831         qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp);
832         qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp);
833     }
834     ret = g_test_run();
835     boot_sector_cleanup(disk);
836     return ret;
837 }
This page took 0.069844 seconds and 4 git commands to generate.