alder_lake_bios/Oem/L05/FeatureCommon/InsydeL05ModulePkg/BootOptionService/LimitedToInternalStorage.c

539 lines
14 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 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 "LimitedToInternalStorage.h"
#include <SetupConfig.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/BaseLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/PrintLib.h>
#include <Library/DebugLib.h>
#include <Library/VariableLib.h>
#include <Library/GenericBdsLib.h>
#include <Library/H2OCpLib.h>
#include <Protocol/BlockIo.h>
#include <Protocol/DevicePath.h>
/**
Is Limited to internal storage.
@param None.
@retval TRUE Boot device will be limited to internal storage.
@retval FALSE Boot device will not be limited to internal storage.
**/
BOOLEAN
L05IsLimitedToInternalStorage (
VOID
)
{
EFI_STATUS Status;
UINTN BufferSize;
SYSTEM_CONFIGURATION *SetupNvData;
BOOLEAN IsLimited;
SetupNvData = NULL;
IsLimited = FALSE;
BufferSize = sizeof (SYSTEM_CONFIGURATION);
SetupNvData = AllocateZeroPool (BufferSize);
if (SetupNvData == NULL) {
return FALSE;
}
Status = CommonGetVariable (
L"Setup",
&gSystemConfigurationGuid,
&BufferSize,
SetupNvData
);
if (EFI_ERROR (Status)) {
return FALSE;
}
if (SetupNvData->L05NaturalFileGuard == 1) { // 0:Disabled, 1:Enabled
IsLimited = TRUE;
}
if (SetupNvData->L05DeviceGuard == 1) { // 0:Disabled, 1:Enabled
IsLimited = TRUE;
}
FreePool (SetupNvData);
return IsLimited;
}
/**
Limited to Internal Storage Process.
Check if platform is Limited to internal storage.
YES - If boot option is not internal storage, set attributes to inactive.
NO - Set attributes to active.
@param None.
**/
VOID
LimitedToInternalStorageProcess (
VOID
)
{
EFI_STATUS Status;
UINTN BlockIoHandleCount;
EFI_HANDLE *BlockIoBuffer;
UINTN BlockIndex;
EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
EFI_BLOCK_IO_PROTOCOL *BlkIo;
UINT16 *BootOrder;
UINTN BootOrderSize;
UINTN BootDevNum;
UINTN Index;
UINT16 BootOptionName[BOOT_OPTION_MAX_CHAR];
UINT8 *BootOption;
UINTN BootOptionSize;
UINT8 *TempPtr;
UINT32 *Attribute;
CHAR16 *Description;
UINTN DescriptionSize;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINT16 DevicePathSize;
BOOLEAN InternalStorage;
BlockIoHandleCount = 0;
BlockIoBuffer = NULL;
BlockIoDevicePath = NULL;
BlkIo = NULL;
BootOrder = NULL;
BootOrderSize = 0;
BootDevNum = 0;
InternalStorage = FALSE;
BlockIoBuffer = NULL;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiBlockIoProtocolGuid,
NULL,
&BlockIoHandleCount,
&BlockIoBuffer
);
if (EFI_ERROR (Status) || BlockIoBuffer == NULL) {
return;
}
Status = CommonGetVariableDataAndSize (
L"BootOrder",
&gEfiGlobalVariableGuid,
&BootOrderSize,
(VOID **) &BootOrder
);
if (EFI_ERROR (Status) || BootOrder == NULL) {
return;
}
BootDevNum = BootOrderSize / sizeof (UINT16);
for (Index = 0; Index < BootDevNum; Index++) {
InternalStorage = FALSE;
UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", BootOrder[Index]);
Status = CommonGetVariableDataAndSize (
BootOptionName,
&gEfiGlobalVariableGuid,
&BootOptionSize,
(VOID **) &BootOption
);
if (EFI_ERROR (Status) || BootOption == NULL) {
continue;
}
TempPtr = BootOption;
Attribute = (UINT32 *) TempPtr;
TempPtr += sizeof (UINT32);
DevicePathSize = *((UINT16 *) TempPtr);
TempPtr += sizeof (UINT16);
Description = (CHAR16 *) TempPtr;
DescriptionSize = StrSize (Description);
TempPtr += DescriptionSize;
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
TempPtr += DevicePathSize;
if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)) {
//
// Find hard drive media device path.
//
if (BlockIoBuffer != NULL && BlockIoHandleCount != 0) {
for (BlockIndex = 0; BlockIndex < BlockIoHandleCount; BlockIndex++) {
BlockIoDevicePath = DevicePathFromHandle (BlockIoBuffer[BlockIndex]);
if (BlockIoDevicePath == NULL) {
continue;
}
if (MatchPartitionDevicePathNode (BlockIoDevicePath, (HARDDRIVE_DEVICE_PATH *) DevicePath)) {
//
// Find the matched partition device path.
//
Status = gBS->HandleProtocol (
BlockIoBuffer[BlockIndex],
&gEfiBlockIoProtocolGuid,
(VOID **) &BlkIo
);
if (EFI_ERROR (Status)) {
continue;
}
if (!BlkIo->Media->RemovableMedia) {
//
// Not removable media, that is internal storage.
//
InternalStorage = TRUE;
break;
}
}
}
}
}
if (!InternalStorage && L05IsLimitedToInternalStorage ()) {
//
// The boot option is not internal storage.
// So set Attributes to inactive for limited to internal storage.
//
*Attribute &= (~((UINT32) LOAD_OPTION_ACTIVE));
} else {
*Attribute |= (((UINT32) LOAD_OPTION_ACTIVE));
}
Status = CommonSetVariable (
BootOptionName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootOptionSize,
BootOption
);
FreePool (BootOption);
}
if (BootOrder != NULL) {
FreePool (BootOrder);
}
return;
}
/**
Limited to Internal Storage update Target HDD Variable.
@param None.
**/
VOID
LimitedToInternalStorageUpdateTargetHddVariable (
VOID
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *TargetHddDevPathVar;
UINTN BufferSize;
SYSTEM_CONFIGURATION *SetupNvData;
UINT8 BootType;
TargetHddDevPathVar = NULL;
SetupNvData = NULL;
if (!L05IsLimitedToInternalStorage ()) {
return;
}
//
// Get TargetHddDevPath variable of fast boot.
//
TargetHddDevPathVar = CommonGetVariableData (
L"TargetHddDevPath",
&gEfiGenericVariableGuid
);
if (TargetHddDevPathVar != NULL) {
FreePool (TargetHddDevPathVar);
return;
}
BufferSize = sizeof (SYSTEM_CONFIGURATION);
SetupNvData = AllocateZeroPool (BufferSize);
if (SetupNvData == NULL) {
return;
}
Status = CommonGetVariable (
L"Setup",
&gSystemConfigurationGuid,
&BufferSize,
SetupNvData
);
if (EFI_ERROR (Status)) {
return;
}
gBdsServices->GetBootType (gBdsServices, &BootType);
if (SetupNvData->Win8FastBoot == 0 &&
BootType == EFI_BOOT_TYPE) {
UpdateTargetHddVariable ();
}
FreePool (SetupNvData);
return;
}
/**
Limited to internal storage at Boot Device Enum After check point.
It will update attribute of boot optoion to limited to internal storage.
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context.
**/
VOID
EFIAPI
LimitedToInternalStorageNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
BOOLEAN IsBootOrderHookEnabled;
IsBootOrderHookEnabled = BdsLibIsBootOrderHookEnabled ();
//
// Update Option Attribute of BootOrder variable.
//
if (IsBootOrderHookEnabled) {
BdsLibDisableBootOrderHook ();
}
LimitedToInternalStorageProcess ();
//
// Update Option Attribute of PhysicalBootOrder variable.
//
BdsLibEnableBootOrderHook ();
LimitedToInternalStorageProcess ();
if (!IsBootOrderHookEnabled) {
BdsLibDisableBootOrderHook ();
}
//
// Update Target HDD Variable
//
LimitedToInternalStorageUpdateTargetHddVariable ();
return;
}
/**
Limited dummy boot option to internal storage after gEfiVariableWriteArchProtocolGuid is installed.
When platform is limited to internal storage, update attribute of dummy boot option to limited to internal storage.
@param Event Pointer to this event
@param Context Event hanlder private data
**/
VOID
EFIAPI
LimitedDummyBootOptionToInternalStorageNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
VOID *Interface;
UINT16 BootOptionName[BOOT_OPTION_MAX_CHAR];
UINTN BootOptionSize;
UINT8 *BootOption;
UINTN Index;
UINT32 *Attribute;
Status = gBS->LocateProtocol (
&gEfiVariableWriteArchProtocolGuid,
NULL,
(VOID **) &Interface
);
if (EFI_ERROR (Status)) {
return;
}
gBS->CloseEvent (Event);
for (Index = (DummyBootOptionStartNum + 1); Index < DummyBootOptionEndNum; Index++) {
UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", Index);
Status = CommonGetVariableDataAndSize (
BootOptionName,
&gEfiGlobalVariableGuid,
&BootOptionSize,
(VOID **) &BootOption
);
if (EFI_ERROR (Status) || BootOption == NULL) {
continue;
}
Attribute = (UINT32 *) BootOption;
if (L05IsLimitedToInternalStorage ()) {
//
// Set Attributes to inactive for limited to internal storage.
//
*Attribute &= (~((UINT32) LOAD_OPTION_ACTIVE));
} else {
*Attribute |= (((UINT32) LOAD_OPTION_ACTIVE));
}
Status = CommonSetVariable (
BootOptionName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootOptionSize,
BootOption
);
gBS->FreePool (BootOption);
}
return;
}
/**
Limited boot next to internal storage after gEfiVariableWriteArchProtocolGuid is installed.
When platform is limited to internal storage, delete BootNext variable if BootNext option is dummy boot option.
@param Event Pointer to this event
@param Context Event hanlder private data
**/
VOID
EFIAPI
LimitedBootNextToInternalStorageNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
VOID *Interface;
UINT16 *BootNext;
BootNext = NULL;
Status = gBS->LocateProtocol (
&gEfiVariableWriteArchProtocolGuid,
NULL,
(VOID **) &Interface
);
if (EFI_ERROR (Status)) {
return;
}
gBS->CloseEvent (Event);
if (!L05IsLimitedToInternalStorage ()) {
return;
}
BootNext = CommonGetVariableData (
L"BootNext",
&gEfiGlobalVariableGuid
);
if (BootNext == NULL) {
return;
}
if (BdsLibIsDummyBootOption (*BootNext)) {
CommonSetVariable (L"BootNext", &gEfiGlobalVariableGuid, 0, 0, NULL);
}
if (BootNext != NULL) {
FreePool (BootNext);
}
return;
}
/**
Limited to internal storage.
@retval EFI_SUCCESS The operation completed successfully.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
LimitedToInternalStorage (
VOID
)
{
EFI_STATUS Status;
H2O_CP_HANDLE CpHandle;
VOID *Registration;
CpHandle = NULL;
if (FeaturePcdGet (PcdH2OBdsCpBootDeviceEnumAfterSupported)) {
Status = H2OCpRegisterHandler (
&gH2OBdsCpBootDeviceEnumAfterGuid,
LimitedToInternalStorageNotify,
H2O_CP_MEDIUM,
&CpHandle
);
if (EFI_ERROR (Status)) {
DEBUG_CP ((DEBUG_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2OBdsCpBootDeviceEnumAfterGuid, Status));
} else {
DEBUG_CP ((DEBUG_INFO, "Checkpoint Registered: %g (%r)\n", &gH2OBdsCpBootDeviceEnumAfterGuid, Status));
}
}
Registration = NULL;
EfiCreateProtocolNotifyEvent (
&gEfiVariableWriteArchProtocolGuid,
TPL_CALLBACK,
LimitedDummyBootOptionToInternalStorageNotify,
NULL,
&Registration
);
Registration = NULL;
EfiCreateProtocolNotifyEvent (
&gEfiVariableWriteArchProtocolGuid,
TPL_CALLBACK,
LimitedBootNextToInternalStorageNotify,
NULL,
&Registration
);
return Status;
}