diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
index 2d0be7cd51..861e35eb99 100644
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
@@ -22,6 +22,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
SMBIOS_INSTANCE mPrivateData;
+UINTN mPreAllocatedPages = 0;
+
//
// Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.
//
@@ -128,6 +130,7 @@ GetSmbiosStructureSize (
{
UINTN FullSize;
UINTN StrLen;
+ UINTN MaxLen;
INT8* CharInStr;
if (Size == NULL || NumberOfStrings == NULL) {
@@ -149,26 +152,27 @@ GetSmbiosStructureSize (
}
if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)){
- for (StrLen = 0 ; StrLen < SMBIOS_STRING_MAX_LENGTH; StrLen++) {
- if (*(CharInStr+StrLen) == 0) {
- break;
- }
- }
-
- if (StrLen == SMBIOS_STRING_MAX_LENGTH) {
- return EFI_INVALID_PARAMETER;
- }
+ MaxLen = SMBIOS_STRING_MAX_LENGTH;
} else {
//
- // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string
+ // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
+ // However, the length of the entire structure table (including all strings) must be reported
+ // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
+ // which is a WORD field limited to 65,535 bytes.
//
- for (StrLen = 0 ;; StrLen++) {
- if (*(CharInStr+StrLen) == 0) {
- break;
- }
+ MaxLen = SMBIOS_TABLE_MAX_LENGTH;
+ }
+
+ for (StrLen = 0 ; StrLen < MaxLen; StrLen++) {
+ if (*(CharInStr+StrLen) == 0) {
+ break;
}
}
+ if (StrLen == MaxLen) {
+ return EFI_INVALID_PARAMETER;
+ }
+
//
// forward the pointer
//
@@ -355,6 +359,15 @@ SmbiosAdd (
return Status;
}
+ if (EntryPointStructure->TableLength + StructureSize > SMBIOS_TABLE_MAX_LENGTH) {
+ //
+ // The length of the entire structure table (including all strings) must be reported
+ // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
+ // which is a WORD field limited to 65,535 bytes.
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+
//
// Enter into critical section
//
@@ -483,13 +496,20 @@ SmbiosUpdateString (
InputStrLen = AsciiStrLen(String);
- //
- // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string
- //
if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) {
if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) {
return EFI_UNSUPPORTED;
}
+ } else {
+ //
+ // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
+ // However, the length of the entire structure table (including all strings) must be reported
+ // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
+ // which is a WORD field limited to 65,535 bytes.
+ //
+ if (InputStrLen > SMBIOS_TABLE_MAX_LENGTH) {
+ return EFI_UNSUPPORTED;
+ }
}
Private = SMBIOS_INSTANCE_FROM_THIS (This);
@@ -558,6 +578,15 @@ SmbiosUpdateString (
return EFI_SUCCESS;
}
+ if (EntryPointStructure->TableLength + InputStrLen - TargetStrLen > SMBIOS_TABLE_MAX_LENGTH) {
+ //
+ // The length of the entire structure table (including all strings) must be reported
+ // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
+ // which is a WORD field limited to 65,535 bytes.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
//
// Original string buffer size is not exactly match input string length.
// Re-allocate buffer is needed.
@@ -880,7 +909,6 @@ SmbiosCreateTable (
EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;
EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure;
EFI_SMBIOS_ENTRY *CurrentSmbiosEntry;
- UINTN PreAllocatedPages;
Status = EFI_SUCCESS;
BufferPointer = NULL;
@@ -890,12 +918,6 @@ SmbiosCreateTable (
//
SmbiosProtocol = &mPrivateData.Smbios;
- if (EntryPointStructure->TableAddress == 0) {
- PreAllocatedPages = 0;
- } else {
- PreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);
- }
-
//
// Make some statistics about all the structures
//
@@ -938,7 +960,7 @@ SmbiosCreateTable (
EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);
}
- if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > PreAllocatedPages) {
+ if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > mPreAllocatedPages) {
//
// If new SMBIOS talbe size exceeds the original pre-allocated page,
// it is time to re-allocate memory (below 4GB).
@@ -949,9 +971,10 @@ SmbiosCreateTable (
//
FreePages (
(VOID*)(UINTN)EntryPointStructure->TableAddress,
- PreAllocatedPages
+ mPreAllocatedPages
);
EntryPointStructure->TableAddress = 0;
+ mPreAllocatedPages = 0;
}
PhysicalAddress = 0xffffffff;
@@ -967,6 +990,7 @@ SmbiosCreateTable (
return EFI_OUT_OF_RESOURCES;
} else {
EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;
+ mPreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);
}
}
@@ -1109,11 +1133,16 @@ SmbiosDriverEntryPoint (
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate SMBIOS table < 4GB\n"));
EntryPointStructure->TableAddress = 0;
- EntryPointStructure->TableLength = 0;
} else {
EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;
- EntryPointStructure->TableLength = EFI_PAGES_TO_SIZE (1);
+ mPreAllocatedPages = 1;
}
+
+ //
+ // Init TableLength to the length of End-Of-Table structure for SmbiosAdd() called at the first time
+ // to check the TableLength limitation.
+ //
+ EntryPointStructure->TableLength = sizeof (EFI_SMBIOS_TABLE_END_STRUCTURE);
//
// Make a new handle and install the protocol
diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h
index 3c78b993bd..e81b543672 100644
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.h
@@ -1,7 +1,7 @@
/** @file
This code supports the implementation of the Smbios protocol
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -31,6 +31,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include
#include
+//
+// The length of the entire structure table (including all strings) must be reported
+// in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
+// which is a WORD field limited to 65,535 bytes.
+//
+#define SMBIOS_TABLE_MAX_LENGTH 0xFFFF
+
#define SMBIOS_INSTANCE_SIGNATURE SIGNATURE_32 ('S', 'B', 'i', 's')
typedef struct {
UINT32 Signature;