]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlNamespace.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AmlNamespace.c
CommitLineData
3dc8585e
JY
1/** @file\r
2 ACPI Sdt Protocol Driver\r
3\r
d1102dba 4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>\r
3dc8585e
JY
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "AcpiTable.h"\r
16\r
17/**\r
18 Construct node list according to the AML handle.\r
d1102dba 19\r
3dc8585e
JY
20 @param[in] AmlHandle AML handle.\r
21 @param[in] AmlRootNodeList AML root node list.\r
22 @param[in] AmlParentNodeList AML parent node list.\r
d1102dba 23\r
3dc8585e
JY
24 @retval EFI_SUCCESS Success.\r
25 @retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.\r
26**/\r
27EFI_STATUS\r
28AmlConstructNodeList (\r
29 IN EFI_AML_HANDLE *AmlHandle,\r
30 IN EFI_AML_NODE_LIST *AmlRootNodeList,\r
31 IN EFI_AML_NODE_LIST *AmlParentNodeList\r
32 );\r
33\r
34/**\r
35 Create AML Node.\r
d1102dba 36\r
3dc8585e
JY
37 @param[in] NameSeg AML NameSeg.\r
38 @param[in] Parent AML parent node list.\r
39 @param[in] AmlByteEncoding AML Byte Encoding.\r
d1102dba 40\r
3dc8585e
JY
41 @return AML Node.\r
42**/\r
43EFI_AML_NODE_LIST *\r
44AmlCreateNode (\r
45 IN UINT8 *NameSeg,\r
46 IN EFI_AML_NODE_LIST *Parent,\r
47 IN AML_BYTE_ENCODING *AmlByteEncoding\r
48 )\r
49{\r
50 EFI_AML_NODE_LIST *AmlNodeList;\r
51\r
52 AmlNodeList = AllocatePool (sizeof(*AmlNodeList));\r
53 ASSERT (AmlNodeList != NULL);\r
54\r
55 AmlNodeList->Signature = EFI_AML_NODE_LIST_SIGNATURE;\r
56 CopyMem (AmlNodeList->Name, NameSeg, AML_NAME_SEG_SIZE);\r
57 AmlNodeList->Buffer = NULL;\r
58 AmlNodeList->Size = 0;\r
59 InitializeListHead (&AmlNodeList->Link);\r
60 InitializeListHead (&AmlNodeList->Children);\r
61 AmlNodeList->Parent = Parent;\r
62 AmlNodeList->AmlByteEncoding = AmlByteEncoding;\r
63\r
64 return AmlNodeList;\r
65}\r
66\r
67/**\r
68 Find the AML NameSeg in the children of AmlParentNodeList.\r
d1102dba 69\r
3dc8585e
JY
70 @param[in] NameSeg AML NameSeg.\r
71 @param[in] AmlParentNodeList AML parent node list.\r
72 @param[in] Create TRUE means to create node if not found.\r
d1102dba 73\r
3dc8585e
JY
74 @return AmlChildNode whoes name is same as NameSeg.\r
75**/\r
76EFI_AML_NODE_LIST *\r
77AmlFindNodeInThis (\r
78 IN UINT8 *NameSeg,\r
79 IN EFI_AML_NODE_LIST *AmlParentNodeList,\r
80 IN BOOLEAN Create\r
81 )\r
82{\r
83 EFI_AML_NODE_LIST *CurrentAmlNodeList;\r
84 LIST_ENTRY *CurrentLink;\r
85 LIST_ENTRY *StartLink;\r
86 EFI_AML_NODE_LIST *AmlNodeList;\r
87\r
88 StartLink = &AmlParentNodeList->Children;\r
89 CurrentLink = StartLink->ForwardLink;\r
90\r
91 while (CurrentLink != StartLink) {\r
92 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);\r
93 //\r
94 // AML name is same as the one stored\r
95 //\r
96 if (CompareMem (CurrentAmlNodeList->Name, NameSeg, AML_NAME_SEG_SIZE) == 0) {\r
97 //\r
98 // Good! Found it\r
99 //\r
100 return CurrentAmlNodeList;\r
101 }\r
102 CurrentLink = CurrentLink->ForwardLink;\r
103 }\r
104\r
105 //\r
106 // Not found\r
107 //\r
108 if (!Create) {\r
109 return NULL;\r
110 }\r
111\r
112 //\r
113 // Create new node with NULL buffer - it means namespace not be returned.\r
114 //\r
115 AmlNodeList = AmlCreateNode (NameSeg, AmlParentNodeList, NULL);\r
116 InsertTailList (&AmlParentNodeList->Children, &AmlNodeList->Link);\r
117\r
118 return AmlNodeList;\r
119}\r
120\r
121/**\r
122 Find the AML NameString in the children of AmlParentNodeList or AmlRootNodeList.\r
d1102dba 123\r
3dc8585e
JY
124 @param[in] NameString AML NameString.\r
125 @param[in] AmlRootNodeList AML root node list.\r
126 @param[in] AmlParentNodeList AML parent node list.\r
127 @param[in] Create TRUE means to create node if not found.\r
d1102dba 128\r
3dc8585e
JY
129 @return AmlChildNode whoes name is same as NameSeg.\r
130**/\r
131EFI_AML_NODE_LIST *\r
132AmlFindNodeInTheTree (\r
133 IN UINT8 *NameString,\r
134 IN EFI_AML_NODE_LIST *AmlRootNodeList,\r
135 IN EFI_AML_NODE_LIST *AmlParentNodeList,\r
136 IN BOOLEAN Create\r
137 )\r
138{\r
139 UINT8 *Buffer;\r
140 EFI_AML_NODE_LIST *AmlNodeList;\r
141 EFI_AML_NODE_LIST *AmlCurrentNodeList;\r
142 UINT8 Index;\r
143 UINT8 SegCount;\r
144\r
145 Buffer = NameString;\r
146\r
147 //\r
148 // Handle root or parent prefix\r
149 //\r
150 if (*Buffer == AML_ROOT_CHAR) {\r
151 AmlCurrentNodeList = AmlRootNodeList;\r
152 Buffer += 1;\r
153 } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {\r
154 AmlCurrentNodeList = AmlParentNodeList;\r
155 do {\r
156 if (AmlCurrentNodeList->Parent != NULL) {\r
157 AmlCurrentNodeList = AmlCurrentNodeList->Parent;\r
158 } else {\r
159 //\r
160 // Only root has no parent\r
161 //\r
162 ASSERT (AmlCurrentNodeList == AmlRootNodeList);\r
163 }\r
164 Buffer += 1;\r
165 } while (*Buffer == AML_PARENT_PREFIX_CHAR);\r
166 } else {\r
167 AmlCurrentNodeList = AmlParentNodeList;\r
168 }\r
d1102dba 169\r
3dc8585e
JY
170 //\r
171 // Handle name segment\r
172 //\r
173 if (*Buffer == AML_DUAL_NAME_PREFIX) {\r
174 Buffer += 1;\r
175 SegCount = 2;\r
176 } else if (*Buffer == AML_MULTI_NAME_PREFIX) {\r
177 Buffer += 1;\r
178 SegCount = *Buffer;\r
179 Buffer += 1;\r
180 } else if (*Buffer == 0) {\r
181 //\r
182 // NULL name, only for Root\r
183 //\r
184 ASSERT (AmlCurrentNodeList == AmlRootNodeList);\r
185 return AmlCurrentNodeList;\r
186 } else {\r
187 SegCount = 1;\r
188 }\r
189\r
190 //\r
191 // Handle NamePath\r
192 //\r
193 Index = 0;\r
194 do {\r
195 AmlNodeList = AmlFindNodeInThis (Buffer, AmlCurrentNodeList, Create);\r
196 if (AmlNodeList == NULL) {\r
197 return NULL;\r
198 }\r
199 AmlCurrentNodeList = AmlNodeList;\r
200 Buffer += AML_NAME_SEG_SIZE;\r
201 Index ++;\r
202 } while (Index < SegCount);\r
203\r
204 return AmlNodeList;\r
205}\r
206\r
207/**\r
208 Insert the NameString to the AmlNodeList.\r
d1102dba 209\r
3dc8585e
JY
210 @param[in] NameString AML NameString.\r
211 @param[in] Buffer Buffer for the Node.\r
212 @param[in] Size Size for the Node.\r
213 @param[in] AmlRootNodeList AML root node list.\r
214 @param[in] AmlParentNodeList AML parent node list.\r
d1102dba 215\r
3dc8585e
JY
216 @return AmlChildNode whoes name is NameString.\r
217**/\r
218EFI_AML_NODE_LIST *\r
219AmlInsertNodeToTree (\r
220 IN UINT8 *NameString,\r
221 IN VOID *Buffer,\r
222 IN UINTN Size,\r
223 IN EFI_AML_NODE_LIST *AmlRootNodeList,\r
224 IN EFI_AML_NODE_LIST *AmlParentNodeList\r
225 )\r
226{\r
227 EFI_AML_NODE_LIST *AmlNodeList;\r
228\r
229 AmlNodeList = AmlFindNodeInTheTree (\r
230 NameString,\r
231 AmlRootNodeList,\r
232 AmlParentNodeList,\r
233 TRUE // Find and Create\r
234 );\r
235 ASSERT (AmlNodeList != NULL);\r
236 if (AmlNodeList == NULL) {\r
237 return NULL;\r
238 }\r
239\r
240 //\r
241 // Check buffer\r
242 //\r
243 if (AmlNodeList->Buffer == NULL) {\r
244 //\r
245 // NULL means new added one or SCOPE_OP\r
246 //\r
247 if (*(UINT8 *)Buffer != AML_SCOPE_OP) {\r
248 //\r
249 // We need check if new one is SCOPE_OP, because SCOPE_OP just means namespace, not a real device.\r
250 // We should not return SCOPE_OP.\r
251 //\r
252 AmlNodeList->Buffer = Buffer;\r
253 AmlNodeList->Size = Size;\r
254 AmlNodeList->AmlByteEncoding = AmlSearchByOpByte (Buffer);\r
255 }\r
256 return AmlNodeList;\r
257 }\r
258\r
259 //\r
260 // Already added\r
261 //\r
262 if (*(UINT8 *)Buffer == AML_SCOPE_OP) {\r
263 //\r
264 // The new one is SCOPE_OP, OK just return;\r
265 //\r
266 return AmlNodeList;\r
267 }\r
268\r
269 //\r
270 // Oops!!!, There must be something wrong.\r
271 //\r
272 DEBUG ((EFI_D_ERROR, "AML: Override Happen - %a!\n", NameString));\r
273 DEBUG ((EFI_D_ERROR, "AML: Existing Node - %x\n", AmlNodeList->Buffer));\r
274 DEBUG ((EFI_D_ERROR, "AML: New Buffer - %x\n", Buffer));\r
275\r
276 return NULL;\r
277}\r
278\r
279/**\r
280 Construct child node list according to the AML handle.\r
d1102dba 281\r
3dc8585e
JY
282 @param[in] AmlHandle AML handle.\r
283 @param[in] AmlRootNodeList AML root node list.\r
284 @param[in] AmlParentNodeList AML parent node list.\r
d1102dba 285\r
3dc8585e
JY
286 @retval EFI_SUCCESS Success.\r
287 @retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.\r
288**/\r
289EFI_STATUS\r
290AmlConstructNodeListForChild (\r
291 IN EFI_AML_HANDLE *AmlHandle,\r
292 IN EFI_AML_NODE_LIST *AmlRootNodeList,\r
293 IN EFI_AML_NODE_LIST *AmlParentNodeList\r
294 )\r
295{\r
296 AML_BYTE_ENCODING *AmlByteEncoding;\r
297 UINT8 *Buffer;\r
298 UINTN BufferSize;\r
299 UINT8 *CurrentBuffer;\r
300 EFI_AML_HANDLE *AmlChildHandle;\r
301 EFI_STATUS Status;\r
302\r
4e1005ec
ED
303 CurrentBuffer = NULL;\r
304 AmlChildHandle = NULL;\r
3dc8585e
JY
305 AmlByteEncoding = AmlHandle->AmlByteEncoding;\r
306 Buffer = AmlHandle->Buffer;\r
307 BufferSize = AmlHandle->Size;\r
308\r
309 //\r
310 // Check if we need recursively add node\r
311 //\r
312 if ((AmlByteEncoding->Attribute & AML_HAS_CHILD_OBJ) == 0) {\r
313 //\r
314 // No more node need to be added\r
315 //\r
316 return EFI_SUCCESS;\r
317 }\r
318\r
319 //\r
320 // Do we need add node within METHOD?\r
321 // Yes, just add Object is OK. But we need filter NameString for METHOD invoke.\r
322 //\r
323\r
324 //\r
325 // Now, we get the last node.\r
326 //\r
327 Status = AmlGetOffsetAfterLastOption (AmlHandle, &CurrentBuffer);\r
328 if (EFI_ERROR (Status)) {\r
329 return EFI_INVALID_PARAMETER;\r
330 }\r
331\r
332 //\r
333 // Go through all the reset buffer.\r
334 //\r
335 while ((UINTN)CurrentBuffer < (UINTN)Buffer + BufferSize) {\r
336 //\r
337 // Find the child node.\r
338 //\r
339 Status = SdtOpenEx (CurrentBuffer, (UINTN)Buffer + BufferSize - (UINTN)CurrentBuffer, (EFI_ACPI_HANDLE *)&AmlChildHandle);\r
340 if (EFI_ERROR (Status)) {\r
341 //\r
342 // No child found, break now.\r
343 //\r
344 break;\r
345 }\r
346\r
347 //\r
348 // Good, find the child. Construct node recursively\r
349 //\r
350 Status = AmlConstructNodeList (\r
351 AmlChildHandle,\r
352 AmlRootNodeList,\r
353 AmlParentNodeList\r
354 );\r
355 if (EFI_ERROR (Status)) {\r
356 break;\r
357 }\r
358\r
359 //\r
360 // Parse next one\r
361 //\r
362 CurrentBuffer += AmlChildHandle->Size;\r
363\r
364 Close ((EFI_ACPI_HANDLE)AmlChildHandle);\r
365 }\r
366\r
367 return EFI_SUCCESS;\r
368}\r
369\r
370/**\r
371 Construct node list according to the AML handle.\r
d1102dba 372\r
3dc8585e
JY
373 @param[in] AmlHandle AML handle.\r
374 @param[in] AmlRootNodeList AML root node list.\r
375 @param[in] AmlParentNodeList AML parent node list.\r
d1102dba 376\r
3dc8585e
JY
377 @retval EFI_SUCCESS Success.\r
378 @retval EFI_INVALID_PARAMETER AML handle does not refer to a valid ACPI object.\r
379**/\r
380EFI_STATUS\r
381AmlConstructNodeList (\r
382 IN EFI_AML_HANDLE *AmlHandle,\r
383 IN EFI_AML_NODE_LIST *AmlRootNodeList,\r
384 IN EFI_AML_NODE_LIST *AmlParentNodeList\r
385 )\r
386{\r
387 VOID *NameString;\r
388 EFI_AML_NODE_LIST *AmlNodeList;\r
389\r
390 //\r
391 // 1. Check if there is need to construct node for this OpCode.\r
392 //\r
393 if ((AmlHandle->AmlByteEncoding->Attribute & AML_IN_NAMESPACE) == 0) {\r
394 //\r
395 // No need to construct node, so we just skip this OpCode.\r
396 //\r
397 return EFI_SUCCESS;\r
398 }\r
399\r
400 //\r
401 // 2. Now, we need construct node for this OpCode.\r
402 //\r
403 NameString = AmlGetObjectName (AmlHandle);\r
404 if (NameString == NULL) {\r
405 return EFI_INVALID_PARAMETER;\r
406 }\r
407\r
408 //\r
409 // Now, we need to insert node to the node list.\r
410 // NOTE: The name here could be AML NameString. So the callee need parse it.\r
411 //\r
412 AmlNodeList = AmlInsertNodeToTree (NameString, AmlHandle->Buffer, AmlHandle->Size, AmlRootNodeList, AmlParentNodeList);\r
413 ASSERT (AmlNodeList != NULL);\r
414\r
415 //\r
416 // 3. Ok, we need to parse the object list to see if there are more node to be added.\r
417 //\r
418 return AmlConstructNodeListForChild (AmlHandle, AmlRootNodeList, AmlNodeList);\r
419}\r
420\r
421/**\r
422 Destruct node list\r
d1102dba 423\r
3dc8585e
JY
424 @param[in] AmlParentNodeList AML parent node list.\r
425**/\r
426VOID\r
427AmlDestructNodeList (\r
428 IN EFI_AML_NODE_LIST *AmlParentNodeList\r
429 )\r
430{\r
431 EFI_AML_NODE_LIST *CurrentAmlNodeList;\r
432 LIST_ENTRY *CurrentLink;\r
433 LIST_ENTRY *StartLink;\r
434\r
435 //\r
436 // Get the children link\r
437 //\r
438 StartLink = &AmlParentNodeList->Children;\r
439 CurrentLink = StartLink->ForwardLink;\r
440\r
441 //\r
442 // Go through all the children\r
443 //\r
444 while (CurrentLink != StartLink) {\r
445 //\r
446 // Destruct the child's list recursively\r
447 //\r
448 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);\r
449 CurrentLink = CurrentLink->ForwardLink;\r
450\r
451 //\r
452 // Remove this child from list and free the node\r
453 //\r
454 RemoveEntryList (&(CurrentAmlNodeList->Link));\r
455\r
456 AmlDestructNodeList (CurrentAmlNodeList);\r
457 }\r
458\r
459 //\r
460 // Done.\r
461 //\r
462 FreePool (AmlParentNodeList);\r
463 return ;\r
464}\r
465\r
466/**\r
467 Dump node list\r
d1102dba 468\r
3dc8585e
JY
469 @param[in] AmlParentNodeList AML parent node list.\r
470 @param[in] Level Output debug level.\r
471**/\r
472VOID\r
473AmlDumpNodeInfo (\r
474 IN EFI_AML_NODE_LIST *AmlParentNodeList,\r
475 IN UINTN Level\r
476 )\r
477{\r
478 EFI_AML_NODE_LIST *CurrentAmlNodeList;\r
479 volatile LIST_ENTRY *CurrentLink;\r
480 UINTN Index;\r
481\r
482 CurrentLink = AmlParentNodeList->Children.ForwardLink;\r
483\r
484 if (Level == 0) {\r
485 DEBUG ((EFI_D_ERROR, "\\"));\r
486 } else {\r
487 for (Index = 0; Index < Level; Index++) {\r
488 DEBUG ((EFI_D_ERROR, " "));\r
489 }\r
490 AmlPrintNameSeg (AmlParentNodeList->Name);\r
491 }\r
492 DEBUG ((EFI_D_ERROR, "\n"));\r
493\r
494 while (CurrentLink != &AmlParentNodeList->Children) {\r
495 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);\r
496 AmlDumpNodeInfo (CurrentAmlNodeList, Level + 1);\r
497 CurrentLink = CurrentLink->ForwardLink;\r
498 }\r
499\r
500 return ;\r
501}\r
502\r
503/**\r
504 Returns the handle of the ACPI object representing the specified ACPI AML path\r
d1102dba 505\r
3dc8585e
JY
506 @param[in] AmlHandle Points to the handle of the object representing the starting point for the path search.\r
507 @param[in] AmlPath Points to the ACPI AML path.\r
508 @param[out] Buffer On return, points to the ACPI object which represents AcpiPath, relative to\r
509 HandleIn.\r
510 @param[in] FromRoot TRUE means to find AML path from \ (Root) Node.\r
511 FALSE means to find AML path from this Node (The HandleIn).\r
d1102dba 512\r
3dc8585e 513 @retval EFI_SUCCESS Success\r
d1102dba 514 @retval EFI_INVALID_PARAMETER HandleIn does not refer to a valid ACPI object.\r
3dc8585e
JY
515**/\r
516EFI_STATUS\r
517AmlFindPath (\r
518 IN EFI_AML_HANDLE *AmlHandle,\r
519 IN UINT8 *AmlPath,\r
520 OUT VOID **Buffer,\r
521 IN BOOLEAN FromRoot\r
522 )\r
523{\r
524 EFI_AML_NODE_LIST *AmlRootNodeList;\r
525 EFI_STATUS Status;\r
526 EFI_AML_NODE_LIST *AmlNodeList;\r
527 UINT8 RootNameSeg[AML_NAME_SEG_SIZE];\r
528 EFI_AML_NODE_LIST *CurrentAmlNodeList;\r
529 LIST_ENTRY *CurrentLink;\r
530\r
531 //\r
532 // 1. create tree\r
533 //\r
534\r
535 //\r
536 // Create root handle\r
537 //\r
538 RootNameSeg[0] = AML_ROOT_CHAR;\r
539 RootNameSeg[1] = 0;\r
540 AmlRootNodeList = AmlCreateNode (RootNameSeg, NULL, AmlHandle->AmlByteEncoding);\r
541\r
542 Status = AmlConstructNodeList (\r
543 AmlHandle,\r
544 AmlRootNodeList, // Root\r
545 AmlRootNodeList // Parent\r
546 );\r
547 if (EFI_ERROR (Status)) {\r
548 return EFI_INVALID_PARAMETER;\r
549 }\r
550\r
551 DEBUG_CODE_BEGIN ();\r
552 DEBUG ((EFI_D_ERROR, "AcpiSdt: NameSpace:\n"));\r
553 AmlDumpNodeInfo (AmlRootNodeList, 0);\r
554 DEBUG_CODE_END ();\r
555\r
556 //\r
557 // 2. Search the node in the tree\r
558 //\r
559 if (FromRoot) {\r
560 //\r
561 // Search from Root\r
562 //\r
563 CurrentAmlNodeList = AmlRootNodeList;\r
564 } else {\r
565 //\r
566 // Search from this node, NOT ROOT.\r
567 // Since we insert node to ROOT one by one, we just get the first node and search from it.\r
568 //\r
569 CurrentLink = AmlRootNodeList->Children.ForwardLink;\r
570 if (CurrentLink != &AmlRootNodeList->Children) {\r
571 //\r
572 // First node\r
573 //\r
574 CurrentAmlNodeList = EFI_AML_NODE_LIST_FROM_LINK (CurrentLink);\r
575 } else {\r
576 //\r
577 // No child\r
578 //\r
579 CurrentAmlNodeList = NULL;\r
580 }\r
581 }\r
582\r
583 //\r
584 // Search\r
585 //\r
586 if (CurrentAmlNodeList != NULL) {\r
587 DEBUG_CODE_BEGIN ();\r
588 DEBUG ((EFI_D_ERROR, "AcpiSdt: Search from: \\"));\r
589 AmlPrintNameSeg (CurrentAmlNodeList->Name);\r
590 DEBUG ((EFI_D_ERROR, "\n"));\r
591 DEBUG_CODE_END ();\r
592 AmlNodeList = AmlFindNodeInTheTree (\r
593 AmlPath,\r
594 AmlRootNodeList, // Root\r
595 CurrentAmlNodeList, // Parent\r
596 FALSE\r
597 );\r
598 } else {\r
599 AmlNodeList = NULL;\r
600 }\r
601\r
602 *Buffer = NULL;\r
603 Status = EFI_SUCCESS;\r
604 if (AmlNodeList != NULL && AmlNodeList->Buffer != NULL) {\r
605 *Buffer = AmlNodeList->Buffer;\r
606 }\r
607\r
608 //\r
609 // 3. free the tree\r
610 //\r
611 AmlDestructNodeList (AmlRootNodeList);\r
612\r
613 return Status;\r
614}\r