
Hi Simon,
-----"Simon Glass" sjg@chromium.org schrieb: -----
Betreff: [PATCH v2 22/35] acpi: Add support for various misc ACPI opcodes
Add more functions to handle some miscellaneous ACPI opcodes.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None Changes in v1: None
include/acpi/acpigen.h | 114 +++++++++++++++++++++++++++++++++++++++++ lib/acpi/acpigen.c | 83 ++++++++++++++++++++++++++++++ test/dm/acpigen.c | 75 +++++++++++++++++++++++++++ 3 files changed, 272 insertions(+)
diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index 16b33ebe66..c595bb9efa 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -26,9 +26,26 @@ enum { QWORD_PREFIX = 0x0e, BUFFER_OP = 0x11, PACKAGE_OP = 0x12,
- METHOD_OP = 0x14,
- SLEEP_OP = 0x22, DUAL_NAME_PREFIX = 0x2e, MULTI_NAME_PREFIX = 0x2f,
- DEBUG_OP = 0x31,
- EXT_OP_PREFIX = 0x5b, ROOT_PREFIX = 0x5c,
- LOCAL0_OP = 0x60,
- LOCAL1_OP = 0x61,
- LOCAL2_OP = 0x62,
- LOCAL3_OP = 0x63,
- LOCAL4_OP = 0x64,
- LOCAL5_OP = 0x65,
- LOCAL6_OP = 0x66,
- LOCAL7_OP = 0x67,
- STORE_OP = 0x70,
- AND_OP = 0x7b,
- OR_OP = 0x7d,
- NOT_OP = 0x80,
- RETURN_OP = 0xa4,
};
/** @@ -196,4 +213,101 @@ void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath); */ int acpigen_write_uuid(struct acpi_ctx *ctx, const char *uuid);
+/**
- acpigen_emit_ext_op() - Emit an extended op with the EXT_OP_PREFIX prefix
- @ctx: ACPI context pointer
- @op: Operation code (e.g. SLEEP_OP)
- */
+void acpigen_emit_ext_op(struct acpi_ctx *ctx, uint op);
+/**
- acpigen_write_method() - Write a method header
- @ctx: ACPI context pointer
- @name: Method name (4 characters)
- @nargs: Number of method arguments (0 if none)
- */
+void acpigen_write_method(struct acpi_ctx *ctx, const char *name, int nargs);
+/**
- acpigen_write_method_serialized() - Write a method header
- This sets the 'serialized' flag so that the method is thread-safe
- @ctx: ACPI context pointer
- @name: Method name (4 characters)
- @nargs: Number of method arguments (0 if none)
- */
+void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name,
int nargs);
+/**
- acpigen_write_sta() - Write a _STA method
- @ctx: ACPI context pointer
- @status: Status value to return
- */
+void acpigen_write_sta(struct acpi_ctx *ctx, uint status);
+/**
- acpigen_write_sleep() - Write a sleep operation
- @ctx: ACPI context pointer
- @sleep_ms: Number of milliseconds to sleep for
- */
+void acpigen_write_sleep(struct acpi_ctx *ctx, u64 sleep_ms);
+/**
- acpigen_write_store() - Write a store operation
- @ctx: ACPI context pointer
- */
+void acpigen_write_store(struct acpi_ctx *ctx);
+/**
- acpigen_write_debug_string() - Write a debug string
- This writes a debug operation with an associated string
- @ctx: ACPI context pointer
- @str: String to write
- */
+void acpigen_write_debug_string(struct acpi_ctx *ctx, const char *str);
+/**
- acpigen_write_or() - Write a bitwise OR operation
- res = arg1 | arg2
- @ctx: ACPI context pointer
- @arg1: ACPI opcode for operand 1 (e.g. LOCAL0_OP)
- @arg2: ACPI opcode for operand 2 (e.g. LOCAL1_OP)
- @res: ACPI opcode for result (e.g. LOCAL2_OP)
- */
+void acpigen_write_or(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res);
+/**
- acpigen_write_and() - Write a bitwise AND operation
- res = arg1 & arg2
- @ctx: ACPI context pointer
- @arg1: ACPI opcode for operand 1 (e.g. LOCAL0_OP)
- @arg2: ACPI opcode for operand 2 (e.g. LOCAL1_OP)
- @res: ACPI opcode for result (e.g. LOCAL2_OP)
- */
+void acpigen_write_and(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res);
+/**
- acpigen_write_or() - Write a bitwise NOT operation
Typo: this should be acpigen_write_not()
- res = ~arg1
- @ctx: ACPI context pointer
- @arg: ACPI opcode for operand (e.g. LOCAL0_OP)
- @res: ACPI opcode for result (e.g. LOCAL2_OP)
- */
+void acpigen_write_not(struct acpi_ctx *ctx, u8 arg, u8 res);
#endif diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c index 7321a98c0f..57b295aa4e 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -74,6 +74,12 @@ void acpigen_pop_len(struct acpi_ctx *ctx) p[2] = (len >> 12 & 0xff); }
+void acpigen_emit_ext_op(struct acpi_ctx *ctx, uint op) +{
- acpigen_emit_byte(ctx, EXT_OP_PREFIX);
- acpigen_emit_byte(ctx, op);
+}
char *acpigen_write_package(struct acpi_ctx *ctx, int nr_el) { char *p; @@ -253,6 +259,37 @@ void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath) acpigen_emit_namestring(ctx, namepath); }
+static void acpigen_write_method_(struct acpi_ctx *ctx, const char *name,
uint flags)
+{
- acpigen_emit_byte(ctx, METHOD_OP);
- acpigen_write_len_f(ctx);
- acpigen_emit_namestring(ctx, name);
- acpigen_emit_byte(ctx, flags);
+}
+/* Method (name, nargs, NotSerialized) */ +void acpigen_write_method(struct acpi_ctx *ctx, const char *name, int nargs) +{
- acpigen_write_method_(ctx, name, nargs & 7);
+}
+/* Method (name, nargs, Serialized) */ +void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name,
int nargs)
+{
- acpigen_write_method_(ctx, name, (nargs & 7) | (1 << 3));
Nit: Defines for the mask and the flag would make this and the above function more readable.
+}
+void acpigen_write_sta(struct acpi_ctx *ctx, uint status) +{
- /* Method (_STA, 0, NotSerialized) { Return (status) } */
- acpigen_write_method(ctx, "_STA", 0);
- acpigen_emit_byte(ctx, RETURN_OP);
- acpigen_write_byte(ctx, status);
- acpigen_pop_len(ctx);
+}
/*
- ToUUID(uuid)
@@ -290,3 +327,49 @@ int acpigen_write_uuid(struct acpi_ctx *ctx, const char *uuid)
return 0; }
+/* Sleep (ms) */ +void acpigen_write_sleep(struct acpi_ctx *ctx, u64 sleep_ms) +{
- acpigen_emit_ext_op(ctx, SLEEP_OP);
- acpigen_write_integer(ctx, sleep_ms);
+}
+void acpigen_write_store(struct acpi_ctx *ctx) +{
- acpigen_emit_byte(ctx, STORE_OP);
+}
+/* Or (arg1, arg2, res) */ +void acpigen_write_or(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res) +{
- acpigen_emit_byte(ctx, OR_OP);
- acpigen_emit_byte(ctx, arg1);
- acpigen_emit_byte(ctx, arg2);
- acpigen_emit_byte(ctx, res);
+}
+/* And (arg1, arg2, res) */ +void acpigen_write_and(struct acpi_ctx *ctx, u8 arg1, u8 arg2, u8 res) +{
- acpigen_emit_byte(ctx, AND_OP);
- acpigen_emit_byte(ctx, arg1);
- acpigen_emit_byte(ctx, arg2);
- acpigen_emit_byte(ctx, res);
+}
+/* Not (arg, res) */ +void acpigen_write_not(struct acpi_ctx *ctx, u8 arg, u8 res) +{
- acpigen_emit_byte(ctx, NOT_OP);
- acpigen_emit_byte(ctx, arg);
- acpigen_emit_byte(ctx, res);
+}
+/* Store (str, DEBUG) */ +void acpigen_write_debug_string(struct acpi_ctx *ctx, const char *str) +{
- acpigen_write_store(ctx);
- acpigen_write_string(ctx, str);
- acpigen_emit_ext_op(ctx, DEBUG_OP);
+} diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index db8cad47d8..e059d6f80d 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -621,3 +621,78 @@ static int dm_test_acpi_uuid(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_uuid, 0);
+/* Test writing misc ACPI codes */ +static int dm_test_acpi_misc(struct unit_test_state *uts) +{
- struct acpi_ctx *ctx;
- const int flags = 3;
- const int nargs = 4;
- u8 *ptr;
- ut_assertok(alloc_context(&ctx));
- ptr = acpigen_get_current(ctx);
- acpigen_write_sleep(ctx, TEST_INT64);
- ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 3)));
- ptr += 11;
- acpigen_write_store(ctx);
- ut_asserteq(STORE_OP, *ptr);
- ptr++;
- acpigen_write_debug_string(ctx, TEST_STRING);
- ut_asserteq_str(TEST_STRING, (char *)ptr + 2);
- ptr += 2 + sizeof(TEST_STRING);
- ut_asserteq(EXT_OP_PREFIX, ptr[0]);
- ut_asserteq(DEBUG_OP, ptr[1]);
- ptr += 2;
- acpigen_write_sta(ctx, flags);
- ut_asserteq(METHOD_OP, ptr[0]);
- ut_asserteq(11, get_length(ptr + 1));
- ut_asserteq_strn("_STA", (char *)ptr + 4);
- ut_asserteq(0, ptr[8]);
- ut_asserteq(RETURN_OP, ptr[9]);
- ut_asserteq(BYTE_PREFIX, ptr[10]);
- ut_asserteq(flags, ptr[11]);
- ptr += 12;
- acpigen_write_sleep(ctx, TEST_INT16);
- ut_asserteq(SLEEP_OP, ptr[1]);
- ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 3)));
- ptr += 5;
- acpigen_write_method_serialized(ctx, "FRED", nargs);
- ut_asserteq(METHOD_OP, ptr[0]);
- ut_asserteq_strn("FRED", (char *)ptr + 4);
- ut_asserteq(1 << 3 | nargs, ptr[8]);
- ut_asserteq(1, ctx->ltop); /* method is unfinished */
- ptr += 9;
- acpigen_write_or(ctx, LOCAL0_OP, LOCAL1_OP, LOCAL2_OP);
- acpigen_write_and(ctx, LOCAL3_OP, LOCAL4_OP, LOCAL5_OP);
- acpigen_write_not(ctx, LOCAL6_OP, LOCAL7_OP);
- ut_asserteq(OR_OP, ptr[0]);
- ut_asserteq(LOCAL0_OP, ptr[1]);
- ut_asserteq(LOCAL1_OP, ptr[2]);
- ut_asserteq(LOCAL2_OP, ptr[3]);
- ptr += 4;
- ut_asserteq(AND_OP, ptr[0]);
- ut_asserteq(LOCAL3_OP, ptr[1]);
- ut_asserteq(LOCAL4_OP, ptr[2]);
- ut_asserteq(LOCAL5_OP, ptr[3]);
- ptr += 4;
- ut_asserteq(NOT_OP, ptr[0]);
- ut_asserteq(LOCAL6_OP, ptr[1]);
- ut_asserteq(LOCAL7_OP, ptr[2]);
- ptr += 3;
- ut_asserteq_ptr(ptr, ctx->current);
- free_context(&ctx);
- return 0;
+}
+DM_TEST(dm_test_acpi_misc, 0);
2.26.2.645.ge9eca65c58-goog
Reviewed-by: Wolfgang Wallner wolfgang.wallner@br-automation.com