Skip to content

Commit

Permalink
acpi: Write pointers to tables instead of addresses
Browse files Browse the repository at this point in the history
Sandbox uses an API to map between addresses and pointers. This allows
it to have (emulated) memory at zero and avoid arch-specific addressing
details. It also allows memory-mapped peripherals to work.

As an example, on many machines sandbox maps address 100 to pointer
value 10000000.

However this is not correct for ACPI, if sandbox starts another program
(e.g EFI app) and passes it the tables. That app has no knowledge of
sandbox's address mapping. So to make this work we want to store
10000000 as the value in the table.

Add two new 'nomap' functions which clearly make this exeption to how
sandbox works.

This should allow EFI apps to access ACPI tables with sandbox, e.g. for
testing purposes.

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
  • Loading branch information
sjg20 committed Jan 7, 2024
1 parent 5e3adc4 commit a8efebe
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 24 deletions.
16 changes: 16 additions & 0 deletions arch/sandbox/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,5 +231,21 @@ static inline void unmap_sysmem(const void *vaddr)
unmap_physmem(vaddr, MAP_WRBACK);
}

/**
* nomap_sysmem() - pass through an address unchanged
*
* This is used to indicate an address which should NOT be mapped, e.g. in
* SMBIOS tables. Using this function instead of a case shows that the sandbox
* conversion has been done
*/
static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len)
{
return (void *)(uintptr_t)paddr;
}

static inline phys_addr_t nomap_to_sysmem(const void *ptr)
{
return (phys_addr_t)(uintptr_t)ptr;
}

#endif
6 changes: 3 additions & 3 deletions arch/x86/lib/acpi_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ int acpi_write_tcpa(struct acpi_ctx *ctx, const struct acpi_writer *entry)

tcpa->platform_class = 0;
tcpa->laml = size;
tcpa->lasa = map_to_sysmem(log);
tcpa->lasa = nomap_to_sysmem(log);

/* (Re)calculate length and checksum */
current = (u32)tcpa + sizeof(struct acpi_tcpa);
Expand Down Expand Up @@ -268,7 +268,7 @@ static int acpi_write_tpm2(struct acpi_ctx *ctx,

/* Fill the log area size and start address fields. */
tpm2->laml = tpm2_log_len;
tpm2->lasa = map_to_sysmem(lasa);
tpm2->lasa = nomap_to_sysmem(lasa);

/* Calculate checksum. */
header->checksum = table_compute_checksum(tpm2, header->length);
Expand Down Expand Up @@ -430,7 +430,7 @@ int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry)
u32 *gnvs = (u32 *)((u32)ctx->dsdt + i);

if (*gnvs == ACPI_GNVS_ADDR) {
*gnvs = map_to_sysmem(ctx->current);
*gnvs = nomap_to_sysmem(ctx->current);
log_debug("Fix up global NVS in DSDT to %#08x\n",
*gnvs);
break;
Expand Down
12 changes: 6 additions & 6 deletions cmd/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static int dump_table_name(const char *sig)
if (!hdr)
return -ENOENT;
printf("%.*s @ %16lx\n", ACPI_NAME_LEN, hdr->signature,
(ulong)map_to_sysmem(hdr));
(ulong)nomap_to_sysmem(hdr));
print_buffer(0, hdr, 1, hdr->length, 0);

return 0;
Expand All @@ -54,9 +54,9 @@ static int dump_table_name(const char *sig)
static void list_fadt(struct acpi_fadt *fadt)
{
if (fadt->dsdt)
dump_hdr(map_sysmem(fadt->dsdt, 0));
dump_hdr(nomap_sysmem(fadt->dsdt, 0));
if (fadt->firmware_ctrl)
dump_hdr(map_sysmem(fadt->firmware_ctrl, 0));
dump_hdr(nomap_sysmem(fadt->firmware_ctrl, 0));
}

static void list_rsdt(struct acpi_rsdp *rsdp)
Expand All @@ -66,11 +66,11 @@ static void list_rsdt(struct acpi_rsdp *rsdp)
struct acpi_xsdt *xsdt;

if (rsdp->rsdt_address) {
rsdt = map_sysmem(rsdp->rsdt_address, 0);
rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
dump_hdr(&rsdt->header);
}
if (rsdp->xsdt_address) {
xsdt = map_sysmem(rsdp->xsdt_address, 0);
xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
dump_hdr(&xsdt->header);
len = xsdt->header.length - sizeof(xsdt->header);
count = len / sizeof(u64);
Expand All @@ -91,7 +91,7 @@ static void list_rsdt(struct acpi_rsdp *rsdp)
entry = rsdt->entry[i];
if (!entry)
break;
hdr = map_sysmem(entry, 0);
hdr = nomap_sysmem(entry, 0);
dump_hdr(hdr);
if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN))
list_fadt((struct acpi_fadt *)hdr);
Expand Down
18 changes: 18 additions & 0 deletions include/mapmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ static inline phys_addr_t map_to_sysmem(const void *ptr)
{
return (phys_addr_t)(uintptr_t)ptr;
}

