]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiSdt.c
Add missing parameter in functions header.
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AcpiSdt.c
CommitLineData
3dc8585e
JY
1/** @file\r
2 ACPI Sdt Protocol Driver\r
3\r
4 Copyright (c) 2010, Intel Corporation. All rights reserved. <BR>\r
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//\r
16// Includes\r
17//\r
18#include "AcpiTable.h"\r
19\r
20GLOBAL_REMOVE_IF_UNREFERENCED\r
21EFI_ACPI_SDT_PROTOCOL mAcpiSdtProtocolTemplate = {\r
22 EFI_ACPI_TABLE_VERSION_NONE | EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0 | EFI_ACPI_TABLE_VERSION_4_0,\r
23 GetAcpiTable2,\r
24 RegisterNotify,\r
25 Open,\r
26 OpenSdt,\r
27 Close,\r
28 GetChild,\r
29 GetOption,\r
30 SetOption,\r
31 FindPath\r
32};\r
33\r
34/**\r
35 This function returns ACPI Table instance.\r
36\r
37 @return AcpiTableInstance\r
38**/\r
39EFI_ACPI_TABLE_INSTANCE *\r
40SdtGetAcpiTableInstance (\r
41 VOID\r
42 )\r
43{\r
44 return mPrivateData;\r
45}\r
46\r
47/**\r
48 This function finds the table specified by the buffer.\r
49\r
50 @param[in] Buffer Table buffer to find.\r
51\r
52 @return ACPI table list.\r
53**/\r
54EFI_ACPI_TABLE_LIST *\r
55FindTableByBuffer (\r
56 IN VOID *Buffer\r
57 )\r
58{\r
59 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;\r
60 LIST_ENTRY *CurrentLink;\r
61 EFI_ACPI_TABLE_LIST *CurrentTableList;\r
62 LIST_ENTRY *StartLink;\r
63\r
64 //\r
65 // Get the instance of the ACPI Table\r
66 //\r
67 AcpiTableInstance = SdtGetAcpiTableInstance ();\r
68\r
69 //\r
70 // Find the notify\r
71 //\r
72 StartLink = &AcpiTableInstance->TableList;\r
73 CurrentLink = StartLink->ForwardLink;\r
74\r
75 while (CurrentLink != StartLink) {\r
76 CurrentTableList = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);\r
77 if (((UINTN)CurrentTableList->PageAddress <= (UINTN)Buffer) &&\r
78 ((UINTN)CurrentTableList->PageAddress + EFI_PAGES_TO_SIZE(CurrentTableList->NumberOfPages) > (UINTN)Buffer)) {\r
79 //\r
80 // Good! Found Table.\r
81 //\r
82 return CurrentTableList;\r
83 }\r
84\r
85 CurrentLink = CurrentLink->ForwardLink;\r
86 }\r
87\r
88 return NULL;\r
89}\r
90\r
91/**\r
92 This function updates AML table checksum.\r
93 It will search the ACPI table installed by ACPI_TABLE protocol.\r
94\r
95 @param[in] Buffer A piece of AML code buffer pointer.\r
96\r
97 @retval EFI_SUCCESS The table holds the AML buffer is found, and checksum is updated.\r
98 @retval EFI_NOT_FOUND The table holds the AML buffer is not found.\r
99**/\r
100EFI_STATUS\r
101SdtUpdateAmlChecksum (\r
102 IN VOID *Buffer\r
103 )\r
104{\r
105 EFI_ACPI_TABLE_LIST *CurrentTableList;\r
106\r
107 CurrentTableList = FindTableByBuffer (Buffer);\r
108 if (CurrentTableList == NULL) {\r
109 return EFI_NOT_FOUND;\r
110 }\r
111\r
112 AcpiPlatformChecksum (\r
113 (VOID *)CurrentTableList->Table,\r
114 CurrentTableList->Table->Length,\r
115 OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum)\r
116 );\r
117 return EFI_SUCCESS;\r
118}\r
119\r
120/**\r
121 This function finds MAX AML buffer size.\r
122 It will search the ACPI table installed by ACPI_TABLE protocol.\r
123\r
124 @param[in] Buffer A piece of AML code buffer pointer.\r
125 @param[out] MaxSize On return it holds the MAX size of buffer.\r
126\r
127 @retval EFI_SUCCESS The table holds the AML buffer is found, and MAX size if returned.\r
128 @retval EFI_NOT_FOUND The table holds the AML buffer is not found.\r
129**/\r
130EFI_STATUS\r
131SdtGetMaxAmlBufferSize (\r
132 IN VOID *Buffer,\r
133 OUT UINTN *MaxSize\r
134 )\r
135{\r
136 EFI_ACPI_TABLE_LIST *CurrentTableList;\r
137\r
138 CurrentTableList = FindTableByBuffer (Buffer);\r
139 if (CurrentTableList == NULL) {\r
140 return EFI_NOT_FOUND;\r
141 }\r
142\r
143 *MaxSize = (UINTN)CurrentTableList->Table + CurrentTableList->Table->Length - (UINTN)Buffer;\r
144 return EFI_SUCCESS;\r
145}\r
146\r
147/**\r
148 This function invokes ACPI notification.\r
149\r
150 @param[in] AcpiTableInstance Instance to AcpiTable\r
151 @param[in] Version Version(s) to set.\r
152 @param[in] Handle Handle of the table.\r
153**/\r
154VOID\r
155SdtNotifyAcpiList (\r
156 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,\r
157 IN EFI_ACPI_TABLE_VERSION Version,\r
158 IN UINTN Handle\r
159 )\r
160{\r
161 EFI_ACPI_NOTIFY_LIST *CurrentNotifyList;\r
162 LIST_ENTRY *CurrentLink;\r
163 LIST_ENTRY *StartLink;\r
164 EFI_ACPI_TABLE_LIST *Table;\r
165 EFI_STATUS Status;\r
166\r
167 //\r
168 // We should not use Table buffer, because it is user input buffer.\r
169 //\r
170 Status = FindTableByHandle (\r
171 Handle,\r
172 &AcpiTableInstance->TableList,\r
173 &Table\r
174 );\r
175 ASSERT_EFI_ERROR (Status);\r
176\r
177 //\r
178 // Find the notify\r
179 //\r
180 StartLink = &AcpiTableInstance->NotifyList;\r
181 CurrentLink = StartLink->ForwardLink;\r
182\r
183 while (CurrentLink != StartLink) {\r
184 CurrentNotifyList = EFI_ACPI_NOTIFY_LIST_FROM_LINK (CurrentLink);\r
185\r
186 //\r
187 // Inovke notification\r
188 //\r
189 CurrentNotifyList->Notification ((EFI_ACPI_SDT_HEADER *)Table->Table, Version, Handle);\r
190\r
191 CurrentLink = CurrentLink->ForwardLink;\r
192 }\r
193\r
194 return ;\r
195}\r
196\r
197/**\r
198 Returns a requested ACPI table.\r
199 \r
200 The GetAcpiTable() function returns a pointer to a buffer containing the ACPI table associated\r
201 with the Index that was input. The following structures are not considered elements in the list of\r
202 ACPI tables:\r
203 - Root System Description Pointer (RSD_PTR)\r
204 - Root System Description Table (RSDT)\r
205 - Extended System Description Table (XSDT)\r
206 Version is updated with a bit map containing all the versions of ACPI of which the table is a\r
207 member.\r
208 \r
209 @param[in] Index The zero-based index of the table to retrieve.\r
210 @param[out] Table Pointer for returning the table buffer.\r
211 @param[out] Version On return, updated with the ACPI versions to which this table belongs. Type\r
212 EFI_ACPI_TABLE_VERSION is defined in "Related Definitions" in the\r
213 EFI_ACPI_SDT_PROTOCOL. \r
214 @param[out] TableKey On return, points to the table key for the specified ACPI system definition table. This\r
215 is identical to the table key used in the EFI_ACPI_TABLE_PROTOCOL. \r
216 \r
217 @retval EFI_SUCCESS The function completed successfully.\r
218 @retval EFI_NOT_FOUND The requested index is too large and a table was not found. \r
219**/ \r
220EFI_STATUS\r
221EFIAPI\r
222GetAcpiTable2 (\r
223 IN UINTN Index,\r
224 OUT EFI_ACPI_SDT_HEADER **Table,\r
225 OUT EFI_ACPI_TABLE_VERSION *Version,\r
226 OUT UINTN *TableKey\r
227 )\r
228{\r
229 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;\r
230 UINTN TableIndex;\r
231 LIST_ENTRY *CurrentLink;\r
232 LIST_ENTRY *StartLink;\r
233 EFI_ACPI_TABLE_LIST *CurrentTable;\r
234\r
235 ASSERT (Table != NULL);\r
236 ASSERT (Version != NULL);\r
237 ASSERT (TableKey != NULL);\r
238\r
239 //\r
240 // Get the instance of the ACPI Table\r
241 //\r
242 AcpiTableInstance = SdtGetAcpiTableInstance ();\r
243\r
244 //\r
245 // Find the table\r
246 //\r
247 StartLink = &AcpiTableInstance->TableList;\r
248 CurrentLink = StartLink->ForwardLink;\r
249 TableIndex = 0;\r
250\r
251 while (CurrentLink != StartLink) {\r
252 if (TableIndex == Index) {\r
253 break;\r
254 }\r
255 //\r
256 // Next one\r
257 //\r
258 CurrentLink = CurrentLink->ForwardLink;\r
259 TableIndex ++;\r
260 }\r
261\r
262 if ((TableIndex != Index) || (CurrentLink == StartLink)) {\r
263 return EFI_NOT_FOUND;\r
264 }\r
265\r
266 //\r
267 // Get handle and version\r
268 //\r
269 CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);\r
270 *TableKey = CurrentTable->Handle;\r
271 *Version = CurrentTable->Version;\r
272 *Table = (EFI_ACPI_SDT_HEADER *)CurrentTable->Table;\r
273\r
274 return EFI_SUCCESS;\r
275}\r
276\r
277/**\r
278 Register a callback when an ACPI table is installed.\r
279 \r
280 This function registers a function which will be called whenever a new ACPI table is installed.\r
281 \r
282 @param[in] Notification Points to the callback function to be registered\r
283**/\r
284VOID\r
285SdtRegisterNotify (\r
286 IN EFI_ACPI_NOTIFICATION_FN Notification\r
287 )\r
288{\r
289 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;\r
290 EFI_ACPI_NOTIFY_LIST *CurrentNotifyList;\r
291\r
292 //\r
293 // Get the instance of the ACPI Table\r
294 //\r
295 AcpiTableInstance = SdtGetAcpiTableInstance ();\r
296\r
297 //\r
298 // Create a new list entry\r
299 //\r
300 CurrentNotifyList = AllocatePool (sizeof (EFI_ACPI_NOTIFY_LIST));\r
301 ASSERT (CurrentNotifyList != NULL);\r
302\r
303 //\r
304 // Initialize the table contents\r
305 //\r
306 CurrentNotifyList->Signature = EFI_ACPI_NOTIFY_LIST_SIGNATURE;\r
307 CurrentNotifyList->Notification = Notification;\r
308\r
309 //\r
310 // Add the table to the current list of tables\r
311 //\r
312 InsertTailList (&AcpiTableInstance->NotifyList, &CurrentNotifyList->Link);\r
313\r
314 return ;\r
315}\r
316\r
317/**\r
318 Unregister a callback when an ACPI table is installed.\r
319 \r
320 This function unregisters a function which will be called whenever a new ACPI table is installed.\r
321 \r
322 @param[in] Notification Points to the callback function to be unregistered.\r
323 \r
324 @retval EFI_SUCCESS Callback successfully unregistered.\r
325 @retval EFI_INVALID_PARAMETER Notification does not match a known registration function. \r
326**/\r
327EFI_STATUS\r
328SdtUnregisterNotify (\r
329 IN EFI_ACPI_NOTIFICATION_FN Notification\r
330 )\r
331{\r
332 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;\r
333 EFI_ACPI_NOTIFY_LIST *CurrentNotifyList;\r
334 LIST_ENTRY *CurrentLink;\r
335 LIST_ENTRY *StartLink;\r
336\r
337 //\r
338 // Get the instance of the ACPI Table\r
339 //\r
340 AcpiTableInstance = SdtGetAcpiTableInstance ();\r
341\r
342 //\r
343 // Find the notify\r
344 //\r
345 StartLink = &AcpiTableInstance->NotifyList;\r
346 CurrentLink = StartLink->ForwardLink;\r
347\r
348 while (CurrentLink != StartLink) {\r
349 CurrentNotifyList = EFI_ACPI_NOTIFY_LIST_FROM_LINK (CurrentLink);\r
350 if (CurrentNotifyList->Notification == Notification) {\r
351 //\r
352 // Good! Found notification.\r
353 //\r
354 // Remove it from list and free the node.\r
355 //\r
356 RemoveEntryList (&(CurrentNotifyList->Link));\r
357 FreePool (CurrentNotifyList);\r
358 return EFI_SUCCESS;\r
359 }\r
360\r
361 CurrentLink = CurrentLink->ForwardLink;\r
362 }\r
363\r
364 //\r
365 // Not found!\r
366 //\r
367 return EFI_INVALID_PARAMETER;\r
368}\r
369\r
370/**\r
371 Register or unregister a callback when an ACPI table is installed.\r
372 \r
373 This function registers or unregisters a function which will be called whenever a new ACPI table is\r
374 installed.\r
375 \r
376 @param[in] Register If TRUE, then the specified function will be registered. If FALSE, then the specified\r
377 function will be unregistered.\r
378 @param[in] Notification Points to the callback function to be registered or unregistered.\r
379 \r
380 @retval EFI_SUCCESS Callback successfully registered or unregistered.\r
381 @retval EFI_INVALID_PARAMETER Notification is NULL\r
382 @retval EFI_INVALID_PARAMETER Register is FALSE and Notification does not match a known registration function. \r
383**/\r
384EFI_STATUS\r
385EFIAPI\r
386RegisterNotify (\r
387 IN BOOLEAN Register,\r
388 IN EFI_ACPI_NOTIFICATION_FN Notification\r
389 )\r
390{\r
391 //\r
392 // Check for invalid input parameters\r
393 //\r
394 if (Notification == NULL) {\r
395 return EFI_INVALID_PARAMETER;\r
396 }\r
397\r
398 if (Register) {\r
399 //\r
400 // Register a new notify\r
401 //\r
402 SdtRegisterNotify (Notification);\r
403 return EFI_SUCCESS;\r
404 } else {\r
405 //\r
406 // Unregister an old notify\r
407 //\r
408 return SdtUnregisterNotify (Notification);\r
409 }\r
410}\r
411\r
412/**\r
413 Create a handle for the first ACPI opcode in an ACPI system description table.\r
414 \r
415 @param[in] TableKey The table key for the ACPI table, as returned by GetTable().\r
416 @param[out] Handle On return, points to the newly created ACPI handle.\r
417\r
418 @retval EFI_SUCCESS Handle created successfully.\r
419 @retval EFI_NOT_FOUND TableKey does not refer to a valid ACPI table. \r
420**/\r
421EFI_STATUS\r
422SdtOpenSdtTable (\r
423 IN UINTN TableKey,\r
424 OUT EFI_ACPI_HANDLE *Handle\r
425 )\r
426{\r
427 EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance;\r
428 EFI_STATUS Status;\r
429 EFI_ACPI_TABLE_LIST *Table;\r
430 EFI_AML_HANDLE *AmlHandle;\r
431\r
432 //\r
433 // Get the instance of the ACPI Table\r
434 //\r
435 AcpiTableInstance = SdtGetAcpiTableInstance ();\r
436\r
437 //\r
438 // Find the table\r
439 //\r
440 Status = FindTableByHandle (\r
441 TableKey,\r
442 &AcpiTableInstance->TableList,\r
443 &Table\r
444 );\r
445 if (EFI_ERROR (Status)) {\r
446 return EFI_NOT_FOUND;\r
447 }\r
448\r
449 AmlHandle = AllocatePool (sizeof(*AmlHandle));\r
450 ASSERT (AmlHandle != NULL);\r
451 AmlHandle->Signature = EFI_AML_ROOT_HANDLE_SIGNATURE;\r
452 AmlHandle->Buffer = (VOID *)((UINTN)Table->Table + sizeof(EFI_ACPI_SDT_HEADER));\r
453 AmlHandle->Size = Table->Table->Length - sizeof(EFI_ACPI_SDT_HEADER);\r
454 AmlHandle->AmlByteEncoding = NULL;\r
455 AmlHandle->Modified = FALSE;\r
456\r
457 //\r
458 // return the ACPI handle\r
459 //\r
460 *Handle = (EFI_ACPI_HANDLE)AmlHandle;\r
461\r
462 return EFI_SUCCESS;\r
463}\r
464\r
465/**\r
466 Create a handle for the first ACPI opcode in an ACPI system description table.\r
467 \r
468 @param[in] TableKey The table key for the ACPI table, as returned by GetTable().\r
469 @param[out] Handle On return, points to the newly created ACPI handle.\r
470\r
471 @retval EFI_SUCCESS Handle created successfully.\r
472 @retval EFI_NOT_FOUND TableKey does not refer to a valid ACPI table. \r
473**/\r
474EFI_STATUS\r
475EFIAPI\r
476OpenSdt (\r
477 IN UINTN TableKey,\r
478 OUT EFI_ACPI_HANDLE *Handle\r
479 )\r
480{\r
481 if (Handle == NULL) {\r
482 return EFI_INVALID_PARAMETER;\r
483 }\r
484\r
485 return SdtOpenSdtTable (TableKey, Handle);\r
486}\r
487\r
488/**\r
489 Create a handle from an ACPI opcode\r
490 \r
491 @param[in] Buffer Points to the ACPI opcode.\r
492 @param[in] BufferSize Max buffer size.\r
493 @param[out] Handle Upon return, holds the handle.\r
494 \r
495 @retval EFI_SUCCESS Success\r
496 @retval EFI_INVALID_PARAMETER Buffer is NULL or Handle is NULL or Buffer points to an\r
497 invalid opcode.\r
498 \r
499**/\r
500EFI_STATUS\r
501SdtOpenEx (\r
502 IN VOID *Buffer,\r
503 IN UINTN BufferSize,\r
504 OUT EFI_ACPI_HANDLE *Handle \r
505 )\r
506{\r
507 AML_BYTE_ENCODING *AmlByteEncoding;\r
508 EFI_AML_HANDLE *AmlHandle;\r
509\r
510 AmlByteEncoding = AmlSearchByOpByte (Buffer);\r
511 if (AmlByteEncoding == NULL) {\r
512 return EFI_INVALID_PARAMETER;\r
513 }\r
514\r
515 //\r
516 // Do not open NameString as handle\r
517 //\r
518 if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) != 0) {\r
519 return EFI_INVALID_PARAMETER;\r
520 }\r
521\r
522 //\r
523 // Good, find it\r
524 //\r
525 AmlHandle = AllocatePool (sizeof(*AmlHandle));\r
526 ASSERT (AmlHandle != NULL);\r
527 \r
528 AmlHandle->Signature = EFI_AML_HANDLE_SIGNATURE;\r
529 AmlHandle->Buffer = Buffer;\r
530 AmlHandle->AmlByteEncoding = AmlByteEncoding;\r
531 AmlHandle->Modified = FALSE;\r
532\r
533 AmlHandle->Size = AmlGetObjectSize (AmlByteEncoding, Buffer, BufferSize);\r
534 if (AmlHandle->Size == 0) {\r
535 FreePool (AmlHandle);\r
536 return EFI_INVALID_PARAMETER;\r
537 }\r
538\r
539 *Handle = (EFI_ACPI_HANDLE)AmlHandle;\r
540\r
541 return EFI_SUCCESS;\r
542}\r
543\r
544/**\r
545 Create a handle from an ACPI opcode\r
546 \r
547 @param[in] Buffer Points to the ACPI opcode.\r
548 @param[out] Handle Upon return, holds the handle.\r
549 \r
550 @retval EFI_SUCCESS Success\r
551 @retval EFI_INVALID_PARAMETER Buffer is NULL or Handle is NULL or Buffer points to an\r
552 invalid opcode.\r
553 \r
554**/\r
555EFI_STATUS\r
556EFIAPI\r
557Open (\r
558 IN VOID *Buffer,\r
559 OUT EFI_ACPI_HANDLE *Handle \r
560 )\r
561{\r
562 EFI_STATUS Status;\r
563 UINTN MaxSize;\r
564\r
a6bb62e4 565 MaxSize = 0;\r
566\r
3dc8585e
JY
567 //\r
568 // Check for invalid input parameters\r
569 //\r
570 if (Buffer == NULL || Handle == NULL) {\r
571 return EFI_INVALID_PARAMETER;\r
572 }\r
573\r
574 Status = SdtGetMaxAmlBufferSize (Buffer, &MaxSize);\r
575 if (EFI_ERROR (Status)) {\r
576 return EFI_INVALID_PARAMETER;\r
577 }\r
578\r
579 return SdtOpenEx (Buffer, MaxSize, Handle);\r
580}\r
581\r
582/**\r
583 Close an ACPI handle.\r
584 \r
585 @param[in] Handle Returns the handle.\r
586 \r
587 @retval EFI_SUCCESS Success\r
588 @retval EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object. \r
589**/\r
590EFI_STATUS\r
591EFIAPI\r
592Close (\r
593 IN EFI_ACPI_HANDLE Handle\r
594 )\r
595{\r
596 EFI_AML_HANDLE *AmlHandle;\r
597 EFI_STATUS Status;\r
598\r
599 //\r
600 // Check for invalid input parameters\r
601 //\r
602 if (Handle == NULL) {\r
603 return EFI_INVALID_PARAMETER;\r
604 }\r
605\r
606 AmlHandle = (EFI_AML_HANDLE *)Handle;\r
607 if ((AmlHandle->Signature != EFI_AML_ROOT_HANDLE_SIGNATURE) &&\r
608 (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE)) {\r
609 return EFI_INVALID_PARAMETER;\r
610 }\r
611\r
612 //\r
613 // Update Checksum only if modified\r
614 //\r
615 if (AmlHandle->Modified) {\r
616 Status = SdtUpdateAmlChecksum (AmlHandle->Buffer);\r
617 if (EFI_ERROR (Status)) {\r
618 return EFI_INVALID_PARAMETER;\r
619 }\r
620 }\r
621\r
622 FreePool (AmlHandle);\r
623\r
624 return EFI_SUCCESS;\r
625}\r
626\r
627/**\r
628 Retrieve information about an ACPI object.\r
629 \r
630 @param[in] Handle ACPI object handle.\r
631 @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right\r
632 in the ACPI encoding, with index 0 always being the ACPI opcode.\r
633 @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists\r
634 for the specified index.\r
635 @param[out] Data Upon return, points to the pointer to the data.\r
636 @param[out] DataSize Upon return, points to the size of Data.\r
637 \r
638 @retval EFI_SUCCESS Success.\r
639 @retval EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object.\r
640**/\r
641EFI_STATUS\r
642EFIAPI\r
643GetOption (\r
644 IN EFI_ACPI_HANDLE Handle,\r
645 IN UINTN Index,\r
646 OUT EFI_ACPI_DATA_TYPE *DataType,\r
647 OUT CONST VOID **Data,\r
648 OUT UINTN *DataSize\r
649 )\r
650{\r
651 EFI_AML_HANDLE *AmlHandle;\r
652 AML_BYTE_ENCODING *AmlByteEncoding;\r
653 EFI_STATUS Status;\r
654\r
655 ASSERT (DataType != NULL);\r
656 ASSERT (Data != NULL);\r
657 ASSERT (DataSize != NULL);\r
658\r
659 //\r
660 // Check for invalid input parameters\r
661 //\r
662 if (Handle == NULL) {\r
663 return EFI_INVALID_PARAMETER;\r
664 }\r
665\r
666 AmlHandle = (EFI_AML_HANDLE *)Handle;\r
667 //\r
668 // Do not check EFI_AML_ROOT_HANDLE_SIGNATURE because there is no option for Root handle\r
669 //\r
670 if (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE) {\r
671 return EFI_INVALID_PARAMETER;\r
672 }\r
673\r
674 AmlByteEncoding = AmlHandle->AmlByteEncoding;\r
675 if (Index > AmlByteEncoding->MaxIndex) {\r
676 *DataType = EFI_ACPI_DATA_TYPE_NONE;\r
677 return EFI_SUCCESS;\r
678 }\r
679\r
680 //\r
681 // Parse option\r
682 //\r
683 Status = AmlParseOptionHandleCommon (AmlHandle, (AML_OP_PARSE_INDEX)Index, DataType, (VOID **)Data, DataSize);\r
684 if (EFI_ERROR (Status)) {\r
685 return EFI_INVALID_PARAMETER;\r
686 }\r
687\r
688 return EFI_SUCCESS;\r
689}\r
690\r
691/**\r
692 Change information about an ACPI object.\r
693 \r
694 @param[in] Handle ACPI object handle.\r
695 @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right\r
696 in the ACPI encoding, with index 0 always being the ACPI opcode.\r
697 @param[in] Data Points to the data.\r
698 @param[in] DataSize The size of the Data.\r
699\r
700 @retval EFI_SUCCESS Success\r
701 @retval EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object.\r
702 @retval EFI_BAD_BUFFER_SIZE Data cannot be accommodated in the space occupied by\r
703 the option.\r
704\r
705**/\r
706EFI_STATUS\r
707EFIAPI\r
708SetOption (\r
709 IN EFI_ACPI_HANDLE Handle,\r
710 IN UINTN Index,\r
711 IN CONST VOID *Data,\r
712 IN UINTN DataSize\r
713 )\r
714{\r
715 EFI_AML_HANDLE *AmlHandle;\r
716 AML_BYTE_ENCODING *AmlByteEncoding;\r
717 EFI_STATUS Status;\r
718 EFI_ACPI_DATA_TYPE DataType;\r
719 VOID *OrgData;\r
720 UINTN OrgDataSize;\r
721\r
722 ASSERT (Data != NULL);\r
723\r
724 //\r
725 // Check for invalid input parameters\r
726 //\r
727 if (Handle == NULL) {\r
728 return EFI_INVALID_PARAMETER;\r
729 }\r
730\r
731 AmlHandle = (EFI_AML_HANDLE *)Handle;\r
732 //\r
733 // Do not check EFI_AML_ROOT_HANDLE_SIGNATURE because there is no option for Root handle\r
734 //\r
735 if (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE) {\r
736 return EFI_INVALID_PARAMETER;\r
737 }\r
738 AmlByteEncoding = AmlHandle->AmlByteEncoding;\r
739\r
740 if (Index > AmlByteEncoding->MaxIndex) {\r
741 return EFI_INVALID_PARAMETER;\r
742 }\r
743\r
744 //\r
745 // Parse option\r
746 //\r
747 Status = AmlParseOptionHandleCommon (AmlHandle, (AML_OP_PARSE_INDEX)Index, &DataType, &OrgData, &OrgDataSize);\r
748 if (EFI_ERROR (Status)) {\r
749 return EFI_INVALID_PARAMETER;\r
750 }\r
751 if (DataType == EFI_ACPI_DATA_TYPE_NONE) {\r
752 return EFI_INVALID_PARAMETER;\r
753 }\r
754\r
755 if (DataSize > OrgDataSize) {\r
756 return EFI_BAD_BUFFER_SIZE;\r
757 }\r
758\r
759 //\r
760 // Update\r
761 //\r
762 CopyMem (OrgData, Data, DataSize);\r
763 AmlHandle->Modified = TRUE;\r
764\r
765 return EFI_SUCCESS;\r
766}\r
767\r
768/**\r
769 Return the child ACPI objects.\r
770 \r
771 @param[in] ParentHandle Parent handle.\r
772 @param[in, out] Handle On entry, points to the previously returned handle or NULL to start with the first\r
773 handle. On return, points to the next returned ACPI handle or NULL if there are no\r
774 child objects.\r
775\r
776 @retval EFI_SUCCESS Success\r
777 @retval EFI_INVALID_PARAMETER ParentHandle is NULL or does not refer to a valid ACPI object. \r
778**/\r
779EFI_STATUS\r
780EFIAPI\r
781GetChild (\r
782 IN EFI_ACPI_HANDLE ParentHandle,\r
783 IN OUT EFI_ACPI_HANDLE *Handle\r
784 )\r
785{\r
786 EFI_AML_HANDLE *AmlParentHandle;\r
787 EFI_AML_HANDLE *AmlHandle;\r
788 VOID *Buffer;\r
789 EFI_STATUS Status;\r
790\r
791 ASSERT (Handle != NULL);\r
792\r
793 //\r
794 // Check for invalid input parameters\r
795 //\r
796 if (ParentHandle == NULL) {\r
797 return EFI_INVALID_PARAMETER;\r
798 }\r
799\r
800 AmlHandle = *Handle;\r
801 if ((AmlHandle != NULL) && (AmlHandle->Signature != EFI_AML_HANDLE_SIGNATURE)) {\r
802 return EFI_INVALID_PARAMETER;\r
803 }\r
804\r
805 AmlParentHandle = (EFI_AML_HANDLE *)ParentHandle;\r
806 if (AmlParentHandle->Signature == EFI_AML_ROOT_HANDLE_SIGNATURE) {\r
807 //\r
808 // Root handle\r
809 //\r
810 Status = AmlGetChildFromRoot (AmlParentHandle, AmlHandle, &Buffer);\r
811 } else if (AmlParentHandle->Signature == EFI_AML_HANDLE_SIGNATURE) {\r
812 //\r
813 // Non-root handle\r
814 //\r
815 Status = AmlGetChildFromNonRoot (AmlParentHandle, AmlHandle, &Buffer);\r
816 } else {\r
817 //\r
818 // Invalid\r
819 //\r
820 return EFI_INVALID_PARAMETER;\r
821 }\r
822\r
823 if (EFI_ERROR (Status)) {\r
824 return EFI_INVALID_PARAMETER;\r
825 }\r
826 if (Buffer == NULL) {\r
827 *Handle = NULL;\r
828 return EFI_SUCCESS;\r
829 }\r
830 return SdtOpenEx (Buffer, (UINTN)AmlParentHandle->Buffer + AmlParentHandle->Size - (UINTN)Buffer, Handle);\r
831}\r
832\r
833/**\r
834 Returns the handle of the ACPI object representing the specified ACPI path\r
835 \r
836 @param[in] HandleIn Points to the handle of the object representing the starting point for the path search.\r
837 @param[in] AmlPath Points to the AML path.\r
838 @param[out] HandleOut On return, points to the ACPI object which represents AcpiPath, relative to\r
839 HandleIn.\r
840 \r
841 @retval EFI_SUCCESS Success\r
842 @retval EFI_INVALID_PARAMETER HandleIn is NULL or does not refer to a valid ACPI object. \r
843**/\r
844EFI_STATUS\r
845SdtFindPathFromNonRoot (\r
846 IN EFI_ACPI_HANDLE HandleIn,\r
847 IN UINT8 *AmlPath,\r
848 OUT EFI_ACPI_HANDLE *HandleOut\r
849 )\r
850{\r
851 EFI_AML_HANDLE *AmlHandle;\r
852 VOID *Buffer;\r
853 EFI_STATUS Status;\r
854\r
855 AmlHandle = (EFI_AML_HANDLE *)HandleIn;\r
856\r
857 //\r
858 // For non-root handle, we need search from THIS node instead of ROOT.\r
859 //\r
860 Status = AmlFindPath (AmlHandle, AmlPath, &Buffer, FALSE);\r
861 if (EFI_ERROR (Status)) {\r
862 return EFI_INVALID_PARAMETER;\r
863 }\r
864 if (Buffer == NULL) {\r
865 *HandleOut = NULL;\r
866 return EFI_SUCCESS;\r
867 }\r
868 return SdtOpenEx (Buffer, (UINTN)AmlHandle->Buffer + AmlHandle->Size - (UINTN)Buffer, HandleOut);\r
869}\r
870\r
871/**\r
872 Duplicate AML handle.\r
873 \r
874 @param[in] AmlHandle Handle to be duplicated.\r
875 \r
876 @return Duplicated AML handle.\r
877**/\r
878EFI_AML_HANDLE *\r
879SdtDuplicateHandle (\r
880 IN EFI_AML_HANDLE *AmlHandle\r
881 )\r
882{\r
883 EFI_AML_HANDLE *DstAmlHandle;\r
884\r
885 DstAmlHandle = AllocatePool (sizeof(*DstAmlHandle));\r
886 ASSERT (DstAmlHandle != NULL);\r
887 CopyMem (DstAmlHandle, (VOID *)AmlHandle, sizeof(*DstAmlHandle));\r
888\r
889 return DstAmlHandle;\r
890}\r
891\r
892/**\r
893 Returns the handle of the ACPI object representing the specified ACPI path\r
894 \r
895 @param[in] HandleIn Points to the handle of the object representing the starting point for the path search.\r
896 @param[in] AmlPath Points to the AML path.\r
897 @param[out] HandleOut On return, points to the ACPI object which represents AcpiPath, relative to\r
898 HandleIn.\r
899 \r
900 @retval EFI_SUCCESS Success\r
901 @retval EFI_INVALID_PARAMETER HandleIn is NULL or does not refer to a valid ACPI object. \r
902**/\r
903EFI_STATUS\r
904SdtFindPathFromRoot (\r
905 IN EFI_ACPI_HANDLE HandleIn,\r
906 IN UINT8 *AmlPath,\r
907 OUT EFI_ACPI_HANDLE *HandleOut\r
908 )\r
909{\r
910 EFI_ACPI_HANDLE ChildHandle;\r
911 EFI_AML_HANDLE *AmlHandle;\r
912 EFI_STATUS Status;\r
913 VOID *Buffer;\r
914\r
915 AmlHandle = (EFI_AML_HANDLE *)HandleIn;\r
916\r
917 //\r
918 // Handle case that AcpiPath is Root\r
919 //\r
920 if (AmlIsRootPath (AmlPath)) {\r
921 //\r
922 // Duplicate RootHandle\r
923 //\r
924 *HandleOut = (EFI_ACPI_HANDLE)SdtDuplicateHandle (AmlHandle);\r
925 return EFI_SUCCESS;\r
926 }\r
927\r
928 //\r
929 // Let children find it.\r
930 //\r
931 ChildHandle = NULL;\r
932 while (TRUE) {\r
933 Status = GetChild (HandleIn, &ChildHandle);\r
934 if (EFI_ERROR (Status)) {\r
935 return EFI_INVALID_PARAMETER;\r
936 }\r
937\r
938 if (ChildHandle == NULL) {\r
939 //\r
940 // Not found\r
941 //\r
942 *HandleOut = NULL;\r
943 return EFI_SUCCESS;\r
944 }\r
945\r
946 //\r
947 // More child\r
948 //\r
949 AmlHandle = (EFI_AML_HANDLE *)ChildHandle;\r
950 Status = AmlFindPath (AmlHandle, AmlPath, &Buffer, TRUE);\r
951 if (EFI_ERROR (Status)) {\r
952 return EFI_INVALID_PARAMETER;\r
953 }\r
954\r
955 if (Buffer != NULL) {\r
956 //\r
957 // Great! Find it, open\r
958 //\r
959 Status = SdtOpenEx (Buffer, (UINTN)AmlHandle->Buffer + AmlHandle->Size - (UINTN)Buffer, HandleOut);\r
960 if (!EFI_ERROR (Status)) {\r
961 return EFI_SUCCESS;\r
962 }\r
963 //\r
964 // Not success, try next one\r
965 //\r
966 }\r
967 }\r
968\r
969 //\r
970 // Should not run here\r
971 //\r
972}\r
973\r
974/**\r
975 Returns the handle of the ACPI object representing the specified ACPI path\r
976 \r
977 @param[in] HandleIn Points to the handle of the object representing the starting point for the path search.\r
978 @param[in] AcpiPath Points to the ACPI path, which conforms to the ACPI encoded path format.\r
979 @param[out] HandleOut On return, points to the ACPI object which represents AcpiPath, relative to\r
980 HandleIn.\r
981 \r
982 @retval EFI_SUCCESS Success\r
983 @retval EFI_INVALID_PARAMETER HandleIn is NULL or does not refer to a valid ACPI object. \r
984**/\r
985EFI_STATUS\r
986EFIAPI\r
987FindPath (\r
988 IN EFI_ACPI_HANDLE HandleIn,\r
989 IN VOID *AcpiPath,\r
990 OUT EFI_ACPI_HANDLE *HandleOut\r
991 )\r
992{\r
993 EFI_AML_HANDLE *AmlHandle;\r
994 EFI_STATUS Status;\r
995 UINT8 *AmlPath;\r
996\r
997 //\r
998 // Check for invalid input parameters\r
999 //\r
1000 if (HandleIn == NULL) {\r
1001 return EFI_INVALID_PARAMETER;\r
1002 }\r
1003\r
1004 AmlHandle = (EFI_AML_HANDLE *)HandleIn;\r
1005 \r
1006 //\r
1007 // Convert ASL path to AML path\r
1008 //\r
1009 AmlPath = AmlNameFromAslName (AcpiPath);\r
1010 if (AmlPath == NULL) {\r
1011 return EFI_INVALID_PARAMETER;\r
1012 }\r
1013\r
1014 DEBUG_CODE_BEGIN ();\r
1015 DEBUG ((EFI_D_ERROR, "AcpiSdt: FindPath - "));\r
1016 AmlPrintNameString (AmlPath);\r
1017 DEBUG ((EFI_D_ERROR, "\n"));\r
1018 DEBUG_CODE_END ();\r
1019\r
1020 if (AmlHandle->Signature == EFI_AML_ROOT_HANDLE_SIGNATURE) {\r
1021 //\r
1022 // Root Handle\r
1023 //\r
1024 Status = SdtFindPathFromRoot (HandleIn, AmlPath, HandleOut);\r
1025 } else if (AmlHandle->Signature == EFI_AML_HANDLE_SIGNATURE) {\r
1026 //\r
1027 // Non-Root handle\r
1028 //\r
1029 Status = SdtFindPathFromNonRoot (HandleIn, AmlPath, HandleOut);\r
1030 } else {\r
1031 Status = EFI_INVALID_PARAMETER;\r
1032 }\r
1033\r
1034 FreePool (AmlPath);\r
1035\r
1036 return Status;\r
1037}\r
1038\r
1039/**\r
1040 ExitPmAuth Protocol notification event handler.\r
1041\r
1042 @param[in] Event Event whose notification function is being invoked.\r
1043 @param[in] Context Pointer to the notification function's context.\r
1044**/\r
1045VOID\r
1046EFIAPI\r
1047ExitPmAuthNotification (\r
1048 IN EFI_EVENT Event,\r
1049 IN VOID *Context\r
1050 )\r
1051{\r
1052 EFI_STATUS Status;\r
1053 VOID *DxeSmmReadyToLock;\r
1054\r
1055 //\r
1056 // Add more check to locate protocol after got event, because\r
1057 // the library will signal this event immediately once it is register\r
1058 // just in case it is already installed.\r
1059 //\r
1060 Status = gBS->LocateProtocol (\r
1061 &gEfiDxeSmmReadyToLockProtocolGuid,\r
1062 NULL,\r
1063 &DxeSmmReadyToLock\r
1064 );\r
1065 if (EFI_ERROR (Status)) {\r
1066 return ;\r
1067 }\r
1068\r
1069 //\r
1070 // Uninstall ACPI SDT protocol, so that we can make sure no one update ACPI table from API level.\r
1071 //\r
1072 Status = gBS->UninstallProtocolInterface (\r
1073 mHandle,\r
1074 &gEfiAcpiSdtProtocolGuid,\r
1075 &mPrivateData->AcpiSdtProtocol\r
1076 );\r
1077 ASSERT_EFI_ERROR (Status);\r
1078\r
1079 //\r
1080 // Close event, so it will not be invoked again.\r
1081 //\r
1082 gBS->CloseEvent (Event);\r
1083\r
1084 return ;\r
1085}\r
1086\r
1087/**\r
1088 This function initializes AcpiSdt protocol in ACPI table instance.\r
1089\r
1090 @param[in] AcpiTableInstance Instance to construct\r
1091**/\r
1092VOID\r
1093SdtAcpiTableAcpiSdtConstructor (\r
1094 IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance\r
1095 )\r
1096{\r
1097 VOID *Registration;\r
1098\r
1099 InitializeListHead (&AcpiTableInstance->NotifyList);\r
1100 CopyMem (&AcpiTableInstance->AcpiSdtProtocol, &mAcpiSdtProtocolTemplate, sizeof(mAcpiSdtProtocolTemplate));\r
1101\r
1102 //\r
1103 // Register event for ExitPmAuth, so that we can uninstall ACPI SDT protocol after ExitPmAuth.\r
1104 //\r
1105 EfiCreateProtocolNotifyEvent (\r
1106 &gEfiDxeSmmReadyToLockProtocolGuid,\r
1107 TPL_CALLBACK,\r
1108 ExitPmAuthNotification,\r
1109 NULL,\r
1110 &Registration\r
1111 );\r
1112\r
1113 return ;\r
1114}\r