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