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