summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
diff options
context:
space:
mode:
authorli-elvin <li-elvin@6f19259b-4bc3-4df7-8a09-765794883524>2011-08-01 07:30:02 +0000
committerli-elvin <li-elvin@6f19259b-4bc3-4df7-8a09-765794883524>2011-08-01 07:30:02 +0000
commit0ddd855318a42ecdd52c87e59202481996062276 (patch)
treef7c9a0cc2c682372fc3f7401f62019baee186dc9 /MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
parentafe05b7a45cefed0fffd482741d57143b34dc036 (diff)
downloadedk2-platforms-0ddd855318a42ecdd52c87e59202481996062276.tar.xz
Create smbios table when user adds/removes/Updatestring for a SMBIOS entry. It is for UEFI driver to access SMBIOS table in configuration table before boot.
Signed-off-by: li-elvin Reviewed-by: lzeng14 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12067 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c')
-rw-r--r--MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c293
1 files changed, 181 insertions, 112 deletions
diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
index 8b2efa14a1..56ece92c9a 100644
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
@@ -105,15 +105,15 @@ SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {
/**
- Get the full size of smbios structure including optional strings that follow the formatted structure.
+ Get the full size of SMBIOS structure including optional strings that follow the formatted structure.
@param This The EFI_SMBIOS_PROTOCOL instance.
- @param Head Pointer to the beginning of smbios structure.
+ @param Head Pointer to the beginning of SMBIOS structure.
@param Size The returned size.
@param NumberOfStrings The returned number of optional strings that follow the formatted structure.
@retval EFI_SUCCESS Size retured in Size.
- @retval EFI_INVALID_PARAMETER Input smbios structure mal-formed or Size is NULL.
+ @retval EFI_INVALID_PARAMETER Input SMBIOS structure mal-formed or Size is NULL.
**/
EFI_STATUS
@@ -187,7 +187,7 @@ GetSmbiosStructureSize (
Determin whether an SmbiosHandle has already in use.
- @param Head Pointer to the beginning of smbios structure.
+ @param Head Pointer to the beginning of SMBIOS structure.
@param Handle A unique handle will be assigned to the SMBIOS record.
@retval TRUE Smbios handle already in use.
@@ -409,6 +409,14 @@ SmbiosAdd (
((EFI_SMBIOS_TABLE_HEADER*)Raw)->Handle = *SmbiosHandle;
//
+ // Some UEFI drivers (such as network) need some information in SMBIOS table.
+ // Here we create SMBIOS table and publish it in
+ // configuration table, so other UEFI drivers can get SMBIOS table from
+ // configuration table without depending on PI SMBIOS protocol.
+ //
+ SmbiosTableConstruction ();
+
+ //
// Leave critical section
//
EfiReleaseLock (&Private->DataLock);
@@ -499,7 +507,7 @@ SmbiosUpdateString (
if (Record->Handle == *SmbiosHandle) {
//
- // Find out the specified Smbios record
+ // Find out the specified SMBIOS record
//
if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) {
EfiReleaseLock (&Private->DataLock);
@@ -538,6 +546,13 @@ SmbiosUpdateString (
TargetStrLen = AsciiStrLen(StrStart);
if (InputStrLen == TargetStrLen) {
AsciiStrCpy(StrStart, String);
+ //
+ // Some UEFI drivers (such as network) need some information in SMBIOS table.
+ // Here we create SMBIOS table and publish it in
+ // configuration table, so other UEFI drivers can get SMBIOS table from
+ // configuration table without depending on PI SMBIOS protocol.
+ //
+ SmbiosTableConstruction ();
EfiReleaseLock (&Private->DataLock);
return EFI_SUCCESS;
}
@@ -567,7 +582,7 @@ SmbiosUpdateString (
InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings;
//
- // Copy smbios structure and optional strings.
+ // Copy SMBIOS structure and optional strings.
//
CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset);
CopyMem ((VOID*)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1);
@@ -588,6 +603,13 @@ SmbiosUpdateString (
//
RemoveEntryList(Link);
FreePool(SmbiosEntry);
+ //
+ // Some UEFI drivers (such as network) need some information in SMBIOS table.
+ // Here we create SMBIOS table and publish it in
+ // configuration table, so other UEFI drivers can get SMBIOS table from
+ // configuration table without depending on PI SMBIOS protocol.
+ //
+ SmbiosTableConstruction ();
EfiReleaseLock (&Private->DataLock);
return EFI_SUCCESS;
}
@@ -663,6 +685,13 @@ SmbiosRemove (
break;
}
}
+ //
+ // Some UEFI drivers (such as network) need some information in SMBIOS table.
+ // Here we create SMBIOS table and publish it in
+ // configuration table, so other UEFI drivers can get SMBIOS table from
+ // configuration table without depending on PI SMBIOS protocol.
+ //
+ SmbiosTableConstruction ();
EfiReleaseLock (&Private->DataLock);
return EFI_SUCCESS;
}
@@ -691,7 +720,6 @@ SmbiosRemove (
If a NULL pointer is passed in no data will be returned
@retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.
- SmbiosHandle is the handle of the current SMBIOS record
@retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record.
**/
@@ -740,7 +768,7 @@ SmbiosGetNext (
}
//
- // Start this round search from the next Smbios handle
+ // Start this round search from the next SMBIOS handle
//
if (!StartPointFound && (*SmbiosHandle == SmbiosTableHeader->Handle)) {
StartPointFound = TRUE;
@@ -767,9 +795,65 @@ SmbiosGetNext (
}
+/**
+ Allow the caller to discover all of the SMBIOS records.
+
+ @param This The EFI_SMBIOS_PROTOCOL instance.
+ @param CurrentSmbiosEntry On exit, points to the SMBIOS entry on the list which includes the returned SMBIOS record information.
+ If *CurrentSmbiosEntry is NULL on entry, then the first SMBIOS entry on the list will be returned.
+ @param Record On exit, points to the SMBIOS Record consisting of the formatted area followed by
+ the unformatted area. The unformatted area optionally contains text strings.
+
+ @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record.
+ *CurrentSmbiosEntry points to the SMBIOS entry which includes the returned SMBIOS record information.
+ @retval EFI_NOT_FOUND There is no more SMBIOS entry.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextSmbiosRecord (
+ IN CONST EFI_SMBIOS_PROTOCOL *This,
+ IN OUT EFI_SMBIOS_ENTRY **CurrentSmbiosEntry,
+ OUT EFI_SMBIOS_TABLE_HEADER **Record
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Head;
+ SMBIOS_INSTANCE *Private;
+ EFI_SMBIOS_ENTRY *SmbiosEntry;
+ EFI_SMBIOS_TABLE_HEADER *SmbiosTableHeader;
+
+ Private = SMBIOS_INSTANCE_FROM_THIS (This);
+ if (*CurrentSmbiosEntry == NULL) {
+ //
+ // Get the beginning of SMBIOS entry.
+ //
+ Head = &Private->DataListHead;
+ } else {
+ //
+ // Get previous SMBIOS entry and make it as start point.
+ //
+ Head = &(*CurrentSmbiosEntry)->Link;
+ }
+
+ Link = Head->ForwardLink;
+
+ if (Link == &Private->DataListHead) {
+ //
+ // If no more SMBIOS entry in the list, return not found.
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);
+ SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);
+ *Record = SmbiosTableHeader;
+ *CurrentSmbiosEntry = SmbiosEntry;
+ return EFI_SUCCESS;
+}
/**
- Assembles Smbios table from the SMBIOS protocol. Produce Table
+ Assembles SMBIOS table from the SMBIOS protocol. Produce Table
Entry Point and return the pointer to it.
@param TableEntryPointStructure On exit, points to the SMBIOS entrypoint structure.
@@ -794,54 +878,18 @@ SmbiosCreateTable (
EFI_PHYSICAL_ADDRESS PhysicalAddress;
EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;
EFI_SMBIOS_TABLE_END_STRUCTURE EndStructure;
+ EFI_SMBIOS_ENTRY *CurrentSmbiosEntry;
+ UINTN PreAllocatedPages;
Status = EFI_SUCCESS;
BufferPointer = NULL;
//
- // Initialize the EntryPointStructure with initial values.
+ // Get Smbios protocol to traverse SMBIOS records.
//
- if (EntryPointStructure == NULL) {
- //
- // Allocate memory (below 4GB)
- //
- PhysicalAddress = 0xffffffff;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),
- &PhysicalAddress
- );
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
+ SmbiosProtocol = &mPrivateData.Smbios;
- EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) (UINTN) PhysicalAddress;
-
- CopyMem (
- EntryPointStructure,
- &EntryPointStructureData,
- sizeof (SMBIOS_TABLE_ENTRY_POINT)
- );
- }
-
- //
- // Free the original image
- //
- if (EntryPointStructure->TableAddress != 0) {
- FreePages (
- (VOID*)(UINTN)EntryPointStructure->TableAddress,
- EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength)
- );
- EntryPointStructure->TableAddress = 0;
- }
-
- //
- // Locate smbios protocol to traverse smbios records.
- //
- Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &SmbiosProtocol);
- ASSERT_EFI_ERROR (Status);
- ASSERT (SmbiosProtocol != NULL);
+ PreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);
//
// Make some statistics about all the structures
@@ -849,19 +897,13 @@ SmbiosCreateTable (
EntryPointStructure->NumberOfSmbiosStructures = 0;
EntryPointStructure->TableLength = 0;
EntryPointStructure->MaxStructureSize = 0;
- SmbiosHandle = 0;
//
// Calculate EPS Table Length
//
+ CurrentSmbiosEntry = NULL;
do {
- Status = SmbiosProtocol->GetNext (
- SmbiosProtocol,
- &SmbiosHandle,
- NULL,
- &SmbiosRecord,
- NULL
- );
+ Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);
if (Status == EFI_SUCCESS) {
GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);
@@ -890,38 +932,44 @@ SmbiosCreateTable (
if (sizeof (EndStructure) > EntryPointStructure->MaxStructureSize) {
EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);
}
-
- //
- // Allocate memory (below 4GB)
- //
- PhysicalAddress = 0xffffffff;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),
- &PhysicalAddress
- );
- if (EFI_ERROR (Status)) {
- FreePages ((VOID*) EntryPointStructure, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)));
- EntryPointStructure = NULL;
- return EFI_OUT_OF_RESOURCES;
- }
- EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;
+ if (EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > PreAllocatedPages) {
+ //
+ // If new SMBIOS talbe size exceeds the original pre-allocated page,
+ // it is time to re-allocate memory (below 4GB).
+ //
+ if (EntryPointStructure->TableAddress != 0) {
+ //
+ // Free the original pre-allocated page
+ //
+ FreePages (
+ (VOID*)(UINTN)EntryPointStructure->TableAddress,
+ PreAllocatedPages
+ );
+ EntryPointStructure->TableAddress = 0;
+ }
+
+ PhysicalAddress = 0xffffffff;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),
+ &PhysicalAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;
+ }
//
// Assemble the tables
//
- BufferPointer = (UINT8 *) (UINTN) PhysicalAddress;
- SmbiosHandle = 0;
+ BufferPointer = (UINT8 *) (UINTN) EntryPointStructure->TableAddress;
+ CurrentSmbiosEntry = NULL;
do {
- Status = SmbiosProtocol->GetNext (
- SmbiosProtocol,
- &SmbiosHandle,
- NULL,
- &SmbiosRecord,
- NULL
- );
+ Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);
+
if (Status == EFI_SUCCESS) {
GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);
CopyMem (BufferPointer, SmbiosRecord, RecordSize);
@@ -950,21 +998,13 @@ SmbiosCreateTable (
return EFI_SUCCESS;
}
-
-
/**
- Installs the Smbios Table to the System Table. This function gets called
- when the EFI_EVENT_SIGNAL_READY_TO_BOOT gets signaled
-
- @param Event The event to signal
- @param Context Event contex
-
+ Create SMBIOS Table and install it to the System Table.
**/
VOID
EFIAPI
SmbiosTableConstruction (
- IN EFI_EVENT Event,
- IN VOID *Context
+ VOID
)
{
UINT8 *Eps;
@@ -976,10 +1016,9 @@ SmbiosTableConstruction (
}
}
-
/**
- Driver to produce Smbios protocol and register event for constructing SMBIOS table.
+ Driver to produce Smbios protocol and pre-allocate 1 page for the final SMBIOS table.
@param ImageHandle Module's image handle
@param SystemTable Pointer of EFI_SYSTEM_TABLE
@@ -996,7 +1035,7 @@ SmbiosDriverEntryPoint (
)
{
EFI_STATUS Status;
- EFI_EVENT ReadyToBootEvent;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
mPrivateData.Signature = SMBIOS_INSTANCE_SIGNATURE;
mPrivateData.Smbios.Add = SmbiosAdd;
@@ -1009,7 +1048,52 @@ SmbiosDriverEntryPoint (
InitializeListHead (&mPrivateData.DataListHead);
InitializeListHead (&mPrivateData.AllocatedHandleListHead);
EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
+
+ //
+ // Initialize the EntryPointStructure with initial values.
+ // Allocate memory (below 4GB).
+ //
+ PhysicalAddress = 0xffffffff;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),
+ &PhysicalAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) (UINTN) PhysicalAddress;
+ CopyMem (
+ EntryPointStructure,
+ &EntryPointStructureData,
+ sizeof (SMBIOS_TABLE_ENTRY_POINT)
+ );
+
+ //
+ // Pre-allocate 1 page for SMBIOS table below 4GB.
+ // SMBIOS table will be updated when new SMBIOS type is added or
+ // existing SMBIOS type is updated. If the total size of SMBIOS table exceeds 1 page,
+ // we will re-allocate new memory when creating whole SMBIOS table.
+ //
+ PhysicalAddress = 0xffffffff;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ 1,
+ &PhysicalAddress
+ );
+ if (EFI_ERROR (Status)) {
+ FreePages ((VOID*) EntryPointStructure, EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)));
+ EntryPointStructure = NULL;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;
+ EntryPointStructure->TableLength = EFI_PAGES_TO_SIZE (1);
+
//
// Make a new handle and install the protocol
//
@@ -1021,20 +1105,5 @@ SmbiosDriverEntryPoint (
&mPrivateData.Smbios
);
- if (EFI_ERROR(Status)) {
- return Status;
- }
- //
- // Register the event to install SMBIOS Table into EFI System Table
- //
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- SmbiosTableConstruction,
- NULL,
- &gEfiEventReadyToBootGuid,
- &ReadyToBootEvent
- );
-
return Status;
}