]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeDeferImageLoadLib/DxeDeferImageLoadLib.c
SecurityPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / SecurityPkg / Library / DxeDeferImageLoadLib / DxeDeferImageLoadLib.c
index 84b8cf78847c06143b70d6d07e42d983ac2c7da5..a6a3fe3cfc68627253010bd211bd03bc67e785ab 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   Implement defer image load services for user identification in UEFI2.2.\r
 \r
-Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution.  The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -33,9 +27,9 @@ EFI_DEFERRED_IMAGE_LOAD_PROTOCOL gDeferredImageLoad   = {
   Get the image type.\r
 \r
   @param[in]    File    This is a pointer to the device path of the file\r
-                        that is being dispatched. \r
+                        that is being dispatched.\r
 \r
-  @return       UINT32  Image Type             \r
+  @return       UINT32  Image Type\r
 \r
 **/\r
 UINT32\r
@@ -44,7 +38,7 @@ GetFileType (
   )\r
 {\r
   EFI_STATUS                        Status;\r
-  EFI_HANDLE                        DeviceHandle; \r
+  EFI_HANDLE                        DeviceHandle;\r
   EFI_DEVICE_PATH_PROTOCOL          *TempDevicePath;\r
   EFI_BLOCK_IO_PROTOCOL             *BlockIo;\r
 \r
@@ -110,7 +104,7 @@ GetFileType (
   }\r
 \r
   //\r
-  // File is not in a Firmware Volume or on a Block I/O device, so check to see if \r
+  // File is not in a Firmware Volume or on a Block I/O device, so check to see if\r
   // the device path supports the Simple File System Protocol.\r
   //\r
   DeviceHandle   = NULL;\r
@@ -129,12 +123,12 @@ GetFileType (
 \r
   //\r
   // File is not from an FV, Block I/O or Simple File System, so the only options\r
-  // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.  \r
+  // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.\r
   //\r
   TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;\r
   while (!IsDevicePathEndType (TempDevicePath)) {\r
     switch (DevicePathType (TempDevicePath)) {\r
-    \r
+\r
     case MEDIA_DEVICE_PATH:\r
       if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {\r
         return IMAGE_FROM_OPTION_ROM;\r
@@ -144,7 +138,7 @@ GetFileType (
     case MESSAGING_DEVICE_PATH:\r
       if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {\r
         return IMAGE_FROM_REMOVABLE_MEDIA;\r
-      } \r
+      }\r
       break;\r
 \r
     default:\r
@@ -152,7 +146,7 @@ GetFileType (
     }\r
     TempDevicePath = NextDevicePathNode (TempDevicePath);\r
   }\r
-  return IMAGE_UNKNOWN; \r
+  return IMAGE_UNKNOWN;\r
 }\r
 \r
 \r
@@ -191,7 +185,7 @@ GetAccessControl (
   if (EFI_ERROR (Status)) {\r
     return EFI_NOT_FOUND;\r
   }\r
-  \r
+\r
   //\r
   // Get current user access information.\r
   //\r
@@ -234,19 +228,19 @@ GetAccessControl (
     if (EFI_ERROR (Status)) {\r
       break;\r
     }\r
-    \r
+\r
     ASSERT (Info != NULL);\r
     if (Info->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) {\r
       continue;\r
     }\r
-    \r
+\r
     //\r
     // Get specified access information.\r
     //\r
     CheckLen  = 0;\r
     while (CheckLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {\r
       Access = (EFI_USER_INFO_ACCESS_CONTROL *) ((UINT8 *) (Info + 1) + CheckLen);\r
-      if ((Access->Type == AccessType)) {\r
+      if (Access->Type == AccessType) {\r
         *AccessControl = AllocateZeroPool (Access->Size);\r
         ASSERT (*AccessControl != NULL);\r
         CopyMem (*AccessControl, Access, Access->Size);\r
@@ -256,64 +250,114 @@ GetAccessControl (
       CheckLen += Access->Size;\r
     }\r
   }\r
-  \r
+\r
   if (Info != NULL) {\r
     FreePool (Info);\r
   }\r
   return EFI_NOT_FOUND;\r
 }\r
 \r
-\r
 /**\r
-  Convert the '/' to '\' in the specified string.\r
+  Get file name from device path.\r
+\r
+  The file name may contain one or more device path node. Save the file name in a\r
+  buffer if file name is found. The caller is responsible to free the buffer.\r
+\r
+  @param[in]  DevicePath     A pointer to a device path.\r
+  @param[out] FileName       The callee allocated buffer to save the file name if file name is found.\r
+  @param[out] FileNameOffset The offset of file name in device path if file name is found.\r
 \r
-  @param[in, out]  Str       Points to the string to convert.\r
+  @retval     UINTN          The file name length. 0 means file name is not found.\r
 \r
 **/\r
-VOID\r
-ConvertDPStr (\r
-  IN OUT EFI_STRING                     Str \r
+UINTN\r
+GetFileName (\r
+  IN  CONST EFI_DEVICE_PATH_PROTOCOL          *DevicePath,\r
+  OUT UINT8                                   **FileName,\r
+  OUT UINTN                                   *FileNameOffset\r
   )\r
 {\r
-  INTN                                  Count;\r
-  INTN                                  Index;\r
-  \r
-  Count = StrSize(Str) / 2 - 1;\r
+  UINTN                                       Length;\r
+  EFI_DEVICE_PATH_PROTOCOL                    *TmpDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL                    *RootDevicePath;\r
+  CHAR8                                       *NodeStr;\r
+  UINTN                                       NodeStrLength;\r
+  CHAR16                                      LastNodeChar;\r
+  CHAR16                                      FirstNodeChar;\r
+\r
+  //\r
+  // Get the length of DevicePath before file name.\r
+  //\r
+  Length = 0;\r
+  RootDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;\r
+  while (!IsDevicePathEnd (RootDevicePath)) {\r
+    if ((DevicePathType(RootDevicePath) == MEDIA_DEVICE_PATH) && (DevicePathSubType(RootDevicePath) == MEDIA_FILEPATH_DP)) {\r
+      break;\r
+    }\r
+    Length += DevicePathNodeLength (RootDevicePath);\r
+    RootDevicePath = NextDevicePathNode (RootDevicePath);\r
+  }\r
 \r
-  if (Count < 4) {\r
-    return;\r
+  *FileNameOffset = Length;\r
+  if (Length == 0) {\r
+    return 0;\r
   }\r
-  \r
+\r
   //\r
-  // Convert device path string.\r
+  // Get the file name length.\r
   //\r
-  Index = Count - 1;\r
-  while (Index > 0) {\r
-    //\r
-    // Find the last '/'.\r
-    //\r
-    for (Index = Count - 1; Index > 0; Index--) {\r
-      if (Str[Index] == L'/')\r
-        break;\r
+  Length = 0;\r
+  TmpDevicePath = RootDevicePath;\r
+  while (!IsDevicePathEnd (TmpDevicePath)) {\r
+    if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) {\r
+      break;\r
     }\r
+    Length += DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+    TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
+  }\r
+  if (Length == 0) {\r
+    return 0;\r
+  }\r
 \r
-    //\r
-    // Check next char.\r
-    //\r
-    if (Str[Index + 1] == L'\\')\r
-      return;\r
-    \r
-    Str[Index] = L'\\';\r
-    \r
-    //\r
-    // Check previous char.\r
-    //\r
-    if ((Index > 0) && (Str[Index - 1] == L'\\')) {\r
-      CopyMem (&Str[Index - 1], &Str[Index], (UINTN) ((Count - Index + 1) * sizeof (CHAR16)));\r
-      return;\r
+  *FileName = AllocateZeroPool (Length);\r
+  ASSERT (*FileName != NULL);\r
+\r
+  //\r
+  // Copy the file name to the buffer.\r
+  //\r
+  Length = 0;\r
+  LastNodeChar = '\\';\r
+  TmpDevicePath = RootDevicePath;\r
+  while (!IsDevicePathEnd (TmpDevicePath)) {\r
+    if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) {\r
+      break;\r
     }\r
-    Index--;\r
+\r
+    FirstNodeChar = (CHAR16) ReadUnaligned16 ((UINT16 *)((UINT8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL)));\r
+    NodeStr = (CHAR8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+    NodeStrLength = DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof(CHAR16);\r
+\r
+    if ((FirstNodeChar == '\\') && (LastNodeChar == '\\')) {\r
+      //\r
+      // Skip separator "\" when there are two separators.\r
+      //\r
+      NodeStr += sizeof (CHAR16);\r
+      NodeStrLength -= sizeof (CHAR16);\r
+    } else if ((FirstNodeChar != '\\') && (LastNodeChar != '\\')) {\r
+      //\r
+      // Add separator "\" when there is no separator.\r
+      //\r
+      WriteUnaligned16 ((UINT16 *)(*FileName + Length), '\\');\r
+      Length += sizeof (CHAR16);\r
+    }\r
+    CopyMem (*FileName + Length, NodeStr, NodeStrLength);\r
+    Length += NodeStrLength;\r
+\r
+    LastNodeChar  = (CHAR16) ReadUnaligned16 ((UINT16 *) (NodeStr + NodeStrLength - sizeof(CHAR16)));\r
+    TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
   }\r
+\r
+  return Length;\r
 }\r
 \r
 \r
@@ -323,16 +367,16 @@ ConvertDPStr (
 \r
   If DevicePath2 is identical with DevicePath1, or with DevicePath1's child device\r
   path, then TRUE returned. Otherwise, FALSE is returned.\r
-  \r
+\r
   If DevicePath1 is NULL, then ASSERT().\r
   If DevicePath2 is NULL, then ASSERT().\r
 \r
   @param[in]  DevicePath1   A pointer to a device path.\r
   @param[in]  DevicePath2   A pointer to a device path.\r
 \r
-  @retval     TRUE          Two device paths are identical , or DevicePath2 is \r
+  @retval     TRUE          Two device paths are identical , or DevicePath2 is\r
                             DevicePath1's child device path.\r
-  @retval     FALSE         Two device paths are not identical, and DevicePath2 \r
+  @retval     FALSE         Two device paths are not identical, and DevicePath2\r
                             is not DevicePath1's child device path.\r
 \r
 **/\r
@@ -342,66 +386,84 @@ CheckDevicePath (
   IN  CONST EFI_DEVICE_PATH_PROTOCOL          *DevicePath2\r
   )\r
 {\r
-  EFI_STATUS                            Status;\r
-  EFI_STRING                            DevicePathStr1;\r
-  EFI_STRING                            DevicePathStr2;\r
-  UINTN                                 StrLen1;\r
-  UINTN                                 StrLen2;\r
-  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL      *DevicePathText;\r
-  BOOLEAN                               DevicePathEqual;\r
+  UINTN                                       DevicePathSize;\r
+  UINTN                                       FileNameSize1;\r
+  UINTN                                       FileNameSize2;\r
+  UINT8                                       *FileName1;\r
+  UINT8                                       *FileName2;\r
+  UINTN                                       FileNameOffset1;\r
+  UINTN                                       FileNameOffset2;\r
+  BOOLEAN                                     DevicePathEqual;\r
+\r
+  FileName1       = NULL;\r
+  FileName2       = NULL;\r
+  DevicePathEqual = TRUE;\r
 \r
   ASSERT (DevicePath1 != NULL);\r
   ASSERT (DevicePath2 != NULL);\r
-  \r
-  DevicePathEqual = FALSE;\r
-  DevicePathText  = NULL;\r
-  Status = gBS->LocateProtocol ( \r
-                  &gEfiDevicePathToTextProtocolGuid,\r
-                  NULL,\r
-                  (VOID **) &DevicePathText\r
-                  );\r
-  ASSERT (Status == EFI_SUCCESS);\r
-  \r
-  //\r
-  // Get first device path string.\r
-  //\r
-  DevicePathStr1 = DevicePathText->ConvertDevicePathToText (DevicePath1, TRUE, TRUE);\r
-  ConvertDPStr (DevicePathStr1);\r
+  if (IsDevicePathEnd (DevicePath1)) {\r
+    return FALSE;\r
+  }\r
+\r
   //\r
-  // Get second device path string.\r
+  // The file name may contain one or more device path node.\r
+  // To compare the file name, copy file name to a buffer and compare the buffer.\r
   //\r
-  DevicePathStr2 = DevicePathText->ConvertDevicePathToText (DevicePath2, TRUE, TRUE);\r
-  ConvertDPStr (DevicePathStr2);\r
-  \r
+  FileNameSize1 = GetFileName (DevicePath1, &FileName1, &FileNameOffset1);\r
+  if (FileNameSize1 != 0) {\r
+    FileNameSize2 = GetFileName (DevicePath2, &FileName2, &FileNameOffset2);\r
+    if (FileNameOffset1 != FileNameOffset2) {\r
+      DevicePathEqual = FALSE;\r
+      goto Done;\r
+    }\r
+    if (CompareMem (DevicePath1, DevicePath2, FileNameOffset1) != 0) {\r
+      DevicePathEqual = FALSE;\r
+      goto Done;\r
+    }\r
+    if (FileNameSize1 > FileNameSize2) {\r
+      DevicePathEqual = FALSE;\r
+      goto Done;\r
+    }\r
+    if (CompareMem (FileName1, FileName2, FileNameSize1) != 0) {\r
+      DevicePathEqual = FALSE;\r
+      goto Done;\r
+    }\r
+    DevicePathEqual = TRUE;\r
+    goto Done;\r
+  }\r
+\r
+  DevicePathSize = GetDevicePathSize (DevicePath1);\r
+  if (DevicePathSize > GetDevicePathSize (DevicePath2)) {\r
+    return FALSE;\r
+  }\r
+\r
   //\r
-  // Compare device path string.\r
+  // Exclude the end of device path node.\r
   //\r
-  StrLen1 = StrSize (DevicePathStr1);\r
-  StrLen2 = StrSize (DevicePathStr2);\r
-  if (StrLen1 > StrLen2) {\r
+  DevicePathSize -= sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+  if (CompareMem (DevicePath1, DevicePath2, DevicePathSize) != 0) {\r
     DevicePathEqual = FALSE;\r
-    goto Done;\r
-  }\r
-  \r
-  if (CompareMem (DevicePathStr1, DevicePathStr2, StrLen1) == 0) {\r
-    DevicePathEqual = TRUE;\r
   }\r
 \r
 Done:\r
-  FreePool (DevicePathStr1);\r
-  FreePool (DevicePathStr2);\r
+  if (FileName1 != NULL) {\r
+    FreePool (FileName1);\r
+  }\r
+  if (FileName2 != NULL) {\r
+    FreePool (FileName2);\r
+  }\r
   return DevicePathEqual;\r
 }\r
 \r
 \r
 /**\r
-  Check whether the image pointed to by DevicePath is in the device path list \r
-  specified by AccessType.  \r
+  Check whether the image pointed to by DevicePath is in the device path list\r
+  specified by AccessType.\r
 \r
   @param[in] DevicePath  Points to device path.\r
   @param[in] AccessType  The type of user access control.\r
\r
-  @retval    TURE        The DevicePath is in the specified List.\r
+\r
+  @retval    TRUE        The DevicePath is in the specified List.\r
   @retval    FALSE       The DevicePath is not in the specified List.\r
 \r
 **/\r
@@ -414,37 +476,37 @@ IsDevicePathInList (
   EFI_STATUS                            Status;\r
   EFI_USER_INFO_ACCESS_CONTROL          *Access;\r
   EFI_DEVICE_PATH_PROTOCOL              *Path;\r
-  UINTN                                 OffSet;  \r
+  UINTN                                 OffSet;\r
 \r
   Status = GetAccessControl (&Access, AccessType);\r
   if (EFI_ERROR (Status)) {\r
     return FALSE;\r
-  }  \r
+  }\r
 \r
   OffSet = 0;\r
   while (OffSet < Access->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
-    Path = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)(Access + 1) + OffSet);    \r
+    Path = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)(Access + 1) + OffSet);\r
     if (CheckDevicePath (Path, DevicePath)) {\r
       //\r
       // The device path is found in list.\r
       //\r
       FreePool (Access);\r
       return TRUE;\r
-    }  \r
+    }\r
     OffSet += GetDevicePathSize (Path);\r
   }\r
-  \r
+\r
   FreePool (Access);\r
-  return FALSE; \r
+  return FALSE;\r
 }\r
 \r
 \r
 /**\r
-  Check whether the image pointed to by DevicePath is permitted to load.  \r
+  Check whether the image pointed to by DevicePath is permitted to load.\r
 \r
   @param[in] DevicePath  Points to device path\r
\r
-  @retval    TURE        The image pointed by DevicePath is permitted to load.\r
+\r
+  @retval    TRUE        The image pointed by DevicePath is permitted to load.\r
   @retval    FALSE       The image pointed by DevicePath is forbidden to load.\r
 \r
 **/\r
@@ -455,29 +517,29 @@ VerifyDevicePath (
 {\r
   if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_PERMIT_LOAD)) {\r
     //\r
-    // This access control overrides any restrictions put in place by the \r
+    // This access control overrides any restrictions put in place by the\r
     // EFI_USER_INFO_ACCESS_FORBID_LOAD record.\r
     //\r
     return TRUE;\r
   }\r
-  \r
+\r
   if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_FORBID_LOAD)) {\r
     //\r
     // The device path is found in the forbidden list.\r
     //\r
     return FALSE;\r
   }\r
-  \r
-  return TRUE; \r
+\r
+  return TRUE;\r
 }\r
 \r
 \r
 /**\r
-  Check the image pointed by DevicePath is a boot option or not.  \r
+  Check the image pointed by DevicePath is a boot option or not.\r
 \r
   @param[in] DevicePath  Points to device path.\r
\r
-  @retval    TURE        The image pointed by DevicePath is a boot option.\r
+\r
+  @retval    TRUE        The image pointed by DevicePath is a boot option.\r
   @retval    FALSE       The image pointed by DevicePath is not a boot option.\r
 \r
 **/\r
@@ -494,31 +556,31 @@ IsBootOption (
   UINT8                             *OptionBuffer;\r
   UINT8                             *OptionPtr;\r
   EFI_DEVICE_PATH_PROTOCOL          *OptionDevicePath;\r
-  \r
+\r
   //\r
   // Get BootOrder\r
   //\r
   BootOrderListSize = 0;\r
-  BootOrderList     = NULL;  \r
+  BootOrderList     = NULL;\r
   Status = gRT->GetVariable (\r
-                  L"BootOrder", \r
-                  &gEfiGlobalVariableGuid, \r
-                  NULL, \r
-                  &BootOrderListSize, \r
+                  L"BootOrder",\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &BootOrderListSize,\r
                   NULL\r
                   );\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     BootOrderList = AllocateZeroPool (BootOrderListSize);\r
     ASSERT (BootOrderList != NULL);\r
     Status = gRT->GetVariable (\r
-                    L"BootOrder", \r
-                    &gEfiGlobalVariableGuid, \r
-                    NULL, \r
-                    &BootOrderListSize, \r
+                    L"BootOrder",\r
+                    &gEfiGlobalVariableGuid,\r
+                    NULL,\r
+                    &BootOrderListSize,\r
                     BootOrderList\r
                     );\r
   }\r
-  \r
+\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // No Boot option\r
@@ -540,7 +602,7 @@ IsBootOption (
     //\r
     // Check whether the image is forbidden.\r
     //\r
-    \r
+\r
     OptionPtr = OptionBuffer;\r
     //\r
     // Skip attribute.\r
@@ -556,7 +618,7 @@ IsBootOption (
     // Skip descript string\r
     //\r
     OptionPtr += StrSize ((UINT16 *) OptionPtr);\r
\r
+\r
     //\r
     // Now OptionPtr points to Device Path.\r
     //\r
@@ -582,11 +644,11 @@ IsBootOption (
 /**\r
   Add the image info to a deferred image list.\r
 \r
-  @param[in]  ImageDevicePath  A pointer to the device path of a image.                                \r
-  @param[in]  Image            Points to the first byte of the image, or NULL if the \r
+  @param[in]  ImageDevicePath  A pointer to the device path of a image.\r
+  @param[in]  Image            Points to the first byte of the image, or NULL if the\r
                                image is not available.\r
   @param[in]  ImageSize        The size of the image, or 0 if the image is not available.\r
-  \r
+\r
 **/\r
 VOID\r
 PutDefferedImageInfo (\r
@@ -607,9 +669,9 @@ PutDefferedImageInfo (
   } else {\r
     CurImageInfo = AllocatePool ((mDeferredImage.Count + 1) * sizeof (DEFERRED_IMAGE_INFO));\r
     ASSERT (CurImageInfo != NULL);\r
-    \r
+\r
     CopyMem (\r
-      CurImageInfo, \r
+      CurImageInfo,\r
       mDeferredImage.ImageInfo,\r
       mDeferredImage.Count * sizeof (DEFERRED_IMAGE_INFO)\r
       );\r
@@ -617,7 +679,7 @@ PutDefferedImageInfo (
     mDeferredImage.ImageInfo = CurImageInfo;\r
   }\r
   mDeferredImage.Count++;\r
-  \r
+\r
   //\r
   // Save the deferred image information.\r
   //\r
@@ -636,29 +698,29 @@ PutDefferedImageInfo (
 /**\r
   Returns information about a deferred image.\r
 \r
-  This function returns information about a single deferred image. The deferred images are \r
-  numbered consecutively, starting with 0.  If there is no image which corresponds to \r
-  ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by \r
+  This function returns information about a single deferred image. The deferred images are\r
+  numbered consecutively, starting with 0.  If there is no image which corresponds to\r
+  ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by\r
   iteratively calling this function until EFI_NOT_FOUND is returned.\r
-  Image may be NULL and ImageSize set to 0 if the decision to defer execution was made \r
-  because of the location of the executable image, rather than its actual contents.  \r
+  Image may be NULL and ImageSize set to 0 if the decision to defer execution was made\r
+  because of the location of the executable image, rather than its actual contents.\r
 \r
   @param[in]  This             Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL.\r
   @param[in]  ImageIndex       Zero-based index of the deferred index.\r
-  @param[out] ImageDevicePath  On return, points to a pointer to the device path of the image. \r
-                               The device path should not be freed by the caller. \r
-  @param[out] Image            On return, points to the first byte of the image or NULL if the \r
+  @param[out] ImageDevicePath  On return, points to a pointer to the device path of the image.\r
+                               The device path should not be freed by the caller.\r
+  @param[out] Image            On return, points to the first byte of the image or NULL if the\r
                                image is not available. The image should not be freed by the caller\r
-                               unless LoadImage() has been successfully called.  \r
+                               unless LoadImage() has been successfully called.\r
   @param[out] ImageSize        On return, the size of the image, or 0 if the image is not available.\r
-  @param[out] BootOption       On return, points to TRUE if the image was intended as a boot option \r
-                               or FALSE if it was not intended as a boot option. \r
\r
+  @param[out] BootOption       On return, points to TRUE if the image was intended as a boot option\r
+                               or FALSE if it was not intended as a boot option.\r
+\r
   @retval EFI_SUCCESS           Image information returned successfully.\r
   @retval EFI_NOT_FOUND         ImageIndex does not refer to a valid image.\r
-  @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or \r
+  @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or\r
                                 BootOption is NULL.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -680,7 +742,7 @@ GetDefferedImageInfo (
   if ((This == NULL) || (ImageSize == NULL) || (Image == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
   if ((ImageDevicePath == NULL) || (BootOption == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -688,17 +750,17 @@ GetDefferedImageInfo (
   if (ImageIndex >= mDeferredImage.Count) {\r
     return EFI_NOT_FOUND;\r
   }\r
-  \r
+\r
   //\r
   // Get the request deferred image.\r
-  // \r
+  //\r
   ReqImageInfo = &mDeferredImage.ImageInfo[ImageIndex];\r
-   \r
+\r
   *ImageDevicePath = ReqImageInfo->ImageDevicePath;\r
   *Image           = ReqImageInfo->Image;\r
   *ImageSize       = ReqImageInfo->ImageSize;\r
   *BootOption      = ReqImageInfo->BootOption;\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -707,25 +769,29 @@ GetDefferedImageInfo (
   Provides the service of deferring image load based on platform policy control,\r
   and installs Deferred Image Load Protocol.\r
 \r
-  @param[in]  AuthenticationStatus  This is the authentication status returned from the \r
+  @param[in]  AuthenticationStatus  This is the authentication status returned from the\r
                                     security measurement services for the input file.\r
   @param[in]  File                  This is a pointer to the device path of the file that\r
                                     is being dispatched. This will optionally be used for\r
                                     logging.\r
   @param[in]  FileBuffer            File buffer matches the input file device path.\r
   @param[in]  FileSize              Size of File buffer matches the input file device path.\r
-\r
-  @retval EFI_SUCCESS               The file specified by File did authenticate, and the\r
-                                    platform policy dictates that the DXE Core may use File.\r
-  @retval EFI_INVALID_PARAMETER     File is NULL.\r
-  @retval EFI_SECURITY_VIOLATION    The file specified by File did not authenticate, and\r
-                                    the platform policy dictates that File should be placed\r
-                                    in the untrusted state. A file may be promoted from\r
-                                    the untrusted to the trusted state at a future time\r
-                                    with a call to the Trust() DXE Service.\r
-  @retval EFI_ACCESS_DENIED         The file specified by File did not authenticate, and\r
-                                    the platform policy dictates that File should not be\r
-                                    used for any purpose.\r
+  @param[in]  BootPolicy            A boot policy that was used to call LoadImage() UEFI service.\r
+\r
+  @retval EFI_SUCCESS               FileBuffer is NULL and current user has permission to start\r
+                                    UEFI device drivers on the device path specified by DevicePath.\r
+  @retval EFI_SUCCESS               The file specified by DevicePath and non-NULL\r
+                                    FileBuffer did authenticate, and the platform policy dictates\r
+                                    that the DXE Foundation may use the file.\r
+  @retval EFI_SECURITY_VIOLATION    FileBuffer is NULL and the user has no\r
+                                    permission to start UEFI device drivers on the device path specified\r
+                                    by DevicePath.\r
+  @retval EFI_SECURITY_VIOLATION    FileBuffer is not NULL and the user has no permission to load\r
+                                    drivers from the device path specified by DevicePath. The\r
+                                    image has been added into the list of the deferred images.\r
+  @retval EFI_ACCESS_DENIED         The file specified by File and FileBuffer did not\r
+                                    authenticate, and the platform policy dictates that the DXE\r
+                                    Foundation many not use File.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -734,22 +800,25 @@ DxeDeferImageLoadHandler (
   IN  UINT32                           AuthenticationStatus,\r
   IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
   IN  VOID                             *FileBuffer,\r
-  IN  UINTN                            FileSize\r
+  IN  UINTN                            FileSize,\r
+  IN  BOOLEAN                          BootPolicy\r
   )\r
-\r
 {\r
   EFI_STATUS                           Status;\r
   EFI_USER_PROFILE_HANDLE              CurrentUser;\r
   UINT32                               Policy;\r
   UINT32                               FileType;\r
 \r
+  //\r
+  // Ignore if File is NULL.\r
+  //\r
   if (File == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   //\r
   // Check whether user has a logon.\r
-  // \r
+  //\r
   CurrentUser = NULL;\r
   if (mUserManager != NULL) {\r
     mUserManager->Current (mUserManager, &CurrentUser);\r
@@ -759,12 +828,12 @@ DxeDeferImageLoadHandler (
       //\r
       if (!VerifyDevicePath (File)) {\r
         DEBUG ((EFI_D_ERROR, "[Security] The image is forbidden to load!\n"));\r
-        return EFI_ACCESS_DENIED;\r
+        return EFI_SECURITY_VIOLATION;\r
       }\r
       return EFI_SUCCESS;\r
     }\r
   }\r
-  \r
+\r
   //\r
   // Still no user logon.\r
   // Check the file type and get policy setting.\r
@@ -777,9 +846,9 @@ DxeDeferImageLoadHandler (
     //\r
     return EFI_SUCCESS;\r
   }\r
\r
-  DEBUG ((EFI_D_ERROR, "[Security] No user identified, the image is deferred to load!\n"));\r
-  PutDefferedImageInfo (File, NULL, 0);\r
+\r
+  DEBUG ((EFI_D_INFO, "[Security] No user identified, the image is deferred to load!\n"));\r
+  PutDefferedImageInfo (File, FileBuffer, FileSize);\r
 \r
   //\r
   // Install the Deferred Image Load Protocol onto a new handle.\r
@@ -799,10 +868,10 @@ DxeDeferImageLoadHandler (
 }\r
 \r
 /**\r
-  Locate user manager protocol when user manager is installed.  \r
+  Locate user manager protocol when user manager is installed.\r
 \r
   @param[in] Event    The Event that is being processed, not used.\r
-  @param[in] Context  Event Context, not used. \r
+  @param[in] Context  Event Context, not used.\r
 \r
 **/\r
 VOID\r
@@ -817,7 +886,7 @@ FindUserManagerProtocol (
          NULL,\r
          (VOID **) &mUserManager\r
          );\r
-  \r
+\r
 }\r
 \r
 \r
@@ -837,22 +906,22 @@ DxeDeferImageLoadLibConstructor (
   )\r
 {\r
   VOID                 *Registration;\r
-  \r
+\r
   //\r
   // Register user manager notification function.\r
   //\r
   EfiCreateProtocolNotifyEvent (\r
-    &gEfiUserManagerProtocolGuid, \r
+    &gEfiUserManagerProtocolGuid,\r
     TPL_CALLBACK,\r
     FindUserManagerProtocol,\r
     NULL,\r
     &Registration\r
     );\r
-  \r
-  return RegisterSecurityHandler (\r
+\r
+  return RegisterSecurity2Handler (\r
            DxeDeferImageLoadHandler,\r
-           EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD \r
-           );      \r
+           EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD\r
+           );\r
 }\r
 \r
 \r