diff options
author | Igor Mammedov <imammedo@redhat.com> | 2015-02-18 19:14:14 +0000 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2015-02-26 13:04:09 +0100 |
commit | 0f2707e4e733614f2cd566e7210c1cff6f3b5b42 (patch) | |
tree | 4c876e48e265085bb95b1b5247ed7a1d72576ddf /hw/acpi | |
parent | e0d2be2ad6461ccdcf3e3930742a6b18a7ee5eb8 (diff) | |
download | qemu-0f2707e4e733614f2cd566e7210c1cff6f3b5b42.tar.gz qemu-0f2707e4e733614f2cd566e7210c1cff6f3b5b42.tar.bz2 qemu-0f2707e4e733614f2cd566e7210c1cff6f3b5b42.zip |
acpi: introduce AML composer aml_append()
Adds for dynamic AML creation, which will be used
for piecing ASL/AML primitives together and hiding
from user/caller details about how nested context
should be closed/packed leaving less space for
mistakes and necessity to know how AML should be
encoded, allowing user to concentrate on ASL
representation instead.
For example it will allow to create AML like this:
init_aml_allocator();
...
Aml *scope = aml_scope("PCI0")
Aml *dev = aml_device("PM")
aml_append(dev, aml_name_decl("_ADR", aml_int(addr)))
aml_append(scope, dev);
...
free_aml_allocator();
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/acpi')
-rw-r--r-- | hw/acpi/aml-build.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index bcb288eab4..caf792b5d2 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -25,6 +25,7 @@ #include <stdbool.h> #include <string.h> #include "hw/acpi/aml-build.h" +#include "qemu/bswap.h" GArray *build_alloc_array(void) { @@ -257,3 +258,80 @@ void build_append_int(GArray *table, uint32_t value) build_append_value(table, value, 4); } } + +static GPtrArray *alloc_list; + +static Aml *aml_alloc(void) +{ + Aml *var = g_new0(typeof(*var), 1); + + g_ptr_array_add(alloc_list, var); + var->block_flags = AML_NO_OPCODE; + var->buf = build_alloc_array(); + return var; +} + +static void aml_free(gpointer data) +{ + Aml *var = data; + build_free_array(var->buf); +} + +Aml *init_aml_allocator(void) +{ + Aml *var; + + assert(!alloc_list); + alloc_list = g_ptr_array_new_with_free_func(aml_free); + var = aml_alloc(); + return var; +} + +void free_aml_allocator(void) +{ + g_ptr_array_free(alloc_list, true); + alloc_list = 0; +} + +/* pack data with DefBuffer encoding */ +static void build_buffer(GArray *array, uint8_t op) +{ + GArray *data = build_alloc_array(); + + build_append_int(data, array->len); + g_array_prepend_vals(array, data->data, data->len); + build_free_array(data); + build_package(array, op); +} + +void aml_append(Aml *parent_ctx, Aml *child) +{ + switch (child->block_flags) { + case AML_OPCODE: + build_append_byte(parent_ctx->buf, child->op); + break; + case AML_EXT_PACKAGE: + build_extop_package(child->buf, child->op); + break; + case AML_PACKAGE: + build_package(child->buf, child->op); + break; + case AML_RES_TEMPLATE: + build_append_byte(child->buf, 0x79); /* EndTag */ + /* + * checksum operations are treated as succeeded if checksum + * field is zero. [ACPI Spec 1.0b, 6.4.2.8 End Tag] + */ + build_append_byte(child->buf, 0); + /* fall through, to pack resources in buffer */ + case AML_BUFFER: + build_buffer(child->buf, child->op); + break; + case AML_NO_OPCODE: + break; + default: + assert(0); + break; + } + build_append_array(parent_ctx->buf, child->buf); +} |