diff --git a/source/compiler/aslmessages.h b/source/compiler/aslmessages.h index bf8b67eb5..0d38ab37c 100644 --- a/source/compiler/aslmessages.h +++ b/source/compiler/aslmessages.h @@ -145,6 +145,8 @@ typedef enum ASL_MSG_CLOSE, ASL_MSG_COMPILER_INTERNAL, ASL_MSG_COMPILER_RESERVED, + ASL_MSG_CONNECTION_MISSING, + ASL_MSG_CONNECTION_INVALID, ASL_MSG_CONSTANT_EVALUATION, ASL_MSG_CONSTANT_FOLDED, ASL_MSG_CORE_EXCEPTION, @@ -165,6 +167,8 @@ typedef enum ASL_MSG_FIELD_UNIT_OFFSET, ASL_MSG_GPE_NAME_CONFLICT, ASL_MSG_HID_LENGTH, + ASL_MSG_HID_PREFIX, + ASL_MSG_HID_SUFFIX, ASL_MSG_INCLUDE_FILE_OPEN, ASL_MSG_INPUT_FILE_OPEN, ASL_MSG_INTEGER_LENGTH, @@ -301,6 +305,8 @@ char *AslMessages [] = { /* ASL_MSG_CLOSE */ "Could not close file", /* ASL_MSG_COMPILER_INTERNAL */ "Internal compiler error", /* ASL_MSG_COMPILER_RESERVED */ "Use of compiler reserved name", +/* ASL_MSG_CONNECTION_MISSING */ "A Connection operator is required for this field SpaceId", +/* ASL_MSG_CONNECTION_INVALID */ "Invalid OpRegion SpaceId for use of Connection operator", /* ASL_MSG_CONSTANT_EVALUATION */ "Could not evaluate constant expression", /* ASL_MSG_CONSTANT_FOLDED */ "Constant expression evaluated and reduced", /* ASL_MSG_CORE_EXCEPTION */ "From ACPI CA Subsystem", @@ -321,6 +327,8 @@ char *AslMessages [] = { /* ASL_MSG_FIELD_UNIT_OFFSET */ "Field Unit extends beyond region limit", /* ASL_MSG_GPE_NAME_CONFLICT */ "Name conflicts with a previous GPE method", /* ASL_MSG_HID_LENGTH */ "_HID string must be exactly 7 or 8 characters", +/* ASL_MSG_HID_PREFIX */ "_HID prefix must be all uppercase or decimal digits", +/* ASL_MSG_HID_SUFFIX */ "_HID suffix must be all hex digits", /* ASL_MSG_INCLUDE_FILE_OPEN */ "Could not open include file", /* ASL_MSG_INPUT_FILE_OPEN */ "Could not open input file", /* ASL_MSG_INTEGER_LENGTH */ "64-bit integer in 32-bit table, truncating", diff --git a/source/compiler/aslwalks.c b/source/compiler/aslwalks.c index ae1716ade..7b178baee 100644 --- a/source/compiler/aslwalks.c +++ b/source/compiler/aslwalks.c @@ -1104,6 +1104,7 @@ AnOtherSemanticAnalysisWalkBegin ( ACPI_PARSE_OBJECT *ArgNode; ACPI_PARSE_OBJECT *PrevArgNode = NULL; const ACPI_OPCODE_INFO *OpInfo; + ACPI_NAMESPACE_NODE *Node; OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); @@ -1228,6 +1229,74 @@ AnOtherSemanticAnalysisWalkBegin ( } break; + case PARSEOP_CONNECTION: + /* + * Ensure that the referenced operation region has the correct SPACE_ID. + * From the grammar/parser, we know the parent is a FIELD definition. + */ + ArgNode = Op->Asl.Parent; /* Field definition */ + ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ + Node = ArgNode->Asl.Node; /* OpRegion namespace node */ + + ArgNode = Node->Op; /* OpRegion definition */ + ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ + ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ + + /* + * The Connection() operator is only valid for the following operation + * region SpaceIds: GeneralPurposeIo and GenericSerialBus. + */ + if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && + (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) + { + AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL); + } + break; + + case PARSEOP_FIELD: + /* + * Ensure that fields for GeneralPurposeIo and GenericSerialBus + * contain at least one Connection() operator + */ + ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ + Node = ArgNode->Asl.Node; /* OpRegion namespace node */ + + ArgNode = Node->Op; /* OpRegion definition */ + ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ + ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ + + /* We are only interested in GeneralPurposeIo and GenericSerialBus */ + + if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && + (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) + { + break; + } + + ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ + ArgNode = ArgNode->Asl.Next; /* AccessType */ + ArgNode = ArgNode->Asl.Next; /* LockRule */ + ArgNode = ArgNode->Asl.Next; /* UpdateRule */ + ArgNode = ArgNode->Asl.Next; /* Start of FieldUnitList */ + + /* Walk the FieldUnitList */ + + while (ArgNode) + { + if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION) + { + break; + } + else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG) + { + AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL); + break; + } + + ArgNode = ArgNode->Asl.Next; + } + break; + default: break; }