Example #1
0
/**
  Update the structure buffer of a structure node in SMBIOS database.
  The function lead the structure pointer for SMBIOS record changed.
  
  @param StructureNode The structure node whose structure buffer is to be enlarged.
  @param NewRecord     The new SMBIOS record.
  
**/
VOID
SmbiosUpdateStructureBuffer (
  IN OUT  SMBIOS_STRUCTURE_NODE *StructureNode,
  IN EFI_SMBIOS_TABLE_HEADER    *NewRecord
  )
{
  EFI_SMBIOS_PROTOCOL       *Smbios;
  EFI_STATUS                Status;
  UINT8                     CountOfString;
  
  Smbios    = GetSmbiosProtocol();
  ASSERT (Smbios != NULL);
  
  Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle);
  ASSERT_EFI_ERROR (Status);
  
  //
  // try to use original handle to enlarge the buffer.
  //
  Status = Smbios->Add (Smbios, NULL, &StructureNode->SmbiosHandle, NewRecord);
  ASSERT_EFI_ERROR (Status);
  
  StructureNode->Structure = GetSmbiosBufferFromHandle (
                               StructureNode->SmbiosHandle, 
                               StructureNode->SmbiosType, 
                               NULL
                               );
  GetSmbiosStructureSize (
    StructureNode->Structure,
    &StructureNode->StructureSize,
    &CountOfString
    );
  return ;
}
Example #2
0
/**
  Enlarge the structure buffer of a structure node in SMBIOS database.
  The function maybe lead the structure pointer for SMBIOS record changed.
  
  @param StructureNode The structure node whose structure buffer is to be enlarged.
  @param NewLength     The new length of SMBIOS record which does not include unformat area.
  @param OldBufferSize The old size of SMBIOS record buffer.
  @param NewBufferSize The new size is targeted for enlarged.
  
  @retval EFI_OUT_OF_RESOURCES  No more memory to allocate new record
  @retval EFI_SUCCESS           Success to enlarge the record buffer size.
**/
EFI_STATUS
SmbiosEnlargeStructureBuffer (
  IN OUT  SMBIOS_STRUCTURE_NODE *StructureNode,
  UINT8                         NewLength,
  UINTN                         OldBufferSize,
  UINTN                         NewBufferSize
  )
{
  EFI_SMBIOS_TABLE_HEADER   *NewRecord;
  EFI_SMBIOS_PROTOCOL       *Smbios;
  EFI_STATUS                Status;
  UINT8                     CountOfString;
  
  NewRecord = NULL;
  Smbios    = GetSmbiosProtocol();
  ASSERT (Smbios != NULL);
  
  NewRecord = (EFI_SMBIOS_TABLE_HEADER*) AllocateZeroPool (NewBufferSize);
  if (NewRecord == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  CopyMem (NewRecord, StructureNode->Structure, OldBufferSize);
  
  
  Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle);
  ASSERT_EFI_ERROR (Status);
  
  //
  // try to use original handle to enlarge the buffer.
  //
  NewRecord->Length = NewLength;
  Status = Smbios->Add (Smbios, NULL, &StructureNode->SmbiosHandle, NewRecord);
  ASSERT_EFI_ERROR (Status);
  FreePool (NewRecord);
  
  StructureNode->Structure = GetSmbiosBufferFromHandle (
                               StructureNode->SmbiosHandle, 
                               StructureNode->SmbiosType, 
                               NULL
                               );
  GetSmbiosStructureSize (
    StructureNode->Structure,
    &StructureNode->StructureSize,
    &CountOfString
    );
  return EFI_SUCCESS;
}
Example #3
0
/**
  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, if non-zero, the handle of the SMBIOS record. If zero, 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;
  
  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 != 0 && CheckSmbiosHandleExistance(Head, *SmbiosHandle)) {
    return EFI_ALREADY_STARTED;
  }

  //
  // when SmbiosHandle is zero, an available handle will be assigned
  //
  if (*SmbiosHandle == 0) {
    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;
  }

  //
  // 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;
  InsertTailList (&Private->DataListHead, &SmbiosEntry->Link);

  CopyMem (Raw, Record, StructureSize);
  ((EFI_SMBIOS_TABLE_HEADER*)Raw)->Handle = *SmbiosHandle;

  //
  // Leave critical section
  //
  EfiReleaseLock (&Private->DataLock);
  return EFI_SUCCESS;
}
Example #4
0
/**
  Fill a standard Smbios string field. 
  
  This function will convert the unicode string to single byte chars, and only
  English language is supported.
  This function changes the Structure pointer value of the structure node, 
  which should be noted by Caller.
  
  @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
  @param Offset           Offset of SMBIOS record which RecordData will be filled.
  @param RecordData       RecordData buffer will be filled.
  @param RecordDataSize   The size of RecordData buffer.
  
  @retval EFI_INVALID_PARAMETER   RecordDataSize is too larger
  @retval EFI_OUT_OF_RESOURCES    No memory to allocate new buffer for string
  @retval EFI_SUCCESS             Sucess append string for a SMBIOS record.
**/
EFI_STATUS
SmbiosFldString (
  IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
  IN      UINT32                    Offset,
  IN      VOID                      *RecordData,
  IN      UINT32                    RecordDataSize
  )
{
  EFI_STATUS              Status;
  UINT16                  *Data;
  CHAR8                   AsciiData[SMBIOS_STRING_MAX_LENGTH];
  UINT8                   CountOfStrings;
  UINTN                   OrigStringNumber;
  EFI_SMBIOS_PROTOCOL     *Smbios;
  EFI_SMBIOS_HANDLE       SmbiosHandle;
  UINT32                  OrigStructureSize;
  UINTN                   NewStructureSize;
  EFI_SMBIOS_TABLE_HEADER *NewRecord;
  UINT32                  StringLength;
  
  Status            = EFI_SUCCESS;
  OrigStringNumber  = 0;
  OrigStructureSize = 0;

  //
  // if we have a NULL token,
  //
  if (0 == *((STRING_REF *) RecordData)) {
    *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0;
    return EFI_SUCCESS;
  }
  
  //
  // Get the String from the Hii Database
  //
  Data = HiiGetPackageString (
             &(StructureNode->ProducerName),
             *((EFI_STRING_ID *) RecordData),
             NULL
             );
  if (Data == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  StringLength = (UINT32)StrLen (Data);
  //
  // Count the string size including the terminating 0.
  //
  if (StringLength == 0) {
    *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0;
    FreePool (Data);
    return EFI_SUCCESS;
  }
  
  if (StringLength > SMBIOS_STRING_MAX_LENGTH) {
    //
    // Too long a string
    //
    FreePool (Data);
    return EFI_INVALID_PARAMETER;
  }
    
  Smbios = GetSmbiosProtocol();
  ASSERT (Smbios != NULL);
  
  //
  // Convert Unicode string to Ascii string which only supported by SMBIOS.
  //
  ZeroMem (AsciiData, SMBIOS_STRING_MAX_LENGTH);
  UnicodeStrToAsciiStr (Data, AsciiData);
  
  //
  // if the field at offset is already filled with some value,
  // find out the string it points to
  //
  OrigStringNumber = *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset);
  if (OrigStringNumber != 0) {
    DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Update %dth string for type[%d],offset[0x%x],handle[0x%x] to [%s]\n", 
            OrigStringNumber, StructureNode->SmbiosType, Offset, StructureNode->SmbiosHandle, AsciiData));  
    
    //
    // If original string number is not zero, just update string
    //
    Status = Smbios->UpdateString (Smbios, &StructureNode->SmbiosHandle, &OrigStringNumber, AsciiData);
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Fail to update %dth string in offset 0x%x for handle:0x%x type:0x%x\n", 
             OrigStringNumber, Offset, StructureNode->SmbiosHandle, StructureNode->SmbiosType));
      ASSERT_EFI_ERROR (Status);
      return Status;
    }
  } else {
    //
    // If the string has not been filled in SMBIOS database, remove it and add again
    // with string appended.
    //
    Status = GetSmbiosStructureSize (StructureNode->Structure, &OrigStructureSize, &CountOfStrings);
    ASSERT_EFI_ERROR (Status);
    
    if (CountOfStrings == 0) {
      NewStructureSize = OrigStructureSize + StringLength;
    } else {
      NewStructureSize = OrigStructureSize + StringLength + 1;
    }
    
    NewRecord = AllocateZeroPool (NewStructureSize);
    if (NewRecord == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    CopyMem (NewRecord, StructureNode->Structure, OrigStructureSize);
    
    //
    // Copy new string into tail of original SMBIOS record buffer.
    //
    if (CountOfStrings == 0) {
      AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 2, AsciiData);
    } else {
      AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 1, AsciiData);
    }
    DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Type(%d) offset(0x%x) StringNumber:%d\n", 
            StructureNode->SmbiosType, Offset, CountOfStrings + 1));
    //
    // Update string reference number
    //
    *(UINT8 *) ((UINT8 *) NewRecord + Offset) = (UINT8) (CountOfStrings + 1);
    SmbiosHandle = StructureNode->SmbiosHandle;
    
    //
    // Remove original SMBIOS record and add new one
    //
    Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle);
    ASSERT_EFI_ERROR (Status);
    
    //
    // Add new SMBIOS record
    //
    Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, NewRecord);
    ASSERT_EFI_ERROR (Status);
    
    StructureNode->SmbiosHandle = SmbiosHandle;
    
    FreePool (NewRecord);
  }
  
  //
  // The SMBIOS record buffer maybe re-allocated in SMBIOS database,
  // so update cached buffer pointer in DataHub structure list.
  //
  StructureNode->Structure = GetSmbiosBufferFromHandle (
                               StructureNode->SmbiosHandle, 
                               StructureNode->SmbiosType,
                               NULL
                               );
  ASSERT (StructureNode->Structure != NULL);
  
  //
  // The string update action maybe lead the record is re-allocated in SMBIOS database
  // so update cached record pointer
  //
  Status = GetSmbiosStructureSize (StructureNode->Structure, &StructureNode->StructureSize, &CountOfStrings);
  ASSERT_EFI_ERROR (Status);
  
  return EFI_SUCCESS;
}
Example #5
0
/**
  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;
}