mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
11 KiB
544 lines
11 KiB
#include "asl.h"
|
|
|
|
//
|
|
// Functions
|
|
//
|
|
|
|
VOID NullTok (VOID) { Vnone(); }
|
|
VOID IsZeroOp (VOID) { Vnone(); }
|
|
VOID VSn (VOID) { VAlArgs("S", NULL); }
|
|
VOID VOp (VOID) { VAlArgs("O", NULL); }
|
|
VOID VSnOp (VOID) { VAlArgs("SO", NULL); }
|
|
VOID VOpSn (VOID) { VAlArgs("OS", NULL); }
|
|
VOID VOpOp (VOID) { VAlArgs("OO", NULL); }
|
|
VOID VOpOpSn (VOID) { VAlArgs("OOS", NULL); }
|
|
VOID VOpOpOp (VOID) { VAlArgs("OOO", NULL); }
|
|
VOID VOpOpSnSn (VOID) { VAlArgs("OOSS", NULL); }
|
|
VOID VOpOpOpSn (VOID) { VAlArgs("OOOS", NULL); }
|
|
|
|
|
|
// not done..
|
|
|
|
VOID DefineTok (VOID) { AERROR ("Not complete: DefineTok"); }
|
|
VOID AliasOp (VOID) { AERROR ("Not complete: AliasOp"); }
|
|
VOID LoadOp (VOID) { AERROR ("Not complete: LoadOp"); }
|
|
|
|
UCHAR VAlArgMsg[] = "Argx";
|
|
|
|
BOOLEAN
|
|
VAlArg (
|
|
IN PUCHAR Msg,
|
|
IN PAL_DATA Arg,
|
|
IN UCHAR Type
|
|
)
|
|
//
|
|
// O - OpCode
|
|
// N - Name
|
|
// S - SuperName
|
|
// D - DefData
|
|
// Z - ASCIZ
|
|
//
|
|
{
|
|
BOOLEAN IsOpcode, IsSuperName, IsDefData, IsName, NotASLTerm, IsNumeric;
|
|
BOOLEAN Match, VerifyReference;
|
|
PUCHAR Data;
|
|
ULONG Len, SegLen;
|
|
UCHAR c;
|
|
PUCHAR p;
|
|
|
|
//
|
|
// If lower case, then a default value can be used
|
|
//
|
|
|
|
if (Type >= 'a' && Type <= 'z') {
|
|
|
|
if (Arg->Term == NullTok) {
|
|
return TRUE;
|
|
}
|
|
|
|
Type -= 'a' - 'A';
|
|
}
|
|
|
|
|
|
//
|
|
// Determine AL_DATA type
|
|
//
|
|
|
|
if (Arg->Term) {
|
|
//
|
|
// Is ASL term, type is encoded in term table
|
|
//
|
|
|
|
IsName = FALSE;
|
|
NotASLTerm = FALSE;
|
|
|
|
IsOpcode = Arg->Term->Flags & T_OPCODE ? TRUE : FALSE;
|
|
IsSuperName = Arg->Term->Flags & T_SUPERNAME ? TRUE : FALSE;
|
|
IsDefData = Arg->Term->Flags & T_DEFDATA ? TRUE : FALSE;
|
|
|
|
} else {
|
|
//
|
|
// Not ASL term, either a string or name refernce
|
|
//
|
|
|
|
IsOpcode = FALSE;
|
|
IsSuperName = FALSE;
|
|
IsDefData = FALSE;
|
|
IsNumeric = Arg->Flags & F_ISNUMERIC ? TRUE : FALSE;
|
|
NotASLTerm = TRUE;
|
|
IsName = FALSE;
|
|
|
|
GetAlData (Arg, &Data, &Len);
|
|
if (Len && !IsNumeric) {
|
|
//
|
|
// Determine if it's a valid name
|
|
//
|
|
|
|
IsName = TRUE;
|
|
SegLen = NAME_SEG_LENGTH;
|
|
while (Len) {
|
|
c = *Data;
|
|
if (c == '\\' || c == '^' || c == '.') {
|
|
SegLen = NAME_SEG_LENGTH;
|
|
} else if ( (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') {
|
|
if (SegLen) {
|
|
SegLen -= 1;
|
|
} else {
|
|
IsName = FALSE;
|
|
break;
|
|
}
|
|
} else {
|
|
IsName = FALSE;
|
|
}
|
|
|
|
Len -= 1;
|
|
Data += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Match = FALSE;
|
|
VerifyReference = FALSE;
|
|
|
|
switch (Type) {
|
|
case 'O': // opcode arg
|
|
p = "[Opcode|SuperName|Name]";
|
|
VerifyReference = NotASLTerm;
|
|
Match = IsOpcode || IsSuperName || IsName;
|
|
break;
|
|
|
|
case 'S': // supername arg
|
|
p = "[SuperName|Name]";
|
|
VerifyReference = NotASLTerm;
|
|
Match = IsSuperName || IsName;
|
|
break;
|
|
|
|
case 'N': // name arg
|
|
p = "Name";
|
|
VerifyReference = NotASLTerm;
|
|
Match = IsName;
|
|
break;
|
|
|
|
case 'D': // define data arg
|
|
p = "DataType";
|
|
Match = IsDefData;
|
|
break;
|
|
|
|
case 'V':
|
|
p = "Numeric";
|
|
Match = IsNumeric;
|
|
break;
|
|
|
|
case 'Z':
|
|
p = "ASCIZ";
|
|
Match = NotASLTerm;
|
|
break;
|
|
}
|
|
|
|
if (!Match) {
|
|
ERRORAL (AlLoc, "%s is invalid type. Expected %s", Msg, p);
|
|
} else if (VerifyReference && !(Arg->Flags & F_VERIFYREF)) {
|
|
ASSERT (Arg->u1.VerifyRef.Flink == NULL, "Can not have package");
|
|
Arg->Flags |= F_VERIFYREF;
|
|
InsertTailList (&VerifyRef, &Arg->u1.VerifyRef);
|
|
}
|
|
return Match;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
VAlArgs (
|
|
IN PUCHAR Types,
|
|
OUT PAL_DATA *Args
|
|
)
|
|
// Verify AL ha a fixed list of the given type
|
|
{
|
|
ULONG len, noargs, i;
|
|
PAL_DATA Arg;
|
|
PLIST_ENTRY Link;
|
|
BOOLEAN Status, Missing;
|
|
|
|
|
|
Status = TRUE;
|
|
Missing = FALSE;
|
|
noargs = strlen(Types);
|
|
len = noargs;
|
|
|
|
if (len < AlLoc->FLCount) {
|
|
ERRORAL (AlLoc, "Too many args. (Have %d, Want %d)", AlLoc->FLCount, len);
|
|
Status = FALSE;
|
|
}
|
|
|
|
if (len > AlLoc->FLCount) {
|
|
len = AlLoc->FLCount;
|
|
}
|
|
|
|
//
|
|
// Walk each arg and verify it
|
|
//
|
|
|
|
Link = AlLoc->FixedList.Flink;
|
|
for (i=0; i < len; i++) {
|
|
Arg = CONTAINING_RECORD(Link, AL_DATA, Link);
|
|
Link = Link->Flink;
|
|
|
|
//
|
|
// Build arg array for caller
|
|
//
|
|
|
|
if (Args) {
|
|
Args[i] = Arg;
|
|
}
|
|
|
|
//
|
|
// Verify this arg's data type
|
|
//
|
|
|
|
VAlArgMsg[3] = '0' + i;
|
|
if (!VAlArg (VAlArgMsg, Arg, Types[i])) {
|
|
Status = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Verify each unsupplied arg as optional
|
|
//
|
|
|
|
for (; i < noargs; i++) {
|
|
if (Args) {
|
|
// allocate a null Al
|
|
Arg = AllocAl();
|
|
Arg->Flags |= F_AMLENCODE;
|
|
InsertTailList (&AlLoc->FixedList, &Arg->Link);
|
|
Args[i] = Arg;
|
|
}
|
|
|
|
if (Types[i] < 'a' || Types[i] > 'z') {
|
|
// not an optional arg
|
|
if (!Missing) {
|
|
ERRORAL (AlLoc, "Missing args. Need %d\n", len);
|
|
Missing = TRUE;
|
|
Status = FALSE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
__cdecl SetAlData (
|
|
IN PAL_DATA Al,
|
|
IN PUCHAR Fmt,
|
|
...
|
|
)
|
|
{
|
|
ULONG i, j, plen;
|
|
ULONG Len;
|
|
PUCHAR Data;
|
|
UCHAR s[200];
|
|
union {
|
|
UCHAR c[4];
|
|
USHORT w;
|
|
ULONG d;
|
|
} u;
|
|
va_list args;
|
|
|
|
|
|
va_start (args, Fmt);
|
|
Len = 0;
|
|
for (i=0; Fmt[i]; i++) {
|
|
plen = 0;
|
|
switch (Fmt[i]) {
|
|
case 'O':
|
|
s[Len++] = Al->Term->Op1;
|
|
if (Al->Term->Op2) {
|
|
s[Len++] = Al->Term->Op2;
|
|
}
|
|
break;
|
|
|
|
case 'B':
|
|
u.c[0] = va_arg(args, UCHAR);
|
|
plen = sizeof(UCHAR);
|
|
break;
|
|
|
|
case 'W':
|
|
u.w = va_arg(args, USHORT);
|
|
plen = sizeof(USHORT);
|
|
break;
|
|
case 'D':
|
|
u.d = va_arg(args, ULONG);
|
|
plen = sizeof(ULONG);
|
|
break;
|
|
default:
|
|
ASSERT(FALSE, "SetAlData");
|
|
}
|
|
|
|
for (j=0; j < plen; j++) {
|
|
s[Len++] = u.c[j];
|
|
}
|
|
}
|
|
|
|
Data = SetAlDataLen(Al, Len);
|
|
memcpy (Data, s, Len);
|
|
}
|
|
|
|
|
|
VOID
|
|
Vnone (
|
|
VOID
|
|
)
|
|
{
|
|
if (AlLoc->FLCount) {
|
|
ERRORAL (AlLoc, "Too many args. (Have %d, Want 0)", AlLoc->FLCount);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ParseMethodReference(
|
|
VOID
|
|
)
|
|
{
|
|
BOOLEAN Status;
|
|
|
|
// verify AlLoc is a name & add it to the VerifyRef list
|
|
Status = VAlArg ("", AlLoc, 'N');
|
|
|
|
// Encode it
|
|
if (Status) {
|
|
AMLEncodeName (AlLoc);
|
|
}
|
|
|
|
// retire it
|
|
AlLoc = AlLoc->Parent;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
IncludeTok (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2], Al;
|
|
PUCHAR Name;
|
|
ULONG Len;
|
|
BOOLEAN Status;
|
|
|
|
Status = VAlArgs ("Z", Args);
|
|
|
|
if (Status) {
|
|
GetAlData (Args[0], &Name, &Len);
|
|
IncludeSource (Name);
|
|
}
|
|
|
|
Al = AlLoc;
|
|
AlLoc = NULL;
|
|
FreeAl (Al);
|
|
}
|
|
|
|
|
|
VOID
|
|
MoveBodyToArg (
|
|
IN PAL_DATA BodyAl
|
|
)
|
|
{
|
|
PAL_DATA Al;
|
|
|
|
//
|
|
// If null list, then add nop
|
|
//
|
|
|
|
if (IsListEmpty(&BodyAl->u1.VariableList)) {
|
|
// add nop
|
|
Al = AllocAl();
|
|
InsertTailList(&BodyAl->u1.VariableList, &Al->Link);
|
|
Al->Flags |= F_AMLENCODE;
|
|
Al->u.Data.Length = 1;
|
|
Al->u.Data.Data[0] = AML_NOP;
|
|
}
|
|
|
|
//
|
|
// If Flink != Blink, there is more then one term in the body.
|
|
// Put it in a code package
|
|
//
|
|
|
|
if (BodyAl->u1.VariableList.Flink != BodyAl->u1.VariableList.Blink) {
|
|
Al = AllocAl();
|
|
Al->DataType = TypeCodePackage;
|
|
Al->Flags |= F_AMLPACKAGE | F_AMLENCODE;
|
|
Al->u.Data.Length = 1;
|
|
Al->u.Data.Data[0] = AML_CODEPACKAGE;
|
|
|
|
// move list to Al
|
|
Al->u1.VariableList.Flink = BodyAl->u1.VariableList.Flink;
|
|
Al->u1.VariableList.Blink = BodyAl->u1.VariableList.Blink;
|
|
Al->u1.VariableList.Flink->Blink = &Al->u1.VariableList;
|
|
Al->u1.VariableList.Blink->Flink = &Al->u1.VariableList;
|
|
|
|
} else {
|
|
|
|
Al = CONTAINING_RECORD(BodyAl->u1.VariableList.Flink, AL_DATA, Link);
|
|
}
|
|
|
|
// no longer a package
|
|
BodyAl->Flags &= ~F_AMLPACKAGE;
|
|
InitializeListHead (&BodyAl->u1.VariableList);
|
|
|
|
// append to fixed list
|
|
InsertTailList (&AlLoc->FixedList, &Al->Link);
|
|
}
|
|
|
|
VOID
|
|
WhileOp (
|
|
VOID
|
|
)
|
|
{
|
|
if (AlLoc->FLCount != 1) {
|
|
ERRORAL (AlLoc, "Syntax error in predicate");
|
|
return ;
|
|
}
|
|
|
|
MoveBodyToArg(AlLoc);
|
|
}
|
|
|
|
|
|
VOID
|
|
IfOp (
|
|
VOID
|
|
)
|
|
{
|
|
AlLoc->DataType = TypeIf;
|
|
if (AlLoc->FLCount != 1) {
|
|
ERRORAL (AlLoc, "Syntax error in predicate");
|
|
return ;
|
|
}
|
|
|
|
MoveBodyToArg(AlLoc);
|
|
}
|
|
|
|
|
|
VOID
|
|
ElseOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Al, ElseAl;
|
|
PLIST_ENTRY Link;
|
|
|
|
if (AlLoc->FLCount != 0) {
|
|
ERRORAL (AlLoc, "Syntax error in predicate");
|
|
return ;
|
|
}
|
|
|
|
//
|
|
// Entry just before this one should be an If
|
|
//
|
|
|
|
Link = AlLoc->Parent->u1.VariableList.Blink;
|
|
ASSERT (Link == &AlLoc->Link, "Else not last term");
|
|
Al = CONTAINING_RECORD(Link->Blink, AL_DATA, Link);
|
|
|
|
if (Link->Blink == &AlLoc->Parent->u1.VariableList || Al->DataType != TypeIf) {
|
|
ERRORAL (AlLoc, "else unexpected");
|
|
return ;
|
|
}
|
|
|
|
//
|
|
// Convert 'if' to 'if-else', and add else body
|
|
//
|
|
|
|
Al->u.Data.Data[0] = AlLoc->u.Data.Data[0];
|
|
ElseAl = AlLoc;
|
|
AlLoc = Al;
|
|
MoveBodyToArg(ElseAl);
|
|
|
|
//
|
|
// Remove else
|
|
//
|
|
|
|
FreeAl (ElseAl);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
StallOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Arg;
|
|
BOOLEAN Status;
|
|
ULONG Stall;
|
|
|
|
// Get the Number arg
|
|
Status = VAlArgs ("V", &Arg);
|
|
|
|
if (Status) {
|
|
Stall = ArgToValue(&Arg, 0, "Stall(Arg0)", 0xff);
|
|
SetAlData (Arg, "B", Stall);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
SleepOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Arg;
|
|
BOOLEAN Status;
|
|
ULONG Sleep;
|
|
|
|
// Get the Number arg
|
|
Status = VAlArgs ("V", &Arg);
|
|
|
|
if (Status) {
|
|
Sleep = ArgToValue(&Arg, 0, "Sleep(Arg0)", 0xffff);
|
|
SetAlData (Arg, "W", Sleep);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FatalOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[3];
|
|
BOOLEAN Status;
|
|
ULONG Type, Code;
|
|
|
|
// Get the Number arg
|
|
Status = VAlArgs ("VVO", Args);
|
|
|
|
if (Status) {
|
|
Type = ArgToValue(&Args, 0, "Fatal(Arg0)", 0xff);
|
|
Code = ArgToValue(&Args, 1, "Fatal(Arg0)", -1);
|
|
SetAlData (Args[0], "BD", Type, Code);
|
|
FreeAl (Args[1]);
|
|
}
|
|
}
|