363 lines
11 KiB
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;
|
|
|
|
}
|
|
|