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 <console.h> 10#include <dm.h> 11#include <malloc.h> 12#include <mapmem.h> 13#include <tables_csum.h> 14#include <version_string.h> 15#include <acpi/acpigen.h> 16#include <acpi/acpi_device.h> 17#include <acpi/acpi_table.h> 18#include <asm/global_data.h> 19#include <dm/acpi.h> 20#include <dm/test.h> 21#include <test/ut.h> 22#include "acpi.h" 23 24#define BUF_SIZE 4096 25 26#define OEM_REVISION ((((version_num / 1000) % 10) << 28) | \ 27 (((version_num / 100) % 10) << 24) | \ 28 (((version_num / 10) % 10) << 20) | \ 29 ((version_num % 10) << 16) | \ 30 (((version_num_patch / 10) % 10) << 12) | \ 31 ((version_num_patch % 10) << 8) | \ 32 0x01) 33 34/** 35 * struct testacpi_plat - Platform data for the test ACPI device 36 * 37 * @no_name: true to emit an empty ACPI name from testacpi_get_name() 38 * @return_error: true to return an error instead of a name 39 */ 40struct testacpi_plat { 41 bool return_error; 42 bool no_name; 43}; 44 45/** 46 * setup_ctx_and_base_tables() - Set up context along with RSDP, RSDT and XSDT 47 * 48 * Set up the context with the given start position. Some basic tables are 49 * always needed, so set them up as well. 50 * 51 * @ctx: Context to set up 52 */ 53static int setup_ctx_and_base_tables(struct unit_test_state *uts, 54 struct acpi_ctx *ctx, ulong start) 55{ 56 struct acpi_writer *entry = ACPI_WRITER_GET(0base); 57 58 acpi_setup_ctx(ctx, start); 59 60 ctx->tab_start = ctx->current; 61 ut_assertok(acpi_write_one(ctx, entry)); 62 63 return 0; 64} 65 66static int testacpi_write_tables(const struct udevice *dev, 67 struct acpi_ctx *ctx) 68{ 69 struct acpi_dmar *dmar; 70 int ret; 71 72 dmar = (struct acpi_dmar *)ctx->current; 73 acpi_create_dmar(dmar, DMAR_INTR_REMAP); 74 ctx->current += sizeof(struct acpi_dmar); 75 ret = acpi_add_table(ctx, dmar); 76 if (ret) 77 return log_msg_ret("add", ret); 78 79 return 0; 80} 81 82static int testacpi_get_name(const struct udevice *dev, char *out_name) 83{ 84 struct testacpi_plat *plat = dev_get_plat(dev); 85 86 if (plat->return_error) 87 return -EINVAL; 88 if (plat->no_name) { 89 *out_name = '\0'; 90 return 0; 91 } 92 if (device_get_uclass_id(dev->parent) == UCLASS_TEST_ACPI) 93 return acpi_copy_name(out_name, ACPI_TEST_CHILD_NAME); 94 else 95 return acpi_copy_name(out_name, ACPI_TEST_DEV_NAME); 96} 97 98static int testacpi_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) 99{ 100 const char *data; 101 102 data = dev_read_string(dev, "acpi-ssdt-test-data"); 103 if (data) { 104 while (*data) 105 acpigen_emit_byte(ctx, *data++); 106 } 107 108 return 0; 109} 110 111static int testacpi_inject_dsdt(const struct udevice *dev, struct acpi_ctx *ctx) 112{ 113 const char *data; 114 115 data = dev_read_string(dev, "acpi-dsdt-test-data"); 116 if (data) { 117 while (*data) 118 acpigen_emit_byte(ctx, *data++); 119 } 120 121 return 0; 122} 123 124struct acpi_ops testacpi_ops = { 125 .get_name = testacpi_get_name, 126 .write_tables = testacpi_write_tables, 127 .fill_ssdt = testacpi_fill_ssdt, 128 .inject_dsdt = testacpi_inject_dsdt, 129}; 130 131static const struct udevice_id testacpi_ids[] = { 132 { .compatible = "denx,u-boot-acpi-test" }, 133 { } 134}; 135 136U_BOOT_DRIVER(testacpi_drv) = { 137 .name = "testacpi_drv", 138 .of_match = testacpi_ids, 139 .id = UCLASS_TEST_ACPI, 140 .bind = dm_scan_fdt_dev, 141 .plat_auto = sizeof(struct testacpi_plat), 142 ACPI_OPS_PTR(&testacpi_ops) 143}; 144 145UCLASS_DRIVER(testacpi) = { 146 .name = "testacpi", 147 .id = UCLASS_TEST_ACPI, 148}; 149 150/* Test ACPI get_name() */ 151static int dm_test_acpi_get_name(struct unit_test_state *uts) 152{ 153 char name[ACPI_NAME_MAX]; 154 struct udevice *dev, *dev2, *i2c, *spi, *timer, *sound; 155 struct udevice *pci, *root; 156 157 /* Test getting the name from the driver */ 158 ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); 159 ut_assertok(acpi_get_name(dev, name)); 160 ut_asserteq_str(ACPI_TEST_DEV_NAME, name); 161 162 /* Test getting the name from the device tree */ 163 ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test", 164 &dev2)); 165 ut_assertok(acpi_get_name(dev2, name)); 166 ut_asserteq_str("GHIJ", name); 167 168 /* Test getting the name from acpi_device_get_name() */ 169 ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c)); 170 ut_assertok(acpi_get_name(i2c, name)); 171 ut_asserteq_str("I2C0", name); 172 173 ut_assertok(uclass_first_device_err(UCLASS_SPI, &spi)); 174 ut_assertok(acpi_get_name(spi, name)); 175 ut_asserteq_str("SPI0", name); 176 177 /* ACPI doesn't know about the timer */ 178 ut_assertok(uclass_first_device_err(UCLASS_TIMER, &timer)); 179 ut_asserteq(-ENOENT, acpi_get_name(timer, name)); 180 181 /* May as well test the rest of the cases */ 182 ut_assertok(uclass_first_device_err(UCLASS_SOUND, &sound)); 183 ut_assertok(acpi_get_name(sound, name)); 184 ut_asserteq_str("HDAS", name); 185 186 ut_assertok(uclass_first_device_err(UCLASS_PCI, &pci)); 187 ut_assertok(acpi_get_name(pci, name)); 188 ut_asserteq_str("PCI0", name); 189 190 ut_assertok(uclass_first_device_err(UCLASS_ROOT, &root)); 191 ut_assertok(acpi_get_name(root, name)); 192 ut_asserteq_str("\\_SB", name); 193 194 /* Note that we don't have tests for acpi_name_from_id() */ 195 196 return 0; 197} 198DM_TEST(dm_test_acpi_get_name, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 199 200/* Test acpi_get_table_revision() */ 201static int dm_test_acpi_get_table_revision(struct unit_test_state *uts) 202{ 203 ut_asserteq(1, acpi_get_table_revision(ACPITAB_MCFG)); 204 ut_asserteq(2, acpi_get_table_revision(ACPITAB_RSDP)); 205 ut_asserteq(4, acpi_get_table_revision(ACPITAB_TPM2)); 206 ut_asserteq(-EINVAL, acpi_get_table_revision(ACPITAB_COUNT)); 207 208 return 0; 209} 210DM_TEST(dm_test_acpi_get_table_revision, 211 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 212 213/* Test acpi_create_dmar() */ 214static int dm_test_acpi_create_dmar(struct unit_test_state *uts) 215{ 216 struct acpi_dmar dmar; 217 struct udevice *cpu; 218 219 ut_assertok(uclass_first_device_err(UCLASS_CPU, &cpu)); 220 ut_assertnonnull(cpu); 221 ut_assertok(acpi_create_dmar(&dmar, DMAR_INTR_REMAP)); 222 ut_asserteq(DMAR_INTR_REMAP, dmar.flags); 223 ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, 224 dmar.host_address_width); 225 226 return 0; 227} 228DM_TEST(dm_test_acpi_create_dmar, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 229 230/* Test acpi_fill_header() */ 231static int dm_test_acpi_fill_header(struct unit_test_state *uts) 232{ 233 struct acpi_table_header hdr; 234 235 /* Make sure these 5 fields are not changed */ 236 hdr.length = 0x11; 237 hdr.revision = 0x22; 238 hdr.checksum = 0x33; 239 hdr.creator_revision = 0x44; 240 acpi_fill_header(&hdr, "ABCD"); 241 242 ut_asserteq_mem("ABCD", hdr.signature, sizeof(hdr.signature)); 243 ut_asserteq(0x11, hdr.length); 244 ut_asserteq(0x22, hdr.revision); 245 ut_asserteq(0x33, hdr.checksum); 246 ut_asserteq_mem(OEM_ID, hdr.oem_id, sizeof(hdr.oem_id)); 247 ut_asserteq_mem(OEM_TABLE_ID, hdr.oem_table_id, 248 sizeof(hdr.oem_table_id)); 249 ut_asserteq(OEM_REVISION, hdr.oem_revision); 250 ut_asserteq_mem(ASLC_ID, hdr.creator_id, sizeof(hdr.creator_id)); 251 ut_asserteq(0x44, hdr.creator_revision); 252 253 return 0; 254} 255DM_TEST(dm_test_acpi_fill_header, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 256 257/* Test ACPI write_tables() */ 258static int dm_test_acpi_write_tables(struct unit_test_state *uts) 259{ 260 struct acpi_dmar *dmar; 261 struct acpi_ctx ctx; 262 ulong addr; 263 void *buf; 264 int i; 265 266 buf = malloc(BUF_SIZE); 267 ut_assertnonnull(buf); 268 addr = map_to_sysmem(buf); 269 270 ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); 271 dmar = ctx.current; 272 ut_assertok(acpi_write_dev_tables(&ctx)); 273 274 /* 275 * We should have three dmar tables, one for each 276 * "denx,u-boot-acpi-test" device 277 */ 278 ut_asserteq_ptr(dmar + 3, ctx.current); 279 ut_asserteq(DMAR_INTR_REMAP, dmar->flags); 280 ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, 281 dmar->host_address_width); 282 283 ut_asserteq(DMAR_INTR_REMAP, dmar[1].flags); 284 ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, 285 dmar[1].host_address_width); 286 287 ut_asserteq(DMAR_INTR_REMAP, dmar[2].flags); 288 ut_asserteq((IS_ENABLED(CONFIG_PHYS_64BIT) ? 64 : 32) - 1, 289 dmar[2].host_address_width); 290 291 /* Check that the pointers were added correctly */ 292 for (i = 0; i < 3; i++) { 293 ut_asserteq(nomap_to_sysmem(dmar + i), ctx.rsdt->entry[i]); 294 ut_asserteq(nomap_to_sysmem(dmar + i), ctx.xsdt->entry[i]); 295 } 296 ut_asserteq(0, ctx.rsdt->entry[3]); 297 ut_asserteq(0, ctx.xsdt->entry[3]); 298 299 return 0; 300} 301DM_TEST(dm_test_acpi_write_tables, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 302 303/* Test basic ACPI functions */ 304static int dm_test_acpi_basic(struct unit_test_state *uts) 305{ 306 struct acpi_ctx ctx; 307 308 /* Check align works */ 309 ctx.current = (void *)5; 310 acpi_align(&ctx); 311 ut_asserteq_ptr((void *)16, ctx.current); 312 313 /* Check that align does nothing if already aligned */ 314 acpi_align(&ctx); 315 ut_asserteq_ptr((void *)16, ctx.current); 316 acpi_align64(&ctx); 317 ut_asserteq_ptr((void *)64, ctx.current); 318 acpi_align64(&ctx); 319 ut_asserteq_ptr((void *)64, ctx.current); 320 321 /* Check incrementing */ 322 acpi_inc(&ctx, 3); 323 ut_asserteq_ptr((void *)67, ctx.current); 324 acpi_inc_align(&ctx, 3); 325 ut_asserteq_ptr((void *)80, ctx.current); 326 327 return 0; 328} 329DM_TEST(dm_test_acpi_basic, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 330 331/* Test setup_ctx_and_base_tables */ 332static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts) 333{ 334 struct acpi_rsdp *rsdp; 335 struct acpi_rsdt *rsdt; 336 struct acpi_xsdt *xsdt; 337 struct acpi_ctx ctx; 338 void *buf, *end; 339 ulong addr; 340 341 /* 342 * Use an unaligned address deliberately, by allocating an aligned 343 * address and then adding 4 to it 344 */ 345 buf = memalign(64, BUF_SIZE); 346 ut_assertnonnull(buf); 347 addr = map_to_sysmem(buf); 348 ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr + 4)); 349 ut_asserteq(map_to_sysmem(PTR_ALIGN(buf + 4, 16)), gd_acpi_start()); 350 351 rsdp = buf + 16; 352 ut_asserteq_ptr(rsdp, ctx.rsdp); 353 ut_asserteq_mem(RSDP_SIG, rsdp->signature, sizeof(rsdp->signature)); 354 ut_asserteq(sizeof(*rsdp), rsdp->length); 355 ut_assertok(table_compute_checksum(rsdp, 20)); 356 ut_assertok(table_compute_checksum(rsdp, sizeof(*rsdp))); 357 358 rsdt = PTR_ALIGN((void *)rsdp + sizeof(*rsdp), 16); 359 ut_asserteq_ptr(rsdt, ctx.rsdt); 360 ut_asserteq_mem("RSDT", rsdt->header.signature, ACPI_NAME_LEN); 361 ut_asserteq(sizeof(*rsdt), rsdt->header.length); 362 ut_assertok(table_compute_checksum(rsdt, sizeof(*rsdt))); 363 364 xsdt = PTR_ALIGN((void *)rsdt + sizeof(*rsdt), 16); 365 ut_asserteq_ptr(xsdt, ctx.xsdt); 366 ut_asserteq_mem("XSDT", xsdt->header.signature, ACPI_NAME_LEN); 367 ut_asserteq(sizeof(*xsdt), xsdt->header.length); 368 ut_assertok(table_compute_checksum(xsdt, sizeof(*xsdt))); 369 370 end = PTR_ALIGN((void *)xsdt + sizeof(*xsdt), 64); 371 ut_asserteq_ptr(end, ctx.current); 372 373 ut_asserteq(nomap_to_sysmem(rsdt), rsdp->rsdt_address); 374 ut_asserteq(nomap_to_sysmem(xsdt), rsdp->xsdt_address); 375 376 return 0; 377} 378DM_TEST(dm_test_acpi_ctx_and_base_tables, 379 UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 380 381/* Test 'acpi list' command */ 382static int dm_test_acpi_cmd_list(struct unit_test_state *uts) 383{ 384 struct acpi_ctx ctx; 385 ulong addr; 386 void *buf; 387 388 buf = memalign(16, BUF_SIZE); 389 ut_assertnonnull(buf); 390 addr = map_to_sysmem(buf); 391 ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); 392 393 ut_assertok(acpi_write_dev_tables(&ctx)); 394 395 console_record_reset(); 396 run_command("acpi list", 0); 397 ut_assert_nextline("Name Base Size Detail"); 398 ut_assert_nextline("---- ---------------- ----- ----------------------------"); 399 ut_assert_nextline("RSDP %16lx %5zx v02 U-BOOT", addr, 400 sizeof(struct acpi_rsdp)); 401 addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16); 402 ut_assert_nextline("RSDT %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0", 403 addr, sizeof(struct acpi_table_header) + 404 3 * sizeof(u32), OEM_REVISION); 405 addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16); 406 ut_assert_nextline("XSDT %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0", 407 addr, sizeof(struct acpi_table_header) + 408 3 * sizeof(u64), OEM_REVISION); 409 addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64); 410 ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0", 411 addr, sizeof(struct acpi_dmar), OEM_REVISION); 412 addr = ALIGN(addr + sizeof(struct acpi_dmar), 16); 413 ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0", 414 addr, sizeof(struct acpi_dmar), OEM_REVISION); 415 addr = ALIGN(addr + sizeof(struct acpi_dmar), 16); 416 ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0", 417 addr, sizeof(struct acpi_dmar), OEM_REVISION); 418 ut_assert_console_end(); 419 420 return 0; 421} 422DM_TEST(dm_test_acpi_cmd_list, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 423 424/* Test 'acpi dump' command */ 425static int dm_test_acpi_cmd_dump(struct unit_test_state *uts) 426{ 427 struct acpi_ctx ctx; 428 ulong addr; 429 void *buf; 430 431 buf = memalign(16, BUF_SIZE); 432 ut_assertnonnull(buf); 433 addr = map_to_sysmem(buf); 434 ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); 435 436 ut_assertok(acpi_write_dev_tables(&ctx)); 437 438 /* First search for a non-existent table */ 439 console_record_reset(); 440 run_command("acpi dump rdst", 0); 441 ut_assert_nextline("Table 'RDST' not found"); 442 ut_assert_console_end(); 443 444 /* Now a real table */ 445 console_record_reset(); 446 run_command("acpi dump dmar", 0); 447 addr = ALIGN(nomap_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64); 448 ut_assert_nextline("DMAR @ %16lx", addr); 449 ut_assert_nextlines_are_dump(0x30); 450 ut_assert_console_end(); 451 452 return 0; 453} 454DM_TEST(dm_test_acpi_cmd_dump, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 455 456/* Test acpi_device_path() */ 457static int dm_test_acpi_device_path(struct unit_test_state *uts) 458{ 459 struct testacpi_plat *plat; 460 char buf[ACPI_PATH_MAX]; 461 struct udevice *dev, *child; 462 463 ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); 464 ut_assertok(acpi_device_path(dev, buf, sizeof(buf))); 465 ut_asserteq_str("\\_SB." ACPI_TEST_DEV_NAME, buf); 466 467 /* Test running out of space */ 468 buf[5] = '\0'; 469 ut_asserteq(-ENOSPC, acpi_device_path(dev, buf, 5)); 470 ut_asserteq('\0', buf[5]); 471 472 /* Test a three-component name */ 473 ut_assertok(device_first_child_err(dev, &child)); 474 ut_assertok(acpi_device_path(child, buf, sizeof(buf))); 475 ut_asserteq_str("\\_SB." ACPI_TEST_DEV_NAME "." ACPI_TEST_CHILD_NAME, 476 buf); 477 478 /* Test handling of a device which doesn't produce a name */ 479 plat = dev_get_plat(dev); 480 plat->no_name = true; 481 ut_assertok(acpi_device_path(child, buf, sizeof(buf))); 482 ut_asserteq_str("\\_SB." ACPI_TEST_CHILD_NAME, buf); 483 484 /* Test handling of a device which returns an error */ 485 plat = dev_get_plat(dev); 486 plat->return_error = true; 487 ut_asserteq(-EINVAL, acpi_device_path(child, buf, sizeof(buf))); 488 489 return 0; 490} 491DM_TEST(dm_test_acpi_device_path, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 492 493/* Test acpi_device_status() */ 494static int dm_test_acpi_device_status(struct unit_test_state *uts) 495{ 496 struct udevice *dev; 497 498 ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); 499 ut_asserteq(ACPI_DSTATUS_ALL_ON, acpi_device_status(dev)); 500 501 return 0; 502} 503DM_TEST(dm_test_acpi_device_status, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 504 505/* Test acpi_fill_ssdt() */ 506static int dm_test_acpi_fill_ssdt(struct unit_test_state *uts) 507{ 508 struct acpi_ctx ctx; 509 u8 *buf; 510 511 buf = malloc(BUF_SIZE); 512 ut_assertnonnull(buf); 513 514 acpi_reset_items(); 515 ctx.current = buf; 516 buf[4] = 'z'; /* sentinel */ 517 ut_assertok(acpi_fill_ssdt(&ctx)); 518 519 /* 520 * These values come from acpi-test2's acpi-ssdt-test-data property. 521 * This device comes first because of u-boot,acpi-ssdt-order 522 */ 523 ut_asserteq('c', buf[0]); 524 ut_asserteq('d', buf[1]); 525 526 /* These values come from acpi-test's acpi-ssdt-test-data property */ 527 ut_asserteq('a', buf[2]); 528 ut_asserteq('b', buf[3]); 529 530 ut_asserteq('z', buf[4]); 531 532 return 0; 533} 534DM_TEST(dm_test_acpi_fill_ssdt, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 535 536/* Test acpi_inject_dsdt() */ 537static int dm_test_acpi_inject_dsdt(struct unit_test_state *uts) 538{ 539 struct acpi_ctx ctx; 540 u8 *buf; 541 542 buf = malloc(BUF_SIZE); 543 ut_assertnonnull(buf); 544 545 acpi_reset_items(); 546 ctx.current = buf; 547 buf[4] = 'z'; /* sentinel */ 548 ut_assertok(acpi_inject_dsdt(&ctx)); 549 550 /* 551 * These values come from acpi-test's acpi-dsdt-test-data property. 552 * There is no u-boot,acpi-dsdt-order so device-tree order is used. 553 */ 554 ut_asserteq('h', buf[0]); 555 ut_asserteq('i', buf[1]); 556 557 /* These values come from acpi-test's acpi-dsdt-test-data property */ 558 ut_asserteq('j', buf[2]); 559 ut_asserteq('k', buf[3]); 560 561 ut_asserteq('z', buf[4]); 562 563 return 0; 564} 565DM_TEST(dm_test_acpi_inject_dsdt, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 566 567/* Test 'acpi items' command */ 568static int dm_test_acpi_cmd_items(struct unit_test_state *uts) 569{ 570 struct acpi_ctx ctx; 571 ulong addr; 572 void *buf; 573 574 buf = malloc(BUF_SIZE); 575 ut_assertnonnull(buf); 576 addr = map_to_sysmem(buf); 577 578 acpi_reset_items(); 579 ctx.current = buf; 580 ut_assertok(acpi_fill_ssdt(&ctx)); 581 console_record_reset(); 582 run_command("acpi items", 0); 583 ut_assert_nextline("Seq Type Base Size Device/Writer"); 584 ut_assert_nextline("--- ----- -------- ---- -------------"); 585 ut_assert_nextline(" 0 ssdt %8lx 2 acpi-test", addr); 586 ut_assert_nextline(" 1 ssdt %8lx 2 acpi-test2", addr + 2); 587 ut_assert_console_end(); 588 589 acpi_reset_items(); 590 ctx.current = buf; 591 ut_assertok(acpi_inject_dsdt(&ctx)); 592 console_record_reset(); 593 run_command("acpi items", 0); 594 ut_assert_nextlinen("Seq"); 595 ut_assert_nextlinen("---"); 596 ut_assert_nextline(" 0 dsdt %8lx 2 acpi-test", addr); 597 ut_assert_nextline(" 1 dsdt %8lx 2 acpi-test2", addr + 2); 598 ut_assert_console_end(); 599 600 console_record_reset(); 601 run_command("acpi items -d", 0); 602 ut_assert_nextlinen("Seq"); 603 ut_assert_nextlinen("---"); 604 ut_assert_nextline(" 0 dsdt %8lx 2 acpi-test", addr); 605 ut_assert_nextlines_are_dump(2); 606 ut_assert_nextline("%s", ""); 607 ut_assert_nextline(" 1 dsdt %8lx 2 acpi-test2", addr + 2); 608 ut_assert_nextlines_are_dump(2); 609 ut_assert_nextline("%s", ""); 610 ut_assert_console_end(); 611 612 return 0; 613} 614DM_TEST(dm_test_acpi_cmd_items, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 615 616/* Test 'acpi set' command */ 617static int dm_test_acpi_cmd_set(struct unit_test_state *uts) 618{ 619 struct acpi_ctx ctx; 620 ulong addr; 621 void *buf; 622 623 gd_set_acpi_start(0); 624 625 console_record_reset(); 626 ut_asserteq(0, gd_acpi_start()); 627 ut_assertok(run_command("acpi set", 0)); 628 ut_assert_nextline("ACPI pointer: 0"); 629 630 buf = memalign(16, BUF_SIZE); 631 ut_assertnonnull(buf); 632 addr = map_to_sysmem(buf); 633 ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); 634 635 ut_assertok(acpi_write_dev_tables(&ctx)); 636 637 ut_assertok(run_command("acpi set", 0)); 638 ut_assert_nextline("ACPI pointer: %lx", addr); 639 640 ut_assertok(run_command("acpi set 0", 0)); 641 ut_assert_nextline("Setting ACPI pointer to 0"); 642 ut_asserteq(0, gd_acpi_start()); 643 644 ut_assertok(run_commandf("acpi set %lx", addr)); 645 ut_assert_nextline("Setting ACPI pointer to %lx", addr); 646 ut_asserteq(addr, gd_acpi_start()); 647 648 ut_assert_console_end(); 649 650 return 0; 651} 652DM_TEST(dm_test_acpi_cmd_set, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); 653 654/** 655 * dm_test_write_test_table() - create test ACPI table 656 * 657 * Create an ACPI table TSTn, where n is given by @index. 658 * 659 * @ctx: ACPI table writing context 660 * @index: table index 661 * Return: generated table 662 */ 663static struct acpi_table_header 664*dm_test_write_test_table(struct acpi_ctx *ctx, int index) 665{ 666 struct acpi_table_header *tbl = ctx->current; 667 char signature[5]; 668 669 snprintf(signature, sizeof(signature), "TST%1d", index); 670 memset(tbl, 0, sizeof(*tbl)); 671 acpi_fill_header(tbl, signature); 672 acpi_inc(ctx, sizeof(struct acpi_table_header)); 673 tbl->length = (u8 *)ctx->current - (u8 *)tbl; 674 tbl->checksum = table_compute_checksum(tbl, tbl->length); 675 acpi_add_table(ctx, tbl); 676 677 return tbl; 678} 679 680/* Test acpi_find_table() */ 681static int dm_test_acpi_find_table(struct unit_test_state *uts) 682{ 683 struct acpi_ctx ctx; 684 ulong acpi_start, addr; 685 void *buf; 686 struct acpi_table_header *table, *table1, *table2, *table3; 687 struct acpi_rsdp *rsdp; 688 ulong rsdt; 689 ulong xsdt; 690 691 /* Keep reference to original ACPI tables */ 692 acpi_start = gd_acpi_start(); 693 694 /* Setup new ACPI tables */ 695 buf = memalign(16, BUF_SIZE); 696 ut_assertnonnull(buf); 697 addr = map_to_sysmem(buf); 698 ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); 699 table3 = dm_test_write_test_table(&ctx, 3); 700 table1 = dm_test_write_test_table(&ctx, 1); 701 table2 = dm_test_write_test_table(&ctx, 2); 702 703 /* Retrieve RSDP, RSDT, XSDT */ 704 rsdp = map_sysmem(gd_acpi_start(), 0); 705 ut_assertnonnull(rsdp); 706 rsdt = rsdp->rsdt_address; 707 ut_assert(rsdt); 708 xsdt = rsdp->xsdt_address; 709 ut_assert(xsdt); 710 711 /* Find with both RSDT and XSDT */ 712 table = acpi_find_table("TST1"); 713 ut_asserteq_ptr(table1, table); 714 ut_asserteq_strn("TST1", table->signature); 715 table = acpi_find_table("TST2"); 716 ut_asserteq_ptr(table2, table); 717 ut_asserteq_strn("TST2", table->signature); 718 table = acpi_find_table("TST3"); 719 ut_asserteq_ptr(table3, table); 720 ut_asserteq_strn("TST3", table->signature); 721 722 /* Find with XSDT only */ 723 rsdp->rsdt_address = 0; 724 table = acpi_find_table("TST1"); 725 ut_asserteq_ptr(table1, table); 726 table = acpi_find_table("TST2"); 727 ut_asserteq_ptr(table2, table); 728 table = acpi_find_table("TST3"); 729 ut_asserteq_ptr(table3, table); 730 rsdp->rsdt_address = rsdt; 731 732 /* Find with RSDT only */ 733 rsdp->xsdt_address = 0; 734 table = acpi_find_table("TST1"); 735 ut_asserteq_ptr(table1, table); 736 table = acpi_find_table("TST2"); 737 ut_asserteq_ptr(table2, table); 738 table = acpi_find_table("TST3"); 739 ut_asserteq_ptr(table3, table); 740 rsdp->xsdt_address = xsdt; 741 742 /* Restore previous ACPI tables */ 743 gd_set_acpi_start(acpi_start); 744 free(buf); 745 746 return 0; 747} 748DM_TEST(dm_test_acpi_find_table, 0); 749 750/* Test offsets in RSDT, XSDT */ 751static int dm_test_acpi_offsets(struct unit_test_state *uts) 752{ 753 ut_asserteq(36, offsetof(struct acpi_rsdt, entry)); 754 ut_asserteq(36, offsetof(struct acpi_xsdt, entry)); 755 756 return 0; 757} 758DM_TEST(dm_test_acpi_offsets, 0); 759