\r
/**\r
\r
- Get the full size of smbios structure including optional strings that follow the formatted structure.\r
+ Get the full size of SMBIOS structure including optional strings that follow the formatted structure.\r
\r
@param This The EFI_SMBIOS_PROTOCOL instance.\r
- @param Head Pointer to the beginning of smbios structure.\r
+ @param Head Pointer to the beginning of SMBIOS structure.\r
@param Size The returned size.\r
@param NumberOfStrings The returned number of optional strings that follow the formatted structure.\r
\r
@retval EFI_SUCCESS Size retured in Size.\r
- @retval EFI_INVALID_PARAMETER Input smbios structure mal-formed or Size is NULL.\r
+ @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.\r
\r
**/\r
EFI_STATUS\r
\r
Determin whether an SmbiosHandle has already in use.\r
\r
- @param Head Pointer to the beginning of smbios structure.\r
+ @param Head Pointer to the beginning of SMBIOS structure.\r
@param Handle A unique handle will be assigned to the SMBIOS record.\r
\r
@retval TRUE Smbios handle already in use.\r
CopyMem (Raw, Record, StructureSize);\r
((EFI_SMBIOS_TABLE_HEADER*)Raw)->Handle = *SmbiosHandle;\r
\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
+ \r
//\r
// Leave critical section\r
//\r
\r
if (Record->Handle == *SmbiosHandle) {\r
//\r
- // Find out the specified Smbios record\r
+ // Find out the specified SMBIOS record\r
//\r
if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) {\r
EfiReleaseLock (&Private->DataLock);\r
TargetStrLen = AsciiStrLen(StrStart);\r
if (InputStrLen == TargetStrLen) {\r
AsciiStrCpy(StrStart, 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
EfiReleaseLock (&Private->DataLock);\r
return EFI_SUCCESS;\r
}\r
InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings;\r
\r
//\r
- // Copy smbios structure and optional strings.\r
+ // Copy SMBIOS structure and optional strings.\r
//\r
CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset);\r
CopyMem ((VOID*)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1);\r
//\r
RemoveEntryList(Link);\r
FreePool(SmbiosEntry);\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
EfiReleaseLock (&Private->DataLock);\r
return EFI_SUCCESS;\r
}\r
break;\r
}\r
}\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
EfiReleaseLock (&Private->DataLock);\r
return EFI_SUCCESS;\r
}\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
- SmbiosHandle is the handle of the current SMBIOS record\r
@retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.\r
\r
**/\r
}\r
\r
//\r
- // Start this round search from the next Smbios handle\r
+ // Start this round search from the next SMBIOS handle\r
//\r
if (!StartPointFound && (*SmbiosHandle == SmbiosTableHeader->Handle)) {\r
StartPointFound = TRUE;\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 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
+ @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
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetNextSmbiosRecord (\r
+ IN CONST EFI_SMBIOS_PROTOCOL *This,\r
+ IN OUT EFI_SMBIOS_ENTRY **CurrentSmbiosEntry,\r
+ OUT EFI_SMBIOS_TABLE_HEADER **Record\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *Head;\r
+ SMBIOS_INSTANCE *Private;\r
+ EFI_SMBIOS_ENTRY *SmbiosEntry;\r
+ EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;\r
+\r
+ Private = SMBIOS_INSTANCE_FROM_THIS (This);\r
+ if (*CurrentSmbiosEntry == NULL) {\r
+ //\r
+ // Get the beginning of SMBIOS entry.\r
+ //\r
+ Head = &Private->DataListHead;\r
+ } else {\r
+ //\r
+ // Get previous SMBIOS entry and make it as start point.\r
+ //\r
+ Head = &(*CurrentSmbiosEntry)->Link;\r
+ }\r
+ \r
+ Link = Head->ForwardLink;\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
+ SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);\r
+ SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);\r
+ *Record = SmbiosTableHeader; \r
+ *CurrentSmbiosEntry = SmbiosEntry;\r
+ return EFI_SUCCESS; \r
+}\r
\r
/**\r
- Assembles Smbios table from the SMBIOS protocol. Produce Table\r
+ Assembles SMBIOS 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
EFI_PHYSICAL_ADDRESS PhysicalAddress;\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
//\r
- // Initialize the EntryPointStructure with initial values.\r
+ // Get Smbios protocol to traverse SMBIOS records.\r
//\r
- if (EntryPointStructure == NULL) {\r
- //\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
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ SmbiosProtocol = &mPrivateData.Smbios;\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
- // Free the original image\r
- //\r
- if (EntryPointStructure->TableAddress != 0) {\r
- FreePages (\r
- (VOID*)(UINTN)EntryPointStructure->TableAddress,\r
- EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength)\r
- );\r
- EntryPointStructure->TableAddress = 0;\r
- }\r
- \r
- //\r
- // Locate smbios protocol to traverse smbios records.\r
- //\r
- Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &SmbiosProtocol);\r
- ASSERT_EFI_ERROR (Status);\r
- ASSERT (SmbiosProtocol != NULL);\r
+ PreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);\r
\r
//\r
// Make some statistics about all the structures\r
EntryPointStructure->NumberOfSmbiosStructures = 0;\r
EntryPointStructure->TableLength = 0;\r
EntryPointStructure->MaxStructureSize = 0;\r
- SmbiosHandle = 0;\r
\r
//\r
// Calculate EPS Table Length\r
//\r
+ CurrentSmbiosEntry = NULL;\r
do {\r
- Status = SmbiosProtocol->GetNext (\r
- SmbiosProtocol,\r
- &SmbiosHandle,\r
- NULL,\r
- &SmbiosRecord,\r
- NULL\r
- );\r
+ Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
\r
if (Status == EFI_SUCCESS) {\r
GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
if (sizeof (EndStructure) > EntryPointStructure->MaxStructureSize) {\r
EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);\r
}\r
- \r
- //\r
- // Allocate memory (below 4GB)\r
- //\r
- PhysicalAddress = 0xffffffff;\r
- Status = gBS->AllocatePages (\r
- AllocateMaxAddress,\r
- EfiReservedMemoryType,\r
- EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r
- &PhysicalAddress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePages ((VOID*) EntryPointStructure, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)));\r
- EntryPointStructure = NULL;\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
\r
- EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
+ if (EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > PreAllocatedPages) {\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
+ if (EntryPointStructure->TableAddress != 0) {\r
+ //\r
+ // Free the original pre-allocated page\r
+ // \r
+ FreePages (\r
+ (VOID*)(UINTN)EntryPointStructure->TableAddress,\r
+ PreAllocatedPages\r
+ );\r
+ EntryPointStructure->TableAddress = 0;\r
+ }\r
+ \r
+ PhysicalAddress = 0xffffffff;\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiReservedMemoryType,\r
+ EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),\r
+ &PhysicalAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
+ }\r
\r
//\r
// Assemble the tables\r
//\r
- BufferPointer = (UINT8 *) (UINTN) PhysicalAddress;\r
- SmbiosHandle = 0;\r
+ BufferPointer = (UINT8 *) (UINTN) EntryPointStructure->TableAddress;\r
+ CurrentSmbiosEntry = NULL;\r
do {\r
- Status = SmbiosProtocol->GetNext (\r
- SmbiosProtocol,\r
- &SmbiosHandle,\r
- NULL,\r
- &SmbiosRecord,\r
- NULL\r
- );\r
+ Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);\r
+\r
if (Status == EFI_SUCCESS) {\r
GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);\r
CopyMem (BufferPointer, SmbiosRecord, RecordSize);\r
return EFI_SUCCESS;\r
}\r
\r
-\r
-\r
/**\r
- Installs the Smbios Table to the System Table. This function gets called\r
- when the EFI_EVENT_SIGNAL_READY_TO_BOOT gets signaled\r
- \r
- @param Event The event to signal\r
- @param Context Event contex\r
-\r
+ Create SMBIOS Table and install it to the System Table.\r
**/\r
VOID\r
EFIAPI\r
SmbiosTableConstruction (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
+ VOID\r
)\r
{\r
UINT8 *Eps;\r
}\r
}\r
\r
-\r
/**\r
\r
- Driver to produce Smbios protocol and register event for constructing 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
)\r
{\r
EFI_STATUS Status;\r
- EFI_EVENT ReadyToBootEvent;\r
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
\r
mPrivateData.Signature = SMBIOS_INSTANCE_SIGNATURE;\r
mPrivateData.Smbios.Add = SmbiosAdd;\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
+ return EFI_OUT_OF_RESOURCES;\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
+ FreePages ((VOID*) EntryPointStructure, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)));\r
+ EntryPointStructure = NULL;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;\r
+ EntryPointStructure->TableLength = EFI_PAGES_TO_SIZE (1);\r
+\r
//\r
// Make a new handle and install the protocol\r
//\r
&mPrivateData.Smbios\r
);\r
\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
- //\r
- // Register the event to install SMBIOS Table into EFI System Table\r
- //\r
- Status = gBS->CreateEventEx (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- SmbiosTableConstruction,\r
- NULL,\r
- &gEfiEventReadyToBootGuid,\r
- &ReadyToBootEvent\r
- );\r
- \r
return Status;\r
}\r