All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [PATCH v3 17/35] acpi: Support writing a name
Date: Sat, 13 Jun 2020 20:55:05 -0600	[thread overview]
Message-ID: <20200614025523.40183-7-sjg@chromium.org> (raw)
In-Reply-To: <20200614025523.40183-1-sjg@chromium.org>

ACPI supports storing names which are made up of multiple path components.
Several special cases are supported. Add a function to emit a name.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com>
---

(no changes since v1)

 include/acpi/acpigen.h | 25 +++++++++++
 include/test/ut.h      | 17 ++++++++
 lib/acpi/acpigen.c     | 96 ++++++++++++++++++++++++++++++++++++++++++
 test/dm/acpigen.c      | 93 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 231 insertions(+)

diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h
index cf7f6173db..4d3202c922 100644
--- a/include/acpi/acpigen.h
+++ b/include/acpi/acpigen.h
@@ -21,12 +21,15 @@ struct acpi_ctx;
 enum {
 	ZERO_OP			= 0x00,
 	ONE_OP			= 0x01,
+	NAME_OP			= 0x08,
 	BYTE_PREFIX		= 0x0a,
 	WORD_PREFIX		= 0x0b,
 	DWORD_PREFIX		= 0x0c,
 	STRING_PREFIX		= 0x0d,
 	QWORD_PREFIX		= 0x0e,
 	PACKAGE_OP		= 0x12,
+	DUAL_NAME_PREFIX	= 0x2e,
+	MULTI_NAME_PREFIX	= 0x2f,
 };
 
 /**
@@ -162,4 +165,26 @@ void acpigen_write_integer(struct acpi_ctx *ctx, u64 data);
  * @str: String to write
  */
 void acpigen_write_string(struct acpi_ctx *ctx, const char *str);
+
+/**
+ * acpigen_emit_namestring() - Emit an ACPI name
+ *
+ * This writes out an ACPI name or path in the required special format. It does
+ * not add the NAME_OP prefix.
+ *
+ * @ctx: ACPI context pointer
+ * @namepath: Name / path to emit
+ */
+void acpigen_emit_namestring(struct acpi_ctx *ctx, const char *namepath);
+
+/**
+ * acpigen_write_name() - Write out an ACPI name
+ *
+ * This writes out an ACPI name or path in the required special format with a
+ * NAME_OP prefix.
+ *
+ * @ctx: ACPI context pointer
+ * @namepath: Name / path to emit
+ */
+void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath);
 #endif
diff --git a/include/test/ut.h b/include/test/ut.h
index 7ddd6e8872..99bbb1230c 100644
--- a/include/test/ut.h
+++ b/include/test/ut.h
@@ -134,6 +134,23 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes);
 	}								\
 }
 
+/*
+ * Assert that two string expressions are equal, up to length of the
+ * first
+ */
+#define ut_asserteq_strn(expr1, expr2) {				\
+	const char *_val1 = (expr1), *_val2 = (expr2);			\
+	int _len = strlen(_val1);					\
+									\
+	if (memcmp(_val1, _val2, _len)) {				\
+		ut_failf(uts, __FILE__, __LINE__, __func__,		\
+			 #expr1 " = " #expr2,				\
+			 "Expected \"%.*s\", got \"%.*s\"",		\
+			 _len, _val1, _len, _val2);			\
+		return CMD_RET_FAILURE;					\
+	}								\
+}
+
 /* Assert that two memory areas are equal */
 #define ut_asserteq_mem(expr1, expr2, len) {				\
 	const u8 *_val1 = (u8 *)(expr1), *_val2 = (u8 *)(expr2);	\
diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c
index dcf84afbe6..55d7afc633 100644
--- a/lib/acpi/acpigen.c
+++ b/lib/acpi/acpigen.c
@@ -152,3 +152,99 @@ void acpigen_write_string(struct acpi_ctx *ctx, const char *str)
 	acpigen_emit_byte(ctx, STRING_PREFIX);
 	acpigen_emit_string(ctx, str);
 }
