Merge https://gitlab.denx.de/u-boot/custodians/u-boot-spi
[platform/kernel/u-boot.git] / test / dm / acpi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Tests for ACPI table generation
4  *
5  * Copyright 2019 Google LLC
6  * Written by Simon Glass <sjg@chromium.org>
7  */
8
9 #include <common.h>
10 #include <console.h>
11 #include <dm.h>
12 #include <malloc.h>
13 #include <mapmem.h>
14 #include <version.h>
15 #include <tables_csum.h>
16 #include <version.h>
17 #include <acpi/acpi_table.h>
18 #include <dm/acpi.h>
19 #include <dm/test.h>
20 #include <test/ut.h>
21
22 #define ACPI_TEST_DEV_NAME      "ABCD"
23 #define BUF_SIZE                4096
24
25 static int testacpi_write_tables(const struct udevice *dev,
26                                  struct acpi_ctx *ctx)
27 {
28         struct acpi_dmar *dmar;
29         int ret;
30
31         dmar = (struct acpi_dmar *)ctx->current;
32         acpi_create_dmar(dmar, DMAR_INTR_REMAP);
33         ctx->current += sizeof(struct acpi_dmar);
34         ret = acpi_add_table(ctx, dmar);
35         if (ret)
36                 return log_msg_ret("add", ret);
37
38         return 0;
39 }
40
41 static int testacpi_get_name(const struct udevice *dev, char *out_name)
42 {
43         return acpi_copy_name(out_name, ACPI_TEST_DEV_NAME);
44 }
45
46 struct acpi_ops testacpi_ops = {
47         .get_name       = testacpi_get_name,
48         .write_tables   = testacpi_write_tables,
49 };
50
51 static const struct udevice_id testacpi_ids[] = {
52         { .compatible = "denx,u-boot-acpi-test" },
53         { }
54 };
55
56 U_BOOT_DRIVER(testacpi_drv) = {
57         .name   = "testacpi_drv",
58         .of_match       = testacpi_ids,
59         .id     = UCLASS_TEST_ACPI,
60         ACPI_OPS_PTR(&testacpi_ops)
61 };
62
63 UCLASS_DRIVER(testacpi) = {
64         .name           = "testacpi",
65         .id             = UCLASS_TEST_ACPI,
66 };
67
68 /* Test ACPI get_name() */
69 static int dm_test_acpi_get_name(struct unit_test_state *uts)
70 {
71         char name[ACPI_NAME_MAX];
72         struct udevice *dev;
73
74         ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev));
75         ut_assertok(acpi_get_name(dev, name));
76         ut_asserteq_str(ACPI_TEST_DEV_NAME, name);
77
78         return 0;
79 }
80 DM_TEST(dm_test_acpi_get_name, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
81
82 /* Test acpi_get_table_revision() */
83 static int dm_test_acpi_get_table_revision(struct unit_test_state *uts)
84 {
85         ut_asserteq(1, acpi_get_table_revision(ACPITAB_MCFG));
86         ut_asserteq(2, acpi_get_table_revision(ACPITAB_RSDP));
87         ut_asserteq(4, acpi_get_table_revision(ACPITAB_TPM2));
88         ut_asserteq(-EINVAL, acpi_get_table_revision(ACPITAB_COUNT));
89
90         return 0;
91 }
92 DM_TEST(dm_test_acpi_get_table_revision,
93         DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
94
95 /* Test acpi_create_dmar() */
96 static int dm_test_acpi_create_dmar(struct unit_test_state *uts)
97 {
98         struct acpi_dmar dmar;
99
100         ut_assertok(acpi_create_dmar(&dmar, DMAR_INTR_REMAP));
101         ut_asserteq(DMAR_INTR_REMAP, dmar.flags);
102         ut_asserteq(32 - 1, dmar.host_address_width);
103
104         return 0;
105 }
106 DM_TEST(dm_test_acpi_create_dmar, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
107
108 /* Test acpi_fill_header() */
109 static int dm_test_acpi_fill_header(struct unit_test_state *uts)
110 {
111         struct acpi_table_header hdr;
112
113         /* Make sure these 5 fields are not changed */
114         hdr.length = 0x11;
115         hdr.revision = 0x22;
116         hdr.checksum = 0x33;
117         hdr.aslc_revision = 0x44;
118         acpi_fill_header(&hdr, "ABCD");
119
120         ut_asserteq_mem("ABCD", hdr.signature, sizeof(hdr.signature));
121         ut_asserteq(0x11, hdr.length);
122         ut_asserteq(0x22, hdr.revision);
123         ut_asserteq(0x33, hdr.checksum);
124         ut_asserteq_mem(OEM_ID, hdr.oem_id, sizeof(hdr.oem_id));
125         ut_asserteq_mem(OEM_TABLE_ID, hdr.oem_table_id,
126                         sizeof(hdr.oem_table_id));
127         ut_asserteq(U_BOOT_BUILD_DATE, hdr.oem_revision);
128         ut_asserteq_mem(ASLC_ID, hdr.aslc_id, sizeof(hdr.aslc_id));
129         ut_asserteq(0x44, hdr.aslc_revision);
130
131         return 0;
132 }
133 DM_TEST(dm_test_acpi_fill_header, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
134
135 /* Test ACPI write_tables() */
136 static int dm_test_acpi_write_tables(struct unit_test_state *uts)
137 {
138         struct acpi_dmar *dmar;
139         struct acpi_ctx ctx;
140         void *buf;
141
142         buf = malloc(BUF_SIZE);
143         ut_assertnonnull(buf);
144
145         acpi_setup_base_tables(&ctx, buf);
146         dmar = ctx.current;
147         ut_assertok(acpi_write_dev_tables(&ctx));
148
149         /*
150          * We should have two dmar tables, one for each "denx,u-boot-acpi-test"
151          * device
152          */
153         ut_asserteq_ptr(dmar + 2, ctx.current);
154         ut_asserteq(DMAR_INTR_REMAP, dmar->flags);
155         ut_asserteq(32 - 1, dmar->host_address_width);
156
157         ut_asserteq(DMAR_INTR_REMAP, dmar[1].flags);
158         ut_asserteq(32 - 1, dmar[1].host_address_width);
159
160         /* Check that the pointers were added correctly */
161         ut_asserteq(map_to_sysmem(dmar), ctx.rsdt->entry[0]);
162         ut_asserteq(map_to_sysmem(dmar + 1), ctx.rsdt->entry[1]);
163         ut_asserteq(0, ctx.rsdt->entry[2]);
164
165         ut_asserteq(map_to_sysmem(dmar), ctx.xsdt->entry[0]);
166         ut_asserteq(map_to_sysmem(dmar + 1), ctx.xsdt->entry[1]);
167         ut_asserteq(0, ctx.xsdt->entry[2]);
168
169         return 0;
170 }
171 DM_TEST(dm_test_acpi_write_tables, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
172
173 /* Test basic ACPI functions */
174 static int dm_test_acpi_basic(struct unit_test_state *uts)
175 {
176         struct acpi_ctx ctx;
177
178         /* Check align works */
179         ctx.current = (void *)5;
180         acpi_align(&ctx);
181         ut_asserteq_ptr((void *)16, ctx.current);
182
183         /* Check that align does nothing if already aligned */
184         acpi_align(&ctx);
185         ut_asserteq_ptr((void *)16, ctx.current);
186         acpi_align64(&ctx);
187         ut_asserteq_ptr((void *)64, ctx.current);
188         acpi_align64(&ctx);
189         ut_asserteq_ptr((void *)64, ctx.current);
190
191         /* Check incrementing */
192         acpi_inc(&ctx, 3);
193         ut_asserteq_ptr((void *)67, ctx.current);
194         acpi_inc_align(&ctx, 3);
195         ut_asserteq_ptr((void *)80, ctx.current);
196
197         return 0;
198 }
199 DM_TEST(dm_test_acpi_basic, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
200
201 /* Test acpi_setup_base_tables */
202 static int dm_test_acpi_setup_base_tables(struct unit_test_state *uts)
203 {
204         struct acpi_rsdp *rsdp;
205         struct acpi_rsdt *rsdt;
206         struct acpi_xsdt *xsdt;
207         struct acpi_ctx ctx;
208         void *buf, *end;
209
210         /*
211          * Use an unaligned address deliberately, by allocating an aligned
212          * address and then adding 4 to it
213          */
214         buf = memalign(64, BUF_SIZE);
215         ut_assertnonnull(buf);
216         acpi_setup_base_tables(&ctx, buf + 4);
217         ut_asserteq(map_to_sysmem(PTR_ALIGN(buf + 4, 16)), gd->arch.acpi_start);
218
219         rsdp = buf + 16;
220         ut_asserteq_ptr(rsdp, ctx.rsdp);
221         ut_assertok(memcmp(RSDP_SIG, rsdp->signature, sizeof(rsdp->signature)));
222         ut_asserteq(sizeof(*rsdp), rsdp->length);
223         ut_assertok(table_compute_checksum(rsdp, 20));
224         ut_assertok(table_compute_checksum(rsdp, sizeof(*rsdp)));
225
226         rsdt = PTR_ALIGN((void *)rsdp + sizeof(*rsdp), 16);
227         ut_asserteq_ptr(rsdt, ctx.rsdt);
228         ut_assertok(memcmp("RSDT", rsdt->header.signature, ACPI_NAME_LEN));
229         ut_asserteq(sizeof(*rsdt), rsdt->header.length);
230         ut_assertok(table_compute_checksum(rsdt, sizeof(*rsdt)));
231
232         xsdt = PTR_ALIGN((void *)rsdt + sizeof(*rsdt), 16);
233         ut_asserteq_ptr(xsdt, ctx.xsdt);
234         ut_assertok(memcmp("XSDT", xsdt->header.signature, ACPI_NAME_LEN));
235         ut_asserteq(sizeof(*xsdt), xsdt->header.length);
236         ut_assertok(table_compute_checksum(xsdt, sizeof(*xsdt)));
237
238         end = PTR_ALIGN((void *)xsdt + sizeof(*xsdt), 64);
239         ut_asserteq_ptr(end, ctx.current);
240
241         ut_asserteq(map_to_sysmem(rsdt), rsdp->rsdt_address);
242         ut_asserteq(map_to_sysmem(xsdt), rsdp->xsdt_address);
243
244         return 0;
245 }
246 DM_TEST(dm_test_acpi_setup_base_tables,
247         DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
248
249 /* Test 'acpi list' command */
250 static int dm_test_acpi_cmd_list(struct unit_test_state *uts)
251 {
252         struct acpi_ctx ctx;
253         ulong addr;
254         void *buf;
255
256         buf = memalign(16, BUF_SIZE);
257         ut_assertnonnull(buf);
258         acpi_setup_base_tables(&ctx, buf);
259
260         ut_assertok(acpi_write_dev_tables(&ctx));
261
262         console_record_reset();
263         run_command("acpi list", 0);
264         addr = (ulong)map_to_sysmem(buf);
265         ut_assert_nextline("ACPI tables start at %lx", addr);
266         ut_assert_nextline("RSDP %08lx %06lx (v02 U-BOOT)", addr,
267                            sizeof(struct acpi_rsdp));
268         addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
269         ut_assert_nextline("RSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
270                            addr, sizeof(struct acpi_table_header) +
271                            2 * sizeof(u32), U_BOOT_BUILD_DATE);
272         addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
273         ut_assert_nextline("XSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
274                            addr, sizeof(struct acpi_table_header) +
275                            2 * sizeof(u64), U_BOOT_BUILD_DATE);
276         addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
277         ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
278                            addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
279         addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
280         ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %u INTL 0)",
281                            addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE);
282         ut_assert_console_end();
283
284         return 0;
285 }
286 DM_TEST(dm_test_acpi_cmd_list, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
287
288 /* Test 'acpi dump' command */
289 static int dm_test_acpi_cmd_dump(struct unit_test_state *uts)
290 {
291         struct acpi_ctx ctx;
292         ulong addr;
293         void *buf;
294
295         buf = memalign(16, BUF_SIZE);
296         ut_assertnonnull(buf);
297         acpi_setup_base_tables(&ctx, buf);
298
299         ut_assertok(acpi_write_dev_tables(&ctx));
300
301         /* First search for a non-existent table */
302         console_record_reset();
303         run_command("acpi dump rdst", 0);
304         ut_assert_nextline("Table 'RDST' not found");
305         ut_assert_console_end();
306
307         /* Now a real table */
308         console_record_reset();
309         run_command("acpi dump dmar", 0);
310         addr = ALIGN(map_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64);
311         ut_assert_nextline("DMAR @ %08lx", addr);
312         ut_assert_nextlines_are_dump(0x30);
313         ut_assert_console_end();
314
315         return 0;
316 }
317 DM_TEST(dm_test_acpi_cmd_dump, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);