]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
Small code refinement in MdeModulePkg.
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AcpiTableProtocol.c
index 1e9a7d5e1020337c86a0e2af20776d38da5db447..23117b1ded24847a05e792f56dfaf0b4fdd9c2e9 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   ACPI Table Protocol Implementation\r
 \r
-  Copyright (c) 2006 - 2009, Intel Corporation<BR>\r
-  All rights reserved. This program and the accompanying materials\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
   http://opensource.org/licenses/bsd-license.php\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)(UINTN)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
@@ -606,61 +719,59 @@ AddTableToList (
       //\r
       // Update pointers in FADT.  If tables don't exist this will put NULL pointers there.\r
       //\r
-      if (AcpiTableInstance->Fadt3 != NULL) {\r
-        AcpiTableInstance->Fadt3->FirmwareCtrl  = (UINT32) (UINTN) AcpiTableInstance->Facs3;\r
-        Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;\r
-        CopyMem (\r
-          &AcpiTableInstance->Fadt3->XFirmwareCtrl,\r
-          &Buffer64,\r
-          sizeof (UINT64)\r
-          );\r
-        AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
-        Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
-        CopyMem (\r
-          &AcpiTableInstance->Fadt3->XDsdt,\r
-          &Buffer64,\r
-          sizeof (UINT64)\r
-          );\r
+      AcpiTableInstance->Fadt3->FirmwareCtrl  = (UINT32) (UINTN) AcpiTableInstance->Facs3;\r
+      Buffer64 = (UINT64) (UINTN) AcpiTableInstance->Facs3;\r
+      CopyMem (\r
+        &AcpiTableInstance->Fadt3->XFirmwareCtrl,\r
+        &Buffer64,\r
+        sizeof (UINT64)\r
+        );\r
+      AcpiTableInstance->Fadt3->Dsdt  = (UINT32) (UINTN) AcpiTableInstance->Dsdt3;\r
+      Buffer64                          = (UINT64) (UINTN) AcpiTableInstance->Dsdt3;\r
+      CopyMem (\r
+        &AcpiTableInstance->Fadt3->XDsdt,\r
+        &Buffer64,\r
+        sizeof (UINT64)\r
+        );\r
 \r
-        //\r
-        // RSDP OEM information is updated to match the FADT OEM information\r
-        //\r
-        CopyMem (\r
-          &AcpiTableInstance->Rsdp3->OemId,\r
-          &AcpiTableInstance->Fadt3->Header.OemId,\r
-          6\r
-          );\r
-        \r
-        //\r
-        // RSDT OEM information is updated to match FADT OEM information.\r
-        //\r
-        CopyMem (\r
-          &AcpiTableInstance->Rsdt3->OemId,\r
-          &AcpiTableInstance->Fadt3->Header.OemId,\r
-          6\r
-          );\r
-        CopyMem (\r
-          &AcpiTableInstance->Rsdt3->OemTableId,\r
-          &AcpiTableInstance->Fadt3->Header.OemTableId,\r
-          sizeof (UINT64)\r
-          );\r
-        AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
-        \r
-        //\r
-        // XSDT OEM information is updated to match FADT OEM information.\r
-        //\r
-        CopyMem (\r
-          &AcpiTableInstance->Xsdt->OemId,\r
-          &AcpiTableInstance->Fadt3->Header.OemId,\r
-          6\r
-          );\r
-        CopyMem (\r
-          &AcpiTableInstance->Xsdt->OemTableId,\r
-          &AcpiTableInstance->Fadt3->Header.OemTableId,\r
-          sizeof (UINT64)\r
-          );\r
-        AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
-      }\r
+      //\r
+      // RSDP OEM information is updated to match the FADT OEM information\r
+      //\r
+      CopyMem (\r
+        &AcpiTableInstance->Rsdp3->OemId,\r
+        &AcpiTableInstance->Fadt3->Header.OemId,\r
+        6\r
+        );\r
+      \r
+      //\r
+      // RSDT OEM information is updated to match FADT OEM information.\r
+      //\r
+      CopyMem (\r
+        &AcpiTableInstance->Rsdt3->OemId,\r
+        &AcpiTableInstance->Fadt3->Header.OemId,\r
+        6\r
+        );\r
+      CopyMem (\r
+        &AcpiTableInstance->Rsdt3->OemTableId,\r
+        &AcpiTableInstance->Fadt3->Header.OemTableId,\r
+        sizeof (UINT64)\r
+        );\r
+      AcpiTableInstance->Rsdt3->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
+      \r
+      //\r
+      // XSDT OEM information is updated to match FADT OEM information.\r
+      //\r
+      CopyMem (\r
+        &AcpiTableInstance->Xsdt->OemId,\r
+        &AcpiTableInstance->Fadt3->Header.OemId,\r
+        6\r
+        );\r
+      CopyMem (\r
+        &AcpiTableInstance->Xsdt->OemTableId,\r
+        &AcpiTableInstance->Fadt3->Header.OemTableId,\r
+        sizeof (UINT64)\r
+        );\r
+      AcpiTableInstance->Xsdt->OemRevision = AcpiTableInstance->Fadt3->Header.OemRevision;\r
     }    \r
     //\r
     // Checksum the table\r
@@ -865,90 +976,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 +1714,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