1 /** @file
2   ACPI Support Protocol implementation
3 
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 //
11 // Includes
12 //
13 #include "AcpiSupport.h"
14 //
15 // The maximum number of tables that pre-allocated.
16 //
17 UINTN         mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES;
18 /**
19   This function adds an ACPI table to the table list.  It will detect FACS and
20   allocate the correct type of memory and properly align the table.
21 
22   @param  AcpiSupportInstance       Instance of the protocol.
23   @param  Table                     Table to add.
24   @param  Checksum                  Does the table require checksumming.
25   @param  Version                   The version of the list to add the table to.
26   @param  Handle                    Pointer for returning the handle.
27 
28   @return EFI_SUCCESS               The function completed successfully.
29   @return EFI_OUT_OF_RESOURCES      Could not allocate a required resource.
30   @return EFI_ABORTED               The table is a duplicate of a table that is required
31                                     to be unique.
32 **/
33 EFI_STATUS
34 AddTableToList (
35   IN EFI_ACPI_SUPPORT_INSTANCE            *AcpiSupportInstance,
36   IN VOID                                 *Table,
37   IN BOOLEAN                              Checksum,
38   IN EFI_ACPI_TABLE_VERSION               Version,
39   OUT UINTN                               *Handle
40   );
41 /**
42   This function finds and removes the table specified by the handle.
43 
44   @param  AcpiSupportInstance  Instance of the protocol.
45   @param  Version              Bitmask of which versions to remove.
46   @param  Handle               Table to remove.
47 
48   @return EFI_SUCCESS    The function completed successfully.
49   @return EFI_ABORTED    An error occurred.
50   @return EFI_NOT_FOUND  Handle not found in table list.
51 **/
52 EFI_STATUS
53 RemoveTableFromList (
54   IN EFI_ACPI_SUPPORT_INSTANCE            *AcpiSupportInstance,
55   IN EFI_ACPI_TABLE_VERSION               Version,
56   IN UINTN                                Handle
57   );
58 /**
59   This function calculates and updates an UINT8 checksum.
60 
61   @param  Buffer          Pointer to buffer to checksum
62   @param  Size            Number of bytes to checksum
63   @param  ChecksumOffset  Offset to place the checksum result in
64 
65   @return EFI_SUCCESS             The function completed successfully.
66 **/
67 EFI_STATUS
68 AcpiPlatformChecksum (
69   IN VOID       *Buffer,
70   IN UINTN      Size,
71   IN UINTN      ChecksumOffset
72   );
73 /**
74   Checksum all versions of the common tables, RSDP, RSDT, XSDT.
75 
76   @param  AcpiSupportInstance  Protocol instance private data.
77 
78   @return EFI_SUCCESS        The function completed successfully.
79 
80 **/
81 EFI_STATUS
82 ChecksumCommonTables (
83   IN OUT EFI_ACPI_SUPPORT_INSTANCE        *AcpiSupportInstance
84   );
85 
86 /**
87   This function returns a table specified by an index if it exists.
88 
89   The function returns a buffer containing the table that the caller must free.
90   The function also returns a handle used to identify the table for update or
91   deletion using the SetAcpiTable function.
92 
93   @param This        Instance of the protocol.
94   @param Index       Zero-based index of the table to retrieve.
95   @param Table       Returned pointer to the table.
96   @param Version     Versions that the table is currently used in.
97   @param Handle      Handle of the table, used in updating tables.
98 
99   @retval EFI_SUCCESS             The function completed successfully.
100   @retval EFI_NOT_FOUND           The requested table does not exist.
101 
102 **/
103 EFI_STATUS
104 EFIAPI
GetAcpiTable(IN EFI_ACPI_SUPPORT_PROTOCOL * This,IN INTN Index,OUT VOID ** Table,OUT EFI_ACPI_TABLE_VERSION * Version,OUT UINTN * Handle)105 GetAcpiTable (
106   IN EFI_ACPI_SUPPORT_PROTOCOL            *This,
107   IN INTN                                 Index,
108   OUT VOID                                **Table,
109   OUT EFI_ACPI_TABLE_VERSION              *Version,
110   OUT UINTN                               *Handle
111   )
112 
113 {
114   EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance;
115   INTN                  TempIndex;
116   LIST_ENTRY            *CurrentLink;
117   LIST_ENTRY            *StartLink;
118   EFI_ACPI_TABLE_LIST       *CurrentTable;
119 
120   //
121   // Check for invalid input parameters
122   //
123   ASSERT (This);
124   ASSERT (Table);
125   ASSERT (Handle);
126 
127   //
128   // Get the instance of the protocol
129   //
130   AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This);
131 
132   //
133   // Find the table
134   //
135   CurrentLink = AcpiSupportInstance->TableList.ForwardLink;
136   StartLink   = &AcpiSupportInstance->TableList;
137   for (TempIndex = 0; (TempIndex < Index) && (CurrentLink != StartLink) && (CurrentLink != NULL); TempIndex++) {
138     CurrentLink = CurrentLink->ForwardLink;
139   }
140 
141   if (TempIndex != Index || CurrentLink == StartLink) {
142     return EFI_NOT_FOUND;
143   }
144   //
145   // Get handle and version
146   //
147   CurrentTable  = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
148   *Handle       = CurrentTable->Handle;
149   *Version      = CurrentTable->Version;
150 
151   //
152   // Copy the table
153   //
154   *Table = AllocateCopyPool (CurrentTable->Table->Length, CurrentTable->Table);
155   ASSERT (*Table);
156 
157   return EFI_SUCCESS;
158 }
159 /**
160   This function adds, removes, or updates ACPI tables.  If the address is not
161   null and the handle value is null, the table is added.  If both the address and
162   handle are not null, the table at handle is updated with the table at address.
163   If the address is null and the handle is not, the table at handle is deleted.
164 
165   @param  This                 Pointer of the protocol.
166   @param  Table                Pointer to a table.
167   @param  Checksum             Boolean indicating if the checksum should be calculated.
168   @param  Version              Version(s) to set.
169   @param  Handle               Handle of the table.
170 
171   @return EFI_SUCCESS             The function completed successfully.
172   @return EFI_INVALID_PARAMETER   Both the Table and *Handle were NULL.
173   @return EFI_ABORTED             Could not complete the desired request.
174 
175 **/
176 EFI_STATUS
177 EFIAPI
SetAcpiTable(IN EFI_ACPI_SUPPORT_PROTOCOL * This,IN VOID * Table OPTIONAL,IN BOOLEAN Checksum,IN EFI_ACPI_TABLE_VERSION Version,IN OUT UINTN * Handle)178 SetAcpiTable (
179   IN EFI_ACPI_SUPPORT_PROTOCOL            *This,
180   IN VOID                                 *Table OPTIONAL,
181   IN BOOLEAN                              Checksum,
182   IN EFI_ACPI_TABLE_VERSION               Version,
183   IN OUT UINTN                            *Handle
184   )
185 {
186   EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance;
187   UINTN                     SavedHandle;
188   EFI_STATUS                Status;
189 
190   //
191   // Check for invalid input parameters
192   //
193   ASSERT (This);
194   ASSERT (Handle != NULL);
195 
196   //
197   // Get the instance of the protocol
198   //
199   AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This);
200 
201   //
202   // Initialize locals
203   //
204   //
205   // Determine desired action
206   //
207   if (*Handle == 0) {
208     if (Table == NULL) {
209       //
210       // Invalid parameter combination
211       //
212       return EFI_INVALID_PARAMETER;
213     } else {
214       //
215       // Add table
216       //
217       Status = AddTableToList (AcpiSupportInstance, Table, Checksum, Version, Handle);
218     }
219   } else {
220     if (Table != NULL) {
221       //
222       // Update table
223       //
224       //
225       // Delete the table list entry
226       //
227       Status = RemoveTableFromList (AcpiSupportInstance, Version, *Handle);
228       if (EFI_ERROR (Status)) {
229         //
230         // Should not get an error here ever, but abort if we do.
231         //
232         return EFI_ABORTED;
233       }
234       //
235       // Set the handle to replace the table at the same handle
236       //
237       SavedHandle                         = AcpiSupportInstance->CurrentHandle;
238       AcpiSupportInstance->CurrentHandle  = *Handle;
239 
240       //
241       // Add the table
242       //
243       Status = AddTableToList (AcpiSupportInstance, Table, Checksum, Version, Handle);
244 
245       //
246       // Restore the saved current handle
247       //
248       AcpiSupportInstance->CurrentHandle = SavedHandle;
249     } else {
250       //
251       // Delete table
252       //
253       Status = RemoveTableFromList (AcpiSupportInstance, Version, *Handle);
254     }
255   }
256 
257   if (EFI_ERROR (Status)) {
258     //
259     // Should not get an error here ever, but abort if we do.
260     //
261     return EFI_ABORTED;
262   }
263   //
264   // Done
265   //
266   return EFI_SUCCESS;
267 }
268 /**
269   This function publishes the specified versions of the ACPI tables by
270   installing EFI configuration table entries for them.  Any combination of
271   table versions can be published.
272 
273   @param  This                 Pointer of the protocol.
274   @param  Version              Version(s) to publish.
275 
276   @return EFI_SUCCESS  The function completed successfully.
277   @return EFI_ABORTED  The function could not complete successfully.
278 
279 **/
280 EFI_STATUS
281 EFIAPI
PublishTables(IN EFI_ACPI_SUPPORT_PROTOCOL * This,IN EFI_ACPI_TABLE_VERSION Version)282 PublishTables (
283   IN EFI_ACPI_SUPPORT_PROTOCOL            *This,
284   IN EFI_ACPI_TABLE_VERSION               Version
285   )
286 {
287   EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance;
288   EFI_STATUS                Status;
289   UINT32                    *CurrentRsdtEntry;
290   VOID                      *CurrentXsdtEntry;
291   UINT64                    Buffer64;
292 
293   //
294   // Get the instance of the protocol
295   //
296   AcpiSupportInstance = EFI_ACPI_SUPPORT_INSTANCE_FROM_ACPI_SUPPORT_THIS (This);
297 
298   //
299   // Reorder tables as some operating systems don't seem to find the
300   // FADT correctly if it is not in the first few entries
301   //
302 
303   //
304   // Add FADT as the first entry
305   //
306   if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
307     CurrentRsdtEntry  = (UINT32 *) ((UINT8 *) AcpiSupportInstance->Rsdt1 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
308     *CurrentRsdtEntry = (UINT32) (UINTN) AcpiSupportInstance->Fadt1;
309   }
310   if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
311     CurrentRsdtEntry  = (UINT32 *) ((UINT8 *) AcpiSupportInstance->Rsdt3 + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
312     *CurrentRsdtEntry = (UINT32) (UINTN) AcpiSupportInstance->Fadt3;
313     CurrentXsdtEntry  = (VOID *) ((UINT8 *) AcpiSupportInstance->Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
314     //
315     // Add entry to XSDT, XSDT expects 64 bit pointers, but
316     // the table pointers in XSDT are not aligned on 8 byte boundary.
317     //
318     Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Fadt3;
319     CopyMem (
320       CurrentXsdtEntry,
321       &Buffer64,
322       sizeof (UINT64)
323       );
324   }
325 
326   //
327   // Do checksum again because Dsdt/Xsdt is updated.
328   //
329   ChecksumCommonTables (AcpiSupportInstance);
330 
331   //
332   // Add the RSD_PTR to the system table and store that we have installed the
333   // tables.
334   //
335   if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && !AcpiSupportInstance->TablesInstalled1) {
336     Status = gBS->InstallConfigurationTable (&gEfiAcpi10TableGuid, AcpiSupportInstance->Rsdp1);
337     if (EFI_ERROR (Status)) {
338       return EFI_ABORTED;
339     }
340 
341     AcpiSupportInstance->TablesInstalled1 = TRUE;
342   }
343 
344   if (((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) &&
345       !AcpiSupportInstance->TablesInstalled3) {
346     Status = gBS->InstallConfigurationTable (&gEfiAcpiTableGuid, AcpiSupportInstance->Rsdp3);
347     if (EFI_ERROR (Status)) {
348       return EFI_ABORTED;
349     }
350 
351     AcpiSupportInstance->TablesInstalled3= TRUE;
352   }
353 
354   return EFI_SUCCESS;
355 }
356 /**
357   Installs an ACPI table into the RSDT/XSDT.
358   Note that the ACPI table should be checksumed before installing it.
359   Otherwise it will assert.
360 
361   @param  This                 Protocol instance pointer.
362   @param  AcpiTableBuffer      A pointer to a buffer containing the ACPI table to be installed.
363   @param  AcpiTableBufferSize  Specifies the size, in bytes, of the AcpiTableBuffer buffer.
364   @param  TableKey             Reurns a key to refer to the ACPI table.
365 
366   @return EFI_SUCCESS            The table was successfully inserted.
367   @return EFI_INVALID_PARAMETER  Either AcpiTableBuffer is NULL, TableKey is NULL, or AcpiTableBufferSize
368                                  and the size field embedded in the ACPI table pointed to by AcpiTableBuffer
369                                  are not in sync.
370   @return EFI_OUT_OF_RESOURCES   Insufficient resources exist to complete the request.
371   @retval EFI_ACCESS_DENIED      The table signature matches a table already
372                                  present in the system and platform policy
373                                  does not allow duplicate tables of this type.
374 
375 **/
376 EFI_STATUS
377 EFIAPI
InstallAcpiTable(IN EFI_ACPI_TABLE_PROTOCOL * This,IN VOID * AcpiTableBuffer,IN UINTN AcpiTableBufferSize,OUT UINTN * TableKey)378 InstallAcpiTable (
379   IN   EFI_ACPI_TABLE_PROTOCOL                    *This,
380   IN   VOID                                       *AcpiTableBuffer,
381   IN   UINTN                                      AcpiTableBufferSize,
382   OUT  UINTN                                      *TableKey
383   )
384 {
385   EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance;
386   EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
387   EFI_STATUS                Status;
388   VOID                      *AcpiTableBufferConst;
389 
390   //
391   // Check for invalid input parameters
392   //
393   if ((AcpiTableBuffer == NULL) || (TableKey == NULL)
394      || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) {
395     return EFI_INVALID_PARAMETER;
396   }
397 
398   //
399   // Get the instance of the ACPI support protocol
400   //
401   AcpiSupportInstance = EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS (This);
402   AcpiSupport = &AcpiSupportInstance->AcpiSupport;
403 
404   //
405   // Install the ACPI table by using ACPI support protocol
406   //
407   AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize, AcpiTableBuffer);
408   *TableKey = 0;
409   Status = AddTableToList (
410              AcpiSupportInstance,
411              AcpiTableBufferConst,
412              TRUE,
413              EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0,
414              TableKey
415              );
416   if (!EFI_ERROR (Status)) {
417     Status = AcpiSupport->PublishTables (
418                             AcpiSupport,
419                             EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0
420                             );
421   }
422   FreePool (AcpiTableBufferConst);
423 
424   return Status;
425 }
426 /**
427   Removes an ACPI table from the RSDT/XSDT.
428 
429   @param  This      Protocol instance pointer.
430   @param  TableKey  Specifies the table to uninstall.  The key was returned from InstallAcpiTable().
431 
432   @return EFI_SUCCESS    The table was successfully uninstalled.
433   @return EFI_NOT_FOUND  TableKey does not refer to a valid key for a table entry.
434 
435 **/
436 EFI_STATUS
437 EFIAPI
UninstallAcpiTable(IN EFI_ACPI_TABLE_PROTOCOL * This,IN UINTN TableKey)438 UninstallAcpiTable (
439   IN  EFI_ACPI_TABLE_PROTOCOL                    *This,
440   IN  UINTN                                      TableKey
441   )
442 {
443   EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance;
444   EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
445   EFI_STATUS                Status;
446 
447   //
448   // Get the instance of the ACPI support protocol
449   //
450   AcpiSupportInstance = EFI_ACPI_TABLE_INSTANCE_FROM_ACPI_SUPPORT_THIS (This);
451   AcpiSupport = &AcpiSupportInstance->AcpiSupport;
452 
453   //
454   // Uninstall the ACPI table by using ACPI support protocol
455   //
456   Status = RemoveTableFromList (
457              AcpiSupportInstance,
458              EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0,
459              TableKey
460              );
461   if (!EFI_ERROR (Status)) {
462     Status = AcpiSupport->PublishTables (
463                             AcpiSupport,
464                             EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0
465                             );
466   }
467 
468   if (EFI_ERROR (Status)) {
469     return EFI_NOT_FOUND;
470   } else {
471     return EFI_SUCCESS;
472   }
473 }
474 /**
475   If the number of APCI tables exceeds the preallocated max table number, enlarge the table buffer.
476 
477   @param  AcpiSupportInstance       ACPI support protocol instance data structure
478 
479   @return EFI_SUCCESS             reallocate the table beffer successfully.
480   @return EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
481 
482 **/
483 EFI_STATUS
ReallocateAcpiTableBuffer(IN EFI_ACPI_SUPPORT_INSTANCE * AcpiSupportInstance)484 ReallocateAcpiTableBuffer (
485   IN EFI_ACPI_SUPPORT_INSTANCE            *AcpiSupportInstance
486   )
487 {
488   UINTN                      NewMaxTableNumber;
489   UINTN                      TotalSize;
490   UINT8                      *Pointer;
491   EFI_PHYSICAL_ADDRESS       PageAddress;
492   EFI_ACPI_SUPPORT_INSTANCE  TempPrivateData;
493   EFI_STATUS                 Status;
494   UINT64                     CurrentData;
495 
496   CopyMem (&TempPrivateData, AcpiSupportInstance, sizeof (EFI_ACPI_SUPPORT_INSTANCE));
497   //
498   // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES
499   //
500   NewMaxTableNumber = mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES;
501   //
502   // Create RSDT, XSDT structures and allocate buffers.
503   //
504   TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT
505               NewMaxTableNumber * sizeof (UINT32) +
506               sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT
507               NewMaxTableNumber * sizeof (UINT32) +
508               sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT
509               NewMaxTableNumber * sizeof (UINT64);
510 
511   //
512   // Allocate memory in the lower 32 bit of address range for
513   // compatibility with ACPI 1.0 OS.
514   //
515   // This is done because ACPI 1.0 pointers are 32 bit values.
516   // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
517   // There is no architectural reason these should be below 4GB, it is purely
518   // for convenience of implementation that we force memory below 4GB.
519   //
520   PageAddress = 0xFFFFFFFF;
521   Status = gBS->AllocatePages (
522                   AllocateMaxAddress,
523                   EfiACPIReclaimMemory,
524                   EFI_SIZE_TO_PAGES (TotalSize),
525                   &PageAddress
526                   );
527 
528   if (EFI_ERROR (Status)) {
529     return EFI_OUT_OF_RESOURCES;
530   }
531 
532   Pointer = (UINT8 *) (UINTN) PageAddress;
533   ZeroMem (Pointer, TotalSize);
534 
535   AcpiSupportInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
536   Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));
537   AcpiSupportInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
538   Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));
539   AcpiSupportInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
540 
541   //
542   // Update RSDP to point to the new Rsdt and Xsdt address.
543   //
544   AcpiSupportInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt1;
545   AcpiSupportInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt3;
546   CurrentData = (UINT64) (UINTN) AcpiSupportInstance->Xsdt;
547   CopyMem (&AcpiSupportInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));
548 
549   //
550   // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer
551   //
552   CopyMem (AcpiSupportInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32)));
553   CopyMem (AcpiSupportInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32)));
554   CopyMem (AcpiSupportInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64)));
555 
556   //
557   // Calculate orignal ACPI table buffer size
558   //
559   TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT
560               mEfiAcpiMaxNumTables * sizeof (UINT32) +
561               sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT
562               mEfiAcpiMaxNumTables * sizeof (UINT32) +
563               sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT
564               mEfiAcpiMaxNumTables * sizeof (UINT64);
565   gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize));
566 
567   //
568   // Update the Max ACPI table number
569   //
570   mEfiAcpiMaxNumTables = NewMaxTableNumber;
571   return EFI_SUCCESS;
572 }
573 /**
574   This function adds an ACPI table to the table list.  It will detect FACS and
575   allocate the correct type of memory and properly align the table.
576 
577   @param  AcpiSupportInstance       Instance of the protocol.
578   @param  Table                     Table to add.
579   @param  Checksum                  Does the table require checksumming.
580   @param  Version                   The version of the list to add the table to.
581   @param  Handle                    Pointer for returning the handle.
582 
583   @return EFI_SUCCESS               The function completed successfully.
584   @return EFI_OUT_OF_RESOURCES      Could not allocate a required resource.
585   @retval EFI_ACCESS_DENIED         The table signature matches a table already
586                                     present in the system and platform policy
587                                     does not allow duplicate tables of this type.
588 **/
589 EFI_STATUS
AddTableToList(IN EFI_ACPI_SUPPORT_INSTANCE * AcpiSupportInstance,IN VOID * Table,IN BOOLEAN Checksum,IN EFI_ACPI_TABLE_VERSION Version,OUT UINTN * Handle)590 AddTableToList (
591   IN EFI_ACPI_SUPPORT_INSTANCE            *AcpiSupportInstance,
592   IN VOID                                 *Table,
593   IN BOOLEAN                              Checksum,
594   IN EFI_ACPI_TABLE_VERSION               Version,
595   OUT UINTN                               *Handle
596   )
597 {
598   EFI_STATUS          Status;
599   EFI_ACPI_TABLE_LIST *CurrentTableList;
600   UINT32              CurrentTableSignature;
601   UINT32              CurrentTableSize;
602   UINT32              *CurrentRsdtEntry;
603   VOID                *CurrentXsdtEntry;
604   UINT64              Buffer64;
605   BOOLEAN             AddToRsdt;
606 
607   //
608   // Check for invalid input parameters
609   //
610   ASSERT (AcpiSupportInstance);
611   ASSERT (Table);
612   ASSERT (Handle);
613 
614   //
615   // Init locals
616   //
617   AddToRsdt = TRUE;
618 
619   //
620   // Create a new list entry
621   //
622   CurrentTableList = AllocatePool (sizeof (EFI_ACPI_TABLE_LIST));
623   ASSERT (CurrentTableList);
624 
625   //
626   // Determine table type and size
627   //
628   CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table)->Signature;
629   CurrentTableSize      = ((EFI_ACPI_COMMON_HEADER *) Table)->Length;
630 
631   //
632   // Allocate a buffer for the table.  All tables are allocated in the lower 32 bits of address space
633   // for backwards compatibility with ACPI 1.0 OS.
634   //
635   // This is done because ACPI 1.0 pointers are 32 bit values.
636   // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
637   // There is no architectural reason these should be below 4GB, it is purely
638   // for convenience of implementation that we force memory below 4GB.
639   //
640   CurrentTableList->PageAddress   = 0xFFFFFFFF;
641   CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize);
642 
643   //
644   // Allocation memory type depends on the type of the table
645   //
646   if ((CurrentTableSignature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
647       (CurrentTableSignature == EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE)) {
648     //
649     // Allocate memory for the FACS.  This structure must be aligned
650     // on a 64 byte boundary and must be ACPI NVS memory.
651     // Using AllocatePages should ensure that it is always aligned.
652     // Do not change signature for new ACPI version because they are same.
653     //
654     // UEFI table also need to be in ACPI NVS memory, because some data field
655     // could be updated by OS present agent. For example, BufferPtrAddress in
656     // SMM communication ACPI table.
657     //
658     ASSERT ((EFI_PAGE_SIZE % 64) == 0);
659     Status = gBS->AllocatePages (
660                     AllocateMaxAddress,
661                     EfiACPIMemoryNVS,
662                     CurrentTableList->NumberOfPages,
663                     &CurrentTableList->PageAddress
664                     );
665   } else {
666     //
667     // All other tables are ACPI reclaim memory, no alignment requirements.
668     //
669     Status = gBS->AllocatePages (
670                     AllocateMaxAddress,
671                     EfiACPIReclaimMemory,
672                     CurrentTableList->NumberOfPages,
673                     &CurrentTableList->PageAddress
674                     );
675   }
676   //
677   // Check return value from memory alloc.
678   //
679   if (EFI_ERROR (Status)) {
680     gBS->FreePool (CurrentTableList);
681     return EFI_OUT_OF_RESOURCES;
682   }
683   //
684   // Update the table pointer with the allocated memory start
685   //
686   CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress;
687 
688   //
689   // Initialize the table contents
690   //
691   CurrentTableList->Signature = EFI_ACPI_TABLE_LIST_SIGNATURE;
692   CopyMem (CurrentTableList->Table, Table, CurrentTableSize);
693   CurrentTableList->Handle  = AcpiSupportInstance->CurrentHandle++;
694   *Handle                   = CurrentTableList->Handle;
695   CurrentTableList->Version = Version;
696 
697   //
698   // Update internal pointers if this is a required table.  If it is a required
699   // table and a table of that type already exists, return an error.
700   //
701   // Calculate the checksum if the table is not FACS.
702   //
703   switch (CurrentTableSignature) {
704 
705   case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
706     //
707     // We don't add the FADT in the standard way because some
708     // OS expect the FADT to be early in the table list.
709     // So we always add it as the first element in the list.
710     //
711     AddToRsdt = FALSE;
712 
713     //
714     // Check that the table has not been previously added.
715     //
716    if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Fadt1 != NULL) ||
717         ((Version & EFI_ACPI_TABLE_VERSION_2_0)  != 0 && AcpiSupportInstance->Fadt3 != NULL) ||
718         ((Version & EFI_ACPI_TABLE_VERSION_3_0)  != 0 && AcpiSupportInstance->Fadt3 != NULL)
719         ) {
720       gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
721       gBS->FreePool (CurrentTableList);
722       return EFI_ACCESS_DENIED;
723     }
724     //
725     // Add the table to the appropriate table version
726     //
727     if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
728       //
729       // Save a pointer to the table
730       //
731       AcpiSupportInstance->Fadt1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
732 
733       //
734       // Update pointers in FADT.  If tables don't exist this will put NULL pointers there.
735       //
736       AcpiSupportInstance->Fadt1->FirmwareCtrl  = (UINT32) (UINTN) AcpiSupportInstance->Facs1;
737       AcpiSupportInstance->Fadt1->Dsdt          = (UINT32) (UINTN) AcpiSupportInstance->Dsdt1;
738 
739       //
740       // RSDP OEM information is updated to match the FADT OEM information
741       //
742       CopyMem (
743         &AcpiSupportInstance->Rsdp1->OemId,
744         &AcpiSupportInstance->Fadt1->Header.OemId,
745         6
746         );
747 
748       //
749       // RSDT OEM information is updated to match the FADT OEM information.
750       //
751       CopyMem (
752         &AcpiSupportInstance->Rsdt1->OemId,
753         &AcpiSupportInstance->Fadt1->Header.OemId,
754         6
755         );
756 
757       CopyMem (
758         &AcpiSupportInstance->Rsdt1->OemTableId,
759         &AcpiSupportInstance->Fadt1->Header.OemTableId,
760         sizeof (UINT64)
761         );
762       AcpiSupportInstance->Rsdt1->OemRevision = AcpiSupportInstance->Fadt1->Header.OemRevision;
763     }
764 
765     if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
766         (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
767       //
768       // Save a pointer to the table
769       //
770       AcpiSupportInstance->Fadt3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) CurrentTableList->Table;
771 
772       //
773       // Update pointers in FADT.  If tables don't exist this will put NULL pointers there.
774       // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and
775       // vice-versa.
776       //
777       if ((UINT64)(UINTN)AcpiSupportInstance->Facs3 < BASE_4GB) {
778         AcpiSupportInstance->Fadt3->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs3;
779         ZeroMem (
780           &AcpiSupportInstance->Fadt3->XFirmwareCtrl,
781           sizeof (UINT64)
782           );
783       } else {
784         AcpiSupportInstance->Fadt3->FirmwareCtrl = 0;
785         Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Facs3;
786         CopyMem (
787           &AcpiSupportInstance->Fadt3->XFirmwareCtrl,
788           &Buffer64,
789           sizeof (UINT64)
790           );
791       }
792       AcpiSupportInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiSupportInstance->Dsdt3;
793       Buffer64                          = (UINT64) (UINTN) AcpiSupportInstance->Dsdt3;
794       CopyMem (
795         &AcpiSupportInstance->Fadt3->XDsdt,
796         &Buffer64,
797         sizeof (UINT64)
798         );
799 
800       //
801       // RSDP OEM information is updated to match the FADT OEM information
802       //
803       CopyMem (
804         &AcpiSupportInstance->Rsdp3->OemId,
805         &AcpiSupportInstance->Fadt3->Header.OemId,
806         6
807         );
808 
809       //
810       // RSDT OEM information is updated to match FADT OEM information.
811       //
812       CopyMem (
813         &AcpiSupportInstance->Rsdt3->OemId,
814         &AcpiSupportInstance->Fadt3->Header.OemId,
815         6
816         );
817       CopyMem (
818         &AcpiSupportInstance->Rsdt3->OemTableId,
819         &AcpiSupportInstance->Fadt3->Header.OemTableId,
820         sizeof (UINT64)
821         );
822       AcpiSupportInstance->Rsdt3->OemRevision = AcpiSupportInstance->Fadt3->Header.OemRevision;
823 
824       //
825       // XSDT OEM information is updated to match FADT OEM information.
826       //
827       CopyMem (
828         &AcpiSupportInstance->Xsdt->OemId,
829         &AcpiSupportInstance->Fadt3->Header.OemId,
830         6
831         );
832       CopyMem (
833         &AcpiSupportInstance->Xsdt->OemTableId,
834         &AcpiSupportInstance->Fadt3->Header.OemTableId,
835         sizeof (UINT64)
836         );
837       AcpiSupportInstance->Xsdt->OemRevision = AcpiSupportInstance->Fadt3->Header.OemRevision;
838     }
839 
840     //
841     // Checksum the table
842     //
843     if (Checksum) {
844       AcpiPlatformChecksum (
845         CurrentTableList->Table,
846         CurrentTableList->Table->Length,
847         OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
848         Checksum)
849         );
850     }
851     break;
852 
853   case EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
854     //
855     // Check that the table has not been previously added.
856     //
857    if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Facs1 != NULL) ||
858         ((Version & EFI_ACPI_TABLE_VERSION_2_0)  != 0 && AcpiSupportInstance->Facs3 != NULL) ||
859         ((Version & EFI_ACPI_TABLE_VERSION_3_0)  != 0 && AcpiSupportInstance->Facs3 != NULL)
860         ) {
861       gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
862       gBS->FreePool (CurrentTableList);
863       return EFI_ACCESS_DENIED;
864     }
865     //
866     // FACS is referenced by FADT and is not part of RSDT
867     //
868     AddToRsdt = FALSE;
869 
870     //
871     // Add the table to the appropriate table version
872     //
873     if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
874       //
875       // Save a pointer to the table
876       //
877       AcpiSupportInstance->Facs1 = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
878 
879       //
880       // If FADT already exists, update table pointers.
881       //
882       if (AcpiSupportInstance->Fadt1 != NULL) {
883         AcpiSupportInstance->Fadt1->FirmwareCtrl = (UINT32) (UINTN) AcpiSupportInstance->Facs1;
884 
885         //
886         // Checksum FADT table
887         //
888         AcpiPlatformChecksum (
889           AcpiSupportInstance->Fadt1,
890           AcpiSupportInstance->Fadt1->Header.Length,
891           OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
892           Checksum)
893           );
894       }
895     }
896 
897     if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
898         (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
899       //
900       // Save a pointer to the table
901       //
902       AcpiSupportInstance->Facs3 = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) CurrentTableList->Table;
903 
904       //
905       // If FADT already exists, update table pointers.
906       //
907       if (AcpiSupportInstance->Fadt3 != NULL) {
908         //
909         // Note: If the FIRMWARE_CTRL is non-zero, then X_FIRMWARE_CTRL must be zero, and
910         // vice-versa.
911         //
912         if ((UINT64)(UINTN)AcpiSupportInstance->Facs3 < BASE_4GB) {
913           AcpiSupportInstance->Fadt3->FirmwareCtrl  = (UINT32) (UINTN) AcpiSupportInstance->Facs3;
914         } else {
915           Buffer64 = (UINT64) (UINTN) AcpiSupportInstance->Facs3;
916           CopyMem (
917             &AcpiSupportInstance->Fadt3->XFirmwareCtrl,
918             &Buffer64,
919             sizeof (UINT64)
920             );
921         }
922 
923         //
924         // Checksum FADT table
925         //
926         AcpiPlatformChecksum (
927           AcpiSupportInstance->Fadt3,
928           AcpiSupportInstance->Fadt3->Header.Length,
929           OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
930           Checksum)
931           );
932       }
933     }
934 
935     break;
936 
937   case EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
938     //
939     // Check that the table has not been previously added.
940     //
941    if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiSupportInstance->Dsdt1 != NULL) ||
942         ((Version & EFI_ACPI_TABLE_VERSION_2_0)  != 0 && AcpiSupportInstance->Dsdt3 != NULL) ||
943         ((Version & EFI_ACPI_TABLE_VERSION_3_0)  != 0 && AcpiSupportInstance->Dsdt3 != NULL)
944         ) {
945       gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
946       gBS->FreePool (CurrentTableList);
947       return EFI_ACCESS_DENIED;
948     }
949     //
950     // DSDT is referenced by FADT and is not part of RSDT
951     //
952     AddToRsdt = FALSE;
953 
954     //
955     // Add the table to the appropriate table version
956     //
957     if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
958       //
959       // Save a pointer to the table
960       //
961       AcpiSupportInstance->Dsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
962 
963       //
964       // If FADT already exists, update table pointers.
965       //
966       if (AcpiSupportInstance->Fadt1 != NULL) {
967         AcpiSupportInstance->Fadt1->Dsdt = (UINT32) (UINTN) AcpiSupportInstance->Dsdt1;
968 
969         //
970         // Checksum FADT table
971         //
972         AcpiPlatformChecksum (
973           AcpiSupportInstance->Fadt1,
974           AcpiSupportInstance->Fadt1->Header.Length,
975           OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
976           Checksum)
977           );
978       }
979     }
980 
981      if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
982         (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
983       //
984       // Save a pointer to the table
985       //
986       AcpiSupportInstance->Dsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTableList->Table;
987 
988       //
989       // If FADT already exists, update table pointers.
990       //
991       if (AcpiSupportInstance->Fadt3 != NULL) {
992         AcpiSupportInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiSupportInstance->Dsdt3;
993         Buffer64                          = (UINT64) (UINTN) AcpiSupportInstance->Dsdt3;
994         CopyMem (
995           &AcpiSupportInstance->Fadt3->XDsdt,
996           &Buffer64,
997           sizeof (UINT64)
998           );
999 
1000         //
1001         // Checksum FADT table
1002         //
1003         AcpiPlatformChecksum (
1004           AcpiSupportInstance->Fadt3,
1005           AcpiSupportInstance->Fadt3->Header.Length,
1006           OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1007           Checksum)
1008           );
1009       }
1010     }
1011     //
1012     // Checksum the table
1013     //
1014     if (Checksum) {
1015       AcpiPlatformChecksum (
1016         CurrentTableList->Table,
1017         CurrentTableList->Table->Length,
1018         OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1019         Checksum)
1020         );
1021     }
1022     break;
1023 
1024   default:
1025     //
1026     // Checksum the table
1027     //
1028     if (Checksum) {
1029       AcpiPlatformChecksum (
1030         CurrentTableList->Table,
1031         CurrentTableList->Table->Length,
1032         OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1033         Checksum)
1034         );
1035     }
1036     break;
1037   }
1038   //
1039   // Add the table to the current list of tables
1040   //
1041   InsertTailList (&AcpiSupportInstance->TableList, &CurrentTableList->Link);
1042 
1043   //
1044   // Add the table to RSDT and/or XSDT table entry lists.
1045   //
1046   //
1047   // Add to ACPI 1.0b table tree
1048   //
1049   if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1050     if (AddToRsdt) {
1051       //
1052       // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer
1053       //
1054       if (AcpiSupportInstance->NumberOfTableEntries1 >= mEfiAcpiMaxNumTables) {
1055         Status = ReallocateAcpiTableBuffer (AcpiSupportInstance);
1056         ASSERT_EFI_ERROR (Status);
1057       }
1058       CurrentRsdtEntry = (UINT32 *)
1059         (
1060           (UINT8 *) AcpiSupportInstance->Rsdt1 +
1061           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
1062           AcpiSupportInstance->NumberOfTableEntries1 *
1063           sizeof (UINT32)
1064         );
1065 
1066       //
1067       // Add entry to the RSDT unless its the FACS or DSDT
1068       //
1069       *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
1070 
1071       //
1072       // Update RSDT length
1073       //
1074       AcpiSupportInstance->Rsdt1->Length = AcpiSupportInstance->Rsdt1->Length + sizeof (UINT32);
1075 
1076       AcpiSupportInstance->NumberOfTableEntries1++;
1077     }
1078   }
1079   //
1080   // Add to ACPI 2.0/3.0  table tree
1081   //
1082   if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 || (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1083     if (AddToRsdt) {
1084        //
1085        // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer
1086        //
1087        if (AcpiSupportInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) {
1088          Status = ReallocateAcpiTableBuffer (AcpiSupportInstance);
1089          ASSERT_EFI_ERROR (Status);
1090        }
1091       //
1092       // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
1093       // If it becomes necessary to maintain separate table lists, changes will be required.
1094       //
1095       CurrentRsdtEntry = (UINT32 *)
1096         (
1097           (UINT8 *) AcpiSupportInstance->Rsdt3 +
1098           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
1099           AcpiSupportInstance->NumberOfTableEntries3 *
1100           sizeof (UINT32)
1101         );
1102 
1103       //
1104       // This pointer must not be directly dereferenced as the XSDT entries may not
1105       // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.
1106       //
1107       CurrentXsdtEntry = (VOID *)
1108         (
1109           (UINT8 *) AcpiSupportInstance->Xsdt +
1110           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
1111           AcpiSupportInstance->NumberOfTableEntries3 *
1112           sizeof (UINT64)
1113         );
1114 
1115       //
1116       // Add entry to the RSDT
1117       //
1118       *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;
1119 
1120       //
1121       // Update RSDT length
1122       //
1123       AcpiSupportInstance->Rsdt3->Length = AcpiSupportInstance->Rsdt3->Length + sizeof (UINT32);
1124 
1125       //
1126       // Add entry to XSDT, XSDT expects 64 bit pointers, but
1127       // the table pointers in XSDT are not aligned on 8 byte boundary.
1128       //
1129       Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;
1130       CopyMem (
1131         CurrentXsdtEntry,
1132         &Buffer64,
1133         sizeof (UINT64)
1134         );
1135 
1136       //
1137       // Update length
1138       //
1139       AcpiSupportInstance->Xsdt->Length = AcpiSupportInstance->Xsdt->Length + sizeof (UINT64);
1140 
1141       AcpiSupportInstance->NumberOfTableEntries3++;
1142     }
1143   }
1144 
1145   ChecksumCommonTables (AcpiSupportInstance);
1146   return EFI_SUCCESS;
1147 }
1148 /**
1149   This function finds the table specified by the handle and returns a pointer to it.
1150   If the handle is not found, EFI_NOT_FOUND is returned and the contents of Table are
1151   undefined.
1152 
1153   @param  Handle      Table to find.
1154   @param  TableList   Table list to search
1155   @param  Table       Pointer to table found.
1156 
1157   @return EFI_SUCCESS    The function completed successfully.
1158   @return EFI_NOT_FOUND  No table found matching the handle specified.
1159 
1160 **/
1161 EFI_STATUS
FindTableByHandle(IN UINTN Handle,IN LIST_ENTRY * TableList,OUT EFI_ACPI_TABLE_LIST ** Table)1162 FindTableByHandle (
1163   IN UINTN                                Handle,
1164   IN LIST_ENTRY                       *TableList,
1165   OUT EFI_ACPI_TABLE_LIST                 **Table
1166   )
1167 {
1168   LIST_ENTRY      *CurrentLink;
1169   EFI_ACPI_TABLE_LIST *CurrentTable;
1170 
1171   //
1172   // Check for invalid input parameters
1173   //
1174   ASSERT (Table);
1175 
1176   //
1177   // Find the table
1178   //
1179   CurrentLink = TableList->ForwardLink;
1180 
1181   while (CurrentLink != TableList) {
1182     CurrentTable = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
1183     if (CurrentTable->Handle == Handle) {
1184       //
1185       // Found handle, so return this table.
1186       //
1187       *Table = CurrentTable;
1188       return EFI_SUCCESS;
1189     }
1190 
1191     CurrentLink = CurrentLink->ForwardLink;
1192   }
1193   //
1194   // Table not found
1195   //
1196   return EFI_NOT_FOUND;
1197 }
1198 /**
1199   This function removes a basic table from the RSDT and/or XSDT.
1200   For Acpi 1.0 tables, pass in the Rsdt.
1201   For Acpi 2.0 tables, pass in both Rsdt and Xsdt.
1202 
1203   @param  Table                 Pointer to table found.
1204   @param  NumberOfTableEntries  Current number of table entries in the RSDT/XSDT
1205   @param  Rsdt                  Pointer to the RSDT to remove from
1206   @param  Xsdt                  Pointer to the Xsdt to remove from
1207 
1208   @return EFI_SUCCESS            The function completed successfully.
1209   @return EFI_INVALID_PARAMETER  The table was not found in both Rsdt and Xsdt.
1210 
1211 **/
1212 EFI_STATUS
RemoveTableFromRsdt(IN OUT EFI_ACPI_TABLE_LIST * Table,IN OUT UINTN * NumberOfTableEntries,IN OUT EFI_ACPI_DESCRIPTION_HEADER * Rsdt,IN OUT EFI_ACPI_DESCRIPTION_HEADER * Xsdt OPTIONAL)1213 RemoveTableFromRsdt (
1214   IN OUT EFI_ACPI_TABLE_LIST              * Table,
1215   IN OUT UINTN                            *NumberOfTableEntries,
1216   IN OUT EFI_ACPI_DESCRIPTION_HEADER      * Rsdt,
1217   IN OUT EFI_ACPI_DESCRIPTION_HEADER      * Xsdt OPTIONAL
1218   )
1219 {
1220   UINT32  *CurrentRsdtEntry;
1221   VOID    *CurrentXsdtEntry;
1222   UINT64  CurrentTablePointer64;
1223   UINTN   TempIndex;
1224 
1225   //
1226   // Check for invalid input parameters
1227   //
1228   ASSERT (Table);
1229   ASSERT (NumberOfTableEntries);
1230   ASSERT (Rsdt);
1231 
1232   //
1233   // Find the table entry in the RSDT and XSDT
1234   //
1235   for (TempIndex = 0; TempIndex < *NumberOfTableEntries; TempIndex++) {
1236     //
1237     // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.
1238     // If it becomes necessary to maintain separate table lists, changes will be required.
1239     //
1240     CurrentRsdtEntry = (UINT32 *) ((UINT8 *) Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + TempIndex * sizeof (UINT32));
1241     if (Xsdt != NULL) {
1242       //
1243       // This pointer must not be directly dereferenced as the XSDT entries may not
1244       // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.
1245       //
1246       CurrentXsdtEntry = (VOID *) ((UINT8 *) Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + TempIndex * sizeof (UINT64));
1247 
1248       //
1249       // Read the entry value out of the XSDT
1250       //
1251       CopyMem (&CurrentTablePointer64, CurrentXsdtEntry, sizeof (UINT64));
1252     } else {
1253       //
1254       // Initialize to NULL
1255       //
1256       CurrentXsdtEntry      = 0;
1257       CurrentTablePointer64 = 0;
1258     }
1259     //
1260     // Check if we have found the corresponding entry in both RSDT and XSDT
1261     //
1262     if (*CurrentRsdtEntry == (UINT32) (UINTN) Table->Table &&
1263         ((Xsdt == NULL) || CurrentTablePointer64 == (UINT64) (UINTN) Table->Table)
1264         ) {
1265       //
1266       // Found entry, so copy all following entries and shrink table
1267       // We actually copy all + 1 to copy the initialized value of memory over
1268       // the last entry.
1269       //
1270       CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - TempIndex) * sizeof (UINT32));
1271       Rsdt->Length = Rsdt->Length - sizeof (UINT32);
1272       if (Xsdt != NULL) {
1273         CopyMem (CurrentXsdtEntry, ((UINT64 *) CurrentXsdtEntry) + 1, (*NumberOfTableEntries - TempIndex) * sizeof (UINT64));
1274         Xsdt->Length = Xsdt->Length - sizeof (UINT64);
1275       }
1276       break;
1277     } else if (TempIndex + 1 == *NumberOfTableEntries) {
1278       //
1279       // At the last entry, and table not found
1280       //
1281       return EFI_INVALID_PARAMETER;
1282     }
1283   }
1284   //
1285   // Checksum the tables
1286   //
1287   AcpiPlatformChecksum (
1288     Rsdt,
1289     Rsdt->Length,
1290     OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1291     Checksum)
1292     );
1293 
1294   if (Xsdt != NULL) {
1295     AcpiPlatformChecksum (
1296       Xsdt,
1297       Xsdt->Length,
1298       OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1299       Checksum)
1300       );
1301   }
1302   //
1303   // Decrement the number of tables
1304   //
1305   (*NumberOfTableEntries)--;
1306 
1307   return EFI_SUCCESS;
1308 }
1309 /**
1310   This function removes a table and frees any associated memory.
1311 
1312   @param  AcpiSupportInstance  Instance of the protocol.
1313   @param  Version            Version(s) to delete.
1314   @param  Table              Pointer to table found.
1315 
1316   @return EFI_SUCCESS  The function completed successfully.
1317 
1318 **/
1319 EFI_STATUS
DeleteTable(IN EFI_ACPI_SUPPORT_INSTANCE * AcpiSupportInstance,IN EFI_ACPI_TABLE_VERSION Version,IN OUT EFI_ACPI_TABLE_LIST * Table)1320 DeleteTable (
1321   IN EFI_ACPI_SUPPORT_INSTANCE            *AcpiSupportInstance,
1322   IN EFI_ACPI_TABLE_VERSION               Version,
1323   IN OUT EFI_ACPI_TABLE_LIST              *Table
1324   )
1325 {
1326   UINT32  CurrentTableSignature;
1327   BOOLEAN RemoveFromRsdt;
1328 
1329   //
1330   // Check for invalid input parameters
1331   //
1332   ASSERT (AcpiSupportInstance);
1333   ASSERT (Table);
1334 
1335   //
1336   // Init locals
1337   //
1338   RemoveFromRsdt        = TRUE;
1339 
1340   if (Table->Table != NULL) {
1341     CurrentTableSignature = ((EFI_ACPI_COMMON_HEADER *) Table->Table)->Signature;
1342 
1343     //
1344     // Basic tasks to accomplish delete are:
1345     //   Determine removal requirements (in RSDT/XSDT or not)
1346     //   Remove entry from RSDT/XSDT
1347     //   Remove any table references to the table
1348     //   If no one is using the table
1349     //      Free the table (removing pointers from private data and tables)
1350     //      Remove from list
1351     //      Free list structure
1352     //
1353     //
1354     // Determine if this table is in the RSDT or XSDT
1355     //
1356     if ((CurrentTableSignature == EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
1357         (CurrentTableSignature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||
1358         (CurrentTableSignature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)
1359         ) {
1360       RemoveFromRsdt = FALSE;
1361     }
1362     //
1363     // We don't remove the FADT in the standard way because some
1364     // OS expect the FADT to be early in the table list.
1365     // So we always put it as the first element in the list.
1366     //
1367     if (CurrentTableSignature == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
1368       RemoveFromRsdt = FALSE;
1369     }
1370 
1371     //
1372     // Remove the table from RSDT and XSDT
1373     //
1374 
1375     //
1376     // This is a basic table, remove it from any lists and the Rsdt and/or Xsdt
1377     //
1378     if (Version & EFI_ACPI_TABLE_VERSION_NONE & Table->Version) {
1379       //
1380       // Remove this version from the table
1381       //
1382       Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_NONE;
1383     }
1384 
1385     if (Version & EFI_ACPI_TABLE_VERSION_1_0B & Table->Version) {
1386       //
1387       // Remove this version from the table
1388       //
1389       Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_1_0B;
1390 
1391       //
1392       // Remove from Rsdt.  We don't care about the return value because it is
1393       // acceptable for the table to not exist in Rsdt.
1394       // We didn't add some tables so we don't remove them.
1395       //
1396       if (RemoveFromRsdt) {
1397         RemoveTableFromRsdt (
1398           Table,
1399           &AcpiSupportInstance->NumberOfTableEntries1,
1400           AcpiSupportInstance->Rsdt1,
1401           NULL
1402           );
1403       }
1404     }
1405 
1406     if ((Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) ||
1407         (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version)) {
1408       //
1409       // Remove this version from the table
1410       //
1411       if (Version & EFI_ACPI_TABLE_VERSION_2_0 & Table->Version) {
1412         Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_2_0;
1413       }
1414       if (Version & EFI_ACPI_TABLE_VERSION_3_0 & Table->Version) {
1415         Table->Version = Table->Version &~EFI_ACPI_TABLE_VERSION_3_0;
1416       }
1417 
1418       //
1419       // Remove from Rsdt and Xsdt.  We don't care about the return value
1420       // because it is acceptable for the table to not exist in Rsdt/Xsdt.
1421       // We didn't add some tables so we don't remove them.
1422       //
1423       if (RemoveFromRsdt) {
1424         RemoveTableFromRsdt (
1425           Table,
1426           &AcpiSupportInstance->NumberOfTableEntries3,
1427           AcpiSupportInstance->Rsdt3,
1428           AcpiSupportInstance->Xsdt
1429           );
1430       }
1431     }
1432     //
1433     // Free the table, clean up any dependent tables and our private data pointers.
1434     //
1435     switch (Table->Table->Signature) {
1436 
1437     case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
1438       if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1439         AcpiSupportInstance->Fadt1 = NULL;
1440       }
1441 
1442       if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1443           (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1444         AcpiSupportInstance->Fadt3 = NULL;
1445       }
1446       break;
1447 
1448     case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
1449       if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1450         AcpiSupportInstance->Facs1 = NULL;
1451 
1452         //
1453         // Update FADT table pointers
1454         //
1455         if (AcpiSupportInstance->Fadt1 != NULL) {
1456           AcpiSupportInstance->Fadt1->FirmwareCtrl = 0;
1457 
1458           //
1459           // Checksum table
1460           //
1461           AcpiPlatformChecksum (
1462             AcpiSupportInstance->Fadt1,
1463             AcpiSupportInstance->Fadt1->Header.Length,
1464             OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1465             Checksum)
1466             );
1467         }
1468       }
1469 
1470       if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1471           (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1472         AcpiSupportInstance->Facs3 = NULL;
1473 
1474         //
1475         // Update FADT table pointers
1476         //
1477         if (AcpiSupportInstance->Fadt3 != NULL) {
1478           AcpiSupportInstance->Fadt3->FirmwareCtrl = 0;
1479           ZeroMem (&AcpiSupportInstance->Fadt3->XFirmwareCtrl, sizeof (UINT64));
1480 
1481           //
1482           // Checksum table
1483           //
1484           AcpiPlatformChecksum (
1485             AcpiSupportInstance->Fadt3,
1486             AcpiSupportInstance->Fadt3->Header.Length,
1487             OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1488             Checksum)
1489             );
1490         }
1491       }
1492       break;
1493 
1494     case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
1495       if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
1496         AcpiSupportInstance->Dsdt1 = NULL;
1497 
1498         //
1499         // Update FADT table pointers
1500         //
1501         if (AcpiSupportInstance->Fadt1 != NULL) {
1502           AcpiSupportInstance->Fadt1->Dsdt = 0;
1503 
1504           //
1505           // Checksum table
1506           //
1507           AcpiPlatformChecksum (
1508             AcpiSupportInstance->Fadt1,
1509             AcpiSupportInstance->Fadt1->Header.Length,
1510             OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1511             Checksum)
1512             );
1513         }
1514       }
1515 
1516 
1517       if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||
1518           (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {
1519         AcpiSupportInstance->Dsdt3 = NULL;
1520 
1521         //
1522         // Update FADT table pointers
1523         //
1524         if (AcpiSupportInstance->Fadt3 != NULL) {
1525           AcpiSupportInstance->Fadt3->Dsdt = 0;
1526           ZeroMem (&AcpiSupportInstance->Fadt3->XDsdt, sizeof (UINT64));
1527 
1528           //
1529           // Checksum table
1530           //
1531           AcpiPlatformChecksum (
1532             AcpiSupportInstance->Fadt3,
1533             AcpiSupportInstance->Fadt3->Header.Length,
1534             OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1535             Checksum)
1536             );
1537         }
1538       }
1539       break;
1540 
1541     default:
1542       //
1543       // Do nothing
1544       //
1545       break;
1546     }
1547   }
1548   //
1549   // If no version is using this table anymore, remove and free list entry.
1550   //
1551   if (Table->Version == 0) {
1552     //
1553     // Free the Table
1554     //
1555     gBS->FreePages (Table->PageAddress, Table->NumberOfPages);
1556     RemoveEntryList (&(Table->Link));
1557     gBS->FreePool (Table);
1558   }
1559   //
1560   // Done
1561   //
1562   return EFI_SUCCESS;
1563 }
1564 /**
1565   This function finds and removes the table specified by the handle.
1566 
1567   @param  AcpiSupportInstance  Instance of the protocol.
1568   @param  Version              Bitmask of which versions to remove.
1569   @param  Handle               Table to remove.
1570 
1571   @return EFI_SUCCESS    The function completed successfully.
1572   @return EFI_ABORTED    An error occurred.
1573   @return EFI_NOT_FOUND  Handle not found in table list.
1574 **/
1575 EFI_STATUS
RemoveTableFromList(IN EFI_ACPI_SUPPORT_INSTANCE * AcpiSupportInstance,IN EFI_ACPI_TABLE_VERSION Version,IN UINTN Handle)1576 RemoveTableFromList (
1577   IN EFI_ACPI_SUPPORT_INSTANCE            *AcpiSupportInstance,
1578   IN EFI_ACPI_TABLE_VERSION               Version,
1579   IN UINTN                                Handle
1580   )
1581 {
1582   EFI_ACPI_TABLE_LIST *Table;
1583   EFI_STATUS          Status;
1584 
1585   Table = NULL;
1586 
1587   //
1588   // Check for invalid input parameters
1589   //
1590   ASSERT (AcpiSupportInstance);
1591 
1592   //
1593   // Find the table
1594   //
1595   Status = FindTableByHandle (
1596             Handle,
1597             &AcpiSupportInstance->TableList,
1598             &Table
1599             );
1600   if (EFI_ERROR (Status)) {
1601     return EFI_NOT_FOUND;
1602   }
1603   //
1604   // Remove the table
1605   //
1606   Status = DeleteTable (AcpiSupportInstance, Version, Table);
1607   if (EFI_ERROR (Status)) {
1608     return EFI_ABORTED;
1609   }
1610   //
1611   // Completed successfully
1612   //
1613   return EFI_SUCCESS;
1614 }
1615 /**
1616   This function calculates and updates an UINT8 checksum.
1617 
1618   @param  Buffer          Pointer to buffer to checksum
1619   @param  Size            Number of bytes to checksum
1620   @param  ChecksumOffset  Offset to place the checksum result in
1621 
1622   @return EFI_SUCCESS             The function completed successfully.
1623 
1624 **/
1625 EFI_STATUS
AcpiPlatformChecksum(IN VOID * Buffer,IN UINTN Size,IN UINTN ChecksumOffset)1626 AcpiPlatformChecksum (
1627   IN VOID       *Buffer,
1628   IN UINTN      Size,
1629   IN UINTN      ChecksumOffset
1630   )
1631 {
1632   UINT8 Sum;
1633   UINT8 *Ptr;
1634 
1635   Sum = 0;
1636   //
1637   // Initialize pointer
1638   //
1639   Ptr = Buffer;
1640 
1641   //
1642   // set checksum to 0 first
1643   //
1644   Ptr[ChecksumOffset] = 0;
1645 
1646   //
1647   // add all content of buffer
1648   //
1649   while ((Size--) != 0) {
1650     Sum = (UINT8) (Sum + (*Ptr++));
1651   }
1652   //
1653   // set checksum
1654   //
1655   Ptr                 = Buffer;
1656   Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
1657 
1658   return EFI_SUCCESS;
1659 }
1660 /**
1661   Checksum all versions of the common tables, RSDP, RSDT, XSDT.
1662 
1663   @param  AcpiSupportInstance  Protocol instance private data.
1664 
1665   @return EFI_SUCCESS        The function completed successfully.
1666 
1667 **/
1668 EFI_STATUS
ChecksumCommonTables(IN OUT EFI_ACPI_SUPPORT_INSTANCE * AcpiSupportInstance)1669 ChecksumCommonTables (
1670   IN OUT EFI_ACPI_SUPPORT_INSTANCE                 *AcpiSupportInstance
1671   )
1672 {
1673   //
1674   // RSDP ACPI 1.0 checksum for 1.0 table.  This is only the first 20 bytes of the structure
1675   //
1676   AcpiPlatformChecksum (
1677     AcpiSupportInstance->Rsdp1,
1678     sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1679     OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1680     Checksum)
1681     );
1682 
1683   //
1684   // RSDP ACPI 1.0 checksum for 2.0/3.0 table.  This is only the first 20 bytes of the structure
1685   //
1686   AcpiPlatformChecksum (
1687     AcpiSupportInstance->Rsdp3,
1688     sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1689     OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1690     Checksum)
1691     );
1692 
1693   //
1694   // RSDP ACPI 2.0/3.0 checksum, this is the entire table
1695   //
1696   AcpiPlatformChecksum (
1697     AcpiSupportInstance->Rsdp3,
1698     sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
1699     OFFSET_OF (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
1700     ExtendedChecksum)
1701     );
1702 
1703   //
1704   // RSDT checksums
1705   //
1706   AcpiPlatformChecksum (
1707     AcpiSupportInstance->Rsdt1,
1708     AcpiSupportInstance->Rsdt1->Length,
1709     OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1710     Checksum)
1711     );
1712 
1713   AcpiPlatformChecksum (
1714     AcpiSupportInstance->Rsdt3,
1715     AcpiSupportInstance->Rsdt3->Length,
1716     OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1717     Checksum)
1718     );
1719 
1720   //
1721   // XSDT checksum
1722   //
1723   AcpiPlatformChecksum (
1724     AcpiSupportInstance->Xsdt,
1725     AcpiSupportInstance->Xsdt->Length,
1726     OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER,
1727     Checksum)
1728     );
1729 
1730   return EFI_SUCCESS;
1731 }
1732 /**
1733   Constructor for the ACPI support protocol to initializes instance data.
1734 
1735   @param AcpiSupportInstance   Instance to construct
1736 
1737   @retval EFI_SUCCESS             Instance initialized.
1738   @retval  EFI_OUT_OF_RESOURCES  Unable to allocate required resources.
1739 **/
1740 EFI_STATUS
AcpiSupportAcpiSupportConstructor(IN EFI_ACPI_SUPPORT_INSTANCE * AcpiSupportInstance)1741 AcpiSupportAcpiSupportConstructor (
1742   IN EFI_ACPI_SUPPORT_INSTANCE                 *AcpiSupportInstance
1743   )
1744 {
1745   EFI_STATUS            Status;
1746   UINT64                CurrentData;
1747   UINTN                 TotalSize;
1748   UINTN                 RsdpTableSize;
1749   UINT8                 *Pointer;
1750   EFI_PHYSICAL_ADDRESS  PageAddress;
1751 
1752   //
1753   // Check for invalid input parameters
1754   //
1755   ASSERT (AcpiSupportInstance);
1756 
1757   InitializeListHead (&AcpiSupportInstance->TableList);
1758   AcpiSupportInstance->CurrentHandle              = 1;
1759   AcpiSupportInstance->AcpiSupport.GetAcpiTable   = GetAcpiTable;
1760   AcpiSupportInstance->AcpiSupport.SetAcpiTable   = SetAcpiTable;
1761   AcpiSupportInstance->AcpiSupport.PublishTables  = PublishTables;
1762 
1763   AcpiSupportInstance->AcpiTableProtocol.InstallAcpiTable   = InstallAcpiTable;
1764   AcpiSupportInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;
1765 
1766   //
1767   // Create RSDP table
1768   //
1769   RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
1770                   sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1771 
1772   PageAddress = 0xFFFFFFFF;
1773   Status = gBS->AllocatePages (
1774                   AllocateMaxAddress,
1775                   EfiACPIReclaimMemory,
1776                   EFI_SIZE_TO_PAGES (RsdpTableSize),
1777                   &PageAddress
1778                   );
1779 
1780   if (EFI_ERROR (Status)) {
1781     return EFI_OUT_OF_RESOURCES;
1782   }
1783 
1784   Pointer = (UINT8 *) (UINTN) PageAddress;
1785   ZeroMem (Pointer, RsdpTableSize);
1786 
1787   AcpiSupportInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
1788   Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1789   AcpiSupportInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
1790 
1791   //
1792   // Create RSDT, XSDT structures
1793   //
1794   TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT
1795               mEfiAcpiMaxNumTables * sizeof (UINT32) +
1796               sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT
1797               mEfiAcpiMaxNumTables * sizeof (UINT32) +
1798               sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT
1799               mEfiAcpiMaxNumTables * sizeof (UINT64);
1800 
1801   //
1802   // Allocate memory in the lower 32 bit of address range for
1803   // compatibility with ACPI 1.0 OS.
1804   //
1805   // This is done because ACPI 1.0 pointers are 32 bit values.
1806   // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
1807   // There is no architectural reason these should be below 4GB, it is purely
1808   // for convenience of implementation that we force memory below 4GB.
1809   //
1810   PageAddress = 0xFFFFFFFF;
1811   Status = gBS->AllocatePages (
1812                   AllocateMaxAddress,
1813                   EfiACPIReclaimMemory,
1814                   EFI_SIZE_TO_PAGES (TotalSize),
1815                   &PageAddress
1816                   );
1817 
1818   if (EFI_ERROR (Status)) {
1819     gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiSupportInstance->Rsdp1, EFI_SIZE_TO_PAGES (RsdpTableSize));
1820     return EFI_OUT_OF_RESOURCES;
1821   }
1822 
1823   Pointer = (UINT8 *) (UINTN) PageAddress;
1824   ZeroMem (Pointer, TotalSize);
1825 
1826   AcpiSupportInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1827   Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
1828   AcpiSupportInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1829   Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32));
1830   AcpiSupportInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
1831 
1832   //
1833   // Initialize RSDP
1834   //
1835   CurrentData = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
1836   CopyMem (&AcpiSupportInstance->Rsdp1->Signature, &CurrentData, sizeof (UINT64));
1837   CopyMem (AcpiSupportInstance->Rsdp1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdp1->OemId));
1838   AcpiSupportInstance->Rsdp1->Reserved    = EFI_ACPI_RESERVED_BYTE;
1839   AcpiSupportInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt1;
1840 
1841   CurrentData = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE;
1842   CopyMem (&AcpiSupportInstance->Rsdp3->Signature, &CurrentData, sizeof (UINT64));
1843   CopyMem (AcpiSupportInstance->Rsdp3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdp3->OemId));
1844   AcpiSupportInstance->Rsdp3->Revision    = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION;
1845   AcpiSupportInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiSupportInstance->Rsdt3;
1846   AcpiSupportInstance->Rsdp3->Length      = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
1847   CurrentData = (UINT64) (UINTN) AcpiSupportInstance->Xsdt;
1848   CopyMem (&AcpiSupportInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));
1849   SetMem (AcpiSupportInstance->Rsdp3->Reserved, 3, EFI_ACPI_RESERVED_BYTE);
1850 
1851   //
1852   // Initialize Rsdt
1853   //
1854   // Note that we "reserve" one entry for the FADT so it can always be
1855   // at the beginning of the list of tables.  Some OS don't seem
1856   // to find it correctly if it is too far down the list.
1857   //
1858   AcpiSupportInstance->Rsdt1->Signature = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1859   AcpiSupportInstance->Rsdt1->Length    = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1860   AcpiSupportInstance->Rsdt1->Revision  = EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1861   CopyMem (AcpiSupportInstance->Rsdt1->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdt1->OemId));
1862   CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);
1863   CopyMem (&AcpiSupportInstance->Rsdt1->OemTableId, &CurrentData, sizeof (UINT64));
1864   AcpiSupportInstance->Rsdt1->OemRevision     = PcdGet32 (PcdAcpiDefaultOemRevision);
1865   AcpiSupportInstance->Rsdt1->CreatorId       = PcdGet32 (PcdAcpiDefaultCreatorId);
1866   AcpiSupportInstance->Rsdt1->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
1867   //
1868   // We always reserve first one for FADT
1869   //
1870   AcpiSupportInstance->NumberOfTableEntries1  = 1;
1871   AcpiSupportInstance->Rsdt1->Length          = AcpiSupportInstance->Rsdt1->Length + sizeof(UINT32);
1872 
1873   AcpiSupportInstance->Rsdt3->Signature       = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1874   AcpiSupportInstance->Rsdt3->Length          = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1875   AcpiSupportInstance->Rsdt3->Revision        = EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
1876   CopyMem (AcpiSupportInstance->Rsdt3->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Rsdt3->OemId));
1877   CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);
1878   CopyMem (&AcpiSupportInstance->Rsdt3->OemTableId, &CurrentData, sizeof (UINT64));
1879   AcpiSupportInstance->Rsdt3->OemRevision     = PcdGet32 (PcdAcpiDefaultOemRevision);
1880   AcpiSupportInstance->Rsdt3->CreatorId       = PcdGet32 (PcdAcpiDefaultCreatorId);
1881   AcpiSupportInstance->Rsdt3->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
1882   //
1883   // We always reserve first one for FADT
1884   //
1885   AcpiSupportInstance->NumberOfTableEntries3  = 1;
1886   AcpiSupportInstance->Rsdt3->Length          = AcpiSupportInstance->Rsdt3->Length + sizeof(UINT32);
1887 
1888   //
1889   // Initialize Xsdt
1890   //
1891   AcpiSupportInstance->Xsdt->Signature  = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
1892   AcpiSupportInstance->Xsdt->Length     = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
1893   AcpiSupportInstance->Xsdt->Revision   = EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION;
1894   CopyMem (AcpiSupportInstance->Xsdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (AcpiSupportInstance->Xsdt->OemId));
1895   CurrentData = PcdGet64 (PcdAcpiDefaultOemTableId);
1896   CopyMem (&AcpiSupportInstance->Xsdt->OemTableId, &CurrentData, sizeof (UINT64));
1897   AcpiSupportInstance->Xsdt->OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
1898   AcpiSupportInstance->Xsdt->CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
1899   AcpiSupportInstance->Xsdt->CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
1900   //
1901   // We always reserve first one for FADT
1902   //
1903   AcpiSupportInstance->Xsdt->Length           = AcpiSupportInstance->Xsdt->Length + sizeof(UINT64);
1904 
1905   ChecksumCommonTables (AcpiSupportInstance);
1906 
1907   //
1908   // Completed successfully
1909   //
1910   return EFI_SUCCESS;
1911 }
1912