]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / SmbiosDxe / SmbiosDxe.c
index 596e8b2d8bb2774a0647e664f218930b327cfbf8..3cdb0b1ed74f1a4ea3c8e9747f9ca050e02f77b5 100644 (file)
@@ -1,15 +1,9 @@
 /** @file\r
-  This code produces the Smbios protocol. It also responsible for constructing \r
+  This code produces the Smbios protocol. It also responsible for constructing\r
   SMBIOS table into system table.\r
-  \r
-Copyright (c) 2009 - 2011, 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
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -22,6 +16,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 SMBIOS_INSTANCE mPrivateData;\r
 \r
+UINTN mPreAllocatedPages      = 0;\r
+UINTN mPre64BitAllocatedPages = 0;\r
+\r
 //\r
 // Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.\r
 //\r
@@ -47,11 +44,11 @@ SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {
   //\r
   // MajorVersion\r
   //\r
-  (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) >> 8),\r
+  0,\r
   //\r
   // MinorVersion\r
   //\r
-  (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) & 0x00ff),\r
+  0,\r
   //\r
   // MaxStructureSize, TO BE FILLED\r
   //\r
@@ -85,11 +82,11 @@ SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {
   //\r
   0,\r
   //\r
-  // StructureTableLength, TO BE FILLED\r
+  // TableLength, TO BE FILLED\r
   //\r
   0,\r
   //\r
-  // StructureTableAddress, TO BE FILLED\r
+  // TableAddress, TO BE FILLED\r
   //\r
   0,\r
   //\r
@@ -99,11 +96,58 @@ SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {
   //\r
   // SmbiosBcdRevision\r
   //\r
-  0  \r
+  0\r
 };\r
 \r
-\r
-\r
+SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios30EntryPointStructure    = NULL;\r
+SMBIOS_TABLE_3_0_ENTRY_POINT Smbios30EntryPointStructureData = {\r
+  //\r
+  // AnchorString _SM3_\r
+  //\r
+  {\r
+    0x5f,\r
+    0x53,\r
+    0x4d,\r
+    0x33,\r
+    0x5f,\r
+  },\r
+  //\r
+  // EntryPointStructureChecksum,TO BE FILLED\r
+  //\r
+  0,\r
+  //\r
+  // EntryPointLength\r
+  //\r
+  0x18,\r
+  //\r
+  // MajorVersion\r
+  //\r
+  0,\r
+  //\r
+  // MinorVersion\r
+  //\r
+  0,\r
+  //\r
+  // DocRev\r
+  //\r
+  0,\r
+  //\r
+  // EntryPointRevision\r
+  //\r
+  0x01,\r
+  //\r
+  // Reserved\r
+  //\r
+  0,\r
+  //\r
+  // TableMaximumSize,TO BE FILLED\r
+  //\r
+  0,\r
+  //\r
+  // TableAddress,TO BE FILLED\r
+  //\r
+  0\r
+};\r
 /**\r
 \r
   Get the full size of SMBIOS structure including optional strings that follow the formatted structure.\r
@@ -115,7 +159,7 @@ SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {
 \r
   @retval EFI_SUCCESS           Size retured in Size.\r
   @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -127,9 +171,10 @@ GetSmbiosStructureSize (
   )\r
 {\r
   UINTN  FullSize;\r
-  UINT8  StrLen;\r
+  UINTN  StrLen;\r
+  UINTN  MaxLen;\r
   INT8*  CharInStr;\r
-  \r
+\r
   if (Size == NULL || NumberOfStrings == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -142,33 +187,40 @@ GetSmbiosStructureSize (
   //\r
   // look for the two consecutive zeros, check the string limit by the way.\r
   //\r
-  while (*CharInStr != 0 || *(CharInStr+1) != 0) { \r
+  while (*CharInStr != 0 || *(CharInStr+1) != 0) {\r
     if (*CharInStr == 0) {\r
       *Size += 1;\r
       CharInStr++;\r
     }\r
 \r
     if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)){\r
-      for (StrLen = 0 ; StrLen < SMBIOS_STRING_MAX_LENGTH; StrLen++) {\r
-        if (*(CharInStr+StrLen) == 0) {\r
-          break;\r
-        }\r
-      }\r
-\r
-      if (StrLen == SMBIOS_STRING_MAX_LENGTH) {\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
+      MaxLen = SMBIOS_STRING_MAX_LENGTH;\r
+    } else if (This->MajorVersion < 3) {\r
+      //\r
+      // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.\r
+      // However, the length of the entire structure table (including all strings) must be reported\r
+      // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
+      // which is a WORD field limited to 65,535 bytes.\r
+      //\r
+      MaxLen = SMBIOS_TABLE_MAX_LENGTH;\r
     } else {\r
       //\r
-      // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string\r
+      // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.\r
+      // Locate the end of string as long as possible.\r
       //\r
-      for (StrLen = 0 ;; StrLen++) {\r
-        if (*(CharInStr+StrLen) == 0) {\r
-          break;\r
-        }\r
+      MaxLen = SMBIOS_3_0_TABLE_MAX_LENGTH;\r
+    }\r
+\r
+    for (StrLen = 0 ; StrLen < MaxLen; StrLen++) {\r
+      if (*(CharInStr+StrLen) == 0) {\r
+        break;\r
       }\r
     }\r
 \r
+    if (StrLen == MaxLen) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
     //\r
     // forward the pointer\r
     //\r
@@ -193,7 +245,7 @@ GetSmbiosStructureSize (
 \r
   @retval TRUE       Smbios handle already in use.\r
   @retval FALSE      Smbios handle is NOT used.\r
-  \r
+\r
 **/\r
 BOOLEAN\r
 EFIAPI\r
