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
+Copyright (c) 2009 - 2014, 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
//\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
//\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
//\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
//\r
// SmbiosBcdRevision\r
//\r
- 0 \r
+ 0\r
};\r
\r
\r
)\r
{\r
UINTN FullSize;\r
- UINT8 StrLen;\r
+ UINTN StrLen;\r
+ UINTN MaxLen;\r
INT8* CharInStr;\r
\r
if (Size == NULL || NumberOfStrings == NULL) {\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 {\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
\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
@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
// 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
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
\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
\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
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
\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
+ 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
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
}\r
}\r
}\r
\r
- *SmbiosHandle = 0;\r
+ *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
return EFI_NOT_FOUND;\r
\r
}\r
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
//\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
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
// \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
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\r
EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r
&PhysicalAddress\r
);\r
return EFI_OUT_OF_RESOURCES;\r
} else {\r
EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
+ mPreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
}\r
}\r
\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
+ EntryPointStructureData.MajorVersion = mPrivateData.Smbios.MajorVersion;\r
+ EntryPointStructureData.MinorVersion = mPrivateData.Smbios.MinorVersion;\r
+ EntryPointStructureData.SmbiosBcdRevision = (UINT8) ((PcdGet16 (PcdSmbiosVersion) >> 4) & 0xf0) | (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x0f);\r
\r
InitializeListHead (&mPrivateData.DataListHead);\r
InitializeListHead (&mPrivateData.AllocatedHandleListHead);\r
PhysicalAddress = 0xffffffff;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\r
EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
&PhysicalAddress\r
);\r
DEBUG ((EFI_D_ERROR, "SmbiosDriverEntryPoint() could not allocate EntryPointStructure < 4GB\n"));\r
Status = gBS->AllocatePages (\r
AllocateAnyPages,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\r
EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),\r
&PhysicalAddress\r
);\r
PhysicalAddress = 0xffffffff;\r
Status = gBS->AllocatePages (\r
AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
+ EfiRuntimeServicesData,\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
+ 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