summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/acpigen.c119
-rw-r--r--src/arch/x86/include/arch/acpigen.h17
2 files changed, 78 insertions, 58 deletions
diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c
index 5447752823..8ebdd0982c 100644
--- a/src/arch/x86/acpigen.c
+++ b/src/arch/x86/acpigen.c
@@ -1180,11 +1180,50 @@ void acpigen_write_return_string(const char *arg)
acpigen_write_string(arg);
}
+void acpigen_write_dsm(const char *uuid, void (**callbacks)(void *),
+ size_t count, void *arg)
+{
+ struct dsm_uuid id = DSM_UUID(uuid, callbacks, count, arg);
+ acpigen_write_dsm_uuid_arr(&id, 1);
+}
+
+static void acpigen_write_dsm_uuid(struct dsm_uuid *id)
+{
+ size_t i;
+
+ /* If (LEqual (Local0, ToUUID(uuid))) */
+ acpigen_write_if();
+ acpigen_emit_byte(LEQUAL_OP);
+ acpigen_emit_byte(LOCAL0_OP);
+ acpigen_write_uuid(id->uuid);
+
+ /* ToInteger (Arg2, Local1) */
+ acpigen_write_to_integer(ARG2_OP, LOCAL1_OP);
+
+ for (i = 0; i < id->count; i++) {
+ /* If (LEqual (Local1, i)) */
+ acpigen_write_if_lequal_op_int(LOCAL1_OP, i);
+
+ /* Callback to write if handler. */
+ if (id->callbacks[i])
+ id->callbacks[i](id->arg);
+
+ acpigen_pop_len(); /* If */
+ }
+
+ /* Default case: Return (Buffer (One) { 0x0 }) */
+ acpigen_write_return_singleton_buffer(0x0);
+
+ acpigen_pop_len(); /* If (LEqual (Local0, ToUUID(uuid))) */
+
+}
+
/*
* 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.
+ * This function takes as input array of 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
@@ -1194,26 +1233,26 @@ void acpigen_write_return_string(const char *arg)
*
* 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 })
- * }
+ * ToBuffer (Arg0, Local0)
+ * If (LEqual (Local0, ToUUID(uuid))) {
+ * ToInteger (Arg2, Local1)
+ * If (LEqual (Local1, 0)) {
+ * <acpigen by callback[0]>
+ * }
+ * ...
+ * If (LEqual (Local1, n)) {
+ * <acpigen by callback[n]>
+ * }
+ * Return (Buffer (One) { 0x0 })
+ * }
+ * ...
+ * If (LEqual (Local0, ToUUID(uuidn))) {
+ * ...
+ * }
+ * Return (Buffer (One) { 0x0 })
* }
*/
-void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
- size_t count, void *arg)
+void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count)
{
size_t i;
@@ -1223,46 +1262,12 @@ void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
/* 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_op_int(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();
+ acpigen_write_dsm_uuid(&ids[i]);
- /* Return (Buffer (One) { 0x0 }) */
+ /* Return (Buffer (One) { 0x0 }) */
acpigen_write_return_singleton_buffer(0x0);
- acpigen_pop_len(); /* Else */
acpigen_pop_len(); /* Method _DSM */
}
diff --git a/src/arch/x86/include/arch/acpigen.h b/src/arch/x86/include/arch/acpigen.h
index dcd8fb7a64..f76d85e9bc 100644
--- a/src/arch/x86/include/arch/acpigen.h
+++ b/src/arch/x86/include/arch/acpigen.h
@@ -144,6 +144,20 @@ struct opregion {
unsigned long regionlen;
};
+#define DSM_UUID(DSM_UUID, DSM_CALLBACKS, DSM_COUNT, DSM_ARG) \
+ { .uuid = DSM_UUID, \
+ .callbacks = DSM_CALLBACKS, \
+ .count = DSM_COUNT, \
+ .arg = DSM_ARG, \
+ }
+
+struct dsm_uuid {
+ const char *uuid;
+ void (**callbacks)(void *);
+ size_t count;
+ void *arg;
+};
+
void acpigen_write_return_integer(uint64_t arg);
void acpigen_write_return_string(const char *arg);
void acpigen_write_len_f(void);
@@ -235,8 +249,9 @@ void acpigen_write_return_byte(uint8_t arg);
* argument to pass into the callbacks. Callbacks should ensure that Local0 and
* Local1 are left untouched. Use of Local2-Local7 is permitted in callbacks.
*/
-void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
+void acpigen_write_dsm(const char *uuid, void (**callbacks)(void *),
size_t count, void *arg);
+void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count);
/*
* Generate ACPI AML code for OperationRegion
* This function takes input region name, region space, region offset & region