2 ACPI Sdt Protocol Driver
4 Copyright (c) 2010 - 2014, 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 CurrentBuffer
= NULL
;
304 AmlChildHandle
= NULL
;
305 AmlByteEncoding
= AmlHandle
->AmlByteEncoding
;
306 Buffer
= AmlHandle
->Buffer
;
307 BufferSize
= AmlHandle
->Size
;
310 // Check if we need recursively add node
312 if ((AmlByteEncoding
->Attribute
& AML_HAS_CHILD_OBJ
) == 0) {
314 // No more node need to be added
320 // Do we need add node within METHOD?
321 // Yes, just add Object is OK. But we need filter NameString for METHOD invoke.
325 // Now, we get the last node.
327 Status
= AmlGetOffsetAfterLastOption (AmlHandle
, &CurrentBuffer
);
328 if (EFI_ERROR (Status
)) {
329 return EFI_INVALID_PARAMETER
;
333 // Go through all the reset buffer.
335 while ((UINTN
)CurrentBuffer
< (UINTN
)Buffer
+ BufferSize
) {
337 // Find the child node.
339 Status
= SdtOpenEx (CurrentBuffer
, (UINTN
)Buffer
+ BufferSize
- (UINTN
)CurrentBuffer
, (EFI_ACPI_HANDLE
*)&AmlChildHandle
);
340 if (EFI_ERROR (Status
)) {
342 // No child found, break now.
348 // Good, find the child. Construct node recursively
350 Status
= AmlConstructNodeList (
355 if (EFI_ERROR (Status
)) {
362 CurrentBuffer
+= AmlChildHandle
->Size
;
364 Close ((EFI_ACPI_HANDLE
)AmlChildHandle
);
371 Construct node list according to the AML handle.
373 @param[in] AmlHandle AML handle.
374 @param[in] AmlRootNodeList AML root node list.
375 @param[in] AmlParentNodeList AML parent node list.
377 @retval EFI_SUCCESS Success.
378 @retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.
381 AmlConstructNodeList (
382 IN EFI_AML_HANDLE
*AmlHandle
,
383 IN EFI_AML_NODE_LIST
*AmlRootNodeList
,
384 IN EFI_AML_NODE_LIST
*AmlParentNodeList
388 EFI_AML_NODE_LIST
*AmlNodeList
;
391 // 1. Check if there is need to construct node for this OpCode.
393 if ((AmlHandle
->AmlByteEncoding
->Attribute
& AML_IN_NAMESPACE
) == 0) {
395 // No need to construct node, so we just skip this OpCode.
401 // 2. Now, we need construct node for this OpCode.
403 NameString
= AmlGetObjectName (AmlHandle
);
404 if (NameString
== NULL
) {
405 return EFI_INVALID_PARAMETER
;
409 // Now, we need to insert node to the node list.
410 // NOTE: The name here could be AML NameString. So the callee need parse it.
412 AmlNodeList
= AmlInsertNodeToTree (NameString
, AmlHandle
->Buffer
, AmlHandle
->Size
, AmlRootNodeList
, AmlParentNodeList
);
413 ASSERT (AmlNodeList
!= NULL
);
416 // 3. Ok, we need to parse the object list to see if there are more node to be added.
418 return AmlConstructNodeListForChild (AmlHandle
, AmlRootNodeList
, AmlNodeList
);
424 @param[in] AmlParentNodeList AML parent node list.
427 AmlDestructNodeList (
428 IN EFI_AML_NODE_LIST
*AmlParentNodeList
431 EFI_AML_NODE_LIST
*CurrentAmlNodeList
;
432 LIST_ENTRY
*CurrentLink
;
433 LIST_ENTRY
*StartLink
;
436 // Get the children link
438 StartLink
= &AmlParentNodeList
->Children
;
439 CurrentLink
= StartLink
->ForwardLink
;
442 // Go through all the children
444 while (CurrentLink
!= StartLink
) {
446 // Destruct the child's list recursively
448 CurrentAmlNodeList
= EFI_AML_NODE_LIST_FROM_LINK (CurrentLink
);
449 CurrentLink
= CurrentLink
->ForwardLink
;
452 // Remove this child from list and free the node
454 RemoveEntryList (&(CurrentAmlNodeList
->Link
));
456 AmlDestructNodeList (CurrentAmlNodeList
);
462 FreePool (AmlParentNodeList
);
469 @param[in] AmlParentNodeList AML parent node list.
470 @param[in] Level Output debug level.
474 IN EFI_AML_NODE_LIST
*AmlParentNodeList
,
478 EFI_AML_NODE_LIST
*CurrentAmlNodeList
;
479 volatile LIST_ENTRY
*CurrentLink
;
482 CurrentLink
= AmlParentNodeList
->Children
.ForwardLink
;
485 DEBUG ((EFI_D_ERROR
, "\\"));
487 for (Index
= 0; Index
< Level
; Index
++) {
488 DEBUG ((EFI_D_ERROR
, " "));
490 AmlPrintNameSeg (AmlParentNodeList
->Name
);
492 DEBUG ((EFI_D_ERROR
, "\n"));
494 while (CurrentLink
!= &AmlParentNodeList
->Children
) {
495 CurrentAmlNodeList
= EFI_AML_NODE_LIST_FROM_LINK (CurrentLink
);
496 AmlDumpNodeInfo (CurrentAmlNodeList
, Level
+ 1);
497 CurrentLink
= CurrentLink
->ForwardLink
;
504 Returns the handle of the ACPI object representing the specified ACPI AML path
506 @param[in] AmlHandle Points to the handle of the object representing the starting point for the path search.
507 @param[in] AmlPath Points to the ACPI AML path.
508 @param[out] Buffer On return, points to the ACPI object which represents AcpiPath, relative to
510 @param[in] FromRoot TRUE means to find AML path from \ (Root) Node.
511 FALSE means to find AML path from this Node (The HandleIn).
513 @retval EFI_SUCCESS Success
514 @retval EFI_INVALID_PARAMETER HandleIn does not refer to a valid ACPI object.
518 IN EFI_AML_HANDLE
*AmlHandle
,
524 EFI_AML_NODE_LIST
*AmlRootNodeList
;
526 EFI_AML_NODE_LIST
*AmlNodeList
;
527 UINT8 RootNameSeg
[AML_NAME_SEG_SIZE
];
528 EFI_AML_NODE_LIST
*CurrentAmlNodeList
;
529 LIST_ENTRY
*CurrentLink
;
536 // Create root handle
538 RootNameSeg
[0] = AML_ROOT_CHAR
;
540 AmlRootNodeList
= AmlCreateNode (RootNameSeg
, NULL
, AmlHandle
->AmlByteEncoding
);
542 Status
= AmlConstructNodeList (
544 AmlRootNodeList
, // Root
545 AmlRootNodeList
// Parent
547 if (EFI_ERROR (Status
)) {
548 return EFI_INVALID_PARAMETER
;
552 DEBUG ((EFI_D_ERROR
, "AcpiSdt: NameSpace:\n"));
553 AmlDumpNodeInfo (AmlRootNodeList
, 0);
557 // 2. Search the node in the tree
563 CurrentAmlNodeList
= AmlRootNodeList
;
566 // Search from this node, NOT ROOT.
567 // Since we insert node to ROOT one by one, we just get the first node and search from it.
569 CurrentLink
= AmlRootNodeList
->Children
.ForwardLink
;
570 if (CurrentLink
!= &AmlRootNodeList
->Children
) {
574 CurrentAmlNodeList
= EFI_AML_NODE_LIST_FROM_LINK (CurrentLink
);
579 CurrentAmlNodeList
= NULL
;
586 if (CurrentAmlNodeList
!= NULL
) {
588 DEBUG ((EFI_D_ERROR
, "AcpiSdt: Search from: \\"));
589 AmlPrintNameSeg (CurrentAmlNodeList
->Name
);
590 DEBUG ((EFI_D_ERROR
, "\n"));
592 AmlNodeList
= AmlFindNodeInTheTree (
594 AmlRootNodeList
, // Root
595 CurrentAmlNodeList
, // Parent
603 Status
= EFI_SUCCESS
;
604 if (AmlNodeList
!= NULL
&& AmlNodeList
->Buffer
!= NULL
) {
605 *Buffer
= AmlNodeList
->Buffer
;
611 AmlDestructNodeList (AmlRootNodeList
);