1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include "qemu/osdep.h"
16#include <glib/gstdio.h>
17#include "qemu-common.h"
18#include "qemu/bitmap.h"
19#include "acpi-utils.h"
20#include "boot-sector.h"
21
22uint8_t acpi_calc_checksum(const uint8_t *data, int len)
23{
24 int i;
25 uint8_t sum = 0;
26
27 for (i = 0; i < len; i++) {
28 sum += data[i];
29 }
30
31 return sum;
32}
33
34uint32_t acpi_find_rsdp_address(QTestState *qts)
35{
36 uint32_t off;
37
38
39 for (off = 0xf0000; off < 0x100000; off += 0x10) {
40 uint8_t sig[] = "RSD PTR ";
41 int i;
42
43 for (i = 0; i < sizeof sig - 1; ++i) {
44 sig[i] = qtest_readb(qts, off + i);
45 }
46
47 if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
48 break;
49 }
50 }
51 return off;
52}
53
54void acpi_fetch_rsdp_table(QTestState *qts, uint64_t addr, uint8_t *rsdp_table)
55{
56 uint8_t revision;
57
58
59 qtest_memread(qts, addr, rsdp_table, 20);
60 revision = rsdp_table[15 ];
61
62 switch (revision) {
63 case 0:
64 break;
65 case 2:
66
67 qtest_memread(qts, addr + 20, rsdp_table + 20, 16);
68 break;
69 default:
70 g_assert_not_reached();
71 }
72
73 ACPI_ASSERT_CMP64(*((uint64_t *)(rsdp_table)), "RSD PTR ");
74}
75
76
77
78
79
80
81void acpi_fetch_table(QTestState *qts, uint8_t **aml, uint32_t *aml_len,
82 const uint8_t *addr_ptr, int addr_size, const char *sig,
83 bool verify_checksum)
84{
85 uint32_t len;
86 uint64_t addr = 0;
87
88 g_assert(addr_size == 4 || addr_size == 8);
89 memcpy(&addr, addr_ptr , addr_size);
90 addr = le64_to_cpu(addr);
91 qtest_memread(qts, addr + 4, &len, 4);
92 *aml_len = le32_to_cpu(len);
93 *aml = g_malloc0(*aml_len);
94
95 qtest_memread(qts, addr, *aml, *aml_len);
96
97 if (sig) {
98 ACPI_ASSERT_CMP(**aml, sig);
99 }
100 if (verify_checksum) {
101 if (acpi_calc_checksum(*aml, *aml_len)) {
102 gint fd, ret;
103 char *fname = NULL;
104 GError *error = NULL;
105
106 fprintf(stderr, "Invalid '%.4s'(%d)\n", *aml, *aml_len);
107 fd = g_file_open_tmp("malformed-XXXXXX.dat", &fname, &error);
108 g_assert_no_error(error);
109 fprintf(stderr, "Dumping invalid table into '%s'\n", fname);
110 ret = qemu_write_full(fd, *aml, *aml_len);
111 g_assert(ret == *aml_len);
112 close(fd);
113 g_free(fname);
114 }
115 g_assert(!acpi_calc_checksum(*aml, *aml_len));
116 }
117}
118
119#define GUID_SIZE 16
120static const uint8_t AcpiTestSupportGuid[GUID_SIZE] = {
121 0xb1, 0xa6, 0x87, 0xab,
122 0x34, 0x20,
123 0xa0, 0xbd,
124 0x71, 0xbd, 0x37, 0x50, 0x07, 0x75, 0x77, 0x85 };
125
126typedef struct {
127 uint8_t signature_guid[GUID_SIZE];
128 uint64_t rsdp10;
129 uint64_t rsdp20;
130} __attribute__((packed)) UefiTestSupport;
131
132
133#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
134#define TEST_CYCLES MAX((600 * G_USEC_PER_SEC / TEST_DELAY), 1)
135#define MB 0x100000ULL
136uint64_t acpi_find_rsdp_address_uefi(QTestState *qts, uint64_t start,
137 uint64_t size)
138{
139 int i, j;
140 uint8_t data[GUID_SIZE];
141
142 for (i = 0; i < TEST_CYCLES; ++i) {
143 for (j = 0; j < size / MB; j++) {
144
145 uint64_t addr = start + j * MB;
146
147 qtest_memread(qts, addr, data, sizeof(data));
148 if (!memcmp(AcpiTestSupportGuid, data, sizeof(data))) {
149 UefiTestSupport ret;
150
151 qtest_memread(qts, addr, &ret, sizeof(ret));
152 ret.rsdp10 = le64_to_cpu(ret.rsdp10);
153 ret.rsdp20 = le64_to_cpu(ret.rsdp20);
154 return ret.rsdp20 ? ret.rsdp20 : ret.rsdp10;
155 }
156 }
157 g_usleep(TEST_DELAY);
158 }
159 g_assert_not_reached();
160 return 0;
161}
162