2 ACPI Sdt Protocol Driver
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Construct node list according to the AML handle.
14 @param[in] AmlHandle AML handle.
15 @param[in] AmlRootNodeList AML root node list.
16 @param[in] AmlParentNodeList AML parent node list.
18 @retval EFI_SUCCESS Success.
19 @retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.
22 AmlConstructNodeList (
23 IN EFI_AML_HANDLE
*AmlHandle
,
24 IN EFI_AML_NODE_LIST
*AmlRootNodeList
,
25 IN EFI_AML_NODE_LIST
*AmlParentNodeList
31 @param[in] NameSeg AML NameSeg.
32 @param[in] Parent AML parent node list.
33 @param[in] AmlByteEncoding AML Byte Encoding.
40 IN EFI_AML_NODE_LIST
*Parent
,
41 IN AML_BYTE_ENCODING
*AmlByteEncoding
44 EFI_AML_NODE_LIST
*AmlNodeList
;
46 AmlNodeList
= AllocatePool (sizeof(*AmlNodeList
));
47 ASSERT (AmlNodeList
!= NULL
);
49 AmlNodeList
->Signature
= EFI_AML_NODE_LIST_SIGNATURE
;
50 CopyMem (AmlNodeList
->Name
, NameSeg
, AML_NAME_SEG_SIZE
);
51 AmlNodeList
->Buffer
= NULL
;
52 AmlNodeList
->Size
= 0;
53 InitializeListHead (&AmlNodeList
->Link
);
54 InitializeListHead (&AmlNodeList
->Children
);
55 AmlNodeList
->Parent
= Parent
;
56 AmlNodeList
->AmlByteEncoding
= AmlByteEncoding
;
62 Find the AML NameSeg in the children of AmlParentNodeList.
64 @param[in] NameSeg AML NameSeg.
65 @param[in] AmlParentNodeList AML parent node list.
66 @param[in] Create TRUE means to create node if not found.
68 @return AmlChildNode whoes name is same as NameSeg.
73 IN EFI_AML_NODE_LIST
*AmlParentNodeList
,
77 EFI_AML_NODE_LIST
*CurrentAmlNodeList
;
78 LIST_ENTRY
*CurrentLink
;
79 LIST_ENTRY
*StartLink
;
80 EFI_AML_NODE_LIST
*AmlNodeList
;
82 StartLink
= &AmlParentNodeList
->Children
;
83 CurrentLink
= StartLink
->ForwardLink
;
85 while (CurrentLink
!= StartLink
) {
86 CurrentAmlNodeList
= EFI_AML_NODE_LIST_FROM_LINK (CurrentLink
);
88 // AML name is same as the one stored
90 if (CompareMem (CurrentAmlNodeList
->Name
, NameSeg
, AML_NAME_SEG_SIZE
) == 0) {
94 return CurrentAmlNodeList
;
96 CurrentLink
= CurrentLink
->ForwardLink
;
107 // Create new node with NULL buffer - it means namespace not be returned.
109 AmlNodeList
= AmlCreateNode (NameSeg
, AmlParentNodeList
, NULL
);
110 InsertTailList (&AmlParentNodeList
->Children
, &AmlNodeList
->Link
);
116 Find the AML NameString in the children of AmlParentNodeList or AmlRootNodeList.
118 @param[in] NameString AML NameString.
119 @param[in] AmlRootNodeList AML root node list.
120 @param[in] AmlParentNodeList AML parent node list.
121 @param[in] Create TRUE means to create node if not found.
123 @return AmlChildNode whoes name is same as NameSeg.
126 AmlFindNodeInTheTree (
127 IN UINT8
*NameString
,
128 IN EFI_AML_NODE_LIST
*AmlRootNodeList
,
129 IN EFI_AML_NODE_LIST
*AmlParentNodeList
,
134 EFI_AML_NODE_LIST
*AmlNodeList
;
135 EFI_AML_NODE_LIST
*AmlCurrentNodeList
;
142 // Handle root or parent prefix
144 if (*Buffer
== AML_ROOT_CHAR
) {
145 AmlCurrentNodeList
= AmlRootNodeList
;
147 } else if (*Buffer
== AML_PARENT_PREFIX_CHAR
) {
148 AmlCurrentNodeList
= AmlParentNodeList
;
150 if (AmlCurrentNodeList
->Parent
!= NULL
) {
151 AmlCurrentNodeList
= AmlCurrentNodeList
->Parent
;
154 // Only root has no parent
156 ASSERT (AmlCurrentNodeList
== AmlRootNodeList
);
159 } while (*Buffer
== AML_PARENT_PREFIX_CHAR
);
161 AmlCurrentNodeList
= AmlParentNodeList
;
165 // Handle name segment
167 if (*Buffer
== AML_DUAL_NAME_PREFIX
) {
170 } else if (*Buffer
== AML_MULTI_NAME_PREFIX
) {
174 } else if (*Buffer
== 0) {
176 // NULL name, only for Root
178 ASSERT (AmlCurrentNodeList
== AmlRootNodeList
);
179 return AmlCurrentNodeList
;
189 AmlNodeList
= AmlFindNodeInThis (Buffer
, AmlCurrentNodeList
, Create
);
190 if (AmlNodeList
== NULL
) {
193 AmlCurrentNodeList
= AmlNodeList
;
194 Buffer
+= AML_NAME_SEG_SIZE
;
196 } while (Index
< SegCount
);
202 Insert the NameString to the AmlNodeList.
204 @param[in] NameString AML NameString.
205 @param[in] Buffer Buffer for the Node.
206 @param[in] Size Size for the Node.
207 @param[in] AmlRootNodeList AML root node list.
208 @param[in] AmlParentNodeList AML parent node list.
210 @return AmlChildNode whoes name is NameString.
213 AmlInsertNodeToTree (
214 IN UINT8
*NameString
,
217 IN EFI_AML_NODE_LIST
*AmlRootNodeList
,
218 IN EFI_AML_NODE_LIST
*AmlParentNodeList
221 EFI_AML_NODE_LIST
*AmlNodeList
;
223 AmlNodeList
= AmlFindNodeInTheTree (
227 TRUE
// Find and Create
229 ASSERT (AmlNodeList
!= NULL
);
230 if (AmlNodeList
== NULL
) {
237 if (AmlNodeList
->Buffer
== NULL
) {
239 // NULL means new added one or SCOPE_OP
241 if (*(UINT8
*)Buffer
!= AML_SCOPE_OP
) {
243 // We need check if new one is SCOPE_OP, because SCOPE_OP just means namespace, not a real device.
244 // We should not return SCOPE_OP.
246 AmlNodeList
->Buffer
= Buffer
;
247 AmlNodeList
->Size
= Size
;
248 AmlNodeList
->AmlByteEncoding
= AmlSearchByOpByte (Buffer
);
256 if (*(UINT8
*)Buffer
== AML_SCOPE_OP
) {
258 // The new one is SCOPE_OP, OK just return;
264 // Oops!!!, There must be something wrong.
266 DEBUG ((DEBUG_ERROR
, "AML: Override Happen - %a!\n", NameString
));
267 DEBUG ((DEBUG_ERROR
, "AML: Existing Node - %x\n", AmlNodeList
->Buffer
));
268 DEBUG ((DEBUG_ERROR
, "AML: New Buffer - %x\n", Buffer
));
274 Construct child node list according to the AML handle.
276 @param[in] AmlHandle AML handle.
277 @param[in] AmlRootNodeList AML root node list.
278 @param[in] AmlParentNodeList AML parent node list.
280 @retval EFI_SUCCESS Success.
281 @retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.
284 AmlConstructNodeListForChild (
285 IN EFI_AML_HANDLE
*AmlHandle
,
286 IN EFI_AML_NODE_LIST
*AmlRootNodeList
,
287 IN EFI_AML_NODE_LIST
*AmlParentNodeList
290 AML_BYTE_ENCODING
*AmlByteEncoding
;
293 UINT8
*CurrentBuffer
;
294 EFI_AML_HANDLE
*AmlChildHandle
;
297 CurrentBuffer
= NULL
;
298 AmlChildHandle
= NULL
;
299 AmlByteEncoding
= AmlHandle
->AmlByteEncoding
;
300 Buffer
= AmlHandle
->Buffer
;
301 BufferSize
= AmlHandle
->Size
;
304 // Check if we need recursively add node
306 if ((AmlByteEncoding
->Attribute
& AML_HAS_CHILD_OBJ
) == 0) {
308 // No more node need to be added
314 // Do we need add node within METHOD?
315 // Yes, just add Object is OK. But we need filter NameString for METHOD invoke.
319 // Now, we get the last node.
321 Status
= AmlGetOffsetAfterLastOption (AmlHandle
, &CurrentBuffer
);
322 if (EFI_ERROR (Status
)) {
323 return EFI_INVALID_PARAMETER
;
327 // Go through all the reset buffer.
329 while ((UINTN
)CurrentBuffer
< (UINTN
)Buffer
+ BufferSize
) {
331 // Find the child node.
333 Status
= SdtOpenEx (CurrentBuffer
, (UINTN
)Buffer
+ BufferSize
- (UINTN
)CurrentBuffer
, (EFI_ACPI_HANDLE
*)&AmlChildHandle
);
334 if (EFI_ERROR (Status
)) {
336 // No child found, break now.
342 // Good, find the child. Construct node recursively
344 Status
= AmlConstructNodeList (
349 if (EFI_ERROR (Status
)) {
356 CurrentBuffer
+= AmlChildHandle
->Size
;
358 Close ((EFI_ACPI_HANDLE
)AmlChildHandle
);
365 Construct node list according to the AML handle.
367 @param[in] AmlHandle AML handle.
368 @param[in] AmlRootNodeList AML root node list.
369 @param[in] AmlParentNodeList AML parent node list.
371 @retval EFI_SUCCESS Success.
372 @retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.
375 AmlConstructNodeList (
376 IN EFI_AML_HANDLE
*AmlHandle
,
377 IN EFI_AML_NODE_LIST
*AmlRootNodeList
,
378 IN EFI_AML_NODE_LIST
*AmlParentNodeList
382 EFI_AML_NODE_LIST
*AmlNodeList
;
385 // 1. Check if there is need to construct node for this OpCode.
387 if ((AmlHandle
->AmlByteEncoding
->Attribute
& AML_IN_NAMESPACE
) == 0) {
389 // No need to construct node, so we just skip this OpCode.
395 // 2. Now, we need construct node for this OpCode.
397 NameString
= AmlGetObjectName (AmlHandle
);
398 if (NameString
== NULL
) {
399 return EFI_INVALID_PARAMETER
;
403 // Now, we need to insert node to the node list.
404 // NOTE: The name here could be AML NameString. So the callee need parse it.
406 AmlNodeList
= AmlInsertNodeToTree (NameString
, AmlHandle
->Buffer
, AmlHandle
->Size
, AmlRootNodeList
, AmlParentNodeList
);
407 ASSERT (AmlNodeList
!= NULL
);
410 // 3. Ok, we need to parse the object list to see if there are more node to be added.
412 return AmlConstructNodeListForChild (AmlHandle
, AmlRootNodeList
, AmlNodeList
);
418 @param[in] AmlParentNodeList AML parent node list.
421 AmlDestructNodeList (
422 IN EFI_AML_NODE_LIST
*AmlParentNodeList
425 EFI_AML_NODE_LIST
*CurrentAmlNodeList
;
426 LIST_ENTRY
*CurrentLink
;
427 LIST_ENTRY
*StartLink
;
430 // Get the children link
432 StartLink
= &AmlParentNodeList
->Children
;
433 CurrentLink
= StartLink
->ForwardLink
;
436 // Go through all the children
438 while (CurrentLink
!= StartLink
) {
440 // Destruct the child's list recursively
442 CurrentAmlNodeList
= EFI_AML_NODE_LIST_FROM_LINK (CurrentLink
);
443 CurrentLink
= CurrentLink
->ForwardLink
;
446 // Remove this child from list and free the node
448 RemoveEntryList (&(CurrentAmlNodeList
->Link
));
450 AmlDestructNodeList (CurrentAmlNodeList
);
456 FreePool (AmlParentNodeList
);
463 @param[in] AmlParentNodeList AML parent node list.
464 @param[in] Level Output debug level.
468 IN EFI_AML_NODE_LIST
*AmlParentNodeList
,
472 EFI_AML_NODE_LIST
*CurrentAmlNodeList
;
473 volatile LIST_ENTRY
*CurrentLink
;
476 CurrentLink
= AmlParentNodeList
->Children
.ForwardLink
;
479 DEBUG ((DEBUG_ERROR
, "\\"));
481 for (Index
= 0; Index
< Level
; Index
++) {
482 DEBUG ((DEBUG_ERROR
, " "));
484 AmlPrintNameSeg (AmlParentNodeList
->Name
);
486 DEBUG ((DEBUG_ERROR
, "\n"));
488 while (CurrentLink
!= &AmlParentNodeList
->Children
) {
489 CurrentAmlNodeList
= EFI_AML_NODE_LIST_FROM_LINK (CurrentLink
);
490 AmlDumpNodeInfo (CurrentAmlNodeList
, Level
+ 1);
491 CurrentLink
= CurrentLink
->ForwardLink
;
498 Returns the handle of the ACPI object representing the specified ACPI AML path
500 @param[in] AmlHandle Points to the handle of the object representing the starting point for the path search.
501 @param[in] AmlPath Points to the ACPI AML path.
502 @param[out] Buffer On return, points to the ACPI object which represents AcpiPath, relative to
504 @param[in] FromRoot TRUE means to find AML path from \ (Root) Node.
505 FALSE means to find AML path from this Node (The HandleIn).
507 @retval EFI_SUCCESS Success
508 @retval EFI_INVALID_PARAMETER HandleIn does not refer to a valid ACPI object.
512 IN EFI_AML_HANDLE
*AmlHandle
,
518 EFI_AML_NODE_LIST
*AmlRootNodeList
;
520 EFI_AML_NODE_LIST
*AmlNodeList
;
521 UINT8 RootNameSeg
[AML_NAME_SEG_SIZE
];
522 EFI_AML_NODE_LIST
*CurrentAmlNodeList
;
523 LIST_ENTRY
*CurrentLink
;
530 // Create root handle
532 RootNameSeg
[0] = AML_ROOT_CHAR
;
534 AmlRootNodeList
= AmlCreateNode (RootNameSeg
, NULL
, AmlHandle
->AmlByteEncoding
);
536 Status
= AmlConstructNodeList (
538 AmlRootNodeList
, // Root
539 AmlRootNodeList
// Parent
541 if (EFI_ERROR (Status
)) {
542 return EFI_INVALID_PARAMETER
;
546 DEBUG ((DEBUG_ERROR
, "AcpiSdt: NameSpace:\n"));
547 AmlDumpNodeInfo (AmlRootNodeList
, 0);
551 // 2. Search the node in the tree
557 CurrentAmlNodeList
= AmlRootNodeList
;
560 // Search from this node, NOT ROOT.
561 // Since we insert node to ROOT one by one, we just get the first node and search from it.
563 CurrentLink
= AmlRootNodeList
->Children
.ForwardLink
;
564 if (CurrentLink
!= &AmlRootNodeList
->Children
) {
568 CurrentAmlNodeList
= EFI_AML_NODE_LIST_FROM_LINK (CurrentLink
);
573 CurrentAmlNodeList
= NULL
;
580 if (CurrentAmlNodeList
!= NULL
) {
582 DEBUG ((DEBUG_ERROR
, "AcpiSdt: Search from: \\"));
583 AmlPrintNameSeg (CurrentAmlNodeList
->Name
);
584 DEBUG ((DEBUG_ERROR
, "\n"));
586 AmlNodeList
= AmlFindNodeInTheTree (
588 AmlRootNodeList
, // Root
589 CurrentAmlNodeList
, // Parent
597 Status
= EFI_SUCCESS
;
598 if (AmlNodeList
!= NULL
&& AmlNodeList
->Buffer
!= NULL
) {
599 *Buffer
= AmlNodeList
->Buffer
;
605 AmlDestructNodeList (AmlRootNodeList
);