diff options
Diffstat (limited to 'MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c')
| -rw-r--r-- | MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c | 828 |
1 files changed, 414 insertions, 414 deletions
diff --git a/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c b/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c index bf04a02661..b6be96e9c9 100644 --- a/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c +++ b/MdeModulePkg/Universal/SecurityStubDxe/Defer3rdPartyImageLoad.c @@ -1,414 +1,414 @@ -/** @file
- Implement defer image load services for user identification in UEFI2.2.
-
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-#include "Defer3rdPartyImageLoad.h"
-
-//
-// The structure to save the deferred 3rd party image information.
-//
-typedef struct {
- EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
- BOOLEAN BootOption;
- BOOLEAN Loaded;
-} DEFERRED_3RD_PARTY_IMAGE_INFO;
-
-//
-// The table to save the deferred 3rd party image item.
-//
-typedef struct {
- UINTN Count; ///< deferred 3rd party image count
- DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo; ///< deferred 3rd party image item
-} DEFERRED_3RD_PARTY_IMAGE_TABLE;
-
-BOOLEAN mImageLoadedAfterEndOfDxe = FALSE;
-BOOLEAN mEndOfDxe = FALSE;
-DEFERRED_3RD_PARTY_IMAGE_TABLE mDeferred3rdPartyImage = {
- 0, // Deferred image count
- NULL // The deferred image info
-};
-
-EFI_DEFERRED_IMAGE_LOAD_PROTOCOL mDeferredImageLoad = {
- GetDefferedImageInfo
-};
-
-/**
- Return whether the file comes from FV.
-
- @param[in] File This is a pointer to the device path of the file
- that is being dispatched.
-
- @retval TRUE File comes from FV.
- @retval FALSE File doesn't come from FV.
-**/
-BOOLEAN
-FileFromFv (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE DeviceHandle;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
-
- //
- // First check to see if File is from a Firmware Volume
- //
- DeviceHandle = NULL;
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
- Status = gBS->LocateDevicePath (
- &gEfiFirmwareVolume2ProtocolGuid,
- &TempDevicePath,
- &DeviceHandle
- );
- if (!EFI_ERROR (Status)) {
- Status = gBS->OpenProtocol (
- DeviceHandle,
- &gEfiFirmwareVolume2ProtocolGuid,
- NULL,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Find the deferred image which matches the device path.
-
- @param[in] ImageDevicePath A pointer to the device path of a image.
- @param[in] BootOption Whether the image is a boot option.
-
- @return Pointer to the found deferred image or NULL if not found.
-**/
-DEFERRED_3RD_PARTY_IMAGE_INFO *
-LookupImage (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,
- IN BOOLEAN BootOption
- )
-{
- UINTN Index;
- UINTN DevicePathSize;
-
- DevicePathSize = GetDevicePathSize (ImageDevicePath);
-
- for (Index = 0; Index < mDeferred3rdPartyImage.Count; Index++) {
- if (CompareMem (ImageDevicePath, mDeferred3rdPartyImage.ImageInfo[Index].ImageDevicePath, DevicePathSize) == 0) {
- ASSERT (mDeferred3rdPartyImage.ImageInfo[Index].BootOption == BootOption);
- return &mDeferred3rdPartyImage.ImageInfo[Index];
- }
- }
-
- return NULL;
-}
-
-/**
- Add the image info to a deferred image list.
-
- @param[in] ImageDevicePath A pointer to the device path of a image.
- @param[in] BootOption Whether the image is a boot option.
-
-**/
-VOID
-QueueImage (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,
- IN BOOLEAN BootOption
- )
-{
- DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo;
-
- //
- // Expand memory for the new deferred image.
- //
- ImageInfo = ReallocatePool (
- mDeferred3rdPartyImage.Count * sizeof (DEFERRED_3RD_PARTY_IMAGE_INFO),
- (mDeferred3rdPartyImage.Count + 1) * sizeof (DEFERRED_3RD_PARTY_IMAGE_INFO),
- mDeferred3rdPartyImage.ImageInfo
- );
- if (ImageInfo == NULL) {
- return;
- }
-
- mDeferred3rdPartyImage.ImageInfo = ImageInfo;
-
- //
- // Save the deferred image information.
- //
- ImageInfo = &mDeferred3rdPartyImage.ImageInfo[mDeferred3rdPartyImage.Count];
- ImageInfo->ImageDevicePath = DuplicateDevicePath (ImageDevicePath);
- if (ImageInfo->ImageDevicePath == NULL) {
- return;
- }
-
- ImageInfo->BootOption = BootOption;
- ImageInfo->Loaded = FALSE;
- mDeferred3rdPartyImage.Count++;
-}
-
-/**
- Returns information about a deferred image.
-
- This function returns information about a single deferred image. The deferred images are
- numbered consecutively, starting with 0. If there is no image which corresponds to
- ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by
- iteratively calling this function until EFI_NOT_FOUND is returned.
- Image may be NULL and ImageSize set to 0 if the decision to defer execution was made
- because of the location of the executable image, rather than its actual contents.
-
- @param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL.
- @param[in] ImageIndex Zero-based index of the deferred index.
- @param[out] ImageDevicePath On return, points to a pointer to the device path of the image.
- The device path should not be freed by the caller.
- @param[out] Image On return, points to the first byte of the image or NULL if the
- image is not available. The image should not be freed by the caller
- unless LoadImage() has been successfully called.
- @param[out] ImageSize On return, the size of the image, or 0 if the image is not available.
- @param[out] BootOption On return, points to TRUE if the image was intended as a boot option
- or FALSE if it was not intended as a boot option.
-
- @retval EFI_SUCCESS Image information returned successfully.
- @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image.
- @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or
- BootOption is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-GetDefferedImageInfo (
- IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This,
- IN UINTN ImageIndex,
- OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath,
- OUT VOID **Image,
- OUT UINTN *ImageSize,
- OUT BOOLEAN *BootOption
- )
-{
- UINTN Index;
- UINTN NewCount;
-
- if ((This == NULL) || (ImageSize == NULL) || (Image == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if ((ImageDevicePath == NULL) || (BootOption == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Remove the loaded images from the defer list in the first call.
- //
- if (ImageIndex == 0) {
- NewCount = 0;
- for (Index = 0; Index < mDeferred3rdPartyImage.Count; Index++) {
- if (!mDeferred3rdPartyImage.ImageInfo[Index].Loaded) {
- CopyMem (
- &mDeferred3rdPartyImage.ImageInfo[NewCount],
- &mDeferred3rdPartyImage.ImageInfo[Index],
- sizeof (DEFERRED_3RD_PARTY_IMAGE_INFO)
- );
- NewCount++;
- }
- }
-
- mDeferred3rdPartyImage.Count = NewCount;
- }
-
- if (ImageIndex >= mDeferred3rdPartyImage.Count) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Get the request deferred image.
- //
- *ImageDevicePath = mDeferred3rdPartyImage.ImageInfo[ImageIndex].ImageDevicePath;
- *BootOption = mDeferred3rdPartyImage.ImageInfo[ImageIndex].BootOption;
- *Image = NULL;
- *ImageSize = 0;
-
- return EFI_SUCCESS;
-}
-
-/**
- Callback function executed when the EndOfDxe event group is signaled.
-
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context The pointer to the notification function's context, which
- is implementation-dependent.
-**/
-VOID
-EFIAPI
-EndOfDxe (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- mEndOfDxe = TRUE;
-}
-
-/**
- Event notification for gEfiDxeSmmReadyToLockProtocolGuid event.
-
- This function reports failure if any deferred image is loaded before
- this callback.
- Platform should publish ReadyToLock protocol immediately after signaling
- of the End of DXE Event.
-
- @param Event The Event that is being processed, not used.
- @param Context Event Context, not used.
-
-**/
-VOID
-EFIAPI
-DxeSmmReadyToLock (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- VOID *Interface;
-
- Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- gBS->CloseEvent (Event);
-
- if (mImageLoadedAfterEndOfDxe) {
- //
- // Platform should not dispatch the 3rd party images after signaling EndOfDxe event
- // but before publishing DxeSmmReadyToLock protocol.
- //
- DEBUG ((
- DEBUG_ERROR,
- "[Security] 3rd party images must be dispatched after DxeSmmReadyToLock Protocol installation!\n"
- ));
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED,
- (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)
- );
- ASSERT (FALSE);
- CpuDeadLoop ();
- }
-}
-
-/**
- Defer the 3rd party image load and installs Deferred Image Load Protocol.
-
- @param[in] File This is a pointer to the device path of the file that
- is being dispatched. This will optionally be used for
- logging.
- @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
-
- @retval EFI_SUCCESS The file is not 3rd party image and can be loaded immediately.
- @retval EFI_ACCESS_DENIED The file is 3rd party image and needs deferred.
-**/
-EFI_STATUS
-Defer3rdPartyImageLoad (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
- IN BOOLEAN BootPolicy
- )
-{
- DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo;
-
- //
- // Ignore if File is NULL.
- //
- if (File == NULL) {
- return EFI_SUCCESS;
- }
-
- if (FileFromFv (File)) {
- return EFI_SUCCESS;
- }
-
- ImageInfo = LookupImage (File, BootPolicy);
-
- DEBUG_CODE_BEGIN ();
- CHAR16 *DevicePathStr;
-
- DevicePathStr = ConvertDevicePathToText (File, FALSE, FALSE);
- DEBUG ((
- DEBUG_INFO,
- "[Security] 3rd party image[%p] %s EndOfDxe: %s.\n",
- ImageInfo,
- mEndOfDxe ? L"can be loaded after" : L"is deferred to load before",
- DevicePathStr
- ));
- if (DevicePathStr != NULL) {
- FreePool (DevicePathStr);
- }
-
- DEBUG_CODE_END ();
-
- if (mEndOfDxe) {
- mImageLoadedAfterEndOfDxe = TRUE;
- //
- // The image might be first time loaded after EndOfDxe,
- // So ImageInfo can be NULL.
- //
- if (ImageInfo != NULL) {
- ImageInfo->Loaded = TRUE;
- }
-
- return EFI_SUCCESS;
- } else {
- //
- // The image might be second time loaded before EndOfDxe,
- // So ImageInfo can be non-NULL.
- //
- if (ImageInfo == NULL) {
- QueueImage (File, BootPolicy);
- }
-
- return EFI_ACCESS_DENIED;
- }
-}
-
-/**
- Installs DeferredImageLoad Protocol and listens EndOfDxe event.
-**/
-VOID
-Defer3rdPartyImageLoadInitialize (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- EFI_EVENT Event;
- VOID *Registration;
-
- Handle = NULL;
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Handle,
- &gEfiDeferredImageLoadProtocolGuid,
- &mDeferredImageLoad,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- EndOfDxe,
- NULL,
- &gEfiEndOfDxeEventGroupGuid,
- &Event
- );
- ASSERT_EFI_ERROR (Status);
-
- EfiCreateProtocolNotifyEvent (
- &gEfiDxeSmmReadyToLockProtocolGuid,
- TPL_CALLBACK,
- DxeSmmReadyToLock,
- NULL,
- &Registration
- );
-}
+/** @file + Implement defer image load services for user identification in UEFI2.2. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "Defer3rdPartyImageLoad.h" + +// +// The structure to save the deferred 3rd party image information. +// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + BOOLEAN BootOption; + BOOLEAN Loaded; +} DEFERRED_3RD_PARTY_IMAGE_INFO; + +// +// The table to save the deferred 3rd party image item. +// +typedef struct { + UINTN Count; ///< deferred 3rd party image count + DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo; ///< deferred 3rd party image item +} DEFERRED_3RD_PARTY_IMAGE_TABLE; + +BOOLEAN mImageLoadedAfterEndOfDxe = FALSE; +BOOLEAN mEndOfDxe = FALSE; +DEFERRED_3RD_PARTY_IMAGE_TABLE mDeferred3rdPartyImage = { + 0, // Deferred image count + NULL // The deferred image info +}; + +EFI_DEFERRED_IMAGE_LOAD_PROTOCOL mDeferredImageLoad = { + GetDefferedImageInfo +}; + +/** + Return whether the file comes from FV. + + @param[in] File This is a pointer to the device path of the file + that is being dispatched. + + @retval TRUE File comes from FV. + @retval FALSE File doesn't come from FV. +**/ +BOOLEAN +FileFromFv ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *File + ) +{ + EFI_STATUS Status; + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + + // + // First check to see if File is from a Firmware Volume + // + DeviceHandle = NULL; + TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File; + Status = gBS->LocateDevicePath ( + &gEfiFirmwareVolume2ProtocolGuid, + &TempDevicePath, + &DeviceHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return TRUE; + } + } + + return FALSE; +} + +/** + Find the deferred image which matches the device path. + + @param[in] ImageDevicePath A pointer to the device path of a image. + @param[in] BootOption Whether the image is a boot option. + + @return Pointer to the found deferred image or NULL if not found. +**/ +DEFERRED_3RD_PARTY_IMAGE_INFO * +LookupImage ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath, + IN BOOLEAN BootOption + ) +{ + UINTN Index; + UINTN DevicePathSize; + + DevicePathSize = GetDevicePathSize (ImageDevicePath); + + for (Index = 0; Index < mDeferred3rdPartyImage.Count; Index++) { + if (CompareMem (ImageDevicePath, mDeferred3rdPartyImage.ImageInfo[Index].ImageDevicePath, DevicePathSize) == 0) { + ASSERT (mDeferred3rdPartyImage.ImageInfo[Index].BootOption == BootOption); + return &mDeferred3rdPartyImage.ImageInfo[Index]; + } + } + + return NULL; +} + +/** + Add the image info to a deferred image list. + + @param[in] ImageDevicePath A pointer to the device path of a image. + @param[in] BootOption Whether the image is a boot option. + +**/ +VOID +QueueImage ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath, + IN BOOLEAN BootOption + ) +{ + DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo; + + // + // Expand memory for the new deferred image. + // + ImageInfo = ReallocatePool ( + mDeferred3rdPartyImage.Count * sizeof (DEFERRED_3RD_PARTY_IMAGE_INFO), + (mDeferred3rdPartyImage.Count + 1) * sizeof (DEFERRED_3RD_PARTY_IMAGE_INFO), + mDeferred3rdPartyImage.ImageInfo + ); + if (ImageInfo == NULL) { + return; + } + + mDeferred3rdPartyImage.ImageInfo = ImageInfo; + + // + // Save the deferred image information. + // + ImageInfo = &mDeferred3rdPartyImage.ImageInfo[mDeferred3rdPartyImage.Count]; + ImageInfo->ImageDevicePath = DuplicateDevicePath (ImageDevicePath); + if (ImageInfo->ImageDevicePath == NULL) { + return; + } + + ImageInfo->BootOption = BootOption; + ImageInfo->Loaded = FALSE; + mDeferred3rdPartyImage.Count++; +} + +/** + Returns information about a deferred image. + + This function returns information about a single deferred image. The deferred images are + numbered consecutively, starting with 0. If there is no image which corresponds to + ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by + iteratively calling this function until EFI_NOT_FOUND is returned. + Image may be NULL and ImageSize set to 0 if the decision to defer execution was made + because of the location of the executable image, rather than its actual contents. + + @param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL. + @param[in] ImageIndex Zero-based index of the deferred index. + @param[out] ImageDevicePath On return, points to a pointer to the device path of the image. + The device path should not be freed by the caller. + @param[out] Image On return, points to the first byte of the image or NULL if the + image is not available. The image should not be freed by the caller + unless LoadImage() has been successfully called. + @param[out] ImageSize On return, the size of the image, or 0 if the image is not available. + @param[out] BootOption On return, points to TRUE if the image was intended as a boot option + or FALSE if it was not intended as a boot option. + + @retval EFI_SUCCESS Image information returned successfully. + @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image. + @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or + BootOption is NULL. + +**/ +EFI_STATUS +EFIAPI +GetDefferedImageInfo ( + IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This, + IN UINTN ImageIndex, + OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath, + OUT VOID **Image, + OUT UINTN *ImageSize, + OUT BOOLEAN *BootOption + ) +{ + UINTN Index; + UINTN NewCount; + + if ((This == NULL) || (ImageSize == NULL) || (Image == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((ImageDevicePath == NULL) || (BootOption == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Remove the loaded images from the defer list in the first call. + // + if (ImageIndex == 0) { + NewCount = 0; + for (Index = 0; Index < mDeferred3rdPartyImage.Count; Index++) { + if (!mDeferred3rdPartyImage.ImageInfo[Index].Loaded) { + CopyMem ( + &mDeferred3rdPartyImage.ImageInfo[NewCount], + &mDeferred3rdPartyImage.ImageInfo[Index], + sizeof (DEFERRED_3RD_PARTY_IMAGE_INFO) + ); + NewCount++; + } + } + + mDeferred3rdPartyImage.Count = NewCount; + } + + if (ImageIndex >= mDeferred3rdPartyImage.Count) { + return EFI_NOT_FOUND; + } + + // + // Get the request deferred image. + // + *ImageDevicePath = mDeferred3rdPartyImage.ImageInfo[ImageIndex].ImageDevicePath; + *BootOption = mDeferred3rdPartyImage.ImageInfo[ImageIndex].BootOption; + *Image = NULL; + *ImageSize = 0; + + return EFI_SUCCESS; +} + +/** + Callback function executed when the EndOfDxe event group is signaled. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context The pointer to the notification function's context, which + is implementation-dependent. +**/ +VOID +EFIAPI +EndOfDxe ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mEndOfDxe = TRUE; +} + +/** + Event notification for gEfiDxeSmmReadyToLockProtocolGuid event. + + This function reports failure if any deferred image is loaded before + this callback. + Platform should publish ReadyToLock protocol immediately after signaling + of the End of DXE Event. + + @param Event The Event that is being processed, not used. + @param Context Event Context, not used. + +**/ +VOID +EFIAPI +DxeSmmReadyToLock ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *Interface; + + Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface); + if (EFI_ERROR (Status)) { + return; + } + + gBS->CloseEvent (Event); + + if (mImageLoadedAfterEndOfDxe) { + // + // Platform should not dispatch the 3rd party images after signaling EndOfDxe event + // but before publishing DxeSmmReadyToLock protocol. + // + DEBUG (( + DEBUG_ERROR, + "[Security] 3rd party images must be dispatched after DxeSmmReadyToLock Protocol installation!\n" + )); + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE) + ); + ASSERT (FALSE); + CpuDeadLoop (); + } +} + +/** + Defer the 3rd party image load and installs Deferred Image Load Protocol. + + @param[in] File This is a pointer to the device path of the file that + is being dispatched. This will optionally be used for + logging. + @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service. + + @retval EFI_SUCCESS The file is not 3rd party image and can be loaded immediately. + @retval EFI_ACCESS_DENIED The file is 3rd party image and needs deferred. +**/ +EFI_STATUS +Defer3rdPartyImageLoad ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *File, + IN BOOLEAN BootPolicy + ) +{ + DEFERRED_3RD_PARTY_IMAGE_INFO *ImageInfo; + + // + // Ignore if File is NULL. + // + if (File == NULL) { + return EFI_SUCCESS; + } + + if (FileFromFv (File)) { + return EFI_SUCCESS; + } + + ImageInfo = LookupImage (File, BootPolicy); + + DEBUG_CODE_BEGIN (); + CHAR16 *DevicePathStr; + + DevicePathStr = ConvertDevicePathToText (File, FALSE, FALSE); + DEBUG (( + DEBUG_INFO, + "[Security] 3rd party image[%p] %s EndOfDxe: %s.\n", + ImageInfo, + mEndOfDxe ? L"can be loaded after" : L"is deferred to load before", + DevicePathStr + )); + if (DevicePathStr != NULL) { + FreePool (DevicePathStr); + } + + DEBUG_CODE_END (); + + if (mEndOfDxe) { + mImageLoadedAfterEndOfDxe = TRUE; + // + // The image might be first time loaded after EndOfDxe, + // So ImageInfo can be NULL. + // + if (ImageInfo != NULL) { + ImageInfo->Loaded = TRUE; + } + + return EFI_SUCCESS; + } else { + // + // The image might be second time loaded before EndOfDxe, + // So ImageInfo can be non-NULL. + // + if (ImageInfo == NULL) { + QueueImage (File, BootPolicy); + } + + return EFI_ACCESS_DENIED; + } +} + +/** + Installs DeferredImageLoad Protocol and listens EndOfDxe event. +**/ +VOID +Defer3rdPartyImageLoadInitialize ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_EVENT Event; + VOID *Registration; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiDeferredImageLoadProtocolGuid, + &mDeferredImageLoad, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + EndOfDxe, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + + EfiCreateProtocolNotifyEvent ( + &gEfiDxeSmmReadyToLockProtocolGuid, + TPL_CALLBACK, + DxeSmmReadyToLock, + NULL, + &Registration + ); +} |
