]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
Enhance SmbiosDxe driver:
[mirror_edk2.git] / MdeModulePkg / Universal / SmbiosDxe / SmbiosDxe.c
index 2d0be7cd51485f6696573725f6dc4cfebbd382e0..861e35eb9986c96b6ee9d1f770bfb154b06e66f3 100644 (file)
@@ -22,6 +22,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 SMBIOS_INSTANCE mPrivateData;\r
 \r
+UINTN mPreAllocatedPages = 0;\r
+\r
 //\r
 // Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.\r
 //\r
@@ -128,6 +130,7 @@ GetSmbiosStructureSize (
 {\r
   UINTN  FullSize;\r
   UINTN  StrLen;\r
+  UINTN  MaxLen;\r
   INT8*  CharInStr;\r
   \r
   if (Size == NULL || NumberOfStrings == NULL) {\r
@@ -149,26 +152,27 @@ GetSmbiosStructureSize (
     }\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 {\r
       //\r
-      // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string\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
-      for (StrLen = 0 ;; StrLen++) {\r
-        if (*(CharInStr+StrLen) == 0) {\r
-          break;\r
-        }\r
+      MaxLen = SMBIOS_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
@@ -355,6 +359,15 @@ SmbiosAdd (
     return Status;\r
   }\r
 \r
+  if (EntryPointStructure->TableLength + StructureSize > 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
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
   //\r
   // Enter into critical section\r
   //  \r
@@ -483,13 +496,20 @@ 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 {\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
   }\r
 \r
   Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
@@ -558,6 +578,15 @@ SmbiosUpdateString (
         return EFI_SUCCESS;\r
       }\r
 \r
+      if (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
+        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
@@ -880,7 +909,6 @@ SmbiosCreateTable (
   EFI_SMBIOS_TABLE_HEADER         *SmbiosRecord;\r
   EFI_SMBIOS_TABLE_END_STRUCTURE  EndStructure;\r
   EFI_SMBIOS_ENTRY                *CurrentSmbiosEntry;\r
-  UINTN                           PreAllocatedPages;\r
   \r
   Status            = EFI_SUCCESS;\r
   BufferPointer     = NULL;\r
@@ -890,12 +918,6 @@ SmbiosCreateTable (
   //\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
@@ -938,7 +960,7 @@ SmbiosCreateTable (
     EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);\r
   }\r
 \r
-  if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > PreAllocatedPages) {\r
+  if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > mPreAllocatedPages) {\r
     //\r
     // If new SMBIOS talbe size exceeds the original pre-allocated page, \r
     // it is time to re-allocate memory (below 4GB).\r
@@ -949,9 +971,10 @@ SmbiosCreateTable (
       //      \r
       FreePages (\r
             (VOID*)(UINTN)EntryPointStructure->TableAddress,\r
-            PreAllocatedPages\r
+            mPreAllocatedPages\r
             );\r
       EntryPointStructure->TableAddress = 0;\r
+      mPreAllocatedPages = 0;\r
     }\r
     \r
     PhysicalAddress = 0xffffffff;\r
@@ -967,6 +990,7 @@ 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
@@ -1109,11 +1133,16 @@ SmbiosDriverEntryPoint (
   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
+    mPreAllocatedPages = 1;\r
   }\r
+\r
+  //\r
+  // Init TableLength to the length of End-Of-Table structure for SmbiosAdd() called at the first time\r
+  // to check the TableLength limitation.\r
+  //\r
+  EntryPointStructure->TableLength  = sizeof (EFI_SMBIOS_TABLE_END_STRUCTURE);\r
   \r
   //\r
   // Make a new handle and install the protocol\r