+
+/*
+ * The naming conventions for ACPI namespace names are a bit tricky as
+ * each element has to be 4 chars wide ("All names are a fixed 32 bits.")
+ * and "By convention, when an ASL compiler pads a name shorter than 4
+ * characters, it is done so with trailing underscores ('_')".
+ *
+ * Check sections 5.3, 20.2.2 and 20.4 of ACPI spec 6.3 for details.
+ */
+static void acpigen_emit_simple_namestring(struct acpi_ctx *ctx,
+					   const char *name)
+{
+	const char *ptr;
+	int i;
+
+	for (i = 0, ptr = name; i < 4; i++) {
+		if (!*ptr || *ptr == '.')
+			acpigen_emit_byte(ctx, '_');
+		else
+			acpigen_emit_byte(ctx, *ptr++);
+	}
+}
+
+static void acpigen_emit_double_namestring(struct acpi_ctx *ctx,
+					   const char *name, int dotpos)
+{
+	acpigen_emit_byte(ctx, DUAL_NAME_PREFIX);
+	acpigen_emit_simple_namestring(ctx, name);
+	acpigen_emit_simple_namestring(ctx, &name[dotpos + 1]);
+}
+
+static void acpigen_emit_multi_namestring(struct acpi_ctx *ctx,
+					  const char *name)
+{
+	unsigned char *pathlen;
+	int count = 0;
+
+	acpigen_emit_byte(ctx, MULTI_NAME_PREFIX);
+	pathlen = ctx->current;
+	acpigen_emit_byte(ctx, 0);
+
+	while (*name) {
+		acpigen_emit_simple_namestring(ctx, name);
+		/* find end or next entity */
+		while (*name != '.' && *name)
+			name++;
+		/* forward to next */
+		if (*name == '.')
+			name++;
+		count++;
+	}
+
+	*pathlen = count;
+}
+
+void acpigen_emit_namestring(struct acpi_ctx *ctx, const char *namepath)
+{
+	int dotcount;
+	int dotpos;
+	int i;
+
+	/* We can start with a '\' */
+	if (*namepath == '\\') {
+		acpigen_emit_byte(ctx, '\\');
+		namepath++;
+	}
+
+	/* And there can be any number of '^' */
+	while (*namepath == '^') {
+		acpigen_emit_byte(ctx, '^');
+		namepath++;
+	}
+
+	for (i = 0, dotcount = 0; namepath[i]; i++) {
+		if (namepath[i] == '.') {
+			dotcount++;
+			dotpos = i;
+		}
+	}
+
+	/* If we have only \\ or only ^* then we need to add a nul name */
+	if (!*namepath)
+		acpigen_emit_byte(ctx, ZERO_OP);
+	else if (dotcount == 0)
+		acpigen_emit_simple_namestring(ctx, namepath);
+	else if (dotcount == 1)
+		acpigen_emit_double_namestring(ctx, namepath, dotpos);
+	else
+		acpigen_emit_multi_namestring(ctx, namepath);
+}
+
+void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath)
+{
+	acpigen_emit_byte(ctx, NAME_OP);
+	acpigen_emit_namestring(ctx, namepath);
+}
diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c
index 836cb4f75c..c151f7a76b 100644
--- a/test/dm/acpigen.c
+++ b/test/dm/acpigen.c
@@ -499,3 +499,96 @@ static int dm_test_acpi_string(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_acpi_string, 0);
+
+/* Test writing a name */
+static int dm_test_acpi_name(struct unit_test_state *uts)
+{
+	struct acpi_ctx *ctx;
+	u8 *ptr;
+
+	ut_assertok(alloc_context(&ctx));
+
+	ptr = acpigen_get_current(ctx);
+
+	/*
+	 * The names here are made up for testing the various cases. The
+	 * grammar is in the ACPI spec 6.3 section 19.2.2
+	 */
+	acpigen_write_name(ctx, "\\_SB");
+	acpigen_write_name(ctx, "\\_SB.I2C0");
+	acpigen_write_name(ctx, "\\_SB.I2C0.TPM2");
+	acpigen_write_name(ctx, "\\_SB.I2C0.TPM2.LONG");
+	acpigen_write_name(ctx, "^^^^SPI0.FLAS");
+	acpigen_write_name(ctx, "NN");
+	acpigen_write_name(ctx, "^AB.CD.D.EFG");
+	acpigen_write_name(ctx, "^^^^");
+	acpigen_write_name(ctx, "\\");
+	acpigen_write_name(ctx, "\\ABCD");
+
+	ut_asserteq(107, acpigen_get_current(ctx) - ptr);
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq_strn("\\_SB_", (char *)ptr + 1);
+	ptr += 6;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq('\\', ptr[1]);
+	ut_asserteq(DUAL_NAME_PREFIX, ptr[2]);
+	ut_asserteq_strn("_SB_I2C0", (char *)ptr + 3);
+	ptr += 11;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq('\\', ptr[1]);
+	ut_asserteq(MULTI_NAME_PREFIX, ptr[2]);
+	ut_asserteq(3, ptr[3]);
+	ut_asserteq_strn("_SB_I2C0TPM2", (char *)ptr + 4);
+	ptr += 16;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq('\\', ptr[1]);
+	ut_asserteq(MULTI_NAME_PREFIX, ptr[2]);
+	ut_asserteq(4, ptr[3]);
+	ut_asserteq_strn("_SB_I2C0TPM2LONG", (char *)ptr + 4);
+	ptr += 20;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq('^', ptr[1]);
+	ut_asserteq('^', ptr[2]);
+	ut_asserteq('^', ptr[3]);
+	ut_asserteq('^', ptr[4]);
+	ut_asserteq(DUAL_NAME_PREFIX, ptr[5]);
+	ut_asserteq_strn("SPI0FLAS", (char *)ptr + 6);
+	ptr += 14;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq_strn("NN__", (char *)ptr + 1);
+	ptr += 5;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq('^', ptr[1]);
+	ut_asserteq(MULTI_NAME_PREFIX, ptr[2]);
+	ut_asserteq(4, ptr[3]);
+	ut_asserteq_strn("AB__CD__D___EFG_", (char *)ptr + 4);
+	ptr += 20;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq('^', ptr[1]);
+	ut_asserteq('^', ptr[2]);
+	ut_asserteq('^', ptr[3]);
+	ut_asserteq('^', ptr[4]);
+	ut_asserteq(ZERO_OP, ptr[5]);
+	ptr += 6;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq('\\', ptr[1]);
+	ut_asserteq(ZERO_OP, ptr[2]);
+	ptr += 3;
+
+	ut_asserteq(NAME_OP, ptr[0]);
+	ut_asserteq_strn("\\ABCD", (char *)ptr + 1);
+	ptr += 5;
+
+	free_context(&ctx);
+
+	return 0;
+}
+DM_TEST(dm_test_acpi_name, 0);
-- 
2.27.0.290.gba653c62da-goog

  parent reply	other threads:[~2020-06-14  2:55 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-14  2:54 [PATCH v3 00/35] dm: Add programmatic generation of ACPI tables (part B) Simon Glass
2020-06-14  2:54 ` [PATCH v3 01/35] dm: core: Add an ACPI name for the root node Simon Glass
2020-06-14  2:54 ` [PATCH v3 02/35] acpi: Add a function to get a device path and scope Simon Glass
2020-06-14  2:54 ` [PATCH v3 03/35] acpi: Add a way to check device status Simon Glass
2020-06-28  9:13   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 04/35] irq: Add a method to convert an interrupt to ACPI Simon Glass
2020-06-28  9:13   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 05/35] acpi: Support generation of ACPI code Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-28  9:13   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 06/35] acpi: Support generation of interrupt descriptor Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 07/35] gpio: Add a method to convert a GPIO to ACPI Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 08/35] acpi: Support string output Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:54 ` [PATCH v3 09/35] acpi: Support generation of GPIO descriptor Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:54 ` [PATCH v3 10/35] acpi: Support generation of a GPIO/irq for a device Simon Glass
2020-06-28  9:55   ` Bin Meng
2020-06-14  2:54 ` [PATCH v3 11/35] acpi: Support generation of I2C descriptor Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 12/35] acpi: Support generation of SPI descriptor Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  1:27   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:55 ` [PATCH v3 13/35] acpigen: Support writing a length Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 14/35] acpigen: Support writing a package Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 15/35] acpi: Support writing an integer Simon Glass
2020-06-29  1:27   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 16/35] acpi: Support writing a string Simon Glass
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` Simon Glass [this message]
2020-06-29  2:07   ` [PATCH v3 17/35] acpi: Support writing a name Bin Meng
2020-06-14  2:55 ` [PATCH v3 18/35] acpi: Support writing a UUID Simon Glass
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 19/35] acpi: Support writing Device Properties objects via _DSD Simon Glass
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 20/35] acpi: Support writing a GPIO Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  2:07   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 21/35] acpi: Support copying properties from device tree to ACPI Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 22/35] acpi: Add support for various misc ACPI opcodes Simon Glass
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 23/35] acpi: Add support for writing a Power Resource Simon Glass
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 24/35] acpi: Add support for writing a GPIO power sequence Simon Glass
2020-06-29  3:00   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 25/35] acpi: Add support for a generic " Simon Glass
2020-06-14  2:55 ` [PATCH v3 26/35] acpi: Add support for SSDT generation Simon Glass
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 27/35] x86: acpi: Move MADT down a bit Simon Glass
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 28/35] acpi: Record the items added to SSDT Simon Glass
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 29/35] acpi: Support ordering SSDT data by device Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 30/35] x86: Allow devices to write an SSDT Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  3:36   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 31/35] acpi: Add support for DSDT generation Simon Glass
2020-06-29  5:39   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:55 ` [PATCH v3 32/35] x86: Allow devices to write to DSDT Simon Glass
2020-06-16 11:31   ` Wolfgang Wallner
2020-06-29  5:39   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 33/35] pci: Avoid a crash in device_is_on_pci_bus() Simon Glass
2020-06-29  5:39   ` Bin Meng
2020-06-14  2:55 ` [PATCH v3 34/35] dm: acpi: Enhance acpi_get_name() Simon Glass
2020-06-29  5:39   ` Bin Meng
2020-07-07 19:12     ` Simon Glass
2020-06-14  2:55 ` [PATCH v3 35/35] acpi: Add an acpi command to list/dump generated ACPI items Simon Glass
2020-06-29  5:39   ` Bin Meng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200614025523.40183-7-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.