tools: amldecode: add parsing support for more AML opcodes
This commit is contained in:
@@ -99,7 +99,7 @@ void acpi_object_print(struct acpi_object *object, int depth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (object->name[0] == 0) {
|
if (object->name[0] == 0) {
|
||||||
printf("<unnamed>\n");
|
printf("<unnamed> [%s]\n", acpi_object_type_string(object->type));
|
||||||
} else {
|
} else {
|
||||||
printf("%s [%s]\n", object->name, acpi_object_type_string(object->type));
|
printf("%s [%s]\n", object->name, acpi_object_type_string(object->type));
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ const char *acpi_object_type_string(enum acpi_object_type type)
|
|||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_NONE)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_NONE)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_VALUE)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_VALUE)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_NAMESPACE)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_NAMESPACE)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_CPU)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_PROCESSOR)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_DEVICE)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_DEVICE)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_METHOD)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_METHOD)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_POWER_RESOURCE)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_POWER_RESOURCE)
|
||||||
@@ -130,6 +130,8 @@ const char *acpi_object_type_string(enum acpi_object_type type)
|
|||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_FIELD)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_FIELD)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_PACKAGE)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_PACKAGE)
|
||||||
OBJECT_TYPE_STRING(ACPI_OBJECT_BUFFER)
|
OBJECT_TYPE_STRING(ACPI_OBJECT_BUFFER)
|
||||||
|
OBJECT_TYPE_STRING(ACPI_OBJECT_ALIAS)
|
||||||
|
OBJECT_TYPE_STRING(ACPI_OBJECT_MUTEX)
|
||||||
default:
|
default:
|
||||||
return "<unknown>";
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ enum acpi_object_type {
|
|||||||
ACPI_OBJECT_NONE = 0,
|
ACPI_OBJECT_NONE = 0,
|
||||||
ACPI_OBJECT_VALUE,
|
ACPI_OBJECT_VALUE,
|
||||||
ACPI_OBJECT_NAMESPACE,
|
ACPI_OBJECT_NAMESPACE,
|
||||||
ACPI_OBJECT_CPU,
|
ACPI_OBJECT_PROCESSOR,
|
||||||
ACPI_OBJECT_DEVICE,
|
ACPI_OBJECT_DEVICE,
|
||||||
ACPI_OBJECT_METHOD,
|
ACPI_OBJECT_METHOD,
|
||||||
ACPI_OBJECT_POWER_RESOURCE,
|
ACPI_OBJECT_POWER_RESOURCE,
|
||||||
@@ -17,6 +17,9 @@ enum acpi_object_type {
|
|||||||
ACPI_OBJECT_FIELD,
|
ACPI_OBJECT_FIELD,
|
||||||
ACPI_OBJECT_PACKAGE,
|
ACPI_OBJECT_PACKAGE,
|
||||||
ACPI_OBJECT_BUFFER,
|
ACPI_OBJECT_BUFFER,
|
||||||
|
ACPI_OBJECT_ALIAS,
|
||||||
|
ACPI_OBJECT_MUTEX,
|
||||||
|
ACPI_OBJECT_EVENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct acpi_object {
|
struct acpi_object {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "../table.h"
|
||||||
|
|
||||||
#define BYTECODE(opcode, parser, name) \
|
#define BYTECODE(opcode, parser, name) \
|
||||||
{ opcode, 0, parser, name }
|
{ opcode, 0, parser, name }
|
||||||
@@ -150,7 +151,11 @@ static enum parse_status read_name(struct aml_parser *parser, char **out)
|
|||||||
c = '\\';
|
c = '\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isalnum(c) && c != '_' && c != '\\') {
|
if (c == AML_PARENT_PREFIX_CHAR) {
|
||||||
|
c = '^';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isalnum(c) && c != '_' && c != '\\' && c != '^') {
|
||||||
return PARSE_BADSTRING;
|
return PARSE_BADSTRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +312,7 @@ static enum parse_status parse_string_prefix(struct aml_parser *parser, struct a
|
|||||||
buf[i] = c;
|
buf[i] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[len - 1] = '\0';
|
buf[len] = '\0';
|
||||||
|
|
||||||
out->type = AML_VALUE_STRING;
|
out->type = AML_VALUE_STRING;
|
||||||
out->value.str = buf;
|
out->value.str = buf;
|
||||||
@@ -372,7 +377,11 @@ static enum parse_status parse_op_region(struct aml_parser *parser, struct aml_v
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aml_value_is_integer(®ion_offset)) {
|
if (aml_value_is_name(®ion_offset)) {
|
||||||
|
/* TODO */
|
||||||
|
} else if (aml_value_is_integer(®ion_offset)) {
|
||||||
|
/* TODO */
|
||||||
|
} else {
|
||||||
free(name);
|
free(name);
|
||||||
return PARSE_BADTYPE;
|
return PARSE_BADTYPE;
|
||||||
}
|
}
|
||||||
@@ -384,12 +393,16 @@ static enum parse_status parse_op_region(struct aml_parser *parser, struct aml_v
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aml_value_is_integer(®ion_len)) {
|
if (aml_value_is_name(®ion_len)) {
|
||||||
|
/* TODO */
|
||||||
|
} else if (aml_value_is_integer(®ion_len)) {
|
||||||
|
/* TODO */
|
||||||
|
} else {
|
||||||
free(name);
|
free(name);
|
||||||
return PARSE_BADTYPE;
|
return PARSE_BADTYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct acpi_object *op_region = acpi_object_create(name, ACPI_OBJECT_OPERATION_REGION);
|
struct acpi_object *op_region = acpi_object_create(NULL, ACPI_OBJECT_OPERATION_REGION);
|
||||||
op_region->publish_path = name;
|
op_region->publish_path = name;
|
||||||
|
|
||||||
out->type = AML_VALUE_OBJECT;
|
out->type = AML_VALUE_OBJECT;
|
||||||
@@ -398,12 +411,109 @@ static enum parse_status parse_op_region(struct aml_parser *parser, struct aml_v
|
|||||||
return PARSE_OK;
|
return PARSE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_named_field(struct aml_parser *parser, struct acpi_object *region)
|
||||||
|
{
|
||||||
|
char unit_name[ACPI_OBJECT_NAME_MAX];
|
||||||
|
enum parse_status status = read_single_segment_name(parser, unit_name);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bits = read_pkg_length(parser);
|
||||||
|
if (bits < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *field = acpi_object_create(unit_name, ACPI_OBJECT_FIELD);
|
||||||
|
//field_unit->field_unit.size = bits / 8;
|
||||||
|
|
||||||
|
acpi_object_add_child(region, field);
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_reserved_field(struct aml_parser *parser, struct acpi_object *region)
|
||||||
|
{
|
||||||
|
int c = aml_parser_advance(parser);
|
||||||
|
if (c < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bits = read_pkg_length(parser);
|
||||||
|
if (bits < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *field = acpi_object_create(NULL, ACPI_OBJECT_FIELD);
|
||||||
|
//field_unit->field_unit.size = bits / 8;
|
||||||
|
|
||||||
|
acpi_object_add_child(region, field);
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_access_field(struct aml_parser *parser, struct acpi_object *region)
|
||||||
|
{
|
||||||
|
int c = aml_parser_advance(parser);
|
||||||
|
if (c < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int access_type = aml_parser_advance(parser);
|
||||||
|
if (access_type < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int access_attrib = aml_parser_advance(parser);
|
||||||
|
if (access_attrib < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *field = acpi_object_create(NULL, ACPI_OBJECT_FIELD);
|
||||||
|
//field_unit->field_unit.size = bits / 8;
|
||||||
|
|
||||||
|
acpi_object_add_child(region, field);
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_extended_access_field(struct aml_parser *parser, struct acpi_object *region)
|
||||||
|
{
|
||||||
|
int c = aml_parser_advance(parser);
|
||||||
|
if (c < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int access_type = aml_parser_advance(parser);
|
||||||
|
if (access_type < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ext_access_attrib = aml_parser_advance(parser);
|
||||||
|
if (ext_access_attrib < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int access_length = aml_parser_advance(parser);
|
||||||
|
if (access_length < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *field = acpi_object_create(NULL, ACPI_OBJECT_FIELD);
|
||||||
|
//field_unit->field_unit.size = bits / 8;
|
||||||
|
|
||||||
|
acpi_object_add_child(region, field);
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_connect_field(struct aml_parser *parser, struct acpi_object *region)
|
||||||
|
{
|
||||||
|
return PARSE_UNKNOWNOP;
|
||||||
|
}
|
||||||
|
|
||||||
static enum parse_status parse_field(struct aml_parser *parser, struct aml_value *out)
|
static enum parse_status parse_field(struct aml_parser *parser, struct aml_value *out)
|
||||||
{
|
{
|
||||||
long start = aml_parser_cursorpos(parser);
|
aml_parser_advance(parser);
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
aml_parser_advance(parser);
|
long start = aml_parser_cursorpos(parser);
|
||||||
aml_parser_advance(parser);
|
|
||||||
|
|
||||||
long len = read_pkg_length(parser);
|
long len = read_pkg_length(parser);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
@@ -423,29 +533,111 @@ static enum parse_status parse_field(struct aml_parser *parser, struct aml_value
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct acpi_object *region = aml_parser_resolve_path(parser, name);
|
struct acpi_object *region = aml_parser_resolve_path(parser, name);
|
||||||
free(name);
|
|
||||||
|
|
||||||
if (!region) {
|
if (!region) {
|
||||||
return PARSE_BADREF;
|
return PARSE_BADREF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
|
||||||
long end = start + len;
|
long end = start + len;
|
||||||
while (aml_parser_cursorpos(parser) < end) {
|
while (aml_parser_cursorpos(parser) < end) {
|
||||||
char unit_name[ACPI_OBJECT_NAME_MAX];
|
int c = aml_parser_peek(parser);
|
||||||
status = read_single_segment_name(parser, unit_name);
|
if (isalpha(c)) {
|
||||||
|
/* Named field */
|
||||||
|
status = parse_named_field(parser, region);
|
||||||
|
} else if (c == 0x00) {
|
||||||
|
/* Reserved field */
|
||||||
|
status = parse_reserved_field(parser, region);
|
||||||
|
} else if (c == 0x01) {
|
||||||
|
/* Access field */
|
||||||
|
status = parse_access_field(parser, region);
|
||||||
|
} else if (c == 0x03) {
|
||||||
|
/* Extended access field */
|
||||||
|
status = parse_extended_access_field(parser, region);
|
||||||
|
} else if (c == 0x02) {
|
||||||
|
/* Connect field */
|
||||||
|
status = parse_connect_field(parser, region);
|
||||||
|
} else if (c < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
} else {
|
||||||
|
return PARSE_UNKNOWNOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
out->type = AML_VALUE_NONE;
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_index_field(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
long start = aml_parser_cursorpos(parser);
|
||||||
|
|
||||||
|
long len = read_pkg_length(parser);
|
||||||
|
if (len < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *index_name;
|
||||||
|
enum parse_status status = read_name(parser, &index_name);
|
||||||
if (status != PARSE_OK) {
|
if (status != PARSE_OK) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bits = read_pkg_length(parser);
|
char *data_name;
|
||||||
if (bits < 0) {
|
status = read_name(parser, &data_name);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
free(index_name);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flags = aml_parser_advance(parser);
|
||||||
|
if (flags < 0) {
|
||||||
|
free(index_name);
|
||||||
|
free(data_name);
|
||||||
return PARSE_EOF;
|
return PARSE_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct acpi_object *field = acpi_object_create(unit_name, ACPI_OBJECT_FIELD);
|
free(index_name);
|
||||||
//field_unit->field_unit.size = bits / 8;
|
free(data_name);
|
||||||
|
|
||||||
acpi_object_add_child(region, field);
|
#if 0
|
||||||
|
struct acpi_object *region = aml_parser_resolve_path(parser, index_name);
|
||||||
|
|
||||||
|
if (!region) {
|
||||||
|
return PARSE_BADREF;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
long end = start + len;
|
||||||
|
while (aml_parser_cursorpos(parser) < end) {
|
||||||
|
int c = aml_parser_advance(parser);
|
||||||
|
#if 0
|
||||||
|
if (isalpha(c)) {
|
||||||
|
/* Named field */
|
||||||
|
status = parse_named_field(parser, region);
|
||||||
|
} else if (c == 0x00) {
|
||||||
|
/* Reserved field */
|
||||||
|
status = parse_reserved_field(parser, region);
|
||||||
|
} else if (c == 0x01) {
|
||||||
|
/* Access field */
|
||||||
|
status = parse_access_field(parser, region);
|
||||||
|
} else if (c == 0x03) {
|
||||||
|
/* Extended access field */
|
||||||
|
status = parse_extended_access_field(parser, region);
|
||||||
|
} else if (c == 0x02) {
|
||||||
|
/* Connect field */
|
||||||
|
status = parse_connect_field(parser, region);
|
||||||
|
} else if (c < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
} else {
|
||||||
|
return PARSE_UNKNOWNOP;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
out->type = AML_VALUE_NONE;
|
out->type = AML_VALUE_NONE;
|
||||||
@@ -517,6 +709,7 @@ static enum parse_status parse_package(struct aml_parser *parser, struct aml_val
|
|||||||
{
|
{
|
||||||
aml_parser_advance(parser);
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
long start = aml_parser_cursorpos(parser);
|
||||||
long len = read_pkg_length(parser);
|
long len = read_pkg_length(parser);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
return PARSE_EOF;
|
return PARSE_EOF;
|
||||||
@@ -539,6 +732,10 @@ static enum parse_status parse_package(struct aml_parser *parser, struct aml_val
|
|||||||
// TODO add value to package
|
// TODO add value to package
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (aml_parser_cursorpos(parser) < start + len) {
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
}
|
||||||
|
|
||||||
out->type = AML_VALUE_OBJECT;
|
out->type = AML_VALUE_OBJECT;
|
||||||
out->value.object = pkg;
|
out->value.object = pkg;
|
||||||
|
|
||||||
@@ -561,6 +758,7 @@ static enum parse_status parse_name_chars(struct aml_parser *parser, struct aml_
|
|||||||
static enum parse_status parse_buffer(struct aml_parser *parser, struct aml_value *out)
|
static enum parse_status parse_buffer(struct aml_parser *parser, struct aml_value *out)
|
||||||
{
|
{
|
||||||
aml_parser_advance(parser);
|
aml_parser_advance(parser);
|
||||||
|
long start = aml_parser_cursorpos(parser);
|
||||||
long pkg_len = read_pkg_length(parser);
|
long pkg_len = read_pkg_length(parser);
|
||||||
if (pkg_len < 0) {
|
if (pkg_len < 0) {
|
||||||
return PARSE_EOF;
|
return PARSE_EOF;
|
||||||
@@ -577,8 +775,10 @@ static enum parse_status parse_buffer(struct aml_parser *parser, struct aml_valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t nbytes = aml_value_get_integer(&buffer_size);
|
uint64_t nbytes = aml_value_get_integer(&buffer_size);
|
||||||
|
long end = start + pkg_len;
|
||||||
|
|
||||||
for (uint64_t i = 0; i < nbytes; i++) {
|
while (aml_parser_cursorpos(parser) < end) {
|
||||||
|
//for (uint64_t i = 0; i < nbytes; i++) {
|
||||||
int b = aml_parser_advance(parser);
|
int b = aml_parser_advance(parser);
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
return PARSE_EOF;
|
return PARSE_EOF;
|
||||||
@@ -631,10 +831,212 @@ static enum parse_status parse_method(struct aml_parser *parser, struct aml_valu
|
|||||||
return PARSE_OK;
|
return PARSE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_ones(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
if (parser->revision == 0x02) {
|
||||||
|
out->type = AML_VALUE_UINT64;
|
||||||
|
out->value.uint64 = 0xFFFFFFFFFFFFFFFF;
|
||||||
|
} else {
|
||||||
|
out->type = AML_VALUE_UINT32;
|
||||||
|
out->value.uint32 = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_processor(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
long start = aml_parser_cursorpos(parser);
|
||||||
|
|
||||||
|
long pkg_len = read_pkg_length(parser);
|
||||||
|
if (pkg_len < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
enum parse_status status = read_name(parser, &name);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int proc_id = aml_parser_advance(parser);
|
||||||
|
if (proc_id < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int a = aml_parser_advance(parser);
|
||||||
|
int b = aml_parser_advance(parser);
|
||||||
|
int c = aml_parser_advance(parser);
|
||||||
|
int d = aml_parser_advance(parser);
|
||||||
|
|
||||||
|
if (d < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pblk_len = aml_parser_advance(parser);
|
||||||
|
if (pblk_len < 0) {
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *processor = acpi_object_create(NULL, ACPI_OBJECT_PROCESSOR);
|
||||||
|
processor->publish_path = name;
|
||||||
|
processor->scope_end = start + pkg_len;
|
||||||
|
|
||||||
|
out->type = AML_VALUE_OBJECT;
|
||||||
|
out->value.object = processor;
|
||||||
|
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_alias(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
char *target_path, *alias_path;
|
||||||
|
enum parse_status status = read_name(parser, &target_path);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = read_name(parser, &alias_path);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *alias = acpi_object_create(NULL, ACPI_OBJECT_ALIAS);
|
||||||
|
alias->publish_path = alias_path;
|
||||||
|
free(target_path);
|
||||||
|
|
||||||
|
out->type = AML_VALUE_OBJECT;
|
||||||
|
out->value.object = alias;
|
||||||
|
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_mutex(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
enum parse_status status = read_name(parser, &name);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sync_flags = aml_parser_advance(parser);
|
||||||
|
if (sync_flags < 0) {
|
||||||
|
free(name);
|
||||||
|
return PARSE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *mutex = acpi_object_create(NULL, ACPI_OBJECT_MUTEX);
|
||||||
|
mutex->publish_path = name;
|
||||||
|
|
||||||
|
out->type = AML_VALUE_OBJECT;
|
||||||
|
out->value.object = mutex;
|
||||||
|
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_create_byte_field(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
char *buffer_path;
|
||||||
|
enum parse_status status = read_name(parser, &buffer_path);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct aml_value byte_index;
|
||||||
|
status = parse_opcode(parser, &byte_index);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *field_name;
|
||||||
|
status = read_name(parser, &field_name);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *field = acpi_object_create(NULL, ACPI_OBJECT_FIELD);
|
||||||
|
field->publish_path = field_name;
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
free(buffer_path);
|
||||||
|
|
||||||
|
out->type = AML_VALUE_OBJECT;
|
||||||
|
out->value.object = field;
|
||||||
|
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_create_word_field(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
char *buffer_path;
|
||||||
|
enum parse_status status = read_name(parser, &buffer_path);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct aml_value byte_index;
|
||||||
|
status = parse_opcode(parser, &byte_index);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *field_name;
|
||||||
|
status = read_name(parser, &field_name);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *field = acpi_object_create(NULL, ACPI_OBJECT_FIELD);
|
||||||
|
field->publish_path = field_name;
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
free(buffer_path);
|
||||||
|
|
||||||
|
out->type = AML_VALUE_OBJECT;
|
||||||
|
out->value.object = field;
|
||||||
|
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum parse_status parse_event(struct aml_parser *parser, struct aml_value *out)
|
||||||
|
{
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
aml_parser_advance(parser);
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
enum parse_status status = read_name(parser, &name);
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_object *event = acpi_object_create(NULL, ACPI_OBJECT_EVENT);
|
||||||
|
event->publish_path = name;
|
||||||
|
|
||||||
|
out->type = AML_VALUE_OBJECT;
|
||||||
|
out->value.object = event;
|
||||||
|
|
||||||
|
return PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
struct aml_byte_encoding byte_encoding[] = {
|
struct aml_byte_encoding byte_encoding[] = {
|
||||||
BYTECODE(AML_ZERO_OP, parse_zero, "ZeroOp"),
|
BYTECODE(AML_ZERO_OP, parse_zero, "ZeroOp"),
|
||||||
BYTECODE(AML_ONE_OP, parse_one, "OneOp"),
|
BYTECODE(AML_ONE_OP, parse_one, "OneOp"),
|
||||||
BYTECODE(AML_ALIAS_OP, NULL, "AliasOp"),
|
BYTECODE(AML_ALIAS_OP, parse_alias, "AliasOp"),
|
||||||
BYTECODE(AML_NAME_OP, parse_name, "NameOp"),
|
BYTECODE(AML_NAME_OP, parse_name, "NameOp"),
|
||||||
BYTECODE(AML_BYTE_PREFIX, parse_byte_prefix, "BytePrefix"),
|
BYTECODE(AML_BYTE_PREFIX, parse_byte_prefix, "BytePrefix"),
|
||||||
BYTECODE(AML_WORD_PREFIX, parse_word_prefix, "WordPrefix"),
|
BYTECODE(AML_WORD_PREFIX, parse_word_prefix, "WordPrefix"),
|
||||||
@@ -684,8 +1086,8 @@ struct aml_byte_encoding byte_encoding[] = {
|
|||||||
BYTECODE('X', parse_name_chars, "NameChar"),
|
BYTECODE('X', parse_name_chars, "NameChar"),
|
||||||
BYTECODE('Y', parse_name_chars, "NameChar"),
|
BYTECODE('Y', parse_name_chars, "NameChar"),
|
||||||
BYTECODE('Z', parse_name_chars, "NameChar"),
|
BYTECODE('Z', parse_name_chars, "NameChar"),
|
||||||
EXT_BYTECODE(AML_EXT_MUTEX_OP, NULL, "MutexOp"),
|
EXT_BYTECODE(AML_EXT_MUTEX_OP, parse_mutex, "MutexOp"),
|
||||||
EXT_BYTECODE(AML_EXT_EVENT_OP, NULL, "EventOp"),
|
EXT_BYTECODE(AML_EXT_EVENT_OP, parse_event, "EventOp"),
|
||||||
EXT_BYTECODE(AML_EXT_COND_REF_OF_OP, NULL, "CondRefOfOp"),
|
EXT_BYTECODE(AML_EXT_COND_REF_OF_OP, NULL, "CondRefOfOp"),
|
||||||
EXT_BYTECODE(AML_EXT_CREATE_FIELD_OP, NULL, "CreateFieldOp"),
|
EXT_BYTECODE(AML_EXT_CREATE_FIELD_OP, NULL, "CreateFieldOp"),
|
||||||
EXT_BYTECODE(AML_EXT_LOAD_TABLE_OP, NULL, "LoadTableOp"),
|
EXT_BYTECODE(AML_EXT_LOAD_TABLE_OP, NULL, "LoadTableOp"),
|
||||||
@@ -707,10 +1109,10 @@ struct aml_byte_encoding byte_encoding[] = {
|
|||||||
EXT_BYTECODE(AML_EXT_REGION_OP, parse_op_region, "OpRegionOp"),
|
EXT_BYTECODE(AML_EXT_REGION_OP, parse_op_region, "OpRegionOp"),
|
||||||
EXT_BYTECODE(AML_EXT_FIELD_OP, parse_field, "FieldOp"),
|
EXT_BYTECODE(AML_EXT_FIELD_OP, parse_field, "FieldOp"),
|
||||||
EXT_BYTECODE(AML_EXT_DEVICE_OP, parse_device, "DeviceOp"),
|
EXT_BYTECODE(AML_EXT_DEVICE_OP, parse_device, "DeviceOp"),
|
||||||
EXT_BYTECODE(AML_EXT_PROCESSOR_OP, NULL, "ProcessorOp"),
|
EXT_BYTECODE(AML_EXT_PROCESSOR_OP, parse_processor, "ProcessorOp"),
|
||||||
EXT_BYTECODE(AML_EXT_POWER_RES_OP, NULL, "PowerResOp"),
|
EXT_BYTECODE(AML_EXT_POWER_RES_OP, NULL, "PowerResOp"),
|
||||||
EXT_BYTECODE(AML_EXT_THERMAL_ZONE_OP, NULL, "ThermalZoneOp"),
|
EXT_BYTECODE(AML_EXT_THERMAL_ZONE_OP, NULL, "ThermalZoneOp"),
|
||||||
EXT_BYTECODE(AML_EXT_INDEX_FIELD_OP, NULL, "IndexFieldOp"),
|
EXT_BYTECODE(AML_EXT_INDEX_FIELD_OP, parse_index_field, "IndexFieldOp"),
|
||||||
EXT_BYTECODE(AML_EXT_BANK_FIELD_OP, NULL, "BankFieldOp"),
|
EXT_BYTECODE(AML_EXT_BANK_FIELD_OP, NULL, "BankFieldOp"),
|
||||||
EXT_BYTECODE(AML_EXT_DATA_REGION_OP, NULL, "DataRegionOp"),
|
EXT_BYTECODE(AML_EXT_DATA_REGION_OP, NULL, "DataRegionOp"),
|
||||||
BYTECODE(AML_ROOT_CHAR, NULL, "RootChar"),
|
BYTECODE(AML_ROOT_CHAR, NULL, "RootChar"),
|
||||||
@@ -758,8 +1160,8 @@ struct aml_byte_encoding byte_encoding[] = {
|
|||||||
BYTECODE(AML_INDEX_OP, NULL, "IndexOp"),
|
BYTECODE(AML_INDEX_OP, NULL, "IndexOp"),
|
||||||
BYTECODE(AML_MATCH_OP, NULL, "MatchOp"),
|
BYTECODE(AML_MATCH_OP, NULL, "MatchOp"),
|
||||||
BYTECODE(AML_CREATE_DWORD_FIELD_OP, NULL, "CreateDWordFieldOp"),
|
BYTECODE(AML_CREATE_DWORD_FIELD_OP, NULL, "CreateDWordFieldOp"),
|
||||||
BYTECODE(AML_CREATE_WORD_FIELD_OP, NULL, "CreateWordFieldOp"),
|
BYTECODE(AML_CREATE_WORD_FIELD_OP, parse_create_word_field, "CreateWordFieldOp"),
|
||||||
BYTECODE(AML_CREATE_BYTE_FIELD_OP, NULL, "CreateByteFieldOp"),
|
BYTECODE(AML_CREATE_BYTE_FIELD_OP, parse_create_byte_field, "CreateByteFieldOp"),
|
||||||
BYTECODE(AML_CREATE_BIT_FIELD_OP, NULL, "CreateBitFieldOp"),
|
BYTECODE(AML_CREATE_BIT_FIELD_OP, NULL, "CreateBitFieldOp"),
|
||||||
BYTECODE(AML_OBJECT_TYPE_OP, NULL, "ObjectTypeOp"),
|
BYTECODE(AML_OBJECT_TYPE_OP, NULL, "ObjectTypeOp"),
|
||||||
BYTECODE(AML_CREATE_QWORD_FIELD_OP, NULL, "CreateQWordFieldOp"),
|
BYTECODE(AML_CREATE_QWORD_FIELD_OP, NULL, "CreateQWordFieldOp"),
|
||||||
@@ -784,7 +1186,7 @@ struct aml_byte_encoding byte_encoding[] = {
|
|||||||
BYTECODE(AML_RETURN_OP, NULL, "ReturnOp"),
|
BYTECODE(AML_RETURN_OP, NULL, "ReturnOp"),
|
||||||
BYTECODE(AML_BREAK_OP, NULL, "BreakOp"),
|
BYTECODE(AML_BREAK_OP, NULL, "BreakOp"),
|
||||||
BYTECODE(AML_BREAK_POINT_OP, NULL, "BreakPointOp"),
|
BYTECODE(AML_BREAK_POINT_OP, NULL, "BreakPointOp"),
|
||||||
BYTECODE(AML_ONES_OP, NULL, "OnesOp"),
|
BYTECODE(AML_ONES_OP, parse_ones, "OnesOp"),
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int nr_byte_encoding = sizeof byte_encoding / sizeof(struct aml_byte_encoding);
|
static unsigned int nr_byte_encoding = sizeof byte_encoding / sizeof(struct aml_byte_encoding);
|
||||||
@@ -815,12 +1217,12 @@ enum parse_status parse_opcode(struct aml_parser *parser, struct aml_value *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!opcode) {
|
if (!opcode) {
|
||||||
fprintf(stderr, "unrecognised opcode at 0x%04x: %02x:%02x\n", offset, op0, op1);
|
fprintf(stderr, "unrecognised opcode at 0x%04lx: %02x:%02x\n", offset + sizeof(struct acpi_table), op0, op1);
|
||||||
return PARSE_UNKNOWNOP;
|
return PARSE_UNKNOWNOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opcode->parser) {
|
if (!opcode->parser) {
|
||||||
fprintf(stderr, "unimplemented opcode at 0x%04x: %02x:%02x (%s)\n", offset, op0, op1, opcode->name);
|
fprintf(stderr, "unimplemented opcode at 0x%04lx: %02x:%02x (%s)\n", offset + sizeof(struct acpi_table), op0, op1, opcode->name);
|
||||||
return PARSE_UNKNOWNOP;
|
return PARSE_UNKNOWNOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "opcode.h"
|
#include "opcode.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
#include "../table.h"
|
||||||
|
|
||||||
void aml_parser_init(struct aml_parser *parser, void *p, size_t len)
|
void aml_parser_init(struct aml_parser *parser, void *p, size_t len)
|
||||||
{
|
{
|
||||||
@@ -116,6 +117,7 @@ void aml_parser_add_object(struct aml_parser *parser, struct acpi_object *object
|
|||||||
}
|
}
|
||||||
|
|
||||||
tok = next_tok;
|
tok = next_tok;
|
||||||
|
cur = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(object->name, tok, sizeof object->name - 1);
|
strncpy(object->name, tok, sizeof object->name - 1);
|
||||||
@@ -192,12 +194,14 @@ static bool should_pop_current_scope(struct aml_parser *parser)
|
|||||||
enum parse_status aml_parser_parse_into_namespace(struct aml_parser *parser, struct acpi_namespace *ns)
|
enum parse_status aml_parser_parse_into_namespace(struct aml_parser *parser, struct acpi_namespace *ns)
|
||||||
{
|
{
|
||||||
parser->ns = ns;
|
parser->ns = ns;
|
||||||
|
aml_parser_push_scope(parser, ns->root);
|
||||||
|
enum parse_status status = PARSE_OK;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct aml_value value;
|
struct aml_value value;
|
||||||
enum parse_status status = parse_opcode(parser, &value);
|
status = parse_opcode(parser, &value);
|
||||||
if (status != PARSE_OK) {
|
if (status != PARSE_OK) {
|
||||||
return status;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.type == AML_VALUE_OBJECT) {
|
if (value.type == AML_VALUE_OBJECT) {
|
||||||
@@ -210,7 +214,16 @@ enum parse_status aml_parser_parse_into_namespace(struct aml_parser *parser, str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return PARSE_OK;
|
if (status == PARSE_EOF && !parser->cur_scope->next) {
|
||||||
|
status = PARSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != PARSE_OK) {
|
||||||
|
fprintf(stderr, "parse error at 0x%04lx: %s\n",
|
||||||
|
aml_parser_cursorpos(parser) + sizeof(struct acpi_table), parse_status_string(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct acpi_object *aml_parser_resolve_path(struct aml_parser *parser, const char *path)
|
struct acpi_object *aml_parser_resolve_path(struct aml_parser *parser, const char *path)
|
||||||
@@ -223,10 +236,16 @@ struct acpi_object *aml_parser_resolve_path(struct aml_parser *parser, const cha
|
|||||||
|
|
||||||
size_t path_len = strlen(path);
|
size_t path_len = strlen(path);
|
||||||
char *rpath = malloc(path_len + 1);
|
char *rpath = malloc(path_len + 1);
|
||||||
|
char *token_buf = rpath;
|
||||||
strcpy(rpath, path);
|
strcpy(rpath, path);
|
||||||
|
|
||||||
|
while (*token_buf == '^') {
|
||||||
|
cur = cur->parent;
|
||||||
|
token_buf++;
|
||||||
|
}
|
||||||
|
|
||||||
char *sp;
|
char *sp;
|
||||||
char *tok = strtok_r(rpath, ".", &sp);
|
char *tok = strtok_r(token_buf, ".", &sp);
|
||||||
if (tok && object_name_is_always_root(tok)) {
|
if (tok && object_name_is_always_root(tok)) {
|
||||||
cur = parser->ns->root;
|
cur = parser->ns->root;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ static inline bool aml_value_is_integer(const struct aml_value *value)
|
|||||||
{
|
{
|
||||||
return value->type == AML_VALUE_UINT8 || value->type == AML_VALUE_UINT16 || value->type == AML_VALUE_UINT32 || value->type == AML_VALUE_UINT64;
|
return value->type == AML_VALUE_UINT8 || value->type == AML_VALUE_UINT16 || value->type == AML_VALUE_UINT32 || value->type == AML_VALUE_UINT64;
|
||||||
}
|
}
|
||||||
|
static inline bool aml_value_is_name(const struct aml_value *value)
|
||||||
|
{
|
||||||
|
return value->type == AML_VALUE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
extern uint64_t aml_value_get_integer(const struct aml_value *value);
|
extern uint64_t aml_value_get_integer(const struct aml_value *value);
|
||||||
extern void aml_value_destroy(struct aml_value *value);
|
extern void aml_value_destroy(struct aml_value *value);
|
||||||
|
|||||||
Reference in New Issue
Block a user