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.
484 lines
9.6 KiB
484 lines
9.6 KiB
#include "asl.h"
|
|
|
|
PUCHAR
|
|
AMLEncodeName (
|
|
IN PAL_DATA Al
|
|
)
|
|
{
|
|
PUCHAR Data, Name;
|
|
ULONG Len;
|
|
BOOLEAN IsRoot;
|
|
UCHAR s[200];
|
|
ULONG newlen, nopar;
|
|
UCHAR c;
|
|
|
|
|
|
//
|
|
// Convert name to it's AML encoding
|
|
//
|
|
|
|
GetAlData (Al, &Data, &Len);
|
|
|
|
newlen = 0;
|
|
nopar = 0;
|
|
IsRoot = FALSE;
|
|
for (; ;) {
|
|
|
|
ASSERT(newlen < 190, "ASL name too large");
|
|
|
|
if (Len && *Data != '\\' && *Data != '^' && *Data != '.') {
|
|
|
|
s[newlen] = *Data;
|
|
newlen += 1;
|
|
|
|
} else {
|
|
|
|
while (newlen % 4) {
|
|
s[newlen] = '_';
|
|
newlen += 1;
|
|
}
|
|
|
|
if (!Len) {
|
|
break;
|
|
}
|
|
|
|
switch (*Data) {
|
|
case '\\':
|
|
IsRoot = TRUE; // go to root
|
|
newlen = 0;
|
|
break;
|
|
case '^':
|
|
if (newlen) {
|
|
newlen -= 4; // back up one level
|
|
} else {
|
|
nopar += 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
Data += 1;
|
|
Len -= 1;
|
|
}
|
|
|
|
if (IsRoot) {
|
|
nopar = 0;
|
|
}
|
|
|
|
Len = newlen + nopar + (IsRoot ? 1 : 0);
|
|
if (newlen == 8) {
|
|
// needs dual prefix
|
|
Len += 1;
|
|
}
|
|
if (newlen > 8) {
|
|
// needs multi prefix
|
|
Len += 2;
|
|
}
|
|
|
|
Name = SetAlDataLen (Al, Len);
|
|
Data = Name;
|
|
|
|
if (IsRoot) {
|
|
*(Data++) = '\\';
|
|
}
|
|
|
|
for (; nopar; nopar--) {
|
|
*(Data++) = '\\';
|
|
}
|
|
|
|
if (newlen == 8) {
|
|
*(Data++) = AML_DUAL_PREFIX;
|
|
}
|
|
|
|
if (newlen > 8) {
|
|
*(Data++) = AML_MULTI_PREFIX;
|
|
*(Data++) = newlen / 4;
|
|
}
|
|
|
|
memcpy (Data, s, newlen);
|
|
return Name;
|
|
}
|
|
|
|
PAML_DATA
|
|
FindNameSeg (
|
|
PAML_NAME Name,
|
|
PUCHAR pName
|
|
)
|
|
{
|
|
ULONG NameSeg;
|
|
PLIST_ENTRY Link;
|
|
PAML_NAME Check;
|
|
|
|
NameSeg = *((PULONG) pName);
|
|
|
|
Link = &Name->Next;
|
|
do {
|
|
Check = CONTAINING_RECORD(Link, AML_NAME, Next);
|
|
if (Check->NameSeg == NameSeg) {
|
|
// found it
|
|
return Check;
|
|
}
|
|
|
|
Link = Link->Flink;
|
|
} while (Link != &Name->Next);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
VOID
|
|
NameAl (
|
|
PAL_DATA Al,
|
|
PUCHAR Name
|
|
)
|
|
{
|
|
PAL_DATA RAl;
|
|
PAML_NAME Loc, NewLoc;
|
|
ULONG segs;
|
|
BOOLEAN AlAdded, IsPeer;
|
|
|
|
// bugbug: need to verify name doesn't traverse through
|
|
// something which can't hose a name. (E.g. a "D" within an "M")
|
|
|
|
VPRINT (4, "Adding nameseg %.4s\n", Name);
|
|
|
|
//
|
|
// Get starting point
|
|
//
|
|
|
|
if (*Name == '\\') {
|
|
Loc = DataImage->Name;
|
|
Name += 1;
|
|
} else {
|
|
for (RAl = Al; !RAl->Name; RAl = RAl->Parent) ;
|
|
Loc = RAl->Name;
|
|
}
|
|
|
|
//
|
|
// Go up one for each parent indicator
|
|
//
|
|
|
|
while (*Name == '^') {
|
|
if (Loc->Parent) {
|
|
Loc = Loc->Parent;
|
|
}
|
|
Name++;
|
|
}
|
|
|
|
//
|
|
// Go down names indicated, expect for last
|
|
//
|
|
|
|
segs = 1;
|
|
if (*Name == AML_DUAL_PREFIX) {
|
|
segs = 2;
|
|
Name += 1;
|
|
} else if (*Name == AML_MULTI_PREFIX) {
|
|
segs = Name[1];
|
|
Name += 2;
|
|
}
|
|
|
|
//
|
|
// Find first peer name
|
|
//
|
|
|
|
AlAdded = FALSE;
|
|
IsPeer = FALSE;
|
|
|
|
//
|
|
// Loop for each NameSeg
|
|
//
|
|
|
|
while (segs) {
|
|
|
|
//
|
|
// Need to go down to the child entry now
|
|
//
|
|
|
|
if (Loc->Child) {
|
|
Loc = Loc->Child;
|
|
NewLoc = FindNameSeg(Loc, Name);
|
|
IsPeer = TRUE;
|
|
} else {
|
|
IsPeer = FALSE;
|
|
NewLoc = NULL;
|
|
}
|
|
|
|
if (!NewLoc) {
|
|
//
|
|
// Name was not found, add it
|
|
//
|
|
|
|
NewLoc = AllocName();
|
|
if (segs == 1) {
|
|
// last name component, add Al
|
|
NewLoc->Al = Al;
|
|
Al->Name = NewLoc;
|
|
AlAdded = TRUE;
|
|
}
|
|
|
|
// initialize name
|
|
NewLoc->NameSeg = *((PULONG) Name);
|
|
|
|
if (IsPeer) {
|
|
// add as a peer
|
|
NewLoc->Parent = Loc->Parent;
|
|
InsertTailList(&Loc->Next, &NewLoc->Next);
|
|
} else {
|
|
// add as a child
|
|
ASSERT(Loc->Child == NULL, "NameAl");
|
|
NewLoc->Parent = Loc;
|
|
Loc->Child = NewLoc;
|
|
}
|
|
}
|
|
|
|
Loc = NewLoc;
|
|
|
|
segs -= 1;
|
|
Name += 4;
|
|
}
|
|
|
|
if (!AlAdded) {
|
|
//
|
|
// Name was already in name space
|
|
//
|
|
|
|
if (!Loc->Al ||
|
|
(Loc->Al && Loc->Al->DataType == TypeScope)) {
|
|
// we can own it
|
|
Loc->Al = Al;
|
|
Al->Name = Loc;
|
|
} else {
|
|
// if new name is scope, it's ok
|
|
if (Al->DataType == TypeScope) {
|
|
Al->Name = Loc;
|
|
} else {
|
|
ERRORAL (AlLoc, "Duplicate name '%.4s'", Name-4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
VAlArgsAndNameArg0 (
|
|
DATATYPE ObjType,
|
|
PUCHAR ArgTypes,
|
|
PAL_DATA *Args
|
|
)
|
|
{
|
|
BOOLEAN Status;
|
|
PUCHAR Name;
|
|
|
|
AlLoc->DataType = ObjType;
|
|
|
|
// Get the args for NameOp
|
|
Status = VAlArgs (ArgTypes, Args);
|
|
|
|
if (Status) {
|
|
// encode the name
|
|
Name = AMLEncodeName (Args[0]);
|
|
|
|
// remove from verification list, and flag that
|
|
// this name is to be generated
|
|
|
|
ASSERT(Args[0]->Flags & F_VERIFYREF, "NameArg0");
|
|
Args[0]->Flags &= ~F_VERIFYREF;
|
|
RemoveEntryList (&Args[0]->u1.VerifyRef);
|
|
Args[0]->u1.VerifyRef.Flink = NULL;
|
|
Args[0]->u1.VerifyRef.Blink = NULL;
|
|
|
|
Args[0]->Flags |= F_CREATENAME;
|
|
|
|
// put it in the name space
|
|
NameAl (AlLoc, Name);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
NameOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2];
|
|
VAlArgsAndNameArg0 (TypeName, "ND", Args);
|
|
}
|
|
|
|
|
|
VOID
|
|
ScopeOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2];
|
|
VAlArgsAndNameArg0 (TypeScope, "N", Args);
|
|
}
|
|
|
|
|
|
VOID
|
|
MethodOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2];
|
|
BOOLEAN Status;
|
|
ULONG ArgCnt;
|
|
PUCHAR Data;
|
|
|
|
if (!AlLoc->u1.VariableList.Flink) {
|
|
|
|
Status = VAlArgsAndNameArg0 (TypeMethod, "Nv", Args);
|
|
|
|
if (Status) {
|
|
// get mathod arg count
|
|
ArgCnt = ArgToValue(Args, 1, "Method(Arg1)", 0xff);
|
|
|
|
if (ArgCnt > 7) {
|
|
ERRORAL (AlLoc, "Method arg count too large");
|
|
ArgCnt = 0;
|
|
}
|
|
|
|
// build AML encoding of argcnt
|
|
Data = SetAlDataLen(Args[1], 1);
|
|
*Data = ArgCnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DeviceOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2];
|
|
VAlArgsAndNameArg0 (TypeDevice, "N", Args);
|
|
}
|
|
|
|
|
|
VOID
|
|
ThermalZoneOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2];
|
|
VAlArgsAndNameArg0 (TypeThermalZone, "N", Args);
|
|
}
|
|
|
|
|
|
VOID EventOp(
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2];
|
|
VAlArgsAndNameArg0 (TypeSync, "N", Args);
|
|
}
|
|
|
|
VOID MutexOp(
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[2];
|
|
BOOLEAN Status;
|
|
PUCHAR Data;
|
|
ULONG Level;
|
|
|
|
Status = VAlArgsAndNameArg0 (TypeSync, "NV", Args);
|
|
if (Status) {
|
|
Level = ArgToValue(Args, 1, "Mutex(Arg1)", 0xffff);
|
|
SetAlData (Args[1], "W", Level);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
FieldOp (
|
|
VOID
|
|
)
|
|
{
|
|
PAL_DATA Args[4];
|
|
ULONG Width, Lock, Access;
|
|
BOOLEAN Status;
|
|
FIELDENCODE Field;
|
|
PLIST_ENTRY Link;
|
|
PAL_DATA Al;
|
|
ULONG ArgNo;
|
|
PUCHAR Data;
|
|
ULONG Len, bits;
|
|
PUCHAR Name;
|
|
|
|
|
|
if (!AlLoc->u1.VariableList.Flink) {
|
|
|
|
// Get the element count arg
|
|
Status = VAlArgs ("Nzzz", Args);
|
|
|
|
if (Status) {
|
|
MatchArg (Args[1], "Field()", 1, FieldWidth, &Width);
|
|
MatchArg (Args[2], "Field()", 2, FieldLock, &Lock);
|
|
MatchArg (Args[3], "Field()", 3, FieldAccess, &Access);
|
|
FreeAl (Args[2]);
|
|
FreeAl (Args[3]);
|
|
|
|
memset (&Field, 0, sizeof (Field));
|
|
|
|
Field.Lock = Lock;
|
|
Field.Width = Width;
|
|
Field.Type = Access;
|
|
SetAlData (Args[1], "W", *((PULONG)&Field));
|
|
}
|
|
|
|
} else {
|
|
|
|
// bugbug: errors here look like arg errors, not term errors
|
|
|
|
Status = TRUE;
|
|
ArgNo = 0;
|
|
Link = AlLoc->u1.VariableList.Flink;
|
|
while (Status && Link != &AlLoc->u1.VariableList) {
|
|
Al = CONTAINING_RECORD(Link, AL_DATA, Link);
|
|
Link = Link->Flink;
|
|
|
|
ArgNo += 1;
|
|
|
|
if (ArgNo % 2) {
|
|
//
|
|
// Get bit field name
|
|
//
|
|
|
|
Al->DataType = TypeField;
|
|
VAlArg ("bit field name", Al, 'z');
|
|
GetAlData(Al, &Data, &Len);
|
|
if (!Len) {
|
|
// reserved bits
|
|
Al->Flags |= F_AMLENCODE;
|
|
Al->u.Data.Length = 1;
|
|
Al->u.Data.Data[0] = 0;
|
|
} else {
|
|
// get value as name
|
|
Status = VAlArg ("bit field name", Al, 'N');
|
|
if (!Status) {
|
|
break;
|
|
}
|
|
Name = AMLEncodeName (Al);
|
|
NameAl (Al, Name);
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Get # of bits
|
|
//
|
|
|
|
VAlArg ("bit count", Al, 'V');
|
|
bits = ArgToValue (&Al, 0, "FieldDefinitions", 0xff);
|
|
SetAlData (Al, "B", bits);
|
|
}
|
|
}
|
|
|
|
if (ArgNo % 2) {
|
|
ERRORAL (AlLoc, "FieldDefinitions - missing bit count");
|
|
}
|
|
}
|
|
}
|