]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Add fix for the hardcoded Max ACPI table number. With this fix, the number of ACPI...
authorjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 11 May 2010 08:46:12 +0000 (08:46 +0000)
committerjchen20 <jchen20@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 11 May 2010 08:46:12 +0000 (08:46 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10480 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c

index b32c3d75a5dd9c4d0295fa718ace725208848280..b7efceba2de43c9d5209a8f9a77057954a05ee99 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   ACPI Table Protocol Implementation\r
 \r
-  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
 // Includes\r
 //\r
 #include "AcpiTable.h"\r
-\r
+//\r
+// The maximum number of tables that pre-allocated. \r
+//\r
+UINTN         mEfiAcpiMaxNumTables = EFI_ACPI_MAX_NUM_TABLES; \r
 \r
 /**\r
   This function adds an ACPI table to the table list.  It will detect FACS and\r
@@ -70,7 +73,6 @@ RemoveTableFromList (
   @param  ChecksumOffset  Offset to place the checksum result in\r
 \r
   @return EFI_SUCCESS             The function completed successfully.\r
-\r
 **/\r
 EFI_STATUS\r
 AcpiPlatformChecksum (\r
@@ -408,7 +410,118 @@ UninstallAcpiTable (
   }\r
 }\r
 \r
+/**\r
+  If the number of APCI tables exceeds the preallocated max table number, enlarge the table buffer.\r
+\r
+  @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 RSDP, RSDT, XSDT structures and allocate all buffers\r
+  //\r
+  TotalSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
+      sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
+      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
+      sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
+      NewMaxTableNumber * sizeof (UINT64);\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
+                  AllocateMaxAddress,\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->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;\r
+  Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+  AcpiTableInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;\r
+  Pointer += sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);\r
+\r
+  AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;\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
+  // Initialize RSDP\r
+  //\r
+  CopyMem (AcpiTableInstance->Rsdp1, TempPrivateData.Rsdp1, sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)); \r
+  AcpiTableInstance->Rsdp1->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt1;\r
+  \r
+  CopyMem (AcpiTableInstance->Rsdp3, TempPrivateData.Rsdp3, sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER)); \r
+  AcpiTableInstance->Rsdp3->RsdtAddress = (UINT32) (UINTN) AcpiTableInstance->Rsdt3;\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
+  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
+  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_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
+      sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
+      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
+      sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
+      mEfiAcpiMaxNumTables * sizeof (UINT64);\r
+  gBS->FreePages ((EFI_PHYSICAL_ADDRESS)TempPrivateData.Rsdp1, EFI_SIZE_TO_PAGES (TotalSize));\r
+  \r
+  //\r
+  // Update the Max ACPI table number\r
+  // \r
+  mEfiAcpiMaxNumTables = NewMaxTableNumber;\r
+  return EFI_SUCCESS;\r
+}\r
 /**\r
   This function adds an ACPI table to the table list.  It will detect FACS and\r
   allocate the correct type of memory and properly align the table.\r
@@ -865,90 +978,100 @@ AddTableToList (
   // Add to ACPI 1.0b table tree\r
   //\r
   if ((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {\r
-    CurrentRsdtEntry = (UINT32 *)\r
-      (\r
-        (UINT8 *) AcpiTableInstance->Rsdt1 +\r
-        sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
-        AcpiTableInstance->NumberOfTableEntries1 *\r
-        sizeof (UINT32)\r
-      );\r
-\r
-    //\r
-    // Add entry to the RSDT unless its the FACS or DSDT\r
-    //\r
-    if (AddToRsdt) {\r
-      *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;\r
-\r
-      //\r
-      // Update RSDT length\r
-      //\r
-      AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof (UINT32);\r
-\r
-      AcpiTableInstance->NumberOfTableEntries1++;\r
-    }\r
-\r
-    ASSERT (AcpiTableInstance->NumberOfTableEntries1 <= EFI_ACPI_MAX_NUM_TABLES);\r
-  }\r
-  //\r
-  // Add to ACPI 2.0/3.0  table tree\r
-  //\r
-  if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
-      (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
     if (AddToRsdt) {\r
       //\r
-      // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.\r
-      // If it becomes necessary to maintain separate table lists, changes will be required.\r
+      // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer\r
       //\r
+      if (AcpiTableInstance->NumberOfTableEntries1 >= mEfiAcpiMaxNumTables) {\r
+        Status = ReallocateAcpiTableBuffer (AcpiTableInstance);\r
+        ASSERT_EFI_ERROR (Status);\r
+      }\r
       CurrentRsdtEntry = (UINT32 *)\r
         (\r
-          (UINT8 *) AcpiTableInstance->Rsdt3 +\r
+          (UINT8 *) AcpiTableInstance->Rsdt1 +\r
           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
-          AcpiTableInstance->NumberOfTableEntries3 *\r
+          AcpiTableInstance->NumberOfTableEntries1 *\r
           sizeof (UINT32)\r
         );\r
 \r
       //\r
-      // This pointer must not be directly dereferenced as the XSDT entries may not\r
-      // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.\r
-      //\r
-      CurrentXsdtEntry = (VOID *)\r
-        (\r
-          (UINT8 *) AcpiTableInstance->Xsdt +\r
-          sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
-          AcpiTableInstance->NumberOfTableEntries3 *\r
-          sizeof (UINT64)\r
-        );\r
-\r
-      //\r
-      // Add entry to the RSDT\r
+      // Add entry to the RSDT unless its the FACS or DSDT\r
       //\r
       *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;\r
 \r
       //\r
       // Update RSDT length\r
       //\r
-      AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);\r
-\r
-      //\r
-      // Add entry to XSDT, XSDT expects 64 bit pointers, but\r
-      // the table pointers in XSDT are not aligned on 8 byte boundary.\r
-      //\r
-      Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;\r
-      CopyMem (\r
-        CurrentXsdtEntry,\r
-        &Buffer64,\r
-        sizeof (UINT64)\r
-        );\r
-\r
-      //\r
-      // Update length\r
-      //\r
-      AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);\r
+      AcpiTableInstance->Rsdt1->Length = AcpiTableInstance->Rsdt1->Length + sizeof (UINT32);\r
 \r
-      AcpiTableInstance->NumberOfTableEntries3++;\r
+      AcpiTableInstance->NumberOfTableEntries1++;\r
+    }\r
+  }\r
+  //\r
+  // Add to ACPI 2.0/3.0  table tree\r
+  //\r
+  if ((Version & EFI_ACPI_TABLE_VERSION_2_0) != 0 ||\r
+      (Version & EFI_ACPI_TABLE_VERSION_3_0) != 0) {\r
+     if (AddToRsdt) {\r
+       //\r
+       // If the table number exceed the gEfiAcpiMaxNumTables, enlarge the table buffer\r
+       //\r
+       if (AcpiTableInstance->NumberOfTableEntries3 >= mEfiAcpiMaxNumTables) {\r
+         Status = ReallocateAcpiTableBuffer (AcpiTableInstance);\r
+         ASSERT_EFI_ERROR (Status);\r
+       }\r
+       //\r
+       // At this time, it is assumed that RSDT and XSDT maintain parallel lists of tables.\r
+       // If it becomes necessary to maintain separate table lists, changes will be required.\r
+       //\r
+       CurrentRsdtEntry = (UINT32 *)\r
+         (\r
+           (UINT8 *) AcpiTableInstance->Rsdt3 +\r
+           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
+           AcpiTableInstance->NumberOfTableEntries3 *\r
+           sizeof (UINT32)\r
+         );\r
+\r
+       //\r
+       // This pointer must not be directly dereferenced as the XSDT entries may not\r
+       // be 64 bit aligned resulting in a possible fault.  Use CopyMem to update.\r
+       //\r
+       CurrentXsdtEntry = (VOID *)\r
+         (\r
+           (UINT8 *) AcpiTableInstance->Xsdt +\r
+           sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
+           AcpiTableInstance->NumberOfTableEntries3 *\r
+           sizeof (UINT64)\r
+         );\r
+\r
+       //\r
+       // Add entry to the RSDT\r
+       //\r
+       *CurrentRsdtEntry = (UINT32) (UINTN) CurrentTableList->Table;\r
+\r
+       //\r
+       // Update RSDT length\r
+       //\r
+       AcpiTableInstance->Rsdt3->Length = AcpiTableInstance->Rsdt3->Length + sizeof (UINT32);\r
+\r
+       //\r
+       // Add entry to XSDT, XSDT expects 64 bit pointers, but\r
+       // the table pointers in XSDT are not aligned on 8 byte boundary.\r
+       //\r
+       Buffer64 = (UINT64) (UINTN) CurrentTableList->Table;\r
+       CopyMem (\r
+         CurrentXsdtEntry,\r
+         &Buffer64,\r
+         sizeof (UINT64)\r
+         );\r
+\r
+       //\r
+       // Update length\r
+       //\r
+       AcpiTableInstance->Xsdt->Length = AcpiTableInstance->Xsdt->Length + sizeof (UINT64);\r
+\r
+       AcpiTableInstance->NumberOfTableEntries3++;\r
     }\r
-\r
-    ASSERT (AcpiTableInstance->NumberOfTableEntries3 <= EFI_ACPI_MAX_NUM_TABLES);\r
   }\r
 \r
   ChecksumCommonTables (AcpiTableInstance);\r
@@ -1593,11 +1716,11 @@ AcpiTableAcpiTableConstructor (
   TotalSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
       sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +\r
       sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 1.0 RSDT\r
-      EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +\r
+      mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
       sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 RSDT\r
-      EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT32) +\r
+      mEfiAcpiMaxNumTables * sizeof (UINT32) +\r
       sizeof (EFI_ACPI_DESCRIPTION_HEADER) +         // for ACPI 2.0/3.0 XSDT\r
-      EFI_ACPI_MAX_NUM_TABLES * sizeof (UINT64);\r
+      mEfiAcpiMaxNumTables * sizeof (UINT64);\r
 \r
   //\r
   // Allocate memory in the lower 32 bit of address range for\r