mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 19:13:50 +00:00 
			
		
		
		
	 5efb28784f
			
		
	
	
		5efb28784f
		
	
	
	
	
		
			
			These messages don't report errors, hence they should be emitted as EFI_D_INFO (or EFI_D_VERBOSE even). Cc: Star Zeng <star.zeng@intel.com> Cc: Drew Jones <drjones@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Star Zeng <star.zeng@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18621 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1462 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1462 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This code produces the Smbios protocol. It also responsible for constructing 
 | |
|   SMBIOS table into system table.
 | |
|   
 | |
| Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
 | |
| 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        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "SmbiosDxe.h"
 | |
| 
 | |
| //
 | |
| // Module Global:
 | |
| // Since this driver will only ever produce one instance of the
 | |
| // protocol you are not required to dynamically allocate the PrivateData.
 | |
| //
 | |
| SMBIOS_INSTANCE mPrivateData;
 | |
| 
 | |
| UINTN mPreAllocatedPages      = 0;
 | |
| UINTN mPre64BitAllocatedPages = 0;
 | |
| 
 | |
| //
 | |
| // Chassis for SMBIOS entry point structure that is to be installed into EFI system config table.
 | |
| //
 | |
| SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure    = NULL;
 | |
| SMBIOS_TABLE_ENTRY_POINT EntryPointStructureData = {
 | |
|   //
 | |
|   // AnchorString
 | |
|   //
 | |
|   {
 | |
|     0x5f,
 | |
|     0x53,
 | |
|     0x4d,
 | |
|     0x5f
 | |
|   },
 | |
|   //
 | |
|   // EntryPointStructureChecksum,TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // EntryPointStructure Length
 | |
|   //
 | |
|   0x1f,
 | |
|   //
 | |
|   // MajorVersion
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // MinorVersion
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // MaxStructureSize, TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // EntryPointRevision
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // FormattedArea
 | |
|   //
 | |
|   {
 | |
|     0,
 | |
|     0,
 | |
|     0,
 | |
|     0,
 | |
|     0
 | |
|   },
 | |
|   //
 | |
|   // IntermediateAnchorString
 | |
|   //
 | |
|   {
 | |
|     0x5f,
 | |
|     0x44,
 | |
|     0x4d,
 | |
|     0x49,
 | |
|     0x5f
 | |
|   },
 | |
|   //
 | |
|   // IntermediateChecksum, TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // TableLength, TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // TableAddress, TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // NumberOfSmbiosStructures, TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // SmbiosBcdRevision
 | |
|   //
 | |
|   0
 | |
| };
 | |
| 
 | |
| SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios30EntryPointStructure    = NULL;
 | |
| SMBIOS_TABLE_3_0_ENTRY_POINT Smbios30EntryPointStructureData = {
 | |
|   //
 | |
|   // AnchorString _SM3_
 | |
|   //
 | |
|   {
 | |
|     0x5f,
 | |
|     0x53,
 | |
|     0x4d,
 | |
|     0x33,
 | |
|     0x5f,
 | |
|   },
 | |
|   //
 | |
|   // EntryPointStructureChecksum,TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // EntryPointLength
 | |
|   //
 | |
|   0x18,
 | |
|   //
 | |
|   // MajorVersion
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // MinorVersion
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // DocRev
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // EntryPointRevision
 | |
|   //
 | |
|   0x01,
 | |
|   //
 | |
|   // Reserved
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // TableMaximumSize,TO BE FILLED
 | |
|   //
 | |
|   0,
 | |
|   //
 | |
|   // TableAddress,TO BE FILLED
 | |
|   //
 | |
|   0
 | |
| };
 | |
