369 lines
10 KiB
C
369 lines
10 KiB
C
/** @file
|
|
Multi Config DXE module implement code.
|
|
|
|
This c file contains driver entry function for DXE phase.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2013 - 2021, Insyde Software Corporation. 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 <IndustryStandard/SmBios.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/BvdtLib.h>
|
|
#include <Protocol/Smbios.h>
|
|
#include <Protocol/StringTransform.h>
|
|
|
|
|
|
STRING_TRANSFORM_PROTOCOL mStringTransform;
|
|
|
|
#define GET_ARRAY_COUNT(a) (sizeof (a)/ sizeof ((a)[0]))
|
|
|
|
CHAR16 *Supporttype[] = {
|
|
L"%BIOSVER%",
|
|
L"%BUILDDATE%",
|
|
L"%CPUTYPE%",
|
|
L"%MEMSPEED%",
|
|
L"%CPUID%"
|
|
};
|
|
|
|
VOID
|
|
ReplaceString (
|
|
IN CONST CHAR16 *InputString,
|
|
IN CHAR16 *ReplaceStrPtr,
|
|
IN UINTN ReplaceStrSize,
|
|
IN CHAR16 *DataStr,
|
|
OUT CHAR16 **OutputString
|
|
)
|
|
{
|
|
UINTN BeforeStrSize;
|
|
CHAR16 *RemainStr;
|
|
UINTN StringSize;
|
|
CHAR16 *FinalStr;
|
|
|
|
BeforeStrSize = 0;
|
|
StringSize = 0;
|
|
FinalStr = NULL;
|
|
|
|
StringSize = StrSize (InputString) - ReplaceStrSize + StrSize (DataStr);
|
|
FinalStr = (CHAR16 *)AllocateZeroPool ((StringSize + 1) * sizeof (CHAR16));
|
|
BeforeStrSize = ((UINTN)ReplaceStrPtr - (UINTN)InputString);
|
|
//
|
|
//Copy the string before matched string.
|
|
//
|
|
CopyMem (FinalStr, InputString, BeforeStrSize);
|
|
//
|
|
//Copy the string which replace the the original string.
|
|
//
|
|
StrCatS (FinalStr, StringSize + 1, DataStr);
|
|
//
|
|
//Copy the string after match String.
|
|
//
|
|
RemainStr = (CHAR16 *)((UINTN)ReplaceStrPtr + ReplaceStrSize);
|
|
StrCatS (FinalStr, StringSize + 1, RemainStr);
|
|
|
|
*OutputString = FinalStr;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetOptionalStringByIndex (
|
|
IN CHAR8 *OptionalStrStart,
|
|
IN UINT8 Index,
|
|
OUT CHAR16 **String
|
|
)
|
|
{
|
|
UINTN StrSize;
|
|
|
|
if (Index == 0) {
|
|
*String = AllocateZeroPool (sizeof (CHAR16));
|
|
if (*String == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
StrSize = 0;
|
|
do {
|
|
Index--;
|
|
OptionalStrStart += StrSize;
|
|
StrSize = AsciiStrSize (OptionalStrStart);
|
|
} while (OptionalStrStart[StrSize] != 0 && Index != 0);
|
|
|
|
if ((Index != 0) || (StrSize == 1)) {
|
|
//
|
|
// Meet the end of strings set but Index is non-zero, or
|
|
// Find an empty string
|
|
//
|
|
*String = L"Missing String";
|
|
} else {
|
|
*String = AllocatePool (StrSize * sizeof (CHAR16));
|
|
if (*String == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetSystemInfoFromSMBios (
|
|
CHAR16 **BuildDate,
|
|
CHAR16 **CpuType,
|
|
CHAR16 **MemSpee,
|
|
CHAR16 **CpuID
|
|
)
|
|
{
|
|
EFI_SMBIOS_HANDLE SmbiosHandle;
|
|
BOOLEAN Find[3];
|
|
UINT8 StrIndex;
|
|
EFI_SMBIOS_TABLE_HEADER *Record;
|
|
SMBIOS_TABLE_TYPE0 *Type0Record;
|
|
SMBIOS_TABLE_TYPE4 *Type4Record;
|
|
SMBIOS_TABLE_TYPE17 *Type17cord;
|
|
EFI_SMBIOS_PROTOCOL *Smbios;
|
|
EFI_STATUS Status;
|
|
CHAR16 *StrPtr;
|
|
|
|
ZeroMem (Find, sizeof (Find));
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSmbiosProtocolGuid,
|
|
NULL,
|
|
(VOID **)&Smbios
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
|
|
do {
|
|
Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// BIOS Release Date
|
|
//
|
|
if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) {
|
|
Type0Record = (SMBIOS_TABLE_TYPE0 *)Record;
|
|
StrIndex = Type0Record->BiosReleaseDate;
|
|
Status = GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &StrPtr);
|
|
if (Status != EFI_SUCCESS) {
|
|
continue;
|
|
}
|
|
*BuildDate = StrPtr;
|
|
Find[0] = TRUE;
|
|
}
|
|
|
|
//
|
|
// CPU Type
|
|
//
|
|
if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) {
|
|
Type4Record = (SMBIOS_TABLE_TYPE4 *)Record;
|
|
StrIndex = Type4Record->ProcessorVersion;
|
|
Status = GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &StrPtr);
|
|
if (Status != EFI_SUCCESS) {
|
|
continue;
|
|
}
|
|
*CpuType = StrPtr;
|
|
//
|
|
// CPU ID
|
|
//
|
|
StrPtr = AllocateZeroPool (0x100);
|
|
if (StrPtr == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
UnicodeSPrint (StrPtr, 0x100, L"%x", Type4Record->ProcessorId.Signature);
|
|
*CpuID = StrPtr;
|
|
Find[1] = TRUE;
|
|
}
|
|
//
|
|
// Memory Bus Speed
|
|
//
|
|
if (Record->Type == EFI_SMBIOS_TYPE_MEMORY_DEVICE) {
|
|
Type17cord = (SMBIOS_TABLE_TYPE17 *)Record;
|
|
|
|
if (Type17cord->ConfiguredMemoryClockSpeed != 0) {
|
|
StrPtr = AllocateZeroPool (0x100);
|
|
if (StrPtr == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
//
|
|
// need to have 4 digits to show 1067 MHz
|
|
//
|
|
UnicodeValueToStringS (StrPtr, sizeof (StrPtr) / sizeof (CHAR16), PREFIX_ZERO, Type17cord->ConfiguredMemoryClockSpeed, 4);
|
|
StrCatS (StrPtr, 0x100 / sizeof(CHAR16), L" MHz");
|
|
*MemSpee = StrPtr;
|
|
Find[2] = TRUE;
|
|
}
|
|
}
|
|
} while (!(Find[0] && Find[1] && Find[2]));
|
|
|
|
if (!(Find[0] && Find[1] && Find[2])) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Transform (
|
|
IN STRING_TRANSFORM_PROTOCOL *This,
|
|
IN CONST CHAR16 *String,
|
|
OUT CHAR16 **OutputString
|
|
)
|
|
{
|
|
UINTN Index;
|
|
CHAR16 *MatchStr;
|
|
UINTN StringSize;
|
|
CHAR16 Str[BVDT_MAX_STR_SIZE];
|
|
EFI_STATUS Status;
|
|
CHAR16 *DataStr;
|
|
static CHAR16 *BuildDate;
|
|
static CHAR16 *CpuType;
|
|
static CHAR16 *MemSpeed;
|
|
static CHAR16 *CpuID;
|
|
static BOOLEAN IsFirst;
|
|
|
|
MatchStr = NULL;
|
|
DataStr = NULL;
|
|
Status = EFI_SUCCESS;
|
|
//
|
|
// OutputString default is same as input srting
|
|
//
|
|
*OutputString = (CHAR16*)String;
|
|
|
|
for (Index = 0; Index < GET_ARRAY_COUNT (Supporttype); Index++) {
|
|
MatchStr = StrStr (String, Supporttype[Index]);
|
|
if (MatchStr != NULL) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (MatchStr == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (!IsFirst) {
|
|
GetSystemInfoFromSMBios (&BuildDate, &CpuType, &MemSpeed, &CpuID);
|
|
IsFirst = TRUE;
|
|
}
|
|
|
|
|
|
switch (Index) {
|
|
//
|
|
// BIOSVER
|
|
//
|
|
case 0:
|
|
StringSize = BVDT_MAX_STR_SIZE;
|
|
Status = GetBvdtInfo ((BVDT_TYPE)BvdtBiosVer, &StringSize, Str);
|
|
DataStr = Str;
|
|
if (DataStr == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
break;
|
|
//
|
|
// BUILDDATE
|
|
//
|
|
case 1:
|
|
if (BuildDate == NULL) {
|
|
Status = EFI_UNSUPPORTED;
|
|
} else {
|
|
DataStr = BuildDate;
|
|
}
|
|
break;
|
|
//
|
|
// CPUTYPE
|
|
//
|
|
case 2:
|
|
if (CpuType == NULL) {
|
|
Status = EFI_UNSUPPORTED;
|
|
} else {
|
|
DataStr = CpuType;
|
|
}
|
|
break;
|
|
//
|
|
// MEMSPEED
|
|
//
|
|
case 3:
|
|
if (MemSpeed == NULL) {
|
|
Status = EFI_UNSUPPORTED;
|
|
} else {
|
|
DataStr = MemSpeed;
|
|
}
|
|
break;
|
|
//
|
|
// PROCESSORID
|
|
//
|
|
case 4:
|
|
if (CpuID == NULL) {
|
|
Status = EFI_UNSUPPORTED;
|
|
} else {
|
|
DataStr = CpuID;
|
|
}
|
|
break;
|
|
default:
|
|
Status = EFI_UNSUPPORTED;
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DataStr = L"N/A";
|
|
}
|
|
ReplaceString (String, MatchStr, StrLen (Supporttype[Index]) * sizeof (CHAR16), DataStr, OutputString);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Entrypoint of this module.
|
|
|
|
This function is the entry point of this module. It installs Multi Config Interface Protocol
|
|
in DXE phase.
|
|
|
|
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
|
@param[in] SystemTable A pointer to the EFI System Table.
|
|
|
|
@retval EFI_SUCCESS Install protocol success.
|
|
@retval !EFI_SUCCESS Install protocol fail.
|
|
*/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
StringTransformDxeEntry (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
|
|
mStringTransform.Transform = Transform;
|
|
|
|
//
|
|
// Install protocol
|
|
//
|
|
Handle = NULL;
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Handle,
|
|
&gStringTransformProtocolGuid,
|
|
&mStringTransform,
|
|
NULL
|
|
);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|