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);
}
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_write_dsm_uuid(&ids[i]);
acpigen_pop_len(); /* If (LEqual (Local0, ToUUID(uuid))) */
/* Else */
acpigen_write_else();
/* Return (Buffer (One) { 0x0 }) */
/* Return (Buffer (One) { 0x0 }) */
acpigen_write_return_singleton_buffer(0x0);
acpigen_pop_len(); /* Else */
acpigen_pop_len(); /* Method _DSM */
}

View File

@ -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