alder_lake_bios/Insyde/InsydeModulePkg/Universal/Dash/DashDxe/PldmSmbios.c

363 lines
11 KiB
C

/** @file
Platform Level Data Model for SMBIOS Data Transfer implementation
;******************************************************************************
;* Copyright (c) 2012 - 2020, 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 "PldmSmbios.h"
/**
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 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;
//
// 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;
//
// 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++;
}
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;
}
/**
Send SBIOS Structure Table Meta Data to the management controller
@param This Pointer to EFI_PLDM_PROTOCOL
@retval EFI_SUCCESS Successful
@return Other values Unsuccessful
**/
EFI_STATUS
EFIAPI
PldmSetSmbiosStructureTableMetaData (
EFI_PLDM_PROTOCOL *This
)
{
PLDM_CONTEXT *Context;
SMBIOS_TABLE_ENTRY_POINT *SmbiosEntry;
SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosEntry64Bit;
EFI_STATUS Status;
PLDM_SMBIOS_STRUCTURE_TABLE_METADATA PldmRequest;
UINTN RecordSize;
UINT16 MaxStructureSize;
UINT16 NumberOfSmbiosStructures;
UINTN NumOfStr;
EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;
EFI_SMBIOS_PROTOCOL *SmbiosProtocol;
EFI_SMBIOS_HANDLE SmbiosHandle;
Context = PLDM_CONTEXT_FROM_THIS(This);
if (((PcdGet16 (PcdSmbiosVersion) >> 8) < 0x3) ||
(((PcdGet16 (PcdSmbiosVersion) >> 8) >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) {
Status = EfiGetSystemConfigurationTable (
&gEfiSmbiosTableGuid,
(VOID **)&SmbiosEntry
);
EFI_ERROR_RETURN (Status);
PldmRequest.MajorVersion = SmbiosEntry->MajorVersion;
PldmRequest.MinorVersion = SmbiosEntry->MinorVersion;
PldmRequest.MaxStructureSize = SmbiosEntry->MaxStructureSize;
PldmRequest.TableLength = Context->SmbiosTableLen; //SmbiosEntry->TableLength;
PldmRequest.NumberOfSmbiosStructures = SmbiosEntry->NumberOfSmbiosStructures;
PldmRequest.Crc32 = Context->SmbiosCrc32;
} else {
Status = EfiGetSystemConfigurationTable (
&gEfiSmbios3TableGuid,
(VOID **)&SmbiosEntry64Bit
);
EFI_ERROR_RETURN (Status);
RecordSize = 0;
MaxStructureSize = 0;
NumOfStr = 0;
NumberOfSmbiosStructures = 0;
Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &SmbiosProtocol);
EFI_ERROR_RETURN (Status);
//
// Calculate EPS Table Length
//
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
do {
Status = SmbiosProtocol->GetNext (SmbiosProtocol, &SmbiosHandle, NULL, &SmbiosRecord, NULL);
if (Status == EFI_SUCCESS) {
GetSmbiosStructureSize(SmbiosRecord, &RecordSize, &NumOfStr);
//
// Record NumberOfSmbiosStructures, TableLength and MaxStructureSize
//
NumberOfSmbiosStructures++;
if (RecordSize >= MaxStructureSize) {
MaxStructureSize = (UINT16) RecordSize;
}
}
} while (!EFI_ERROR(Status));
PldmRequest.MajorVersion = SmbiosEntry64Bit->MajorVersion;
PldmRequest.MinorVersion = SmbiosEntry64Bit->MinorVersion;
PldmRequest.MaxStructureSize = MaxStructureSize;
PldmRequest.TableLength = (UINT16)SmbiosEntry64Bit->TableMaximumSize; //SmbiosEntry->TableLength;
PldmRequest.NumberOfSmbiosStructures = NumberOfSmbiosStructures;
PldmRequest.Crc32 = Context->Smbios64BitCrc32;
}
return ProcessSimplePldmMessage( This,
PLDM_TYPE_SMBIOS,
PLDM_SET_SMBIOS_STRUCTURE_TABLE_METADATA,
&PldmRequest,
sizeof (PldmRequest),
NULL,
0
);
}
/**
Receive SBIOS Structure Table Meta Data from the management controller
@param This Pointer to EFI_PLDM_PROTOCOL
@param PldmResponse The received SMBIOS Structure Table Meta Data from the management controller
@retval EFI_SUCCESS Successful
@return Other values Unsuccessful
**/
EFI_STATUS
EFIAPI
PldmGetSmbiosStructureTableMetaData (
EFI_PLDM_PROTOCOL *This,
PLDM_SMBIOS_STRUCTURE_TABLE_METADATA *PldmResponse
)
{
UINTN Size;
Size = sizeof (PLDM_SMBIOS_STRUCTURE_TABLE_METADATA);
return ProcessSimplePldmMessage( This,
PLDM_TYPE_SMBIOS,
PLDM_GET_SMBIOS_STRUCTURE_TABLE_METADATA,
NULL,
0,
PldmResponse,
&Size
);
}
/**
Receive SBIOS Structure Table from the management controller
@param [in] This Pointer to EFI_PLDM_PROTOCOL
@param [out] SmbiosBuf Buffer storing the SMBIOS Sturcture Table
@param [in, out] Size Number of bytes received for SmbiosBuf
@retval EFI_SUCCESS Successful
@return Other values Unsuccessful
**/
EFI_STATUS
EFIAPI
PldmGetSmbiosStructureTable (
IN EFI_PLDM_PROTOCOL *This,
OUT UINT8 *SmbiosBuf,
IN OUT UINTN *Size
)
{
PLDM_TRANSFER_HEADER TransferHeader;
return ProcessPldmMessageWithSplitResponses ( This,
PLDM_TYPE_SMBIOS,
PLDM_GET_SMBIOS_STRUCTURE_TABLE,
&TransferHeader,
sizeof (TransferHeader),
SmbiosBuf,
Size
);
}
/**
Send SBIOS Structure Table to the management controller
@param This Pointer to EFI_PLDM_PROTOCOL
@retval EFI_SUCCESS Successful
@return Other values Unsuccessful
**/
EFI_STATUS
EFIAPI
PldmSetSmbiosStructureTable(
EFI_PLDM_PROTOCOL *This
)
{
EFI_STATUS Status;
SMBIOS_TABLE_ENTRY_POINT *SmbiosEntry;
UINT8 *SmbiosBuf;
UINTN Size;
UINTN Index;
PLDM_TRANSFER_HEADER TransferHeader;
EFI_CPU_IO2_PROTOCOL *CpuIo;
SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosEntry64Bit;
Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&CpuIo);
EFI_ERROR_RETURN (Status);
if (((PcdGet16 (PcdSmbiosVersion) >> 8) < 0x3) ||
(((PcdGet16 (PcdSmbiosVersion) >> 8) >= 0x3) && ((PcdGet32 (PcdSmbiosEntryPointProvideMethod) & BIT0) == BIT0))) {
Status = EfiGetSystemConfigurationTable (
&gEfiSmbiosTableGuid,
(VOID **)&SmbiosEntry
);
EFI_ERROR_RETURN (Status);
if ((SmbiosEntry->TableLength % 4) == 0) {
Size = SmbiosEntry->TableLength;
} else {
Size = SmbiosEntry->TableLength + (4 - (SmbiosEntry->TableLength % 4));
}
SmbiosBuf = AllocatePool (Size);
if (SmbiosBuf == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = CpuIo->Mem.Read (CpuIo, EfiCpuIoWidthUint8, SmbiosEntry->TableAddress, SmbiosEntry->TableLength, SmbiosBuf);
if(EFI_ERROR(Status)) {
FreePool(SmbiosBuf);
return Status;
}
for (Index = SmbiosEntry->TableLength; Index < Size; Index++) {
SmbiosBuf[Index] = 0;
}
} else {
Status = EfiGetSystemConfigurationTable (
&gEfiSmbios3TableGuid,
(VOID **)&SmbiosEntry64Bit
);
EFI_ERROR_RETURN (Status);
if ((SmbiosEntry64Bit->TableMaximumSize % 4) == 0) {
Size = SmbiosEntry64Bit->TableMaximumSize;
} else {
Size = SmbiosEntry64Bit->TableMaximumSize + (4 - (SmbiosEntry64Bit->TableMaximumSize % 4));
}
SmbiosBuf = AllocatePool (Size);
if (SmbiosBuf == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = CpuIo->Mem.Read (CpuIo, EfiCpuIoWidthUint8, SmbiosEntry64Bit->TableAddress, SmbiosEntry64Bit->TableMaximumSize, SmbiosBuf);
if(EFI_ERROR(Status)) {
FreePool(SmbiosBuf);
return Status;
}
for (Index = SmbiosEntry64Bit->TableMaximumSize; Index < Size; Index++) {
SmbiosBuf[Index] = 0;
}
}
Status = ProcessPldmMessageWithSplitRequests ( This,
PLDM_TYPE_SMBIOS,
PLDM_SET_SMBIOS_STRUCTURE_TABLE,
&TransferHeader,
sizeof(TransferHeader),
SmbiosBuf,
Size
);
FreePool(SmbiosBuf);
return Status;
}