arch/x86/acpigen: Write DSM method with multiple UUID's

Enable generic way of writing DSM method which can write acpi table for
multiple UUID's.

Change-Id: Ic1fbdc0647e8fdc50ffa407887feb19a63cb48e4
Signed-off-by: Naresh G Solanki <naresh.solanki@intel.com>
Reviewed-on: https://review.coreboot.org/17424
Tested-by: build bot (Jenkins)
Reviewed-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Naresh G Solanki 2016-11-15 10:13:15 +05:30 committed by Martin Roth
parent c36fa6433e
commit ab77cd4785
2 changed files with 78 additions and 58 deletions

View File

@ -1180,11 +1180,50 @@ void acpigen_write_return_string(const char *arg)
acpigen_write_string(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. * Generate ACPI AML code for _DSM method.
* This function takes as input uuid for the device, set of callbacks and * This function takes as input array of uuid for the device, set of callbacks
* argument to pass into the callbacks. Callbacks should ensure that Local0 and * and argument to pass into the callbacks. Callbacks should ensure that Local0
* Local1 are left untouched. Use of Local2-Local7 is permitted in callbacks. * and Local1 are left untouched. Use of Local2-Local7 is permitted in
* callbacks.
* *
* Arguments passed into _DSM method: * Arguments passed into _DSM method:
* Arg0 = UUID * Arg0 = UUID
@ -1194,26 +1233,26 @@ void acpigen_write_return_string(const char *arg)
* *
* AML code generated would look like: * AML code generated would look like:
* Method (_DSM, 4, Serialized) { * Method (_DSM, 4, Serialized) {
* ToBuffer (Arg0, Local0) * ToBuffer (Arg0, Local0)
* If (LEqual (Local0, ToUUID(uuid))) { * If (LEqual (Local0, ToUUID(uuid))) {
* ToInteger (Arg2, Local1) * ToInteger (Arg2, Local1)
* If (LEqual (Local1, 0)) { * If (LEqual (Local1, 0)) {
* <acpigen by callback[0]> * <acpigen by callback[0]>
* } Else { * }
* ... * ...
* If (LEqual (Local1, n)) { * If (LEqual (Local1, n)) {
* <acpigen by callback[n]> * <acpigen by callback[n]>
* } Else { * }
* Return (Buffer (One) { 0x0 }) * Return (Buffer (One) { 0x0 })
* } * }
* } * ...
* } Else { * If (LEqual (Local0, ToUUID(uuidn))) {
* Return (Buffer (One) { 0x0 }) * ...
* } * }
* Return (Buffer (One) { 0x0 })
* } * }
*/ */
void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *), void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count)
size_t count, void *arg)
{ {
size_t i; size_t i;
@ -1223,46 +1262,12 @@ void acpigen_write_dsm(const char *uuid, void (*callbacks[])(void *),
/* ToBuffer (Arg0, Local0) */ /* ToBuffer (Arg0, Local0) */
acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP); 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++) for (i = 0; i < count; i++)
acpigen_pop_len(); acpigen_write_dsm_uuid(&ids[i]);
acpigen_pop_len(); /* If (LEqual (Local0, ToUUID(uuid))) */ /* Return (Buffer (One) { 0x0 }) */
/* Else */
acpigen_write_else();
/* Return (Buffer (One) { 0x0 }) */
acpigen_write_return_singleton_buffer(0x0); acpigen_write_return_singleton_buffer(0x0);
acpigen_pop_len(); /* Else */
acpigen_pop_len(); /* Method _DSM */ acpigen_pop_len(); /* Method _DSM */
} }

View File

@ -144,6 +144,20 @@ struct opregion {
unsigned long regionlen; 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_integer(uint64_t arg);
void acpigen_write_return_string(const char *arg); void acpigen_write_return_string(const char *arg);
void acpigen_write_len_f(void); 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 * argument to pass into the callbacks. Callbacks should ensure that Local0 and
* Local1 are left untouched. Use of Local2-Local7 is permitted in callbacks. * 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); size_t count, void *arg);
void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, size_t count);
/* /*
* Generate ACPI AML code for OperationRegion * Generate ACPI AML code for OperationRegion
* This function takes input region name, region space, region offset & region * This function takes input region name, region space, region offset & region