]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
Revert "Capsule-on-Disk entire Patch
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / CapsuleOnDisk.c
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
deleted file mode 100644 (file)
index bb34e6d..0000000
+++ /dev/null
@@ -1,1966 +0,0 @@
-/** @file\r
-  The implementation supports Capusle on Disk.\r
-\r
-  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "CapsuleOnDisk.h"\r
-\r
-/**\r
-  Return if this capsule is a capsule name capsule, based upon CapsuleHeader.\r
-\r
-  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
-\r
-  @retval TRUE  It is a capsule name capsule.\r
-  @retval FALSE It is not a capsule name capsule.\r
-**/\r
-BOOLEAN\r
-IsCapsuleNameCapsule (\r
-  IN EFI_CAPSULE_HEADER         *CapsuleHeader\r
-  );\r
-\r
-/**\r
-  Check the integrity of the capsule name capsule.\r
-  If the capsule is vaild, return the physical address of each capsule name string.\r
-\r
-  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule name capsule.\r
-  @param[out] CapsuleNameNum  Number of capsule name.\r
-\r
-  @retval NULL                Capsule name capsule is not valid.\r
-  @retval CapsuleNameBuf      Array of capsule name physical address.\r
-\r
-**/\r
-EFI_PHYSICAL_ADDRESS *\r
-ValidateCapsuleNameCapsuleIntegrity (\r
-  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,\r
-  OUT UINTN                         *CapsuleNameNum\r
-  )\r
-{\r
-  UINT8                    *CapsuleNamePtr;\r
-  UINT8                    *CapsuleNameBufStart;\r
-  UINT8                    *CapsuleNameBufEnd;\r
-  UINTN                    Index;\r
-  UINTN                    StringSize;\r
-  EFI_PHYSICAL_ADDRESS     *CapsuleNameBuf;\r
-\r
-  if (!IsCapsuleNameCapsule (CapsuleHeader)) {\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Total string size must be even.\r
-  //\r
-  if (((CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize) & BIT0) != 0) {\r
-    return NULL;\r
-  }\r
-\r
-  *CapsuleNameNum = 0;\r
-  Index = 0;\r
-  CapsuleNameBufStart = (UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize;\r
-\r
-  //\r
-  // If strings are not aligned on a 16-bit boundary, reallocate memory for it.\r
-  //\r
-  if (((UINTN) CapsuleNameBufStart & BIT0) != 0) {\r
-    CapsuleNameBufStart = AllocateCopyPool (CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize, CapsuleNameBufStart);\r
-  }\r
-\r
-  CapsuleNameBufEnd = CapsuleNameBufStart + CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;\r
-\r
-  CapsuleNamePtr = CapsuleNameBufStart;\r
-  while (CapsuleNamePtr < CapsuleNameBufEnd) {\r
-    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd - CapsuleNamePtr)/sizeof(CHAR16));\r
-    CapsuleNamePtr += StringSize;\r
-    (*CapsuleNameNum) ++;\r
-  }\r
-\r
-  //\r
-  // Integrity check.\r
-  //\r
-  if (CapsuleNamePtr != CapsuleNameBufEnd) {\r
-    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize) {\r
-      FreePool (CapsuleNameBufStart);\r
-    }\r
-    return NULL;\r
-  }\r
-\r
-  CapsuleNameBuf = AllocatePool (*CapsuleNameNum * sizeof (EFI_PHYSICAL_ADDRESS));\r
-  if (CapsuleNameBuf == NULL) {\r
-    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize) {\r
-      FreePool (CapsuleNameBufStart);\r
-    }\r
-    return NULL;\r
-  }\r
-\r
-  CapsuleNamePtr = CapsuleNameBufStart;\r
-  while (CapsuleNamePtr < CapsuleNameBufEnd) {\r
-    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd - CapsuleNamePtr)/sizeof(CHAR16));\r
-    CapsuleNameBuf[Index] = (EFI_PHYSICAL_ADDRESS)(UINTN) CapsuleNamePtr;\r
-    CapsuleNamePtr += StringSize;\r
-    Index ++;\r
-  }\r
-\r
-  return CapsuleNameBuf;\r
-}\r
-\r
-/**\r
-  This routine is called to upper case given unicode string.\r
-\r
-  @param[in]   Str              String to upper case\r
-\r
-  @retval upper cased string after process\r
-\r
-**/\r
-static\r
-CHAR16 *\r
-UpperCaseString (\r
-  IN CHAR16 *Str\r
-  )\r
-{\r
-  CHAR16  *Cptr;\r
-\r
-  for (Cptr = Str; *Cptr; Cptr++) {\r
-    if (L'a' <= *Cptr && *Cptr <= L'z') {\r
-      *Cptr = *Cptr - L'a' + L'A';\r
-    }\r
-  }\r
-\r
-  return Str;\r
-}\r
-\r
-/**\r
-  This routine is used to return substring before period '.' or '\0'\r
-  Caller should respsonsible of substr space allocation & free\r
-\r
-  @param[in]   Str              String to check\r
-  @param[out]  SubStr           First part of string before period or '\0'\r
-  @param[out]  SubStrLen        Length of first part of string\r
-\r
-**/\r
-static\r
-VOID\r
-GetSubStringBeforePeriod (\r
-  IN  CHAR16 *Str,\r
-  OUT CHAR16 *SubStr,\r
-  OUT UINTN  *SubStrLen\r
-  )\r
-{\r
-  UINTN Index;\r
-  for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {\r
-    SubStr[Index] = Str[Index];\r
-  }\r
-\r
-  SubStr[Index] = L'\0';\r
-  *SubStrLen = Index;\r
-}\r
-\r
-/**\r
-  This routine pad the string in tail with input character.\r
-\r
-  @param[in]   StrBuf            Str buffer to be padded, should be enough room for\r
-  @param[in]   PadLen            Expected padding length\r
-  @param[in]   Character         Character used to pad\r
-\r
-**/\r
-static\r
-VOID\r
-PadStrInTail (\r
-  IN CHAR16   *StrBuf,\r
-  IN UINTN    PadLen,\r
-  IN CHAR16   Character\r
-  )\r
-{\r
-  UINTN Index;\r
-\r
-  for (Index = 0; StrBuf[Index] != L'\0'; Index++);\r
-\r
-  while(PadLen != 0) {\r
-    StrBuf[Index] = Character;\r
-    Index++;\r
-    PadLen--;\r
-  }\r
-\r
-  StrBuf[Index] = L'\0';\r
-}\r
-\r
-/**\r
-  This routine find the offset of the last period '.' of string. If No period exists\r
-  function FileNameExtension is set to L'\0'\r
-\r
-  @param[in]  FileName           File name to split between last period\r
-  @param[out] FileNameFirst      First FileName before last period\r
-  @param[out] FileNameExtension  FileName after last period\r
-\r
-**/\r
-static\r
-VOID\r
-SplitFileNameExtension (\r
-  IN CHAR16   *FileName,\r
-  OUT CHAR16  *FileNameFirst,\r
-  OUT CHAR16  *FileNameExtension\r
-  )\r
-{\r
-  UINTN Index;\r
-  UINTN StringLen;\r
-\r
-  StringLen = StrnLenS(FileName, MAX_FILE_NAME_SIZE);\r
-  for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--);\r
-\r
-  //\r
-  // No period exists. No FileName Extension\r
-  //\r
-  if (Index == 0 && FileName[Index] != L'.') {\r
-    FileNameExtension[0] = L'\0';\r
-    Index = StringLen;\r
-  } else {\r
-    StrCpyS(FileNameExtension, MAX_FILE_NAME_SIZE, &FileName[Index+1]);\r
-  }\r
-\r
-  //\r
-  // Copy First file name\r
-  //\r
-  StrnCpyS(FileNameFirst, MAX_FILE_NAME_SIZE, FileName, Index);\r
-  FileNameFirst[Index] = L'\0';\r
-}\r
-\r
-/**\r
-  This routine is called to get all boot options in the order determnined by:\r
-    1. "OptionBuf"\r
-    2. "BootOrder"\r
-\r
-  @param[out] OptionBuf           BootList buffer to all boot options returned\r
-  @param[out] OptionCount         BootList count of all boot options returned\r
-\r
-  @retval EFI_SUCCESS             There is no error when processing capsule\r
-\r
-**/\r
-EFI_STATUS\r
-GetBootOptionInOrder(\r
-  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf,\r
-  OUT UINTN                        *OptionCount\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  UINTN                        DataSize;\r
-  UINT16                       BootNext;\r
-  CHAR16                       BootOptionName[20];\r
-  EFI_BOOT_MANAGER_LOAD_OPTION *BootOrderOptionBuf;\r
-  UINTN                        BootOrderCount;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry;\r
-  UINTN                        BootNextCount;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION *TempBuf;\r
-\r
-  BootOrderOptionBuf  = NULL;\r
-  TempBuf             = NULL;\r
-  BootNextCount       = 0;\r
-  BootOrderCount      = 0;\r
-  *OptionBuf          = NULL;\r
-  *OptionCount        = 0;\r
-\r
-  //\r
-  // First Get BootOption from "BootNext"\r
-  //\r
-  DataSize = sizeof(BootNext);\r
-  Status = gRT->GetVariable (\r
-                  EFI_BOOT_NEXT_VARIABLE_NAME,\r
-                  &gEfiGlobalVariableGuid,\r
-                  NULL,\r
-                  &DataSize,\r
-                  (VOID *)&BootNext\r
-                  );\r
-  //\r
-  // BootNext variable is a single UINT16\r
-  //\r
-  if (!EFI_ERROR(Status) && DataSize == sizeof(UINT16)) {\r
-    //\r
-    // Add the boot next boot option\r
-    //\r
-    UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", BootNext);\r
-    ZeroMem(&BootNextOptionEntry, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));\r
-    Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry);\r
-\r
-    if (!EFI_ERROR(Status)) {\r
-      BootNextCount = 1;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Second get BootOption from "BootOrder"\r
-  //\r
-  BootOrderOptionBuf = EfiBootManagerGetLoadOptions (&BootOrderCount, LoadOptionTypeBoot);\r
-  if (BootNextCount == 0 && BootOrderCount == 0) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // At least one BootOption is found\r
-  //\r
-  TempBuf = AllocatePool(sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * (BootNextCount + BootOrderCount));\r
-  if (TempBuf != NULL) {\r
-    if (BootNextCount == 1) {\r
-      CopyMem(TempBuf, &BootNextOptionEntry, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));\r
-    }\r
-\r
-    if (BootOrderCount > 0) {\r
-      CopyMem(TempBuf + BootNextCount, BootOrderOptionBuf, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * BootOrderCount);\r
-    }\r
-\r
-    *OptionBuf   = TempBuf;\r
-    *OptionCount = BootNextCount + BootOrderCount;\r
-    Status = EFI_SUCCESS;\r
-  } else {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  FreePool(BootOrderOptionBuf);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  This routine is called to get boot option by OptionNumber.\r
-\r
-  @param[in] Number               The OptionNumber of boot option\r
-  @param[out] OptionBuf           BootList buffer to all boot options returned\r
-\r
-  @retval EFI_SUCCESS             There is no error when getting boot option\r
-\r
-**/\r
-EFI_STATUS\r
-GetBootOptionByNumber(\r
-  IN  UINT16                       Number,\r
-  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  CHAR16                        BootOptionName[20];\r
-  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;\r
-\r
-  UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", Number);\r
-  ZeroMem (&BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));\r
-  Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootOption);\r
-\r
-  if (!EFI_ERROR (Status)) {\r
-    *OptionBuf = AllocatePool (sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));\r
-    CopyMem (*OptionBuf, &BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Get Active EFI System Partition within GPT based on device path.\r
-\r
-  @param[in] DevicePath    Device path to find a active EFI System Partition\r
-  @param[out] FsHandle     BootList points to all boot options returned\r
-\r
-  @retval EFI_SUCCESS      Active EFI System Partition is succesfully found\r
-  @retval EFI_NOT_FOUND    No Active EFI System Partition is found\r
-\r
-**/\r
-EFI_STATUS\r
-GetEfiSysPartitionFromDevPath(\r
-  IN EFI_DEVICE_PATH_PROTOCOL         *DevicePath,\r
-  OUT EFI_HANDLE                      *FsHandle\r
-  )\r
-{\r
-  EFI_STATUS                      Status;\r
-  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;\r
-  HARDDRIVE_DEVICE_PATH           *Hd;\r
-  EFI_HANDLE                      Handle;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;\r
-\r
-  //\r
-  // Check if the device path contains GPT node\r
-  //\r
-  TempDevicePath = DevicePath;\r
-  while (!IsDevicePathEnd (TempDevicePath)) {\r
-    if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&\r
-       (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP)) {\r
-      Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;\r
-      if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {\r
-        break;\r
-      }\r
-    }\r
-    TempDevicePath = NextDevicePathNode (TempDevicePath);\r
-  }\r
-\r
-  if (!IsDevicePathEnd (TempDevicePath)) {\r
-    //\r
-    // Search for EFI system partition protocol on full device path in Boot Option\r
-    //\r
-    Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, &DevicePath, &Handle);\r
-\r
-    //\r
-    // Search for simple file system on this handler\r
-    //\r
-    if (!EFI_ERROR(Status)) {\r
-      Status = gBS->HandleProtocol(Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);\r
-      if (!EFI_ERROR(Status)) {\r
-        *FsHandle = Handle;\r
-        return EFI_SUCCESS;\r
-      }\r
-    }\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  This routine is called to get Simple File System protocol on the first EFI system partition found in\r
-  active boot option. The boot option list is detemined in order by\r
-    1. "BootNext"\r
-    2. "BootOrder"\r
-\r
-  @param[in]       MaxRetry           Max Connection Retry. Stall 100ms between each connection try to ensure\r
-                                      device like USB can get enumerated.\r
-  @param[in, out]  LoadOptionNumber   On input, specify the boot option to get EFI system partition.\r
-                                      On output, return the OptionNumber of the boot option where EFI\r
-                                      system partition is got from.\r
-  @param[out]      FsFsHandle         Simple File System Protocol found on first active EFI system partition\r
-\r
-  @retval EFI_SUCCESS     Simple File System protocol found for EFI system partition\r
-  @retval EFI_NOT_FOUND   No Simple File System protocol found for EFI system partition\r
-\r
-**/\r
-EFI_STATUS\r
-GetEfiSysPartitionFromActiveBootOption(\r
-  IN UINTN                             MaxRetry,\r
-  IN OUT UINT16                        **LoadOptionNumber,\r
-  OUT EFI_HANDLE                       *FsHandle\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuf;\r
-  UINTN                        BootOptionNum;\r
-  UINTN                        Index;\r
-  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;\r
-  EFI_DEVICE_PATH_PROTOCOL     *CurFullPath;\r
-  EFI_DEVICE_PATH_PROTOCOL     *PreFullPath;\r
-\r
-  *FsHandle = NULL;\r
-\r
-  if (*LoadOptionNumber != NULL) {\r
-    BootOptionNum = 1;\r
-    Status = GetBootOptionByNumber(**LoadOptionNumber, &BootOptionBuf);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG ((DEBUG_ERROR, "GetBootOptionByIndex Failed %x! No BootOption available for connection\n", Status));\r
-      return Status;\r
-    }\r
-  } else {\r
-    Status = GetBootOptionInOrder(&BootOptionBuf, &BootOptionNum);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG ((DEBUG_ERROR, "GetBootOptionInOrder Failed %x! No BootOption available for connection\n", Status));\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Search BootOptionList to check if it is an active boot option with EFI system partition\r
-  //  1. Connect device path\r
-  //  2. expend short/plug in devicepath\r
-  //  3. LoadImage\r
-  //\r
-  for (Index = 0; Index < BootOptionNum; Index++) {\r
-    //\r
-    // Get the boot option from the link list\r
-    //\r
-    DevicePath  = BootOptionBuf[Index].FilePath;\r
-\r
-    //\r
-    // Skip inactive or legacy boot options\r
-    //\r
-    if ((BootOptionBuf[Index].Attributes & LOAD_OPTION_ACTIVE) == 0 ||\r
-        DevicePathType (DevicePath) == BBS_DEVICE_PATH) {\r
-      continue;\r
-    }\r
-\r
-    DEBUG_CODE (\r
-      CHAR16 *DevicePathStr;\r
-\r
-      DevicePathStr = ConvertDevicePathToText(DevicePath, TRUE, TRUE);\r
-      if (DevicePathStr != NULL){\r
-        DEBUG((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr));\r
-        FreePool(DevicePathStr);\r
-      } else {\r
-        DEBUG((DEBUG_INFO, "DevicePathToStr failed\n"));\r
-      }\r
-    );\r
-\r
-    CurFullPath = NULL;\r
-    //\r
-    // Try every full device Path generated from bootoption\r
-    //\r
-    do {\r
-      PreFullPath = CurFullPath;\r
-      CurFullPath = EfiBootManagerGetNextLoadOptionDevicePath(DevicePath, CurFullPath);\r
-\r
-      if (PreFullPath != NULL) {\r
-        FreePool (PreFullPath);\r
-      }\r
-\r
-      if (CurFullPath == NULL) {\r
-        //\r
-        // No Active EFI system partition is found in BootOption device path\r
-        //\r
-        Status = EFI_NOT_FOUND;\r
-        break;\r
-      }\r
-\r
-      DEBUG_CODE (\r
-        CHAR16 *DevicePathStr1;\r
-\r
-        DevicePathStr1 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);\r
-        if (DevicePathStr1 != NULL){\r
-          DEBUG((DEBUG_INFO, "Full device path %s\n", DevicePathStr1));\r
-          FreePool(DevicePathStr1);\r
-        }\r
-      );\r
-\r
-      //\r
-      // Make sure the boot option device path connected.\r
-      // Only handle first device in boot option. Other optional device paths are described as OSV specific\r
-      // FullDevice could contain extra directory & file info. So don't check connection status here.\r
-      //\r
-      EfiBootManagerConnectDevicePath (CurFullPath, NULL);\r
-      Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);\r
-\r
-      //\r
-      // Some relocation device like USB need more time to get enumerated\r
-      //\r
-      while (EFI_ERROR(Status) && MaxRetry > 0) {\r
-        EfiBootManagerConnectDevicePath(CurFullPath, NULL);\r
-\r
-        //\r
-        // Search for EFI system partition protocol on full device path in Boot Option\r
-        //\r
-        Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);\r
-        if (!EFI_ERROR(Status)) {\r
-          break;\r
-        }\r
-        DEBUG((DEBUG_ERROR, "GetEfiSysPartitionFromDevPath Loop %x\n", Status));\r
-        //\r
-        // Stall 100ms if connection failed to ensure USB stack is ready\r
-        //\r
-        gBS->Stall(100000);\r
-        MaxRetry --;\r
-      }\r
-    } while(EFI_ERROR(Status));\r
-\r
-    //\r
-    // Find a qualified Simple File System\r
-    //\r
-    if (!EFI_ERROR(Status)) {\r
-      break;\r
-    }\r
-\r
-  }\r
-\r
-  //\r
-  // Return the OptionNumber of the boot option where EFI system partition is got from\r
-  //\r
-  if (*LoadOptionNumber == NULL) {\r
-    *LoadOptionNumber = AllocateCopyPool (sizeof(UINT16), (UINT16 *) &BootOptionBuf[Index].OptionNumber);\r
-  }\r
-\r
-  //\r
-  // No qualified EFI system partition found\r
-  //\r
-  if (*FsHandle == NULL) {\r
-    Status = EFI_NOT_FOUND;\r
-  }\r
-\r
-  DEBUG_CODE (\r
-    CHAR16 *DevicePathStr2;\r
-    if (*FsHandle != NULL) {\r
-      DevicePathStr2 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);\r
-      if (DevicePathStr2 != NULL){\r
-        DEBUG((DEBUG_INFO, "Found Active EFI System Partion on %s\n", DevicePathStr2));\r
-        FreePool(DevicePathStr2);\r
-      }\r
-    } else {\r
-      DEBUG((DEBUG_INFO, "Failed to found Active EFI System Partion\n"));\r
-    }\r
-  );\r
-\r
-  if (CurFullPath != NULL) {\r
-    FreePool(CurFullPath);\r
-  }\r
-\r
-  //\r
-  // Free BootOption Buffer\r
-  //\r
-  for (Index = 0; Index < BootOptionNum; Index++) {\r
-    if (BootOptionBuf[Index].Description != NULL) {\r
-      FreePool(BootOptionBuf[Index].Description);\r
-    }\r
-\r
-    if (BootOptionBuf[Index].FilePath != NULL) {\r
-      FreePool(BootOptionBuf[Index].FilePath);\r
-    }\r
-\r
-    if (BootOptionBuf[Index].OptionalData != NULL) {\r
-      FreePool(BootOptionBuf[Index].OptionalData);\r
-    }\r
-  }\r
-\r
-  FreePool(BootOptionBuf);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  This routine is called to get all file infos with in a given dir & with given file attribute, the file info is listed in\r
-  alphabetical order described in UEFI spec.\r
-\r
-  @param[in]  Dir                 Directory file handler\r
-  @param[in]  FileAttr            Attribute of file to be red from directory\r
-  @param[out] FileInfoList        File images info list red from directory\r
-  @param[out] FileNum             File images number red from directory\r
-\r
-  @retval EFI_SUCCESS             File FileInfo list in the given\r
-\r
-**/\r
-EFI_STATUS\r
-GetFileInfoListInAlphabetFromDir(\r
-  IN EFI_FILE_HANDLE  Dir,\r
-  IN UINT64           FileAttr,\r
-  OUT LIST_ENTRY      *FileInfoList,\r
-  OUT UINTN           *FileNum\r
-  )\r
-{\r
-  EFI_STATUS        Status;\r
-  FILE_INFO_ENTRY   *NewFileInfoEntry;\r
-  FILE_INFO_ENTRY   *TempFileInfoEntry;\r
-  EFI_FILE_INFO     *FileInfo;\r
-  CHAR16            *NewFileName;\r
-  CHAR16            *ListedFileName;\r
-  CHAR16            *NewFileNameExtension;\r
-  CHAR16            *ListedFileNameExtension;\r
-  CHAR16            *TempNewSubStr;\r
-  CHAR16            *TempListedSubStr;\r
-  LIST_ENTRY        *Link;\r
-  BOOLEAN           NoFile;\r
-  UINTN             FileCount;\r
-  UINTN             IndexNew;\r
-  UINTN             IndexListed;\r
-  UINTN             NewSubStrLen;\r
-  UINTN             ListedSubStrLen;\r
-  INTN              SubStrCmpResult;\r
-\r
-  Status                  = EFI_SUCCESS;\r
-  NewFileName             = NULL;\r
-  ListedFileName          = NULL;\r
-  NewFileNameExtension    = NULL;\r
-  ListedFileNameExtension = NULL;\r
-  TempNewSubStr           = NULL;\r
-  TempListedSubStr        = NULL;\r
-  NoFile                  = FALSE;\r
-  FileCount               = 0;\r
-\r
-  InitializeListHead(FileInfoList);\r
-\r
-  TempNewSubStr           = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);\r
-  TempListedSubStr        = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);\r
-\r
-  if (TempNewSubStr == NULL || TempListedSubStr == NULL ) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto EXIT;\r
-  }\r
-\r
-  for ( Status = FileHandleFindFirstFile(Dir, &FileInfo)\r
-      ; !EFI_ERROR(Status) && !NoFile\r
-      ; Status = FileHandleFindNextFile(Dir, FileInfo, &NoFile)\r
-     ){\r
-\r
-    //\r
-    // Skip file with mismatching File attribute\r
-    //\r
-    if ((FileInfo->Attribute & (FileAttr)) == 0) {\r
-      continue;\r
-    }\r
-\r
-    NewFileInfoEntry = NULL;\r
-    NewFileInfoEntry = (FILE_INFO_ENTRY*)AllocateZeroPool(sizeof(FILE_INFO_ENTRY));\r
-    if (NewFileInfoEntry == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto EXIT;\r
-    }\r
-    NewFileInfoEntry->Signature = FILE_INFO_SIGNATURE;\r
-    NewFileInfoEntry->FileInfo  = AllocateCopyPool((UINTN) FileInfo->Size, FileInfo);\r
-    if (NewFileInfoEntry->FileInfo == NULL) {\r
-      FreePool(NewFileInfoEntry);\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto EXIT;\r
-    }\r
-\r
-    NewFileInfoEntry->FileNameFirstPart  = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);\r
-    if (NewFileInfoEntry->FileNameFirstPart == NULL) {\r
-      FreePool(NewFileInfoEntry->FileInfo);\r
-      FreePool(NewFileInfoEntry);\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto EXIT;\r
-    }\r
-    NewFileInfoEntry->FileNameSecondPart = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);\r
-    if (NewFileInfoEntry->FileNameSecondPart == NULL) {\r
-      FreePool(NewFileInfoEntry->FileInfo);\r
-      FreePool(NewFileInfoEntry->FileNameFirstPart);\r
-      FreePool(NewFileInfoEntry);\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto EXIT;\r
-    }\r
-\r
-    //\r
-    // Splitter the whole New file name into 2 parts between the last period L'.' into NewFileName NewFileExtension\r
-    // If no period in the whole file name. NewFileExtension is set to L'\0'\r
-    //\r
-    NewFileName          = NewFileInfoEntry->FileNameFirstPart;\r
-    NewFileNameExtension = NewFileInfoEntry->FileNameSecondPart;\r
-    SplitFileNameExtension(FileInfo->FileName, NewFileName, NewFileNameExtension);\r
-    UpperCaseString(NewFileName);\r
-    UpperCaseString(NewFileNameExtension);\r
-\r
-    //\r
-    // Insert capsule file in alphabetical ordered list\r
-    //\r
-    for (Link = FileInfoList->ForwardLink; Link != FileInfoList; Link = Link->ForwardLink) {\r
-      //\r
-      // Get the FileInfo from the link list\r
-      //\r
-      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);\r
-      ListedFileName          = TempFileInfoEntry->FileNameFirstPart;\r
-      ListedFileNameExtension = TempFileInfoEntry->FileNameSecondPart;\r
-\r
-      //\r
-      // Follow rule in UEFI spec 8.5.5 to compare file name\r
-      //\r
-      IndexListed = 0;\r
-      IndexNew    = 0;\r
-      while (TRUE){\r
-        //\r
-        // First compare each substrings in NewFileName & ListedFileName between periods\r
-        //\r
-        GetSubStringBeforePeriod(&NewFileName[IndexNew], TempNewSubStr, &NewSubStrLen);\r
-        GetSubStringBeforePeriod(&ListedFileName[IndexListed], TempListedSubStr, &ListedSubStrLen);\r
-        if (NewSubStrLen > ListedSubStrLen) {\r
-          //\r
-          // Substr in NewFileName is longer. Pad tail with SPACE\r
-          //\r
-          PadStrInTail(TempListedSubStr, NewSubStrLen - ListedSubStrLen, L' ');\r
-        } else if (NewSubStrLen < ListedSubStrLen){\r
-          //\r
-          // Substr in ListedFileName is longer. Pad tail with SPACE\r
-          //\r
-          PadStrInTail(TempNewSubStr, ListedSubStrLen - NewSubStrLen, L' ');\r
-        }\r
-\r
-        SubStrCmpResult = StrnCmp(TempNewSubStr, TempListedSubStr, MAX_FILE_NAME_LEN);\r
-        if (SubStrCmpResult != 0) {\r
-          break;\r
-        }\r
-\r
-        //\r
-        // Move to skip this substring\r
-        //\r
-        IndexNew    += NewSubStrLen;\r
-        IndexListed += ListedSubStrLen;\r
-        //\r
-        // Reach File First Name end\r
-        //\r
-        if (NewFileName[IndexNew] == L'\0' || ListedFileName[IndexListed] == L'\0') {\r
-          break;\r
-        }\r
-\r
-        //\r
-        // Skip the period L'.'\r
-        //\r
-        IndexNew++;\r
-        IndexListed++;\r
-      }\r
-\r
-      if (SubStrCmpResult < 0) {\r
-        //\r
-        // NewFileName is smaller. Find the right place to insert New file\r
-        //\r
-        break;\r
-      } else if (SubStrCmpResult == 0) {\r
-        //\r
-        // 2 cases whole NewFileName is smaller than ListedFileName\r
-        //   1. if NewFileName == ListedFileName. Continue to compare FileNameExtension\r
-        //   2. if NewFileName is shorter than ListedFileName\r
-        //\r
-        if (NewFileName[IndexNew] == L'\0') {\r
-          if (ListedFileName[IndexListed] != L'\0' || (StrnCmp(NewFileNameExtension, ListedFileNameExtension, MAX_FILE_NAME_LEN) < 0)) {\r
-            break;\r
-          }\r
-        }\r
-      }\r
-\r
-      //\r
-      // Other case, ListedFileName is smaller. Continue to compare the next file in the list\r
-      //\r
-    }\r
-\r
-    //\r
-    // If Find an entry in the list whose name is bigger than new FileInfo in alphabet order\r
-    //    Insert it before this entry\r
-    // else\r
-    //    Insert at the tail of this list (Link = FileInfoList)\r
-    //\r
-    InsertTailList(Link, &NewFileInfoEntry->Link);\r
-\r
-    FileCount++;\r
-  }\r
-\r
-  *FileNum = FileCount;\r
-\r
-EXIT:\r
-\r
-  if (TempNewSubStr != NULL) {\r
-    FreePool(TempNewSubStr);\r
-  }\r
-\r
-  if (TempListedSubStr != NULL) {\r
-    FreePool(TempListedSubStr);\r
-  }\r
-\r
-  if (EFI_ERROR(Status)) {\r
-    while(!IsListEmpty(FileInfoList)) {\r
-      Link = FileInfoList->ForwardLink;\r
-      RemoveEntryList(Link);\r
-\r
-      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);\r
-\r
-      FreePool(TempFileInfoEntry->FileInfo);\r
-      FreePool(TempFileInfoEntry->FileNameFirstPart);\r
-      FreePool(TempFileInfoEntry->FileNameSecondPart);\r
-      FreePool(TempFileInfoEntry);\r
-    }\r
-    *FileNum = 0;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  This routine is called to get all qualified image from file from an given directory\r
-  in alphabetic order. All the file image is copied to allocated boottime memory.\r
-  Caller should free these memory\r
-\r
-  @param[in]  Dir            Directory file handler\r
-  @param[in]  FileAttr       Attribute of file to be red from directory\r
-  @param[out] FilePtr        File images Info buffer red from directory\r
-  @param[out] FileNum        File images number red from directory\r
-\r
-  @retval EFI_SUCCESS  Succeed to get all capsules in alphabetic order.\r
-\r
-**/\r
-EFI_STATUS\r
-GetFileImageInAlphabetFromDir(\r
-  IN EFI_FILE_HANDLE   Dir,\r
-  IN UINT64            FileAttr,\r
-  OUT IMAGE_INFO       **FilePtr,\r
-  OUT UINTN            *FileNum\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  LIST_ENTRY            *Link;\r
-  EFI_FILE_HANDLE       FileHandle;\r
-  FILE_INFO_ENTRY       *FileInfoEntry;\r
-  EFI_FILE_INFO         *FileInfo;\r
-  UINTN                 FileCount;\r
-  IMAGE_INFO            *TempFilePtrBuf;\r
-  UINTN                 Size;\r
-  LIST_ENTRY            FileInfoList;\r
-\r
-  FileHandle       = NULL;\r
-  FileCount        = 0;\r
-  TempFilePtrBuf   = NULL;\r
-  *FilePtr         = NULL;\r
-\r
-  //\r
-  // Get file list in Dir in alphabetical order\r
-  //\r
-  Status = GetFileInfoListInAlphabetFromDir(\r
-             Dir,\r
-             FileAttr,\r
-             &FileInfoList,\r
-             &FileCount\r
-             );\r
-  if (EFI_ERROR(Status)) {\r
-    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n"));\r
-    goto EXIT;\r
-  }\r
-\r
-  if (FileCount == 0) {\r
-    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));\r
-    Status = EFI_NOT_FOUND;\r
-    goto EXIT;\r
-  }\r
-\r
-  TempFilePtrBuf = (IMAGE_INFO *)AllocateZeroPool(sizeof(IMAGE_INFO) * FileCount);\r
-  if (TempFilePtrBuf == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Read all files from FileInfoList to BS memory\r
-  //\r
-  FileCount = 0;\r
-  for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link->ForwardLink) {\r
-    //\r
-    // Get FileInfo from the link list\r
-    //\r
-    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);\r
-    FileInfo      = FileInfoEntry->FileInfo;\r
-\r
-    Status = Dir->Open(\r
-                    Dir,\r
-                    &FileHandle,\r
-                    FileInfo->FileName,\r
-                    EFI_FILE_MODE_READ,\r
-                    0\r
-                    );\r
-    if (EFI_ERROR(Status)){\r
-      continue;\r
-    }\r
-\r
-    Size = (UINTN)FileInfo->FileSize;\r
-    TempFilePtrBuf[FileCount].ImageAddress = AllocateZeroPool(Size);\r
-    if (TempFilePtrBuf[FileCount].ImageAddress == NULL) {\r
-      DEBUG((DEBUG_ERROR, "Fail to allocate memory for capsule. Stop processing the rest.\n"));\r
-      break;\r
-    }\r
-\r
-    Status = FileHandle->Read(\r
-                           FileHandle,\r
-                           &Size,\r
-                           TempFilePtrBuf[FileCount].ImageAddress\r
-                           );\r
-\r
-    FileHandle->Close(FileHandle);\r
-\r
-    //\r
-    // Skip read error file\r
-    //\r
-    if (EFI_ERROR(Status) || Size != (UINTN)FileInfo->FileSize) {\r
-      //\r
-      // Remove this error file info accordingly\r
-      // & move Link to BackLink\r
-      //\r
-      Link = RemoveEntryList(Link);\r
-      Link = Link->BackLink;\r
-\r
-      FreePool(FileInfoEntry->FileInfo);\r
-      FreePool(FileInfoEntry->FileNameFirstPart);\r
-      FreePool(FileInfoEntry->FileNameSecondPart);\r
-      FreePool(FileInfoEntry);\r
-\r
-      FreePool(TempFilePtrBuf[FileCount].ImageAddress);\r
-      TempFilePtrBuf[FileCount].ImageAddress = NULL;\r
-      TempFilePtrBuf[FileCount].FileInfo     = NULL;\r
-\r
-      continue;\r
-    }\r
-    TempFilePtrBuf[FileCount].FileInfo = FileInfo;\r
-    FileCount++;\r
-  }\r
-\r
-  DEBUG_CODE (\r
-    for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link->ForwardLink) {\r
-      FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);\r
-      FileInfo      = FileInfoEntry->FileInfo;\r
-      DEBUG((DEBUG_INFO, "Successfully read capsule file %s from disk.\n", FileInfo->FileName));\r
-    }\r
-  );\r
-\r
-EXIT:\r
-\r
-  *FilePtr = TempFilePtrBuf;\r
-  *FileNum = FileCount;\r
-\r
-  //\r
-  // FileInfo will be freed by Calller\r
-  //\r
-  while(!IsListEmpty(&FileInfoList)) {\r
-    Link = FileInfoList.ForwardLink;\r
-    RemoveEntryList(Link);\r
-\r
-    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);\r
-\r
-    FreePool(FileInfoEntry->FileNameFirstPart);\r
-    FreePool(FileInfoEntry->FileNameSecondPart);\r
-    FreePool(FileInfoEntry);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  This routine is called to remove all qualified image from file from an given directory.\r
-\r
-  @param[in] Dir                  Directory file handler\r
-  @param[in] FileAttr             Attribute of files to be deleted\r
-\r
-  @retval EFI_SUCCESS  Succeed to remove all files from an given directory.\r
-\r
-**/\r
-EFI_STATUS\r
-RemoveFileFromDir(\r
-  IN EFI_FILE_HANDLE   Dir,\r
-  IN UINT64            FileAttr\r
-  )\r
-{\r
-  EFI_STATUS        Status;\r
-  LIST_ENTRY        *Link;\r
-  LIST_ENTRY        FileInfoList;\r
-  EFI_FILE_HANDLE   FileHandle;\r
-  FILE_INFO_ENTRY   *FileInfoEntry;\r
-  EFI_FILE_INFO     *FileInfo;\r
-  UINTN             FileCount;\r
-\r
-  FileHandle = NULL;\r
-\r
-  //\r
-  // Get file list in Dir in alphabetical order\r
-  //\r
-  Status = GetFileInfoListInAlphabetFromDir(\r
-             Dir,\r
-             FileAttr,\r
-             &FileInfoList,\r
-             &FileCount\r
-             );\r
-  if (EFI_ERROR(Status)) {\r
-    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n"));\r
-    goto EXIT;\r
-  }\r
-\r
-  if (FileCount == 0) {\r
-    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));\r
-    Status = EFI_NOT_FOUND;\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Delete all files with given attribute in Dir\r
-  //\r
-  for (Link = FileInfoList.ForwardLink; Link != &(FileInfoList); Link = Link->ForwardLink) {\r
-    //\r
-    // Get FileInfo from the link list\r
-    //\r
-    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);\r
-    FileInfo      = FileInfoEntry->FileInfo;\r
-\r
-    Status = Dir->Open(\r
-                    Dir,\r
-                    &FileHandle,\r
-                    FileInfo->FileName,\r
-                    EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,\r
-                    0\r
-                    );\r
-    if (EFI_ERROR(Status)){\r
-      continue;\r
-    }\r
-\r
-    Status = FileHandle->Delete(FileHandle);\r
-  }\r
-\r
-EXIT:\r
-\r
-  while(!IsListEmpty(&FileInfoList)) {\r
-    Link = FileInfoList.ForwardLink;\r
-    RemoveEntryList(Link);\r
-\r
-    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);\r
-\r
-    FreePool(FileInfoEntry->FileInfo);\r
-    FreePool(FileInfoEntry);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  This routine is called to get all caspules from file. The capsule file image is\r
-  copied to BS memory. Caller is responsible to free them.\r
-\r
-  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure\r
-                                     devices like USB can get enumerated.\r
-  @param[out]   CapsulePtr           Copied Capsule file Image Info buffer\r
-  @param[out]   CapsuleNum           CapsuleNumber\r
-  @param[out]   FsHandle             File system handle\r
-  @param[out]   LoadOptionNumber     OptionNumber of boot option\r
-\r
-  @retval EFI_SUCCESS  Succeed to get all capsules.\r
-\r
-**/\r
-EFI_STATUS\r
-GetAllCapsuleOnDisk(\r
-  IN  UINTN                            MaxRetry,\r
-  OUT IMAGE_INFO                       **CapsulePtr,\r
-  OUT UINTN                            *CapsuleNum,\r
-  OUT EFI_HANDLE                       *FsHandle,\r
-  OUT UINT16                            *LoadOptionNumber\r
-  )\r
-{\r
-  EFI_STATUS                       Status;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;\r
-  EFI_FILE_HANDLE                  RootDir;\r
-  EFI_FILE_HANDLE                  FileDir;\r
-  UINT16                           *TempOptionNumber;\r
-\r
-  Fs               = NULL;\r
-  RootDir          = NULL;\r
-  FileDir          = NULL;\r
-  TempOptionNumber = NULL;\r
-  *CapsuleNum      = 0;\r
-\r
-  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry, &TempOptionNumber, FsHandle);\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = gBS->HandleProtocol(*FsHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = Fs->OpenVolume(Fs, &RootDir);\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = RootDir->Open(\r
-                      RootDir,\r
-                      &FileDir,\r
-                      EFI_CAPSULE_FILE_DIRECTORY,\r
-                      EFI_FILE_MODE_READ,\r
-                      0\r
-                      );\r
-  if (EFI_ERROR(Status)) {\r
-    DEBUG((DEBUG_ERROR, "CodLibGetAllCapsuleOnDisk fail to open RootDir!\n"));\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Only Load files with EFI_FILE_SYSTEM or EFI_FILE_ARCHIVE attribute\r
-  // ignore EFI_FILE_READ_ONLY, EFI_FILE_HIDDEN, EFI_FILE_RESERVED, EFI_FILE_DIRECTORY\r
-  //\r
-  Status = GetFileImageInAlphabetFromDir(\r
-             FileDir,\r
-             EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE,\r
-             CapsulePtr,\r
-             CapsuleNum\r
-             );\r
-  DEBUG((DEBUG_INFO, "GetFileImageInAlphabetFromDir status %x\n", Status));\r
-\r
-  //\r
-  // Always remove file to avoid deadloop in capsule process\r
-  //\r
-  Status = RemoveFileFromDir(FileDir, EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE);\r
-  DEBUG((DEBUG_INFO, "RemoveFileFromDir status %x\n", Status));\r
-\r
-  if (LoadOptionNumber != NULL) {\r
-    *LoadOptionNumber = *TempOptionNumber;\r
-  }\r
-\r
-EXIT:\r
-\r
-  if (FileDir != NULL) {\r
-    FileDir->Close (FileDir);\r
-  }\r
-\r
-  if (RootDir != NULL) {\r
-    RootDir->Close (RootDir);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Build Gather list for a list of capsule images.\r
-\r
-  @param[in]  CapsuleBuffer    An array of pointer to capsule images\r
-  @param[in]  CapsuleSize      An array of UINTN to capsule images size\r
-  @param[in]  CapsuleNum       The count of capsule images\r
-  @param[out] BlockDescriptors The block descriptors for the capsule images\r
-\r
-  @retval EFI_SUCCESS The block descriptors for the capsule images are constructed.\r
-\r
-**/\r
-EFI_STATUS\r
-BuildGatherList (\r
-  IN VOID                          **CapsuleBuffer,\r
-  IN UINTN                         *CapsuleSize,\r
-  IN UINTN                         CapsuleNum,\r
-  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;\r
-  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;\r
-  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;\r
-  UINTN                         Index;\r
-\r
-  BlockDescriptors1      = NULL;\r
-  BlockDescriptorPre     = NULL;\r
-  BlockDescriptorsHeader = NULL;\r
-\r
-  for (Index = 0; Index < CapsuleNum; Index++) {\r
-    //\r
-    // Allocate memory for the descriptors.\r
-    //\r
-    BlockDescriptors1  = AllocateZeroPool (2 * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR));\r
-    if (BlockDescriptors1 == NULL) {\r
-      DEBUG ((DEBUG_ERROR, "BuildGatherList: failed to allocate memory for descriptors\n"));\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto ERREXIT;\r
-    } else {\r
-      DEBUG ((DEBUG_INFO, "BuildGatherList: creating capsule descriptors at 0x%X\n", (UINTN) BlockDescriptors1));\r
-    }\r
-\r
-    //\r
-    // Record descirptor header\r
-    //\r
-    if (Index == 0) {\r
-      BlockDescriptorsHeader = BlockDescriptors1;\r
-    }\r
-\r
-    if (BlockDescriptorPre != NULL) {\r
-      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;\r
-      BlockDescriptorPre->Length = 0;\r
-    }\r
-\r
-    BlockDescriptors1->Union.DataBlock = (UINTN) CapsuleBuffer[Index];\r
-    BlockDescriptors1->Length = CapsuleSize[Index];\r
-\r
-    BlockDescriptorPre = BlockDescriptors1 + 1;\r
-    BlockDescriptors1 = NULL;\r
-  }\r
-\r
-  //\r
-  // Null-terminate.\r
-  //\r
-  if (BlockDescriptorPre != NULL) {\r
-    BlockDescriptorPre->Union.ContinuationPointer = (UINTN)NULL;\r
-    BlockDescriptorPre->Length = 0;\r
-    *BlockDescriptors = BlockDescriptorsHeader;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-\r
-ERREXIT:\r
-  if (BlockDescriptors1 != NULL) {\r
-    FreePool (BlockDescriptors1);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  This routine is called to check if CapsuleOnDisk flag in OsIndications Variable\r
-  is enabled.\r
-\r
-  @retval TRUE     Flag is enabled\r
-  @retval FALSE    Flag is not enabled\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-CoDCheckCapsuleOnDiskFlag(\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINT64                OsIndication;\r
-  UINTN                 DataSize;\r
-\r
-  //\r
-  // Check File Capsule Delivery Supported Flag in OsIndication variable\r
-  //\r
-  OsIndication = 0;\r
-  DataSize     = sizeof(UINT64);\r
-  Status = gRT->GetVariable (\r
-                  EFI_OS_INDICATIONS_VARIABLE_NAME,\r
-                  &gEfiGlobalVariableGuid,\r
-                  NULL,\r
-                  &DataSize,\r
-                  &OsIndication\r
-                  );\r
-  if (!EFI_ERROR(Status) &&\r
-      (OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0) {\r
-    return TRUE;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-\r
-/**\r
-  This routine is called to clear CapsuleOnDisk flags including OsIndications and BootNext variable.\r
-\r
-  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CoDClearCapsuleOnDiskFlag(\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINT64                OsIndication;\r
-  UINTN                 DataSize;\r
-\r
-  //\r
-  // Reset File Capsule Delivery Supported Flag in OsIndication variable\r
-  //\r
-  OsIndication = 0;\r
-  DataSize = sizeof(UINT64);\r
-  Status = gRT->GetVariable (\r
-                  EFI_OS_INDICATIONS_VARIABLE_NAME,\r
-                  &gEfiGlobalVariableGuid,\r
-                  NULL,\r
-                  &DataSize,\r
-                  &OsIndication\r
-                  );\r
-  if (EFI_ERROR(Status) ||\r
-      (OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) == 0) {\r
-    return Status;\r
-  }\r
-\r
-  OsIndication &= ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);\r
-  Status = gRT->SetVariable (\r
-                  EFI_OS_INDICATIONS_VARIABLE_NAME,\r
-                  &gEfiGlobalVariableGuid,\r
-                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
-                  sizeof(UINT64),\r
-                  &OsIndication\r
-                  );\r
-  ASSERT(!EFI_ERROR(Status));\r
-\r
-  //\r
-  // Delete BootNext variable. Capsule Process may reset system, so can't rely on Bds to clear this variable\r
-  //\r
-  Status = gRT->SetVariable (\r
-                  EFI_BOOT_NEXT_VARIABLE_NAME,\r
-                  &gEfiGlobalVariableGuid,\r
-                  0,\r
-                  0,\r
-                  NULL\r
-                  );\r
-  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This routine is called to clear CapsuleOnDisk Relocation Info variable.\r
-  Total Capsule On Disk length is recorded in this variable\r
-\r
-  @retval EFI_SUCCESS   Capsule On Disk flags are cleared\r
-\r
-**/\r
-EFI_STATUS\r
-CoDClearCapsuleRelocationInfo(\r
-  VOID\r
-  )\r
-{\r
-  return gRT->SetVariable (\r
-                COD_RELOCATION_INFO_VAR_NAME,\r
-                &gEfiCapsuleVendorGuid,\r
-                0,\r
-                0,\r
-                NULL\r
-                );\r
-}\r
-\r
-/**\r
-  Relocate Capsule on Disk from EFI system partition to a platform-specific NV storage device\r
-  with BlockIo protocol. Relocation device path, identified by PcdCodRelocationDevPath, must\r
-  be a full device path.\r
-  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.\r
-  Function will stall 100ms between each retry.\r
-\r
-  Side Effects:\r
-    Content corruption. Block IO write directly touches low level write. Orignal partitions, file systems\r
-    of the relocation device will be corrupted.\r
-\r
-  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure\r
-                                     devices like USB can get enumerated.\r
-\r
-  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated to the platform-specific device.\r
-\r
-**/\r
-EFI_STATUS\r
-RelocateCapsuleToDisk(\r
-  UINTN     MaxRetry\r
-  )\r
-{\r
-  EFI_STATUS                      Status;\r
-  UINTN                           CapsuleOnDiskNum;\r
-  UINTN                           Index;\r
-  UINTN                           DataSize;\r
-  UINT64                          TotalImageSize;\r
-  UINT64                          TotalImageNameSize;\r
-  IMAGE_INFO                      *CapsuleOnDiskBuf;\r
-  EFI_HANDLE                      Handle;\r
-  EFI_HANDLE                      TempHandle;\r
-  EFI_HANDLE                      *HandleBuffer;\r
-  UINTN                           NumberOfHandles;\r
-  EFI_BLOCK_IO_PROTOCOL           *BlockIo;\r
-  UINT8                           *CapsuleDataBuf;\r
-  UINT8                           *CapsulePtr;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;\r
-  EFI_FILE_HANDLE                 RootDir;\r
-  EFI_FILE_HANDLE                 TempCodFile;\r
-  UINT64                          TempCodFileSize;\r
-  EFI_DEVICE_PATH                 *TempDevicePath;\r
-  BOOLEAN                         RelocationInfo;\r
-  UINT16                          LoadOptionNumber;\r
-  EFI_CAPSULE_HEADER              FileNameCapsuleHeader;\r
-\r
-  RootDir          = NULL;\r
-  TempCodFile      = NULL;\r
-  HandleBuffer     = NULL;\r
-  CapsuleDataBuf   = NULL;\r
-  CapsuleOnDiskBuf = NULL;\r
-  NumberOfHandles  = 0;\r
-\r
-  DEBUG ((DEBUG_INFO, "CapsuleOnDisk RelocateCapsule Enter\n"));\r
-\r
-  //\r
-  // 1. Load all Capsule On Disks in to memory\r
-  //\r
-  Status = GetAllCapsuleOnDisk(MaxRetry, &CapsuleOnDiskBuf, &CapsuleOnDiskNum, &Handle, &LoadOptionNumber);\r
-  if (EFI_ERROR(Status) || CapsuleOnDiskNum == 0) {\r
-    DEBUG ((DEBUG_INFO, "RelocateCapsule: GetAllCapsuleOnDisk Status - 0x%x\n", Status));\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // 2. Connect platform special device path as relocation device.\r
-  // If no platform special device path specified or the device path is invalid, use the EFI system partition where\r
-  // stores the capsules as relocation device.\r
-  //\r
-  if (IsDevicePathValid ((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocationDevPath), PcdGetSize(PcdCodRelocationDevPath))) {\r
-    Status = EfiBootManagerConnectDevicePath ((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocationDevPath), &TempHandle);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG ((DEBUG_ERROR, "RelocateCapsule: EfiBootManagerConnectDevicePath Status - 0x%x\n", Status));\r
-      goto EXIT;\r
-    }\r
-\r
-    //\r
-    // Connect all the child handle. Partition & FAT drivers are allowed in this case\r
-    //\r
-    gBS->ConnectController (TempHandle, NULL, NULL, TRUE);\r
-    Status = gBS->LocateHandleBuffer(\r
-                    ByProtocol,\r
-                    &gEfiSimpleFileSystemProtocolGuid,\r
-                    NULL,\r
-                    &NumberOfHandles,\r
-                    &HandleBuffer\r
-                    );\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG ((DEBUG_ERROR, "RelocateCapsule: LocateHandleBuffer Status - 0x%x\n", Status));\r
-      goto EXIT;\r
-    }\r
-\r
-    //\r
-    // Find first Simple File System Handle which can match PcdCodRelocationDevPath\r
-    //\r
-    for (Index = 0; Index < NumberOfHandles; Index++) {\r
-      Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&TempDevicePath);\r
-      if (EFI_ERROR(Status)) {\r
-        continue;\r
-      }\r
-\r
-      DataSize = GetDevicePathSize((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocationDevPath)) - sizeof(EFI_DEVICE_PATH);\r
-      if (0 == CompareMem((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocationDevPath), TempDevicePath, DataSize)) {\r
-        Handle = HandleBuffer[Index];\r
-        break;\r
-      }\r
-    }\r
-\r
-    FreePool(HandleBuffer);\r
-\r
-    if (Index == NumberOfHandles) {\r
-      DEBUG ((DEBUG_ERROR, "RelocateCapsule: No simple file system protocol found.\n"));\r
-      Status = EFI_NOT_FOUND;\r
-    }\r
-  }\r
-\r
-  Status = gBS->HandleProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
-  if (EFI_ERROR(Status) || BlockIo->Media->ReadOnly) {\r
-    DEBUG((DEBUG_ERROR, "Fail to find Capsule on Disk relocation BlockIo device or device is ReadOnly!\n"));\r
-    goto EXIT;\r
-  }\r
-\r
-  Status = gBS->HandleProtocol(Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);\r
-  if (EFI_ERROR(Status)) {\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Check if device used to relocate Capsule On Disk is big enough\r
-  //\r
-  TotalImageSize     = 0;\r
-  TotalImageNameSize = 0;\r
-  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {\r
-    //\r
-    // Overflow check\r
-    //\r
-    if (MAX_ADDRESS - (UINTN)TotalImageSize <= CapsuleOnDiskBuf[Index].FileInfo->FileSize) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto EXIT;\r
-    }\r
-\r
-    if (MAX_ADDRESS - (UINTN)TotalImageNameSize <= StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName)) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto EXIT;\r
-    }\r
-\r
-    TotalImageSize     += CapsuleOnDiskBuf[Index].FileInfo->FileSize;\r
-    TotalImageNameSize += StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName);\r
-    DEBUG((DEBUG_INFO, "RelocateCapsule: %x Size %x\n",CapsuleOnDiskBuf[Index].FileInfo->FileName, CapsuleOnDiskBuf[Index].FileInfo->FileSize));\r
-  }\r
-\r
-  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageSize %x\n", TotalImageSize));\r
-  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageNameSize %x\n", TotalImageNameSize));\r
-\r
-  if (MAX_ADDRESS - (UINTN)TotalImageNameSize <= sizeof(UINT64) * 2 ||\r
-      MAX_ADDRESS - (UINTN)TotalImageSize <= (UINTN)TotalImageNameSize + sizeof(UINT64) * 2) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto EXIT;\r
-  }\r
-\r
-  TempCodFileSize = sizeof(UINT64) + TotalImageSize + sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;\r
-\r
-  //\r
-  // Check if CapsuleTotalSize. There could be reminder, so use LastBlock number directly\r
-  //\r
-  if (DivU64x32(TempCodFileSize, BlockIo->Media->BlockSize) > BlockIo->Media->LastBlock) {\r
-    DEBUG((DEBUG_ERROR, "RelocateCapsule: Relocation device isn't big enough to hold all Capsule on Disk!\n"));\r
-    DEBUG((DEBUG_ERROR, "TotalImageSize = %x\n", TotalImageSize));\r
-    DEBUG((DEBUG_ERROR, "TotalImageNameSize = %x\n", TotalImageNameSize));\r
-    DEBUG((DEBUG_ERROR, "RelocationDev BlockSize = %x LastBlock = %x\n", BlockIo->Media->BlockSize, BlockIo->Media->LastBlock));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto EXIT;\r
-  }\r
-\r
-  CapsuleDataBuf = AllocatePool((UINTN) TempCodFileSize);\r
-  if (CapsuleDataBuf == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // First UINT64 reserved for total image size, including capsule name capsule.\r
-  //\r
-  *(UINT64 *) CapsuleDataBuf = TotalImageSize + sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;\r
-\r
-  //\r
-  // Line up all the Capsule on Disk and write to relocation disk at one time. It could save some time in disk write\r
-  //\r
-  for (Index = 0, CapsulePtr = CapsuleDataBuf + sizeof(UINT64); Index < CapsuleOnDiskNum; Index++) {\r
-    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].ImageAddress, (UINTN) CapsuleOnDiskBuf[Index].FileInfo->FileSize);\r
-    CapsulePtr += CapsuleOnDiskBuf[Index].FileInfo->FileSize;\r
-  }\r
-\r
-  //\r
-  // Line the capsule header for capsule name capsule.\r
-  //\r
-  CopyGuid(&FileNameCapsuleHeader.CapsuleGuid, &gEdkiiCapsuleOnDiskNameGuid);\r
-  FileNameCapsuleHeader.CapsuleImageSize = (UINT32) TotalImageNameSize + sizeof(EFI_CAPSULE_HEADER);\r
-  FileNameCapsuleHeader.Flags            = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;\r
-  FileNameCapsuleHeader.HeaderSize       = sizeof(EFI_CAPSULE_HEADER);\r
-  CopyMem(CapsulePtr, &FileNameCapsuleHeader, FileNameCapsuleHeader.HeaderSize);\r
-  CapsulePtr += FileNameCapsuleHeader.HeaderSize;\r
-\r
-  //\r
-  // Line up all the Capsule file names.\r
-  //\r
-  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {\r
-    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].FileInfo->FileName, StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName));\r
-    CapsulePtr += StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName);\r
-  }\r
-\r
-  //\r
-  // 5. Flash all Capsules on Disk to TempCoD.tmp under RootDir\r
-  //\r
-  Status = Fs->OpenVolume(Fs, &RootDir);\r
-  if (EFI_ERROR(Status)) {\r
-    DEBUG((DEBUG_ERROR, "RelocateCapsule: OpenVolume error. %x\n", Status));\r
-    goto EXIT;\r
-  }\r
-\r
-  Status = RootDir->Open(\r
-                      RootDir,\r
-                      &TempCodFile,\r
-                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),\r
-                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,\r
-                      0\r
-                      );\r
-  if (!EFI_ERROR(Status)) {\r
-    //\r
-    // Error handling code to prevent malicious code to hold this file to block capsule on disk\r
-    //\r
-    TempCodFile->Delete(TempCodFile);\r
-  }\r
-  Status = RootDir->Open(\r
-                      RootDir,\r
-                      &TempCodFile,\r
-                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),\r
-                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,\r
-                      0\r
-                      );\r
-  if (EFI_ERROR(Status)) {\r
-    DEBUG((DEBUG_ERROR, "RelocateCapsule: Open TemCoD.tmp error. %x\n", Status));\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Always write at the begining of TempCap file\r
-  //\r
-  DataSize = (UINTN) TempCodFileSize;\r
-  Status = TempCodFile->Write(\r
-                          TempCodFile,\r
-                          &DataSize,\r
-                          CapsuleDataBuf\r
-                          );\r
-  if (EFI_ERROR(Status)) {\r
-    DEBUG((DEBUG_ERROR, "RelocateCapsule: Write TemCoD.tmp error. %x\n", Status));\r
-    goto EXIT;\r
-  }\r
-\r
-  if (DataSize != TempCodFileSize) {\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Save Capsule On Disk relocation info to "CodRelocationInfo" Var\r
-  // It is used in next reboot by TCB\r
-  //\r
-  RelocationInfo = TRUE;\r
-  Status = gRT->SetVariable(\r
-                   COD_RELOCATION_INFO_VAR_NAME,\r
-                   &gEfiCapsuleVendorGuid,\r
-                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                   sizeof (BOOLEAN),\r
-                   &RelocationInfo\r
-                   );\r
-  //\r
-  // Save the LoadOptionNumber of the boot option, where the capsule is relocated,\r
-  // into "CodRelocationLoadOption" var. It is used in next reboot after capsule is\r
-  // updated out of TCB to remove the TempCoDFile.\r
-  //\r
-  Status = gRT->SetVariable(\r
-                   COD_RELOCATION_LOAD_OPTION_VAR_NAME,\r
-                   &gEfiCapsuleVendorGuid,\r
-                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                   sizeof (UINT16),\r
-                   &LoadOptionNumber\r
-                   );\r
-\r
-EXIT:\r
-\r
-  if (CapsuleDataBuf != NULL) {\r
-    FreePool(CapsuleDataBuf);\r
-  }\r
-\r
-  if (CapsuleOnDiskBuf != NULL) {\r
-    //\r
-    // Free resources allocated by CodLibGetAllCapsuleOnDisk\r
-    //\r
-    for (Index = 0; Index < CapsuleOnDiskNum; Index++ ) {\r
-      FreePool(CapsuleOnDiskBuf[Index].ImageAddress);\r
-      FreePool(CapsuleOnDiskBuf[Index].FileInfo);\r
-    }\r
-    FreePool(CapsuleOnDiskBuf);\r
-  }\r
-\r
-  if (TempCodFile != NULL) {\r
-    if (EFI_ERROR(Status)) {\r
-      TempCodFile->Delete (TempCodFile);\r
-    } else {\r
-      TempCodFile->Close (TempCodFile);\r
-    }\r
-  }\r
-\r
-  if (RootDir != NULL) {\r
-    RootDir->Close (RootDir);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  For the platforms that support Capsule In Ram, reuse the Capsule In Ram to deliver capsule.\r
-  Relocate Capsule On Disk to memory and call UpdateCapsule().\r
-  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.\r
-  Function will stall 100ms between each retry.\r
-\r
-  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure\r
-                                     devices like USB can get enumerated.\r
-\r
-  @retval EFI_SUCCESS   Deliver capsule through Capsule In Ram successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-RelocateCapsuleToRam (\r
-  UINTN    MaxRetry\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  UINTN                         CapsuleOnDiskNum;\r
-  IMAGE_INFO                    *CapsuleOnDiskBuf;\r
-  EFI_HANDLE                    Handle;\r
-  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;\r
-  VOID                          **CapsuleBuffer;\r
-  UINTN                         *CapsuleSize;\r
-  EFI_CAPSULE_HEADER            *FileNameCapsule;\r
-  UINTN                         Index;\r
-  UINT8                         *StringBuf;\r
-  UINTN                         StringSize;\r
-  UINTN                         TotalStringSize;\r
-\r
-  CapsuleOnDiskBuf = NULL;\r
-  BlockDescriptors = NULL;\r
-  CapsuleBuffer    = NULL;\r
-  CapsuleSize      = NULL;\r
-  FileNameCapsule  = NULL;\r
-  TotalStringSize  = 0;\r
-\r
-  //\r
-  // 1. Load all Capsule On Disks into memory\r
-  //\r
-  Status = GetAllCapsuleOnDisk (MaxRetry, &CapsuleOnDiskBuf, &CapsuleOnDiskNum, &Handle, NULL);\r
-  if (EFI_ERROR (Status) || CapsuleOnDiskNum == 0) {\r
-    DEBUG ((DEBUG_ERROR, "GetAllCapsuleOnDisk Status - 0x%x\n", Status));\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // 2. Add a capsule for Capsule file name strings\r
-  //\r
-  CapsuleBuffer = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof (VOID *));\r
-  if (CapsuleBuffer == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  CapsuleSize = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof (UINTN));\r
-  if (CapsuleSize == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));\r
-    FreePool (CapsuleBuffer);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {\r
-    CapsuleBuffer[Index] = (VOID *)(UINTN) CapsuleOnDiskBuf[Index].ImageAddress;\r
-    CapsuleSize[Index] = (UINTN) CapsuleOnDiskBuf[Index].FileInfo->FileSize;\r
-    TotalStringSize += StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName);\r
-  }\r
-\r
-  FileNameCapsule = AllocateZeroPool (sizeof (EFI_CAPSULE_HEADER) + TotalStringSize);\r
-  if (FileNameCapsule == NULL) {\r
-    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for name capsule.\n"));\r
-    FreePool (CapsuleBuffer);\r
-    FreePool (CapsuleSize);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  FileNameCapsule->CapsuleImageSize = (UINT32) (sizeof (EFI_CAPSULE_HEADER) + TotalStringSize);\r
-  FileNameCapsule->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;\r
-  FileNameCapsule->HeaderSize = sizeof (EFI_CAPSULE_HEADER);\r
-  CopyGuid (&(FileNameCapsule->CapsuleGuid), &gEdkiiCapsuleOnDiskNameGuid);\r
-\r
-  StringBuf = (UINT8 *)FileNameCapsule + FileNameCapsule->HeaderSize;\r
-  for (Index = 0; Index < CapsuleOnDiskNum; Index ++) {\r
-    StringSize = StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName);\r
-    CopyMem (StringBuf, CapsuleOnDiskBuf[Index].FileInfo->FileName, StringSize);\r
-    StringBuf += StringSize;\r
-  }\r
-\r
-  CapsuleBuffer[CapsuleOnDiskNum] = FileNameCapsule;\r
-  CapsuleSize[CapsuleOnDiskNum] = TotalStringSize + sizeof (EFI_CAPSULE_HEADER);\r
-\r
-  //\r
-  // 3. Build Gather list for the capsules\r
-  //\r
-  Status = BuildGatherList (CapsuleBuffer, CapsuleSize, CapsuleOnDiskNum + 1, &BlockDescriptors);\r
-  if (EFI_ERROR (Status) || BlockDescriptors == NULL) {\r
-    FreePool (CapsuleBuffer);\r
-    FreePool (CapsuleSize);\r
-    FreePool (FileNameCapsule);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  //\r
-  // 4. Call UpdateCapsule() service\r
-  //\r
-  Status = gRT->UpdateCapsule((EFI_CAPSULE_HEADER **) CapsuleBuffer, CapsuleOnDiskNum + 1, (UINTN) BlockDescriptors);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Relocate Capsule on Disk from EFI system partition.\r
-\r
-  Two solution to deliver Capsule On Disk:\r
-  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Disk to memory and call UpdateCapsule().\r
-  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On Disk to a platform-specific NV storage\r
-  device with BlockIo protocol.\r
-\r
-  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.\r
-  Function will stall 100ms between each retry.\r
-\r
-  Side Effects:\r
-    Capsule Delivery Supported Flag in OsIndication variable and BootNext variable will be cleared.\r
-    Solution B: Content corruption. Block IO write directly touches low level write. Orignal partitions, file\r
-  systems of the relocation device will be corrupted.\r
-\r
-  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure\r
-                                     devices like USB can get enumerated. Input 0 means no retry.\r
-\r
-  @retval EFI_SUCCESS   Capsule on Disk images are successfully relocated.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CoDRelocateCapsule(\r
-  UINTN     MaxRetry\r
-  )\r
-{\r
-  if (!PcdGetBool (PcdCapsuleOnDiskSupport)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  //\r
-  // Clear CapsuleOnDisk Flag firstly.\r
-  //\r
-  CoDClearCapsuleOnDiskFlag ();\r
-\r
-  //\r
-  // If Capsule In Ram is supported, delivery capsules through memory\r
-  //\r
-  if (PcdGetBool (PcdCapsuleInRamSupport)) {\r
-    DEBUG ((DEBUG_INFO, "Capsule In Ram is supported, call gRT->UpdateCapsule().\n"));\r
-    return RelocateCapsuleToRam (MaxRetry);\r
-  } else {\r
-    DEBUG ((DEBUG_INFO, "Reallcoate all Capsule on Disks to %s in RootDir.\n", (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName)));\r
-    return RelocateCapsuleToDisk (MaxRetry);\r
-  }\r
-}\r
-\r
-/**\r
-  Remove the temp file from the root of EFI System Partition.\r
-  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.\r
-  Function will stall 100ms between each retry.\r
-\r
-  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure\r
-                                     devices like USB can get enumerated. Input 0 means no retry.\r
-\r
-  @retval EFI_SUCCESS   Remove the temp file successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CoDRemoveTempFile (\r
-  UINTN    MaxRetry\r
-  )\r
-{\r
-  EFI_STATUS                       Status;\r
-  UINTN                            DataSize;\r
-  UINT16                           *LoadOptionNumber;\r
-  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;\r
-  EFI_HANDLE                       FsHandle;\r
-  EFI_FILE_HANDLE                  RootDir;\r
-  EFI_FILE_HANDLE                  TempCodFile;\r
-\r
-  RootDir     = NULL;\r
-  TempCodFile = NULL;\r
-  DataSize    = sizeof(UINT16);\r
-\r
-  LoadOptionNumber = AllocatePool (sizeof(UINT16));\r
-  if (LoadOptionNumber == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  //\r
-  // Check if capsule files are relocated\r
-  //\r
-  Status = gRT->GetVariable (\r
-                  COD_RELOCATION_LOAD_OPTION_VAR_NAME,\r
-                  &gEfiCapsuleVendorGuid,\r
-                  NULL,\r
-                  &DataSize,\r
-                  (VOID *)LoadOptionNumber\r
-                  );\r
-  if (EFI_ERROR(Status) || DataSize != sizeof(UINT16)) {\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Get the EFI file system from the boot option where the capsules are relocated\r
-  //\r
-  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry, &LoadOptionNumber, &FsHandle);\r
-  if (EFI_ERROR(Status)) {\r
-    goto EXIT;\r
-  }\r
-\r
-  Status = gBS->HandleProtocol(FsHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);\r
-  if (EFI_ERROR(Status)) {\r
-    goto EXIT;\r
-  }\r
-\r
-  Status = Fs->OpenVolume(Fs, &RootDir);\r
-  if (EFI_ERROR(Status)) {\r
-    goto EXIT;\r
-  }\r
-\r
-  //\r
-  // Delete the TempCoDFile\r
-  //\r
-  Status = RootDir->Open(\r
-                      RootDir,\r
-                      &TempCodFile,\r
-                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),\r
-                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,\r
-                      0\r
-                      );\r
-  if (EFI_ERROR(Status)) {\r
-    goto EXIT;\r
-  }\r
-\r
-  TempCodFile->Delete(TempCodFile);\r
-\r
-  //\r
-  // Clear "CoDRelocationLoadOption" variable\r
-  //\r
-  Status = gRT->SetVariable (\r
-             COD_RELOCATION_LOAD_OPTION_VAR_NAME,\r
-             &gEfiCapsuleVendorGuid,\r
-             0,\r
-             0,\r
-             NULL\r
-             );\r
-\r
-EXIT:\r
-  if (LoadOptionNumber != NULL) {\r
-    FreePool (LoadOptionNumber);\r
-  }\r
-\r
-  if (RootDir != NULL) {\r
-    RootDir->Close(RootDir);\r
-  }\r
-\r
-  return Status;\r
-}\r