Message ID | 20200614025523.40183-11-sjg@chromium.org |
---|---|
State | Superseded |
Headers | show |
Series | dm: Add programmatic generation of ACPI tables (part B) | expand |
Hi Simon, On Sun, Jun 14, 2020 at 10:55 AM Simon Glass <sjg at chromium.org> wrote: > > Add more functions to handle some miscellaneous ACPI opcodes. > > Signed-off-by: Simon Glass <sjg at chromium.org> > Reviewed-by: Wolfgang Wallner <wolfgang.wallner at br-automation.com> > --- > > Changes in v3: > - Fix function name in comment for acpigen_write_not() > - Use #defines for the mask values > > include/acpi/acpigen.h | 117 +++++++++++++++++++++++++++++++++++++++++ > lib/acpi/acpigen.c | 84 +++++++++++++++++++++++++++++ > test/dm/acpigen.c | 75 ++++++++++++++++++++++++++ > 3 files changed, 276 insertions(+) > > diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h > index 40cd72504a..d640324986 100644 > --- a/include/acpi/acpigen.h > +++ b/include/acpi/acpigen.h > @@ -17,6 +17,9 @@ struct acpi_ctx; > /* Top 4 bits of the value used to indicate a three-byte length value */ > #define ACPI_PKG_LEN_3_BYTES 0x80 > > +#define ACPI_METHOD_NARGS_MASK 0x7 > +#define ACPI_METHOD_SERIALIZED_MASK BIT(3) > + > /* ACPI Op/Prefix codes */ > enum { > ZERO_OP = 0x00, > @@ -29,9 +32,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, > }; > > /** > @@ -201,4 +221,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_not() - Write a bitwise NOT operation > + * > + * 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 0f08d7b8a8..81ecad774c 100644 > --- a/lib/acpi/acpigen.c > +++ b/lib/acpi/acpigen.c > @@ -71,6 +71,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; > @@ -250,6 +256,38 @@ 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, I am not sure if this is the naming convention U-Boot uses. I prefer we name this to acpigen_write_method_internal or acpigen_write_method_helper > + 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 & ACPI_METHOD_NARGS_MASK); > +} > + > +/* Method (name, nargs, Serialized) */ > +void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name, > + int nargs) > +{ > + acpigen_write_method_(ctx, name, (nargs & ACPI_METHOD_NARGS_MASK) | > + ACPI_METHOD_SERIALIZED_MASK); > +} > + > +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) > * > @@ -286,3 +324,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 4f514eb9cc..86c65fbb82 100644 > --- a/test/dm/acpigen.c > +++ b/test/dm/acpigen.c > @@ -625,3 +625,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); > -- Other than above, Reviewed-by: Bin Meng <bmeng.cn at gmail.com> Regards, Bin
diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index 40cd72504a..d640324986 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -17,6 +17,9 @@ struct acpi_ctx; /* Top 4 bits of the value used to indicate a three-byte length value */ #define ACPI_PKG_LEN_3_BYTES 0x80 +#define ACPI_METHOD_NARGS_MASK 0x7 +#define ACPI_METHOD_SERIALIZED_MASK BIT(3) + /* ACPI Op/Prefix codes */ enum { ZERO_OP = 0x00, @@ -29,9 +32,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, }; /** @@ -201,4 +221,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_not() - Write a bitwise NOT operation + * + * 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 0f08d7b8a8..81ecad774c 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -71,6 +71,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; @@ -250,6 +256,38 @@ 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 & ACPI_METHOD_NARGS_MASK); +} + +/* Method (name, nargs, Serialized) */ +void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name, + int nargs) +{ + acpigen_write_method_(ctx, name, (nargs & ACPI_METHOD_NARGS_MASK) | + ACPI_METHOD_SERIALIZED_MASK); +} + +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) * @@ -286,3 +324,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 4f514eb9cc..86c65fbb82 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -625,3 +625,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);