123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927 |
- /** @file
- Implement defer image load services for user identification in UEFI2.2.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "DxeDeferImageLoadLib.h"
- //
- // Handle for the Deferred Image Load Protocol instance produced by this driver.
- //
- EFI_HANDLE mDeferredImageHandle = NULL;
- BOOLEAN mIsProtocolInstalled = FALSE;
- EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
- DEFERRED_IMAGE_TABLE mDeferredImage = {
- 0, // Deferred image count
- NULL // The deferred image info
- };
- EFI_DEFERRED_IMAGE_LOAD_PROTOCOL gDeferredImageLoad = {
- GetDefferedImageInfo
- };
- /**
- Get the image type.
- @param[in] File This is a pointer to the device path of the file
- that is being dispatched.
- @return UINT32 Image Type
- **/
- UINT32
- GetFileType (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File
- )
- {
- EFI_STATUS Status;
- EFI_HANDLE DeviceHandle;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- //
- // 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 IMAGE_FROM_FV;
- }
- }
- //
- // Next check to see if File is from a Block I/O device
- //
- DeviceHandle = NULL;
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
- Status = gBS->LocateDevicePath (
- &gEfiBlockIoProtocolGuid,
- &TempDevicePath,
- &DeviceHandle
- );
- if (!EFI_ERROR (Status)) {
- BlockIo = NULL;
- Status = gBS->OpenProtocol (
- DeviceHandle,
- &gEfiBlockIoProtocolGuid,
- (VOID **) &BlockIo,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status) && BlockIo != NULL) {
- if (BlockIo->Media != NULL) {
- if (BlockIo->Media->RemovableMedia) {
- //
- // Block I/O is present and specifies the media is removable
- //
- return IMAGE_FROM_REMOVABLE_MEDIA;
- } else {
- //
- // Block I/O is present and specifies the media is not removable
- //
- return IMAGE_FROM_FIXED_MEDIA;
- }
- }
- }
- }
- //
- // File is not in a Firmware Volume or on a Block I/O device, so check to see if
- // the device path supports the Simple File System Protocol.
- //
- DeviceHandle = NULL;
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
- Status = gBS->LocateDevicePath (
- &gEfiSimpleFileSystemProtocolGuid,
- &TempDevicePath,
- &DeviceHandle
- );
- if (!EFI_ERROR (Status)) {
- //
- // Simple File System is present without Block I/O, so assume media is fixed.
- //
- return IMAGE_FROM_FIXED_MEDIA;
- }
- //
- // File is not from an FV, Block I/O or Simple File System, so the only options
- // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
- //
- TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
- while (!IsDevicePathEndType (TempDevicePath)) {
- switch (DevicePathType (TempDevicePath)) {
- case MEDIA_DEVICE_PATH:
- if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
- return IMAGE_FROM_OPTION_ROM;
- }
- break;
- case MESSAGING_DEVICE_PATH:
- if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
- return IMAGE_FROM_REMOVABLE_MEDIA;
- }
- break;
- default:
- break;
- }
- TempDevicePath = NextDevicePathNode (TempDevicePath);
- }
- return IMAGE_UNKNOWN;
- }
- /**
- Get current user's access right.
- @param[out] AccessControl Points to the user's access control data, the
- caller should free data buffer.
- @param[in] AccessType The type of user access control.
- @retval EFI_SUCCESS Get current user access control successfully
- @retval others Fail to get current user access control
- **/
- EFI_STATUS
- GetAccessControl (
- OUT EFI_USER_INFO_ACCESS_CONTROL **AccessControl,
- IN UINT32 AccessType
- )
- {
- EFI_STATUS Status;
- EFI_USER_INFO_HANDLE UserInfo;
- EFI_USER_INFO *Info;
- UINTN InfoSize;
- EFI_USER_INFO_ACCESS_CONTROL *Access;
- EFI_USER_PROFILE_HANDLE CurrentUser;
- UINTN CheckLen;
- EFI_USER_MANAGER_PROTOCOL *UserManager;
- CurrentUser = NULL;
- Status = gBS->LocateProtocol (
- &gEfiUserManagerProtocolGuid,
- NULL,
- (VOID **) &UserManager
- );
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
- //
- // Get current user access information.
- //
- UserManager->Current (UserManager, &CurrentUser);
- UserInfo = NULL;
- Info = NULL;
- InfoSize = 0;
- while (TRUE) {
- //
- // Get next user information.
- //
- Status = UserManager->GetNextInfo (UserManager, CurrentUser, &UserInfo);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = UserManager->GetInfo (
- UserManager,
- CurrentUser,
- UserInfo,
- Info,
- &InfoSize
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- if (Info != NULL) {
- FreePool (Info);
- }
- Info = AllocateZeroPool (InfoSize);
- ASSERT (Info != NULL);
- Status = UserManager->GetInfo (
- UserManager,
- CurrentUser,
- UserInfo,
- Info,
- &InfoSize
- );
- }
- if (EFI_ERROR (Status)) {
- break;
- }
- ASSERT (Info != NULL);
- if (Info->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) {
- continue;
- }
- //
- // Get specified access information.
- //
- CheckLen = 0;
- while (CheckLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {
- Access = (EFI_USER_INFO_ACCESS_CONTROL *) ((UINT8 *) (Info + 1) + CheckLen);
- if (Access->Type == AccessType) {
- *AccessControl = AllocateZeroPool (Access->Size);
- ASSERT (*AccessControl != NULL);
- CopyMem (*AccessControl, Access, Access->Size);
- FreePool (Info);
- return EFI_SUCCESS;
- }
- CheckLen += Access->Size;
- }
- }
- if (Info != NULL) {
- FreePool (Info);
- }
- return EFI_NOT_FOUND;
- }
- /**
- Get file name from device path.
- The file name may contain one or more device path node. Save the file name in a
- buffer if file name is found. The caller is responsible to free the buffer.
- @param[in] DevicePath A pointer to a device path.
- @param[out] FileName The callee allocated buffer to save the file name if file name is found.
- @param[out] FileNameOffset The offset of file name in device path if file name is found.
- @retval UINTN The file name length. 0 means file name is not found.
- **/
- UINTN
- GetFileName (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- OUT UINT8 **FileName,
- OUT UINTN *FileNameOffset
- )
- {
- UINTN Length;
- EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *RootDevicePath;
- CHAR8 *NodeStr;
- UINTN NodeStrLength;
- CHAR16 LastNodeChar;
- CHAR16 FirstNodeChar;
- //
- // Get the length of DevicePath before file name.
- //
- Length = 0;
- RootDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
- while (!IsDevicePathEnd (RootDevicePath)) {
- if ((DevicePathType(RootDevicePath) == MEDIA_DEVICE_PATH) && (DevicePathSubType(RootDevicePath) == MEDIA_FILEPATH_DP)) {
- break;
- }
- Length += DevicePathNodeLength (RootDevicePath);
- RootDevicePath = NextDevicePathNode (RootDevicePath);
- }
- *FileNameOffset = Length;
- if (Length == 0) {
- return 0;
- }
- //
- // Get the file name length.
- //
- Length = 0;
- TmpDevicePath = RootDevicePath;
- while (!IsDevicePathEnd (TmpDevicePath)) {
- if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) {
- break;
- }
- Length += DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
- TmpDevicePath = NextDevicePathNode (TmpDevicePath);
- }
- if (Length == 0) {
- return 0;
- }
- *FileName = AllocateZeroPool (Length);
- ASSERT (*FileName != NULL);
- //
- // Copy the file name to the buffer.
- //
- Length = 0;
- LastNodeChar = '\\';
- TmpDevicePath = RootDevicePath;
- while (!IsDevicePathEnd (TmpDevicePath)) {
- if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) {
- break;
- }
- FirstNodeChar = (CHAR16) ReadUnaligned16 ((UINT16 *)((UINT8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL)));
- NodeStr = (CHAR8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL);
- NodeStrLength = DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof(CHAR16);
- if ((FirstNodeChar == '\\') && (LastNodeChar == '\\')) {
- //
- // Skip separator "\" when there are two separators.
- //
- NodeStr += sizeof (CHAR16);
- NodeStrLength -= sizeof (CHAR16);
- } else if ((FirstNodeChar != '\\') && (LastNodeChar != '\\')) {
- //
- // Add separator "\" when there is no separator.
- //
- WriteUnaligned16 ((UINT16 *)(*FileName + Length), '\\');
- Length += sizeof (CHAR16);
- }
- CopyMem (*FileName + Length, NodeStr, NodeStrLength);
- Length += NodeStrLength;
- LastNodeChar = (CHAR16) ReadUnaligned16 ((UINT16 *) (NodeStr + NodeStrLength - sizeof(CHAR16)));
- TmpDevicePath = NextDevicePathNode (TmpDevicePath);
- }
- return Length;
- }
- /**
- Check whether the DevicePath2 is identical with DevicePath1, or identical with
- DevicePath1's child device path.
- If DevicePath2 is identical with DevicePath1, or with DevicePath1's child device
- path, then TRUE returned. Otherwise, FALSE is returned.
- If DevicePath1 is NULL, then ASSERT().
- If DevicePath2 is NULL, then ASSERT().
- @param[in] DevicePath1 A pointer to a device path.
- @param[in] DevicePath2 A pointer to a device path.
- @retval TRUE Two device paths are identical , or DevicePath2 is
- DevicePath1's child device path.
- @retval FALSE Two device paths are not identical, and DevicePath2
- is not DevicePath1's child device path.
- **/
- BOOLEAN
- CheckDevicePath (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2
- )
- {
- UINTN DevicePathSize;
- UINTN FileNameSize1;
- UINTN FileNameSize2;
- UINT8 *FileName1;
- UINT8 *FileName2;
- UINTN FileNameOffset1;
- UINTN FileNameOffset2;
- BOOLEAN DevicePathEqual;
- FileName1 = NULL;
- FileName2 = NULL;
- DevicePathEqual = TRUE;
- ASSERT (DevicePath1 != NULL);
- ASSERT (DevicePath2 != NULL);
- if (IsDevicePathEnd (DevicePath1)) {
- return FALSE;
- }
- //
- // The file name may contain one or more device path node.
- // To compare the file name, copy file name to a buffer and compare the buffer.
- //
- FileNameSize1 = GetFileName (DevicePath1, &FileName1, &FileNameOffset1);
- if (FileNameSize1 != 0) {
- FileNameSize2 = GetFileName (DevicePath2, &FileName2, &FileNameOffset2);
- if (FileNameOffset1 != FileNameOffset2) {
- DevicePathEqual = FALSE;
- goto Done;
- }
- if (CompareMem (DevicePath1, DevicePath2, FileNameOffset1) != 0) {
- DevicePathEqual = FALSE;
- goto Done;
- }
- if (FileNameSize1 > FileNameSize2) {
- DevicePathEqual = FALSE;
- goto Done;
- }
- if (CompareMem (FileName1, FileName2, FileNameSize1) != 0) {
- DevicePathEqual = FALSE;
- goto Done;
- }
- DevicePathEqual = TRUE;
- goto Done;
- }
- DevicePathSize = GetDevicePathSize (DevicePath1);
- if (DevicePathSize > GetDevicePathSize (DevicePath2)) {
- return FALSE;
- }
- //
- // Exclude the end of device path node.
- //
- DevicePathSize -= sizeof (EFI_DEVICE_PATH_PROTOCOL);
- if (CompareMem (DevicePath1, DevicePath2, DevicePathSize) != 0) {
- DevicePathEqual = FALSE;
- }
- Done:
- if (FileName1 != NULL) {
- FreePool (FileName1);
- }
- if (FileName2 != NULL) {
- FreePool (FileName2);
- }
- return DevicePathEqual;
- }
- /**
- Check whether the image pointed to by DevicePath is in the device path list
- specified by AccessType.
- @param[in] DevicePath Points to device path.
- @param[in] AccessType The type of user access control.
- @retval TRUE The DevicePath is in the specified List.
- @retval FALSE The DevicePath is not in the specified List.
- **/
- BOOLEAN
- IsDevicePathInList (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN UINT32 AccessType
- )
- {
- EFI_STATUS Status;
- EFI_USER_INFO_ACCESS_CONTROL *Access;
- EFI_DEVICE_PATH_PROTOCOL *Path;
- UINTN OffSet;
- Status = GetAccessControl (&Access, AccessType);
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- OffSet = 0;
- while (OffSet < Access->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
- Path = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)(Access + 1) + OffSet);
- if (CheckDevicePath (Path, DevicePath)) {
- //
- // The device path is found in list.
- //
- FreePool (Access);
- return TRUE;
- }
- OffSet += GetDevicePathSize (Path);
- }
- FreePool (Access);
- return FALSE;
- }
- /**
- Check whether the image pointed to by DevicePath is permitted to load.
- @param[in] DevicePath Points to device path
- @retval TRUE The image pointed by DevicePath is permitted to load.
- @retval FALSE The image pointed by DevicePath is forbidden to load.
- **/
- BOOLEAN
- VerifyDevicePath (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
- {
- if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_PERMIT_LOAD)) {
- //
- // This access control overrides any restrictions put in place by the
- // EFI_USER_INFO_ACCESS_FORBID_LOAD record.
- //
- return TRUE;
- }
- if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_FORBID_LOAD)) {
- //
- // The device path is found in the forbidden list.
- //
- return FALSE;
- }
- return TRUE;
- }
- /**
- Check the image pointed by DevicePath is a boot option or not.
- @param[in] DevicePath Points to device path.
- @retval TRUE The image pointed by DevicePath is a boot option.
- @retval FALSE The image pointed by DevicePath is not a boot option.
- **/
- BOOLEAN
- IsBootOption (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
- {
- EFI_STATUS Status;
- UINT16 *BootOrderList;
- UINTN BootOrderListSize;
- UINTN Index;
- CHAR16 StrTemp[20];
- UINT8 *OptionBuffer;
- UINT8 *OptionPtr;
- EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
- //
- // Get BootOrder
- //
- BootOrderListSize = 0;
- BootOrderList = NULL;
- Status = gRT->GetVariable (
- L"BootOrder",
- &gEfiGlobalVariableGuid,
- NULL,
- &BootOrderListSize,
- NULL
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- BootOrderList = AllocateZeroPool (BootOrderListSize);
- ASSERT (BootOrderList != NULL);
- Status = gRT->GetVariable (
- L"BootOrder",
- &gEfiGlobalVariableGuid,
- NULL,
- &BootOrderListSize,
- BootOrderList
- );
- }
- if (EFI_ERROR (Status)) {
- //
- // No Boot option
- //
- return FALSE;
- }
- OptionBuffer = NULL;
- for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
- //
- // Try to find the DevicePath in BootOption
- //
- UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);
- GetEfiGlobalVariable2 (StrTemp, (VOID**)&OptionBuffer, NULL);
- if (OptionBuffer == NULL) {
- continue;
- }
- //
- // Check whether the image is forbidden.
- //
- OptionPtr = OptionBuffer;
- //
- // Skip attribute.
- //
- OptionPtr += sizeof (UINT32);
- //
- // Skip device path length.
- //
- OptionPtr += sizeof (UINT16);
- //
- // Skip descript string
- //
- OptionPtr += StrSize ((UINT16 *) OptionPtr);
- //
- // Now OptionPtr points to Device Path.
- //
- OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) OptionPtr;
- if (CheckDevicePath (DevicePath, OptionDevicePath)) {
- FreePool (OptionBuffer);
- OptionBuffer = NULL;
- return TRUE;
- }
- FreePool (OptionBuffer);
- OptionBuffer = NULL;
- }
- if (BootOrderList != NULL) {
- FreePool (BootOrderList);
- }
- return FALSE;
- }
- /**
- Add the image info to a deferred image list.
- @param[in] ImageDevicePath A pointer to the device path of a image.
- @param[in] Image Points to the first byte of the image, or NULL if the
- image is not available.
- @param[in] ImageSize The size of the image, or 0 if the image is not available.
- **/
- VOID
- PutDefferedImageInfo (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,
- IN VOID *Image,
- IN UINTN ImageSize
- )
- {
- DEFERRED_IMAGE_INFO *CurImageInfo;
- UINTN PathSize;
- //
- // Expand memory for the new deferred image.
- //
- if (mDeferredImage.Count == 0) {
- mDeferredImage.ImageInfo = AllocatePool (sizeof (DEFERRED_IMAGE_INFO));
- ASSERT (mDeferredImage.ImageInfo != NULL);
- } else {
- CurImageInfo = AllocatePool ((mDeferredImage.Count + 1) * sizeof (DEFERRED_IMAGE_INFO));
- ASSERT (CurImageInfo != NULL);
- CopyMem (
- CurImageInfo,
- mDeferredImage.ImageInfo,
- mDeferredImage.Count * sizeof (DEFERRED_IMAGE_INFO)
- );
- FreePool (mDeferredImage.ImageInfo);
- mDeferredImage.ImageInfo = CurImageInfo;
- }
- mDeferredImage.Count++;
- //
- // Save the deferred image information.
- //
- CurImageInfo = &mDeferredImage.ImageInfo[mDeferredImage.Count - 1];
- PathSize = GetDevicePathSize (ImageDevicePath);
- CurImageInfo->ImageDevicePath = AllocateZeroPool (PathSize);
- ASSERT (CurImageInfo->ImageDevicePath != NULL);
- CopyMem (CurImageInfo->ImageDevicePath, ImageDevicePath, PathSize);
- CurImageInfo->Image = Image;
- CurImageInfo->ImageSize = ImageSize;
- CurImageInfo->BootOption = IsBootOption (ImageDevicePath);
- }
- /**
- 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
- )
- {
- DEFERRED_IMAGE_INFO *ReqImageInfo;
- //
- // Check the parameter.
- //
- if ((This == NULL) || (ImageSize == NULL) || (Image == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((ImageDevicePath == NULL) || (BootOption == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if (ImageIndex >= mDeferredImage.Count) {
- return EFI_NOT_FOUND;
- }
- //
- // Get the request deferred image.
- //
- ReqImageInfo = &mDeferredImage.ImageInfo[ImageIndex];
- *ImageDevicePath = ReqImageInfo->ImageDevicePath;
- *Image = ReqImageInfo->Image;
- *ImageSize = ReqImageInfo->ImageSize;
- *BootOption = ReqImageInfo->BootOption;
- return EFI_SUCCESS;
- }
- /**
- Provides the service of deferring image load based on platform policy control,
- and installs Deferred Image Load Protocol.
- @param[in] AuthenticationStatus This is the authentication status returned from the
- security measurement services for the input file.
- @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] FileBuffer File buffer matches the input file device path.
- @param[in] FileSize Size of File buffer matches the input file device path.
- @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
- @retval EFI_SUCCESS FileBuffer is NULL and current user has permission to start
- UEFI device drivers on the device path specified by DevicePath.
- @retval EFI_SUCCESS The file specified by DevicePath and non-NULL
- FileBuffer did authenticate, and the platform policy dictates
- that the DXE Foundation may use the file.
- @retval EFI_SECURITY_VIOLATION FileBuffer is NULL and the user has no
- permission to start UEFI device drivers on the device path specified
- by DevicePath.
- @retval EFI_SECURITY_VIOLATION FileBuffer is not NULL and the user has no permission to load
- drivers from the device path specified by DevicePath. The
- image has been added into the list of the deferred images.
- @retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not
- authenticate, and the platform policy dictates that the DXE
- Foundation many not use File.
- **/
- EFI_STATUS
- EFIAPI
- DxeDeferImageLoadHandler (
- IN UINT32 AuthenticationStatus,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
- IN VOID *FileBuffer,
- IN UINTN FileSize,
- IN BOOLEAN BootPolicy
- )
- {
- EFI_STATUS Status;
- EFI_USER_PROFILE_HANDLE CurrentUser;
- UINT32 Policy;
- UINT32 FileType;
- //
- // Ignore if File is NULL.
- //
- if (File == NULL) {
- return EFI_SUCCESS;
- }
- //
- // Check whether user has a logon.
- //
- CurrentUser = NULL;
- if (mUserManager != NULL) {
- mUserManager->Current (mUserManager, &CurrentUser);
- if (CurrentUser != NULL) {
- //
- // The user is logon; verify the FilePath by current user access policy.
- //
- if (!VerifyDevicePath (File)) {
- DEBUG ((EFI_D_ERROR, "[Security] The image is forbidden to load!\n"));
- return EFI_SECURITY_VIOLATION;
- }
- return EFI_SUCCESS;
- }
- }
- //
- // Still no user logon.
- // Check the file type and get policy setting.
- //
- FileType = GetFileType (File);
- Policy = PcdGet32 (PcdDeferImageLoadPolicy);
- if ((Policy & FileType) == FileType) {
- //
- // This file type is secure to load.
- //
- return EFI_SUCCESS;
- }
- DEBUG ((EFI_D_INFO, "[Security] No user identified, the image is deferred to load!\n"));
- PutDefferedImageInfo (File, FileBuffer, FileSize);
- //
- // Install the Deferred Image Load Protocol onto a new handle.
- //
- if (!mIsProtocolInstalled) {
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mDeferredImageHandle,
- &gEfiDeferredImageLoadProtocolGuid,
- &gDeferredImageLoad,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
- mIsProtocolInstalled = TRUE;
- }
- return EFI_ACCESS_DENIED;
- }
- /**
- Locate user manager protocol when user manager is installed.
- @param[in] Event The Event that is being processed, not used.
- @param[in] Context Event Context, not used.
- **/
- VOID
- EFIAPI
- FindUserManagerProtocol (
- IN EFI_EVENT Event,
- IN VOID* Context
- )
- {
- gBS->LocateProtocol (
- &gEfiUserManagerProtocolGuid,
- NULL,
- (VOID **) &mUserManager
- );
- }
- /**
- Register security handler for deferred image load.
- @param[in] ImageHandle ImageHandle of the loaded driver.
- @param[in] SystemTable Pointer to the EFI System Table.
- @retval EFI_SUCCESS The handlers were registered successfully.
- **/
- EFI_STATUS
- EFIAPI
- DxeDeferImageLoadLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- VOID *Registration;
- //
- // Register user manager notification function.
- //
- EfiCreateProtocolNotifyEvent (
- &gEfiUserManagerProtocolGuid,
- TPL_CALLBACK,
- FindUserManagerProtocol,
- NULL,
- &Registration
- );
- return RegisterSecurity2Handler (
- DxeDeferImageLoadHandler,
- EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD
- );
- }
|