TianoCore EDK2 master
Loading...
Searching...
No Matches
AmlNamespace.c
Go to the documentation of this file.
1
9#include "AcpiTable.h"
10
23 IN EFI_AML_HANDLE *AmlHandle,
24 IN EFI_AML_NODE_LIST *AmlRootNodeList,
25 IN EFI_AML_NODE_LIST *AmlParentNodeList
26 );
27
39 IN UINT8 *NameSeg,
40 IN EFI_AML_NODE_LIST *Parent,
41 IN AML_BYTE_ENCODING *AmlByteEncoding
42 )
43{
44 EFI_AML_NODE_LIST *AmlNodeList;
45
46 AmlNodeList = AllocatePool (sizeof (*AmlNodeList));
47 if (AmlNodeList == NULL) {
48 ASSERT (AmlNodeList != NULL);
49 return NULL;
50 }
51
52 AmlNodeList->Signature = EFI_AML_NODE_LIST_SIGNATURE;
53 CopyMem (AmlNodeList->Name, NameSeg, AML_NAME_SEG_SIZE);
54 AmlNodeList->Buffer = NULL;
55 AmlNodeList->Size = 0;
56 InitializeListHead (&AmlNodeList->Link);
57 InitializeListHead (&AmlNodeList->Children);
58 AmlNodeList->Parent = Parent;
59 AmlNodeList->AmlByteEncoding = AmlByteEncoding;
60
61 return AmlNodeList;
62}
63
75 IN UINT8 *NameSeg,
76 IN EFI_AML_NODE_LIST *AmlParentNodeList,
77 IN BOOLEAN Create
78 )
79{
80 EFI_AML_NODE_LIST *CurrentAmlNodeList;
81 LIST_ENTRY *CurrentLink;
82 LIST_ENTRY *StartLink;
83 EFI_AML_NODE_LIST *AmlNodeList;
84
85 StartLink = &AmlParentNodeList->Children;
86 CurrentLink = StartLink->ForwardLink;
87
88 while (CurrentLink != StartLink) {
89 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
90 //
91 // AML name is same as the one stored
92 //
93 if (CompareMem (CurrentAmlNodeList->Name, NameSeg, AML_NAME_SEG_SIZE) == 0) {
94 //
95 // Good! Found it
96 //
97 return CurrentAmlNodeList;
98 }
99
100 CurrentLink = CurrentLink->ForwardLink;
101 }
102
103 //
104 // Not found
105 //
106 if (!Create) {
107 return NULL;
108 }
109
110 //
111 // Create new node with NULL buffer - it means namespace not be returned.
112 //
113 AmlNodeList = AmlCreateNode (NameSeg, AmlParentNodeList, NULL);
114 if (AmlNodeList == NULL) {
115 return NULL;
116 }
117
118 InsertTailList (&AmlParentNodeList->Children, &AmlNodeList->Link);
119
120 return AmlNodeList;
121}
122
135 IN UINT8 *NameString,
136 IN EFI_AML_NODE_LIST *AmlRootNodeList,
137 IN EFI_AML_NODE_LIST *AmlParentNodeList,
138 IN BOOLEAN Create
139 )
140{
141 UINT8 *Buffer;
142 EFI_AML_NODE_LIST *AmlNodeList;
143 EFI_AML_NODE_LIST *AmlCurrentNodeList;
144 UINT8 Index;
145 UINT8 SegCount;
146
147 Buffer = NameString;
148
149 //
150 // Handle root or parent prefix
151 //
152 if (*Buffer == AML_ROOT_CHAR) {
153 AmlCurrentNodeList = AmlRootNodeList;
154 Buffer += 1;
155 } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
156 AmlCurrentNodeList = AmlParentNodeList;
157 do {
158 if (AmlCurrentNodeList->Parent != NULL) {
159 AmlCurrentNodeList = AmlCurrentNodeList->Parent;
160 } else {
161 //
162 // Only root has no parent
163 //
164 ASSERT (AmlCurrentNodeList == AmlRootNodeList);
165 }
166
167 Buffer += 1;
168 } while (*Buffer == AML_PARENT_PREFIX_CHAR);
169 } else {
170 AmlCurrentNodeList = AmlParentNodeList;
171 }
172
173 //
174 // Handle name segment
175 //
176 if (*Buffer == AML_DUAL_NAME_PREFIX) {
177 Buffer += 1;
178 SegCount = 2;
179 } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
180 Buffer += 1;
181 SegCount = *Buffer;
182 Buffer += 1;
183 } else if (*Buffer == 0) {
184 //
185 // NULL name, only for Root
186 //
187 ASSERT (AmlCurrentNodeList == AmlRootNodeList);
188 return AmlCurrentNodeList;
189 } else {
190 SegCount = 1;
191 }
192
193 //
194 // Handle NamePath
195 //
196 Index = 0;
197 do {
198 AmlNodeList = AmlFindNodeInThis (Buffer, AmlCurrentNodeList, Create);
199 if (AmlNodeList == NULL) {
200 return NULL;
201 }
202
203 AmlCurrentNodeList = AmlNodeList;
204 Buffer += AML_NAME_SEG_SIZE;
205 Index++;
206 } while (Index < SegCount);
207
208 return AmlNodeList;
209}
210
224 IN UINT8 *NameString,
225 IN VOID *Buffer,
226 IN UINTN Size,
227 IN EFI_AML_NODE_LIST *AmlRootNodeList,
228 IN EFI_AML_NODE_LIST *AmlParentNodeList
229 )
230{
231 EFI_AML_NODE_LIST *AmlNodeList;
232
233 AmlNodeList = AmlFindNodeInTheTree (
234 NameString,
235 AmlRootNodeList,
236 AmlParentNodeList,
237 TRUE // Find and Create
238 );
239 ASSERT (AmlNodeList != NULL);
240 if (AmlNodeList == NULL) {
241 return NULL;
242 }
243
244 //
245 // Check buffer
246 //
247 if (AmlNodeList->Buffer == NULL) {
248 //
249 // NULL means new added one or SCOPE_OP
250 //
251 if (*(UINT8 *)Buffer != AML_SCOPE_OP) {
252 //
253 // We need check if new one is SCOPE_OP, because SCOPE_OP just means namespace, not a real device.
254 // We should not return SCOPE_OP.
255 //
256 AmlNodeList->Buffer = Buffer;
257 AmlNodeList->Size = Size;
258 AmlNodeList->AmlByteEncoding = AmlSearchByOpByte (Buffer);
259 }
260
261 return AmlNodeList;
262 }
263
264 //
265 // Already added
266 //
267 if (*(UINT8 *)Buffer == AML_SCOPE_OP) {
268 //
269 // The new one is SCOPE_OP, OK just return;
270 //
271 return AmlNodeList;
272 }
273
274 //
275 // Oops!!!, There must be something wrong.
276 //
277 DEBUG ((DEBUG_ERROR, "AML: Override Happen - %a!\n", NameString));
278 DEBUG ((DEBUG_ERROR, "AML: Existing Node - %x\n", AmlNodeList->Buffer));
279 DEBUG ((DEBUG_ERROR, "AML: New Buffer - %x\n", Buffer));
280
281 return NULL;
282}
283
296 IN EFI_AML_HANDLE *AmlHandle,
297 IN EFI_AML_NODE_LIST *AmlRootNodeList,
298 IN EFI_AML_NODE_LIST *AmlParentNodeList
299 )
300{
301 AML_BYTE_ENCODING *AmlByteEncoding;
302 UINT8 *Buffer;
303 UINTN BufferSize;
304 UINT8 *CurrentBuffer;
305 EFI_AML_HANDLE *AmlChildHandle;
306 EFI_STATUS Status;
307
308 CurrentBuffer = NULL;
309 AmlChildHandle = NULL;
310 AmlByteEncoding = AmlHandle->AmlByteEncoding;
311 Buffer = AmlHandle->Buffer;
312 BufferSize = AmlHandle->Size;
313
314 //
315 // Check if we need recursively add node
316 //
317 if ((AmlByteEncoding->Attribute & AML_HAS_CHILD_OBJ) == 0) {
318 //
319 // No more node need to be added
320 //
321 return EFI_SUCCESS;
322 }
323
324 //
325 // Do we need add node within METHOD?
326 // Yes, just add Object is OK. But we need filter NameString for METHOD invoke.
327 //
328
329 //
330 // Now, we get the last node.
331 //
332 Status = AmlGetOffsetAfterLastOption (AmlHandle, &CurrentBuffer);
333 if (EFI_ERROR (Status)) {
334 return EFI_INVALID_PARAMETER;
335 }
336
337 //
338 // Go through all the reset buffer.
339 //
340 while ((UINTN)CurrentBuffer < (UINTN)Buffer + BufferSize) {
341 //
342 // Find the child node.
343 //
344 Status = SdtOpenEx (CurrentBuffer, (UINTN)Buffer + BufferSize - (UINTN)CurrentBuffer, (EFI_ACPI_HANDLE *)&AmlChildHandle);
345 if (EFI_ERROR (Status)) {
346 //
347 // No child found, break now.
348 //
349 break;
350 }
351
352 //
353 // Good, find the child. Construct node recursively
354 //
355 Status = AmlConstructNodeList (
356 AmlChildHandle,
357 AmlRootNodeList,
358 AmlParentNodeList
359 );
360 if (EFI_ERROR (Status)) {
361 break;
362 }
363
364 //
365 // Parse next one
366 //
367 CurrentBuffer += AmlChildHandle->Size;
368
369 Close ((EFI_ACPI_HANDLE)AmlChildHandle);
370 }
371
372 return EFI_SUCCESS;
373}
374
387 IN EFI_AML_HANDLE *AmlHandle,
388 IN EFI_AML_NODE_LIST *AmlRootNodeList,
389 IN EFI_AML_NODE_LIST *AmlParentNodeList
390 )
391{
392 VOID *NameString;
393 EFI_AML_NODE_LIST *AmlNodeList;
394
395 //
396 // 1. Check if there is need to construct node for this OpCode.
397 //
398 if ((AmlHandle->AmlByteEncoding->Attribute & AML_IN_NAMESPACE) == 0) {
399 //
400 // No need to construct node, so we just skip this OpCode.
401 //
402 return EFI_SUCCESS;
403 }
404
405 //
406 // 2. Now, we need construct node for this OpCode.
407 //
408 NameString = AmlGetObjectName (AmlHandle);
409 if (NameString == NULL) {
410 return EFI_INVALID_PARAMETER;
411 }
412
413 //
414 // Now, we need to insert node to the node list.
415 // NOTE: The name here could be AML NameString. So the callee need parse it.
416 //
417 AmlNodeList = AmlInsertNodeToTree (NameString, AmlHandle->Buffer, AmlHandle->Size, AmlRootNodeList, AmlParentNodeList);
418 ASSERT (AmlNodeList != NULL);
419
420 //
421 // 3. Ok, we need to parse the object list to see if there are more node to be added.
422 //
423 return AmlConstructNodeListForChild (AmlHandle, AmlRootNodeList, AmlNodeList);
424}
425
431VOID
433 IN EFI_AML_NODE_LIST *AmlParentNodeList
434 )
435{
436 EFI_AML_NODE_LIST *CurrentAmlNodeList;
437 LIST_ENTRY *CurrentLink;
438 LIST_ENTRY *StartLink;
439
440 //
441 // Get the children link
442 //
443 StartLink = &AmlParentNodeList->Children;
444 CurrentLink = StartLink->ForwardLink;
445
446 //
447 // Go through all the children
448 //
449 while (CurrentLink != StartLink) {
450 //
451 // Destruct the child's list recursively
452 //
453 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
454 CurrentLink = CurrentLink->ForwardLink;
455
456 //
457 // Remove this child from list and free the node
458 //
459 RemoveEntryList (&(CurrentAmlNodeList->Link));
460
461 AmlDestructNodeList (CurrentAmlNodeList);
462 }
463
464 //
465 // Done.
466 //
467 FreePool (AmlParentNodeList);
468 return;
469}
470
477VOID
479 IN EFI_AML_NODE_LIST *AmlParentNodeList,
480 IN UINTN Level
481 )
482{
483 EFI_AML_NODE_LIST *CurrentAmlNodeList;
484 volatile LIST_ENTRY *CurrentLink;
485 UINTN Index;
486
487 CurrentLink = AmlParentNodeList->Children.ForwardLink;
488
489 if (Level == 0) {
490 DEBUG ((DEBUG_ERROR, "\\"));
491 } else {
492 for (Index = 0; Index < Level; Index++) {
493 DEBUG ((DEBUG_ERROR, " "));
494 }
495
496 AmlPrintNameSeg (AmlParentNodeList->Name);
497 }
498
499 DEBUG ((DEBUG_ERROR, "\n"));
500
501 while (CurrentLink != &AmlParentNodeList->Children) {
502 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
503 AmlDumpNodeInfo (CurrentAmlNodeList, Level + 1);
504 CurrentLink = CurrentLink->ForwardLink;
505 }
506
507 return;
508}
509
526 IN EFI_AML_HANDLE *AmlHandle,
527 IN UINT8 *AmlPath,
528 OUT VOID **Buffer,
529 IN BOOLEAN FromRoot
530 )
531{
532 EFI_AML_NODE_LIST *AmlRootNodeList;
533 EFI_STATUS Status;
534 EFI_AML_NODE_LIST *AmlNodeList;
535 UINT8 RootNameSeg[AML_NAME_SEG_SIZE];
536 EFI_AML_NODE_LIST *CurrentAmlNodeList;
537 LIST_ENTRY *CurrentLink;
538
539 //
540 // 1. create tree
541 //
542
543 //
544 // Create root handle
545 //
546 RootNameSeg[0] = AML_ROOT_CHAR;
547 RootNameSeg[1] = 0;
548 AmlRootNodeList = AmlCreateNode (RootNameSeg, NULL, AmlHandle->AmlByteEncoding);
549 if (AmlRootNodeList == NULL) {
550 return EFI_OUT_OF_RESOURCES;
551 }
552
553 Status = AmlConstructNodeList (
554 AmlHandle,
555 AmlRootNodeList, // Root
556 AmlRootNodeList // Parent
557 );
558 if (EFI_ERROR (Status)) {
559 return EFI_INVALID_PARAMETER;
560 }
561
563 DEBUG ((DEBUG_ERROR, "AcpiSdt: NameSpace:\n"));
564 AmlDumpNodeInfo (AmlRootNodeList, 0);
566
567 //
568 // 2. Search the node in the tree
569 //
570 if (FromRoot) {
571 //
572 // Search from Root
573 //
574 CurrentAmlNodeList = AmlRootNodeList;
575 } else {
576 //
577 // Search from this node, NOT ROOT.
578 // Since we insert node to ROOT one by one, we just get the first node and search from it.
579 //
580 CurrentLink = AmlRootNodeList->Children.ForwardLink;
581 if (CurrentLink != &AmlRootNodeList->Children) {
582 //
583 // First node
584 //
585 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);
586 } else {
587 //
588 // No child
589 //
590 CurrentAmlNodeList = NULL;
591 }
592 }
593
594 //
595 // Search
596 //
597 if (CurrentAmlNodeList != NULL) {
599 DEBUG ((DEBUG_ERROR, "AcpiSdt: Search from: \\"));
600 AmlPrintNameSeg (CurrentAmlNodeList->Name);
601 DEBUG ((DEBUG_ERROR, "\n"));
603 AmlNodeList = AmlFindNodeInTheTree (
604 AmlPath,
605 AmlRootNodeList, // Root
606 CurrentAmlNodeList, // Parent
607 FALSE
608 );
609 } else {
610 AmlNodeList = NULL;
611 }
612
613 *Buffer = NULL;
614 Status = EFI_SUCCESS;
615 if ((AmlNodeList != NULL) && (AmlNodeList->Buffer != NULL)) {
616 *Buffer = AmlNodeList->Buffer;
617 }
618
619 //
620 // 3. free the tree
621 //
622 AmlDestructNodeList (AmlRootNodeList);
623
624 return Status;
625}
UINT64 UINTN
EFI_STATUS SdtOpenEx(IN VOID *Buffer, IN UINTN BufferSize, OUT EFI_ACPI_HANDLE *Handle)
Definition: AcpiSdt.c:546
EFI_STATUS EFIAPI Close(IN EFI_ACPI_HANDLE Handle)
Definition: AcpiSdt.c:640
CHAR8 * AmlGetObjectName(IN EFI_AML_HANDLE *AmlHandle)
Definition: AmlOption.c:341
VOID AmlPrintNameSeg(IN UINT8 *Buffer)
Definition: AmlString.c:469
AML_BYTE_ENCODING * AmlSearchByOpByte(IN UINT8 *OpByteBuffer)
Definition: Aml.c:180
EFI_STATUS AmlGetOffsetAfterLastOption(IN EFI_AML_HANDLE *AmlHandle, OUT UINT8 **Buffer)
Definition: AmlOption.c:398
#define AML_HAS_CHILD_OBJ
Definition: Aml.h:75
#define AML_IN_NAMESPACE
Definition: Aml.h:98
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS AmlConstructNodeList(IN EFI_AML_HANDLE *AmlHandle, IN EFI_AML_NODE_LIST *AmlRootNodeList, IN EFI_AML_NODE_LIST *AmlParentNodeList)
Definition: AmlNamespace.c:386
EFI_STATUS AmlFindPath(IN EFI_AML_HANDLE *AmlHandle, IN UINT8 *AmlPath, OUT VOID **Buffer, IN BOOLEAN FromRoot)
Definition: AmlNamespace.c:525
EFI_AML_NODE_LIST * AmlFindNodeInTheTree(IN UINT8 *NameString, IN EFI_AML_NODE_LIST *AmlRootNodeList, IN EFI_AML_NODE_LIST *AmlParentNodeList, IN BOOLEAN Create)
Definition: AmlNamespace.c:134
EFI_AML_NODE_LIST * AmlFindNodeInThis(IN UINT8 *NameSeg, IN EFI_AML_NODE_LIST *AmlParentNodeList, IN BOOLEAN Create)
Definition: AmlNamespace.c:74
EFI_AML_NODE_LIST * AmlCreateNode(IN UINT8 *NameSeg, IN EFI_AML_NODE_LIST *Parent, IN AML_BYTE_ENCODING *AmlByteEncoding)
Definition: AmlNamespace.c:38
EFI_STATUS AmlConstructNodeListForChild(IN EFI_AML_HANDLE *AmlHandle, IN EFI_AML_NODE_LIST *AmlRootNodeList, IN EFI_AML_NODE_LIST *AmlParentNodeList)
Definition: AmlNamespace.c:295
EFI_AML_NODE_LIST * AmlInsertNodeToTree(IN UINT8 *NameString, IN VOID *Buffer, IN UINTN Size, IN EFI_AML_NODE_LIST *AmlRootNodeList, IN EFI_AML_NODE_LIST *AmlParentNodeList)
Definition: AmlNamespace.c:223
VOID AmlDestructNodeList(IN EFI_AML_NODE_LIST *AmlParentNodeList)
Definition: AmlNamespace.c:432
VOID AmlDumpNodeInfo(IN EFI_AML_NODE_LIST *AmlParentNodeList, IN UINTN Level)
Definition: AmlNamespace.c:478
#define NULL
Definition: Base.h:319
#define VOID
Definition: Base.h:269
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:565
#define DEBUG(Expression)
Definition: DebugLib.h:435
#define DEBUG_CODE_END()
Definition: DebugLib.h:579
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
AML_OP_ATTRIBUTE Attribute
Additional information on the AML object.
Definition: Aml.h:145