408 lines
12 KiB
C
408 lines
12 KiB
C
/** @file
|
|
|
|
;******************************************************************************
|
|
;* 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 <Library/FlashRegionLib.h>
|
|
#include "PnpRuntimeDxe.h"
|
|
|
|
#define FixedPcdGetPtrSize(TokenName) (UINTN)_PCD_PATCHABLE_##TokenName##_SIZE
|
|
|
|
//
|
|
// global varibles
|
|
//
|
|
PNP_RUNTIME_PRIVATE_DATA *mPrivateData;
|
|
EFI_EVENT mSmbiosGetTableEvent;
|
|
EFI_EVENT mVirtualAddressChangeEvent;
|
|
BOOLEAN mIsOemGPNVMap = FALSE;
|
|
|
|
//
|
|
// PnpRuntime services
|
|
//
|
|
PNP_REDIRECTED_ENTRY_POINT mPnpDmiFunctions[] = {
|
|
Pnp0x50,
|
|
Pnp0x51,
|
|
Pnp0x52
|
|
//
|
|
// new services to be added
|
|
//
|
|
};
|
|
|
|
|
|
/**
|
|
ExitBootService callback function
|
|
|
|
@param [in] Event Registered callback event
|
|
@param [in] Context
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
SmbiosGetTableEntryPointCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
VOID *TempAddress;
|
|
VOID *TempAddress64Bit;
|
|
UINTN EntryLength;
|
|
UINTN EntryLength64Bit;
|
|
UINTN VarSize;
|
|
BOOLEAN IsSmbios32BitTable;
|
|
BOOLEAN IsSmbios64BitTable;
|
|
|
|
IsSmbios32BitTable = FALSE;
|
|
IsSmbios64BitTable = FALSE;
|
|
|
|
if (mPrivateData == NULL) {
|
|
return;
|
|
}
|
|
gBS->CloseEvent (Event);
|
|
|
|
//
|
|
// Check 32Bit, 64 Bit Smbios Table support
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// For 32 Bit Smbios Table
|
|
//
|
|
if (IsSmbios32BitTable && mPrivateData->SMBIOSTableEntryAddress == 0){
|
|
//
|
|
// find physical address of Smbios Table
|
|
//
|
|
EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **)&TempAddress);
|
|
mPrivateData->SMBIOSTableEntryAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)TempAddress;
|
|
mPrivateData->SmbiosTableEntryPoint = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)mPrivateData->SMBIOSTableEntryAddress;
|
|
if (mPrivateData->SmbiosTableEntryPoint == NULL) {
|
|
return;
|
|
}
|
|
mPrivateData->SmbiosTable = (SMBIOS_STRUCTURE *)(UINTN)(mPrivateData->SmbiosTableEntryPoint->TableAddress);
|
|
|
|
EntryLength = mPrivateData->SmbiosTableEntryPoint->EntryPointLength;
|
|
//
|
|
// temp buffer for Pnp0x52ChangeString()
|
|
//
|
|
VarSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES ((UINTN) mPrivateData->SmbiosTableEntryPoint->TableLength));
|
|
mPrivateData->TempStoreArea = AllocateRuntimePool(VarSize);
|
|
if (mPrivateData->TempStoreArea == NULL) {
|
|
return;
|
|
}
|
|
gBS->SetMem (mPrivateData->TempStoreArea, VarSize, 0x00);
|
|
|
|
//
|
|
// for Runtime Access Smbios Table
|
|
//
|
|
VarSize += EntryLength;
|
|
mPrivateData->SmbiosStoreArea = AllocateRuntimePool (VarSize);
|
|
if (mPrivateData->SmbiosStoreArea == NULL) {
|
|
return;
|
|
}
|
|
gBS->SetMem (mPrivateData->SmbiosStoreArea, VarSize, 0x00);
|
|
|
|
//
|
|
// copy to runtime memory
|
|
//
|
|
CopyMem (
|
|
mPrivateData->SmbiosStoreArea,
|
|
mPrivateData->SmbiosTableEntryPoint,
|
|
EntryLength
|
|
);
|
|
|
|
CopyMem (
|
|
(UINT8 *)((UINTN)mPrivateData->SmbiosStoreArea + EntryLength),
|
|
mPrivateData->SmbiosTable,
|
|
mPrivateData->SmbiosTableEntryPoint->TableLength
|
|
);
|
|
|
|
//
|
|
// change pointer
|
|
//
|
|
mPrivateData->SmbiosTableEntryPoint = (SMBIOS_TABLE_ENTRY_POINT *)mPrivateData->SmbiosStoreArea;
|
|
mPrivateData->SmbiosTable = (SMBIOS_STRUCTURE *)((UINTN)mPrivateData->SmbiosStoreArea + EntryLength);
|
|
|
|
}
|
|
|
|
//
|
|
// For 64 Bit Smbios Table
|
|
//
|
|
if ( IsSmbios64BitTable || mPrivateData->SMBIOSTableEntryAddress64Bit == 0){
|
|
|
|
EfiGetSystemConfigurationTable (&gEfiSmbios3TableGuid, (VOID **)&TempAddress64Bit);
|
|
mPrivateData->SMBIOSTableEntryAddress64Bit = (EFI_PHYSICAL_ADDRESS)(UINTN)TempAddress64Bit;
|
|
mPrivateData->SmbiosTableEntryPoint64Bit = (SMBIOS_TABLE_3_0_ENTRY_POINT *)(UINTN)mPrivateData->SMBIOSTableEntryAddress64Bit;
|
|
|
|
if (mPrivateData->SmbiosTableEntryPoint64Bit == NULL) {
|
|
return;
|
|
}
|
|
mPrivateData->SmbiosTable64Bit = (SMBIOS_STRUCTURE *)(UINTN)(mPrivateData->SmbiosTableEntryPoint64Bit->TableAddress);
|
|
EntryLength64Bit = sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT);
|
|
|
|
//
|
|
// for Runtime Access 64 Bit Smbios Table
|
|
//
|
|
VarSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES ((UINTN) mPrivateData->SmbiosTableEntryPoint64Bit->TableMaximumSize));
|
|
VarSize += EntryLength64Bit;
|
|
mPrivateData->SmbiosStoreArea64Bit = AllocateRuntimePool (VarSize);
|
|
if (mPrivateData->SmbiosStoreArea64Bit == NULL) {
|
|
return;
|
|
}
|
|
gBS->SetMem (mPrivateData->SmbiosStoreArea64Bit, VarSize, 0x00);
|
|
|
|
//
|
|
// copy to runtime memory
|
|
//
|
|
CopyMem (
|
|
mPrivateData->SmbiosStoreArea64Bit,
|
|
mPrivateData->SmbiosTableEntryPoint64Bit,
|
|
EntryLength64Bit
|
|
);
|
|
|
|
CopyMem (
|
|
(UINT8 *)((UINTN)mPrivateData->SmbiosStoreArea64Bit + EntryLength64Bit),
|
|
mPrivateData->SmbiosTable64Bit,
|
|
mPrivateData->SmbiosTableEntryPoint64Bit->TableMaximumSize
|
|
);
|
|
|
|
//
|
|
// change pointer
|
|
//
|
|
mPrivateData->SmbiosTableEntryPoint64Bit = (SMBIOS_TABLE_3_0_ENTRY_POINT *)mPrivateData->SmbiosStoreArea64Bit;
|
|
mPrivateData->SmbiosTable64Bit = (SMBIOS_STRUCTURE *)((UINTN)mPrivateData->SmbiosStoreArea64Bit + EntryLength64Bit);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
VirtualAddressChange callback function
|
|
|
|
@param [in] Event Registered callback event
|
|
@param [in] Context
|
|
|
|
@retval None.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
VirtualAddressChangeCallBack (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (mPrivateData == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (mPrivateData->SmbiosTableEntryPoint != NULL) {
|
|
Status = EfiConvertPointer (0, (VOID **)&mPrivateData->SmbiosTableEntryPoint);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (mPrivateData->SmbiosTableEntryPoint64Bit != NULL) {
|
|
Status = EfiConvertPointer (0, (VOID **)&mPrivateData->SmbiosTableEntryPoint64Bit);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (mPrivateData->SmbiosTable != NULL) {
|
|
Status = EfiConvertPointer (0, (VOID **)&mPrivateData->SmbiosTable);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (mPrivateData->SmbiosTable64Bit != NULL) {
|
|
Status = EfiConvertPointer (0, (VOID **)&mPrivateData->SmbiosTable64Bit);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (mPrivateData->GPNVHeader != NULL) {
|
|
EfiConvertPointer (0, (VOID **)&mPrivateData->GPNVHeader);
|
|
}
|
|
|
|
if (mPrivateData->UpdatableStrings != NULL) {
|
|
EfiConvertPointer (0, (VOID **)&mPrivateData->UpdatableStrings);
|
|
}
|
|
|
|
if (mPrivateData->DmiVariableBuf != NULL) {
|
|
EfiConvertPointer (0, (VOID **)&mPrivateData->DmiVariableBuf);
|
|
}
|
|
|
|
if (mPrivateData->SmbiosStoreArea != NULL) {
|
|
Status = EfiConvertPointer (0, (VOID **)&mPrivateData->SmbiosStoreArea);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (mPrivateData->SmbiosStoreArea64Bit != NULL) {
|
|
Status = EfiConvertPointer (0, (VOID **)&mPrivateData->SmbiosStoreArea64Bit);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (mPrivateData->TempStoreArea != NULL) {
|
|
EfiConvertPointer (0, (VOID **)&mPrivateData->TempStoreArea);
|
|
}
|
|
|
|
Status = EfiConvertPointer (0, (VOID **)&mPrivateData);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
Driver entry point
|
|
|
|
@param [in] ImageHandle The image handle
|
|
@param [in] SystemTable
|
|
|
|
@retval EFI_SUCCESS Command completed successfully
|
|
@return Other value Runtime memory allocation failed
|
|
or IrsiRegisterFunction failed
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PnpRuntimeDxeInit (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DMI_UPDATABLE_STRING *TempStringTable;
|
|
UINTN VarSize;
|
|
UINT32 Index;
|
|
UINT32 Command;
|
|
BOOLEAN NeedFreePnpTable;
|
|
OEM_GPNV_MAP *OemGPNVMap = NULL;
|
|
|
|
//
|
|
// initialize global variable
|
|
//
|
|
mPrivateData = AllocateRuntimePool(sizeof (PNP_RUNTIME_PRIVATE_DATA));
|
|
if (mPrivateData == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
TempStringTable = NULL;
|
|
|
|
mPrivateData->UpdatableStringCount = 0;
|
|
mPrivateData->UpdatableStrings = NULL;
|
|
mPrivateData->OemGPNVHandleCount = 0;
|
|
mPrivateData->SMBIOSTableEntryAddress = 0;
|
|
mPrivateData->SMBIOSTableEntryAddress64Bit = 0;
|
|
mPrivateData->SmbiosTableEntryPoint = NULL;
|
|
mPrivateData->SmbiosTableEntryPoint64Bit = NULL;
|
|
mPrivateData->SmbiosTable = NULL;
|
|
mPrivateData->SmbiosTable64Bit = NULL;
|
|
|
|
|
|
VarSize = (UINTN) FdmGetNAtSize(&gH2OFlashMapRegionSmbiosUpdateGuid, 1);
|
|
mPrivateData->DmiVariableBuf = AllocateRuntimePool(VarSize);
|
|
if (mPrivateData->DmiVariableBuf == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
gBS->SetMem (mPrivateData->DmiVariableBuf, VarSize, 0xFF);
|
|
|
|
|
|
//
|
|
// OemServices (Dxe)
|
|
|
|
NeedFreePnpTable = TRUE;
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcDxeInstallPnpStringTable \n"));
|
|
Status = OemSvcDxeInstallPnpStringTable (
|
|
&mPrivateData->UpdatableStringCount,
|
|
&TempStringTable
|
|
);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcDxeInstallPnpStringTable Status: %r\n", Status));
|
|
if (Status == EFI_UNSUPPORTED) {
|
|
NeedFreePnpTable = FALSE;
|
|
TempStringTable = PcdGetPtr(PcdSmbiosUpdatableStringTable);
|
|
mPrivateData->UpdatableStringCount = FixedPcdGetPtrSize(PcdSmbiosUpdatableStringTable) / sizeof(DMI_UPDATABLE_STRING);
|
|
}
|
|
|
|
if ((TempStringTable != NULL) && (mPrivateData->UpdatableStringCount != 0)) {
|
|
mPrivateData->UpdatableStrings = AllocateRuntimePool (((mPrivateData->UpdatableStringCount) * sizeof (DMI_UPDATABLE_STRING)));
|
|
if (mPrivateData->UpdatableStrings != NULL) {
|
|
gBS->CopyMem (
|
|
mPrivateData->UpdatableStrings,
|
|
TempStringTable,
|
|
((mPrivateData->UpdatableStringCount) * sizeof (DMI_UPDATABLE_STRING))
|
|
);
|
|
}
|
|
|
|
if (NeedFreePnpTable) {
|
|
FreePool(TempStringTable);
|
|
}
|
|
}
|
|
|
|
//
|
|
// OemServices (Dxe)
|
|
//
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcDxeInstallPnpGpnvTable \n"));
|
|
Status = OemSvcDxeInstallPnpGpnvTable (&mPrivateData->OemGPNVHandleCount, &OemGPNVMap);
|
|
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcDxeInstallPnpGpnvTable Status: %r\n", Status));
|
|
if (Status == EFI_MEDIA_CHANGED && OemGPNVMap != NULL) {
|
|
mIsOemGPNVMap = TRUE;
|
|
} else {
|
|
mIsOemGPNVMap = FALSE;
|
|
}
|
|
|
|
//
|
|
// This event will be triggered after SMBIOS table entry point is ready.
|
|
// So, we can get the address of entry point and save it.
|
|
//
|
|
Status = EfiCreateEventReadyToBootEx (
|
|
TPL_CALLBACK - 1,
|
|
SmbiosGetTableEntryPointCallback,
|
|
NULL,
|
|
&mSmbiosGetTableEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
VirtualAddressChangeCallBack,
|
|
NULL,
|
|
&gEfiEventVirtualAddressChangeGuid,
|
|
&mVirtualAddressChangeEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Register PnpRuntime services using IrsiLib
|
|
//
|
|
Command = PNP_0X50_SERVICES;
|
|
for (Index = 0; Index < (sizeof (mPnpDmiFunctions) / sizeof (PNP_REDIRECTED_ENTRY_POINT)); Index++) {
|
|
Status = IrsiRegisterFunction (
|
|
&gIsbServicesGuid,
|
|
Command,
|
|
(IRSI_FUNCTION)mPnpDmiFunctions[Index]
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
Command++;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|