@@ -204,7 +256,7 @@ CheckSmbiosHandleExistance (
 {\r
   LIST_ENTRY              *Link;\r
   SMBIOS_HANDLE_ENTRY     *HandleEntry;\r
-  \r
+\r
   for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
     HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link);\r
     if (HandleEntry->SmbiosHandle == Handle) {\r
@@ -228,7 +280,7 @@ EFIAPI
 GetMaxSmbiosHandle (\r
   IN CONST  EFI_SMBIOS_PROTOCOL   *This,\r
   IN OUT    EFI_SMBIOS_HANDLE     *MaxHandle\r
-  ) \r
+  )\r
 {\r
   if (This->MajorVersion == 2 && This->MinorVersion == 0) {\r
     *MaxHandle = 0xFFFE;\r
@@ -246,7 +298,7 @@ GetMaxSmbiosHandle (
 \r
   @retval EFI_SUCCESS            Smbios handle got.\r
   @retval EFI_OUT_OF_RESOURCES   Smbios handle is NOT available.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -264,7 +316,7 @@ GetAvailableSmbiosHandle (
 \r
   Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
   Head = &Private->AllocatedHandleListHead;\r
-  for (AvailableHandle = 1; AvailableHandle < MaxSmbiosHandle; AvailableHandle++) {\r
+  for (AvailableHandle = 0; AvailableHandle < MaxSmbiosHandle; AvailableHandle++) {\r
     if (!CheckSmbiosHandleExistance(Head, AvailableHandle)) {\r
       *Handle = AvailableHandle;\r
       return EFI_SUCCESS;\r
@@ -281,12 +333,12 @@ GetAvailableSmbiosHandle (
   @param  This                  The EFI_SMBIOS_PROTOCOL instance.\r
   @param  ProducerHandle        The handle of the controller or driver associated with the SMBIOS information. NULL\r
                                 means no handle.\r
-  @param  SmbiosHandle          On entry, if non-zero, the handle of the SMBIOS record. If zero, then a unique handle\r
-                                will be assigned to the SMBIOS record. If the SMBIOS handle is already in use\r
+  @param  SmbiosHandle          On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle\r
+                                will be assigned to the SMBIOS record. If the SMBIOS handle is already in use,\r
                                 EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.\r
   @param  Record                The data for the fixed portion of the SMBIOS record. The format of the record is\r
-                                determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined \r
-                                by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or \r
+                                determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined\r
+                                by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or\r
                                 a set of null terminated strings and a null.\r
 \r
   @retval EFI_SUCCESS           Record was added.\r
@@ -315,24 +367,26 @@ SmbiosAdd (
   EFI_SMBIOS_HANDLE           MaxSmbiosHandle;\r
   SMBIOS_HANDLE_ENTRY         *HandleEntry;\r
   EFI_SMBIOS_RECORD_HEADER    *InternalRecord;\r
-  \r
+  BOOLEAN                     Smbios32BitTable;\r
+  BOOLEAN                     Smbios64BitTable;\r
+\r
   if (SmbiosHandle == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
   Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
   //\r
   // Check whether SmbiosHandle is already in use\r
   //\r
   Head = &Private->AllocatedHandleListHead;\r
-  if (*SmbiosHandle != 0 && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) {\r
+  if (*SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
 \r
   //\r
-  // when SmbiosHandle is zero, an available handle will be assigned\r
+  // when SmbiosHandle is 0xFFFE, an available handle will be assigned\r
   //\r
-  if (*SmbiosHandle == 0) {\r
+  if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {\r
     Status = GetAvailableSmbiosHandle(This, SmbiosHandle);\r
     if (EFI_ERROR(Status)) {\r
       return Status;\r
@@ -355,14 +409,56 @@ SmbiosAdd (
     return Status;\r
   }\r
 \r
+  Smbios32BitTable = FALSE;\r
+  Smbios64BitTable = FALSE;\r
+  if ((This->MajorVersion < 0x3) ||\r
+      ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) {\r
+    //\r
+    // For SMBIOS 32-bit table, the length of the entire structure table (including all strings) must be reported\r
+    // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
+    // which is a WORD field limited to 65,535 bytes. So the max size of 32-bit table should not exceed 65,535 bytes.\r
+    //\r
+    if ((EntryPointStructure != NULL) &&\r
+        (EntryPointStructure->TableLength + StructureSize > SMBIOS_TABLE_MAX_LENGTH)) {\r
+      DEBUG ((EFI_D_INFO, "SmbiosAdd: Total length exceeds max 32-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize));\r
+    } else {\r
+      Smbios32BitTable = TRUE;\r
+      DEBUG ((EFI_D_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 32-bit table\n", Record->Type, StructureSize));\r
+    }\r
+  }\r
+\r
+  //\r
+  // For SMBIOS 3.0, Structure table maximum size in Entry Point structure is DWORD field limited to 0xFFFFFFFF bytes.\r
+  //\r
+  if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {\r
+    //\r
+    // For SMBIOS 64-bit table, Structure table maximum size in SMBIOS 3.0 (64-bit) Entry Point\r
+    // is a DWORD field limited to 0xFFFFFFFF bytes. So the max size of 64-bit table should not exceed 0xFFFFFFFF bytes.\r
+    //\r
+    if ((Smbios30EntryPointStructure != NULL) &&\r
+        (Smbios30EntryPointStructure->TableMaximumSize + StructureSize > SMBIOS_3_0_TABLE_MAX_LENGTH)) {\r
+      DEBUG ((EFI_D_INFO, "SmbiosAdd: Total length exceeds max 64-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize));\r
+    } else {\r
+      DEBUG ((EFI_D_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 64-bit table\n", Record->Type, StructureSize));\r
+      Smbios64BitTable = TRUE;\r
+    }\r
+  }\r
+\r
+  if ((!Smbios32BitTable) && (!Smbios64BitTable)) {\r
+    //\r
+    // If both 32-bit and 64-bit table are not updated, quit\r
+    //\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
   //\r
   // Enter into critical section\r
-  //  \r
+  //\r
   Status = EfiAcquireLockOrFail (&Private->DataLock);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  \r
+\r
   RecordSize  = sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize;\r
   TotalSize   = sizeof (EFI_SMBIOS_ENTRY) + RecordSize;\r
 \r
@@ -404,6 +500,8 @@ SmbiosAdd (
   SmbiosEntry->Signature    = EFI_SMBIOS_ENTRY_SIGNATURE;\r
   SmbiosEntry->RecordHeader = InternalRecord;\r
   SmbiosEntry->RecordSize   = TotalSize;\r
+  SmbiosEntry->Smbios32BitTable = Smbios32BitTable;\r
+  SmbiosEntry->Smbios64BitTable = Smbios64BitTable;\r
   InsertTailList (&Private->DataListHead, &SmbiosEntry->Link);\r
 \r
   CopyMem (Raw, Record, StructureSize);\r
@@ -415,8 +513,8 @@ SmbiosAdd (
   // configuration table, so other UEFI drivers can get SMBIOS table from\r
   // configuration table without depending on PI SMBIOS protocol.\r
   //\r
-  SmbiosTableConstruction ();\r
-  \r
+  SmbiosTableConstruction (Smbios32BitTable, Smbios64BitTable);\r
+\r
   //\r
   // Leave critical section\r
   //\r
@@ -434,7 +532,7 @@ SmbiosAdd (
 \r
   @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.\r
   @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.\r
-  @retval EFI_UNSUPPORTED       String was not added since it's longer than 64 significant characters.\r
+  @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.\r
   @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.\r
 \r
 **/\r
@@ -463,7 +561,7 @@ SmbiosUpdateString (
   EFI_SMBIOS_HANDLE         MaxSmbiosHandle;\r
   EFI_SMBIOS_TABLE_HEADER   *Record;\r
   EFI_SMBIOS_RECORD_HEADER  *InternalRecord;\r
-  \r
+\r
   //\r
   // Check args validity\r
   //\r
@@ -483,19 +581,34 @@ SmbiosUpdateString (
 \r
   InputStrLen = AsciiStrLen(String);\r
 \r
-  //\r
-  // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string\r
-  //\r
   if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) {\r
     if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
       return EFI_UNSUPPORTED;\r
     }\r
+  } else if (This->MajorVersion < 3) {\r
+    //\r
+    // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.\r
+    // However, the length of the entire structure table (including all strings) must be reported\r
+    // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
+    // which is a WORD field limited to 65,535 bytes.\r
+    //\r
+    if (InputStrLen > SMBIOS_TABLE_MAX_LENGTH) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  } else {\r
+    if (InputStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH) {\r
+      //\r
+      // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.\r
+      // The input string length should not exceed 0xFFFFFFFF bytes.\r
+      //\r
+      return EFI_UNSUPPORTED;\r
+    }\r
   }\r
 \r
   Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
   //\r
   // Enter into critical section\r
-  //  \r
+  //\r
   Status = EfiAcquireLockOrFail (&Private->DataLock);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -518,7 +631,7 @@ SmbiosUpdateString (
       // Point to unformed string section\r
       //\r
       StrStart = (CHAR8 *) Record + Record->Length;\r
-     \r
+\r
       for (StrIndex = 1, TargetStrOffset = 0; StrIndex < *StringNumber; StrStart++, TargetStrOffset++) {\r
         //\r
         // A string ends in 00h\r
@@ -526,38 +639,77 @@ SmbiosUpdateString (
         if (*StrStart == 0) {\r
           StrIndex++;\r
         }\r
-        \r
+\r
         //\r
         // String section ends in double-null (0000h)\r
         //\r
         if (*StrStart == 0 && *(StrStart + 1) == 0) {\r
           EfiReleaseLock (&Private->DataLock);\r
           return EFI_NOT_FOUND;\r
-        } \r
+        }\r
       }\r
 \r
       if (*StrStart == 0) {\r
         StrStart++;\r
         TargetStrOffset++;\r
       }\r
-      \r
+\r
       //\r
       // Now we get the string target\r
       //\r
       TargetStrLen = AsciiStrLen(StrStart);\r
       if (InputStrLen == TargetStrLen) {\r
-        AsciiStrCpy(StrStart, String);\r
+        AsciiStrCpyS(StrStart, TargetStrLen + 1, String);\r
         //\r
         // Some UEFI drivers (such as network) need some information in SMBIOS table.\r
         // Here we create SMBIOS table and publish it in\r
         // configuration table, so other UEFI drivers can get SMBIOS table from\r
         // configuration table without depending on PI SMBIOS protocol.\r
         //\r
-        SmbiosTableConstruction ();\r
+        SmbiosTableConstruction (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable);\r
         EfiReleaseLock (&Private->DataLock);\r
         return EFI_SUCCESS;\r
       }\r
 \r
+      SmbiosEntry->Smbios32BitTable = FALSE;\r
+      SmbiosEntry->Smbios64BitTable = FALSE;\r
+      if ((This->MajorVersion < 0x3) ||\r
+          ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) {\r
+        //\r
+        // 32-bit table is produced, check the valid length.\r
+        //\r
+        if ((EntryPointStructure != NULL) &&\r
+            (EntryPointStructure->TableLength + InputStrLen - TargetStrLen > SMBIOS_TABLE_MAX_LENGTH)) {\r
+          //\r
+          // The length of the entire structure table (including all strings) must be reported\r
+          // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,\r
+          // which is a WORD field limited to 65,535 bytes.\r
+          //\r
+          DEBUG ((EFI_D_INFO, "SmbiosUpdateString: Total length exceeds max 32-bit table length\n"));\r
+        } else {\r
+          DEBUG ((EFI_D_INFO, "SmbiosUpdateString: New smbios record add to 32-bit table\n"));\r
+          SmbiosEntry->Smbios32BitTable = TRUE;\r
+        }\r
+      }\r
+\r
+      if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {\r
+        //\r
+        // 64-bit table is produced, check the valid length.\r
+        //\r
+        if ((Smbios30EntryPointStructure != NULL) &&\r
+            (Smbios30EntryPointStructure->TableMaximumSize + InputStrLen - TargetStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH)) {\r
+          DEBUG ((EFI_D_INFO, "SmbiosUpdateString: Total length exceeds max 64-bit table length\n"));\r
+        } else {\r
+          DEBUG ((EFI_D_INFO, "SmbiosUpdateString: New smbios record add to 64-bit table\n"));\r
+          SmbiosEntry->Smbios64BitTable = TRUE;\r
+        }\r
+      }\r
+\r
+      if ((!SmbiosEntry->Smbios32BitTable) && (!SmbiosEntry->Smbios64BitTable)) {\r
+        EfiReleaseLock (&Private->DataLock);\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+\r
       //\r
       // Original string buffer size is not exactly match input string length.\r
       // Re-allocate buffer is needed.\r
@@ -597,6 +749,8 @@ SmbiosUpdateString (
       ResizedSmbiosEntry->Signature    = EFI_SMBIOS_ENTRY_SIGNATURE;\r
       ResizedSmbiosEntry->RecordHeader = InternalRecord;\r
       ResizedSmbiosEntry->RecordSize   = NewEntrySize;\r
+      ResizedSmbiosEntry->Smbios32BitTable = SmbiosEntry->Smbios32BitTable;\r
+      ResizedSmbiosEntry->Smbios64BitTable = SmbiosEntry->Smbios64BitTable;\r
       InsertTailList (Link->ForwardLink, &ResizedSmbiosEntry->Link);\r
 \r
       //\r
@@ -610,7 +764,7 @@ SmbiosUpdateString (
       // configuration table, so other UEFI drivers can get SMBIOS table from\r
       // configuration table without depending on PI SMBIOS protocol.\r
       //\r
-      SmbiosTableConstruction ();\r
+      SmbiosTableConstruction (ResizedSmbiosEntry->Smbios32BitTable, ResizedSmbiosEntry->Smbios64BitTable);\r
       EfiReleaseLock (&Private->DataLock);\r
       return EFI_SUCCESS;\r
     }\r
@@ -658,7 +812,7 @@ SmbiosRemove (
   Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
   //\r
   // Enter into critical section\r
-  //  \r
+  //\r
   Status = EfiAcquireLockOrFail (&Private->DataLock);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -673,8 +827,7 @@ SmbiosRemove (
       // Remove specified smobios record from DataList\r
       //\r
       RemoveEntryList(Link);\r
-      FreePool(SmbiosEntry);\r
-      // \r
+      //\r
       // Remove this handle from AllocatedHandleList\r
       //\r
       Head = &Private->AllocatedHandleListHead;\r
@@ -692,7 +845,17 @@ SmbiosRemove (
       // configuration table, so other UEFI drivers can get SMBIOS table from\r
       // configuration table without depending on PI SMBIOS protocol.\r
       //\r
-      SmbiosTableConstruction ();\r
+      if (SmbiosEntry->Smbios32BitTable) {\r
+        DEBUG ((EFI_D_INFO, "SmbiosRemove: remove from 32-bit table\n"));\r
+      }\r
+      if (SmbiosEntry->Smbios64BitTable) {\r
+        DEBUG ((EFI_D_INFO, "SmbiosRemove: remove from 64-bit table\n"));\r
+      }\r
+      //\r
+      // Update the whole SMBIOS table again based on which table the removed SMBIOS record is in.\r
+      //\r
+      SmbiosTableConstruction (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable);\r
+      FreePool(SmbiosEntry);\r
       EfiReleaseLock (&Private->DataLock);\r
       return EFI_SUCCESS;\r
     }\r
@@ -703,7 +866,7 @@ SmbiosRemove (
   //\r
   EfiReleaseLock (&Private->DataLock);\r
   return EFI_INVALID_PARAMETER;\r
-  \r
+\r
 }\r
 \r
 /**\r
@@ -711,15 +874,15 @@ SmbiosRemove (
 \r
   @param  This                  The EFI_SMBIOS_PROTOCOL instance.\r
   @param  SmbiosHandle          On entry, points to the previous handle of the SMBIOS record. On exit, points to the\r
-                                next SMBIOS record handle. If it is zero on entry, then the first SMBIOS record\r
-                                handle will be returned. If it returns zero on exit, then there are no more SMBIOS records.\r
-  @param  Type                  On entry it means return the next SMBIOS record of type Type. If a NULL is passed in \r
+                                next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record\r
+                                handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS records.\r
+  @param  Type                  On entry it means return the next SMBIOS record of type Type. If a NULL is passed in\r
                                 this functionally it ignored. Type is not modified by the GetNext() function.\r
   @param  Record                On exit, points to the SMBIOS Record consisting of the formatted area followed by\r
                                 the unformatted area. The unformatted area optionally contains text strings.\r
-  @param  ProducerHandle        On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned. \r
-                                If a NULL pointer is passed in no data will be returned \r
-                                \r
+  @param  ProducerHandle        On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned.\r
+                                If a NULL pointer is passed in no data will be returned\r
+\r
   @retval EFI_SUCCESS           SMBIOS record information was successfully returned in Record.\r
   @retval EFI_NOT_FOUND         The SMBIOS record with SmbiosHandle was the last available record.\r
 \r
@@ -750,14 +913,14 @@ SmbiosGetNext (
   Head = &Private->DataListHead;\r
   for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
     SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
-    SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); \r
+    SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
 \r
     //\r
-    // If SmbiosHandle is zero, the first matched SMBIOS record handle will be returned\r
+    // If SmbiosHandle is 0xFFFE, the first matched SMBIOS record handle will be returned\r
     //\r
-    if (*SmbiosHandle == 0) {\r
+    if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {\r
       if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r
-        continue;  \r
+        continue;\r
       }\r
 \r
       *SmbiosHandle = SmbiosTableHeader->Handle;\r
@@ -778,33 +941,33 @@ SmbiosGetNext (
 \r
     if (StartPointFound) {\r
       if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {\r
-        continue; \r
+        continue;\r
       }\r
-      \r
+\r
       *SmbiosHandle = SmbiosTableHeader->Handle;\r
-      *Record = SmbiosTableHeader; \r
+      *Record = SmbiosTableHeader;\r
       if (ProducerHandle != NULL) {\r
         *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;\r
       }\r
 \r
-      return EFI_SUCCESS;   \r
+      return EFI_SUCCESS;\r
     }\r
   }\r
 \r
-  *SmbiosHandle = 0;\r
+  *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
   return EFI_NOT_FOUND;\r
-  \r
+\r
 }\r
 \r
 /**\r
   Allow the caller to discover all of the SMBIOS records.\r
 \r
   @param  This                  The EFI_SMBIOS_PROTOCOL instance.\r
-  @param  CurrentSmbiosEntry    On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information. \r
-                                If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned. \r
+  @param  CurrentSmbiosEntry    On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information.\r
+                                If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned.\r
   @param  Record                On exit, points to the SMBIOS Record consisting of the formatted area followed by\r
                                 the unformatted area. The unformatted area optionally contains text strings.\r
-                                \r
+\r
   @retval EFI_SUCCESS           SMBIOS record information was successfully returned in Record.\r
                                 *CurrentSmbiosEntry points to the SMBIOS entry which includes the returned SMBIOS record information.\r
   @retval EFI_NOT_FOUND         There is no more SMBIOS entry.\r
@@ -836,33 +999,32 @@ GetNextSmbiosRecord (
     //\r
     Head = &(*CurrentSmbiosEntry)->Link;\r
   }\r
-  \r
+\r
   Link  = Head->ForwardLink;\r
-  \r
+\r
   if (Link == &Private->DataListHead) {\r
     //\r
     // If no more SMBIOS entry in the list, return not found.\r
     //\r
     return EFI_NOT_FOUND;\r
   }\r
-  \r
+\r
   SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
   SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
-  *Record = SmbiosTableHeader; \r
+  *Record = SmbiosTableHeader;\r
   *CurrentSmbiosEntry = SmbiosEntry;\r
-  return EFI_SUCCESS;   \r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
   Assembles SMBIOS table from the SMBIOS protocol. Produce Table\r
   Entry Point and return the pointer to it.\r
-  \r
+\r
   @param  TableEntryPointStructure   On exit, points to the SMBIOS entrypoint structure.\r
-                                \r
+\r
   @retval EFI_SUCCESS                Structure created sucessfully.\r
-  @retval EFI_NOT_READY              Some of The SMBIOS records was not available yet.\r
   @retval EFI_OUT_OF_RESOURCES       No enough memory.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -880,22 +1042,54 @@ SmbiosCreateTable (
   EFI_SMBIOS_TABLE_HEADER         *SmbiosRecord;\r
   EFI_SMBIOS_TABLE_END_STRUCTURE  EndStructure;\r
   EFI_SMBIOS_ENTRY                *CurrentSmbiosEntry;\r
-  UINTN                           PreAllocatedPages;\r
-  \r
+\r
   Status            = EFI_SUCCESS;\r
   BufferPointer     = NULL;\r
 \r
+  if (EntryPointStructure == NULL) {\r
+    //\r
+    // Initialize the EntryPointStructure with initial values.\r
+    // It should be done only once.\r
+    // Allocate memory (below 4GB).\r
+    //\r
+    DEBUG ((EFI_D_INFO, "SmbiosCreateTable: Initialize 32-bit entry point structure\n"));\r
+    EntryPointStructureData.MajorVersion  = mPrivateData.Smbios.MajorVersion;\r
+    EntryPointStructureData.MinorVersion  = mPrivateData.Smbios.MinorVersion;\r
+    EntryPointStructureData.SmbiosBcdRevision = (UINT8) ((PcdGet16 (PcdSmbiosVersion) >> 4) & 0xf0) | (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x0f);\r
+    PhysicalAddress = 0xffffffff;\r
+    Status = gBS->AllocatePages (\r
+                    AllocateMaxAddress,\r
+                    EfiRuntimeServicesData,\r
+                    EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
+                    &PhysicalAddress\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "SmbiosCreateTable () could not allocate EntryPointStructure < 4GB\n"));\r
+      Status = gBS->AllocatePages (\r
+                      AllocateAnyPages,\r
+                      EfiRuntimeServicesData,\r
+                      EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
+                      &PhysicalAddress\r
+                      );\r
+     if (EFI_ERROR (Status)) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+    }\r
+\r
+    EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) (UINTN) PhysicalAddress;\r
+\r
+    CopyMem (\r
+      EntryPointStructure,\r
+      &EntryPointStructureData,\r
+      sizeof (SMBIOS_TABLE_ENTRY_POINT)\r
+      );\r
+  }\r
+\r
   //\r
   // Get Smbios protocol to traverse SMBIOS records.\r
   //\r
   SmbiosProtocol = &mPrivateData.Smbios;\r
 \r
-  if (EntryPointStructure->TableAddress == 0) {\r
-    PreAllocatedPages = 0;\r
-  } else {\r
-    PreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
-  }\r
-\r
   //\r
   // Make some statistics about all the structures\r
   //\r
@@ -909,8 +1103,8 @@ SmbiosCreateTable (
   CurrentSmbiosEntry = NULL;\r
   do {\r
     Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
-                               \r
-    if (Status == EFI_SUCCESS) {\r
+\r
+    if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios32BitTable)) {\r
       GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
       //\r
       // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize\r
@@ -922,12 +1116,12 @@ SmbiosCreateTable (
       }\r
     }\r
   } while (!EFI_ERROR(Status));\r
-  \r
+\r
   //\r
   // Create End-Of-Table structure\r
   //\r
   GetMaxSmbiosHandle(SmbiosProtocol, &SmbiosHandle);\r
-  EndStructure.Header.Type = EFI_SMBIOS_TYPE_END_OF_TABLE;\r
+  EndStructure.Header.Type = SMBIOS_TYPE_END_OF_TABLE;\r
   EndStructure.Header.Length = (UINT8) sizeof (EFI_SMBIOS_TABLE_HEADER);\r
   EndStructure.Header.Handle = SmbiosHandle;\r
   EndStructure.Tailing[0] = 0;\r
@@ -938,26 +1132,29 @@ SmbiosCreateTable (
     EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);\r
   }\r
 \r
-  if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > PreAllocatedPages) {\r
+  if (EFI_SIZE_TO_PAGES ((UINT32) EntryPointStructure->TableLength) > mPreAllocatedPages) {\r
     //\r
-    // If new SMBIOS talbe size exceeds the original pre-allocated page, \r
+    // If new SMBIOS table size exceeds the previous allocated page,\r
     // it is time to re-allocate memory (below 4GB).\r
-    // \r
+    //\r
+    DEBUG ((EFI_D_INFO, "%a() re-allocate SMBIOS 32-bit table\n",\r
+      __FUNCTION__));\r
     if (EntryPointStructure->TableAddress != 0) {\r
       //\r
-      // Free the original pre-allocated page\r
-      //      \r
+      // Free the previous allocated page\r
+      //\r
       FreePages (\r
             (VOID*)(UINTN)EntryPointStructure->TableAddress,\r
-            PreAllocatedPages\r
+            mPreAllocatedPages\r
             );\r
       EntryPointStructure->TableAddress = 0;\r
+      mPreAllocatedPages = 0;\r
     }\r
-    \r
+\r
     PhysicalAddress = 0xffffffff;\r
     Status = gBS->AllocatePages (\r
                     AllocateMaxAddress,\r
-                    EfiReservedMemoryType,\r
+                    EfiRuntimeServicesData,\r
                     EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r
                     &PhysicalAddress\r
                     );\r
@@ -967,24 +1164,26 @@ SmbiosCreateTable (
       return EFI_OUT_OF_RESOURCES;\r
     } else {\r
       EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
+      mPreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
     }\r
   }\r
-  \r
+\r
   //\r
   // Assemble the tables\r
   //\r
+  ASSERT (EntryPointStructure->TableAddress != 0);\r
   BufferPointer = (UINT8 *) (UINTN) EntryPointStructure->TableAddress;\r
   CurrentSmbiosEntry = NULL;\r
   do {\r
     Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
 \r
-    if (Status == EFI_SUCCESS) {\r
+    if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios32BitTable)) {\r
       GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
       CopyMem (BufferPointer, SmbiosRecord, RecordSize);\r
       BufferPointer = BufferPointer + RecordSize;\r
     }\r
   } while (!EFI_ERROR(Status));\r
-  \r
+\r
   //\r
   // Assemble End-Of-Table structure\r
   //\r
@@ -993,6 +1192,9 @@ SmbiosCreateTable (
   //\r
   // Fixup checksums in the Entry Point Structure\r
   //\r
+  EntryPointStructure->IntermediateChecksum = 0;\r
+  EntryPointStructure->EntryPointStructureChecksum = 0;\r
+\r
   EntryPointStructure->IntermediateChecksum =\r
     CalculateCheckSum8 ((UINT8 *) EntryPointStructure + 0x10, EntryPointStructure->EntryPointLength - 0x10);\r
   EntryPointStructure->EntryPointStructureChecksum =\r
@@ -1007,26 +1209,208 @@ SmbiosCreateTable (
 }\r
 \r
 /**\r
-  Create SMBIOS Table and install it to the System Table.\r
+  Assembles SMBIOS 64-bit table from the SMBIOS protocol. Produce Table\r
+  Entry Point and return the pointer to it.\r
+\r
+  @param  TableEntryPointStructure   On exit, points to the SMBIOS entrypoint structure.\r
+\r
+  @retval EFI_SUCCESS                Structure created sucessfully.\r
+  @retval EFI_OUT_OF_RESOURCES       No enough memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmbiosCreate64BitTable (\r
+  OUT VOID    **TableEntryPointStructure\r
+  )\r
+{\r
+  UINT8                           *BufferPointer;\r
+  UINTN                           RecordSize;\r
+  UINTN                           NumOfStr;\r
+  EFI_STATUS                      Status;\r
+  EFI_SMBIOS_HANDLE               SmbiosHandle;\r
+  EFI_SMBIOS_PROTOCOL             *SmbiosProtocol;\r
+  EFI_PHYSICAL_ADDRESS            PhysicalAddress;\r
+  EFI_SMBIOS_TABLE_HEADER         *SmbiosRecord;\r
+  EFI_SMBIOS_TABLE_END_STRUCTURE  EndStructure;\r
+  EFI_SMBIOS_ENTRY                *CurrentSmbiosEntry;\r
+\r
+  Status            = EFI_SUCCESS;\r
+  BufferPointer     = NULL;\r
+\r
+  if (Smbios30EntryPointStructure == NULL) {\r
+    //\r
+    // Initialize the Smbios30EntryPointStructure with initial values.\r
+    // It should be done only once.\r
+    // Allocate memory at any address.\r
+    //\r
+    DEBUG ((EFI_D_INFO, "SmbiosCreateTable: Initialize 64-bit entry point structure\n"));\r
+    Smbios30EntryPointStructureData.MajorVersion  = mPrivateData.Smbios.MajorVersion;\r
+    Smbios30EntryPointStructureData.MinorVersion  = mPrivateData.Smbios.MinorVersion;\r
+    Smbios30EntryPointStructureData.DocRev        = PcdGet8 (PcdSmbiosDocRev);\r
+    Status = gBS->AllocatePages (\r
+                    AllocateAnyPages,\r
+                    EfiRuntimeServicesData,\r
+                    EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)),\r
+                    &PhysicalAddress\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "SmbiosCreate64BitTable() could not allocate Smbios30EntryPointStructure\n"));\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Smbios30EntryPointStructure = (SMBIOS_TABLE_3_0_ENTRY_POINT *) (UINTN) PhysicalAddress;\r
+\r
+    CopyMem (\r
+      Smbios30EntryPointStructure,\r
+      &Smbios30EntryPointStructureData,\r
+      sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)\r
+      );\r
+  }\r
+\r
+  //\r
+  // Get Smbios protocol to traverse SMBIOS records.\r
+  //\r
+  SmbiosProtocol = &mPrivateData.Smbios;\r
+  Smbios30EntryPointStructure->TableMaximumSize = 0;\r
+\r
+  //\r
+  // Calculate EPS Table Length\r
+  //\r
+  CurrentSmbiosEntry = NULL;\r
+  do {\r
+    Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
+\r
+    if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios64BitTable)) {\r
+      GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
+      //\r
+      // Record TableMaximumSize\r
+      //\r
+      Smbios30EntryPointStructure->TableMaximumSize = (UINT32) (Smbios30EntryPointStructure->TableMaximumSize + RecordSize);\r
+    }\r
+  } while (!EFI_ERROR(Status));\r
+\r
+  //\r
+  // Create End-Of-Table structure\r
+  //\r
+  GetMaxSmbiosHandle(SmbiosProtocol, &SmbiosHandle);\r
+  EndStructure.Header.Type = SMBIOS_TYPE_END_OF_TABLE;\r
+  EndStructure.Header.Length = (UINT8) sizeof (EFI_SMBIOS_TABLE_HEADER);\r
+  EndStructure.Header.Handle = SmbiosHandle;\r
+  EndStructure.Tailing[0] = 0;\r
+  EndStructure.Tailing[1] = 0;\r
+  Smbios30EntryPointStructure->TableMaximumSize = (UINT32) (Smbios30EntryPointStructure->TableMaximumSize + sizeof (EndStructure));\r
+\r
+  if (EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize) > mPre64BitAllocatedPages) {\r
+    //\r
+    // If new SMBIOS table size exceeds the previous allocated page,\r
+    // it is time to re-allocate memory at anywhere.\r
+    //\r
+    DEBUG ((EFI_D_INFO, "%a() re-allocate SMBIOS 64-bit table\n",\r
+      __FUNCTION__));\r
+    if (Smbios30EntryPointStructure->TableAddress != 0) {\r
+      //\r
+      // Free the previous allocated page\r
+      //\r
+      FreePages (\r
+            (VOID*)(UINTN)Smbios30EntryPointStructure->TableAddress,\r
+            mPre64BitAllocatedPages\r
+            );\r
+      Smbios30EntryPointStructure->TableAddress = 0;\r
+      mPre64BitAllocatedPages = 0;\r
+    }\r
+\r
+    Status = gBS->AllocatePages (\r
+                    AllocateAnyPages,\r
+                    EfiRuntimeServicesData,\r
+                    EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize),\r
+                    &PhysicalAddress\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "SmbiosCreateTable() could not allocate SMBIOS 64-bit table\n"));\r
+      Smbios30EntryPointStructure->TableAddress = 0;\r
+      return EFI_OUT_OF_RESOURCES;\r
+    } else {\r
+      Smbios30EntryPointStructure->TableAddress = PhysicalAddress;\r
+      mPre64BitAllocatedPages = EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Assemble the tables\r
+  //\r
+  ASSERT (Smbios30EntryPointStructure->TableAddress != 0);\r
+  BufferPointer = (UINT8 *) (UINTN) Smbios30EntryPointStructure->TableAddress;\r
+  CurrentSmbiosEntry = NULL;\r
+  do {\r
+    Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
+\r
+    if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios64BitTable)) {\r
+      //\r
+      // This record can be added to 64-bit table\r
+      //\r
+      GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
+      CopyMem (BufferPointer, SmbiosRecord, RecordSize);\r
+      BufferPointer = BufferPointer + RecordSize;\r
+    }\r
+  } while (!EFI_ERROR(Status));\r
+\r
+  //\r
+  // Assemble End-Of-Table structure\r
+  //\r
+  CopyMem (BufferPointer, &EndStructure, sizeof (EndStructure));\r
+\r
+  //\r
+  // Fixup checksums in the Entry Point Structure\r
+  //\r
+  Smbios30EntryPointStructure->EntryPointStructureChecksum = 0;\r
+  Smbios30EntryPointStructure->EntryPointStructureChecksum =\r
+    CalculateCheckSum8 ((UINT8 *) Smbios30EntryPointStructure, Smbios30EntryPointStructure->EntryPointLength);\r
+\r
+  //\r
+  // Returns the pointer\r
+  //\r
+  *TableEntryPointStructure = Smbios30EntryPointStructure;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Create Smbios Table and installs the Smbios Table to the System Table.\r
+\r
+  @param  Smbios32BitTable    The flag to update 32-bit table.\r
+  @param  Smbios64BitTable    The flag to update 64-bit table.\r
+\r
 **/\r
 VOID\r
 EFIAPI\r
 SmbiosTableConstruction (\r
-  VOID\r
+  BOOLEAN     Smbios32BitTable,\r
+  BOOLEAN     Smbios64BitTable\r
   )\r
 {\r
   UINT8       *Eps;\r
+  UINT8       *Eps64Bit;\r
   EFI_STATUS  Status;\r
 \r
-  Status = SmbiosCreateTable ((VOID **) &Eps);\r
-  if (!EFI_ERROR (Status)) {\r
-    gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, Eps);\r
+  if (Smbios32BitTable) {\r
+    Status = SmbiosCreateTable ((VOID **) &Eps);\r
+    if (!EFI_ERROR (Status)) {\r
+      gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, Eps);\r
+    }\r
+  }\r
+\r
+  if (Smbios64BitTable) {\r
+    Status = SmbiosCreate64BitTable ((VOID **) &Eps64Bit);\r
+    if (!EFI_ERROR (Status)) {\r
+      gBS->InstallConfigurationTable (&gEfiSmbios3TableGuid, Eps64Bit);\r
+    }\r
   }\r
 }\r
 \r
 /**\r
 \r
-  Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table. \r
+  Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.\r
 \r
   @param ImageHandle     Module's image handle\r
   @param SystemTable     Pointer of EFI_SYSTEM_TABLE\r
@@ -1043,74 +1427,19 @@ SmbiosDriverEntryPoint (
   )\r
 {\r
   EFI_STATUS            Status;\r
-  EFI_PHYSICAL_ADDRESS  PhysicalAddress;\r
 \r
   mPrivateData.Signature                = SMBIOS_INSTANCE_SIGNATURE;\r
   mPrivateData.Smbios.Add               = SmbiosAdd;\r
   mPrivateData.Smbios.UpdateString      = SmbiosUpdateString;\r
   mPrivateData.Smbios.Remove            = SmbiosRemove;\r
   mPrivateData.Smbios.GetNext           = SmbiosGetNext;\r
-  mPrivateData.Smbios.MajorVersion      = (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) >> 8);\r
-  mPrivateData.Smbios.MinorVersion      = (UINT8) (FixedPcdGet16 (PcdSmbiosVersion) & 0x00ff);\r
+  mPrivateData.Smbios.MajorVersion      = (UINT8) (PcdGet16 (PcdSmbiosVersion) >> 8);\r
+  mPrivateData.Smbios.MinorVersion      = (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x00ff);\r
 \r
   InitializeListHead (&mPrivateData.DataListHead);\r
   InitializeListHead (&mPrivateData.AllocatedHandleListHead);\r
   EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);\r
 \r
-  //\r
-  // Initialize the EntryPointStructure with initial values.\r
-  // Allocate memory (below 4GB).\r
-  //\r
-  PhysicalAddress = 0xffffffff;\r
-  Status = gBS->AllocatePages (\r
-                  AllocateMaxAddress,\r
-                  EfiReservedMemoryType,\r
-                  EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
-                  &PhysicalAddress\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate EntryPointStructure < 4GB\n"));\r
-    Status = gBS->AllocatePages (\r
-                    AllocateAnyPages,\r
-                    EfiReservedMemoryType,\r
-                    EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
-                    &PhysicalAddress\r
-                    );\r
-   if (EFI_ERROR (Status)) {   \r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-  }\r
-\r
-  EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) (UINTN) PhysicalAddress;\r
-  \r
-  CopyMem (\r
-    EntryPointStructure,\r
-    &EntryPointStructureData,\r
-    sizeof (SMBIOS_TABLE_ENTRY_POINT)\r
-    );\r
-\r
-  //\r
-  // Pre-allocate 1 page for SMBIOS table below 4GB.\r
-  // SMBIOS table will be updated when new SMBIOS type is added or \r
-  // existing SMBIOS type is updated. If the total size of SMBIOS table exceeds 1 page,\r
-  // we will re-allocate new memory when creating whole SMBIOS table.\r
-  //\r
-  PhysicalAddress = 0xffffffff;\r
-  Status = gBS->AllocatePages (\r
-                  AllocateMaxAddress,\r
-                  EfiReservedMemoryType,\r
-                  1,\r
-                  &PhysicalAddress\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate SMBIOS table < 4GB\n"));\r
-    EntryPointStructure->TableAddress = 0;\r
-    EntryPointStructure->TableLength  = 0;\r
-  } else {\r
-    EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
-    EntryPointStructure->TableLength  = EFI_PAGES_TO_SIZE (1);\r
-  }\r
-  \r
   //\r
   // Make a new handle and install the protocol\r
   //\r