[PATCH v3 05/35] acpi: Support generation of ACPI code
Bin Meng
bmeng.cn at gmail.com
Sun Jun 28 11:13:53 CEST 2020
Hi Simon,
On Sun, Jun 14, 2020 at 10:55 AM Simon Glass <sjg at chromium.org> wrote:
>
> Add a new file to handle generating ACPI code programatically. This is
> used when information must be dynamically added to the tables, e.g. the
> SSDT.
>
> Initial support is just for writing simple values. Also add a 'base' value
> so that the table can be freed. This likely doesn't happen in normal code,
> but is nice to do in tests.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> (no changes since v2)
>
> Changes in v2:
> - Update to add a new 'base' field to struct acpi_ctx
> - Free the memory allocated to the table and context
>
> include/acpi/acpigen.h | 49 ++++++++++++++++++++++++++++++
> include/dm/acpi.h | 2 ++
> lib/acpi/Makefile | 1 +
> lib/acpi/acpi_table.c | 1 +
> lib/acpi/acpigen.c | 38 +++++++++++++++++++++++
> test/dm/Makefile | 1 +
> test/dm/acpigen.c | 69 ++++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 161 insertions(+)
> create mode 100644 include/acpi/acpigen.h
> create mode 100644 lib/acpi/acpigen.c
> create mode 100644 test/dm/acpigen.c
>
> diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h
> new file mode 100644
> index 0000000000..8809cdb4e1
> --- /dev/null
> +++ b/include/acpi/acpigen.h
> @@ -0,0 +1,49 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Core ACPI (Advanced Configuration and Power Interface) support
> + *
> + * Copyright 2019 Google LLC
> + *
> + * Modified from coreboot file acpigen.h
> + */
> +
> +#ifndef __ACPI_ACPIGEN_H
> +#define __ACPI_ACPIGEN_H
> +
> +#include <linux/types.h>
> +
> +struct acpi_ctx;
> +
> +/**
> + * acpigen_get_current() - Get the current ACPI code output pointer
> + *
> + * @ctx: ACPI context pointer
> + * @return output pointer
> + */
> +u8 *acpigen_get_current(struct acpi_ctx *ctx);
> +
> +/**
> + * acpigen_emit_byte() - Emit a byte to the ACPI code
> + *
> + * @ctx: ACPI context pointer
> + * @data: Value to output
> + */
> +void acpigen_emit_byte(struct acpi_ctx *ctx, uint data);
> +
> +/**
> + * acpigen_emit_word() - Emit a 16-bit word to the ACPI code
> + *
> + * @ctx: ACPI context pointer
> + * @data: Value to output
> + */
> +void acpigen_emit_word(struct acpi_ctx *ctx, uint data);
> +
> +/**
> + * acpigen_emit_dword() - Emit a 32-bit 'double word' to the ACPI code
> + *
> + * @ctx: ACPI context pointer
> + * @data: Value to output
> + */
> +void acpigen_emit_dword(struct acpi_ctx *ctx, uint data);
> +
> +#endif
> diff --git a/include/dm/acpi.h b/include/dm/acpi.h
> index 7563a4c60a..696b1a96a0 100644
> --- a/include/dm/acpi.h
> +++ b/include/dm/acpi.h
> @@ -29,6 +29,7 @@
> *
> * This contains a few useful pieces of information used when writing
> *
> + * @base: Base address of ACPI tables
> * @current: Current address for writing
> * @rsdp: Pointer to the Root System Description Pointer, typically used when
> * adding a new table. The RSDP holds pointers to the RSDT and XSDT.
> @@ -36,6 +37,7 @@
> * @xsdt: Pointer to the Extended System Description Table
> */
> struct acpi_ctx {
> + void *base;
> void *current;
> struct acpi_rsdp *rsdp;
> struct acpi_rsdt *rsdt;
> diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile
> index caae6c01bd..85a1f774ad 100644
> --- a/lib/acpi/Makefile
> +++ b/lib/acpi/Makefile
> @@ -1,5 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0+
> #
>
> +obj-y += acpigen.o
> obj-y += acpi_device.o
> obj-y += acpi_table.o
> diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c
> index 431776666e..17d5258438 100644
> --- a/lib/acpi/acpi_table.c
> +++ b/lib/acpi/acpi_table.c
> @@ -238,6 +238,7 @@ static void acpi_write_xsdt(struct acpi_xsdt *xsdt)
> void acpi_setup_base_tables(struct acpi_ctx *ctx, void *start)
> {
> ctx->current = start;
> + ctx->current = start;
This seems to be unnecessary.
>
> /* Align ACPI tables to 16 byte */
> acpi_align(ctx);
> diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c
> new file mode 100644
> index 0000000000..59bd3af0b7
> --- /dev/null
> +++ b/lib/acpi/acpigen.c
> @@ -0,0 +1,38 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Generation of ACPI (Advanced Configuration and Power Interface) tables
> + *
> + * Copyright 2019 Google LLC
> + * Mostly taken from coreboot
> + */
> +
> +#define LOG_CATEGORY LOGC_ACPI
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <acpi/acpigen.h>
> +#include <dm/acpi.h>
> +
> +u8 *acpigen_get_current(struct acpi_ctx *ctx)
> +{
> + return ctx->current;
> +}
> +
> +void acpigen_emit_byte(struct acpi_ctx *ctx, uint data)
> +{
> + *(u8 *)ctx->current++ = data;
> +}
> +
> +void acpigen_emit_word(struct acpi_ctx *ctx, uint data)
> +{
> + acpigen_emit_byte(ctx, data & 0xff);
> + acpigen_emit_byte(ctx, (data >> 8) & 0xff);
> +}
> +
> +void acpigen_emit_dword(struct acpi_ctx *ctx, uint data)
> +{
> + acpigen_emit_byte(ctx, data & 0xff);
> + acpigen_emit_byte(ctx, (data >> 8) & 0xff);
> + acpigen_emit_byte(ctx, (data >> 16) & 0xff);
> + acpigen_emit_byte(ctx, (data >> 24) & 0xff);
It would be better to document the endianness which is little-endian.
> +}
> diff --git a/test/dm/Makefile b/test/dm/Makefile
> index 6c18fd04ce..e3e0cccf01 100644
> --- a/test/dm/Makefile
> +++ b/test/dm/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
> obj-$(CONFIG_UT_DM) += core.o
> ifneq ($(CONFIG_SANDBOX),)
> obj-$(CONFIG_ACPIGEN) += acpi.o
> +obj-$(CONFIG_ACPIGEN) += acpigen.o
> obj-$(CONFIG_SOUND) += audio.o
> obj-$(CONFIG_BLK) += blk.o
> obj-$(CONFIG_BOARD) += board.o
> diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c
> new file mode 100644
> index 0000000000..c353408021
> --- /dev/null
> +++ b/test/dm/acpigen.c
> @@ -0,0 +1,69 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Tests for ACPI code generation
> + *
> + * Copyright 2019 Google LLC
> + * Written by Simon Glass <sjg at chromium.org>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <acpi/acpigen.h>
> +#include <asm/unaligned.h>
> +#include <dm/acpi.h>
> +#include <dm/test.h>
> +#include <test/ut.h>
> +
> +static int alloc_context(struct acpi_ctx **ctxp)
> +{
> + struct acpi_ctx *ctx;
> +
> + *ctxp = NULL;
> + ctx = malloc(sizeof(*ctx));
> + if (!ctx)
> + return -ENOMEM;
> + ctx->base = malloc(150);
nits: avoid magic number
> + if (!ctx->base) {
> + free(ctx);
> + return -ENOMEM;
> + }
> + ctx->current = ctx->base;
> + *ctxp = ctx;
> +
> + return 0;
> +}
> +
> +static void free_context(struct acpi_ctx **ctxp)
> +{
> + free((*ctxp)->base);
> + free(*ctxp);
> + *ctxp = NULL;
> +}
> +
> +/* Test emitting simple types and acpigen_get_current() */
> +static int dm_test_acpi_emit_simple(struct unit_test_state *uts)
> +{
> + struct acpi_ctx *ctx;
> + u8 *ptr;
> +
> + ut_assertok(alloc_context(&ctx));
> +
> + ptr = acpigen_get_current(ctx);
> + acpigen_emit_byte(ctx, 0x23);
> + ut_asserteq(1, acpigen_get_current(ctx) - ptr);
> + ut_asserteq(0x23, *(u8 *)ptr);
> +
> + acpigen_emit_word(ctx, 0x1234);
> + ut_asserteq(3, acpigen_get_current(ctx) - ptr);
> + ut_asserteq(0x1234, get_unaligned((u16 *)(ptr + 1)));
> +
> + acpigen_emit_dword(ctx, 0x87654321);
> + ut_asserteq(7, acpigen_get_current(ctx) - ptr);
> + ut_asserteq(0x87654321, get_unaligned((u32 *)(ptr + 3)));
> +
> + free_context(&ctx);
> +
> + return 0;
> +}
> +DM_TEST(dm_test_acpi_emit_simple, 0);
> --
Regards,
Bin
More information about the U-Boot
mailing list