874 lines
26 KiB
C
874 lines
26 KiB
C
/** @file
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2021, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "PnpDmi.h"
|
|
#include "PnpRuntimeDxe.h"
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/FlashRegionLib.h>
|
|
#include <Guid/DebugMask.h>
|
|
|
|
#define DMI_UPDATA_STRING_SIGNATURE SIGNATURE_32 ('$', 'D', 'M', 'I')
|
|
|
|
INT32 TotalIncreasedStringLength = 0;
|
|
|
|
|
|
/**
|
|
Find Smbios structure by Handle value
|
|
|
|
@param [in, out] Structure
|
|
@param [out] Location
|
|
@param [out] Size
|
|
|
|
@retval EFI_SUCCESS The Smbios structure is found
|
|
@retval EFI_NOT_FOUND Not found
|
|
|
|
**/
|
|
EFI_STATUS
|
|
LocateSmbiosStructure (
|
|
IN BOOLEAN IsSmbios32BitTable,
|
|
IN OUT UINT16 *Structure,
|
|
OUT SMBIOS_STRUCTURE **Location,
|
|
OUT UINTN *Size
|
|
)
|
|
{
|
|
SMBIOS_STRUCTURE *Iter;
|
|
SMBIOS_STRUCTURE *Next;
|
|
SMBIOS_STRUCTURE *End;
|
|
|
|
if (mPrivateData == NULL){
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (IsSmbios32BitTable){
|
|
if (mPrivateData->SmbiosTable == NULL || mPrivateData->SmbiosTableEntryPoint == NULL){
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
} else {
|
|
if (mPrivateData->SmbiosTable64Bit == NULL || mPrivateData->SmbiosTableEntryPoint64Bit == NULL){
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
if (IsSmbios32BitTable && (*Structure == 0) && ((*Location) != NULL) && (*(UINT32 *)(*Location) == (UINT32)SMBIOS_SIGNATURE)) {
|
|
*Structure = mPrivateData->SmbiosTable->Handle;
|
|
}
|
|
|
|
if (!IsSmbios32BitTable && (*Structure == 0) && ((*Location) != NULL) && ( AsciiStrnCmp ((CHAR8*)*Location, (CHAR8*)&SMBIOS_30_SIGNATURE, AsciiStrLen((CHAR8*)&SMBIOS_30_SIGNATURE)) == 0)) {
|
|
*Structure = mPrivateData->SmbiosTable64Bit->Handle;
|
|
}
|
|
|
|
if (IsSmbios32BitTable){
|
|
Iter = mPrivateData->SmbiosTable;
|
|
End = (SMBIOS_STRUCTURE *)((UINTN)mPrivateData->SmbiosTable + mPrivateData->SmbiosTableEntryPoint->TableLength);
|
|
} else {
|
|
Iter = mPrivateData->SmbiosTable64Bit;
|
|
End = (SMBIOS_STRUCTURE *)((UINTN)mPrivateData->SmbiosTable64Bit + mPrivateData->SmbiosTableEntryPoint64Bit->TableMaximumSize);
|
|
}
|
|
|
|
if (TotalIncreasedStringLength >= 0x00) {
|
|
End = (SMBIOS_STRUCTURE *)((UINTN)End + (UINTN)TotalIncreasedStringLength);
|
|
} else {
|
|
End = (SMBIOS_STRUCTURE *)((UINTN)End - (UINTN)(~(TotalIncreasedStringLength - 1)));
|
|
}
|
|
|
|
if (Iter == NULL){
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
while (TRUE) {
|
|
for (Next = (SMBIOS_STRUCTURE *)((UINT8 *)Iter + Iter->Length); *(UINT16 *)Next != 0; Next = (SMBIOS_STRUCTURE *)((UINTN)Next + 1));
|
|
Next = (SMBIOS_STRUCTURE *)((UINTN)Next + 2);
|
|
if (Iter >= End) {
|
|
//
|
|
// End-of-list indicator
|
|
//
|
|
*Structure = 0xffff;
|
|
return EFI_NOT_FOUND;
|
|
} else if (Iter->Handle == *Structure) {
|
|
//
|
|
// The Handle is found
|
|
//
|
|
*Structure = (UINT16)((Next < End) ? Next->Handle : 0xffff);
|
|
*Location = Iter;
|
|
*Size = (UINT16)((UINTN)Next - (UINTN)Iter);
|
|
return EFI_SUCCESS;
|
|
}
|
|
Iter = Next;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Find the string in the Smbios structure
|
|
|
|
@param [in] StringRef Index of the string to be found (1 based)
|
|
@param [in] Structure
|
|
@param [out] Location
|
|
@param [out] Size
|
|
|
|
@retval EFI_SUCCESS The string is found
|
|
@retval EFI_NOT_FOUND Not found
|
|
|
|
**/
|
|
EFI_STATUS
|
|
LocateStringOfStructure (
|
|
IN UINT8 StringRef,
|
|
IN SMBIOS_STRUCTURE *Structure,
|
|
OUT CHAR8 **Location,
|
|
OUT UINTN *Size
|
|
)
|
|
{
|
|
CHAR8 *Next;
|
|
|
|
if (StringRef == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Next = (CHAR8 *)(((UINTN)Structure) + Structure->Length);
|
|
do {
|
|
*Location = Next;
|
|
*Size = AsciiStrLen (*Location);
|
|
Next = *Location + *Size + 1;
|
|
} while ((--StringRef) != 0 && (*Next != 0));
|
|
|
|
return (StringRef == 0) ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
}
|
|
|
|
|
|
/**
|
|
PnP SMBIOS function 0x50, Get SMBIOS Information
|
|
|
|
@param [in] CommBuf
|
|
|
|
@retval EFI_SUCCESS The DMI status is in ReturnCode of GenericEntryFrame
|
|
|
|
**/
|
|
EFI_STATUS
|
|
Pnp0x50 (
|
|
IN VOID *CommBuf
|
|
)
|
|
{
|
|
UINT8 *DmiBIOSRevision;
|
|
UINT16 *NumStructures;
|
|
UINT16 *StructureSize;
|
|
UINT32 *DmiStorageBase;
|
|
UINT16 *DmiStorageSize;
|
|
|
|
RS_PNP_FUNCTION_0x50_FRAME *Frame;
|
|
UINT8 *PnpFrame;
|
|
|
|
PnpFrame = (UINT8 *)CommBuf;
|
|
PnpFrame += sizeof (IRSI_HEADER);
|
|
Frame = (RS_PNP_FUNCTION_0x50_FRAME *)PnpFrame;
|
|
|
|
if (mPrivateData == NULL || mPrivateData->SmbiosTableEntryPoint == NULL || mPrivateData->SmbiosTable == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
//
|
|
// copy to address
|
|
//
|
|
if (((PcdGet16 (PcdSmbiosVersion) >> 8) < 0x3) ||
|
|
(((PcdGet16 (PcdSmbiosVersion) >> 8) >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) {
|
|
|
|
DmiBIOSRevision = (UINT8 *)(UINTN)Frame->DmiBIOSRevisionAddress;
|
|
*DmiBIOSRevision = mPrivateData->SmbiosTableEntryPoint->SmbiosBcdRevision;
|
|
|
|
NumStructures = (UINT16 *)(UINTN)Frame->NumStructuresAddress;
|
|
*NumStructures = mPrivateData->SmbiosTableEntryPoint->NumberOfSmbiosStructures;
|
|
|
|
StructureSize = (UINT16 *)(UINTN)Frame->StructureSizeAddress;
|
|
*StructureSize = mPrivateData->SmbiosTableEntryPoint->MaxStructureSize;
|
|
|
|
DmiStorageBase = (UINT32 *)(UINTN)Frame->DmiStorageBaseAddress;
|
|
//
|
|
// In Runtime (64-bit address), it may be truncated
|
|
//
|
|
*DmiStorageBase = (UINT32)(UINTN)mPrivateData->SmbiosTable;
|
|
|
|
DmiStorageSize = (UINT16 *)(UINTN)Frame->DmiStorageSizeAddress;
|
|
*DmiStorageSize = mPrivateData->SmbiosTableEntryPoint->TableLength;
|
|
|
|
} else {
|
|
|
|
DmiBIOSRevision = (UINT8 *)(UINTN)Frame->DmiBIOSRevisionAddress;
|
|
*DmiBIOSRevision = mPrivateData->SmbiosTableEntryPoint->SmbiosBcdRevision;
|
|
|
|
NumStructures = (UINT16 *)(UINTN)Frame->NumStructuresAddress;
|
|
*NumStructures = 0;
|
|
StructureSize = (UINT16 *)(UINTN)Frame->StructureSizeAddress;
|
|
*StructureSize = 0;
|
|
|
|
DmiStorageBase = (UINT32 *)(UINTN)Frame->DmiStorageBaseAddress;
|
|
//
|
|
// In Runtime (64-bit address), it may be truncated
|
|
//
|
|
*DmiStorageBase = (UINT32)(UINTN)mPrivateData->SmbiosTable64Bit;
|
|
|
|
DmiStorageSize = (UINT16 *)(UINTN)Frame->DmiStorageSizeAddress;
|
|
*DmiStorageSize = (UINT16)mPrivateData->SmbiosTableEntryPoint64Bit->TableMaximumSize;
|
|
|
|
}
|
|
Frame->GenericEntryFrame.ReturnCode = DMI_SUCCESS;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
PnP SMBIOS function 0x51, Get SMBIOS Structure
|
|
|
|
@param [in] CommBuf
|
|
|
|
@retval EFI_SUCCESS The DMI status is in ReturnCode of GenericEntryFrame
|
|
|
|
**/
|
|
EFI_STATUS
|
|
Pnp0x51 (
|
|
IN VOID *CommBuf
|
|
)
|
|
{
|
|
UINT16 *Structure;
|
|
UINT8 *DmiStrucBuffer;
|
|
SMBIOS_STRUCTURE *Location;
|
|
UINTN Size;
|
|
RS_PNP_FUNCTION_0x51_FRAME *Frame;
|
|
UINT8 *PnpFrame;
|
|
BOOLEAN IsSmbios32BitTable;
|
|
BOOLEAN IsSmbios64BitTable;
|
|
|
|
IsSmbios32BitTable = FALSE;
|
|
IsSmbios64BitTable = FALSE;
|
|
|
|
PnpFrame = (UINT8 *)CommBuf;
|
|
PnpFrame += sizeof (IRSI_HEADER);
|
|
Frame= (RS_PNP_FUNCTION_0x51_FRAME *)PnpFrame;
|
|
|
|
Structure = (UINT16 *)(UINTN)Frame->StructureAddress;
|
|
DmiStrucBuffer = (UINT8 *)(UINTN)Frame->DmiStrucBufferAddress;
|
|
Location = (SMBIOS_STRUCTURE *)DmiStrucBuffer;
|
|
|
|
|
|
if (((PcdGet16 (PcdSmbiosVersion) >> 8) >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {
|
|
IsSmbios32BitTable = FALSE;
|
|
} else {
|
|
IsSmbios32BitTable = TRUE;
|
|
}
|
|
|
|
//
|
|
// Locate the Smbios structure by Handle value
|
|
//
|
|
if (!EFI_ERROR (LocateSmbiosStructure (IsSmbios32BitTable, Structure, &Location, &Size))) {
|
|
CopyMem (DmiStrucBuffer, (VOID *)Location, Size);
|
|
Frame->GenericEntryFrame.ReturnCode = DMI_SUCCESS;
|
|
return EFI_SUCCESS;
|
|
} else {
|
|
Frame->GenericEntryFrame.ReturnCode = DMI_INVALID_HANDLE;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
Helper function for Pnp0x52, store the SetStructure info into Variable
|
|
|
|
@param Data
|
|
@param Structure
|
|
|
|
@retval Status The return status of EfiGetVariable, EfiSetVariable
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SetDMI (
|
|
RS_FUNC_0x52_DATA_BUFFER *Data,
|
|
SMBIOS_STRUCTURE *Structure
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN VarSize;
|
|
UINTN DmiEnd;
|
|
UINT8 *Buffer;
|
|
DMI_STRING_STRUCTURE *CurrentPtr;
|
|
DMI_STRING_STRUCTURE *ChangePtr;
|
|
UINTN ChangeLength;
|
|
UINTN Index;
|
|
UINT32 Attributes;
|
|
UINTN NewVariableSize;
|
|
UINTN TotalSmbiosBufferSize;
|
|
UINT64 DmiSize;
|
|
|
|
|
|
Buffer = NULL;
|
|
CurrentPtr = NULL;
|
|
ChangePtr = NULL;
|
|
ChangeLength = 0;
|
|
|
|
//
|
|
// This value is based on SmbiosDxe driver. If the buffer allocation method is changed, this size will be different.
|
|
//
|
|
TotalSmbiosBufferSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES ((UINTN) mPrivateData->SmbiosTableEntryPoint->TableLength));
|
|
|
|
DmiSize = FdmGetNAtSize (&gH2OFlashMapRegionSmbiosUpdateGuid, 1);
|
|
VarSize = (UINTN) DmiSize;
|
|
DmiEnd = sizeof (DMI_UPDATA_STRING_SIGNATURE);
|
|
|
|
Status = EfiGetVariable (
|
|
L"PnpRuntime",
|
|
&gEfiGenericVariableGuid,
|
|
&Attributes,
|
|
&VarSize,
|
|
(VOID *)mPrivateData->DmiVariableBuf
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// check the signature of buffer
|
|
//
|
|
if (*(UINT32 *)mPrivateData->DmiVariableBuf != DMI_UPDATA_STRING_SIGNATURE) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
} else if (Status == EFI_NOT_FOUND) {
|
|
//
|
|
// the variable doesn't exist, create it
|
|
//
|
|
*(UINT32 *)mPrivateData->DmiVariableBuf = DMI_UPDATA_STRING_SIGNATURE;
|
|
VarSize = (UINTN) DmiSize;
|
|
Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
|
|
Status = EfiSetVariable (
|
|
L"PnpRuntime",
|
|
&gEfiGenericVariableGuid,
|
|
Attributes,
|
|
VarSize,
|
|
(VOID *)mPrivateData->DmiVariableBuf
|
|
);
|
|
} else {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// save the SetStructure info to the Variable
|
|
//
|
|
Buffer = mPrivateData->DmiVariableBuf + sizeof (DMI_UPDATA_STRING_SIGNATURE);
|
|
|
|
while (DmiEnd < VarSize) {
|
|
CurrentPtr = (DMI_STRING_STRUCTURE *)Buffer;
|
|
|
|
if (CurrentPtr->Type == 0xFF) {
|
|
//
|
|
// The space is free, we could use it, so break.
|
|
//
|
|
break;
|
|
}
|
|
|
|
if (CurrentPtr->Type == Structure->Type &&
|
|
CurrentPtr->Offset == Data->FieldOffset &&
|
|
CurrentPtr->Valid == 0xFF) {
|
|
//
|
|
// update directly, don't set invalid bits
|
|
//
|
|
ChangePtr = CurrentPtr;
|
|
}
|
|
|
|
//
|
|
// Try to find next.
|
|
//
|
|
DmiEnd = DmiEnd + CurrentPtr->Length;
|
|
Buffer = Buffer + CurrentPtr->Length;
|
|
}
|
|
|
|
if (ChangePtr) {
|
|
//
|
|
// the same structure is already in Variable,
|
|
// copy the rest of Variable data to TempStoreArea
|
|
//
|
|
Buffer = (UINT8 *)((UINTN)ChangePtr + (UINTN)ChangePtr->Length);
|
|
ChangeLength = (UINTN)CurrentPtr - (UINTN)Buffer;
|
|
if (ChangeLength > TotalSmbiosBufferSize) {
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
CopyMem (mPrivateData->TempStoreArea, Buffer, ChangeLength);
|
|
Buffer = (UINT8 *)ChangePtr;
|
|
SetMem (Buffer, (UINTN)CurrentPtr - (UINTN)Buffer, 0xFF);
|
|
CurrentPtr = ChangePtr;
|
|
}
|
|
|
|
if (CurrentPtr == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// The size of mPrivateData->DmiVariableBuf is defined as PcdFlashNvStorageDmiSize.
|
|
//
|
|
NewVariableSize = (UINTN)CurrentPtr - (UINTN)mPrivateData->DmiVariableBuf +
|
|
ChangeLength + sizeof (DMI_STRING_STRUCTURE) + (UINTN)Data->DataLength;
|
|
if (NewVariableSize > DmiSize ) {
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
//
|
|
// update CurrentPtr: start of free space
|
|
//
|
|
CurrentPtr->Type = Structure->Type;
|
|
CurrentPtr->Offset = Data->FieldOffset;
|
|
CurrentPtr->Valid = 0xFF;
|
|
|
|
switch (Data->Command) {
|
|
|
|
case DMI_STRING_CHANGE:
|
|
CurrentPtr->Length = Data->DataLength + (sizeof (DMI_STRING_STRUCTURE) - sizeof (UINT8) - 1);
|
|
for (Index = 0; (Index + 1) < Data->DataLength; Index++) {
|
|
CurrentPtr->String[Index] = Data->StructureData[Index];
|
|
}
|
|
break;
|
|
|
|
default:
|
|
CurrentPtr->Length = Data->DataLength + (sizeof (DMI_STRING_STRUCTURE) - sizeof (UINT8));
|
|
for (Index = 0; Index < Data->DataLength; Index++) {
|
|
CurrentPtr->String[Index] = Data->StructureData[Index];
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
if (ChangePtr) {
|
|
//
|
|
// the same structure is already in Variable,
|
|
// copy the data in TempStoreArea back to variable
|
|
//
|
|
ChangePtr = (DMI_STRING_STRUCTURE *)((UINTN)CurrentPtr + (UINTN)CurrentPtr->Length);
|
|
CopyMem (ChangePtr, mPrivateData->TempStoreArea, ChangeLength);
|
|
}
|
|
|
|
VarSize = (UINTN) DmiSize;
|
|
Status = EfiSetVariable (
|
|
L"PnpRuntime",
|
|
&gEfiGenericVariableGuid,
|
|
Attributes,
|
|
VarSize,
|
|
(VOID *)mPrivateData->DmiVariableBuf
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Helper function for Pnp0x52,
|
|
process command DMI_BYTE_CHANGE, DMI_WORD_CHANGE, and DMI_DWORD_CHANGE
|
|
|
|
@param Data
|
|
@param Structure
|
|
|
|
@retval DMI_READ_ONLY Can not set the data in the structure
|
|
|
|
**/
|
|
INT16
|
|
Pnp0x52ChangeFixedLength (
|
|
RS_FUNC_0x52_DATA_BUFFER *Data,
|
|
SMBIOS_STRUCTURE *Structure
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *ByteTmpPtr;
|
|
UINT16 *WordTmpPtr;
|
|
UINT32 *DWordTmpPtr;
|
|
UINT8 ByteTemp;
|
|
UINT16 WordTemp;
|
|
UINT32 DWordTemp;
|
|
UINTN Index;
|
|
|
|
ByteTmpPtr = NULL;
|
|
WordTmpPtr = NULL;
|
|
DWordTmpPtr = NULL;
|
|
ByteTemp = 0;
|
|
WordTemp = 0;
|
|
DWordTemp = 0;
|
|
|
|
if (mPrivateData->UpdatableStringCount != 0) {
|
|
//
|
|
// check if the data in the structure can be changed
|
|
//
|
|
for (Index = 0; Index < mPrivateData->UpdatableStringCount; Index++) {
|
|
if ((Structure->Type == mPrivateData->UpdatableStrings[Index].Type)
|
|
&&(Data->FieldOffset == mPrivateData->UpdatableStrings[Index].FixedOffset)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Index == mPrivateData->UpdatableStringCount) {
|
|
return DMI_READ_ONLY;
|
|
}
|
|
}
|
|
|
|
switch (Data->Command) {
|
|
|
|
case DMI_BYTE_CHANGE:
|
|
ByteTmpPtr = (UINT8 *) ((UINTN)Structure + Data->FieldOffset);
|
|
if (ByteTmpPtr == NULL) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
ByteTemp = *ByteTmpPtr;
|
|
ByteTemp = ByteTemp & ((UINT8)(Data->ChangeMask));
|
|
ByteTemp = ByteTemp | ((UINT8)((Data->ChangeValue) & ~(Data->ChangeMask)));
|
|
|
|
Data->DataLength = sizeof (UINT8);
|
|
CopyMem((VOID *)&Data->StructureData, (VOID *)&ByteTemp, Data->DataLength);
|
|
break;
|
|
|
|
case DMI_WORD_CHANGE:
|
|
WordTmpPtr = (UINT16 *) ((UINTN)Structure + Data->FieldOffset);
|
|
if (WordTmpPtr == NULL) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
WordTemp = *WordTmpPtr;
|
|
WordTemp = WordTemp & ((UINT16)(Data->ChangeMask));
|
|
WordTemp = WordTemp | ((UINT16)((Data->ChangeValue) & ~(Data->ChangeMask)));
|
|
|
|
Data->DataLength = sizeof (UINT16);
|
|
CopyMem((VOID *)&Data->StructureData, (VOID *)&WordTemp, Data->DataLength);
|
|
break;
|
|
|
|
case DMI_DWORD_CHANGE:
|
|
DWordTmpPtr = (UINT32 *) ((UINTN)Structure + Data->FieldOffset);
|
|
if (DWordTmpPtr == NULL) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
DWordTemp = *DWordTmpPtr;
|
|
DWordTemp = DWordTemp & ((UINT32)(Data->ChangeMask));
|
|
DWordTemp = DWordTemp | ((UINT32)((Data->ChangeValue) & ~(Data->ChangeMask)));
|
|
Data->DataLength = sizeof (UINT32);
|
|
CopyMem((VOID *)&Data->StructureData, (VOID *)&DWordTemp, Data->DataLength);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// store the SetStructure info to the variable
|
|
//
|
|
Status = SetDMI (Data, Structure);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return DMI_READ_ONLY;
|
|
}
|
|
|
|
switch (Data->Command) {
|
|
|
|
case DMI_BYTE_CHANGE:
|
|
if (ByteTmpPtr == NULL) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
CopyMem (ByteTmpPtr, &ByteTemp, sizeof (UINT8));
|
|
break;
|
|
|
|
case DMI_WORD_CHANGE:
|
|
if (WordTmpPtr == NULL) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
CopyMem (WordTmpPtr, &WordTemp, sizeof (UINT16));
|
|
break;
|
|
|
|
case DMI_DWORD_CHANGE:
|
|
if (DWordTmpPtr == NULL) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
CopyMem (DWordTmpPtr, &DWordTemp, sizeof(UINT32));
|
|
break;
|
|
}
|
|
|
|
return DMI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Helper function for Pnp0x52, process command DMI_STRING_CHANGE
|
|
|
|
@param Data
|
|
@param Structure
|
|
|
|
@retval DMI_BAD_PARAMETER The length of data is invalid
|
|
or can not locate the string in the structure
|
|
@retval DMI_READ_ONLY Can not set the data in the structure
|
|
|
|
**/
|
|
INT16
|
|
Pnp0x52ChangeString (
|
|
RS_FUNC_0x52_DATA_BUFFER *Data,
|
|
SMBIOS_STRUCTURE *Structure
|
|
)
|
|
{
|
|
CHAR8 *StructureString;
|
|
CHAR8 *TempstructureString;
|
|
UINTN StructureStringSize;
|
|
UINTN TempstructureStringSize;
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
UINTN CurrentTableSize;
|
|
UINTN TotalSmbiosBufferSize;
|
|
UINTN NewTableSize;
|
|
|
|
|
|
TempstructureString = NULL;
|
|
TempstructureStringSize = 0;
|
|
|
|
if (Data->DataLength > 0xff || Data->DataLength <= 1) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Find string within the SMBIOS structure
|
|
//
|
|
if (Structure->Type == 0x0b || Structure->Type == 0x0c) {
|
|
if (EFI_ERROR (LocateStringOfStructure (
|
|
(UINT8)Data->FieldOffset,
|
|
Structure,
|
|
&StructureString,
|
|
&StructureStringSize
|
|
))) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
Data->FieldOffset += 4;
|
|
} else {
|
|
if (EFI_ERROR (LocateStringOfStructure (
|
|
((UINT8*)Structure)[Data->FieldOffset],
|
|
Structure,
|
|
&StructureString,
|
|
&StructureStringSize
|
|
))) {
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
}
|
|
|
|
if (mPrivateData->UpdatableStringCount != 0) {
|
|
//
|
|
// check if the data in the structure can be changed
|
|
//
|
|
for (Index = 0; Index < mPrivateData->UpdatableStringCount; Index++) {
|
|
if ((Structure->Type == mPrivateData->UpdatableStrings[Index].Type) &&
|
|
(Data->FieldOffset == mPrivateData->UpdatableStrings[Index].FixedOffset)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Index == mPrivateData->UpdatableStringCount) {
|
|
return DMI_READ_ONLY;
|
|
}
|
|
}
|
|
|
|
//
|
|
// store the SetStructure info to the variable
|
|
//
|
|
Status = SetDMI (Data, Structure);
|
|
if (EFI_ERROR (Status)) {
|
|
return DMI_READ_ONLY;
|
|
}
|
|
|
|
//
|
|
// This value is based on SmbiosDxe driver. If the buffer allocation method is changed, this size will be different.
|
|
//
|
|
TotalSmbiosBufferSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES ((UINTN) mPrivateData->SmbiosTableEntryPoint->TableLength));
|
|
TempstructureString = StructureString + StructureStringSize + 1;
|
|
if (TotalIncreasedStringLength >= 0x00) {
|
|
CurrentTableSize = (UINTN)(mPrivateData->SmbiosTableEntryPoint->TableLength + (UINT16)TotalIncreasedStringLength);
|
|
TempstructureStringSize = (UINTN)(mPrivateData->SmbiosTableEntryPoint->TableLength + (UINT16)TotalIncreasedStringLength) - (UINTN)(TempstructureString - (UINTN)mPrivateData->SmbiosTable);
|
|
} else {
|
|
CurrentTableSize = (UINTN)(mPrivateData->SmbiosTableEntryPoint->TableLength - (UINT16)(~(TotalIncreasedStringLength - 1)));
|
|
TempstructureStringSize = (UINTN)(mPrivateData->SmbiosTableEntryPoint->TableLength - (UINT16)(~(TotalIncreasedStringLength - 1))) - (UINTN)(TempstructureString - (UINTN)mPrivateData->SmbiosTable);
|
|
}
|
|
|
|
//
|
|
// If new SMBIOS data is over than the buffer, nothing will change on SMBIOS data,
|
|
// but new string will be written to the Dmi region.
|
|
// Data->DataLength : new string length, including '0'
|
|
// structureStringSize : original string length
|
|
//
|
|
if ((UINTN)Data->DataLength > (StructureStringSize + 1)) {
|
|
NewTableSize = CurrentTableSize + (UINTN)Data->DataLength - (StructureStringSize + 1);
|
|
if (NewTableSize > TotalSmbiosBufferSize) {
|
|
return DMI_NO_CHANGE;
|
|
}
|
|
}
|
|
|
|
CopyMem (mPrivateData->TempStoreArea, TempstructureString, TempstructureStringSize);
|
|
CopyMem (StructureString, Data->StructureData, Data->DataLength);
|
|
TempstructureString = StructureString + Data->DataLength;
|
|
CopyMem (TempstructureString, mPrivateData->TempStoreArea, TempstructureStringSize);
|
|
TotalIncreasedStringLength = TotalIncreasedStringLength + (UINT32)Data->DataLength - (UINT32)(StructureStringSize + 1);
|
|
|
|
return DMI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Helper function for Pnp0x52, process command DMI_BLOCK_CHANGE
|
|
|
|
@param Data
|
|
@param Structure
|
|
|
|
@retval DMI_READ_ONLY The structure is not Type1,
|
|
the block to be set is not at offset 8
|
|
|
|
**/
|
|
INT16
|
|
Pnp0x52ChangeBlock (
|
|
RS_FUNC_0x52_DATA_BUFFER *Data,
|
|
SMBIOS_STRUCTURE *Structure
|
|
)
|
|
{
|
|
UINT8 *TmpPtr;
|
|
UINT8 *DataPtr;
|
|
UINTN CopyLength;
|
|
EFI_STATUS Status;
|
|
|
|
|
|
TmpPtr = (UINT8 *) ((UINTN)Structure + Data->FieldOffset);
|
|
DataPtr = (UINT8 *)Data->StructureData;
|
|
CopyLength = (UINTN)Data->DataLength;
|
|
|
|
if ((Structure->Type != 1) || (Data->FieldOffset != 8)) {
|
|
return DMI_READ_ONLY;
|
|
}
|
|
|
|
if (CopyLength != sizeof (EFI_GUID)){
|
|
return DMI_BAD_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// store the SetStructure info to the variable
|
|
//
|
|
Status = SetDMI (Data, Structure);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return DMI_READ_ONLY;
|
|
}
|
|
CopyMem (TmpPtr, Data->StructureData, Data->DataLength);
|
|
return DMI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
PnP SMBIOS function 0x52, Set SMBIOS Structure
|
|
|
|
@param [in] CommBuf
|
|
|
|
@retval EFI_SUCCESS The DMI status is in ReturnCode of GenericEntryFrame
|
|
|
|
**/
|
|
EFI_STATUS
|
|
Pnp0x52 (
|
|
IN VOID *CommBuf
|
|
)
|
|
{
|
|
RS_FUNC_0x52_DATA_BUFFER *Data;
|
|
SMBIOS_STRUCTURE *StructureLocation;
|
|
SMBIOS_STRUCTURE *StructureLocation64Bit;
|
|
UINT16 StructureHandle;
|
|
UINTN StructureSize;
|
|
UINTN StructureSize64Bit;
|
|
INT16 ReturnStatus;
|
|
INT16 ReturnStatus64Bit;
|
|
|
|
RS_PNP_FUNCTION_0x52_FRAME *Frame;
|
|
UINT8 *PnpFrame;
|
|
EFI_STATUS Status;
|
|
EFI_STATUS Status64Bit;
|
|
BOOLEAN IsSmbios32BitTable;
|
|
BOOLEAN IsSmbios64BitTable;
|
|
|
|
ReturnStatus = 0;
|
|
ReturnStatus64Bit = 0;
|
|
PnpFrame = (UINT8 *)CommBuf;
|
|
PnpFrame += sizeof (IRSI_HEADER);
|
|
Frame= (RS_PNP_FUNCTION_0x52_FRAME *)PnpFrame;
|
|
|
|
IsSmbios32BitTable = FALSE;
|
|
IsSmbios64BitTable = FALSE;
|
|
|
|
Status = EFI_SUCCESS;
|
|
Status64Bit = EFI_SUCCESS;
|
|
|
|
Data = (RS_FUNC_0x52_DATA_BUFFER *)(UINTN)(Frame->DmiDataBufferAddress);
|
|
StructureHandle = Data->StructureHeader.Handle;
|
|
StructureLocation = NULL;
|
|
StructureLocation64Bit = NULL;
|
|
|
|
if (((PcdGet16 (PcdSmbiosVersion) >> 8) < 0x3) ||
|
|
(((PcdGet16 (PcdSmbiosVersion) >> 8) >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))){
|
|
IsSmbios32BitTable = TRUE;
|
|
}
|
|
|
|
if (((PcdGet16 (PcdSmbiosVersion) >> 8) >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT1) == BIT1)) {
|
|
IsSmbios64BitTable = TRUE;
|
|
}
|
|
|
|
if (IsSmbios32BitTable){
|
|
Status = LocateSmbiosStructure (IsSmbios32BitTable, &StructureHandle, &StructureLocation, &StructureSize);
|
|
}
|
|
|
|
if (IsSmbios64BitTable){
|
|
Status64Bit = LocateSmbiosStructure (FALSE, &StructureHandle, &StructureLocation64Bit, &StructureSize64Bit);
|
|
}
|
|
|
|
Status = EFI_ERROR (Status64Bit) ? Status64Bit : Status;
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
switch (Data->Command) {
|
|
|
|
case DMI_BYTE_CHANGE:
|
|
case DMI_WORD_CHANGE:
|
|
case DMI_DWORD_CHANGE:
|
|
if (IsSmbios32BitTable){
|
|
ReturnStatus = Pnp0x52ChangeFixedLength (Data, StructureLocation);
|
|
}
|
|
|
|
if (IsSmbios64BitTable){
|
|
ReturnStatus64Bit = Pnp0x52ChangeFixedLength (Data, StructureLocation64Bit);
|
|
}
|
|
|
|
ReturnStatus = EFI_ERROR (ReturnStatus64Bit) ? ReturnStatus64Bit : ReturnStatus;
|
|
break;
|
|
|
|
case DMI_STRING_CHANGE:
|
|
if (IsSmbios32BitTable){
|
|
ReturnStatus = Pnp0x52ChangeString (Data, StructureLocation);
|
|
}
|
|
|
|
if (IsSmbios64BitTable){
|
|
ReturnStatus64Bit = Pnp0x52ChangeString (Data, StructureLocation64Bit);
|
|
}
|
|
ReturnStatus = EFI_ERROR (ReturnStatus64Bit) ? ReturnStatus64Bit : ReturnStatus;
|
|
break;
|
|
|
|
case DMI_BLOCK_CHANGE:
|
|
if (IsSmbios32BitTable){
|
|
ReturnStatus = Pnp0x52ChangeBlock (Data, StructureLocation);
|
|
}
|
|
|
|
if (IsSmbios64BitTable){
|
|
ReturnStatus64Bit = Pnp0x52ChangeBlock (Data, StructureLocation64Bit);
|
|
}
|
|
|
|
ReturnStatus = EFI_ERROR (ReturnStatus64Bit) ? ReturnStatus64Bit : ReturnStatus;
|
|
break;
|
|
|
|
default:
|
|
ReturnStatus = DMI_BAD_PARAMETER;
|
|
}
|
|
|
|
} else {
|
|
ReturnStatus = DMI_BAD_PARAMETER;
|
|
}
|
|
|
|
Frame->GenericEntryFrame.ReturnCode = ReturnStatus;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|