diff options
author | Furquan Shaikh <furquan@chromium.org> | 2016-10-21 16:37:41 -0700 |
---|---|---|
committer | Furquan Shaikh <furquan@google.com> | 2016-10-25 00:13:16 +0200 |
commit | c00bd18b13f67bf7721d49c89c2d6086c6f9118e (patch) | |
tree | a35d2dc9f17896fa5dda9ee99be2e142def7cbb2 /src/arch/x86/acpigen.c | |
parent | 1d33488968573888ea1fc386b7ede0bc67e9b32c (diff) | |
download | coreboot-c00bd18b13f67bf7721d49c89c2d6086c6f9118e.tar.xz |
arch/x86/acpigen: Add support for _DSM method generation
Add acpigen_write_dsm that generates ACPI AML code for _DSM
method. Caller should provide set of callbacks with callback[i]
corresponding to function index i of DSM method. Local0 and Local1
should not be used in any of the callbacks.
BUG=chrome-os-partner:57846
Change-Id: Ie18cba080424488fe00cc626ea50aa92c1dbb199
Signed-off-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: https://review.coreboot.org/17090
Tested-by: build bot (Jenkins)
Reviewed-by: Alexander Couzens <lynxis@fe80.eu>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/arch/x86/acpigen.c')
-rw-r--r-- | src/arch/x86/acpigen.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c index 35735b5cc9..42d42044af 100644 --- a/src/arch/x86/acpigen.c +++ b/src/arch/x86/acpigen.c @@ -1046,6 +1046,92 @@ void acpigen_write_return_byte(uint8_t arg) acpigen_write_byte(arg); } +/* + * Generate ACPI AML code for _DSM method. + * This function takes as input uuid for the device, set of callbacks and + * argument to pass into the callbacks. Callbacks should ensure that Local0 and + * Local1 are left untouched. Use of Local2-Local7 is permitted in callbacks. + * + * Arguments passed into _DSM method: + * Arg0 = UUID + * Arg1 = Revision + * Arg2 = Function index + * Arg3 = Function specific arguments + * + * AML code generated would look like: + * Method (_DSM, 4, Serialized) { + * ToBuffer (Arg0, Local0) + * If (LEqual (Local0, ToUUID(uuid))) { + * ToInteger (Arg2, Local1) + * If (LEqual (Local1, 0)) { + * <acpigen by callback[0]> + * } Else { + * ... + * If (LEqual (Local1, n)) { + * <acpigen by callback[n]> + * } Else { + * Return (Buffer (One) { 0x0 }) + * } + * } + * } Else { + * Return (Buffer (One) { 0x0 }) + * } + * } + */ +void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *), + size_t count, void *arg) +{ + size_t i; + + /* Method (_DSM, 4, Serialized) */ + acpigen_write_method_serialized("_DSM", 0x4); + + /* ToBuffer (Arg0, Local0) */ + acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP); + + /* If (LEqual (Local0, ToUUID(uuid))) */ + acpigen_write_if(); + acpigen_emit_byte(LEQUAL_OP); + acpigen_emit_byte(LOCAL0_OP); + acpigen_write_uuid(uuid); + + /* ToInteger (Arg2, Local1) */ + acpigen_write_to_integer(ARG2_OP, LOCAL1_OP); + acpigen_write_debug_op(LOCAL1_OP); + + for (i = 0; i < count; i++) { + /* If (Lequal (Local1, i)) */ + acpigen_write_if_lequal(LOCAL1_OP, i); + + /* Callback to write if handler. */ + if (callbacks[i]) + callbacks[i](arg); + + acpigen_pop_len(); /* If */ + + /* Else */ + acpigen_write_else(); + } + + /* Default case: Return (Buffer (One) { 0x0 }) */ + acpigen_write_return_singleton_buffer(0x0); + + /* Pop lengths for all the else clauses. */ + for (i = 0; i < count; i++) + acpigen_pop_len(); + + acpigen_pop_len(); /* If (LEqual (Local0, ToUUID(uuid))) */ + + /* Else */ + acpigen_write_else(); + + /* Return (Buffer (One) { 0x0 }) */ + acpigen_write_return_singleton_buffer(0x0); + + acpigen_pop_len(); /* Else */ + acpigen_pop_len(); /* Method _DSM */ +} + /* Soc-implemented functions -- weak definitions. */ int __attribute__((weak)) acpigen_soc_read_rx_gpio(unsigned int gpio_num) { |