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