tools: amldecode: add parsing support for more AML opcodes

This commit is contained in:
2023-07-22 17:57:20 +01:00
parent d08612f7db
commit d66f0df2c2
5 changed files with 613 additions and 183 deletions

View File

@@ -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>";
} }

View File

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

View File

@@ -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(&region_offset)) { if (aml_value_is_name(&region_offset)) {
/* TODO */
} else if (aml_value_is_integer(&region_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(&region_len)) { if (aml_value_is_name(&region_len)) {
/* TODO */
} else if (aml_value_is_integer(&region_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)) {
if (status != PARSE_OK) { /* Named field */
return status; status = parse_named_field(parser, region);
} } else if (c == 0x00) {
/* Reserved field */
int bits = read_pkg_length(parser); status = parse_reserved_field(parser, region);
if (bits < 0) { } 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; return PARSE_EOF;
} else {
return PARSE_UNKNOWNOP;
} }
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); 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) {
return status;
}
char *data_name;
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;
}
free(index_name);
free(data_name);
#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,160 +831,362 @@ 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"),
BYTECODE(AML_DWORD_PREFIX, parse_dword_prefix, "DWordPrefix"), BYTECODE(AML_DWORD_PREFIX, parse_dword_prefix, "DWordPrefix"),
BYTECODE(AML_STRING_PREFIX, parse_string_prefix, "StringPrefix"), BYTECODE(AML_STRING_PREFIX, parse_string_prefix, "StringPrefix"),
BYTECODE(AML_QWORD_PREFIX, parse_qword_prefix, "QWordPrefix"), BYTECODE(AML_QWORD_PREFIX, parse_qword_prefix, "QWordPrefix"),
BYTECODE(AML_SCOPE_OP, parse_scope, "ScopeOp"), BYTECODE(AML_SCOPE_OP, parse_scope, "ScopeOp"),
BYTECODE(AML_BUFFER_OP, parse_buffer, "BufferOp"), BYTECODE(AML_BUFFER_OP, parse_buffer, "BufferOp"),
BYTECODE(AML_PACKAGE_OP, parse_package, "PackageOp"), BYTECODE(AML_PACKAGE_OP, parse_package, "PackageOp"),
BYTECODE(AML_VAR_PACKAGE_OP, NULL, "VarPackageOp"), BYTECODE(AML_VAR_PACKAGE_OP, NULL, "VarPackageOp"),
BYTECODE(AML_METHOD_OP, parse_method, "MethodOp"), BYTECODE(AML_METHOD_OP, parse_method, "MethodOp"),
BYTECODE(AML_DUAL_NAME_PREFIX, NULL, "DualNamePrefix"), BYTECODE(AML_DUAL_NAME_PREFIX, NULL, "DualNamePrefix"),
BYTECODE(AML_MULTI_NAME_PREFIX, NULL, "MultiNamePrefix"), BYTECODE(AML_MULTI_NAME_PREFIX, NULL, "MultiNamePrefix"),
BYTECODE('0', parse_name_chars, "DigitChar"), BYTECODE('0', parse_name_chars, "DigitChar"),
BYTECODE('1', parse_name_chars, "DigitChar"), BYTECODE('1', parse_name_chars, "DigitChar"),
BYTECODE('2', parse_name_chars, "DigitChar"), BYTECODE('2', parse_name_chars, "DigitChar"),
BYTECODE('3', parse_name_chars, "DigitChar"), BYTECODE('3', parse_name_chars, "DigitChar"),
BYTECODE('4', parse_name_chars, "DigitChar"), BYTECODE('4', parse_name_chars, "DigitChar"),
BYTECODE('5', parse_name_chars, "DigitChar"), BYTECODE('5', parse_name_chars, "DigitChar"),
BYTECODE('6', parse_name_chars, "DigitChar"), BYTECODE('6', parse_name_chars, "DigitChar"),
BYTECODE('7', parse_name_chars, "DigitChar"), BYTECODE('7', parse_name_chars, "DigitChar"),
BYTECODE('8', parse_name_chars, "DigitChar"), BYTECODE('8', parse_name_chars, "DigitChar"),
BYTECODE('9', parse_name_chars, "DigitChar"), BYTECODE('9', parse_name_chars, "DigitChar"),
BYTECODE('A', parse_name_chars, "NameChar"), BYTECODE('A', parse_name_chars, "NameChar"),
BYTECODE('B', parse_name_chars, "NameChar"), BYTECODE('B', parse_name_chars, "NameChar"),
BYTECODE('C', parse_name_chars, "NameChar"), BYTECODE('C', parse_name_chars, "NameChar"),
BYTECODE('D', parse_name_chars, "NameChar"), BYTECODE('D', parse_name_chars, "NameChar"),
BYTECODE('E', parse_name_chars, "NameChar"), BYTECODE('E', parse_name_chars, "NameChar"),
BYTECODE('F', parse_name_chars, "NameChar"), BYTECODE('F', parse_name_chars, "NameChar"),
BYTECODE('G', parse_name_chars, "NameChar"), BYTECODE('G', parse_name_chars, "NameChar"),
BYTECODE('H', parse_name_chars, "NameChar"), BYTECODE('H', parse_name_chars, "NameChar"),
BYTECODE('I', parse_name_chars, "NameChar"), BYTECODE('I', parse_name_chars, "NameChar"),
BYTECODE('J', parse_name_chars, "NameChar"), BYTECODE('J', parse_name_chars, "NameChar"),
BYTECODE('K', parse_name_chars, "NameChar"), BYTECODE('K', parse_name_chars, "NameChar"),
BYTECODE('L', parse_name_chars, "NameChar"), BYTECODE('L', parse_name_chars, "NameChar"),
BYTECODE('M', parse_name_chars, "NameChar"), BYTECODE('M', parse_name_chars, "NameChar"),
BYTECODE('N', parse_name_chars, "NameChar"), BYTECODE('N', parse_name_chars, "NameChar"),
BYTECODE('O', parse_name_chars, "NameChar"), BYTECODE('O', parse_name_chars, "NameChar"),
BYTECODE('P', parse_name_chars, "NameChar"), BYTECODE('P', parse_name_chars, "NameChar"),
BYTECODE('Q', parse_name_chars, "NameChar"), BYTECODE('Q', parse_name_chars, "NameChar"),
BYTECODE('R', parse_name_chars, "NameChar"), BYTECODE('R', parse_name_chars, "NameChar"),
BYTECODE('S', parse_name_chars, "NameChar"), BYTECODE('S', parse_name_chars, "NameChar"),
BYTECODE('T', parse_name_chars, "NameChar"), BYTECODE('T', parse_name_chars, "NameChar"),
BYTECODE('U', parse_name_chars, "NameChar"), BYTECODE('U', parse_name_chars, "NameChar"),
BYTECODE('V', parse_name_chars, "NameChar"), BYTECODE('V', parse_name_chars, "NameChar"),
BYTECODE('W', parse_name_chars, "NameChar"), BYTECODE('W', parse_name_chars, "NameChar"),
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"),
EXT_BYTECODE(AML_EXT_LOAD_OP, NULL, "LoadOp"), EXT_BYTECODE(AML_EXT_LOAD_OP, NULL, "LoadOp"),
EXT_BYTECODE(AML_EXT_STALL_OP, NULL, "StallOp"), EXT_BYTECODE(AML_EXT_STALL_OP, NULL, "StallOp"),
EXT_BYTECODE(AML_EXT_SLEEP_OP, NULL, "SleepOp"), EXT_BYTECODE(AML_EXT_SLEEP_OP, NULL, "SleepOp"),
EXT_BYTECODE(AML_EXT_ACQUIRE_OP, NULL, "AcquireOp"), EXT_BYTECODE(AML_EXT_ACQUIRE_OP, NULL, "AcquireOp"),
EXT_BYTECODE(AML_EXT_SIGNAL_OP, NULL, "SignalOp"), EXT_BYTECODE(AML_EXT_SIGNAL_OP, NULL, "SignalOp"),
EXT_BYTECODE(AML_EXT_WAIT_OP, NULL, "WaitOp"), EXT_BYTECODE(AML_EXT_WAIT_OP, NULL, "WaitOp"),
EXT_BYTECODE(AML_EXT_RESET_OP, NULL, "ResetOp"), EXT_BYTECODE(AML_EXT_RESET_OP, NULL, "ResetOp"),
EXT_BYTECODE(AML_EXT_RELEASE_OP, NULL, "ReleaseOp"), EXT_BYTECODE(AML_EXT_RELEASE_OP, NULL, "ReleaseOp"),
EXT_BYTECODE(AML_EXT_FROM_BCD_OP, NULL, "FromBCDOp"), EXT_BYTECODE(AML_EXT_FROM_BCD_OP, NULL, "FromBCDOp"),
EXT_BYTECODE(AML_EXT_TO_BCD_OP, NULL, "ToBCDOp"), EXT_BYTECODE(AML_EXT_TO_BCD_OP, NULL, "ToBCDOp"),
EXT_BYTECODE(AML_EXT_UNLOAD_OP, NULL, "UnloadOp"), EXT_BYTECODE(AML_EXT_UNLOAD_OP, NULL, "UnloadOp"),
EXT_BYTECODE(AML_EXT_REVISION_OP, NULL, "RevisionOp"), EXT_BYTECODE(AML_EXT_REVISION_OP, NULL, "RevisionOp"),
EXT_BYTECODE(AML_EXT_DEBUG_OP, NULL, "DebugOp"), EXT_BYTECODE(AML_EXT_DEBUG_OP, NULL, "DebugOp"),
EXT_BYTECODE(AML_EXT_FATAL_OP, NULL, "FatalOp"), EXT_BYTECODE(AML_EXT_FATAL_OP, NULL, "FatalOp"),
EXT_BYTECODE(AML_EXT_TIMER_OP, NULL, "TimerOp"), EXT_BYTECODE(AML_EXT_TIMER_OP, NULL, "TimerOp"),
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"),
BYTECODE(AML_PARENT_PREFIX_CHAR, NULL, "ParentPrefixChar"), BYTECODE(AML_PARENT_PREFIX_CHAR, NULL, "ParentPrefixChar"),
BYTECODE('_', NULL, "NameChar"), BYTECODE('_', NULL, "NameChar"),
BYTECODE(AML_LOCAL0, NULL, "Local0Op"), BYTECODE(AML_LOCAL0, NULL, "Local0Op"),
BYTECODE(AML_LOCAL1, NULL, "Local1Op"), BYTECODE(AML_LOCAL1, NULL, "Local1Op"),
BYTECODE(AML_LOCAL2, NULL, "Local2Op"), BYTECODE(AML_LOCAL2, NULL, "Local2Op"),
BYTECODE(AML_LOCAL3, NULL, "Local3Op"), BYTECODE(AML_LOCAL3, NULL, "Local3Op"),
BYTECODE(AML_LOCAL4, NULL, "Local4Op"), BYTECODE(AML_LOCAL4, NULL, "Local4Op"),
BYTECODE(AML_LOCAL5, NULL, "Local5Op"), BYTECODE(AML_LOCAL5, NULL, "Local5Op"),
BYTECODE(AML_LOCAL6, NULL, "Local6Op"), BYTECODE(AML_LOCAL6, NULL, "Local6Op"),
BYTECODE(AML_LOCAL7, NULL, "Local7Op"), BYTECODE(AML_LOCAL7, NULL, "Local7Op"),
BYTECODE(AML_ARG0, NULL, "Arg0Op"), BYTECODE(AML_ARG0, NULL, "Arg0Op"),
BYTECODE(AML_ARG1, NULL, "Arg1Op"), BYTECODE(AML_ARG1, NULL, "Arg1Op"),
BYTECODE(AML_ARG2, NULL, "Arg2Op"), BYTECODE(AML_ARG2, NULL, "Arg2Op"),
BYTECODE(AML_ARG3, NULL, "Arg3Op"), BYTECODE(AML_ARG3, NULL, "Arg3Op"),
BYTECODE(AML_ARG4, NULL, "Arg4Op"), BYTECODE(AML_ARG4, NULL, "Arg4Op"),
BYTECODE(AML_ARG5, NULL, "Arg5Op"), BYTECODE(AML_ARG5, NULL, "Arg5Op"),
BYTECODE(AML_ARG6, NULL, "Arg6Op"), BYTECODE(AML_ARG6, NULL, "Arg6Op"),
BYTECODE(AML_STORE_OP, NULL, "StoreOp"), BYTECODE(AML_STORE_OP, NULL, "StoreOp"),
BYTECODE(AML_REF_OF_OP, NULL, "RefOfOp"), BYTECODE(AML_REF_OF_OP, NULL, "RefOfOp"),
BYTECODE(AML_ADD_OP, NULL, "AddOp"), BYTECODE(AML_ADD_OP, NULL, "AddOp"),
BYTECODE(AML_CONCAT_OP, NULL, "ConcatOp"), BYTECODE(AML_CONCAT_OP, NULL, "ConcatOp"),
BYTECODE(AML_SUBTRACT_OP, NULL, "SubtractOp"), BYTECODE(AML_SUBTRACT_OP, NULL, "SubtractOp"),
BYTECODE(AML_INCREMENT_OP, NULL, "IncrementOp"), BYTECODE(AML_INCREMENT_OP, NULL, "IncrementOp"),
BYTECODE(AML_DECREMENT_OP, NULL, "DecrementOp"), BYTECODE(AML_DECREMENT_OP, NULL, "DecrementOp"),
BYTECODE(AML_MULTIPLY_OP, NULL, "MultiplyOp"), BYTECODE(AML_MULTIPLY_OP, NULL, "MultiplyOp"),
BYTECODE(AML_DIVIDE_OP, NULL, "DivideOp"), BYTECODE(AML_DIVIDE_OP, NULL, "DivideOp"),
BYTECODE(AML_SHIFT_LEFT_OP, NULL, "ShiftLeftOp"), BYTECODE(AML_SHIFT_LEFT_OP, NULL, "ShiftLeftOp"),
BYTECODE(AML_SHIFT_RIGHT_OP, NULL, "ShiftRightOp"), BYTECODE(AML_SHIFT_RIGHT_OP, NULL, "ShiftRightOp"),
BYTECODE(AML_AND_OP, NULL, "AndOp"), BYTECODE(AML_AND_OP, NULL, "AndOp"),
BYTECODE(AML_NAND_OP, NULL, "NAndOp"), BYTECODE(AML_NAND_OP, NULL, "NAndOp"),
BYTECODE(AML_OR_OP, NULL, "OrOp"), BYTECODE(AML_OR_OP, NULL, "OrOp"),
BYTECODE(AML_NOR_OP, NULL, "NorOp"), BYTECODE(AML_NOR_OP, NULL, "NorOp"),
BYTECODE(AML_XOR_OP, NULL, "XOrOp"), BYTECODE(AML_XOR_OP, NULL, "XOrOp"),
BYTECODE(AML_NOT_OP, NULL, "NotOp"), BYTECODE(AML_NOT_OP, NULL, "NotOp"),
BYTECODE(AML_FIND_SET_LEFT_BIT_OP, NULL, "FindSetLeftBitOp"), BYTECODE(AML_FIND_SET_LEFT_BIT_OP, NULL, "FindSetLeftBitOp"),
BYTECODE(AML_FIND_SET_RIGHT_BIT_OP, NULL, "FindSetRightBitOp"), BYTECODE(AML_FIND_SET_RIGHT_BIT_OP, NULL, "FindSetRightBitOp"),
BYTECODE(AML_DEREF_OF_OP, NULL, "DerefOfOp"), BYTECODE(AML_DEREF_OF_OP, NULL, "DerefOfOp"),
BYTECODE(AML_CONCAT_RES_OP, NULL, "ConcatResOp"), BYTECODE(AML_CONCAT_RES_OP, NULL, "ConcatResOp"),
BYTECODE(AML_MOD_OP, NULL, "ModOp"), BYTECODE(AML_MOD_OP, NULL, "ModOp"),
BYTECODE(AML_NOTIFY_OP, NULL, "NotifyOp"), BYTECODE(AML_NOTIFY_OP, NULL, "NotifyOp"),
BYTECODE(AML_SIZE_OF_OP, NULL, "SizeOfOp"), BYTECODE(AML_SIZE_OF_OP, NULL, "SizeOfOp"),
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"),
BYTECODE(AML_LAND_OP, NULL, "LAndOp"), BYTECODE(AML_LAND_OP, NULL, "LAndOp"),
BYTECODE(AML_LOR_OP, NULL, "LOrOp"), BYTECODE(AML_LOR_OP, NULL, "LOrOp"),
BYTECODE(AML_LNOT_OP, NULL, "LNotOp"), BYTECODE(AML_LNOT_OP, NULL, "LNotOp"),
BYTECODE(AML_LEQUAL_OP, NULL, "LEqualOp"), BYTECODE(AML_LEQUAL_OP, NULL, "LEqualOp"),
BYTECODE(AML_LGREATER_OP, NULL, "LGreaterOp"), BYTECODE(AML_LGREATER_OP, NULL, "LGreaterOp"),
BYTECODE(AML_LLESS_OP, NULL, "LLessOp"), BYTECODE(AML_LLESS_OP, NULL, "LLessOp"),
BYTECODE(AML_TO_BUFFER_OP, NULL, "ToBufferOp"), BYTECODE(AML_TO_BUFFER_OP, NULL, "ToBufferOp"),
BYTECODE(AML_TO_DEC_STRING_OP, NULL, "ToDecimalStringOp"), BYTECODE(AML_TO_DEC_STRING_OP, NULL, "ToDecimalStringOp"),
BYTECODE(AML_TO_HEX_STRING_OP, NULL, "ToHexStringOp"), BYTECODE(AML_TO_HEX_STRING_OP, NULL, "ToHexStringOp"),
BYTECODE(AML_TO_INTEGER_OP, NULL, "ToIntegerOp"), BYTECODE(AML_TO_INTEGER_OP, NULL, "ToIntegerOp"),
BYTECODE(AML_TO_STRING_OP, NULL, "ToStringOp"), BYTECODE(AML_TO_STRING_OP, NULL, "ToStringOp"),
BYTECODE(AML_COPY_OBJECT_OP, NULL, "CopyObjectOp"), BYTECODE(AML_COPY_OBJECT_OP, NULL, "CopyObjectOp"),
BYTECODE(AML_MID_OP, NULL, "MidOp"), BYTECODE(AML_MID_OP, NULL, "MidOp"),
BYTECODE(AML_CONTINUE_OP, NULL, "ContinueOp"), BYTECODE(AML_CONTINUE_OP, NULL, "ContinueOp"),
BYTECODE(AML_IF_OP, NULL, "IfOp"), BYTECODE(AML_IF_OP, NULL, "IfOp"),
BYTECODE(AML_ELSE_OP, NULL, "ElseOp"), BYTECODE(AML_ELSE_OP, NULL, "ElseOp"),
BYTECODE(AML_WHILE_OP, NULL, "WhileOp"), BYTECODE(AML_WHILE_OP, NULL, "WhileOp"),
BYTECODE(AML_NOOP_OP, NULL, "NoopOp"), BYTECODE(AML_NOOP_OP, NULL, "NoopOp"),
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;
} }

View File

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

View File

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