| /**
 | |
| 
 | |
|   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 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.
 | |
|   
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetSmbiosStructureSize (
 | |
|   IN   CONST EFI_SMBIOS_PROTOCOL        *This,
 | |
|   IN   EFI_SMBIOS_TABLE_HEADER          *Head,
 | |
|   OUT  UINTN                            *Size,
 | |
|   OUT  UINTN                            *NumberOfStrings
 | |
|   )
 | |
| {
 | |
|   UINTN  FullSize;
 | |
|   UINTN  StrLen;
 | |
|   UINTN  MaxLen;
 | |
|   INT8*  CharInStr;
 | |
|   
 | |
|   if (Size == NULL || NumberOfStrings == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   FullSize = Head->Length;
 | |
|   CharInStr = (INT8*)Head + Head->Length;
 | |
|   *Size = FullSize;
 | |
|   *NumberOfStrings = 0;
 | |
|   StrLen = 0;
 | |
|   //
 | |
|   // look for the two consecutive zeros, check the string limit by the way.
 | |
|   //
 | |
|   while (*CharInStr != 0 || *(CharInStr+1) != 0) { 
 | |
|     if (*CharInStr == 0) {
 | |
|       *Size += 1;
 | |
|       CharInStr++;
 | |
|     }
 | |
| 
 | |
|     if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)){
 | |
|       MaxLen = SMBIOS_STRING_MAX_LENGTH;
 | |
|     } else if (This->MajorVersion < 3) {
 | |
|       //
 | |
|       // 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.
 | |
|       //
 | |
|       MaxLen = SMBIOS_TABLE_MAX_LENGTH;
 | |
|     } else {
 | |
|       //
 | |
|       // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
 | |
|       // Locate the end of string as long as possible.
 | |
|       //
 | |
|       MaxLen = SMBIOS_3_0_TABLE_MAX_LENGTH;
 | |
|     }
 | |
| 
 | |
|     for (StrLen = 0 ; StrLen < MaxLen; StrLen++) {
 | |
|       if (*(CharInStr+StrLen) == 0) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (StrLen == MaxLen) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // forward the pointer
 | |
|     //
 | |
|     CharInStr += StrLen;
 | |
|     *Size += StrLen;
 | |
|     *NumberOfStrings += 1;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // count ending two zeros.
 | |
|   //
 | |
|   *Size += 2;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Determin whether an SmbiosHandle has already in use.
 | |
| 
 | |
|   @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.
 | |
|   @retval FALSE      Smbios handle is NOT used.
 | |
|   
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| CheckSmbiosHandleExistance (
 | |
|   IN  LIST_ENTRY           *Head,
 | |
|   IN  EFI_SMBIOS_HANDLE    Handle
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY              *Link;
 | |
|   SMBIOS_HANDLE_ENTRY     *HandleEntry;
 | |
|   
 | |
|   for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
 | |
|     HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link);
 | |
|     if (HandleEntry->SmbiosHandle == Handle) {
 | |
|       return TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Get the max SmbiosHandle that could be use.
 | |
| 
 | |
|   @param  This           The EFI_SMBIOS_PROTOCOL instance.
 | |
|   @param  MaxHandle      The max handle that could be assigned to the SMBIOS record.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| GetMaxSmbiosHandle (
 | |
|   IN CONST  EFI_SMBIOS_PROTOCOL   *This,
 | |
|   IN OUT    EFI_SMBIOS_HANDLE     *MaxHandle
 | |
|   ) 
 | |
| {
 | |
|   if (This->MajorVersion == 2 && This->MinorVersion == 0) {
 | |
|     *MaxHandle = 0xFFFE;
 | |
|   } else {
 | |
|     *MaxHandle = 0xFEFF;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Get an SmbiosHandle that could use.
 | |
| 
 | |
|   @param  This                   The EFI_SMBIOS_PROTOCOL instance.
 | |
|   @param  SmbiosHandle           A unique handle will be assigned to the SMBIOS record.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Smbios handle got.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Smbios handle is NOT available.
 | |
|   
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetAvailableSmbiosHandle (
 | |
|   IN CONST EFI_SMBIOS_PROTOCOL   *This,
 | |
|   IN OUT   EFI_SMBIOS_HANDLE     *Handle
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY              *Head;
 | |
|   SMBIOS_INSTANCE         *Private;
 | |
|   EFI_SMBIOS_HANDLE       MaxSmbiosHandle;
 | |
|   EFI_SMBIOS_HANDLE       AvailableHandle;
 | |
| 
 | |
|   GetMaxSmbiosHandle(This, &MaxSmbiosHandle);
 | |
| 
 | |
|   Private = SMBIOS_INSTANCE_FROM_THIS (This);
 | |
|   Head = &Private->AllocatedHandleListHead;
 | |
|   for (AvailableHandle = 0; AvailableHandle < MaxSmbiosHandle; AvailableHandle++) {
 | |
|     if (!CheckSmbiosHandleExistance(Head, AvailableHandle)) {
 | |
|       *Handle = AvailableHandle;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_OUT_OF_RESOURCES;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Add an SMBIOS record.
 | |
| 
 | |
|   @param  This                  The EFI_SMBIOS_PROTOCOL instance.
 | |
|   @param  ProducerHandle        The handle of the controller or driver associated with the SMBIOS information. NULL
 | |
|                                 means no handle.
 | |
|   @param  SmbiosHandle          On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle
 | |
|                                 will be assigned to the SMBIOS record. If the SMBIOS handle is already in use,
 | |
|                                 EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.
 | |
|   @param  Record                The data for the fixed portion of the SMBIOS record. The format of the record is
 | |
|                                 determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined 
 | |
|                                 by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or 
 | |
|                                 a set of null terminated strings and a null.
 | |
| 
 | |
|   @retval EFI_SUCCESS           Record was added.
 | |
|   @retval EFI_OUT_OF_RESOURCES  Record was not added due to lack of system resources.
 | |
|   @retval EFI_ALREADY_STARTED   The SmbiosHandle passed in was already in use.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmbiosAdd (
 | |
|   IN CONST EFI_SMBIOS_PROTOCOL  *This,
 | |
|   IN EFI_HANDLE                 ProducerHandle, OPTIONAL
 | |
|   IN OUT EFI_SMBIOS_HANDLE      *SmbiosHandle,
 | |
|   IN EFI_SMBIOS_TABLE_HEADER    *Record
 | |
|   )
 | |
| {
 | |
|   VOID                        *Raw;
 | |
|   UINTN                       TotalSize;
 | |
|   UINTN                       RecordSize;
 | |
|   UINTN                       StructureSize;
 | |
|   UINTN                       NumberOfStrings;
 | |
|   EFI_STATUS                  Status;
 | |
|   LIST_ENTRY                  *Head;
 | |
|   SMBIOS_INSTANCE             *Private;
 | |
|   EFI_SMBIOS_ENTRY            *SmbiosEntry;
 | |
|   EFI_SMBIOS_HANDLE           MaxSmbiosHandle;
 | |
|   SMBIOS_HANDLE_ENTRY         *HandleEntry;
 | |
|   EFI_SMBIOS_RECORD_HEADER    *InternalRecord;
 | |
|   BOOLEAN                     Smbios32BitTable;
 | |
|   BOOLEAN                     Smbios64BitTable;
 | |
|   
 | |
|   if (SmbiosHandle == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   Private = SMBIOS_INSTANCE_FROM_THIS (This);
 | |
|   //
 | |
|   // Check whether SmbiosHandle is already in use
 | |
|   //
 | |
|   Head = &Private->AllocatedHandleListHead;
 | |
|   if (*SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) {
 | |
|     return EFI_ALREADY_STARTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // when SmbiosHandle is 0xFFFE, an available handle will be assigned
 | |
|   //
 | |
|   if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {
 | |
|     Status = GetAvailableSmbiosHandle(This, SmbiosHandle);
 | |
|     if (EFI_ERROR(Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // Check this handle validity
 | |
|     //
 | |
|     GetMaxSmbiosHandle(This, &MaxSmbiosHandle);
 | |
|     if (*SmbiosHandle > MaxSmbiosHandle) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Calculate record size and string number
 | |
|   //
 | |
|   Status = GetSmbiosStructureSize(This, Record, &StructureSize, &NumberOfStrings);
 | |
|   if (EFI_ERROR(Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Smbios32BitTable = FALSE;
 | |
|   Smbios64BitTable = FALSE;
 | |
|   if ((This->MajorVersion < 0x3) || 
 | |
|       ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) {
 | |
|     //
 | |
|     // For SMBIOS 32-bit table, 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. So the max size of 32-bit table should not exceed 65,535 bytes.
 | |
|     //
 | |
|     if ((EntryPointStructure != NULL) && 
 | |
|         (EntryPointStructure->TableLength + StructureSize > SMBIOS_TABLE_MAX_LENGTH)) {
 | |
|       DEBUG ((EFI_D_INFO, "SmbiosAdd: Total length exceeds max 32-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize));
 | |
|     } else {
 | |
|       Smbios32BitTable = TRUE;
 | |
|       DEBUG ((EFI_D_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 32-bit table\n", Record->Type, StructureSize));
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // For SMBIOS 3.0, Structure table maximum size in Entry Point structure is DWORD field limited to 0xFFFFFFFF bytes.
 | |
|   //
 | |
|   if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {
 | |
|     //
 | |
|     // For SMBIOS 64-bit table, Structure table maximum size in SMBIOS 3.0 (64-bit) Entry Point
 | |
|     // is a DWORD field limited to 0xFFFFFFFF bytes. So the max size of 64-bit table should not exceed 0xFFFFFFFF bytes.
 | |
|     //
 | |
|     if ((Smbios30EntryPointStructure != NULL) && 
 | |
|         (Smbios30EntryPointStructure->TableMaximumSize + StructureSize > SMBIOS_3_0_TABLE_MAX_LENGTH)) {
 | |
|       DEBUG ((EFI_D_INFO, "SmbiosAdd: Total length exceeds max 64-bit table length with type = %d size = 0x%x\n", Record->Type, StructureSize));
 | |
|     } else {
 | |
|       DEBUG ((EFI_D_INFO, "SmbiosAdd: Smbios type %d with size 0x%x is added to 64-bit table\n", Record->Type, StructureSize));
 | |
|       Smbios64BitTable = TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((!Smbios32BitTable) && (!Smbios64BitTable)) {
 | |
|     //
 | |
|     // If both 32-bit and 64-bit table are not updated, quit
 | |
|     //
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Enter into critical section
 | |
|   //  
 | |
|   Status = EfiAcquireLockOrFail (&Private->DataLock);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   
 | |
|   RecordSize  = sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize;
 | |
|   TotalSize   = sizeof (EFI_SMBIOS_ENTRY) + RecordSize;
 | |
| 
 | |
|   //
 | |
|   // Allocate internal buffer
 | |
|   //
 | |
|   SmbiosEntry = AllocateZeroPool (TotalSize);
 | |
|   if (SmbiosEntry == NULL) {
 | |
|     EfiReleaseLock (&Private->DataLock);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   HandleEntry = AllocateZeroPool (sizeof(SMBIOS_HANDLE_ENTRY));
 | |
|   if (HandleEntry == NULL) {
 | |
|     EfiReleaseLock (&Private->DataLock);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Build Handle Entry and insert into linked list
 | |
|   //
 | |
|   HandleEntry->Signature     = SMBIOS_HANDLE_ENTRY_SIGNATURE;
 | |
|   HandleEntry->SmbiosHandle  = *SmbiosHandle;
 | |
|   InsertTailList(&Private->AllocatedHandleListHead, &HandleEntry->Link);
 | |
| 
 | |
|   InternalRecord  = (EFI_SMBIOS_RECORD_HEADER *) (SmbiosEntry + 1);
 | |
|   Raw     = (VOID *) (InternalRecord + 1);
 | |
| 
 | |
|   //
 | |
|   // Build internal record Header
 | |
|   //
 | |
|   InternalRecord->Version     = EFI_SMBIOS_RECORD_HEADER_VERSION;
 | |
|   InternalRecord->HeaderSize  = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER);
 | |
|   InternalRecord->RecordSize  = RecordSize;
 | |
|   InternalRecord->ProducerHandle = ProducerHandle;
 | |
|   InternalRecord->NumberOfStrings = NumberOfStrings;
 | |
|   //
 | |
|   // Insert record into the internal linked list
 | |
|   //
 | |
|   SmbiosEntry->Signature    = EFI_SMBIOS_ENTRY_SIGNATURE;
 | |
|   SmbiosEntry->RecordHeader = InternalRecord;
 | |
|   SmbiosEntry->RecordSize   = TotalSize;
 | |
|   SmbiosEntry->Smbios32BitTable = Smbios32BitTable;
 | |
|   SmbiosEntry->Smbios64BitTable = Smbios64BitTable;
 | |
|   InsertTailList (&Private->DataListHead, &SmbiosEntry->Link);
 | |
| 
 | |
|   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 (Smbios32BitTable, Smbios64BitTable);
 | |
|   
 | |
|   //
 | |
|   // Leave critical section
 | |
|   //
 | |
|   EfiReleaseLock (&Private->DataLock);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update the string associated with an existing SMBIOS record.
 | |
| 
 | |
|   @param  This                  The EFI_SMBIOS_PROTOCOL instance.
 | |
|   @param  SmbiosHandle          SMBIOS Handle of structure that will have its string updated.
 | |
|   @param  StringNumber          The non-zero string number of the string to update
 | |
|   @param  String                Update the StringNumber string with String.
 | |
| 
 | |
|   @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
 | |
|   @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist.
 | |
|   @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
 | |
|   @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmbiosUpdateString (
 | |
|   IN CONST EFI_SMBIOS_PROTOCOL      *This,
 | |
|   IN EFI_SMBIOS_HANDLE              *SmbiosHandle,
 | |
|   IN UINTN                          *StringNumber,
 | |
|   IN CHAR8                          *String
 | |
|   )
 | |
| {
 | |
|   UINTN                     InputStrLen;
 | |
|   UINTN                     TargetStrLen;
 | |
|   UINTN                     StrIndex;
 | |
|   UINTN                     TargetStrOffset;
 | |
|   UINTN                     NewEntrySize;
 | |
|   CHAR8                     *StrStart;
 | |
|   VOID                      *Raw;
 | |
|   LIST_ENTRY                *Link;
 | |
|   LIST_ENTRY                *Head;
 | |
|   EFI_STATUS                Status;
 | |
|   SMBIOS_INSTANCE           *Private;
 | |
|   EFI_SMBIOS_ENTRY          *SmbiosEntry;
 | |
|   EFI_SMBIOS_ENTRY          *ResizedSmbiosEntry;
 | |
|   EFI_SMBIOS_HANDLE         MaxSmbiosHandle;
 | |
|   EFI_SMBIOS_TABLE_HEADER   *Record;
 | |
|   EFI_SMBIOS_RECORD_HEADER  *InternalRecord;
 | |
|   
 | |
|   //
 | |
|   // Check args validity
 | |
|   //
 | |
|   GetMaxSmbiosHandle(This, &MaxSmbiosHandle);
 | |
| 
 | |
|   if (*SmbiosHandle > MaxSmbiosHandle) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (String == NULL) {
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   if (*StringNumber == 0) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   InputStrLen = AsciiStrLen(String);
 | |
| 
 | |
|   if (This->MajorVersion < 2 || (This->MajorVersion == 2 && This->MinorVersion < 7)) {
 | |
|     if (InputStrLen > SMBIOS_STRING_MAX_LENGTH) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|   } else if (This->MajorVersion < 3) {
 | |
|     //
 | |
|     // 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;
 | |
|     }
 | |
|   } else {
 | |
|     if (InputStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH) {
 | |
|       //
 | |
|       // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
 | |
|       // The input string length should not exceed 0xFFFFFFFF bytes.
 | |
|       // 
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Private = SMBIOS_INSTANCE_FROM_THIS (This);
 | |
|   //
 | |
|   // Enter into critical section
 | |
|   //  
 | |
|   Status = EfiAcquireLockOrFail (&Private->DataLock);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Head = &Private->DataListHead;
 | |
|   for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
 | |
|     SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);
 | |
|     Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);
 | |
| 
 | |
|     if (Record->Handle == *SmbiosHandle) {
 | |
|       //
 | |
|       // Find out the specified SMBIOS record
 | |
|       //
 | |
|       if (*StringNumber > SmbiosEntry->RecordHeader->NumberOfStrings) {
 | |
|         EfiReleaseLock (&Private->DataLock);
 | |
|         return EFI_NOT_FOUND;
 | |
|       }
 | |
|       //
 | |
|       // Point to unformed string section
 | |
|       //
 | |
|       StrStart = (CHAR8 *) Record + Record->Length;
 | |
|      
 | |
|       for (StrIndex = 1, TargetStrOffset = 0; StrIndex < *StringNumber; StrStart++, TargetStrOffset++) {
 | |
|         //
 | |
|         // A string ends in 00h
 | |
|         //
 | |
|         if (*StrStart == 0) {
 | |
|           StrIndex++;
 | |
|         }
 | |
|         
 | |
|         //
 | |
|         // String section ends in double-null (0000h)
 | |
|         //
 | |
|         if (*StrStart == 0 && *(StrStart + 1) == 0) {
 | |
|           EfiReleaseLock (&Private->DataLock);
 | |
|           return EFI_NOT_FOUND;
 | |
|         } 
 | |
|       }
 | |
| 
 | |
|       if (*StrStart == 0) {
 | |
|         StrStart++;
 | |
|         TargetStrOffset++;
 | |
|       }
 | |
|       
 | |
|       //
 | |
|       // Now we get the string target
 | |
|       //
 | |
|       TargetStrLen = AsciiStrLen(StrStart);
 | |
|       if (InputStrLen == TargetStrLen) {
 | |
|         AsciiStrCpyS(StrStart, TargetStrLen + 1, 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 (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable);
 | |
|         EfiReleaseLock (&Private->DataLock);
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
|       
 | |
|       SmbiosEntry->Smbios32BitTable = FALSE;
 | |
|       SmbiosEntry->Smbios64BitTable = FALSE;
 | |
|       if ((This->MajorVersion < 0x3) || 
 | |
|           ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) {
 | |
|         //
 | |
|         // 32-bit table is produced, check the valid length.
 | |
|         //
 | |
|         if ((EntryPointStructure != NULL) && 
 | |
|             (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.
 | |
|           //
 | |
|           DEBUG ((EFI_D_INFO, "SmbiosUpdateString: Total length exceeds max 32-bit table length\n"));
 | |
|         } else {
 | |
|           DEBUG ((EFI_D_INFO, "SmbiosUpdateString: New smbios record add to 32-bit table\n"));
 | |
|           SmbiosEntry->Smbios32BitTable = TRUE;
 | |
|         }
 | |
|       } 
 | |
| 
 | |
|       if ((This->MajorVersion >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {
 | |
|         //
 | |
|         // 64-bit table is produced, check the valid length.
 | |
|         //
 | |
|         if ((Smbios30EntryPointStructure != NULL) && 
 | |
|             (Smbios30EntryPointStructure->TableMaximumSize + InputStrLen - TargetStrLen > SMBIOS_3_0_TABLE_MAX_LENGTH)) {
 | |
|           DEBUG ((EFI_D_INFO, "SmbiosUpdateString: Total length exceeds max 64-bit table length\n"));
 | |
|         } else {
 | |
|           DEBUG ((EFI_D_INFO, "SmbiosUpdateString: New smbios record add to 64-bit table\n"));
 | |
|           SmbiosEntry->Smbios64BitTable = TRUE;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if ((!SmbiosEntry->Smbios32BitTable) && (!SmbiosEntry->Smbios64BitTable)) {
 | |
|         EfiReleaseLock (&Private->DataLock);
 | |
|         return EFI_UNSUPPORTED;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Original string buffer size is not exactly match input string length.
 | |
|       // Re-allocate buffer is needed.
 | |
|       //
 | |
|       NewEntrySize = SmbiosEntry->RecordSize + InputStrLen - TargetStrLen;
 | |
|       ResizedSmbiosEntry = AllocateZeroPool (NewEntrySize);
 | |
| 
 | |
|       if (ResizedSmbiosEntry == NULL) {
 | |
|         EfiReleaseLock (&Private->DataLock);
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       InternalRecord  = (EFI_SMBIOS_RECORD_HEADER *) (ResizedSmbiosEntry + 1);
 | |
|       Raw     = (VOID *) (InternalRecord + 1);
 | |
| 
 | |
|       //
 | |
|       // Build internal record Header
 | |
|       //
 | |
|       InternalRecord->Version     = EFI_SMBIOS_RECORD_HEADER_VERSION;
 | |
|       InternalRecord->HeaderSize  = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER);
 | |
|       InternalRecord->RecordSize  = SmbiosEntry->RecordHeader->RecordSize + InputStrLen - TargetStrLen;
 | |
|       InternalRecord->ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;
 | |
|       InternalRecord->NumberOfStrings = SmbiosEntry->RecordHeader->NumberOfStrings;
 | |
| 
 | |
|       //
 | |
|       // Copy SMBIOS structure and optional strings.
 | |
|       //
 | |
|       CopyMem (Raw, SmbiosEntry->RecordHeader + 1, Record->Length + TargetStrOffset);
 | |
|       CopyMem ((VOID*)((UINTN)Raw + Record->Length + TargetStrOffset), String, InputStrLen + 1);
 | |
|       CopyMem ((CHAR8*)((UINTN)Raw + Record->Length + TargetStrOffset + InputStrLen + 1),
 | |
|                (CHAR8*)Record + Record->Length + TargetStrOffset + TargetStrLen + 1,
 | |
|                SmbiosEntry->RecordHeader->RecordSize - sizeof (EFI_SMBIOS_RECORD_HEADER) - Record->Length - TargetStrOffset - TargetStrLen - 1);
 | |
| 
 | |
|       //
 | |
|       // Insert new record
 | |
|       //
 | |
|       ResizedSmbiosEntry->Signature    = EFI_SMBIOS_ENTRY_SIGNATURE;
 | |
|       ResizedSmbiosEntry->RecordHeader = InternalRecord;
 | |
|       ResizedSmbiosEntry->RecordSize   = NewEntrySize;
 | |
|       ResizedSmbiosEntry->Smbios32BitTable = SmbiosEntry->Smbios32BitTable;
 | |
|       ResizedSmbiosEntry->Smbios64BitTable = SmbiosEntry->Smbios64BitTable;
 | |
|       InsertTailList (Link->ForwardLink, &ResizedSmbiosEntry->Link);
 | |
| 
 | |
|       //
 | |
|       // Remove old record
 | |
|       //
 | |
|       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 (ResizedSmbiosEntry->Smbios32BitTable, ResizedSmbiosEntry->Smbios64BitTable);
 | |
|       EfiReleaseLock (&Private->DataLock);
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   EfiReleaseLock (&Private->DataLock);
 | |
|   return EFI_INVALID_PARAMETER;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Remove an SMBIOS record.
 | |
| 
 | |
|   @param  This                  The EFI_SMBIOS_PROTOCOL instance.
 | |
|   @param  SmbiosHandle          The handle of the SMBIOS record to remove.
 | |
| 
 | |
|   @retval EFI_SUCCESS           SMBIOS record was removed.
 | |
|   @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmbiosRemove (
 | |
|   IN CONST EFI_SMBIOS_PROTOCOL   *This,
 | |
|   IN EFI_SMBIOS_HANDLE           SmbiosHandle
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY                 *Link;
 | |
|   LIST_ENTRY                 *Head;
 | |
|   EFI_STATUS                 Status;
 | |
|   EFI_SMBIOS_HANDLE          MaxSmbiosHandle;
 | |
|   SMBIOS_INSTANCE            *Private;
 | |
|   EFI_SMBIOS_ENTRY           *SmbiosEntry;
 | |
|   SMBIOS_HANDLE_ENTRY        *HandleEntry;
 | |
|   EFI_SMBIOS_TABLE_HEADER    *Record;
 | |
| 
 | |
|   //
 | |
|   // Check args validity
 | |
|   //
 | |
|   GetMaxSmbiosHandle(This, &MaxSmbiosHandle);
 | |
| 
 | |
|   if (SmbiosHandle > MaxSmbiosHandle) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Private = SMBIOS_INSTANCE_FROM_THIS (This);
 | |
|   //
 | |
|   // Enter into critical section
 | |
|   //  
 | |
|   Status = EfiAcquireLockOrFail (&Private->DataLock);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Head = &Private->DataListHead;
 | |
|   for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
 | |
|     SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);
 | |
|     Record = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1);
 | |
|     if (Record->Handle == SmbiosHandle) {
 | |
|       //
 | |
|       // Remove specified smobios record from DataList
 | |
|       //
 | |
|       RemoveEntryList(Link);
 | |
|       // 
 | |
|       // Remove this handle from AllocatedHandleList
 | |
|       //
 | |
|       Head = &Private->AllocatedHandleListHead;
 | |
|       for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
 | |
|         HandleEntry = SMBIOS_HANDLE_ENTRY_FROM_LINK(Link);
 | |
|         if (HandleEntry->SmbiosHandle == SmbiosHandle) {
 | |
|           RemoveEntryList(Link);
 | |
|           FreePool(HandleEntry);
 | |
|           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.
 | |
|       //
 | |
|       if (SmbiosEntry->Smbios32BitTable) {
 | |
|         DEBUG ((EFI_D_INFO, "SmbiosRemove: remove from 32-bit table\n"));
 | |
|       }
 | |
|       if (SmbiosEntry->Smbios64BitTable) {
 | |
|         DEBUG ((EFI_D_INFO, "SmbiosRemove: remove from 64-bit table\n"));
 | |
|       }
 | |
|       //
 | |
|       // Update the whole SMBIOS table again based on which table the removed SMBIOS record is in.
 | |
|       //
 | |
|       SmbiosTableConstruction (SmbiosEntry->Smbios32BitTable, SmbiosEntry->Smbios64BitTable);
 | |
|       FreePool(SmbiosEntry);
 | |
|       EfiReleaseLock (&Private->DataLock);
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Leave critical section
 | |
|   //
 | |
|   EfiReleaseLock (&Private->DataLock);
 | |
|   return EFI_INVALID_PARAMETER;
 | |
|   
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Allow the caller to discover all or some of the SMBIOS records.
 | |
| 
 | |
|   @param  This                  The EFI_SMBIOS_PROTOCOL instance.
 | |
|   @param  SmbiosHandle          On entry, points to the previous handle of the SMBIOS record. On exit, points to the
 | |
|                                 next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record
 | |
|                                 handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS records.
 | |
|   @param  Type                  On entry it means return the next SMBIOS record of type Type. If a NULL is passed in 
 | |
|                                 this functionally it ignored. Type is not modified by the GetNext() function.
 | |
|   @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.
 | |
|   @param  ProducerHandle        On exit, points to the ProducerHandle registered by Add(). If no ProducerHandle was passed into Add() NULL is returned. 
 | |
|                                 If a NULL pointer is passed in no data will be returned 
 | |
|                                 
 | |
|   @retval EFI_SUCCESS           SMBIOS record information was successfully returned in Record.
 | |
|   @retval EFI_NOT_FOUND         The SMBIOS record with SmbiosHandle was the last available record.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmbiosGetNext (
 | |
|   IN CONST EFI_SMBIOS_PROTOCOL      *This,
 | |
|   IN OUT EFI_SMBIOS_HANDLE          *SmbiosHandle,
 | |
|   IN EFI_SMBIOS_TYPE                *Type,          OPTIONAL
 | |
|   OUT EFI_SMBIOS_TABLE_HEADER       **Record,
 | |
|   OUT EFI_HANDLE                    *ProducerHandle OPTIONAL
 | |
|   )
 | |
| {
 | |
|   BOOLEAN                  StartPointFound;
 | |
|   LIST_ENTRY               *Link;
 | |
|   LIST_ENTRY               *Head;
 | |
|   SMBIOS_INSTANCE          *Private;
 | |
|   EFI_SMBIOS_ENTRY         *SmbiosEntry;
 | |
|   EFI_SMBIOS_TABLE_HEADER  *SmbiosTableHeader;
 | |
| 
 | |
|   if (SmbiosHandle == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   StartPointFound = FALSE;
 | |
|   Private = SMBIOS_INSTANCE_FROM_THIS (This);
 | |
|   Head = &Private->DataListHead;
 | |
|   for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
 | |
|     SmbiosEntry = SMBIOS_ENTRY_FROM_LINK(Link);
 | |
|     SmbiosTableHeader = (EFI_SMBIOS_TABLE_HEADER*)(SmbiosEntry->RecordHeader + 1); 
 | |
| 
 | |
|     //
 | |
|     // If SmbiosHandle is 0xFFFE, the first matched SMBIOS record handle will be returned
 | |
|     //
 | |
|     if (*SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {
 | |
|       if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {
 | |
|         continue;  
 | |
|       }
 | |
| 
 | |
|       *SmbiosHandle = SmbiosTableHeader->Handle;
 | |
|       *Record =SmbiosTableHeader;
 | |
|       if (ProducerHandle != NULL) {
 | |
|         *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;
 | |
|       }
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Start this round search from the next SMBIOS handle
 | |
|     //
 | |
|     if (!StartPointFound && (*SmbiosHandle == SmbiosTableHeader->Handle)) {
 | |
|       StartPointFound = TRUE;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (StartPointFound) {
 | |
|       if ((Type != NULL) && (*Type != SmbiosTableHeader->Type)) {
 | |
|         continue; 
 | |
|       }
 | |
|       
 | |
|       *SmbiosHandle = SmbiosTableHeader->Handle;
 | |
|       *Record = SmbiosTableHeader; 
 | |
|       if (ProducerHandle != NULL) {
 | |
|         *ProducerHandle = SmbiosEntry->RecordHeader->ProducerHandle;
 | |
|       }
 | |
| 
 | |
|       return EFI_SUCCESS;   
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
 | |
|   return EFI_NOT_FOUND;
 | |
|   
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   Entry Point and return the pointer to it.
 | |
|   
 | |
|   @param  TableEntryPointStructure   On exit, points to the SMBIOS entrypoint structure.
 | |
|                                 
 | |
|   @retval EFI_SUCCESS                Structure created sucessfully.
 | |
|   @retval EFI_OUT_OF_RESOURCES       No enough memory.
 | |
|   
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmbiosCreateTable (
 | |
|   OUT VOID    **TableEntryPointStructure
 | |
|   )
 | |
| {
 | |
|   UINT8                           *BufferPointer;
 | |
|   UINTN                           RecordSize;
 | |
|   UINTN                           NumOfStr;
 | |
|   EFI_STATUS                      Status;
 | |
|   EFI_SMBIOS_HANDLE               SmbiosHandle;
 | |
|   EFI_SMBIOS_PROTOCOL             *SmbiosProtocol;
 | |
|   EFI_PHYSICAL_ADDRESS            PhysicalAddress;
 | |
|   EFI_SMBIOS_TABLE_HEADER         *SmbiosRecord;
 | |
|   EFI_SMBIOS_TABLE_END_STRUCTURE  EndStructure;
 | |
|   EFI_SMBIOS_ENTRY                *CurrentSmbiosEntry;
 | |
|   
 | |
|   Status            = EFI_SUCCESS;
 | |
|   BufferPointer     = NULL;
 | |
| 
 | |
|   if (EntryPointStructure == NULL) {
 | |
|     //
 | |
|     // Initialize the EntryPointStructure with initial values.
 | |
|     // It should be done only once.
 | |
|     // Allocate memory (below 4GB).
 | |
|     //
 | |
|     DEBUG ((EFI_D_INFO, "SmbiosCreateTable: Initialize 32-bit entry point structure\n"));
 | |
|     EntryPointStructureData.MajorVersion  = mPrivateData.Smbios.MajorVersion;
 | |
|     EntryPointStructureData.MinorVersion  = mPrivateData.Smbios.MinorVersion;
 | |
|     EntryPointStructureData.SmbiosBcdRevision = (UINT8) ((PcdGet16 (PcdSmbiosVersion) >> 4) & 0xf0) | (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x0f);
 | |
|     PhysicalAddress = 0xffffffff;
 | |
|     Status = gBS->AllocatePages (
 | |
|                     AllocateMaxAddress,
 | |
|                     EfiRuntimeServicesData,
 | |
|                     EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),
 | |
|                     &PhysicalAddress
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((EFI_D_ERROR, "SmbiosCreateTable () could not allocate EntryPointStructure < 4GB\n"));
 | |
|       Status = gBS->AllocatePages (
 | |
|                       AllocateAnyPages,
 | |
|                       EfiRuntimeServicesData,
 | |
|                       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)
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get Smbios protocol to traverse SMBIOS records.
 | |
|   //
 | |
|   SmbiosProtocol = &mPrivateData.Smbios;
 | |
| 
 | |
|   //
 | |
|   // Make some statistics about all the structures
 | |
|   //
 | |
|   EntryPointStructure->NumberOfSmbiosStructures = 0;
 | |
|   EntryPointStructure->TableLength              = 0;
 | |
|   EntryPointStructure->MaxStructureSize         = 0;
 | |
| 
 | |
|   //
 | |
|   // Calculate EPS Table Length
 | |
|   //
 | |
|   CurrentSmbiosEntry = NULL;
 | |
|   do {
 | |
|     Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);
 | |
|                                
 | |
|     if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios32BitTable)) {
 | |
|       GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);
 | |
|       //
 | |
|       // Record NumberOfSmbiosStructures, TableLength and MaxStructureSize
 | |
|       //
 | |
|       EntryPointStructure->NumberOfSmbiosStructures++;
 | |
|       EntryPointStructure->TableLength = (UINT16) (EntryPointStructure->TableLength + RecordSize);
 | |
|       if (RecordSize > EntryPointStructure->MaxStructureSize) {
 | |
|         EntryPointStructure->MaxStructureSize = (UINT16) RecordSize;
 | |
|       }
 | |
|     }
 | |
|   } while (!EFI_ERROR(Status));
 | |
|   
 | |
|   //
 | |
|   // Create End-Of-Table structure
 | |
|   //
 | |
|   GetMaxSmbiosHandle(SmbiosProtocol, &SmbiosHandle);
 | |
|   EndStructure.Header.Type = EFI_SMBIOS_TYPE_END_OF_TABLE;
 | |
|   EndStructure.Header.Length = (UINT8) sizeof (EFI_SMBIOS_TABLE_HEADER);
 | |
|   EndStructure.Header.Handle = SmbiosHandle;
 | |
|   EndStructure.Tailing[0] = 0;
 | |
|   EndStructure.Tailing[1] = 0;
 | |
|   EntryPointStructure->NumberOfSmbiosStructures++;
 | |
|   EntryPointStructure->TableLength = (UINT16) (EntryPointStructure->TableLength + sizeof (EndStructure));
 | |
|   if (sizeof (EndStructure) > EntryPointStructure->MaxStructureSize) {
 | |
|     EntryPointStructure->MaxStructureSize = (UINT16) sizeof (EndStructure);
 | |
|   }
 | |
| 
 | |
|   if ((UINTN) EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength) > mPreAllocatedPages) {
 | |
|     //
 | |
|     // If new SMBIOS table size exceeds the previous allocated page, 
 | |
|     // it is time to re-allocate memory (below 4GB).
 | |
|     // 
 | |
|     DEBUG ((EFI_D_INFO, "%a() re-allocate SMBIOS 32-bit table\n",
 | |
|       __FUNCTION__));
 | |
|     if (EntryPointStructure->TableAddress != 0) {
 | |
|       //
 | |
|       // Free the previous allocated page
 | |
|       //      
 | |
|       FreePages (
 | |
|             (VOID*)(UINTN)EntryPointStructure->TableAddress,
 | |
|             mPreAllocatedPages
 | |
|             );
 | |
|       EntryPointStructure->TableAddress = 0;
 | |
|       mPreAllocatedPages = 0;
 | |
|     }
 | |
|     
 | |
|     PhysicalAddress = 0xffffffff;
 | |
|     Status = gBS->AllocatePages (
 | |
|                     AllocateMaxAddress,
 | |
|                     EfiRuntimeServicesData,
 | |
|                     EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength),
 | |
|                     &PhysicalAddress
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((EFI_D_ERROR, "SmbiosCreateTable() could not allocate SMBIOS table < 4GB\n"));
 | |
|       EntryPointStructure->TableAddress = 0;
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     } else {
 | |
|       EntryPointStructure->TableAddress = (UINT32) PhysicalAddress;
 | |
|       mPreAllocatedPages = EFI_SIZE_TO_PAGES (EntryPointStructure->TableLength);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Assemble the tables
 | |
|   //
 | |
|   ASSERT (EntryPointStructure->TableAddress != 0);
 | |
|   BufferPointer = (UINT8 *) (UINTN) EntryPointStructure->TableAddress;
 | |
|   CurrentSmbiosEntry = NULL;
 | |
|   do {
 | |
|     Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);
 | |
| 
 | |
|     if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios32BitTable)) {
 | |
|       GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);
 | |
|       CopyMem (BufferPointer, SmbiosRecord, RecordSize);
 | |
|       BufferPointer = BufferPointer + RecordSize;
 | |
|     }
 | |
|   } while (!EFI_ERROR(Status));
 | |
|   
 | |
|   //
 | |
|   // Assemble End-Of-Table structure
 | |
|   //
 | |
|   CopyMem (BufferPointer, &EndStructure, sizeof (EndStructure));
 | |
| 
 | |
|   //
 | |
|   // Fixup checksums in the Entry Point Structure
 | |
|   //
 | |
|   EntryPointStructure->IntermediateChecksum = 0;
 | |
|   EntryPointStructure->EntryPointStructureChecksum = 0;
 | |
| 
 | |
|   EntryPointStructure->IntermediateChecksum =
 | |
|     CalculateCheckSum8 ((UINT8 *) EntryPointStructure + 0x10, EntryPointStructure->EntryPointLength - 0x10);
 | |
|   EntryPointStructure->EntryPointStructureChecksum =
 | |
|     CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure->EntryPointLength);
 | |
| 
 | |
|   //
 | |
|   // Returns the pointer
 | |
|   //
 | |
|   *TableEntryPointStructure = EntryPointStructure;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Assembles SMBIOS 64-bit 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.
 | |
| 
 | |
|   @retval EFI_SUCCESS                Structure created sucessfully.
 | |
|   @retval EFI_OUT_OF_RESOURCES       No enough memory.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmbiosCreate64BitTable (
 | |
|   OUT VOID    **TableEntryPointStructure
 | |
|   )
 | |
| {
 | |
|   UINT8                           *BufferPointer;
 | |
|   UINTN                           RecordSize;
 | |
|   UINTN                           NumOfStr;
 | |
|   EFI_STATUS                      Status;
 | |
|   EFI_SMBIOS_HANDLE               SmbiosHandle;
 | |
|   EFI_SMBIOS_PROTOCOL             *SmbiosProtocol;
 | |
|   EFI_PHYSICAL_ADDRESS            PhysicalAddress;
 | |
|   EFI_SMBIOS_TABLE_HEADER         *SmbiosRecord;
 | |
|   EFI_SMBIOS_TABLE_END_STRUCTURE  EndStructure;
 | |
|   EFI_SMBIOS_ENTRY                *CurrentSmbiosEntry;
 | |
|   
 | |
|   Status            = EFI_SUCCESS;
 | |
|   BufferPointer     = NULL;
 | |
| 
 | |
|   if (Smbios30EntryPointStructure == NULL) {
 | |
|     //
 | |
|     // Initialize the Smbios30EntryPointStructure with initial values.
 | |
|     // It should be done only once.
 | |
|     // Allocate memory at any address.
 | |
|     //
 | |
|     DEBUG ((EFI_D_INFO, "SmbiosCreateTable: Initialize 64-bit entry point structure\n"));
 | |
|     Smbios30EntryPointStructureData.MajorVersion  = mPrivateData.Smbios.MajorVersion;
 | |
|     Smbios30EntryPointStructureData.MinorVersion  = mPrivateData.Smbios.MinorVersion;
 | |
|     Smbios30EntryPointStructureData.DocRev        = PcdGet8 (PcdSmbiosDocRev);
 | |
|     Status = gBS->AllocatePages (
 | |
|                     AllocateAnyPages,
 | |
|                     EfiRuntimeServicesData,
 | |
|                     EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)),
 | |
|                     &PhysicalAddress
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((EFI_D_ERROR, "SmbiosCreate64BitTable() could not allocate Smbios30EntryPointStructure\n"));
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     
 | |
|     Smbios30EntryPointStructure = (SMBIOS_TABLE_3_0_ENTRY_POINT *) (UINTN) PhysicalAddress;
 | |
|     
 | |
|     CopyMem (
 | |
|       Smbios30EntryPointStructure,
 | |
|       &Smbios30EntryPointStructureData,
 | |
|       sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get Smbios protocol to traverse SMBIOS records.
 | |
|   //
 | |
|   SmbiosProtocol = &mPrivateData.Smbios;
 | |
|   Smbios30EntryPointStructure->TableMaximumSize = 0;
 | |
| 
 | |
|   //
 | |
|   // Calculate EPS Table Length
 | |
|   //
 | |
|   CurrentSmbiosEntry = NULL;
 | |
|   do {
 | |
|     Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);
 | |
|                                
 | |
|     if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios64BitTable)) {
 | |
|       GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);
 | |
|       //
 | |
|       // Record TableMaximumSize
 | |
|       //
 | |
|       Smbios30EntryPointStructure->TableMaximumSize = (UINT32) (Smbios30EntryPointStructure->TableMaximumSize + RecordSize);
 | |
|     }
 | |
|   } while (!EFI_ERROR(Status));
 | |
| 
 | |
|   //
 | |
|   // Create End-Of-Table structure
 | |
|   //
 | |
|   GetMaxSmbiosHandle(SmbiosProtocol, &SmbiosHandle);
 | |
|   EndStructure.Header.Type = EFI_SMBIOS_TYPE_END_OF_TABLE;
 | |
|   EndStructure.Header.Length = (UINT8) sizeof (EFI_SMBIOS_TABLE_HEADER);
 | |
|   EndStructure.Header.Handle = SmbiosHandle;
 | |
|   EndStructure.Tailing[0] = 0;
 | |
|   EndStructure.Tailing[1] = 0;
 | |
|   Smbios30EntryPointStructure->TableMaximumSize = (UINT32) (Smbios30EntryPointStructure->TableMaximumSize + sizeof (EndStructure));
 | |
| 
 | |
|   if ((UINTN) EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize) > mPre64BitAllocatedPages) {
 | |
|     //
 | |
|     // If new SMBIOS table size exceeds the previous allocated page, 
 | |
|     // it is time to re-allocate memory at anywhere.
 | |
|     //
 | |
|     DEBUG ((EFI_D_INFO, "%a() re-allocate SMBIOS 64-bit table\n",
 | |
|       __FUNCTION__));
 | |
|     if (Smbios30EntryPointStructure->TableAddress != 0) {
 | |
|       //
 | |
|       // Free the previous allocated page
 | |
|       //      
 | |
|       FreePages (
 | |
|             (VOID*)(UINTN)Smbios30EntryPointStructure->TableAddress,
 | |
|             mPre64BitAllocatedPages
 | |
|             );
 | |
|       Smbios30EntryPointStructure->TableAddress = 0;
 | |
|       mPre64BitAllocatedPages = 0;
 | |
|     }
 | |
| 
 | |
|     Status = gBS->AllocatePages (
 | |
|                     AllocateAnyPages,
 | |
|                     EfiRuntimeServicesData,
 | |
|                     EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize),
 | |
|                     &PhysicalAddress
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((EFI_D_ERROR, "SmbiosCreateTable() could not allocate SMBIOS 64-bit table\n"));
 | |
|       Smbios30EntryPointStructure->TableAddress = 0;
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     } else {
 | |
|       Smbios30EntryPointStructure->TableAddress = PhysicalAddress;
 | |
|       mPre64BitAllocatedPages = EFI_SIZE_TO_PAGES (Smbios30EntryPointStructure->TableMaximumSize);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Assemble the tables
 | |
|   //
 | |
|   ASSERT (Smbios30EntryPointStructure->TableAddress != 0);
 | |
|   BufferPointer = (UINT8 *) (UINTN) Smbios30EntryPointStructure->TableAddress;
 | |
|   CurrentSmbiosEntry = NULL;
 | |
|   do {
 | |
|     Status = GetNextSmbiosRecord (SmbiosProtocol, &CurrentSmbiosEntry, &SmbiosRecord);
 | |
| 
 | |
|     if ((Status == EFI_SUCCESS) && (CurrentSmbiosEntry->Smbios64BitTable)) {
 | |
|       //
 | |
|       // This record can be added to 64-bit table
 | |
|       //
 | |
|       GetSmbiosStructureSize(SmbiosProtocol, SmbiosRecord, &RecordSize, &NumOfStr);
 | |
|       CopyMem (BufferPointer, SmbiosRecord, RecordSize);
 | |
|       BufferPointer = BufferPointer + RecordSize;
 | |
|     }
 | |
|   } while (!EFI_ERROR(Status));
 | |
| 
 | |
|   //
 | |
|   // Assemble End-Of-Table structure
 | |
|   //
 | |
|   CopyMem (BufferPointer, &EndStructure, sizeof (EndStructure));
 | |
| 
 | |
|   //
 | |
|   // Fixup checksums in the Entry Point Structure
 | |
|   //
 | |
|   Smbios30EntryPointStructure->EntryPointStructureChecksum = 0;
 | |
|   Smbios30EntryPointStructure->EntryPointStructureChecksum =
 | |
|     CalculateCheckSum8 ((UINT8 *) Smbios30EntryPointStructure, Smbios30EntryPointStructure->EntryPointLength);
 | |
| 
 | |
|   //
 | |
|   // Returns the pointer
 | |
|   //
 | |
|   *TableEntryPointStructure = Smbios30EntryPointStructure;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create Smbios Table and installs the Smbios Table to the System Table.
 | |
|   
 | |
|   @param  Smbios32BitTable    The flag to update 32-bit table.
 | |
|   @param  Smbios64BitTable    The flag to update 64-bit table.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SmbiosTableConstruction (
 | |
|   BOOLEAN     Smbios32BitTable,
 | |
|   BOOLEAN     Smbios64BitTable
 | |
|   )
 | |
| {
 | |
|   UINT8       *Eps;
 | |
|   UINT8       *Eps64Bit;
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   if (Smbios32BitTable) {
 | |
|     Status = SmbiosCreateTable ((VOID **) &Eps);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, Eps);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Smbios64BitTable) {
 | |
|     Status = SmbiosCreate64BitTable ((VOID **) &Eps64Bit);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       gBS->InstallConfigurationTable (&gEfiSmbios3TableGuid, Eps64Bit);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   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
 | |
| 
 | |
|   @retval EFI_SUCCESS    Smbios protocol installed
 | |
|   @retval Other          No protocol installed, unload driver.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmbiosDriverEntryPoint (
 | |
|   IN EFI_HANDLE           ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE     *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
| 
 | |
|   mPrivateData.Signature                = SMBIOS_INSTANCE_SIGNATURE;
 | |
|   mPrivateData.Smbios.Add               = SmbiosAdd;
 | |
|   mPrivateData.Smbios.UpdateString      = SmbiosUpdateString;
 | |
|   mPrivateData.Smbios.Remove            = SmbiosRemove;
 | |
|   mPrivateData.Smbios.GetNext           = SmbiosGetNext;
 | |
|   mPrivateData.Smbios.MajorVersion      = (UINT8) (PcdGet16 (PcdSmbiosVersion) >> 8);
 | |
|   mPrivateData.Smbios.MinorVersion      = (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x00ff);
 | |
| 
 | |
|   InitializeListHead (&mPrivateData.DataListHead);
 | |
|   InitializeListHead (&mPrivateData.AllocatedHandleListHead);
 | |
|   EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
 | |
|   
 | |
|   //
 | |
|   // Make a new handle and install the protocol
 | |
|   //
 | |
|   mPrivateData.Handle = NULL;
 | |
|   Status = gBS->InstallProtocolInterface (
 | |
|                   &mPrivateData.Handle,
 | |
|                   &gEfiSmbiosProtocolGuid,
 | |
|                   EFI_NATIVE_INTERFACE,
 | |
|                   &mPrivateData.Smbios
 | |
|                   );
 | |
| 
 | |
|   return Status;
 | |
| }
 |