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
This commit is contained in:
li-elvin
2011-08-01 07:30:02 +00:00
parent afe05b7a45
commit 0ddd855318
2 changed files with 191 additions and 113 deletions

View File

@@ -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.
@@ -408,6 +408,14 @@ SmbiosAdd (
CopyMem (Raw, Record, StructureSize);
((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
//
@@ -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;
}