+ @param AcpiTableInstance ACPI table protocol instance data structure.\r
+\r
+ @return EFI_SUCCESS reallocate the table beffer successfully.\r
+ @return EFI_OUT_OF_RESOURCES Unable to allocate required resources.\r
+\r
+**/\r
+EFI_STATUS\r
+ReallocateAcpiTableBuffer (\r
+ IN EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance\r
+ )\r
+{\r
+ UINTN NewMaxTableNumber;\r
+ UINTN TotalSize;\r
+ UINT8 *Pointer;\r
+ EFI_PHYSICAL_ADDRESS PageAddress;\r
+ EFI_ACPI_TABLE_INSTANCE TempPrivateData;\r
+ EFI_STATUS Status;\r
+ UINT64 CurrentData;\r
+ \r
+ CopyMem (&TempPrivateData, AcpiTableInstance, sizeof (EFI_ACPI_TABLE_INSTANCE)); \r
+ //\r
+ // Enlarge the max table number from mEfiAcpiMaxNumTables to mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES\r
+ //\r
+ NewMaxTableNumber = mEfiAcpiMaxNumTables + EFI_ACPI_MAX_NUM_TABLES;\r
+ //\r
+ // Create RSDT, XSDT structures and allocate buffers.\r
+ //\r
+ TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT\r
+ NewMaxTableNumber * sizeof (UINT64);\r
+\r
+ if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+ TotalSize += sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT\r
+ NewMaxTableNumber * sizeof (UINT32) +\r
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT\r
+ NewMaxTableNumber * sizeof (UINT32);\r
+ }\r
+\r
+ //\r
+ // Allocate memory in the lower 32 bit of address range for\r
+ // compatibility with ACPI 1.0 OS.\r
+ //\r
+ // This is done because ACPI 1.0 pointers are 32 bit values.\r
+ // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.\r
+ // There is no architectural reason these should be below 4GB, it is purely\r
+ // for convenience of implementation that we force memory below 4GB.\r
+ //\r
+ PageAddress = 0xFFFFFFFF;\r
+ Status = gBS->AllocatePages (\r
+ mAcpiTableAllocType,\r
+ EfiACPIReclaimMemory,\r
+ EFI_SIZE_TO_PAGES (TotalSize),\r
+ &PageAddress\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Pointer = (UINT8 *) (UINTN) PageAddress;\r
+ ZeroMem (Pointer, TotalSize);\r
+ \r
+ AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
+ if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+ Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
+ AcpiTableInstance->Rsdt3 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
+ Pointer += (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + NewMaxTableNumber * sizeof (UINT32));\r
+ }\r
+ AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\r
+\r
+ //\r
+ // Update RSDP to point to the new Rsdt and Xsdt address.\r
+ //\r
+ if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+ AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
+ AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\r
+ }\r
+ CurrentData = (UINT64) (UINTN) AcpiTableInstance->Xsdt;\r
+ CopyMem (&AcpiTableInstance->Rsdp3->XsdtAddress, &CurrentData, sizeof (UINT64));\r
+\r
+ //\r
+ // copy the original Rsdt1, Rsdt3 and Xsdt structure to new buffer \r
+ //\r
+ if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+ CopyMem (AcpiTableInstance->Rsdt1, TempPrivateData.Rsdt1, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); \r
+ CopyMem (AcpiTableInstance->Rsdt3, TempPrivateData.Rsdt3, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT32))); \r
+ }\r
+ CopyMem (AcpiTableInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64)));\r
+ \r
+ //\r
+ // Calculate orignal ACPI table buffer size\r
+ //\r
+ TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT\r
+ mEfiAcpiMaxNumTables * sizeof (UINT64);\r
+\r
+ if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
+ TotalSize += sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT\r
+ mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT\r
+ mEfiAcpiMaxNumTables * sizeof (UINT32);\r
+ }\r
+\r
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize));\r
+ \r
+ //\r
+ // Update the Max ACPI table number\r
+ // \r
+ mEfiAcpiMaxNumTables = NewMaxTableNumber;\r
+ return EFI_SUCCESS;\r
+}\r