/**
* nomap_sysmem() - pass through an address unchanged
*
* This is used to indicate an address which should NOT be mapped, e.g. in
* SMBIOS tables. Using this function instead of a case shows that the sandbox
* conversion has been done
*/
static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len)
{
return (void *)(uintptr_t)paddr;
}

static inline phys_addr_t nomap_to_sysmem(const void *ptr)
{
return (phys_addr_t)(uintptr_t)ptr;
}

# endif

#endif /* __MAPMEM_H */
12 changes: 6 additions & 6 deletions lib/acpi/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,33 @@ struct acpi_table_header *acpi_find_table(const char *sig)
if (!rsdp)
return NULL;
if (rsdp->xsdt_address) {
xsdt = map_sysmem(rsdp->xsdt_address, 0);
xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
len = xsdt->header.length - sizeof(xsdt->header);
count = len / sizeof(u64);
} else {
if (!rsdp->rsdt_address)
return NULL;
rsdt = map_sysmem(rsdp->rsdt_address, 0);
rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
len = rsdt->header.length - sizeof(rsdt->header);
count = len / sizeof(u32);
}
for (i = 0; i < count; i++) {
struct acpi_table_header *hdr;

if (rsdp->xsdt_address)
hdr = map_sysmem(xsdt->entry[i], 0);
hdr = nomap_sysmem(xsdt->entry[i], 0);
else
hdr = map_sysmem(rsdt->entry[i], 0);
hdr = nomap_sysmem(rsdt->entry[i], 0);
if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN))
return hdr;
if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) {
struct acpi_fadt *fadt = (struct acpi_fadt *)hdr;

if (!memcmp(sig, "DSDT", ACPI_NAME_LEN) && fadt->dsdt)
return map_sysmem(fadt->dsdt, 0);
return nomap_sysmem(fadt->dsdt, 0);
if (!memcmp(sig, "FACS", ACPI_NAME_LEN) &&
fadt->firmware_ctrl)
return map_sysmem(fadt->firmware_ctrl, 0);
return nomap_sysmem(fadt->firmware_ctrl, 0);
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/acpi/acpi_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
}

/* Add table to the RSDT */
rsdt->entry[i] = map_to_sysmem(table);
rsdt->entry[i] = nomap_to_sysmem(table);

/* Fix RSDT length or the kernel will assume invalid entries */
rsdt->header.length = sizeof(struct acpi_table_header) +
Expand All @@ -185,7 +185,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table)
xsdt = ctx->xsdt;

/* Add table to the XSDT */
xsdt->entry[i] = map_to_sysmem(table);
xsdt->entry[i] = nomap_to_sysmem(table);

/* Fix XSDT length */
xsdt->header.length = sizeof(struct acpi_table_header) +
Expand Down
4 changes: 2 additions & 2 deletions lib/acpi/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt,
memcpy(rsdp->oem_id, OEM_ID, 6);

if (rsdt)
rsdp->rsdt_address = map_to_sysmem(rsdt);
rsdp->rsdt_address = nomap_to_sysmem(rsdt);

if (xsdt)
rsdp->xsdt_address = map_to_sysmem(xsdt);
rsdp->xsdt_address = nomap_to_sysmem(xsdt);

rsdp->length = sizeof(struct acpi_rsdp);
rsdp->revision = ACPI_RSDP_REV_ACPI_2_0;
Expand Down
10 changes: 5 additions & 5 deletions test/dm/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)

/* Check that the pointers were added correctly */
for (i = 0; i < 3; i++) {
ut_asserteq(map_to_sysmem(dmar + i), ctx.rsdt->entry[i]);
ut_asserteq(map_to_sysmem(dmar + i), ctx.xsdt->entry[i]);
ut_asserteq(nomap_to_sysmem(dmar + i), ctx.rsdt->entry[i]);
ut_asserteq(nomap_to_sysmem(dmar + i), ctx.xsdt->entry[i]);
}
ut_asserteq(0, ctx.rsdt->entry[3]);
ut_asserteq(0, ctx.xsdt->entry[3]);
Expand Down Expand Up @@ -371,8 +371,8 @@ static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts)
end = PTR_ALIGN((void *)xsdt + sizeof(*xsdt), 64);
ut_asserteq_ptr(end, ctx.current);

ut_asserteq(map_to_sysmem(rsdt), rsdp->rsdt_address);
ut_asserteq(map_to_sysmem(xsdt), rsdp->xsdt_address);
ut_asserteq(nomap_to_sysmem(rsdt), rsdp->rsdt_address);
ut_asserteq(nomap_to_sysmem(xsdt), rsdp->xsdt_address);

return 0;
}
Expand Down Expand Up @@ -445,7 +445,7 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts)
/* Now a real table */
console_record_reset();
run_command("acpi dump dmar", 0);
addr = ALIGN(map_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64);
addr = ALIGN(nomap_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64);
ut_assert_nextline("DMAR @ %16lx", addr);
ut_assert_nextlines_are_dump(0x30);
ut_assert_console_end();
Expand Down

0 comments on commit a8efebe

Please sign in to comment.