2
ACPI Sdt Protocol Driver
4
Copyright (c) 2010, Intel Corporation. All rights reserved. <BR>
5
This program and the accompanying materials
6
are licensed and made available under the terms and conditions of the BSD License
7
which accompanies this distribution. The full text of the license may be found at
8
http://opensource.org/licenses/bsd-license.php
10
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
#include "AcpiTable.h"
18
Construct node list according to the AML handle.
20
@param[in] AmlHandle AML handle.
21
@param[in] AmlRootNodeList AML root node list.
22
@param[in] AmlParentNodeList AML parent node list.
24
@retval EFI_SUCCESS Success.
25
@retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.
28
AmlConstructNodeList (
29
IN EFI_AML_HANDLE *AmlHandle,
30
IN EFI_AML_NODE_LIST *AmlRootNodeList,
31
IN EFI_AML_NODE_LIST *AmlParentNodeList
37
@param[in] NameSeg AML NameSeg.
38
@param[in] Parent AML parent node list.
39
@param[in] AmlByteEncoding AML Byte Encoding.
46
IN EFI_AML_NODE_LIST *Parent,
47
IN AML_BYTE_ENCODING *AmlByteEncoding
50
EFI_AML_NODE_LIST *AmlNodeList;
52
AmlNodeList = AllocatePool (sizeof(*AmlNodeList));
53
ASSERT (AmlNodeList != NULL);
55
AmlNodeList->Signature = EFI_AML_NODE_LIST_SIGNATURE;
56
CopyMem (AmlNodeList->Name, NameSeg, AML_NAME_SEG_SIZE);
57
AmlNodeList->Buffer = NULL;
58
AmlNodeList->Size = 0;
59
InitializeListHead (&AmlNodeList->Link);
60
InitializeListHead (&AmlNodeList->Children);
61
AmlNodeList->Parent = Parent;
62
AmlNodeList->AmlByteEncoding = AmlByteEncoding;
68
Find the AML NameSeg in the children of AmlParentNodeList.
70
@param[in] NameSeg AML NameSeg.
71
@param[in] AmlParentNodeList AML parent node list.
72
@param[in] Create TRUE means to create node if not found.
74
@return AmlChildNode whoes name is same as NameSeg.
79
IN EFI_AML_NODE_LIST *AmlParentNodeList,
83
EFI_AML_NODE_LIST *CurrentAmlNodeList;
84
LIST_ENTRY *CurrentLink;
85
LIST_ENTRY *StartLink;
86
EFI_AML_NODE_LIST *AmlNodeList;
88
StartLink = &AmlParentNodeList->Children;
89
CurrentLink = StartLink->ForwardLink;
91
while (CurrentLink != StartLink) {
92
CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
94
// AML name is same as the one stored
96
if (CompareMem (CurrentAmlNodeList->Name, NameSeg, AML_NAME_SEG_SIZE) == 0) {
100
return CurrentAmlNodeList;
102
CurrentLink = CurrentLink->ForwardLink;
113
// Create new node with NULL buffer - it means namespace not be returned.
115
AmlNodeList = AmlCreateNode (NameSeg, AmlParentNodeList, NULL);
116
InsertTailList (&AmlParentNodeList->Children, &AmlNodeList->Link);
122
Find the AML NameString in the children of AmlParentNodeList or AmlRootNodeList.
124
@param[in] NameString AML NameString.
125
@param[in] AmlRootNodeList AML root node list.
126
@param[in] AmlParentNodeList AML parent node list.
127
@param[in] Create TRUE means to create node if not found.
129
@return AmlChildNode whoes name is same as NameSeg.
132
AmlFindNodeInTheTree (
133
IN UINT8 *NameString,
134
IN EFI_AML_NODE_LIST *AmlRootNodeList,
135
IN EFI_AML_NODE_LIST *AmlParentNodeList,
140
EFI_AML_NODE_LIST *AmlNodeList;
141
EFI_AML_NODE_LIST *AmlCurrentNodeList;
148
// Handle root or parent prefix
150
if (*Buffer == AML_ROOT_CHAR) {
151
AmlCurrentNodeList = AmlRootNodeList;
153
} else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
154
AmlCurrentNodeList = AmlParentNodeList;
156
if (AmlCurrentNodeList->Parent != NULL) {
157
AmlCurrentNodeList = AmlCurrentNodeList->Parent;
160
// Only root has no parent
162
ASSERT (AmlCurrentNodeList == AmlRootNodeList);
165
} while (*Buffer == AML_PARENT_PREFIX_CHAR);
167
AmlCurrentNodeList = AmlParentNodeList;
171
// Handle name segment
173
if (*Buffer == AML_DUAL_NAME_PREFIX) {
176
} else if (*Buffer == AML_MULTI_NAME_PREFIX) {
180
} else if (*Buffer == 0) {
182
// NULL name, only for Root
184
ASSERT (AmlCurrentNodeList == AmlRootNodeList);
185
return AmlCurrentNodeList;
195
AmlNodeList = AmlFindNodeInThis (Buffer, AmlCurrentNodeList, Create);
196
if (AmlNodeList == NULL) {
199
AmlCurrentNodeList = AmlNodeList;
200
Buffer += AML_NAME_SEG_SIZE;
202
} while (Index < SegCount);
208
Insert the NameString to the AmlNodeList.
210
@param[in] NameString AML NameString.
211
@param[in] Buffer Buffer for the Node.
212
@param[in] Size Size for the Node.
213
@param[in] AmlRootNodeList AML root node list.
214
@param[in] AmlParentNodeList AML parent node list.
216
@return AmlChildNode whoes name is NameString.
219
AmlInsertNodeToTree (
220
IN UINT8 *NameString,
223
IN EFI_AML_NODE_LIST *AmlRootNodeList,
224
IN EFI_AML_NODE_LIST *AmlParentNodeList
227
EFI_AML_NODE_LIST *AmlNodeList;
229
AmlNodeList = AmlFindNodeInTheTree (
233
TRUE // Find and Create
235
ASSERT (AmlNodeList != NULL);
236
if (AmlNodeList == NULL) {
243
if (AmlNodeList->Buffer == NULL) {
245
// NULL means new added one or SCOPE_OP
247
if (*(UINT8 *)Buffer != AML_SCOPE_OP) {
249
// We need check if new one is SCOPE_OP, because SCOPE_OP just means namespace, not a real device.
250
// We should not return SCOPE_OP.
252
AmlNodeList->Buffer = Buffer;
253
AmlNodeList->Size = Size;
254
AmlNodeList->AmlByteEncoding = AmlSearchByOpByte (Buffer);
262
if (*(UINT8 *)Buffer == AML_SCOPE_OP) {
264
// The new one is SCOPE_OP, OK just return;
270
// Oops!!!, There must be something wrong.
272
DEBUG ((EFI_D_ERROR, "AML: Override Happen - %a!\n", NameString));
273
DEBUG ((EFI_D_ERROR, "AML: Existing Node - %x\n", AmlNodeList->Buffer));
274
DEBUG ((EFI_D_ERROR, "AML: New Buffer - %x\n", Buffer));
280
Construct child node list according to the AML handle.
282
@param[in] AmlHandle AML handle.
283
@param[in] AmlRootNodeList AML root node list.
284
@param[in] AmlParentNodeList AML parent node list.
286
@retval EFI_SUCCESS Success.
287
@retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.
290
AmlConstructNodeListForChild (
291
IN EFI_AML_HANDLE *AmlHandle,
292
IN EFI_AML_NODE_LIST *AmlRootNodeList,
293
IN EFI_AML_NODE_LIST *AmlParentNodeList
296
AML_BYTE_ENCODING *AmlByteEncoding;
299
UINT8 *CurrentBuffer;
300
EFI_AML_HANDLE *AmlChildHandle;
303
AmlByteEncoding = AmlHandle->AmlByteEncoding;
304
Buffer = AmlHandle->Buffer;
305
BufferSize = AmlHandle->Size;
308
// Check if we need recursively add node
310
if ((AmlByteEncoding->Attribute & AML_HAS_CHILD_OBJ) == 0) {
312
// No more node need to be added
318
// Do we need add node within METHOD?
319
// Yes, just add Object is OK. But we need filter NameString for METHOD invoke.
323
// Now, we get the last node.
325
Status = AmlGetOffsetAfterLastOption (AmlHandle, &CurrentBuffer);
326
if (EFI_ERROR (Status)) {
327
return EFI_INVALID_PARAMETER;
331
// Go through all the reset buffer.
333
while ((UINTN)CurrentBuffer < (UINTN)Buffer + BufferSize) {
335
// Find the child node.
337
Status = SdtOpenEx (CurrentBuffer, (UINTN)Buffer + BufferSize - (UINTN)CurrentBuffer, (EFI_ACPI_HANDLE *)&AmlChildHandle);
338
if (EFI_ERROR (Status)) {
340
// No child found, break now.
346
// Good, find the child. Construct node recursively
348
Status = AmlConstructNodeList (
353
if (EFI_ERROR (Status)) {
360
CurrentBuffer += AmlChildHandle->Size;
362
Close ((EFI_ACPI_HANDLE)AmlChildHandle);
369
Construct node list according to the AML handle.
371
@param[in] AmlHandle AML handle.
372
@param[in] AmlRootNodeList AML root node list.
373
@param[in] AmlParentNodeList AML parent node list.
375
@retval EFI_SUCCESS Success.
376
@retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.
379
AmlConstructNodeList (
380
IN EFI_AML_HANDLE *AmlHandle,
381
IN EFI_AML_NODE_LIST *AmlRootNodeList,
382
IN EFI_AML_NODE_LIST *AmlParentNodeList
386
EFI_AML_NODE_LIST *AmlNodeList;
389
// 1. Check if there is need to construct node for this OpCode.
391
if ((AmlHandle->AmlByteEncoding->Attribute & AML_IN_NAMESPACE) == 0) {
393
// No need to construct node, so we just skip this OpCode.
399
// 2. Now, we need construct node for this OpCode.
401
NameString = AmlGetObjectName (AmlHandle);
402
if (NameString == NULL) {
403
return EFI_INVALID_PARAMETER;
407
// Now, we need to insert node to the node list.
408
// NOTE: The name here could be AML NameString. So the callee need parse it.
410
AmlNodeList = AmlInsertNodeToTree (NameString, AmlHandle->Buffer, AmlHandle->Size, AmlRootNodeList, AmlParentNodeList);
411
ASSERT (AmlNodeList != NULL);
414
// 3. Ok, we need to parse the object list to see if there are more node to be added.
416
return AmlConstructNodeListForChild (AmlHandle, AmlRootNodeList, AmlNodeList);
422
@param[in] AmlParentNodeList AML parent node list.
425
AmlDestructNodeList (
426
IN EFI_AML_NODE_LIST *AmlParentNodeList
429
EFI_AML_NODE_LIST *CurrentAmlNodeList;
430
LIST_ENTRY *CurrentLink;
431
LIST_ENTRY *StartLink;
434
// Get the children link
436
StartLink = &AmlParentNodeList->Children;
437
CurrentLink = StartLink->ForwardLink;
440
// Go through all the children
442
while (CurrentLink != StartLink) {
444
// Destruct the child's list recursively
446
CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
447
CurrentLink = CurrentLink->ForwardLink;
450
// Remove this child from list and free the node
452
RemoveEntryList (&(CurrentAmlNodeList->Link));
454
AmlDestructNodeList (CurrentAmlNodeList);
460
FreePool (AmlParentNodeList);
467
@param[in] AmlParentNodeList AML parent node list.
468
@param[in] Level Output debug level.
472
IN EFI_AML_NODE_LIST *AmlParentNodeList,
476
EFI_AML_NODE_LIST *CurrentAmlNodeList;
477
volatile LIST_ENTRY *CurrentLink;
480
CurrentLink = AmlParentNodeList->Children.ForwardLink;
483
DEBUG ((EFI_D_ERROR, "\\"));
485
for (Index = 0; Index < Level; Index++) {
486
DEBUG ((EFI_D_ERROR, " "));
488
AmlPrintNameSeg (AmlParentNodeList->Name);
490
DEBUG ((EFI_D_ERROR, "\n"));
492
while (CurrentLink != &AmlParentNodeList->Children) {
493
CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
494
AmlDumpNodeInfo (CurrentAmlNodeList, Level + 1);
495
CurrentLink = CurrentLink->ForwardLink;
502
Returns the handle of the ACPI object representing the specified ACPI AML path
504
@param[in] AmlHandle Points to the handle of the object representing the starting point for the path search.
505
@param[in] AmlPath Points to the ACPI AML path.
506
@param[out] Buffer On return, points to the ACPI object which represents AcpiPath, relative to
508
@param[in] FromRoot TRUE means to find AML path from \ (Root) Node.
509
FALSE means to find AML path from this Node (The HandleIn).
511
@retval EFI_SUCCESS Success
512
@retval EFI_INVALID_PARAMETER HandleIn does not refer to a valid ACPI object.
516
IN EFI_AML_HANDLE *AmlHandle,
522
EFI_AML_NODE_LIST *AmlRootNodeList;
524
EFI_AML_NODE_LIST *AmlNodeList;
525
UINT8 RootNameSeg[AML_NAME_SEG_SIZE];
526
EFI_AML_NODE_LIST *CurrentAmlNodeList;
527
LIST_ENTRY *CurrentLink;
534
// Create root handle
536
RootNameSeg[0] = AML_ROOT_CHAR;
538
AmlRootNodeList = AmlCreateNode (RootNameSeg, NULL, AmlHandle->AmlByteEncoding);
540
Status = AmlConstructNodeList (
542
AmlRootNodeList, // Root
543
AmlRootNodeList // Parent
545
if (EFI_ERROR (Status)) {
546
return EFI_INVALID_PARAMETER;
550
DEBUG ((EFI_D_ERROR, "AcpiSdt: NameSpace:\n"));
551
AmlDumpNodeInfo (AmlRootNodeList, 0);
555
// 2. Search the node in the tree
561
CurrentAmlNodeList = AmlRootNodeList;
564
// Search from this node, NOT ROOT.
565
// Since we insert node to ROOT one by one, we just get the first node and search from it.
567
CurrentLink = AmlRootNodeList->Children.ForwardLink;
568
if (CurrentLink != &AmlRootNodeList->Children) {
572
CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
577
CurrentAmlNodeList = NULL;
584
if (CurrentAmlNodeList != NULL) {
586
DEBUG ((EFI_D_ERROR, "AcpiSdt: Search from: \\"));
587
AmlPrintNameSeg (CurrentAmlNodeList->Name);
588
DEBUG ((EFI_D_ERROR, "\n"));
590
AmlNodeList = AmlFindNodeInTheTree (
592
AmlRootNodeList, // Root
593
CurrentAmlNodeList, // Parent
601
Status = EFI_SUCCESS;
602
if (AmlNodeList != NULL && AmlNodeList->Buffer != NULL) {
603
*Buffer = AmlNodeList->Buffer;
609
AmlDestructNodeList (AmlRootNodeList);