alder_lake_bios/Insyde/InsydeModulePkg/Library/GenericBdsLib/SecureRecovery.c

350 lines
9.7 KiB
C

/** @file
Routines for handling capsule update security
;******************************************************************************
;* Copyright (c) 2012 - 2019, 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 <PiDxe.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DevicePathLib.h>
#include <Library/DebugLib.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/LoadFile.h>
#include <Guid/ImageAuthentication.h>
#include <Guid/EfiSystemResourceTable.h>
#include <SecureFlash.h>
typedef struct {
EFI_SIGNATURE_LIST SignatureListHeader;
EFI_SIGNATURE_DATA SignatureData;
} CERTIFICATE_DATA;
typedef struct {
MEMMAP_DEVICE_PATH MemDevicePath;
EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
} IMAGE_DEVICE_PATH;
STATIC IMAGE_DEVICE_PATH ImageDP;
STATIC EFI_LOAD_FILE_PROTOCOL MemMapLoadFile;
STATIC EFI_HANDLE mMemMapLoadImageHandle;
/**
Get the certificate from firmware volume
@param NameGuid Pointer to the file GUID of the certificate
@param Buffer Returned the address of the certificate
@param Size Pointer to the size of the certificate
@retval EFI_SUCCESS The certificate was successfully retrieved
@retval EFI_NOT_FOUND Failed to find the certificate
@retval EFI_LOAD_ERROR Firmware Volume Protocol error
**/
EFI_STATUS
GetCertificateData (
IN EFI_GUID *NameGuid,
IN OUT VOID **Buffer,
IN OUT UINTN *Size
)
{
EFI_STATUS Status;
EFI_HANDLE *HandleBuffer;
UINTN HandleCount;
UINTN Index;
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
UINT32 AuthenticationStatus;
Fv = NULL;
AuthenticationStatus = 0;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiFirmwareVolume2ProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status) || (HandleCount == 0)) {
return EFI_NOT_FOUND;
}
//
// Find desired image in all Fvs
//
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiFirmwareVolume2ProtocolGuid,
(VOID **) &Fv
);
if (EFI_ERROR (Status)) {
return EFI_LOAD_ERROR;
}
*Buffer = NULL;
*Size = 0;
Status = Fv->ReadSection (
Fv,
NameGuid,
EFI_SECTION_RAW,
0,
Buffer,
Size,
&AuthenticationStatus
);
if (!EFI_ERROR (Status)) {
break;
}
}
if (Index >= HandleCount) {
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/**
Load the certificate data to "SecureFlashCertData" variable
The certificate is used when the Capsule image is loaded via gBS->LoadImage()
@param None
@retval EFI_SUCCESS Certificate variable was successfully set
@retval EFI_NOT_FOUND Certificate data was not found
**/
EFI_STATUS
LoadCertToVariable (
VOID
)
{
EFI_STATUS Status;
CERTIFICATE_DATA *CertData;
UINTN CertSize;
Status = GetCertificateData (PcdGetPtr (PcdSecureFlashCertificateFile), (VOID **)&CertData, &CertSize);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
Status = gRT->SetVariable (
L"SecureFlashCertData",
&gSecureFlashInfoGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
CertSize,
CertData
);
FreePool (CertData);
return Status;
}
/**
Enable security check of Capsule images
@param None
@retval EFI_SUCCESS Security check of Capsule images is enabled
@return others Failed to install Capsule security check
**/
EFI_STATUS
EnableCapsuleSecurityCheck (
VOID
)
{
EFI_STATUS Status;
UINT8 SetupMode;
Status = LoadCertToVariable ();
if(EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
return Status;
}
//
// Set SecureFlashSetupMode variable to trigger image verification process.
//
SetupMode = USER_MODE;
Status = gRT->SetVariable (
SECURE_FLASH_SETUP_MODE_NAME,
&gSecureFlashInfoGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof (SetupMode),
&SetupMode
);
ASSERT_EFI_ERROR (Status);
return Status;
}
/**
Enable security check of Capsule images
@param None
@retval EFI_SUCCESS Security check of Capsule images is disabled
@return others Failed to disable Capsule security check
**/
EFI_STATUS
DisableCapsuleSecurityCheck (
VOID
)
{
EFI_STATUS Status;
//
// Clear ceritificate data variable
//
Status = gRT->SetVariable (
L"SecureFlashCertData",
&gSecureFlashInfoGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
NULL
);
//
// Clear SecureFlashSetupMode variable
//
Status = gRT->SetVariable (
SECURE_FLASH_SETUP_MODE_NAME,
&gSecureFlashInfoGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
NULL
);
return Status;
}
EFI_STATUS
EFIAPI
MemMapLoadFileFunction (
IN EFI_LOAD_FILE_PROTOCOL *This,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN BOOLEAN BootPolicy,
IN OUT UINTN *BufferSize,
IN VOID *Buffer OPTIONAL
)
{
MEMMAP_DEVICE_PATH *MemMapFilePath;
//
// The FilePath is pointed to EndDevicePath, modify it to the right address(MEMMAP_DEVICE_PATH).
//
MemMapFilePath = (MEMMAP_DEVICE_PATH *)((UINTN)FilePath - sizeof (MEMMAP_DEVICE_PATH));
if ((MemMapFilePath->Header.Type == HARDWARE_DEVICE_PATH) && (MemMapFilePath->Header.SubType == HW_MEMMAP_DP)) {
if (*BufferSize < (MemMapFilePath->EndingAddress - MemMapFilePath->StartingAddress + 1)) {
*BufferSize = (UINTN) (MemMapFilePath->EndingAddress - MemMapFilePath->StartingAddress + 1);
return EFI_BUFFER_TOO_SMALL;
}
*BufferSize = (UINTN) (MemMapFilePath->EndingAddress - MemMapFilePath->StartingAddress + 1);
CopyMem (Buffer, (VOID *) (UINTN) MemMapFilePath->StartingAddress, *BufferSize);
}
return EFI_SUCCESS;
}
BOOLEAN
RecoveryCapsuleIsExecutable (
IN EFI_PEI_HOB_POINTERS *RecoveryHob
)
{
CHAR8 *Buffer;
if (RecoveryHob == NULL) {
return FALSE;
}
Buffer =(CHAR8 *) (UINTN)RecoveryHob->MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
return (BOOLEAN) ((Buffer[0] == 'M') && (Buffer[1] == 'Z'));
}
EFI_STATUS
ExecuteRecoveryCapsule (
IN EFI_PEI_HOB_POINTERS *RecoveryHob
)
{
EFI_PHYSICAL_ADDRESS ImageStart;
EFI_PHYSICAL_ADDRESS ImageEnd;
EFI_HANDLE CapsuleHandle;
EFI_STATUS Status;
UINT32 ImageSize;
if (RecoveryHob == NULL) {
return EFI_INVALID_PARAMETER;
}
CapsuleHandle = NULL;
ImageStart = RecoveryHob->MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
ImageSize = (UINT32)RecoveryHob->MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
ImageEnd = ImageStart + ImageSize - 1;
ImageDP.MemDevicePath.Header.Type = HARDWARE_DEVICE_PATH;
ImageDP.MemDevicePath.Header.SubType = HW_MEMMAP_DP;
ImageDP.MemDevicePath.Header.Length[0] = (UINT8)(sizeof (MEMMAP_DEVICE_PATH));
ImageDP.MemDevicePath.Header.Length[1] = (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8);
ImageDP.MemDevicePath.MemoryType = EfiBootServicesCode;
ImageDP.MemDevicePath.StartingAddress = ImageStart;
ImageDP.MemDevicePath.EndingAddress = ImageEnd;
ImageDP.EndDevicePath.Type = END_DEVICE_PATH_TYPE;
ImageDP.EndDevicePath.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
ImageDP.EndDevicePath.Length[0] = END_DEVICE_PATH_LENGTH;
ImageDP.EndDevicePath.Length[1] = 0;
MemMapLoadFile.LoadFile = MemMapLoadFileFunction;
Status = gBS->InstallMultipleProtocolInterfaces (
&mMemMapLoadImageHandle,
&gEfiDevicePathProtocolGuid,
&ImageDP.MemDevicePath,
&gEfiLoadFileProtocolGuid,
&MemMapLoadFile,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = EnableCapsuleSecurityCheck ();
if (!EFI_ERROR(Status)) {
Status = gBS->LoadImage (
TRUE,
gImageHandle,
&ImageDP.MemDevicePath.Header,
NULL,
ImageSize,
&CapsuleHandle
);
}
if (!EFI_ERROR(Status)) {
Status = gBS->StartImage (CapsuleHandle, NULL, NULL);
}
DisableCapsuleSecurityCheck ();
return Status;
}