public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
@ 2019-06-05 15:41 Xu, Wei6
  2019-06-05 15:41 ` [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition Xu, Wei6
                   ` (8 more replies)
  0 siblings, 9 replies; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:41 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Michael D Kinney, Liming Gao, Chao B Zhang

V2:
Fix Ecc check failure.

V1:
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

This patch set implements Capsule On Disk.
Depends on whether platform supports Capsule-In-Ram, Capsule On Disk feature is composed of 2 solutions:
Solution A): Load capsules out of TCB, rely on UpdateCapsule() runtime service to deliver Capsule-On-Disk.
Solution B): Relocate capsules into a temp file which will be stored in root directory on a platform specific storage device.
Leverage existing storage stack in PEI to load all capsule on disk images and create capsule hobs for the capsules.
This solution has bigger TCB, but can work without Capsule-In-RAM support.


Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>

xuwei6 (7):
  MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
  MdeModulePkg: Add Capsule On Disk related definition.
  MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
  MdeModulePkg/BdsDxe: Support Capsule On Disk.
  MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  MdeModulePkg/DxeIpl: Support Capsule On Disk.
  MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.

 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h              |    3 +-
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf            |   20 +-
 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c             |   37 +-
 MdeModulePkg/Include/Library/CapsuleLib.h          |   94 +-
 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h           |   48 +
 .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       | 1983 ++++++++++++++++++++
 .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |   63 +
 .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |   56 +-
 .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |   21 +-
 .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |  121 +-
 .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |   67 +-
 .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |    3 +-
 .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |   85 +-
 MdeModulePkg/MdeModulePkg.dec                      |   43 +
 MdeModulePkg/MdeModulePkg.dsc                      |    4 +
 MdeModulePkg/MdeModulePkg.uni                      |   32 +
 MdeModulePkg/Universal/BdsDxe/BdsDxe.inf           |    3 +-
 MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |    6 +-
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    |  442 +++++
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |   64 +
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |   15 +
 .../CapsuleOnDiskLoadPeiExtra.uni                  |   14 +
 .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf        |    1 +
 .../Universal/CapsuleRuntimeDxe/CapsuleService.c   |   10 +-
 MdePkg/Include/Ppi/BootInRecoveryMode.h            |    9 +-
 MdePkg/MdePkg.dec                                  |    3 +
 26 files changed, 3205 insertions(+), 42 deletions(-)
 create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiExtra.uni

-- 
2.16.2.windows.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
@ 2019-06-05 15:41 ` Xu, Wei6
  2019-06-05 21:42   ` Felix Polyudov
  2019-06-12  7:48   ` Wu, Hao A
  2019-06-05 15:41 ` [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition Xu, Wei6
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:41 UTC (permalink / raw)
  To: devel; +Cc: Michael D Kinney, Liming Gao, Chao B Zhang, Wei6 Xu

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

This PPI indicates current boot mode is capsule on disk mode.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdePkg/Include/Ppi/BootInRecoveryMode.h | 9 ++++++++-
 MdePkg/MdePkg.dec                       | 3 +++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/MdePkg/Include/Ppi/BootInRecoveryMode.h b/MdePkg/Include/Ppi/BootInRecoveryMode.h
index ae40744d9b..71b0ca8586 100644
--- a/MdePkg/Include/Ppi/BootInRecoveryMode.h
+++ b/MdePkg/Include/Ppi/BootInRecoveryMode.h
@@ -1,10 +1,10 @@
 /** @file
   This PPI is installed by the platform PEIM to designate that a recovery boot
   is in progress.
 
-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
   @par Revision Reference:
   This PPI is introduced in PI Version 1.0.
 
@@ -19,6 +19,13 @@
   }
 
 
 extern EFI_GUID gEfiPeiBootInRecoveryModePpiGuid;
 
+#define EFI_PEI_BOOT_IN_CAPSULE_ON_DISK_MODE_PPI \
+  { \
+    0xb08a11e4, 0xe2b7, 0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } \
+  }
+
+extern EFI_GUID gEfiPeiBootInCapsuleOnDiskModePpiGuid;
+
 #endif
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 6c563375ee..ec02b8c7c7 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -790,10 +790,13 @@
   gEfiPeiMemoryDiscoveredPpiGuid = {0xf894643d, 0xc449, 0x42d1, {0x8e, 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } }
 
   ## Include/Ppi/BootInRecoveryMode.h
   gEfiPeiBootInRecoveryModePpiGuid = { 0x17ee496a, 0xd8e4, 0x4b9a, {0x94, 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } }
 
+  ## Include/Ppi/BootInRecoveryMode.h
+  gEfiPeiBootInCapsuleOnDiskModePpiGuid = { 0xb08a11e4, 0xe2b7, 0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } }
+
   ## Include/Ppi/EndOfPeiPhase.h
   gEfiEndOfPeiSignalPpiGuid = {0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } }
 
   ## Include/Ppi/Reset.h
   gEfiPeiResetPpiGuid = { 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78, 0xc6, 0xf4, 0xfe, 0x71, 0x2f } }
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
  2019-06-05 15:41 ` [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition Xu, Wei6
@ 2019-06-05 15:41 ` Xu, Wei6
  2019-06-12  7:48   ` Wu, Hao A
  2019-06-05 15:41 ` [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM Xu, Wei6
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:41 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Chao B Zhang, Wei6 Xu

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

This patch will add Capsule On Disk related definition, including
GUID, PPI and PCDs:
The Capsule On Disk Name GUID indicates the capsule is to store
Capsule On Disk file names.
The Pei Capsule On Disk PPI provides service to retrieve capsules
from Capsule On Disk temp relocation file on mass storage devices
and create capsule hob for these capsules.
PcdCapsuleOnDiskSupport is used to enable/disable Capsule On Disk.
PcdCapsuleInRamSupport is used to enabble/disable Capsule In Ram.
PcdCoDRelocationFileName specifies the Capsule On Disk temp
relocation file name.
PcdCodRelocationDevPath specifies platform specific device to store
Capsule On Disk tem relocation file.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h | 48 ++++++++++++++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dec            | 43 ++++++++++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.uni            | 32 +++++++++++++++++++++
 3 files changed, 123 insertions(+)
 create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h

diff --git a/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h b/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
new file mode 100644
index 0000000000..28be6e42be
--- /dev/null
+++ b/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
@@ -0,0 +1,48 @@
+/** @file
+  This file declares Capsule On Disk PPI.  This PPI is used to find and load the
+  capsule on files that are relocated into a temp file under rootdir.
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __PEI_CAPSULE_ON_DISK_PPI_H__
+#define __PEI_CAPSULE_ON_DISK_PPI_H__
+
+#define EFI_PEI_CAPSULE_ON_DISK_PPI_GUID \
+  { \
+    0x71a9ea61, 0x5a35, 0x4a5d, {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67, 0xe0 } \
+  }
+
+typedef struct _EFI_PEI_CAPSULE_ON_DISK_PPI EFI_PEI_CAPSULE_ON_DISK_PPI;
+
+/**
+  Loads a DXE capsule from some media into memory and updates the HOB table
+  with the DXE firmware volume information.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
+
+  @retval EFI_SUCCESS        The capsule was loaded correctly.
+  @retval EFI_DEVICE_ERROR   A device error occurred.
+  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PEI_LOAD_CAPSULE_ON_DISK)(
+  IN EFI_PEI_SERVICES             **PeiServices,
+  IN EFI_PEI_CAPSULE_ON_DISK_PPI  *This
+  );
+
+///
+///  Finds and loads the recovery files.
+///
+struct _EFI_PEI_CAPSULE_ON_DISK_PPI {
+  EFI_PEI_LOAD_CAPSULE_ON_DISK LoadCapsuleOnDisk;  ///< Loads a DXE binary capsule into memory.
+};
+
+extern EFI_GUID gEdkiiPeiCapsuleOnDiskPpiGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 6cba729982..d80b728313 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -394,10 +394,13 @@
   gEdkiiS3SmmInitDoneGuid = { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 0x71, 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } }
 
   ## Include/Guid/S3StorageDeviceInitList.h
   gS3StorageDeviceInitListGuid = { 0x310e9b8c, 0xcf90, 0x421e, { 0x8e, 0x9b, 0x9e, 0xef, 0xb6, 0x17, 0xc8, 0xef } }
 
+  ## GUID indicates the capsule is to store Capsule On Disk file names.
+  gEdkiiCapsuleOnDiskNameGuid = { 0x98c80a4f, 0xe16b, 0x4d11, { 0x93, 0x9a, 0xab, 0xe5, 0x61, 0x26, 0x3, 0x30 } }
+
 [Ppis]
   ## Include/Ppi/AtaController.h
   gPeiAtaControllerPpiGuid       = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
 
   ## Include/Ppi/UsbHostController.h
@@ -464,10 +467,13 @@
   gEdkiiPeiAtaPassThruPpiGuid               = { 0xa16473fd, 0xd474, 0x4c89, { 0xae, 0xc7, 0x90, 0xb8, 0x3c, 0x73, 0x86, 0x9  } }
 
   ## Include/Ppi/Debug.h
   gEdkiiDebugPpiGuid                        = { 0x999e699c, 0xb013, 0x475e, { 0xb1, 0x7b, 0xf3, 0xa8, 0xae, 0x5c, 0x48, 0x75 } }
 
+  ## Include/Ppi/CapsuleOnDisk.h
+  gEdkiiPeiCapsuleOnDiskPpiGuid             =  {0x71a9ea61, 0x5a35, 0x4a5d, {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67, 0xe0}}
+
 [Protocols]
   ## Load File protocol provides capability to load and unload EFI image into memory and execute it.
   #  Include/Protocol/LoadPe32Image.h
   #  This protocol is deprecated. Native EDKII module should NOT use this protocol to load/unload image.
   #  If developer need implement such functionality, they should use BasePeCoffLib.
@@ -1473,10 +1479,26 @@
 
   ## Indicates the allowable maximum number of Reset Filters, Reset Notifications or Reset Handlers in PEI phase.
   # @Prompt Maximum Number of PEI Reset Filters, Reset Notifications or Reset Handlers.
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaximumPeiResetNotifies|0x10|UINT32|0x0000010A
 
+  ## Capsule On Disk is to deliver capsules via files on Mass Storage device.<BR><BR>
+  #  This PCD indicates if the Capsule On Disk is supported.<BR>
+  #   TRUE  - Capsule On Disk is supported.<BR>
+  #   FALSE - Capsule On Disk is not supported.<BR>
+  #  If platform does not use this feature, this PCD should be set to FALSE.<BR><BR>
+  #  Two sulotions to deliver Capsule On Disk:<BR>
+  #    a) If PcdCapsuleInRamSupport = TRUE, Load Capsule On Disk image out of TCB, and reuse
+  #       Capsule In Ram to deliver capsule.<BR>
+  #    b) If PcdCapsuleInRamSupport = FALSE, Relocate Capsule On Disk image to RootDir out
+  #       of TCB, and reuse FatPei to load capsules from external storage.<BR>
+  #  Note:<BR>
+  #    If Both Capsule In Ram and Capsule On Disk are provisioned at the same time, the Capsule
+  #  On Disk will be bypassed.
+  # @Prompt Enable Capsule On Disk support.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOOLEAN|0x0000002d
+
 [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
   ## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
   #  This PCD could be set to 0 then console output would be at max column and max row.
   # @Prompt Console output row.
   gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|25|UINT32|0x40000006
@@ -1932,10 +1954,17 @@
   #  The file name must be the 8.3 format.
   #  The PCD data must be in UNICODE format.
   # @Prompt Recover file name in PEI phase
   gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"|VOID*|0x30001045
 
+  ## This is Capsule Temp Relocation file name in PEI phase.
+  #  The file must be in the root directory.
+  #  The file name must be the 8.3 format.
+  #  The PCD data must be in UNICODE format.
+  # @Prompt Capsule On Disk Temp Relocation file name in PEI phase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName|L"TempCod.tmp"|VOID*|0x30001048
+
   ## This PCD hold a list GUIDs for the ImageTypeId to indicate the
   #  FMP capsule is a system FMP.
   # @Prompt A list of system FMP ImageTypeId GUIDs
   gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid|{0x0}|VOID*|0x30001046
 
@@ -1943,10 +1972,24 @@
   #  enabled on AMD processors supporting the Secure Encrypted Virtualization (SEV) feature.
   #  This mask should be applied when creating 1:1 virtual to physical mapping tables.
   # @Prompt The address mask when memory encryption is enabled.
   gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0|UINT64|0x30001047
 
+  ## Capsule In Ram is to use memory to deliver the capsules that will be processed after system
+  #  reset.<BR><BR>
+  #  This PCD indicates if the Capsule In Ram is supported.<BR>
+  #   TRUE  - Capsule In Ram is supported.<BR>
+  #   FALSE - Capsule In Ram is not supported.
+  # @Prompt Enable Capsule In Ram support.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport|TRUE|BOOLEAN|0x0000002e
+
+  ## Full device path of plaform specific device to store Capsule On Disk temp relocation file.<BR>
+  #  If this PCD is set, Capsule On Disk temp relocation file will be stored in the device specified
+  #  by this PCD, instead of the EFI System Partition that stores capsule image file.
+  # @Prompt Capsule On Disk relocation device path.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath|{0xFF}|VOID*|0x0000002f
+
 [PcdsPatchableInModule]
   ## Specify memory size with page number for PEI code when
   #  Loading Module at Fixed Address feature is enabled.
   #  The value will be set by the build tool.
   # @Prompt LMFA PEI code page number.
diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni
index ed8ac9eadc..85c6beae0d 100644
--- a/MdeModulePkg/MdeModulePkg.uni
+++ b/MdeModulePkg/MdeModulePkg.uni
@@ -1064,10 +1064,17 @@
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdRecoveryFileName_HELP  #language en-US "This is recover file name in PEI phase.\n"
                                                                                      "The file must be in the root directory.\n"
                                                                                      "The file name must be the 8.3 format.\n"
                                                                                      "The PCD data must be in UNICODE format."
 
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_PROMPT  #language en-US "Capsule On Disk Temp Relocation file name in PEI phase"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_HELP  #language en-US "This is Capsule Temp Relocation file name in PEI phase.\n"
+                                                                                          "The file must be in the root directory.\n"
+                                                                                          "The file name must be the 8.3 format.\n"
+                                                                                          "The PCD data must be in UNICODE format."
+
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTypeIdGuid_PROMPT  #language en-US "A list of system FMP ImageTypeId GUIDs"
 
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTypeIdGuid_HELP  #language en-US "This PCD hold a list GUIDs for the ImageTypeId to indicate the\n"
                                                                                                     "FMP capsule is a system FMP."
 
@@ -1129,10 +1136,35 @@
 
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPteMemoryEncryptionAddressOrMask_HELP  #language en-US "This PCD holds the address mask for page table entries when memory encryption is\n"
                                                                                                      "enabled on AMD processors supporting the Secure Encrypted Virtualization (SEV) feature.\n"
                                                                                                      "This mask should be applied when creating 1:1 virtual to physical mapping tables."
 
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_PROMPT  #language en-US "Enable Capsule On Disk support"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_HELP  #language en-US   "Capsule On Disk is to deliver capsules via files on Mass Storage device.<BR><BR>"
+                                                                                           "This PCD indicates if the Capsule On Disk is supported.<BR>"
+                                                                                           " TRUE  - Capsule On Disk is supported.<BR>"
+                                                                                           " FALSE - Capsule On Disk is not supported.<BR>"
+                                                                                           "If platform does not use this feature, this PCD should be set to FALSE.<BR><BR>"
+                                                                                           "Two sulotions to deliver Capsule On Disk:<BR>"
+                                                                                           " a) If PcdCapsuleInRamSupport = TRUE, Load Capsule On Disk image out of TCB, and reuse Capsule In Ram to deliver capsule.<BR>"
+                                                                                           " b) If PcdCapsuleInRamSupport = FALSE, Relocate Capsule On Disk image to RootDir out of TCB, and reuse FatPei to load capsules from external storage.<BR>"
+                                                                                           "Note:<BR>"
+                                                                                           "If Both Capsule In Ram and Capsule On Disk are provisioned at the same time, the Capsule On Disk will be bypassed."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROMPT  #language en-US "Enable Capsule In Ram support"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP  #language en-US   "Capsule In Ram is to use memory to deliver the capsules that will be processed after system reset.<BR><BR>"
+                                                                                          "This PCD indicates if the Capsule In Ram is supported.<BR>"
+                                                                                          " TRUE  - Capsule In Ram is supported.<BR>"
+                                                                                          " FALSE - Capsule In Ram is not supported."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_PROMPT  #language en-US "Capsule On Disk relacation device path."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_HELP  #language en-US   "Full device path of plaform specific device to store Capsule On Disk temp relocation file.<BR>"
+                                                                                           "If this PCD is set, Capsule On Disk temp relocation file will be stored in the device specified by this PCD, instead of the EFI System Partition that stores capsule image file."
+
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionPropertyMask_PROMPT  #language en-US "Enable NULL pointer detection"
 
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionPropertyMask_HELP    #language en-US "Mask to control the NULL address detection in code for different phases.\n"
                                                                                                        " If enabled, accessing NULL address in UEFI or SMM code can be caught.\n\n"
                                                                                                        "   BIT0    - Enable NULL pointer detection for UEFI.\n"
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
  2019-06-05 15:41 ` [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition Xu, Wei6
  2019-06-05 15:41 ` [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition Xu, Wei6
@ 2019-06-05 15:41 ` Xu, Wei6
  2019-06-12  7:49   ` Wu, Hao A
  2019-06-05 15:42 ` [edk2-devel][Patch v2 4/7] MdeModulePkg/BdsDxe: Support Capsule On Disk Xu, Wei6
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:41 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Chao B Zhang, Wei6 Xu

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

This module provides PPI to load Capsule On Disk temp relocation file
from Root Directory file system, retrieve the capsules from the temp
file and create capsule hobs for these capsules.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdeModulePkg/MdeModulePkg.dsc                      |   4 +
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    | 442 +++++++++++++++++++++
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |  64 +++
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |  15 +
 .../CapsuleOnDiskLoadPeiExtra.uni                  |  14 +
 5 files changed, 539 insertions(+)
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiExtra.uni

diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 995fd805e1..615edddbcc 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -197,10 +197,13 @@
   gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
 
+[PcdsDynamicExDefault]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
+
 [Components]
   MdeModulePkg/Application/HelloWorld/HelloWorld.inf
   MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
   MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
 
@@ -315,10 +318,11 @@
       NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
   }
   MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
   MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.inf
   MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
+  MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
   MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
   MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
   MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
   MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
   MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf
diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
new file mode 100644
index 0000000000..40d25f3d3b
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
@@ -0,0 +1,442 @@
+/** @file
+  Recovery module.
+
+  Caution: This module requires additional review when modified.
+  This module will have external input - Capsule-on-Disk Temp Relocation image.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+  RetrieveRelocatedCapsule() will receive untrusted input and do basic validation.
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <Uefi.h>
+#include <PiPei.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/FirmwareVolumeInfo.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/Capsule.h>
+#include <Ppi/CapsuleOnDisk.h>
+#include <Ppi/DeviceRecoveryModule.h>
+
+#include <Guid/FirmwareFileSystem2.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+/**
+  Loads a DXE capsule from some media into memory and updates the HOB table
+  with the DXE firmware volume information.
+
+  @param[in]  PeiServices   General-purpose services that are available to every PEIM.
+  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
+
+  @retval EFI_SUCCESS        The capsule was loaded correctly.
+  @retval EFI_DEVICE_ERROR   A device error occurred.
+  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadCapsuleOnDisk (
+  IN EFI_PEI_SERVICES              **PeiServices,
+  IN EFI_PEI_CAPSULE_ON_DISK_PPI   *This
+  );
+
+EFI_PEI_CAPSULE_ON_DISK_PPI mCapsuleOnDiskPpi = {
+  LoadCapsuleOnDisk
+};
+
+EFI_PEI_PPI_DESCRIPTOR mCapsuleOnDiskPpiList = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiPeiCapsuleOnDiskPpiGuid,
+  &mCapsuleOnDiskPpi
+};
+
+/**
+  Determine if capsule comes from memory by checking Capsule PPI.
+
+  @param[in]  PeiServices General purpose services available to every PEIM.
+
+  @retval TRUE   Capsule comes from memory.
+  @retval FALSE  No capsule comes from memory.
+
+**/
+STATIC
+BOOLEAN
+CheckCapsuleFromRam (
+  IN CONST EFI_PEI_SERVICES          **PeiServices
+  )
+{
+  EFI_STATUS              Status;
+  PEI_CAPSULE_PPI         *Capsule;
+
+  Status = PeiServicesLocatePpi (
+             &gPeiCapsulePpiGuid,
+             0,
+             NULL,
+             (VOID **) &Capsule
+             );
+  if (!EFI_ERROR(Status)) {
+    Status = Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES **)PeiServices);
+    if (!EFI_ERROR(Status)) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Determine if it is a Capsule On Disk mode.
+
+  @retval TRUE         Capsule On Disk mode.
+  @retval FALSE        Not capsule On Disk mode.
+
+**/
+BOOLEAN
+IsCapsuleOnDiskMode (
+  VOID
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           Size;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
+  BOOLEAN                         CodRelocInfo;
+
+  Status = PeiServicesLocatePpi (
+             &gEfiPeiReadOnlyVariable2PpiGuid,
+             0,
+             NULL,
+             (VOID **) &PPIVariableServices
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Size = sizeof (BOOLEAN);
+  Status = PPIVariableServices->GetVariable (
+                                  PPIVariableServices,
+                                  COD_RELOCATION_INFO_VAR_NAME,
+                                  &gEfiCapsuleVendorGuid,
+                                  NULL,
+                                  &Size,
+                                  &CodRelocInfo
+                                  );
+
+  if (EFI_ERROR (Status) || Size != sizeof(BOOLEAN) || CodRelocInfo != TRUE) {
+    DEBUG (( DEBUG_ERROR, "Error Get CodRelocationInfo variable %r!\n", Status));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Gets capsule images from relocated capsule buffer.
+  Create Capsule hob for each Capsule.
+
+  Caution: This function may receive untrusted input.
+  Capsule-on-Disk Temp Relocation image is external input, so this function
+  will validate Capsule-on-Disk Temp Relocation image to make sure the content
+  is read within the buffer.
+
+  @param[in]  RelocCapsuleBuf        Buffer pointer to the relocated capsule.
+  @param[in]  RelocCapsuleTotalSize  Total size of the relocated capsule.
+
+  @retval EFI_SUCCESS     Succeed to get capsules and create hob.
+  @retval Others          Fail to get capsules and create hob.
+
+**/
+EFI_STATUS
+EFIAPI
+RetrieveRelocatedCapsule (
+  IN UINT8                *RelocCapsuleBuf,
+  IN UINTN                RelocCapsuleTotalSize
+  )
+{
+  EFI_STATUS               Status;
+  UINTN                    Index;
+  UINT8                    *CapsuleDataBufEnd;
+  UINT8                    *CapsulePtr;
+  UINT32                   CapsuleSize;
+  UINT64                   TotalImageSize;
+  UINTN                    CapsuleNum;
+
+  CapsuleNum = 0;
+
+  //
+  // Temp file contains at least 2 capsule (including 1 capsule name capsule) & 1 UINT64
+  //
+  if (RelocCapsuleTotalSize < sizeof(UINT64) + sizeof(EFI_CAPSULE_HEADER) * 2) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem(&TotalImageSize, RelocCapsuleBuf, sizeof(UINT64));
+
+  DEBUG ((DEBUG_INFO, "ProcessRelocatedCapsule CapsuleBuf %x TotalCapSize %lx\n",
+                      RelocCapsuleBuf, TotalImageSize));
+
+  RelocCapsuleBuf += sizeof(UINT64);
+
+  //
+  // TempCaspule file length check
+  //
+  if (MAX_ADDRESS - TotalImageSize <= sizeof(UINT64) ||
+      (UINT64)RelocCapsuleTotalSize != TotalImageSize + sizeof(UINT64) ||
+      (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)RelocCapsuleBuf) <= TotalImageSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CapsuleDataBufEnd = RelocCapsuleBuf + TotalImageSize;
+
+  //
+  // TempCapsule file integrity check over Capsule Header to ensure no data corruption in NV Var & Relocation storage
+  //
+  CapsulePtr = RelocCapsuleBuf;
+
+  while (CapsulePtr < CapsuleDataBufEnd) {
+    if ((CapsuleDataBufEnd - CapsulePtr) < sizeof(EFI_CAPSULE_HEADER) ||
+        ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize < sizeof(EFI_CAPSULE_HEADER) ||
+        (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)CapsulePtr) < ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize
+        ) {
+      break;
+    }
+    CapsulePtr += ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize;
+    CapsuleNum ++;
+  }
+
+  if (CapsulePtr != CapsuleDataBufEnd) {
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+  }
+
+  //
+  // Capsule count must be less than PcdCapsuleMax, avoid building too many CvHobs to occupy all the free space in HobList.
+  //
+  if (CapsuleNum > PcdGet16 (PcdCapsuleMax)) {
+    Status = EFI_INVALID_PARAMETER;
+    goto EXIT;
+  }
+
+  //
+  // Re-iterate the capsule buffer to create Capsule hob & Capsule Name Str Hob for each Capsule saved in relocated capsule file
+  //
+  CapsulePtr = RelocCapsuleBuf;
+  Index      = 0;
+  while (CapsulePtr < CapsuleDataBufEnd) {
+    CapsuleSize = ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize;
+    BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsulePtr, CapsuleSize);
+
+    DEBUG((DEBUG_INFO, "Capsule saved in address %x size %x\n", CapsulePtr, CapsuleSize));
+
+    CapsulePtr += CapsuleSize;
+    Index++;
+  }
+
+EXIT:
+
+  return Status;
+}
+
+/**
+  Recovery module entrypoint
+
+  @param[in] FileHandle   Handle of the file being invoked.
+  @param[in] PeiServices  Describes the list of possible PEI Services.
+
+  @return EFI_SUCCESS Recovery module is initialized.
+**/
+EFI_STATUS
+EFIAPI
+InitializeCapsuleOnDiskLoad (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       BootMode;
+  UINTN       FileNameSize;
+
+  BootMode = GetBootModeHob();
+  ASSERT(BootMode == BOOT_ON_FLASH_UPDATE);
+
+  //
+  // If there are capsules provisioned in memory, quit.
+  // Only one capsule resource is accept, CapsuleOnRam's priority is higher than CapsuleOnDisk.
+  //
+  if (CheckCapsuleFromRam(PeiServices)) {
+    DEBUG((DEBUG_ERROR, "Capsule On Memory Detected! Quit.\n"));
+    return EFI_ABORTED;
+  }
+
+  DEBUG_CODE (
+   VOID *CapsuleOnDiskModePpi;
+
+  if (!IsCapsuleOnDiskMode()){
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check Capsule On Disk Relocation flag. If exists, load capsule & create Capsule Hob
+  //
+  Status = PeiServicesLocatePpi (
+             &gEfiPeiBootInCapsuleOnDiskModePpiGuid,
+             0,
+             NULL,
+             (VOID **)&CapsuleOnDiskModePpi
+             );
+    if (EFI_ERROR(Status)) {
+      DEBUG((DEBUG_ERROR, "Locate CapsuleOnDiskModePpi error %x\n", Status));
+      return Status;
+    }
+  );
+
+  Status = (**PeiServices).InstallPpi (PeiServices, &mCapsuleOnDiskPpiList);
+  ASSERT_EFI_ERROR (Status);
+
+  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);
+  Status = PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *) PcdGetPtr(PcdCoDRelocationFileName));
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Loads a DXE capsule from some media into memory and updates the HOB table
+  with the DXE firmware volume information.
+
+  @param[in]  PeiServices   General-purpose services that are available to every PEIM.
+  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
+
+  @retval EFI_SUCCESS        The capsule was loaded correctly.
+  @retval EFI_DEVICE_ERROR   A device error occurred.
+  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadCapsuleOnDisk (
+  IN EFI_PEI_SERVICES                     **PeiServices,
+  IN EFI_PEI_CAPSULE_ON_DISK_PPI          *This
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_PEI_DEVICE_RECOVERY_MODULE_PPI  *DeviceRecoveryPpi;
+  UINTN                               NumberRecoveryCapsules;
+  UINTN                               Instance;
+  UINTN                               CapsuleInstance;
+  UINTN                               CapsuleSize;
+  EFI_GUID                            CapsuleType;
+  VOID                                *CapsuleBuffer;
+
+  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Load Capsule On Disk Entry\n"));
+
+  for (Instance = 0; ; Instance++) {
+    Status = PeiServicesLocatePpi (
+               &gEfiPeiDeviceRecoveryModulePpiGuid,
+               Instance,
+               NULL,
+               (VOID **)&DeviceRecoveryPpi
+               );
+    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LocateRecoveryPpi (%d) - %r\n", Instance, Status));
+    if (EFI_ERROR (Status)) {
+      if (Instance == 0) {
+        REPORT_STATUS_CODE (
+          EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+          (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
+          );
+      }
+      break;
+    }
+    NumberRecoveryCapsules = 0;
+    Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
+                                  (EFI_PEI_SERVICES **)PeiServices,
+                                  DeviceRecoveryPpi,
+                                  &NumberRecoveryCapsules
+                                  );
+    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules, Status));
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    for (CapsuleInstance = 1; CapsuleInstance <= NumberRecoveryCapsules; CapsuleInstance++) {
+      CapsuleSize = 0;
+      Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
+                                    (EFI_PEI_SERVICES **)PeiServices,
+                                    DeviceRecoveryPpi,
+                                    CapsuleInstance,
+                                    &CapsuleSize,
+                                    &CapsuleType
+                                    );
+      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - GetRecoveryCapsuleInfo (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+      //
+      // Allocate the memory so that it gets preserved into DXE.
+      // Capsule is special because it may need to populate to system table
+      //
+      CapsuleBuffer = AllocateRuntimePages (EFI_SIZE_TO_PAGES (CapsuleSize));
+
+      if (CapsuleBuffer == NULL) {
+        DEBUG ((DEBUG_ERROR, "LoadCapsuleOnDisk - AllocateRuntimePages fail\n"));
+        continue;
+      }
+
+      Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
+                                    (EFI_PEI_SERVICES **)PeiServices,
+                                    DeviceRecoveryPpi,
+                                    CapsuleInstance,
+                                    CapsuleBuffer
+                                    );
+      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LoadRecoveryCapsule (%d) - %r\n", CapsuleInstance, Status));
+      if (EFI_ERROR (Status)) {
+        FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
+        break;
+      }
+
+      //
+      // Capsule Update Mode, Split relocated Capsule buffer into different capsule vehical hobs.
+      //
+      Status = RetrieveRelocatedCapsule(CapsuleBuffer, CapsuleSize);
+
+      break;
+    }
+
+    if (EFI_ERROR (Status)) {
+      REPORT_STATUS_CODE (
+        EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+        (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
+        );
+    }
+
+    return Status;
+  }
+
+  //
+  // Any attack against GPT, Relocation Info Variable or temp relocation file will result in no Capsule HOB and return EFI_NOT_FOUND.
+  // After flow to DXE phase. since no capsule hob is detected. Platform will clear Info flag and force restart.
+  // No volunerability will be exposed
+  //
+
+  return EFI_NOT_FOUND;
+}
diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
new file mode 100644
index 0000000000..4af07440b7
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
@@ -0,0 +1,64 @@
+## @file
+# Load Capsule on Disk module.
+#
+# Load Capsule On Disk from Root Directory file system. Create CV hob
+# based on temporary Capsule On Disk file.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = CapsuleOnDiskLoadPei
+  MODULE_UNI_FILE                = CapsuleOnDiskLoadPei.uni
+  FILE_GUID                      = 8ADEDF9E-2EC8-40fb-AE56-B76D90225D2D
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeCapsuleOnDiskLoad
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  CapsuleOnDiskLoadPei.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  PeimEntryPoint
+  DebugLib
+  HobLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  ReportStatusCodeLib
+
+[Ppis]
+  gEdkiiPeiCapsuleOnDiskPpiGuid           ## PRODUCES
+  gEfiPeiReadOnlyVariable2PpiGuid         ## CONSUMES
+  gEfiPeiBootInCapsuleOnDiskModePpiGuid   ## SOMETIMES_CONSUMES
+  gEfiPeiDeviceRecoveryModulePpiGuid      ## CONSUMES
+  gPeiCapsulePpiGuid                      ## CONSUMES
+
+[Guids]
+  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ## Variable L"CodRelocationInfo"
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName                 ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax                            ## CONSUMES
+
+[PcdEx]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName                      ## PRODUCES
+
+[depex]
+  gEfiPeiBootInCapsuleOnDiskModePpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  CapsuleOnDiskLoadPeiExtra.uni
diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni
new file mode 100644
index 0000000000..c3eae6a5c2
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Caspule On Disk Load module.
+//
+// Load Capsule On Disk and build CV hob.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Caspule On Disk Load module."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Load Capsule On Disk and build CV hob."
diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiExtra.uni b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiExtra.uni
new file mode 100644
index 0000000000..81034f6294
--- /dev/null
+++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiExtra.uni
@@ -0,0 +1,14 @@
+// /** @file
+// CapsuleOnDiskLoadPei Localized Strings and Content
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"CapsuleOnDiskLoad PEI Driver"
+
+
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel][Patch v2 4/7] MdeModulePkg/BdsDxe: Support Capsule On Disk.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
                   ` (2 preceding siblings ...)
  2019-06-05 15:41 ` [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM Xu, Wei6
@ 2019-06-05 15:42 ` Xu, Wei6
  2019-06-05 15:42 ` [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature Xu, Wei6
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:42 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Chao B Zhang, Wei6 Xu

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

Set EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit of
"OsIndicationsSupported" variable to indicate the Capsule On
Disk is supported or not, according to PcdCapsuleOnDiskSupport.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdeModulePkg/Universal/BdsDxe/BdsDxe.inf | 3 ++-
 MdeModulePkg/Universal/BdsDxe/BdsEntry.c | 6 +++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
index 6913389d34..3d13c725ce 100644
--- a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+++ b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
@@ -3,11 +3,11 @@
 #
 #  When DxeCore dispatching all DXE driver, this module will produce architecture protocol
 #  gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry
 #  interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered.
 #
-#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
 
 [Defines]
@@ -93,10 +93,11 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor                    ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision                  ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand              ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable              ## SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdTestKeyUsed                       ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport              ## CONSUMES
 
 [Depex]
   TRUE
 
 [UserExtensions.TianoCore."ExtraFiles"]
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
index 9d312bd982..2a4ae9f488 100644
--- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
+++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
@@ -3,11 +3,11 @@
   When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed
   which contains interface of BdsEntry.
   After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked
   to enter BDS phase.
 
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -550,10 +550,14 @@ BdsFormalizeOSIndicationVariable (
     EfiBootManagerFreeLoadOption (&BootManagerMenu);
   } else {
     OsIndicationSupport = EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY;
   }
 
+  if (PcdGetBool(PcdCapsuleOnDiskSupport)) {
+    OsIndicationSupport |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
+  }
+
   Status = gRT->SetVariable (
                   EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME,
                   &gEfiGlobalVariableGuid,
                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                   sizeof(UINT64),
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
                   ` (3 preceding siblings ...)
  2019-06-05 15:42 ` [edk2-devel][Patch v2 4/7] MdeModulePkg/BdsDxe: Support Capsule On Disk Xu, Wei6
@ 2019-06-05 15:42 ` Xu, Wei6
  2019-06-12  7:49   ` Wu, Hao A
  2019-06-05 15:42 ` [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule On Disk Xu, Wei6
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:42 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Chao B Zhang, Wei6 Xu

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

Introduce PcdCapsuleInRamSupport to turn on/off Capsule In Ram feature.
Platform could choose to drop CapsulePei/CapsuleX64 and not to support
Capsule In Ram.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf |  1 +
 MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c      | 10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
index 338577e293..9da450722b 100644
--- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -88,10 +88,11 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ## CONSUMES
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ## SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ## SOMETIMES_CONSUMES # Populate Image requires reset support.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ## CONSUMES
 
 [Pcd.X64]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize   ## SOMETIMES_CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ## SOMETIMES_CONSUMES
 
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
index aaf819c4c6..53a1af44e2 100644
--- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
@@ -2,11 +2,11 @@
   Capsule Runtime Driver produces two UEFI capsule runtime services.
   (UpdateCapsule, QueryCapsuleCapabilities)
   It installs the Capsule Architectural Protocol defined in PI1.0a to signify
   the capsule runtime services are ready.
 
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include "CapsuleService.h"
@@ -69,10 +69,18 @@ UpdateCapsule (
   BOOLEAN                   NeedReset;
   BOOLEAN                   InitiateReset;
   CHAR16                    CapsuleVarName[30];
   CHAR16                    *TempVarName;
 
+  //
+  // Check if platform support Capsule In RAM or not.
+  // Platform could choose to drop CapsulePei/CapsuleX64 and do not support Capsule In RAM.
+  //
+  if (!PcdGetBool(PcdCapsuleInRamSupport)) {
+    return EFI_UNSUPPORTED;
+  }
+
   //
   // Capsule Count can't be less than one.
   //
   if (CapsuleCount < 1) {
     return EFI_INVALID_PARAMETER;
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule On Disk.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
                   ` (4 preceding siblings ...)
  2019-06-05 15:42 ` [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature Xu, Wei6
@ 2019-06-05 15:42 ` Xu, Wei6
  2019-06-12  7:49   ` Wu, Hao A
  2019-06-05 15:42 ` [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib Xu, Wei6
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:42 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Chao B Zhang, Wei6 Xu

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

If Capsule On Disk mode, call Capsule On Disk Load PPI to load
capsules. When it fails, still goes to Firmware Update boot path.
BDS will clear corresponding indicator and reboot later on.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h   |  3 ++-
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 20 ++++++++++--------
 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c  | 37 ++++++++++++++++++++++++++++++++-
 3 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
index 063fefb414..90b5b5b211 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
@@ -1,10 +1,10 @@
 /** @file
   Master header file for DxeIpl PEIM. All source files in this module should
   include this file for common definitions.
 
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #ifndef __PEI_DXEIPL_H__
@@ -19,10 +19,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Ppi/FirmwareVolumeInfo.h>
 #include <Ppi/GuidedSectionExtraction.h>
 #include <Ppi/LoadFile.h>
 #include <Ppi/S3Resume2.h>
 #include <Ppi/RecoveryModule.h>
+#include <Ppi/CapsuleOnDisk.h>
 #include <Ppi/VectorHandoffInfo.h>
 
 #include <Guid/MemoryTypeInformation.h>
 #include <Guid/MemoryAllocationHob.h>
 #include <Guid/FirmwareFileSystem2.h>
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index 62bb3f3077..ff036d8688 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -3,11 +3,11 @@
 #
 #  This module produces a special PPI named the DXE Initial Program Load (IPL)
 #  PPI to discover and dispatch the DXE Foundation and components that are
 #  needed to run the DXE Foundation.
 #
-#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -74,21 +74,23 @@
 
 [LibraryClasses.ARM, LibraryClasses.AARCH64]
   ArmMmuLib
 
 [Ppis]
-  gEfiDxeIplPpiGuid                 ## PRODUCES
-  gEfiPeiDecompressPpiGuid          ## PRODUCES
-  gEfiEndOfPeiSignalPpiGuid         ## SOMETIMES_PRODUCES # Not produced on S3 boot path
-  gEfiPeiReadOnlyVariable2PpiGuid   ## SOMETIMES_CONSUMES
-  gEfiPeiLoadFilePpiGuid            ## SOMETIMES_CONSUMES
-  gEfiPeiS3Resume2PpiGuid           ## SOMETIMES_CONSUMES # Consumed on S3 boot path
-  gEfiPeiRecoveryModulePpiGuid      ## SOMETIMES_CONSUMES # Consumed on recovery boot path
+  gEfiDxeIplPpiGuid                      ## PRODUCES
+  gEfiPeiDecompressPpiGuid               ## PRODUCES
+  gEfiEndOfPeiSignalPpiGuid              ## SOMETIMES_PRODUCES # Not produced on S3 boot path
+  gEfiPeiReadOnlyVariable2PpiGuid        ## SOMETIMES_CONSUMES
+  gEfiPeiLoadFilePpiGuid                 ## SOMETIMES_CONSUMES
+  gEfiPeiS3Resume2PpiGuid                ## SOMETIMES_CONSUMES # Consumed on S3 boot path
+  gEfiPeiRecoveryModulePpiGuid           ## SOMETIMES_CONSUMES # Consumed on recovery boot path
   ## SOMETIMES_CONSUMES
   ## UNDEFINED # HOB
   gEfiVectorHandoffInfoPpiGuid
-  gEfiPeiMemoryDiscoveredPpiGuid    ## SOMETIMES_CONSUMES
+  gEfiPeiMemoryDiscoveredPpiGuid         ## SOMETIMES_CONSUMES
+  gEfiPeiBootInCapsuleOnDiskModePpiGuid  ## SOMETIMES_CONSUMES
+  gEdkiiPeiCapsuleOnDiskPpiGuid          ## SOMETIMES_CONSUMES # Consumed on firmware update boot path
 
 [Guids]
   ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation"
   ## SOMETIMES_PRODUCES ## HOB
   gEfiMemoryTypeInformationGuid
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
index c6e5b83309..9dc2d4485f 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -1,11 +1,11 @@
 /** @file
   Last PEIM.
   Responsibility of this module is to load the DXE Core from a Firmware Volume.
 
 Copyright (c) 2016 HP Development Company, L.P.
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include "DxeIpl.h"
@@ -263,17 +263,38 @@ DxeLoadCore (
   UINTN                                     Instance;
   UINT32                                    AuthenticationState;
   UINTN                                     DataSize;
   EFI_PEI_S3_RESUME2_PPI                    *S3Resume;
   EFI_PEI_RECOVERY_MODULE_PPI               *PeiRecovery;
+  EFI_PEI_CAPSULE_ON_DISK_PPI               *PeiCapsuleOnDisk;
   EFI_MEMORY_TYPE_INFORMATION               MemoryData[EfiMaxMemoryType + 1];
+  VOID                                      *CapsuleOnDiskModePpi;
+  BOOLEAN                                   IsCapsuleOnDiskMode;
+
+  IsCapsuleOnDiskMode = FALSE;
 
   //
   // if in S3 Resume, restore configure
   //
   BootMode = GetBootModeHob ();
 
+  //
+  // If Capsule On Disk mode, call storage stack to read Capsule Relocation file
+  // IoMmmu is highly recommmended to enable before reading
+  //
+  if (BootMode == BOOT_ON_FLASH_UPDATE) {
+    Status = PeiServicesLocatePpi (
+               &gEfiPeiBootInCapsuleOnDiskModePpiGuid,
+               0,
+               NULL,
+               &CapsuleOnDiskModePpi
+               );
+    if (!EFI_ERROR(Status)) {
+      IsCapsuleOnDiskMode = TRUE;
+    }
+  }
+
   if (BootMode == BOOT_ON_S3_RESUME) {
     Status = PeiServicesLocatePpi (
                &gEfiPeiS3Resume2PpiGuid,
                0,
                NULL,
@@ -328,10 +349,24 @@ DxeLoadCore (
     }
     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));
     //
     // Now should have a HOB with the DXE core
     //
+  } else if (IsCapsuleOnDiskMode) {
+    Status = PeiServicesLocatePpi (
+               &gEdkiiPeiCapsuleOnDiskPpiGuid,
+               0,
+               NULL,
+               (VOID **) &PeiCapsuleOnDisk
+               );
+
+    //
+    // Whether failed, still goes to Firmware Update boot path. BDS will clear corresponding indicator and reboot later on
+    //
+    if (!EFI_ERROR (Status)) {
+      Status = PeiCapsuleOnDisk->LoadCapsuleOnDisk (PeiServices, PeiCapsuleOnDisk);
+    }
   }
 
   if (GetFirstGuidHob ((CONST EFI_GUID *)&gEfiMemoryTypeInformationGuid) == NULL) {
     //
     // Don't build GuidHob if GuidHob has been installed.
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
                   ` (5 preceding siblings ...)
  2019-06-05 15:42 ` [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule On Disk Xu, Wei6
@ 2019-06-05 15:42 ` Xu, Wei6
  2019-06-12  7:49   ` Wu, Hao A
  2019-06-05 21:53 ` [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Felix Polyudov
  2019-06-12  7:47 ` Wu, Hao A
  8 siblings, 1 reply; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-05 15:42 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Chao B Zhang, Wei6 Xu

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

CoDCheckCapsuleOnDiskFlag() is to check if CapsuleOnDisk flag in
"OsIndications" Variable is enabled. It is used to indicate whether
capsule on disk is provisioned in normal boot path.

CoDClearCapsuleOnDiskFlag() is to to clear CapsuleOnDisk flags,
including "OsIndications" and "BootNext" variable.

CoDRelocateCapsule() is to relocate the capsules from EFI system
partition. Depends on PcdCapsuleInRamSupport, there are two solutions
to relocate the capsule on disk images:
When Capsule In Ram is supported, the Capsule On Disk images are
relocated into memory, and call UpdateCapsule() service to deliver
the capsules.
When Capsule In Ram is not supported, the Capsule On Disk images are
relocated into a temp file which will be stored in root directory on
a platform specific storage device. CapsuleOnDiskLoadPei PEIM will
retrieve the capsules from the relocation temp file and report
capsule hobs for them.

CoDRemoveTempFile() is to remove the relocation temp file in the next
boot after capsules are processed.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdeModulePkg/Include/Library/CapsuleLib.h          |   94 +-
 .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       | 1983 ++++++++++++++++++++
 .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |   63 +
 .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |   56 +-
 .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |   21 +-
 .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |  121 +-
 .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |   67 +-
 .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |    3 +-
 .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |   85 +-
 9 files changed, 2466 insertions(+), 27 deletions(-)
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h

diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h b/MdeModulePkg/Include/Library/CapsuleLib.h
index 1fc2fba3a2..f3cb17cbf9 100644
--- a/MdeModulePkg/Include/Library/CapsuleLib.h
+++ b/MdeModulePkg/Include/Library/CapsuleLib.h
@@ -1,17 +1,37 @@
 /** @file
 
   This library class defines a set of interfaces for how to process capsule image updates.
 
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #ifndef __CAPSULE_LIB_H__
 #define __CAPSULE_LIB_H__
 
+#include <Guid/FileInfo.h>
+
+
+typedef struct {
+  //
+  // image address.
+  //
+  VOID             *ImageAddress;
+  //
+  // The file info of the image comes from.
+  //  if FileInfo == NULL. means image does not come from file
+  //
+  EFI_FILE_INFO    *FileInfo;
+} IMAGE_INFO;
+
+//
+// BOOLEAN Variable to save the total size of all Capsule On Disk during relocation
+//
+#define COD_RELOCATION_INFO_VAR_NAME   L"CodRelocationInfo"
+
 /**
   The firmware checks whether the capsule image is supported
   by the CapsuleGuid in CapsuleHeader or if there is other specific information in
   the capsule image.
 
@@ -79,6 +99,78 @@ EFI_STATUS
 EFIAPI
 ProcessCapsules (
   VOID
   );
 
+/**
+  This routine is called to check if CapsuleOnDisk flag in OsIndications Variable
+  is enabled.
+
+  @retval TRUE     Flag is enabled
+  @retval FALSE    Flag is not enabled
+
+**/
+BOOLEAN
+EFIAPI
+CoDCheckCapsuleOnDiskFlag(
+  VOID
+  );
+
+
+/**
+  This routine is called to clear CapsuleOnDisk flags including OsIndications and BootNext variable
+
+  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
+
+**/
+EFI_STATUS
+EFIAPI
+CoDClearCapsuleOnDiskFlag(
+  VOID
+  );
+
+/**
+  Relocate Capsule on Disk from EFI system partition.
+
+  Two solution to deliver Capsule On Disk:
+  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Disk to memory and call UpdateCapsule().
+  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On Disk to a platform-specific NV storage
+  device with BlockIo protocol.
+
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  Side Effects:
+    Capsule Delivery Supported Flag in OsIndication variable and BootNext variable will be cleared.
+    Solution B: Content corruption. Block IO write directly touches low level write. Orignal partitions, file
+  systems of the relocation device will be corrupted.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoDRelocateCapsule(
+  UINTN     MaxRetry
+  );
+
+/**
+  Remove the temp file from the root of EFI System Partition.
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Remove the temp file successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+CoDRemoveTempFile (
+  UINTN    MaxRetry
+  );
+
 #endif
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
new file mode 100644
index 0000000000..5f1edbbbae
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
@@ -0,0 +1,1983 @@
+/** @file
+  The implementation supports Capusle on Disk.
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CapsuleOnDisk.h"
+
+/**
+  Return if this capsule is a capsule name capsule, based upon CapsuleHeader.
+
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+  @retval TRUE  It is a capsule name capsule.
+  @retval FALSE It is not a capsule name capsule.
+**/
+BOOLEAN
+IsCapsuleNameCapsule (
+  IN EFI_CAPSULE_HEADER         *CapsuleHeader
+  );
+
+/**
+  Check the integrity of the capsule name capsule.
+  If the capsule is vaild, return the physical address of each capsule name string.
+
+  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule name capsule.
+  @param[out] CapsuleNameNum  Number of capsule name.
+
+  @retval NULL                Capsule name capsule is not valid.
+  @retval CapsuleNameBuf      Array of capsule name physical address.
+
+**/
+EFI_PHYSICAL_ADDRESS *
+ValidateCapsuleNameCapsuleIntegrity (
+  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,
+  OUT UINTN                         *CapsuleNameNum
+  )
+{
+  UINT8                    *CapsuleNamePtr;
+  UINT8                    *CapsuleNameBufStart;
+  UINT8                    *CapsuleNameBufEnd;
+  UINTN                    Index;
+  UINTN                    StringSize;
+  EFI_PHYSICAL_ADDRESS     *CapsuleNameBuf;
+
+  if (!IsCapsuleNameCapsule (CapsuleHeader)) {
+    return NULL;
+  }
+
+  //
+  // Total string size must be even.
+  //
+  if (((CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize) & BIT0) != 0) {
+    return NULL;
+  }
+
+  *CapsuleNameNum = 0;
+  Index = 0;
+  CapsuleNameBufStart = (UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize;
+
+  //
+  // If strings are not aligned on a 16-bit boundary, reallocate memory for it.
+  //
+  if (((UINTN) CapsuleNameBufStart & BIT0) != 0) {
+    CapsuleNameBufStart = AllocateCopyPool (CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize, CapsuleNameBufStart);
+  }
+
+  CapsuleNameBufEnd = CapsuleNameBufStart + CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
+
+  CapsuleNamePtr = CapsuleNameBufStart;
+  while (CapsuleNamePtr < CapsuleNameBufEnd) {
+    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd - CapsuleNamePtr)/sizeof(CHAR16));
+    CapsuleNamePtr += StringSize;
+    (*CapsuleNameNum) ++;
+  }
+
+  //
+  // Integrity check.
+  //
+  if (CapsuleNamePtr != CapsuleNameBufEnd) {
+    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize) {
+      FreePool (CapsuleNameBufStart);
+    }
+    return NULL;
+  }
+
+  CapsuleNameBuf = AllocatePool (*CapsuleNameNum * sizeof (EFI_PHYSICAL_ADDRESS));
+  if (CapsuleNameBuf == NULL) {
+    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize) {
+      FreePool (CapsuleNameBufStart);
+    }
+    return NULL;
+  }
+
+  CapsuleNamePtr = CapsuleNameBufStart;
+  while (CapsuleNamePtr < CapsuleNameBufEnd) {
+    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd - CapsuleNamePtr)/sizeof(CHAR16));
+    CapsuleNameBuf[Index] = (EFI_PHYSICAL_ADDRESS)(UINTN) CapsuleNamePtr;
+    CapsuleNamePtr += StringSize;
+    Index ++;
+  }
+
+  return CapsuleNameBuf;
+}
+
+/**
+  This routine is called to upper case given unicode string.
+
+  @param[in]   Str              String to upper case
+
+  @retval upper cased string after process
+
+**/
+STATIC
+CHAR16 *
+UpperCaseString (
+  IN CHAR16 *Str
+  )
+{
+  CHAR16  *Cptr;
+
+  for (Cptr = Str; *Cptr; Cptr++) {
+    if (L'a' <= *Cptr && *Cptr <= L'z') {
+      *Cptr = *Cptr - L'a' + L'A';
+    }
+  }
+
+  return Str;
+}
+
+/**
+  This routine is used to return substring before period '.' or '\0'
+  Caller should respsonsible of substr space allocation & free
+
+  @param[in]   Str              String to check
+  @param[out]  SubStr           First part of string before period or '\0'
+  @param[out]  SubStrLen        Length of first part of string
+
+**/
+STATIC
+VOID
+GetSubStringBeforePeriod (
+  IN  CHAR16 *Str,
+  OUT CHAR16 *SubStr,
+  OUT UINTN  *SubStrLen
+  )
+{
+  UINTN Index;
+  for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {
+    SubStr[Index] = Str[Index];
+  }
+
+  SubStr[Index] = L'\0';
+  *SubStrLen = Index;
+}
+
+/**
+  This routine pad the string in tail with input character.
+
+  @param[in]   StrBuf            Str buffer to be padded, should be enough room for
+  @param[in]   PadLen            Expected padding length
+  @param[in]   Character         Character used to pad
+
+**/
+STATIC
+VOID
+PadStrInTail (
+  IN CHAR16   *StrBuf,
+  IN UINTN    PadLen,
+  IN CHAR16   Character
+  )
+{
+  UINTN Index;
+
+  for (Index = 0; StrBuf[Index] != L'\0'; Index++);
+
+  while(PadLen != 0) {
+    StrBuf[Index] = Character;
+    Index++;
+    PadLen--;
+  }
+
+  StrBuf[Index] = L'\0';
+}
+
+/**
+  This routine find the offset of the last period '.' of string. If No period exists
+  function FileNameExtension is set to L'\0'
+
+  @param[in]  FileName           File name to split between last period
+  @param[out] FileNameFirst      First FileName before last period
+  @param[out] FileNameExtension  FileName after last period
+
+**/
+STATIC
+VOID
+SplitFileNameExtension (
+  IN CHAR16   *FileName,
+  OUT CHAR16  *FileNameFirst,
+  OUT CHAR16  *FileNameExtension
+  )
+{
+  UINTN Index;
+  UINTN StringLen;
+
+  StringLen = StrnLenS(FileName, MAX_FILE_NAME_SIZE);
+  for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--);
+
+  //
+  // No period exists. No FileName Extension
+  //
+  if (Index == 0 && FileName[Index] != L'.') {
+    FileNameExtension[0] = L'\0';
+    Index = StringLen;
+  } else {
+    StrCpyS(FileNameExtension, MAX_FILE_NAME_SIZE, &FileName[Index+1]);
+  }
+
+  //
+  // Copy First file name
+  //
+  StrnCpyS(FileNameFirst, MAX_FILE_NAME_SIZE, FileName, Index);
+  FileNameFirst[Index] = L'\0';
+}
+
+/**
+  This routine is called to get all boot options in the order determnined by:
+    1. "OptionBuf"
+    2. "BootOrder"
+
+  @param[out] OptionBuf           BootList buffer to all boot options returned
+  @param[out] OptionCount         BootList count of all boot options returned
+
+  @retval EFI_SUCCESS             There is no error when processing capsule
+
+**/
+EFI_STATUS
+GetBootOptionInOrder(
+  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf,
+  OUT UINTN                        *OptionCount
+  )
+{
+  EFI_STATUS                   Status;
+  UINTN                        DataSize;
+  UINT16                       BootNext;
+  CHAR16                       BootOptionName[20];
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOrderOptionBuf;
+  UINTN                        BootOrderCount;
+  EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry;
+  UINTN                        BootNextCount;
+  EFI_BOOT_MANAGER_LOAD_OPTION *TempBuf;
+
+  BootOrderOptionBuf  = NULL;
+  TempBuf             = NULL;
+  BootNextCount       = 0;
+  BootOrderCount      = 0;
+  *OptionBuf          = NULL;
+  *OptionCount        = 0;
+
+  //
+  // First Get BootOption from "BootNext"
+  //
+  DataSize = sizeof(BootNext);
+  Status = gRT->GetVariable (
+                  EFI_BOOT_NEXT_VARIABLE_NAME,
+                  &gEfiGlobalVariableGuid,
+                  NULL,
+                  &DataSize,
+                  (VOID *)&BootNext
+                  );
+  //
+  // BootNext variable is a single UINT16
+  //
+  if (!EFI_ERROR(Status) && DataSize == sizeof(UINT16)) {
+    //
+    // Add the boot next boot option
+    //
+    UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", BootNext);
+    ZeroMem(&BootNextOptionEntry, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
+    Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootNextOptionEntry);
+
+    if (!EFI_ERROR(Status)) {
+      BootNextCount = 1;
+    }
+  }
+
+  //
+  // Second get BootOption from "BootOrder"
+  //
+  BootOrderOptionBuf = EfiBootManagerGetLoadOptions (&BootOrderCount, LoadOptionTypeBoot);
+  if (BootNextCount == 0 && BootOrderCount == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // At least one BootOption is found
+  //
+  TempBuf = AllocatePool(sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * (BootNextCount + BootOrderCount));
+  if (TempBuf != NULL) {
+    if (BootNextCount == 1) {
+      CopyMem(TempBuf, &BootNextOptionEntry, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
+    }
+
+    if (BootOrderCount > 0) {
+      CopyMem(TempBuf + BootNextCount, BootOrderOptionBuf, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * BootOrderCount);
+    }
+
+    *OptionBuf   = TempBuf;
+    *OptionCount = BootNextCount + BootOrderCount;
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_OUT_OF_RESOURCES;
+  }
+
+  FreePool(BootOrderOptionBuf);
+
+  return Status;
+}
+
+/**
+  This routine is called to get boot option by OptionNumber.
+
+  @param[in] Number               The OptionNumber of boot option
+  @param[out] OptionBuf           BootList buffer to all boot options returned
+
+  @retval EFI_SUCCESS             There is no error when getting boot option
+
+**/
+EFI_STATUS
+GetBootOptionByNumber(
+  IN  UINT16                       Number,
+  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf
+  )
+{
+  EFI_STATUS                    Status;
+  CHAR16                        BootOptionName[20];
+  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
+
+  UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", Number);
+  ZeroMem (&BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+  Status = EfiBootManagerVariableToLoadOption (BootOptionName, &BootOption);
+
+  if (!EFI_ERROR (Status)) {
+    *OptionBuf = AllocatePool (sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+    CopyMem (*OptionBuf, &BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
+    return EFI_SUCCESS;
+  }
+
+  return Status;
+}
+
+/**
+  Get Active EFI System Partition within GPT based on device path.
+
+  @param[in] DevicePath    Device path to find a active EFI System Partition
+  @param[out] FsHandle     BootList points to all boot options returned
+
+  @retval EFI_SUCCESS      Active EFI System Partition is succesfully found
+  @retval EFI_NOT_FOUND    No Active EFI System Partition is found
+
+**/
+EFI_STATUS
+GetEfiSysPartitionFromDevPath(
+  IN EFI_DEVICE_PATH_PROTOCOL         *DevicePath,
+  OUT EFI_HANDLE                      *FsHandle
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
+  HARDDRIVE_DEVICE_PATH           *Hd;
+  EFI_HANDLE                      Handle;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
+
+  //
+  // Check if the device path contains GPT node
+  //
+  TempDevicePath = DevicePath;
+  while (!IsDevicePathEnd (TempDevicePath)) {
+    if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
+       (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP)) {
+      Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
+      if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
+        break;
+      }
+    }
+    TempDevicePath = NextDevicePathNode (TempDevicePath);
+  }
+
+  if (!IsDevicePathEnd (TempDevicePath)) {
+    //
+    // Search for EFI system partition protocol on full device path in Boot Option
+    //
+    Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, &DevicePath, &Handle);
+
+    //
+    // Search for simple file system on this handler
+    //
+    if (!EFI_ERROR(Status)) {
+      Status = gBS->HandleProtocol(Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+      if (!EFI_ERROR(Status)) {
+        *FsHandle = Handle;
+        return EFI_SUCCESS;
+      }
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  This routine is called to get Simple File System protocol on the first EFI system partition found in
+  active boot option. The boot option list is detemined in order by
+    1. "BootNext"
+    2. "BootOrder"
+
+  @param[in]       MaxRetry           Max Connection Retry. Stall 100ms between each connection try to ensure
+                                      device like USB can get enumerated.
+  @param[in, out]  LoadOptionNumber   On input, specify the boot option to get EFI system partition.
+                                      On output, return the OptionNumber of the boot option where EFI
+                                      system partition is got from.
+  @param[out]      FsFsHandle         Simple File System Protocol found on first active EFI system partition
+
+  @retval EFI_SUCCESS     Simple File System protocol found for EFI system partition
+  @retval EFI_NOT_FOUND   No Simple File System protocol found for EFI system partition
+
+**/
+EFI_STATUS
+GetEfiSysPartitionFromActiveBootOption(
+  IN UINTN                             MaxRetry,
+  IN OUT UINT16                        **LoadOptionNumber,
+  OUT EFI_HANDLE                       *FsHandle
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuf;
+  UINTN                        BootOptionNum;
+  UINTN                        Index;
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL     *CurFullPath;
+  EFI_DEVICE_PATH_PROTOCOL     *PreFullPath;
+
+  *FsHandle = NULL;
+
+  if (*LoadOptionNumber != NULL) {
+    BootOptionNum = 1;
+    Status = GetBootOptionByNumber(**LoadOptionNumber, &BootOptionBuf);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "GetBootOptionByIndex Failed %x! No BootOption available for connection\n", Status));
+      return Status;
+    }
+  } else {
+    Status = GetBootOptionInOrder(&BootOptionBuf, &BootOptionNum);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "GetBootOptionInOrder Failed %x! No BootOption available for connection\n", Status));
+      return Status;
+    }
+  }
+
+  //
+  // Search BootOptionList to check if it is an active boot option with EFI system partition
+  //  1. Connect device path
+  //  2. expend short/plug in devicepath
+  //  3. LoadImage
+  //
+  for (Index = 0; Index < BootOptionNum; Index++) {
+    //
+    // Get the boot option from the link list
+    //
+    DevicePath  = BootOptionBuf[Index].FilePath;
+
+    //
+    // Skip inactive or legacy boot options
+    //
+    if ((BootOptionBuf[Index].Attributes & LOAD_OPTION_ACTIVE) == 0 ||
+        DevicePathType (DevicePath) == BBS_DEVICE_PATH) {
+      continue;
+    }
+
+    DEBUG_CODE (
+      CHAR16 *DevicePathStr;
+
+      DevicePathStr = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
+      if (DevicePathStr != NULL){
+        DEBUG((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr));
+        FreePool(DevicePathStr);
+      } else {
+        DEBUG((DEBUG_INFO, "DevicePathToStr failed\n"));
+      }
+    );
+
+    CurFullPath = NULL;
+    //
+    // Try every full device Path generated from bootoption
+    //
+    do {
+      PreFullPath = CurFullPath;
+      CurFullPath = EfiBootManagerGetNextLoadOptionDevicePath(DevicePath, CurFullPath);
+
+      if (PreFullPath != NULL) {
+        FreePool (PreFullPath);
+      }
+
+      if (CurFullPath == NULL) {
+        //
+        // No Active EFI system partition is found in BootOption device path
+        //
+        Status = EFI_NOT_FOUND;
+        break;
+      }
+
+      DEBUG_CODE (
+        CHAR16 *DevicePathStr1;
+
+        DevicePathStr1 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);
+        if (DevicePathStr1 != NULL){
+          DEBUG((DEBUG_INFO, "Full device path %s\n", DevicePathStr1));
+          FreePool(DevicePathStr1);
+        }
+      );
+
+      //
+      // Make sure the boot option device path connected.
+      // Only handle first device in boot option. Other optional device paths are described as OSV specific
+      // FullDevice could contain extra directory & file info. So don't check connection status here.
+      //
+      EfiBootManagerConnectDevicePath (CurFullPath, NULL);
+      Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);
+
+      //
+      // Some relocation device like USB need more time to get enumerated
+      //
+      while (EFI_ERROR(Status) && MaxRetry > 0) {
+        EfiBootManagerConnectDevicePath(CurFullPath, NULL);
+
+        //
+        // Search for EFI system partition protocol on full device path in Boot Option
+        //
+        Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);
+        if (!EFI_ERROR(Status)) {
+          break;
+        }
+        DEBUG((DEBUG_ERROR, "GetEfiSysPartitionFromDevPath Loop %x\n", Status));
+        //
+        // Stall 100ms if connection failed to ensure USB stack is ready
+        //
+        gBS->Stall(100000);
+        MaxRetry --;
+      }
+    } while(EFI_ERROR(Status));
+
+    //
+    // Find a qualified Simple File System
+    //
+    if (!EFI_ERROR(Status)) {
+      break;
+    }
+
+  }
+
+  //
+  // Return the OptionNumber of the boot option where EFI system partition is got from
+  //
+  if (*LoadOptionNumber == NULL) {
+    *LoadOptionNumber = AllocateCopyPool (sizeof(UINT16), (UINT16 *) &BootOptionBuf[Index].OptionNumber);
+  }
+
+  //
+  // No qualified EFI system partition found
+  //
+  if (*FsHandle == NULL) {
+    Status = EFI_NOT_FOUND;
+  }
+
+  DEBUG_CODE (
+    CHAR16 *DevicePathStr2;
+    if (*FsHandle != NULL) {
+      DevicePathStr2 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);
+      if (DevicePathStr2 != NULL){
+        DEBUG((DEBUG_INFO, "Found Active EFI System Partion on %s\n", DevicePathStr2));
+        FreePool(DevicePathStr2);
+      }
+    } else {
+      DEBUG((DEBUG_INFO, "Failed to found Active EFI System Partion\n"));
+    }
+  );
+
+  if (CurFullPath != NULL) {
+    FreePool(CurFullPath);
+  }
+
+  //
+  // Free BootOption Buffer
+  //
+  for (Index = 0; Index < BootOptionNum; Index++) {
+    if (BootOptionBuf[Index].Description != NULL) {
+      FreePool(BootOptionBuf[Index].Description);
+    }
+
+    if (BootOptionBuf[Index].FilePath != NULL) {
+      FreePool(BootOptionBuf[Index].FilePath);
+    }
+
+    if (BootOptionBuf[Index].OptionalData != NULL) {
+      FreePool(BootOptionBuf[Index].OptionalData);
+    }
+  }
+
+  FreePool(BootOptionBuf);
+
+  return Status;
+}
+
+
+/**
+  This routine is called to get all file infos with in a given dir & with given file attribute, the file info is listed in
+  alphabetical order described in UEFI spec.
+
+  @param[in]  Dir                 Directory file handler
+  @param[in]  FileAttr            Attribute of file to be red from directory
+  @param[out] FileInfoList        File images info list red from directory
+  @param[out] FileNum             File images number red from directory
+
+  @retval EFI_SUCCESS             File FileInfo list in the given
+
+**/
+EFI_STATUS
+GetFileInfoListInAlphabetFromDir(
+  IN EFI_FILE_HANDLE  Dir,
+  IN UINT64           FileAttr,
+  OUT LIST_ENTRY      *FileInfoList,
+  OUT UINTN           *FileNum
+  )
+{
+  EFI_STATUS        Status;
+  FILE_INFO_ENTRY   *NewFileInfoEntry;
+  FILE_INFO_ENTRY   *TempFileInfoEntry;
+  EFI_FILE_INFO     *FileInfo;
+  CHAR16            *NewFileName;
+  CHAR16            *ListedFileName;
+  CHAR16            *NewFileNameExtension;
+  CHAR16            *ListedFileNameExtension;
+  CHAR16            *TempNewSubStr;
+  CHAR16            *TempListedSubStr;
+  LIST_ENTRY        *Link;
+  BOOLEAN           NoFile;
+  UINTN             FileCount;
+  UINTN             IndexNew;
+  UINTN             IndexListed;
+  UINTN             NewSubStrLen;
+  UINTN             ListedSubStrLen;
+  INTN              SubStrCmpResult;
+
+  Status                  = EFI_SUCCESS;
+  NewFileName             = NULL;
+  ListedFileName          = NULL;
+  NewFileNameExtension    = NULL;
+  ListedFileNameExtension = NULL;
+  TempNewSubStr           = NULL;
+  TempListedSubStr        = NULL;
+  NoFile                  = FALSE;
+  FileCount               = 0;
+
+  InitializeListHead(FileInfoList);
+
+  TempNewSubStr           = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);
+  TempListedSubStr        = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);
+
+  if (TempNewSubStr == NULL || TempListedSubStr == NULL ) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  for ( Status = FileHandleFindFirstFile(Dir, &FileInfo)
+      ; !EFI_ERROR(Status) && !NoFile
+      ; Status = FileHandleFindNextFile(Dir, FileInfo, &NoFile)
+     ){
+
+    //
+    // Skip file with mismatching File attribute
+    //
+    if ((FileInfo->Attribute & (FileAttr)) == 0) {
+      continue;
+    }
+
+    NewFileInfoEntry = NULL;
+    NewFileInfoEntry = (FILE_INFO_ENTRY*)AllocateZeroPool(sizeof(FILE_INFO_ENTRY));
+    if (NewFileInfoEntry == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+    NewFileInfoEntry->Signature = FILE_INFO_SIGNATURE;
+    NewFileInfoEntry->FileInfo  = AllocateCopyPool((UINTN) FileInfo->Size, FileInfo);
+    if (NewFileInfoEntry->FileInfo == NULL) {
+      FreePool(NewFileInfoEntry);
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+
+    NewFileInfoEntry->FileNameFirstPart  = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);
+    if (NewFileInfoEntry->FileNameFirstPart == NULL) {
+      FreePool(NewFileInfoEntry->FileInfo);
+      FreePool(NewFileInfoEntry);
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+    NewFileInfoEntry->FileNameSecondPart = (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SIZE);
+    if (NewFileInfoEntry->FileNameSecondPart == NULL) {
+      FreePool(NewFileInfoEntry->FileInfo);
+      FreePool(NewFileInfoEntry->FileNameFirstPart);
+      FreePool(NewFileInfoEntry);
+      Status = EFI_OUT_OF_RESOURCES;
+      goto EXIT;
+    }
+
+    //
+    // Splitter the whole New file name into 2 parts between the last period L'.' into NewFileName NewFileExtension
+    // If no period in the whole file name. NewFileExtension is set to L'\0'
+    //
+    NewFileName          = NewFileInfoEntry->FileNameFirstPart;
+    NewFileNameExtension = NewFileInfoEntry->FileNameSecondPart;
+    SplitFileNameExtension(FileInfo->FileName, NewFileName, NewFileNameExtension);
+    UpperCaseString(NewFileName);
+    UpperCaseString(NewFileNameExtension);
+
+    //
+    // Insert capsule file in alphabetical ordered list
+    //
+    for (Link = FileInfoList->ForwardLink; Link != FileInfoList; Link = Link->ForwardLink) {
+      //
+      // Get the FileInfo from the link list
+      //
+      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
+      ListedFileName          = TempFileInfoEntry->FileNameFirstPart;
+      ListedFileNameExtension = TempFileInfoEntry->FileNameSecondPart;
+
+      //
+      // Follow rule in UEFI spec 8.5.5 to compare file name
+      //
+      IndexListed = 0;
+      IndexNew    = 0;
+      while (TRUE){
+        //
+        // First compare each substrings in NewFileName & ListedFileName between periods
+        //
+        GetSubStringBeforePeriod(&NewFileName[IndexNew], TempNewSubStr, &NewSubStrLen);
+        GetSubStringBeforePeriod(&ListedFileName[IndexListed], TempListedSubStr, &ListedSubStrLen);
+        if (NewSubStrLen > ListedSubStrLen) {
+          //
+          // Substr in NewFileName is longer. Pad tail with SPACE
+          //
+          PadStrInTail(TempListedSubStr, NewSubStrLen - ListedSubStrLen, L' ');
+        } else if (NewSubStrLen < ListedSubStrLen){
+          //
+          // Substr in ListedFileName is longer. Pad tail with SPACE
+          //
+          PadStrInTail(TempNewSubStr, ListedSubStrLen - NewSubStrLen, L' ');
+        }
+
+        SubStrCmpResult = StrnCmp(TempNewSubStr, TempListedSubStr, MAX_FILE_NAME_LEN);
+        if (SubStrCmpResult != 0) {
+          break;
+        }
+
+        //
+        // Move to skip this substring
+        //
+        IndexNew    += NewSubStrLen;
+        IndexListed += ListedSubStrLen;
+        //
+        // Reach File First Name end
+        //
+        if (NewFileName[IndexNew] == L'\0' || ListedFileName[IndexListed] == L'\0') {
+          break;
+        }
+
+        //
+        // Skip the period L'.'
+        //
+        IndexNew++;
+        IndexListed++;
+      }
+
+      if (SubStrCmpResult < 0) {
+        //
+        // NewFileName is smaller. Find the right place to insert New file
+        //
+        break;
+      } else if (SubStrCmpResult == 0) {
+        //
+        // 2 cases whole NewFileName is smaller than ListedFileName
+        //   1. if NewFileName == ListedFileName. Continue to compare FileNameExtension
+        //   2. if NewFileName is shorter than ListedFileName
+        //
+        if (NewFileName[IndexNew] == L'\0') {
+          if (ListedFileName[IndexListed] != L'\0' || (StrnCmp(NewFileNameExtension, ListedFileNameExtension, MAX_FILE_NAME_LEN) < 0)) {
+            break;
+          }
+        }
+      }
+
+      //
+      // Other case, ListedFileName is smaller. Continue to compare the next file in the list
+      //
+    }
+
+    //
+    // If Find an entry in the list whose name is bigger than new FileInfo in alphabet order
+    //    Insert it before this entry
+    // else
+    //    Insert at the tail of this list (Link = FileInfoList)
+    //
+    InsertTailList(Link, &NewFileInfoEntry->Link);
+
+    FileCount++;
+  }
+
+  *FileNum = FileCount;
+
+EXIT:
+
+  if (TempNewSubStr != NULL) {
+    FreePool(TempNewSubStr);
+  }
+
+  if (TempListedSubStr != NULL) {
+    FreePool(TempListedSubStr);
+  }
+
+  if (EFI_ERROR(Status)) {
+    while(!IsListEmpty(FileInfoList)) {
+      Link = FileInfoList->ForwardLink;
+      RemoveEntryList(Link);
+
+      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
+
+      FreePool(TempFileInfoEntry->FileInfo);
+      FreePool(TempFileInfoEntry->FileNameFirstPart);
+      FreePool(TempFileInfoEntry->FileNameSecondPart);
+      FreePool(TempFileInfoEntry);
+    }
+    *FileNum = 0;
+  }
+
+  return Status;
+}
+
+
+/**
+  This routine is called to get all qualified image from file from an given directory
+  in alphabetic order. All the file image is copied to allocated boottime memory.
+  Caller should free these memory
+
+  @param[in]  Dir            Directory file handler
+  @param[in]  FileAttr       Attribute of file to be red from directory
+  @param[out] FilePtr        File images Info buffer red from directory
+  @param[out] FileNum        File images number red from directory
+
+  @retval EFI_SUCCESS  Succeed to get all capsules in alphabetic order.
+
+**/
+EFI_STATUS
+GetFileImageInAlphabetFromDir(
+  IN EFI_FILE_HANDLE   Dir,
+  IN UINT64            FileAttr,
+  OUT IMAGE_INFO       **FilePtr,
+  OUT UINTN            *FileNum
+  )
+{
+  EFI_STATUS            Status;
+  LIST_ENTRY            *Link;
+  EFI_FILE_HANDLE       FileHandle;
+  FILE_INFO_ENTRY       *FileInfoEntry;
+  EFI_FILE_INFO         *FileInfo;
+  UINTN                 FileCount;
+  IMAGE_INFO            *TempFilePtrBuf;
+  UINTN                 Size;
+  LIST_ENTRY            FileInfoList;
+
+  FileHandle       = NULL;
+  FileCount        = 0;
+  TempFilePtrBuf   = NULL;
+  *FilePtr         = NULL;
+
+  //
+  // Get file list in Dir in alphabetical order
+  //
+  Status = GetFileInfoListInAlphabetFromDir(
+             Dir,
+             FileAttr,
+             &FileInfoList,
+             &FileCount
+             );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n"));
+    goto EXIT;
+  }
+
+  if (FileCount == 0) {
+    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));
+    Status = EFI_NOT_FOUND;
+    goto EXIT;
+  }
+
+  TempFilePtrBuf = (IMAGE_INFO *)AllocateZeroPool(sizeof(IMAGE_INFO) * FileCount);
+  if (TempFilePtrBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  //
+  // Read all files from FileInfoList to BS memory
+  //
+  FileCount = 0;
+  for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link->ForwardLink) {
+    //
+    // Get FileInfo from the link list
+    //
+    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
+    FileInfo      = FileInfoEntry->FileInfo;
+
+    Status = Dir->Open(
+                    Dir,
+                    &FileHandle,
+                    FileInfo->FileName,
+                    EFI_FILE_MODE_READ,
+                    0
+                    );
+    if (EFI_ERROR(Status)){
+      continue;
+    }
+
+    Size = (UINTN)FileInfo->FileSize;
+    TempFilePtrBuf[FileCount].ImageAddress = AllocateZeroPool(Size);
+    if (TempFilePtrBuf[FileCount].ImageAddress == NULL) {
+      DEBUG((DEBUG_ERROR, "Fail to allocate memory for capsule. Stop processing the rest.\n"));
+      break;
+    }
+
+    Status = FileHandle->Read(
+                           FileHandle,
+                           &Size,
+                           TempFilePtrBuf[FileCount].ImageAddress
+                           );
+
+    FileHandle->Close(FileHandle);
+
+    //
+    // Skip read error file
+    //
+    if (EFI_ERROR(Status) || Size != (UINTN)FileInfo->FileSize) {
+      //
+      // Remove this error file info accordingly
+      // & move Link to BackLink
+      //
+      Link = RemoveEntryList(Link);
+      Link = Link->BackLink;
+
+      FreePool(FileInfoEntry->FileInfo);
+      FreePool(FileInfoEntry->FileNameFirstPart);
+      FreePool(FileInfoEntry->FileNameSecondPart);
+      FreePool(FileInfoEntry);
+
+      FreePool(TempFilePtrBuf[FileCount].ImageAddress);
+      TempFilePtrBuf[FileCount].ImageAddress = NULL;
+      TempFilePtrBuf[FileCount].FileInfo     = NULL;
+
+      continue;
+    }
+    TempFilePtrBuf[FileCount].FileInfo = FileInfo;
+    FileCount++;
+  }
+
+  DEBUG_CODE (
+    for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link->ForwardLink) {
+      FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
+      FileInfo      = FileInfoEntry->FileInfo;
+      DEBUG((DEBUG_INFO, "Successfully read capsule file %s from disk.\n", FileInfo->FileName));
+    }
+  );
+
+EXIT:
+
+  *FilePtr = TempFilePtrBuf;
+  *FileNum = FileCount;
+
+  //
+  // FileInfo will be freed by Calller
+  //
+  while(!IsListEmpty(&FileInfoList)) {
+    Link = FileInfoList.ForwardLink;
+    RemoveEntryList(Link);
+
+    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
+
+    FreePool(FileInfoEntry->FileNameFirstPart);
+    FreePool(FileInfoEntry->FileNameSecondPart);
+    FreePool(FileInfoEntry);
+  }
+
+  return Status;
+}
+
+/**
+  This routine is called to remove all qualified image from file from an given directory.
+
+  @param[in] Dir                  Directory file handler
+  @param[in] FileAttr             Attribute of files to be deleted
+
+  @retval EFI_SUCCESS  Succeed to remove all files from an given directory.
+
+**/
+EFI_STATUS
+RemoveFileFromDir(
+  IN EFI_FILE_HANDLE   Dir,
+  IN UINT64            FileAttr
+  )
+{
+  EFI_STATUS        Status;
+  LIST_ENTRY        *Link;
+  LIST_ENTRY        FileInfoList;
+  EFI_FILE_HANDLE   FileHandle;
+  FILE_INFO_ENTRY   *FileInfoEntry;
+  EFI_FILE_INFO     *FileInfo;
+  UINTN             FileCount;
+
+  FileHandle = NULL;
+
+  //
+  // Get file list in Dir in alphabetical order
+  //
+  Status = GetFileInfoListInAlphabetFromDir(
+             Dir,
+             FileAttr,
+             &FileInfoList,
+             &FileCount
+             );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n"));
+    goto EXIT;
+  }
+
+  if (FileCount == 0) {
+    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));
+    Status = EFI_NOT_FOUND;
+    goto EXIT;
+  }
+
+  //
+  // Delete all files with given attribute in Dir
+  //
+  for (Link = FileInfoList.ForwardLink; Link != &(FileInfoList); Link = Link->ForwardLink) {
+    //
+    // Get FileInfo from the link list
+    //
+    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
+    FileInfo      = FileInfoEntry->FileInfo;
+
+    Status = Dir->Open(
+                    Dir,
+                    &FileHandle,
+                    FileInfo->FileName,
+                    EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
+                    0
+                    );
+    if (EFI_ERROR(Status)){
+      continue;
+    }
+
+    Status = FileHandle->Delete(FileHandle);
+  }
+
+EXIT:
+
+  while(!IsListEmpty(&FileInfoList)) {
+    Link = FileInfoList.ForwardLink;
+    RemoveEntryList(Link);
+
+    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
+
+    FreePool(FileInfoEntry->FileInfo);
+    FreePool(FileInfoEntry);
+  }
+
+  return Status;
+}
+
+/**
+  This routine is called to get all caspules from file. The capsule file image is
+  copied to BS memory. Caller is responsible to free them.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+  @param[out]   CapsulePtr           Copied Capsule file Image Info buffer
+  @param[out]   CapsuleNum           CapsuleNumber
+  @param[out]   FsHandle             File system handle
+  @param[out]   LoadOptionNumber     OptionNumber of boot option
+
+  @retval EFI_SUCCESS  Succeed to get all capsules.
+
+**/
+EFI_STATUS
+EFIAPI
+GetAllCapsuleOnDisk(
+  IN  UINTN                            MaxRetry,
+  OUT IMAGE_INFO                       **CapsulePtr,
+  OUT UINTN                            *CapsuleNum,
+  OUT EFI_HANDLE                       *FsHandle,
+  OUT UINT16                            *LoadOptionNumber
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
+  EFI_FILE_HANDLE                  RootDir;
+  EFI_FILE_HANDLE                  FileDir;
+  UINT16                           *TempOptionNumber;
+
+  Fs               = NULL;
+  RootDir          = NULL;
+  FileDir          = NULL;
+  TempOptionNumber = NULL;
+  *CapsuleNum      = 0;
+
+  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry, &TempOptionNumber, FsHandle);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol(*FsHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = Fs->OpenVolume(Fs, &RootDir);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = RootDir->Open(
+                      RootDir,
+                      &FileDir,
+                      EFI_CAPSULE_FILE_DIRECTORY,
+                      EFI_FILE_MODE_READ,
+                      0
+                      );
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "CodLibGetAllCapsuleOnDisk fail to open RootDir!\n"));
+    goto EXIT;
+  }
+
+  //
+  // Only Load files with EFI_FILE_SYSTEM or EFI_FILE_ARCHIVE attribute
+  // ignore EFI_FILE_READ_ONLY, EFI_FILE_HIDDEN, EFI_FILE_RESERVED, EFI_FILE_DIRECTORY
+  //
+  Status = GetFileImageInAlphabetFromDir(
+             FileDir,
+             EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE,
+             CapsulePtr,
+             CapsuleNum
+             );
+  DEBUG((DEBUG_INFO, "GetFileImageInAlphabetFromDir status %x\n", Status));
+
+  //
+  // Always remove file to avoid deadloop in capsule process
+  //
+  Status = RemoveFileFromDir(FileDir, EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE);
+  DEBUG((DEBUG_INFO, "RemoveFileFromDir status %x\n", Status));
+
+  if (LoadOptionNumber != NULL) {
+    *LoadOptionNumber = *TempOptionNumber;
+  }
+
+EXIT:
+
+  if (FileDir != NULL) {
+    FileDir->Close (FileDir);
+  }
+
+  if (RootDir != NULL) {
+    RootDir->Close (RootDir);
+  }
+
+  return Status;
+}
+
+/**
+  Build Gather list for a list of capsule images.
+
+  @param[in]  CapsuleBuffer    An array of pointer to capsule images
+  @param[in]  CapsuleSize      An array of UINTN to capsule images size
+  @param[in]  CapsuleNum       The count of capsule images
+  @param[out] BlockDescriptors The block descriptors for the capsule images
+
+  @retval EFI_SUCCESS The block descriptors for the capsule images are constructed.
+
+**/
+EFI_STATUS
+BuildGatherList (
+  IN VOID                          **CapsuleBuffer,
+  IN UINTN                         *CapsuleSize,
+  IN UINTN                         CapsuleNum,
+  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
+  UINTN                         Index;
+
+  BlockDescriptors1      = NULL;
+  BlockDescriptorPre     = NULL;
+  BlockDescriptorsHeader = NULL;
+
+  for (Index = 0; Index < CapsuleNum; Index++) {
+    //
+    // Allocate memory for the descriptors.
+    //
+    BlockDescriptors1  = AllocateZeroPool (2 * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR));
+    if (BlockDescriptors1 == NULL) {
+      DEBUG ((DEBUG_ERROR, "BuildGatherList: failed to allocate memory for descriptors\n"));
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ERREXIT;
+    } else {
+      DEBUG ((DEBUG_INFO, "BuildGatherList: creating capsule descriptors at 0x%X\n", (UINTN) BlockDescriptors1));
+    }
+
+    //
+    // Record descirptor header
+    //
+    if (Index == 0) {
+      BlockDescriptorsHeader = BlockDescriptors1;
+    }
+
+    if (BlockDescriptorPre != NULL) {
+      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
+      BlockDescriptorPre->Length = 0;
+    }
+
+    BlockDescriptors1->Union.DataBlock = (UINTN) CapsuleBuffer[Index];
+    BlockDescriptors1->Length = CapsuleSize[Index];
+
+    BlockDescriptorPre = BlockDescriptors1 + 1;
+    BlockDescriptors1 = NULL;
+  }
+
+  //
+  // Null-terminate.
+  //
+  if (BlockDescriptorPre != NULL) {
+    BlockDescriptorPre->Union.ContinuationPointer = (UINTN)NULL;
+    BlockDescriptorPre->Length = 0;
+    *BlockDescriptors = BlockDescriptorsHeader;
+  }
+
+  return EFI_SUCCESS;
+
+ERREXIT:
+  if (BlockDescriptors1 != NULL) {
+    FreePool (BlockDescriptors1);
+  }
+
+  return Status;
+}
+
+/**
+  This routine is called to check if CapsuleOnDisk flag in OsIndications Variable
+  is enabled.
+
+  @retval TRUE     Flag is enabled
+  @retval FALSE    Flag is not enabled
+
+**/
+BOOLEAN
+EFIAPI
+CoDCheckCapsuleOnDiskFlag(
+  VOID
+  )
+{
+  EFI_STATUS            Status;
+  UINT64                OsIndication;
+  UINTN                 DataSize;
+
+  //
+  // Check File Capsule Delivery Supported Flag in OsIndication variable
+  //
+  OsIndication = 0;
+  DataSize     = sizeof(UINT64);
+  Status = gRT->GetVariable (
+                  EFI_OS_INDICATIONS_VARIABLE_NAME,
+                  &gEfiGlobalVariableGuid,
+                  NULL,
+                  &DataSize,
+                  &OsIndication
+                  );
+  if (!EFI_ERROR(Status) &&
+      (OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
+/**
+  This routine is called to clear CapsuleOnDisk flags including OsIndications and BootNext variable.
+
+  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
+
+**/
+EFI_STATUS
+EFIAPI
+CoDClearCapsuleOnDiskFlag(
+  VOID
+  )
+{
+  EFI_STATUS            Status;
+  UINT64                OsIndication;
+  UINTN                 DataSize;
+
+  //
+  // Reset File Capsule Delivery Supported Flag in OsIndication variable
+  //
+  OsIndication = 0;
+  DataSize = sizeof(UINT64);
+  Status = gRT->GetVariable (
+                  EFI_OS_INDICATIONS_VARIABLE_NAME,
+                  &gEfiGlobalVariableGuid,
+                  NULL,
+                  &DataSize,
+                  &OsIndication
+                  );
+  if (EFI_ERROR(Status) ||
+      (OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) == 0) {
+    return Status;
+  }
+
+  OsIndication &= ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
+  Status = gRT->SetVariable (
+                  EFI_OS_INDICATIONS_VARIABLE_NAME,
+                  &gEfiGlobalVariableGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  sizeof(UINT64),
+                  &OsIndication
+                  );
+  ASSERT(!EFI_ERROR(Status));
+
+  //
+  // Delete BootNext variable. Capsule Process may reset system, so can't rely on Bds to clear this variable
+  //
+  Status = gRT->SetVariable (
+                  EFI_BOOT_NEXT_VARIABLE_NAME,
+                  &gEfiGlobalVariableGuid,
+                  0,
+                  0,
+                  NULL
+                  );
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine is called to clear Capsule On Disk Relocation flag
+  The flag is the total size of capsules being relocated. It is saved
+  in CapsuleOnDisk Relocation Info varible in form of UINT64
+
+  @param[out] CapsuleRelocInfo  The value of "CapsuleRelocInfo" variable
+
+  @retval EFI_SUCCESS   Capsule Relocation flag is cleared
+
+**/
+EFI_STATUS
+CoDCheckCapsuleRelocationInfo(
+  OUT BOOLEAN *CapsuleRelocInfo
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       DataSize;
+
+  DataSize = sizeof(BOOLEAN);
+
+  Status= gRT->GetVariable (
+                 COD_RELOCATION_INFO_VAR_NAME,
+                 &gEfiCapsuleVendorGuid,
+                 NULL,
+                 &DataSize,
+                 CapsuleRelocInfo
+                 );
+
+  if (DataSize != sizeof(BOOLEAN)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return Status;
+}
+
+/**
+  This routine is called to clear CapsuleOnDisk Relocation Info variable.
+  Total Capsule On Disk length is recorded in this variable
+
+  @retval EFI_SUCCESS   Capsule On Disk flags are cleared
+
+**/
+EFI_STATUS
+CoDClearCapsuleRelocationInfo(
+  VOID
+  )
+{
+  return gRT->SetVariable (
+                COD_RELOCATION_INFO_VAR_NAME,
+                &gEfiCapsuleVendorGuid,
+                0,
+                0,
+                NULL
+                );
+}
+
+/**
+  Relocate Capsule on Disk from EFI system partition to a platform-specific NV storage device
+  with BlockIo protocol. Relocation device path, identified by PcdCodRelocationDevPath, must
+  be a full device path.
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  Side Effects:
+    Content corruption. Block IO write directly touches low level write. Orignal partitions, file systems
+    of the relocation device will be corrupted.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated to the platform-specific device.
+
+**/
+EFI_STATUS
+EFIAPI
+RelocateCapsuleToDisk(
+  UINTN     MaxRetry
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           CapsuleOnDiskNum;
+  UINTN                           Index;
+  UINTN                           DataSize;
+  UINT64                          TotalImageSize;
+  UINT64                          TotalImageNameSize;
+  IMAGE_INFO                      *CapsuleOnDiskBuf;
+  EFI_HANDLE                      Handle;
+  EFI_HANDLE                      TempHandle;
+  EFI_HANDLE                      *HandleBuffer;
+  UINTN                           NumberOfHandles;
+  EFI_BLOCK_IO_PROTOCOL           *BlockIo;
+  UINT8                           *CapsuleDataBuf;
+  UINT8                           *CapsulePtr;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
+  EFI_FILE_HANDLE                 RootDir;
+  EFI_FILE_HANDLE                 TempCodFile;
+  UINT64                          TempCodFileSize;
+  EFI_DEVICE_PATH                 *TempDevicePath;
+  BOOLEAN                         RelocationInfo;
+  UINT16                          LoadOptionNumber;
+  EFI_CAPSULE_HEADER              FileNameCapsuleHeader;
+
+  RootDir          = NULL;
+  TempCodFile      = NULL;
+  HandleBuffer     = NULL;
+  CapsuleDataBuf   = NULL;
+  CapsuleOnDiskBuf = NULL;
+  NumberOfHandles  = 0;
+
+  DEBUG ((DEBUG_INFO, "CapsuleOnDisk RelocateCapsule Enter\n"));
+
+  //
+  // 1. Load all Capsule On Disks in to memory
+  //
+  Status = GetAllCapsuleOnDisk(MaxRetry, &CapsuleOnDiskBuf, &CapsuleOnDiskNum, &Handle, &LoadOptionNumber);
+  if (EFI_ERROR(Status) || CapsuleOnDiskNum == 0) {
+    DEBUG ((DEBUG_INFO, "RelocateCapsule: GetAllCapsuleOnDisk Status - 0x%x\n", Status));
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // 2. Connect platform special dev path or Use EFI System Partition as relocation device
+  //
+  if (PcdGetSize(PcdCodRelocationDevPath) > sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
+    Status = EfiBootManagerConnectDevicePath ((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocationDevPath), &TempHandle);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "RelocateCapsule: EfiBootManagerConnectDevicePath Status - 0x%x\n", Status));
+      goto EXIT;
+    }
+
+    //
+    // Connect all the child handle. Partition & FAT drivers are allowed in this case
+    //
+    gBS->ConnectController (TempHandle, NULL, NULL, TRUE);
+    Status = gBS->LocateHandleBuffer(
+                    ByProtocol,
+                    &gEfiSimpleFileSystemProtocolGuid,
+                    NULL,
+                    &NumberOfHandles,
+                    &HandleBuffer
+                    );
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "RelocateCapsule: LocateHandleBuffer Status - 0x%x\n", Status));
+      goto EXIT;
+    }
+
+    //
+    // Find first Simple File System Handle which can match PcdCodRelocationDevPath
+    //
+    for (Index = 0; Index < NumberOfHandles; Index++) {
+      Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&TempDevicePath);
+      if (EFI_ERROR(Status)) {
+        continue;
+      }
+
+      DataSize = GetDevicePathSize((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocationDevPath)) - sizeof(EFI_DEVICE_PATH);
+      if (0 == CompareMem((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocationDevPath), TempDevicePath, DataSize)) {
+        Handle = HandleBuffer[Index];
+        break;
+      }
+    }
+
+    FreePool(HandleBuffer);
+
+    if (Index == NumberOfHandles) {
+      DEBUG ((DEBUG_ERROR, "RelocateCapsule: No simple file system protocol found.\n"));
+      Status = EFI_NOT_FOUND;
+    }
+  }
+
+  Status = gBS->HandleProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+  if (EFI_ERROR(Status) || BlockIo->Media->ReadOnly) {
+    DEBUG((DEBUG_ERROR, "Fail to find Capsule on Disk relocation BlockIo device or device is ReadOnly!\n"));
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol(Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // Check if device used to relocate Capsule On Disk is big enough
+  //
+  TotalImageSize     = 0;
+  TotalImageNameSize = 0;
+  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
+    //
+    // Overflow check
+    //
+    if (MAX_ADDRESS - (UINTN)TotalImageSize <= CapsuleOnDiskBuf[Index].FileInfo->FileSize) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (MAX_ADDRESS - (UINTN)TotalImageNameSize <= StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    TotalImageSize     += CapsuleOnDiskBuf[Index].FileInfo->FileSize;
+    TotalImageNameSize += StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName);
+    DEBUG((DEBUG_INFO, "RelocateCapsule: %x Size %x\n",CapsuleOnDiskBuf[Index].FileInfo->FileName, CapsuleOnDiskBuf[Index].FileInfo->FileSize));
+  }
+
+  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageSize %x\n", TotalImageSize));
+  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageNameSize %x\n", TotalImageNameSize));
+
+  if (MAX_ADDRESS - (UINTN)TotalImageNameSize <= sizeof(UINT64) * 2 ||
+      MAX_ADDRESS - (UINTN)TotalImageSize <= (UINTN)TotalImageNameSize + sizeof(UINT64) * 2) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TempCodFileSize = sizeof(UINT64) + TotalImageSize + sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;
+
+  //
+  // Check if CapsuleTotalSize. There could be reminder, so use LastBlock number directly
+  //
+  if (DivU64x32(TempCodFileSize, BlockIo->Media->BlockSize) > BlockIo->Media->LastBlock) {
+    DEBUG((DEBUG_ERROR, "RelocateCapsule: Relocation device isn't big enough to hold all Capsule on Disk!\n"));
+    DEBUG((DEBUG_ERROR, "TotalImageSize = %x\n", TotalImageSize));
+    DEBUG((DEBUG_ERROR, "TotalImageNameSize = %x\n", TotalImageNameSize));
+    DEBUG((DEBUG_ERROR, "RelocationDev BlockSize = %x LastBlock = %x\n", BlockIo->Media->BlockSize, BlockIo->Media->LastBlock));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  CapsuleDataBuf = AllocatePool((UINTN) TempCodFileSize);
+  if (CapsuleDataBuf == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  //
+  // First UINT64 reserved for total image size, including capsule name capsule.
+  //
+  *(UINT64 *) CapsuleDataBuf = TotalImageSize + sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;
+
+  //
+  // Line up all the Capsule on Disk and write to relocation disk at one time. It could save some time in disk write
+  //
+  for (Index = 0, CapsulePtr = CapsuleDataBuf + sizeof(UINT64); Index < CapsuleOnDiskNum; Index++) {
+    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].ImageAddress, (UINTN) CapsuleOnDiskBuf[Index].FileInfo->FileSize);
+    CapsulePtr += CapsuleOnDiskBuf[Index].FileInfo->FileSize;
+  }
+
+  //
+  // Line the capsule header for capsule name capsule.
+  //
+  CopyGuid(&FileNameCapsuleHeader.CapsuleGuid, &gEdkiiCapsuleOnDiskNameGuid);
+  FileNameCapsuleHeader.CapsuleImageSize = (UINT32) TotalImageNameSize + sizeof(EFI_CAPSULE_HEADER);
+  FileNameCapsuleHeader.Flags            = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+  FileNameCapsuleHeader.HeaderSize       = sizeof(EFI_CAPSULE_HEADER);
+  CopyMem(CapsulePtr, &FileNameCapsuleHeader, FileNameCapsuleHeader.HeaderSize);
+  CapsulePtr += FileNameCapsuleHeader.HeaderSize;
+
+  //
+  // Line up all the Capsule file names.
+  //
+  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
+    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].FileInfo->FileName, StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName));
+    CapsulePtr += StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName);
+  }
+
+  //
+  // 5. Flash all Capsules on Disk to TempCoD.tmp under RootDir
+  //
+  Status = Fs->OpenVolume(Fs, &RootDir);
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "RelocateCapsule: OpenVolume error. %x\n", Status));
+    goto EXIT;
+  }
+
+  Status = RootDir->Open(
+                      RootDir,
+                      &TempCodFile,
+                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
+                      0
+                      );
+  if (!EFI_ERROR(Status)) {
+    //
+    // Error handling code to prevent malicious code to hold this file to block capsule on disk
+    //
+    TempCodFile->Delete(TempCodFile);
+  }
+  Status = RootDir->Open(
+                      RootDir,
+                      &TempCodFile,
+                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+                      0
+                      );
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "RelocateCapsule: Open TemCoD.tmp error. %x\n", Status));
+    goto EXIT;
+  }
+
+  //
+  // Always write at the begining of TempCap file
+  //
+  DataSize = (UINTN) TempCodFileSize;
+  Status = TempCodFile->Write(
+                          TempCodFile,
+                          &DataSize,
+                          CapsuleDataBuf
+                          );
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_ERROR, "RelocateCapsule: Write TemCoD.tmp error. %x\n", Status));
+    goto EXIT;
+  }
+
+  if (DataSize != TempCodFileSize) {
+    Status = EFI_DEVICE_ERROR;
+    goto EXIT;
+  }
+
+  //
+  // Save Capsule On Disk relocation info to "CodRelocationInfo" Var
+  // It is used in next reboot by TCB
+  //
+  RelocationInfo = TRUE;
+  Status = gRT->SetVariable(
+                   COD_RELOCATION_INFO_VAR_NAME,
+                   &gEfiCapsuleVendorGuid,
+                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                   sizeof (BOOLEAN),
+                   &RelocationInfo
+                   );
+  //
+  // Save the LoadOptionNumber of the boot option, where the capsule is relocated,
+  // into "CodRelocationLoadOption" var. It is used in next reboot after capsule is
+  // updated out of TCB to remove the TempCoDFile.
+  //
+  Status = gRT->SetVariable(
+                   COD_RELOCATION_LOAD_OPTION_VAR_NAME,
+                   &gEfiCapsuleVendorGuid,
+                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                   sizeof (UINT16),
+                   &LoadOptionNumber
+                   );
+
+EXIT:
+
+  if (CapsuleDataBuf != NULL) {
+    FreePool(CapsuleDataBuf);
+  }
+
+  if (CapsuleOnDiskBuf != NULL) {
+    //
+    // Free resources allocated by CodLibGetAllCapsuleOnDisk
+    //
+    for (Index = 0; Index < CapsuleOnDiskNum; Index++ ) {
+      FreePool(CapsuleOnDiskBuf[Index].ImageAddress);
+      FreePool(CapsuleOnDiskBuf[Index].FileInfo);
+    }
+    FreePool(CapsuleOnDiskBuf);
+  }
+
+  if (TempCodFile != NULL) {
+    if (EFI_ERROR(Status)) {
+      TempCodFile->Delete (TempCodFile);
+    } else {
+      TempCodFile->Close (TempCodFile);
+    }
+  }
+
+  if (RootDir != NULL) {
+    RootDir->Close (RootDir);
+  }
+
+  return Status;
+}
+
+/**
+  For the platforms that support Capsule In Ram, reuse the Capsule In Ram to deliver capsule.
+  Relocate Capsule On Disk to memory and call UpdateCapsule().
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Deliver capsule through Capsule In Ram successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+RelocateCapsuleToRam (
+  UINTN    MaxRetry
+  )
+{
+  EFI_STATUS                    Status;
+  UINTN                         CapsuleOnDiskNum;
+  IMAGE_INFO                    *CapsuleOnDiskBuf;
+  EFI_HANDLE                    Handle;
+  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
+  VOID                          **CapsuleBuffer;
+  UINTN                         *CapsuleSize;
+  EFI_CAPSULE_HEADER            *FileNameCapsule;
+  UINTN                         Index;
+  UINT8                         *StringBuf;
+  UINTN                         StringSize;
+  UINTN                         TotalStringSize;
+
+  CapsuleOnDiskBuf = NULL;
+  BlockDescriptors = NULL;
+  CapsuleBuffer    = NULL;
+  CapsuleSize      = NULL;
+  FileNameCapsule  = NULL;
+  TotalStringSize  = 0;
+
+  //
+  // 1. Load all Capsule On Disks into memory
+  //
+  Status = GetAllCapsuleOnDisk (MaxRetry, &CapsuleOnDiskBuf, &CapsuleOnDiskNum, &Handle, NULL);
+  if (EFI_ERROR (Status) || CapsuleOnDiskNum == 0) {
+    DEBUG ((DEBUG_ERROR, "GetAllCapsuleOnDisk Status - 0x%x\n", Status));
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // 2. Add a capsule for Capsule file name strings
+  //
+  CapsuleBuffer = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof (VOID *));
+  if (CapsuleBuffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CapsuleSize = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof (UINTN));
+  if (CapsuleSize == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
+    CapsuleBuffer[Index] = (VOID *)(UINTN) CapsuleOnDiskBuf[Index].ImageAddress;
+    CapsuleSize[Index] = (UINTN) CapsuleOnDiskBuf[Index].FileInfo->FileSize;
+    TotalStringSize += StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName);
+  }
+
+  FileNameCapsule = AllocateZeroPool (sizeof (EFI_CAPSULE_HEADER) + TotalStringSize);
+  if (FileNameCapsule == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for name capsule.\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  FileNameCapsule->CapsuleImageSize = (UINT32) (sizeof (EFI_CAPSULE_HEADER) + TotalStringSize);
+  FileNameCapsule->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+  FileNameCapsule->HeaderSize = sizeof (EFI_CAPSULE_HEADER);
+  CopyGuid (&(FileNameCapsule->CapsuleGuid), &gEdkiiCapsuleOnDiskNameGuid);
+
+  StringBuf = (UINT8 *)FileNameCapsule + FileNameCapsule->HeaderSize;
+  for (Index = 0; Index < CapsuleOnDiskNum; Index ++) {
+    StringSize = StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName);
+    CopyMem (StringBuf, CapsuleOnDiskBuf[Index].FileInfo->FileName, StringSize);
+    StringBuf += StringSize;
+  }
+
+  CapsuleBuffer[CapsuleOnDiskNum] = FileNameCapsule;
+  CapsuleSize[CapsuleOnDiskNum] = TotalStringSize + sizeof (EFI_CAPSULE_HEADER);
+
+  //
+  // 3. Build Gather list for the capsules
+  //
+  Status = BuildGatherList (CapsuleBuffer, CapsuleSize, CapsuleOnDiskNum + 1, &BlockDescriptors);
+  if (EFI_ERROR (Status) || BlockDescriptors == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // 4. Call UpdateCapsule() service
+  //
+  Status = gRT->UpdateCapsule((EFI_CAPSULE_HEADER **) CapsuleBuffer, CapsuleOnDiskNum + 1, (UINTN) BlockDescriptors);
+
+  return Status;
+}
+
+/**
+  Relocate Capsule on Disk from EFI system partition.
+
+  Two solution to deliver Capsule On Disk:
+  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Disk to memory and call UpdateCapsule().
+  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On Disk to a platform-specific NV storage
+  device with BlockIo protocol.
+
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  Side Effects:
+    Capsule Delivery Supported Flag in OsIndication variable and BootNext variable will be cleared.
+    Solution B: Content corruption. Block IO write directly touches low level write. Orignal partitions, file
+  systems of the relocation device will be corrupted.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoDRelocateCapsule(
+  UINTN     MaxRetry
+  )
+{
+  if (!PcdGetBool (PcdCapsuleOnDiskSupport)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Clear CapsuleOnDisk Flag firstly.
+  //
+  CoDClearCapsuleOnDiskFlag ();
+
+  //
+  // If Capsule In Ram is supported, delivery capsules through memory
+  //
+  if (PcdGetBool (PcdCapsuleInRamSupport)) {
+    DEBUG ((DEBUG_INFO, "Capsule In Ram is supported, call gRT->UpdateCapsule().\n"));
+    return RelocateCapsuleToRam (MaxRetry);
+  } else {
+    DEBUG ((DEBUG_INFO, "Reallcoate all Capsule on Disks to %s in RootDir.\n", (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName)));
+    return RelocateCapsuleToDisk (MaxRetry);
+  }
+}
+
+/**
+  Remove the temp file from the root of EFI System Partition.
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Remove the temp file successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+CoDRemoveTempFile (
+  UINTN    MaxRetry
+  )
+{
+  EFI_STATUS                       Status;
+  UINTN                            DataSize;
+  UINT16                           *LoadOptionNumber;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
+  EFI_HANDLE                       FsHandle;
+  EFI_FILE_HANDLE                  RootDir;
+  EFI_FILE_HANDLE                  TempCodFile;
+
+  RootDir     = NULL;
+  TempCodFile = NULL;
+
+  LoadOptionNumber = AllocatePool (sizeof(UINT16));
+  DataSize = sizeof(UINT16);
+
+  //
+  // Check if capsule files are relocated
+  //
+  Status = gRT->GetVariable (
+                  COD_RELOCATION_LOAD_OPTION_VAR_NAME,
+                  &gEfiCapsuleVendorGuid,
+                  NULL,
+                  &DataSize,
+                  (VOID *)LoadOptionNumber
+                  );
+  if (EFI_ERROR(Status) || DataSize != sizeof(UINT16)) {
+    return Status;
+  }
+
+  //
+  // Get the EFI file system from the boot option where the capsules are relocated
+  //
+  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry, &LoadOptionNumber, &FsHandle);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol(FsHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Status = Fs->OpenVolume(Fs, &RootDir);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // Delete the TempCoDFile
+  //
+  Status = RootDir->Open(
+                      RootDir,
+                      &TempCodFile,
+                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
+                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
+                      0
+                      );
+  if (!EFI_ERROR(Status)) {
+    TempCodFile->Delete(TempCodFile);
+  }
+
+  if (RootDir != NULL) {
+    RootDir->Close(RootDir);
+  }
+
+  //
+  // Clear "CoDRelocationLoadOption" variable
+  //
+  Status = gRT->SetVariable (
+             COD_RELOCATION_LOAD_OPTION_VAR_NAME,
+             &gEfiCapsuleVendorGuid,
+             0,
+             0,
+             NULL
+             );
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
new file mode 100644
index 0000000000..064dc791b8
--- /dev/null
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
@@ -0,0 +1,63 @@
+/** @file
+  Defines several datastructures used by Capsule On Disk feature.
+  They are mainly used for FAT files.
+
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CAPSULES_ON_DISK_H_
+#define _CAPSULES_ON_DISK_H_
+
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootManagerLib.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/BlockIo.h>
+
+#include <Guid/CapsuleVendor.h>
+#include <Guid/GlobalVariable.h>
+
+//
+// This data structure is the part of FILE_INFO_ENTRY
+//
+#define FILE_INFO_SIGNATURE SIGNATURE_32 ('F', 'L', 'I', 'F')
+
+//
+// LoadOptionNumber of the boot option where the capsules is relocated.
+//
+#define COD_RELOCATION_LOAD_OPTION_VAR_NAME   L"CodRelocationLoadOption"
+
+typedef struct {
+  UINTN           Signature;
+  LIST_ENTRY      Link;                  ///  Linked list members.
+  EFI_FILE_INFO   *FileInfo;             ///  Pointer to the FileInfo struct for this file or NULL.
+  CHAR16          *FileNameFirstPart;    ///  Text to the left of right-most period in the file name. String is capitialized
+  CHAR16          *FileNameSecondPart;   ///  Text to the right of right-most period in the file name.String is capitialized. Maybe NULL
+} FILE_INFO_ENTRY;
+
+//
+// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)
+//
+#define MAX_FILE_NAME_SIZE   522
+#define MAX_FILE_NAME_LEN    (MAX_FILE_NAME_SIZE / sizeof(CHAR16))
+
+#define MAX_FILE_INFO_LEN    (OFFSET_OF(EFI_FILE_INFO, FileName) + MAX_FILE_NAME_LEN)
+
+#endif // _CAPSULES_ON_DISK_H_
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
index f38ab69e38..4254cc8270 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
@@ -8,11 +8,11 @@
 
   SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),
   ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and
   performs basic validation.
 
-  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include <PiDxe.h>
@@ -88,11 +88,12 @@ EFI_STATUS
 RecordFmpCapsuleStatusVariable (
   IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
   IN EFI_STATUS                                    CapsuleStatus,
   IN UINTN                                         PayloadIndex,
   IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader,
-  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath OPTIONAL
+  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath, OPTIONAL
+  IN CHAR16                                        *CapFileName    OPTIONAL
   );
 
 /**
   Function indicate the current completion progress of the firmware
   update. Platform may override with own specific progress function.
@@ -107,10 +108,26 @@ EFI_STATUS
 EFIAPI
 UpdateImageProgress (
   IN UINTN  Completion
   );
 
+/**
+  Return if this capsule is a capsule name capsule, based upon CapsuleHeader.
+
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+  @retval TRUE  It is a capsule name capsule.
+  @retval FALSE It is not a capsule name capsule.
+**/
+BOOLEAN
+IsCapsuleNameCapsule (
+  IN EFI_CAPSULE_HEADER         *CapsuleHeader
+  )
+{
+  return CompareGuid (&CapsuleHeader->CapsuleGuid, &gEdkiiCapsuleOnDiskNameGuid);
+}
+
 /**
   Return if this CapsuleGuid is a FMP capsule GUID or not.
 
   @param[in] CapsuleGuid A pointer to EFI_GUID
 
@@ -1032,23 +1049,25 @@ StartFmpImage (
 }
 
 /**
   Record FMP capsule status.
 
-  @param[in]  Handle        A FMP handle.
+  @param[in] Handle         A FMP handle.
   @param[in] CapsuleHeader  The capsule image header
   @param[in] CapsuleStatus  The capsule process stauts
   @param[in] PayloadIndex   FMP payload index
   @param[in] ImageHeader    FMP image header
+  @param[in] CapFileName    Capsule file name
 **/
 VOID
 RecordFmpCapsuleStatus (
   IN EFI_HANDLE                                    Handle,  OPTIONAL
   IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
   IN EFI_STATUS                                    CapsuleStatus,
   IN UINTN                                         PayloadIndex,
-  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader
+  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader,
+  IN CHAR16                                        *CapFileName   OPTIONAL
   )
 {
   EFI_STATUS                                    Status;
   EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath;
   UINT32                                        FmpImageInfoDescriptorVer;
@@ -1068,11 +1087,12 @@ RecordFmpCapsuleStatus (
   RecordFmpCapsuleStatusVariable (
     CapsuleHeader,
     CapsuleStatus,
     PayloadIndex,
     ImageHeader,
-    FmpDevicePath
+    FmpDevicePath,
+    CapFileName
     );
 
   //
   // Update corresponding ESRT entry LastAttemp Status
   //
@@ -1113,10 +1133,11 @@ RecordFmpCapsuleStatus (
   EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
 
   This function need support nested FMP capsule.
 
   @param[in]  CapsuleHeader         Points to a capsule header.
+  @param[in]  CapFileName           Capsule file name.
   @param[out] ResetRequired         Indicates whether reset is required or not.
 
   @retval EFI_SUCESS            Process Capsule Image successfully.
   @retval EFI_UNSUPPORTED       Capsule image is not supported by the firmware.
   @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
@@ -1124,10 +1145,11 @@ RecordFmpCapsuleStatus (
   @retval EFI_NOT_READY         No FMP protocol to handle this FMP capsule.
 **/
 EFI_STATUS
 ProcessFmpCapsuleImage (
   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN CHAR16              *CapFileName,  OPTIONAL
   OUT BOOLEAN            *ResetRequired OPTIONAL
   )
 {
   EFI_STATUS                                    Status;
   EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER        *FmpCapsuleHeader;
@@ -1143,11 +1165,11 @@ ProcessFmpCapsuleImage (
   UINTN                                         Index2;
   BOOLEAN                                       NotReady;
   BOOLEAN                                       Abort;
 
   if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
-    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);
+    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName, ResetRequired);
   }
 
   NotReady = FALSE;
   Abort = FALSE;
 
@@ -1225,11 +1247,12 @@ ProcessFmpCapsuleImage (
       RecordFmpCapsuleStatus (
         NULL,
         CapsuleHeader,
         EFI_NOT_READY,
         Index - FmpCapsuleHeader->EmbeddedDriverCount,
-        ImageHeader
+        ImageHeader,
+        CapFileName
         );
       continue;
     }
 
     for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
@@ -1237,11 +1260,12 @@ ProcessFmpCapsuleImage (
         RecordFmpCapsuleStatus (
           HandleBuffer[Index2],
           CapsuleHeader,
           EFI_ABORTED,
           Index - FmpCapsuleHeader->EmbeddedDriverCount,
-          ImageHeader
+          ImageHeader,
+          CapFileName
           );
         continue;
       }
 
       Status = SetFmpImageData (
@@ -1260,11 +1284,12 @@ ProcessFmpCapsuleImage (
       RecordFmpCapsuleStatus (
         HandleBuffer[Index2],
         CapsuleHeader,
         Status,
         Index - FmpCapsuleHeader->EmbeddedDriverCount,
-        ImageHeader
+        ImageHeader,
+        CapFileName
         );
     }
     if (HandleBuffer != NULL) {
       FreePool(HandleBuffer);
     }
@@ -1412,10 +1437,17 @@ SupportCapsuleImage (
   //
   if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
     return EFI_SUCCESS;
   }
 
+  //
+  // Check capsule file name capsule
+  //
+  if (IsCapsuleNameCapsule(CapsuleHeader)) {
+    return EFI_SUCCESS;
+  }
+
   if (IsFmpCapsule(CapsuleHeader)) {
     //
     // Fake capsule header is valid case in QueryCapsuleCpapbilities().
     //
     if (CapsuleHeader->HeaderSize == CapsuleHeader->CapsuleImageSize) {
@@ -1434,10 +1466,11 @@ SupportCapsuleImage (
   The firmware implements to process the capsule image.
 
   Caution: This function may receive untrusted input.
 
   @param[in]  CapsuleHeader         Points to a capsule header.
+  @param[in]  CapFileName           Capsule file name.
   @param[out] ResetRequired         Indicates whether reset is required or not.
 
   @retval EFI_SUCESS            Process Capsule Image successfully.
   @retval EFI_UNSUPPORTED       Capsule image is not supported by the firmware.
   @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
@@ -1445,10 +1478,11 @@ SupportCapsuleImage (
 **/
 EFI_STATUS
 EFIAPI
 ProcessThisCapsuleImage (
   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN CHAR16              *CapFileName,  OPTIONAL
   OUT BOOLEAN            *ResetRequired OPTIONAL
   )
 {
   EFI_STATUS                   Status;
 
@@ -1482,11 +1516,11 @@ ProcessThisCapsuleImage (
 
     //
     // Process EFI FMP Capsule
     //
     DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
-    Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);
+    Status = ProcessFmpCapsuleImage(CapsuleHeader, CapFileName, ResetRequired);
     DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
 
     return Status;
   }
 
@@ -1509,11 +1543,11 @@ EFI_STATUS
 EFIAPI
 ProcessCapsuleImage (
   IN EFI_CAPSULE_HEADER  *CapsuleHeader
   )
 {
-  return ProcessThisCapsuleImage (CapsuleHeader, NULL);
+  return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL);
 }
 
 /**
   Callback function executed when the EndOfDxe event group is signaled.
 
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
index 14c3d19bc3..05de4299fb 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
@@ -1,11 +1,11 @@
 ## @file
 #  Capsule library instance for DXE_DRIVER.
 #
 #  Capsule library instance for DXE_DRIVER module types.
 #
-#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
 
 [Defines]
@@ -27,10 +27,12 @@
 
 [Sources]
   DxeCapsuleLib.c
   DxeCapsuleProcessLib.c
   DxeCapsuleReportLib.c
+  CapsuleOnDisk.c
+  CapsuleOnDisk.h
 
 [Packages]
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
 
@@ -45,10 +47,12 @@
   ReportStatusCodeLib
   PrintLib
   HobLib
   BmpSupportLib
   DisplayUpdateProgressLib
+  FileHandleLib
+  UefiBootManagerLib
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax                               ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag      ## CONSUMES
 
@@ -57,23 +61,38 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd      ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware        ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess   ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed    ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem         ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport                      ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport                     ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath                     ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName                    ## CONSUMES
 
 [Protocols]
   gEsrtManagementProtocolGuid                   ## CONSUMES
   gEfiFirmwareManagementProtocolGuid            ## CONSUMES
   gEdkiiVariableLockProtocolGuid                ## SOMETIMES_CONSUMES
   gEdkiiFirmwareManagementProgressProtocolGuid  ## SOMETIMES_CONSUMES
+  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
+  gEfiBlockIoProtocolGuid                       ## CONSUMES
+  gEfiDiskIoProtocolGuid                        ## CONSUMES
 
 [Guids]
   gEfiFmpCapsuleGuid                      ## SOMETIMES_CONSUMES ## GUID
   gWindowsUxCapsuleGuid                   ## SOMETIMES_CONSUMES ## GUID
   ## SOMETIMES_CONSUMES ## Variable:L"CapsuleMax"
   ## SOMETIMES_PRODUCES ## Variable:L"CapsuleMax"
   gEfiCapsuleReportGuid
   gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
   gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
+  gEfiPartTypeSystemPartGuid              ## SOMETIMES_CONSUMES
+  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ## Variable:L"CodRelocationInfo"
+  ## SOMETIMES_CONSUMES ## Variable:L"OsIndications"
+  ## SOMETIMES_PRODUCES ## Variable:L"OsIndications"
+  ## SOMETIMES_CONSUMES ## Variable:L"BootNext"
+  ## SOMETIMES_PRODUCES ## Variable:L"BootNext"
+  gEfiGlobalVariableGuid
+  gEdkiiCapsuleOnDiskNameGuid             ## SOMETIMES_CONSUMES ## GUID
 
 [Depex]
   gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
index 5e2d2b87a8..e07dd7986e 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
@@ -7,11 +7,11 @@
   buffer overflow, integer overflow.
 
   ProcessCapsules(), ProcessTheseCapsules() will receive untrusted
   input and do basic validation.
 
-  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include <PiDxe.h>
@@ -90,14 +90,45 @@ BOOLEAN
 IsValidCapsuleHeader (
   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
   IN UINT64              CapsuleSize
   );
 
+/**
+  Return if this capsule is a capsule name capsule, based upon CapsuleHeader.
+
+  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
+
+  @retval TRUE  It is a capsule name capsule.
+  @retval FALSE It is not a capsule name capsule.
+**/
+BOOLEAN
+IsCapsuleNameCapsule (
+  IN EFI_CAPSULE_HEADER         *CapsuleHeader
+  );
+
+/**
+  Check the integrity of the capsule name capsule.
+  If the capsule is vaild, return the physical address of each capsule name string.
+
+  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule name capsule.
+  @param[out] CapsuleNameNum  Number of capsule name.
+
+  @retval NULL                Capsule name capsule is not valid.
+  @retval CapsuleNameBuf      Array of capsule name physical address.
+
+**/
+EFI_PHYSICAL_ADDRESS *
+ValidateCapsuleNameCapsuleIntegrity (
+  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,
+  OUT UINTN                         *CapsuleNameNum
+  );
+
 extern BOOLEAN                   mDxeCapsuleLibEndOfDxe;
 BOOLEAN                          mNeedReset = FALSE;
 
 VOID                        **mCapsulePtr;
+CHAR16                      **mCapsuleNamePtr;
 EFI_STATUS                  *mCapsuleStatusArray;
 UINT32                      mCapsuleTotalNumber;
 
 /**
   The firmware implements to process the capsule image.
@@ -114,10 +145,11 @@ UINT32                      mCapsuleTotalNumber;
 **/
 EFI_STATUS
 EFIAPI
 ProcessThisCapsuleImage (
   IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN CHAR16              *CapFileName,  OPTIONAL
   OUT BOOLEAN            *ResetRequired OPTIONAL
   );
 
 /**
   Function indicate the current completion progress of the firmware
@@ -183,20 +215,36 @@ InitCapsulePtr (
   VOID
   )
 {
   EFI_PEI_HOB_POINTERS        HobPointer;
   UINTN                       Index;
+  UINTN                       Index2;
+  UINTN                       Index3;
+  UINTN                       CapsuleNameNumber;
+  UINTN                       CapsuleNameTotalNumber;
+  UINTN                       CapsuleNameCapsuleTotalNumber;
+  VOID                        **CapsuleNameCapsulePtr;
+  EFI_PHYSICAL_ADDRESS        *CapsuleNameAddress;
+
+  CapsuleNameNumber             = 0;
+  CapsuleNameTotalNumber        = 0;
+  CapsuleNameCapsuleTotalNumber = 0;
+  CapsuleNameCapsulePtr         = NULL;
 
   //
   // Find all capsule images from hob
   //
   HobPointer.Raw = GetHobList ();
   while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
     if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) {
       HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid
     } else {
-      mCapsuleTotalNumber++;
+      if (IsCapsuleNameCapsule((VOID *)(UINTN)HobPointer.Capsule->BaseAddress)) {
+        CapsuleNameCapsuleTotalNumber++;
+      } else {
+        mCapsuleTotalNumber++;
+      }
     }
     HobPointer.Raw = GET_NEXT_HOB (HobPointer);
   }
 
   DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n", mCapsuleTotalNumber));
@@ -222,19 +270,76 @@ InitCapsulePtr (
     mCapsuleTotalNumber = 0;
     return ;
   }
   SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * mCapsuleTotalNumber, EFI_NOT_READY);
 
+  if (CapsuleNameCapsuleTotalNumber != 0) {
+    CapsuleNameCapsulePtr =  (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleNameCapsuleTotalNumber);
+    if (CapsuleNameCapsulePtr == NULL) {
+      DEBUG ((DEBUG_ERROR, "Allocate CapsuleNameCapsulePtr fail!\n"));
+      FreePool (mCapsulePtr);
+      FreePool (mCapsuleStatusArray);
+      mCapsulePtr         = NULL;
+      mCapsuleStatusArray = NULL;
+      mCapsuleTotalNumber = 0;
+      return ;
+    }
+  }
+
   //
   // Find all capsule images from hob
   //
   HobPointer.Raw = GetHobList ();
-  Index = 0;
+  Index  = 0;
+  Index2 = 0;
   while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
-    mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
+    if (!IsCapsuleNameCapsule ((VOID *) (UINTN) HobPointer.Capsule->BaseAddress)) {
+      mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
+    } else {
+      CapsuleNameCapsulePtr [Index2++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
+    }
     HobPointer.Raw = GET_NEXT_HOB (HobPointer);
   }
+
+  //
+  // Find Capsule On Disk Names
+  //
+  for (Index = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {
+    CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
+    if (CapsuleNameAddress != NULL ) {
+      CapsuleNameTotalNumber += CapsuleNameNumber;
+    }
+  }
+
+  if (CapsuleNameTotalNumber == mCapsuleTotalNumber) {
+    mCapsuleNamePtr = (CHAR16 **) AllocateZeroPool (sizeof (CHAR16 *) * mCapsuleTotalNumber);
+    if (mCapsuleNamePtr == NULL) {
+      DEBUG ((DEBUG_ERROR, "Allocate mCapsuleNamePtr fail!\n"));
+      FreePool (mCapsulePtr);
+      FreePool (mCapsuleStatusArray);
+      FreePool (CapsuleNameCapsulePtr);
+      mCapsulePtr         = NULL;
+      mCapsuleStatusArray = NULL;
+      mCapsuleTotalNumber = 0;
+      return ;
+    }
+
+    for (Index = 0, Index3 = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {
+      CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
+      if (CapsuleNameAddress != NULL ) {
+        for (Index2 = 0; Index2 < CapsuleNameNumber; Index2 ++) {
+          mCapsuleNamePtr[Index3 ++] = (CHAR16 *)(UINTN) CapsuleNameAddress[Index2];
+        }
+      }
+    }
+  } else {
+    mCapsuleNamePtr = NULL;
+  }
+
+  if (CapsuleNameCapsulePtr != NULL) {
+    FreePool (CapsuleNameCapsulePtr);
+  }
 }
 
 /**
   This function returns if all capsule images are processed.
 
@@ -394,10 +499,11 @@ ProcessTheseCapsules (
   EFI_CAPSULE_HEADER          *CapsuleHeader;
   UINT32                      Index;
   ESRT_MANAGEMENT_PROTOCOL    *EsrtManagement;
   UINT16                      EmbeddedDriverCount;
   BOOLEAN                     ResetRequired;
+  CHAR16                      *CapsuleName;
 
   REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));
 
   if (FirstRound) {
     InitCapsulePtr ();
@@ -406,10 +512,11 @@ ProcessTheseCapsules (
   if (mCapsuleTotalNumber == 0) {
     //
     // We didn't find a hob, so had no errors.
     //
     DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update boot mode.\n"));
+    mNeedReset = TRUE;
     return EFI_SUCCESS;
   }
 
   if (AreAllImagesProcessed ()) {
     return EFI_SUCCESS;
@@ -428,14 +535,15 @@ ProcessTheseCapsules (
   //
   // If Windows UX capsule exist, process it first
   //
   for (Index = 0; Index < mCapsuleTotalNumber; Index++) {
     CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
+    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL : mCapsuleNamePtr[Index];
     if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
       DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));
       DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));
-      Status = ProcessThisCapsuleImage (CapsuleHeader, NULL);
+      Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, NULL);
       mCapsuleStatusArray [Index] = EFI_SUCCESS;
       DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n", Status));
       break;
     }
   }
@@ -449,10 +557,11 @@ ProcessTheseCapsules (
     if (mCapsuleStatusArray [Index] != EFI_NOT_READY) {
       // already processed
       continue;
     }
     CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
+    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL : mCapsuleNamePtr[Index];
     if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
       //
       // Call capsule library to process capsule image.
       //
       EmbeddedDriverCount = 0;
@@ -469,11 +578,11 @@ ProcessTheseCapsules (
       }
 
       if ((!FirstRound) || (EmbeddedDriverCount == 0)) {
         DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n", CapsuleHeader));
         ResetRequired = FALSE;
-        Status = ProcessThisCapsuleImage (CapsuleHeader, &ResetRequired);
+        Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, &ResetRequired);
         mCapsuleStatusArray [Index] = Status;
         DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status));
 
         if (Status != EFI_NOT_READY) {
           if (EFI_ERROR(Status)) {
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
index 6ad766d65a..0ec5f20676 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
@@ -1,9 +1,9 @@
 /** @file
   DXE capsule report related function.
 
-  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include <PiDxe.h>
@@ -27,10 +27,22 @@
 #include <Library/DevicePathLib.h>
 #include <Library/CapsuleLib.h>
 
 #include <IndustryStandard/WindowsUxCapsule.h>
 
+/**
+  This routine is called to clear CapsuleOnDisk Relocation Info variable.
+  Total Capsule On Disk length is recorded in this variable
+
+  @retval EFI_SUCCESS   Capsule On Disk flags are cleared
+
+**/
+EFI_STATUS
+CoDClearCapsuleRelocationInfo(
+  VOID
+  );
+
 /**
   Get current capsule last variable index.
 
   @return Current capsule last variable index.
   @retval -1  No current capsule last variable.
@@ -172,44 +184,55 @@ RecordCapsuleStatusVariable (
   @param[in] CapsuleHeader  The capsule image header
   @param[in] CapsuleStatus  The capsule process stauts
   @param[in] PayloadIndex   FMP payload index
   @param[in] ImageHeader    FMP image header
   @param[in] FmpDevicePath  DevicePath associated with the FMP producer
+  @param[in] CapFileName    Capsule file name
 
   @retval EFI_SUCCESS          The capsule status variable is recorded.
   @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
 **/
 EFI_STATUS
 RecordFmpCapsuleStatusVariable (
   IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
   IN EFI_STATUS                                    CapsuleStatus,
   IN UINTN                                         PayloadIndex,
   IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER  *ImageHeader,
-  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath OPTIONAL
+  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath, OPTIONAL
+  IN CHAR16                                        *CapFileName    OPTIONAL
   )
 {
   EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResultVariableHeader;
   EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultVariableFmp;
   EFI_STATUS                          Status;
   UINT8                               *CapsuleResultVariable;
   UINTN                               CapsuleResultVariableSize;
   CHAR16                              *DevicePathStr;
   UINTN                               DevicePathStrSize;
+  UINTN                               CapFileNameSize;
+
+  DevicePathStr   = NULL;
+  CapFileNameSize = sizeof(CHAR16);
 
-  DevicePathStr = NULL;
   if (FmpDevicePath != NULL) {
     DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE);
   }
   if (DevicePathStr != NULL) {
     DevicePathStrSize = StrSize(DevicePathStr);
   } else {
     DevicePathStrSize = sizeof(CHAR16);
   }
+
+  if (CapFileName != NULL) {
+    CapFileNameSize = StrSize(CapFileName);
+  }
+
   //
-  // Allocate zero CHAR16 for CapsuleFileName.
+  // Allocate room for CapsuleFileName.
   //
-  CapsuleResultVariableSize = sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) + DevicePathStrSize;
+  CapsuleResultVariableSize = sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize + DevicePathStrSize;
+
   CapsuleResultVariable     = AllocateZeroPool (CapsuleResultVariableSize);
   if (CapsuleResultVariable == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
   CapsuleResultVariableHeader = (VOID *)CapsuleResultVariable;
@@ -223,12 +246,17 @@ RecordFmpCapsuleStatusVariable (
   CapsuleResultVariableFmp = (VOID *)(CapsuleResultVariable + sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER));
   CapsuleResultVariableFmp->Version = 0x1;
   CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;
   CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader->UpdateImageIndex;
   CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId);
+
+  if (CapFileName != NULL) {
+    CopyMem((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName, CapFileNameSize);
+  }
+
   if (DevicePathStr != NULL) {
-    CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16), DevicePathStr, DevicePathStrSize);
+    CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize, DevicePathStr, DevicePathStrSize);
     FreePool (DevicePathStr);
     DevicePathStr = NULL;
   }
 
   Status = EFI_SUCCESS;
@@ -398,10 +426,35 @@ InitCapsuleUpdateVariable (
     }
     Index++;
   }
 }
 
+/**
+  Initialize capsule relocation info variable.
+**/
+VOID
+InitCapsuleRelocationInfo (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
+
+  CoDClearCapsuleRelocationInfo();
+
+  //
+  // Unlock Capsule On Disk relocation Info variable only when Capsule On Disk flag is enabled
+  //
+  if (!CoDCheckCapsuleOnDiskFlag()) {
+    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
+    if (!EFI_ERROR (Status)) {
+      Status = VariableLock->RequestToLock (VariableLock, COD_RELOCATION_INFO_VAR_NAME, &gEfiCapsuleVendorGuid);
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+}
+
 /**
   Initialize capsule related variables.
 **/
 VOID
 InitCapsuleVariable (
@@ -409,10 +462,12 @@ InitCapsuleVariable (
   )
 {
   InitCapsuleUpdateVariable();
   InitCapsuleMaxVariable();
   InitCapsuleLastVariable();
+  InitCapsuleRelocationInfo();
+
   //
   // No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"
   // to check status and delete them.
   //
 }
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
index 2c93e68700..bf56f4623f 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
@@ -1,11 +1,11 @@
 ## @file
 #  Capsule library instance for DXE_RUNTIME_DRIVER.
 #
 #  Capsule library instance for DXE_RUNTIME_DRIVER module types.
 #
-#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
 
 [Defines]
@@ -66,8 +66,9 @@
   gEfiCapsuleReportGuid
   gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
   gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
   gEfiEventReadyToBootGuid                ## CONSUMES ## Event
   gEfiEventVirtualAddressChangeGuid       ## CONSUMES ## Event
+  gEdkiiCapsuleOnDiskNameGuid             ## SOMETIMES_CONSUMES ## GUID
 
 [Depex]
   gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
index 06a1abe16b..39e37cffcd 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
@@ -1,9 +1,9 @@
 /** @file
   Null Dxe Capsule Library instance does nothing and returns unsupport status.
 
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 #include <Uefi.h>
 #include <Library/CapsuleLib.h>
@@ -83,5 +83,88 @@ ProcessCapsules (
   )
 {
   return EFI_UNSUPPORTED;
 }
 
+
+/**
+  This routine is called to check if CapsuleOnDisk flag in OsIndications Variable
+  is enabled.
+
+  @retval TRUE     Flag is enabled
+  @retval FALSE    Flag is not enabled
+
+**/
+BOOLEAN
+EFIAPI
+CoDCheckCapsuleOnDiskFlag(
+  VOID
+  )
+{
+  return FALSE;
+}
+
+/**
+  This routine is called to clear CapsuleOnDisk flags including OsIndications and BootNext variable.
+
+  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
+
+**/
+EFI_STATUS
+EFIAPI
+CoDClearCapsuleOnDiskFlag(
+  VOID
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Relocate Capsule on Disk from EFI system partition.
+
+  Two solution to deliver Capsule On Disk:
+  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Disk to memory and call UpdateCapsule().
+  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On Disk to a platform-specific NV storage
+  device with BlockIo protocol.
+
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  Side Effects:
+    Capsule Delivery Supported Flag in OsIndication variable and BootNext variable will be cleared.
+    Solution B: Content corruption. Block IO write directly touches low level write. Orignal partitions, file
+  systems of the relocation device will be corrupted.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoDRelocateCapsule(
+  UINTN     MaxRetry
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Remove the temp file from the root of EFI System Partition.
+  Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
+  Function will stall 100ms between each retry.
+
+  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between each connection try to ensure
+                                     devices like USB can get enumerated.
+
+  @retval EFI_SUCCESS   Remove the temp file successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+CoDRemoveTempFile (
+  UINTN    MaxRetry
+  )
+{
+  return EFI_UNSUPPORTED;
+}
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
  2019-06-05 15:41 ` [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition Xu, Wei6
@ 2019-06-05 21:42   ` Felix Polyudov
  2019-06-12  7:48   ` Wu, Hao A
  1 sibling, 0 replies; 33+ messages in thread
From: Felix Polyudov @ 2019-06-05 21:42 UTC (permalink / raw)
  To: devel@edk2.groups.io, 'wei6.xu@intel.com'
  Cc: Michael D Kinney, Liming Gao, Chao B Zhang

1. It is my understanding that edk2 convention is to keep each PPI in a separate header file. If this is the case, new PPI definition should not be added to BootInRecoveryMode.h.
2. gEfiPeiBootInCapsuleOnDiskModePpiGuid is a bad name. New PPI is not defined by UEFI/PI specifications and as such cannot have EFI prefix. Arguably, it shouldn't even be in the MdePkg.

-----Original Message-----
From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu, Wei6
Sent: Wednesday, June 05, 2019 11:42 AM
To: devel@edk2.groups.io
Cc: Michael D Kinney; Liming Gao; Chao B Zhang; Wei6 Xu
Subject: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

This PPI indicates current boot mode is capsule on disk mode.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
 MdePkg/Include/Ppi/BootInRecoveryMode.h | 9 ++++++++-
 MdePkg/MdePkg.dec                       | 3 +++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/MdePkg/Include/Ppi/BootInRecoveryMode.h b/MdePkg/Include/Ppi/BootInRecoveryMode.h
index ae40744d9b..71b0ca8586 100644
--- a/MdePkg/Include/Ppi/BootInRecoveryMode.h
+++ b/MdePkg/Include/Ppi/BootInRecoveryMode.h
@@ -1,10 +1,10 @@
 /** @file
   This PPI is installed by the platform PEIM to designate that a recovery boot
   is in progress.

-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent

   @par Revision Reference:
   This PPI is introduced in PI Version 1.0.

@@ -19,6 +19,13 @@
   }


 extern EFI_GUID gEfiPeiBootInRecoveryModePpiGuid;

+#define EFI_PEI_BOOT_IN_CAPSULE_ON_DISK_MODE_PPI \
+  { \
+    0xb08a11e4, 0xe2b7, 0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } \
+  }
+
+extern EFI_GUID gEfiPeiBootInCapsuleOnDiskModePpiGuid;
+
 #endif
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 6c563375ee..ec02b8c7c7 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -790,10 +790,13 @@
   gEfiPeiMemoryDiscoveredPpiGuid = {0xf894643d, 0xc449, 0x42d1, {0x8e, 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } }

   ## Include/Ppi/BootInRecoveryMode.h
   gEfiPeiBootInRecoveryModePpiGuid = { 0x17ee496a, 0xd8e4, 0x4b9a, {0x94, 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } }

+  ## Include/Ppi/BootInRecoveryMode.h
+  gEfiPeiBootInCapsuleOnDiskModePpiGuid = { 0xb08a11e4, 0xe2b7, 0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } }
+
   ## Include/Ppi/EndOfPeiPhase.h
   gEfiEndOfPeiSignalPpiGuid = {0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } }

   ## Include/Ppi/Reset.h
   gEfiPeiResetPpiGuid = { 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78, 0xc6, 0xf4, 0xfe, 0x71, 0x2f } }
--
2.16.2.windows.1





Please consider the environment before printing this email.

The information contained in this message may be confidential and proprietary to American Megatrends, Inc.  This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited.  Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
                   ` (6 preceding siblings ...)
  2019-06-05 15:42 ` [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib Xu, Wei6
@ 2019-06-05 21:53 ` Felix Polyudov
  2019-06-05 22:36   ` Michael D Kinney
  2019-06-12  7:47 ` Wu, Hao A
  8 siblings, 1 reply; 33+ messages in thread
From: Felix Polyudov @ 2019-06-05 21:53 UTC (permalink / raw)
  To: devel@edk2.groups.io, 'wei6.xu@intel.com'
  Cc: Jian J Wang, Hao A Wu, Michael D Kinney, Liming Gao, Chao B Zhang

1. It looks like the implementation processes capsule files in PEI.
According to UEFI specification capsule files are stored on the active ESP.
Not every UEFI boot device can be accessed in PEI.
For example, RAID connected to the PCI plug in card cannot be accessed in PEI.

2. Solution B) below relocates capsule to "a temp file which will be stored in root directory". I think it is cleaner to reuse UEFI capsule-on-disk infrastructure and keep capsule file in  the dedicated \EFI\UpdateCapsule folder (refer to "Delivery of Capsules via file on Mass Storage device" section of the UEFI specification).

-----Original Message-----
From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu, Wei6
Sent: Wednesday, June 05, 2019 11:42 AM
To: devel@edk2.groups.io
Cc: Jian J Wang; Hao A Wu; Michael D Kinney; Liming Gao; Chao B Zhang
Subject: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.

V2:
Fix Ecc check failure.

V1:
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852

This patch set implements Capsule On Disk.
Depends on whether platform supports Capsule-In-Ram, Capsule On Disk feature is composed of 2 solutions:
Solution A): Load capsules out of TCB, rely on UpdateCapsule() runtime service to deliver Capsule-On-Disk.
Solution B): Relocate capsules into a temp file which will be stored in root directory on a platform specific storage device.
Leverage existing storage stack in PEI to load all capsule on disk images and create capsule hobs for the capsules.
This solution has bigger TCB, but can work without Capsule-In-RAM support.


Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>

xuwei6 (7):
  MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
  MdeModulePkg: Add Capsule On Disk related definition.
  MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
  MdeModulePkg/BdsDxe: Support Capsule On Disk.
  MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  MdeModulePkg/DxeIpl: Support Capsule On Disk.
  MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.

 MdeModulePkg/Core/DxeIplPeim/DxeIpl.h              |    3 +-
 MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf            |   20 +-
 MdeModulePkg/Core/DxeIplPeim/DxeLoad.c             |   37 +-
 MdeModulePkg/Include/Library/CapsuleLib.h          |   94 +-
 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h           |   48 +
 .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       | 1983 ++++++++++++++++++++
 .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |   63 +
 .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |   56 +-
 .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |   21 +-
 .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |  121 +-
 .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |   67 +-
 .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |    3 +-
 .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |   85 +-
 MdeModulePkg/MdeModulePkg.dec                      |   43 +
 MdeModulePkg/MdeModulePkg.dsc                      |    4 +
 MdeModulePkg/MdeModulePkg.uni                      |   32 +
 MdeModulePkg/Universal/BdsDxe/BdsDxe.inf           |    3 +-
 MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |    6 +-
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    |  442 +++++
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |   64 +
 .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |   15 +
 .../CapsuleOnDiskLoadPeiExtra.uni                  |   14 +
 .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf        |    1 +
 .../Universal/CapsuleRuntimeDxe/CapsuleService.c   |   10 +-
 MdePkg/Include/Ppi/BootInRecoveryMode.h            |    9 +-
 MdePkg/MdePkg.dec                                  |    3 +
 26 files changed, 3205 insertions(+), 42 deletions(-)
 create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
 create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni
 create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiExtra.uni

--
2.16.2.windows.1





Please consider the environment before printing this email.

The information contained in this message may be confidential and proprietary to American Megatrends, Inc.  This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited.  Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
  2019-06-05 21:53 ` [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Felix Polyudov
@ 2019-06-05 22:36   ` Michael D Kinney
  2019-06-06  1:23     ` Zhang, Chao B
  0 siblings, 1 reply; 33+ messages in thread
From: Michael D Kinney @ 2019-06-05 22:36 UTC (permalink / raw)
  To: Felix Polyudov, devel@edk2.groups.io, Xu, Wei6, Kinney, Michael D
  Cc: Wang, Jian J, Wu, Hao A, Gao, Liming, Zhang, Chao B

Hi Felix,

For (1), this is a limitation of UEFI Capsule On Disk
for capsules that must be processed before End of DXE.
This solution only work for EFI System Partitions that
can be accessed from PEI.  Platforms that require the
use of a UEFI Driver loaded from a PCI Option ROM to
access the EFI System Partition can not use the UEFI 
Capsule On Disk feature.  They must use the UEFI Capsule
In Memory feature.

For (2), in order to access the capsule file in the
UEFI Spec defines location, the FAT PEIM would have to
be extended to support reading files from subdirectories.
The current FAT PEIM only supports reading files from the
root directory.  This is sufficient for reading recovery
images.  In order to minimize the size of complexity of
PEI phase modules, this solution uses the FAT PEIM "as is"
and uses the features of the UEFI FAT driver to move the
Capsule On Disk content into a location that is compatible
with the existing FAT PEIM.

Thanks,

Mike

> -----Original Message-----
> From: Felix Polyudov [mailto:Felixp@ami.com]
> Sent: Wednesday, June 5, 2019 2:53 PM
> To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Gao, Liming
> <liming.gao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: RE: [edk2-devel][Patch v2 0/7] Implement
> Capsule On Disk.
> 
> 1. It looks like the implementation processes capsule
> files in PEI.
> According to UEFI specification capsule files are stored
> on the active ESP.
> Not every UEFI boot device can be accessed in PEI.
> For example, RAID connected to the PCI plug in card
> cannot be accessed in PEI.
> 
> 2. Solution B) below relocates capsule to "a temp file
> which will be stored in root directory". I think it is
> cleaner to reuse UEFI capsule-on-disk infrastructure and
> keep capsule file in  the dedicated \EFI\UpdateCapsule
> folder (refer to "Delivery of Capsules via file on Mass
> Storage device" section of the UEFI specification).
> 
> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io]
> On Behalf Of Xu, Wei6
> Sent: Wednesday, June 05, 2019 11:42 AM
> To: devel@edk2.groups.io
> Cc: Jian J Wang; Hao A Wu; Michael D Kinney; Liming Gao;
> Chao B Zhang
> Subject: [edk2-devel][Patch v2 0/7] Implement Capsule On
> Disk.
> 
> V2:
> Fix Ecc check failure.
> 
> V1:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> This patch set implements Capsule On Disk.
> Depends on whether platform supports Capsule-In-Ram,
> Capsule On Disk feature is composed of 2 solutions:
> Solution A): Load capsules out of TCB, rely on
> UpdateCapsule() runtime service to deliver Capsule-On-
> Disk.
> Solution B): Relocate capsules into a temp file which
> will be stored in root directory on a platform specific
> storage device.
> Leverage existing storage stack in PEI to load all
> capsule on disk images and create capsule hobs for the
> capsules.
> This solution has bigger TCB, but can work without
> Capsule-In-RAM support.
> 
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> 
> xuwei6 (7):
>   MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi
> definition.
>   MdeModulePkg: Add Capsule On Disk related definition.
>   MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
>   MdeModulePkg/BdsDxe: Support Capsule On Disk.
>   MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to
> control this feature.
>   MdeModulePkg/DxeIpl: Support Capsule On Disk.
>   MdeModulePkg: Add Capsule On Disk APIs into
> CapsuleLib.
> 
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.h              |
> 3 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf            |
> 20 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeLoad.c             |
> 37 +-
>  MdeModulePkg/Include/Library/CapsuleLib.h          |
> 94 +-
>  MdeModulePkg/Include/Ppi/CapsuleOnDisk.h           |
> 48 +
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       |
> 1983 ++++++++++++++++++++
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |
> 63 +
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |
> 56 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |
> 21 +-
>  .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |
> 121 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |
> 67 +-
>  .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |
> 3 +-
>  .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |
> 85 +-
>  MdeModulePkg/MdeModulePkg.dec                      |
> 43 +
>  MdeModulePkg/MdeModulePkg.dsc                      |
> 4 +
>  MdeModulePkg/MdeModulePkg.uni                      |
> 32 +
>  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf           |
> 3 +-
>  MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |
> 6 +-
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    |
> 442 +++++
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |
> 64 +
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |
> 15 +
>  .../CapsuleOnDiskLoadPeiExtra.uni                  |
> 14 +
>  .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf        |
> 1 +
>  .../Universal/CapsuleRuntimeDxe/CapsuleService.c   |
> 10 +-
>  MdePkg/Include/Ppi/BootInRecoveryMode.h            |
> 9 +-
>  MdePkg/MdePkg.dec                                  |
> 3 +
>  26 files changed, 3205 insertions(+), 42 deletions(-)
> create mode 100644
> MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPei.c
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPei.inf
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPei.uni
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPeiExtra.uni
> 
> --
> 2.16.2.windows.1
> 
> 
> 
> 
> 
> Please consider the environment before printing this
> email.
> 
> The information contained in this message may be
> confidential and proprietary to American Megatrends,
> Inc.  This communication is intended to be read only by
> the individual or entity to whom it is addressed or by
> their designee. If the reader of this message is not the
> intended recipient, you are on notice that any
> distribution of this message, in any form, is strictly
> prohibited.  Please promptly notify the sender by reply
> e-mail or by telephone at 770-246-8600, and then delete
> or destroy all copies of the transmission.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
  2019-06-05 22:36   ` Michael D Kinney
@ 2019-06-06  1:23     ` Zhang, Chao B
  0 siblings, 0 replies; 33+ messages in thread
From: Zhang, Chao B @ 2019-06-06  1:23 UTC (permalink / raw)
  To: Kinney, Michael D, Felix Polyudov, devel@edk2.groups.io, Xu, Wei6
  Cc: Wang, Jian J, Wu, Hao A, Gao, Liming

[-- Attachment #1: Type: text/plain, Size: 8627 bytes --]

Hi Felix:
   We did this design for security consideration.
    For Solution B:

1)      We don't want to introduce PartitionDxe and FatDxe into our trust boundary. It brings in new attack surface

2)      We reuse PEI storage stack as it is simple. But PEI FAT reduced attach surface by only accessing files in RootDir. That is why relocation happens
  For Solution A:

3)      It is considered securer with a smaller attack surface.  Because in Solution B, we may suffer from DMA attack when accessing PEI storage device

  Solution B is still valuable option as some platform may don't have Capsule in RAM support. That is why we provide both solution and leave option to user
We have a WIKI page to describe all cases https://github.com/tianocore/tianocore.github.io/wiki/UEFI-Capsule-on-Disk-Introducation
  Just feel free to ask question if anything is not clear

From: Kinney, Michael D
Sent: Thursday, June 6, 2019 6:37 AM
To: Felix Polyudov <Felixp@ami.com>; devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.

Hi Felix,

For (1), this is a limitation of UEFI Capsule On Disk
for capsules that must be processed before End of DXE.
This solution only work for EFI System Partitions that
can be accessed from PEI.  Platforms that require the
use of a UEFI Driver loaded from a PCI Option ROM to
access the EFI System Partition can not use the UEFI
Capsule On Disk feature.  They must use the UEFI Capsule
In Memory feature.

For (2), in order to access the capsule file in the
UEFI Spec defines location, the FAT PEIM would have to
be extended to support reading files from subdirectories.
The current FAT PEIM only supports reading files from the
root directory.  This is sufficient for reading recovery
images.  In order to minimize the size of complexity of
PEI phase modules, this solution uses the FAT PEIM "as is"
and uses the features of the UEFI FAT driver to move the
Capsule On Disk content into a location that is compatible
with the existing FAT PEIM.

Thanks,

Mike

> -----Original Message-----
> From: Felix Polyudov [mailto:Felixp@ami.com]
> Sent: Wednesday, June 5, 2019 2:53 PM
> To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Xu, Wei6 <wei6.xu@intel.com<mailto:wei6.xu@intel.com>>
> Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Wu, Hao A
> <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Kinney, Michael D
> <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>; Gao, Liming
> <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Zhang, Chao B
> <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Subject: RE: [edk2-devel][Patch v2 0/7] Implement
> Capsule On Disk.
>
> 1. It looks like the implementation processes capsule
> files in PEI.
> According to UEFI specification capsule files are stored
> on the active ESP.
> Not every UEFI boot device can be accessed in PEI.
> For example, RAID connected to the PCI plug in card
> cannot be accessed in PEI.
>
> 2. Solution B) below relocates capsule to "a temp file
> which will be stored in root directory". I think it is
> cleaner to reuse UEFI capsule-on-disk infrastructure and
> keep capsule file in  the dedicated \EFI\UpdateCapsule
> folder (refer to "Delivery of Capsules via file on Mass
> Storage device" section of the UEFI specification).
>
> -----Original Message-----
> From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> [mailto:devel@edk2.groups.io]
> On Behalf Of Xu, Wei6
> Sent: Wednesday, June 05, 2019 11:42 AM
> To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> Cc: Jian J Wang; Hao A Wu; Michael D Kinney; Liming Gao;
> Chao B Zhang
> Subject: [edk2-devel][Patch v2 0/7] Implement Capsule On
> Disk.
>
> V2:
> Fix Ecc check failure.
>
> V1:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
>
> This patch set implements Capsule On Disk.
> Depends on whether platform supports Capsule-In-Ram,
> Capsule On Disk feature is composed of 2 solutions:
> Solution A): Load capsules out of TCB, rely on
> UpdateCapsule() runtime service to deliver Capsule-On-
> Disk.
> Solution B): Relocate capsules into a temp file which
> will be stored in root directory on a platform specific
> storage device.
> Leverage existing storage stack in PEI to load all
> capsule on disk images and create capsule hobs for the
> capsules.
> This solution has bigger TCB, but can work without
> Capsule-In-RAM support.
>
>
> Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
> Cc: Chao B Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
>
> xuwei6 (7):
>   MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi
> definition.
>   MdeModulePkg: Add Capsule On Disk related definition.
>   MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
>   MdeModulePkg/BdsDxe: Support Capsule On Disk.
>   MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to
> control this feature.
>   MdeModulePkg/DxeIpl: Support Capsule On Disk.
>   MdeModulePkg: Add Capsule On Disk APIs into
> CapsuleLib.
>
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.h              |
> 3 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf            |
> 20 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeLoad.c             |
> 37 +-
>  MdeModulePkg/Include/Library/CapsuleLib.h          |
> 94 +-
>  MdeModulePkg/Include/Ppi/CapsuleOnDisk.h           |
> 48 +
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       |
> 1983 ++++++++++++++++++++
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |
> 63 +
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |
> 56 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |
> 21 +-
>  .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |
> 121 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |
> 67 +-
>  .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |
> 3 +-
>  .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |
> 85 +-
>  MdeModulePkg/MdeModulePkg.dec                      |
> 43 +
>  MdeModulePkg/MdeModulePkg.dsc                      |
> 4 +
>  MdeModulePkg/MdeModulePkg.uni                      |
> 32 +
>  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf           |
> 3 +-
>  MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |
> 6 +-
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    |
> 442 +++++
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |
> 64 +
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |
> 15 +
>  .../CapsuleOnDiskLoadPeiExtra.uni                  |
> 14 +
>  .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf        |
> 1 +
>  .../Universal/CapsuleRuntimeDxe/CapsuleService.c   |
> 10 +-
>  MdePkg/Include/Ppi/BootInRecoveryMode.h            |
> 9 +-
>  MdePkg/MdePkg.dec                                  |
> 3 +
>  26 files changed, 3205 insertions(+), 42 deletions(-)
> create mode 100644
> MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPei.c
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPei.inf
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPei.uni
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDis
> kLoadPeiExtra.uni
>
> --
> 2.16.2.windows.1
>
>
> 
>
>
> Please consider the environment before printing this
> email.
>
> The information contained in this message may be
> confidential and proprietary to American Megatrends,
> Inc.  This communication is intended to be read only by
> the individual or entity to whom it is addressed or by
> their designee. If the reader of this message is not the
> intended recipient, you are on notice that any
> distribution of this message, in any form, is strictly
> prohibited.  Please promptly notify the sender by reply
> e-mail or by telephone at 770-246-8600, and then delete
> or destroy all copies of the transmission.

[-- Attachment #2: Type: text/html, Size: 29497 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
  2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
                   ` (7 preceding siblings ...)
  2019-06-05 21:53 ` [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Felix Polyudov
@ 2019-06-12  7:47 ` Wu, Hao A
  2019-06-12  8:13   ` Zhang, Chao B
  8 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-12  7:47 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6, Zhang, Chao B
  Cc: Wang, Jian J, Kinney, Michael D, Gao, Liming

Hello Chao,

Do you have any comment/feedback on this series?

One comment with regard to the series below:

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Xu, Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Kinney, Michael D; Gao, Liming; Zhang, Chao B
> Subject: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
> 
> V2:
> Fix Ecc check failure.
> 
> V1:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> This patch set implements Capsule On Disk.
> Depends on whether platform supports Capsule-In-Ram, Capsule On Disk
> feature is composed of 2 solutions:
> Solution A): Load capsules out of TCB, rely on UpdateCapsule() runtime
> service to deliver Capsule-On-Disk.
> Solution B): Relocate capsules into a temp file which will be stored in root
> directory on a platform specific storage device.
> Leverage existing storage stack in PEI to load all capsule on disk images and
> create capsule hobs for the capsules.
> This solution has bigger TCB, but can work without Capsule-In-RAM support.
> 
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> 
> xuwei6 (7):
>   MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
>   MdeModulePkg: Add Capsule On Disk related definition.
>   MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
>   MdeModulePkg/BdsDxe: Support Capsule On Disk.
>   MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
>   MdeModulePkg/DxeIpl: Support Capsule On Disk.
>   MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.


Please re-order the sequence of the patches.
I found that the below patch:
MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.

depends on some definitions added in patch (last one):
MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.

Best Regards,
Hao Wu


> 
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.h              |    3 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf            |   20 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeLoad.c             |   37 +-
>  MdeModulePkg/Include/Library/CapsuleLib.h          |   94 +-
>  MdeModulePkg/Include/Ppi/CapsuleOnDisk.h           |   48 +
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       | 1983
> ++++++++++++++++++++
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |   63 +
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |   56 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |   21 +-
>  .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |  121 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |   67 +-
>  .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |    3 +-
>  .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |   85 +-
>  MdeModulePkg/MdeModulePkg.dec                      |   43 +
>  MdeModulePkg/MdeModulePkg.dsc                      |    4 +
>  MdeModulePkg/MdeModulePkg.uni                      |   32 +
>  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf           |    3 +-
>  MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |    6 +-
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    |  442 +++++
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |   64 +
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |   15 +
>  .../CapsuleOnDiskLoadPeiExtra.uni                  |   14 +
>  .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf        |    1 +
>  .../Universal/CapsuleRuntimeDxe/CapsuleService.c   |   10 +-
>  MdePkg/Include/Ppi/BootInRecoveryMode.h            |    9 +-
>  MdePkg/MdePkg.dec                                  |    3 +
>  26 files changed, 3205 insertions(+), 42 deletions(-)
>  create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.i
> nf
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.u
> ni
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiE
> xtra.uni
> 
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
  2019-06-05 15:41 ` [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition Xu, Wei6
  2019-06-05 21:42   ` Felix Polyudov
@ 2019-06-12  7:48   ` Wu, Hao A
  2019-06-12  8:28     ` Liming Gao
  1 sibling, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-12  7:48 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6
  Cc: Kinney, Michael D, Gao, Liming, Zhang, Chao B

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Kinney, Michael D; Gao, Liming; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk
> Mode Ppi definition.
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> This PPI indicates current boot mode is capsule on disk mode.
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
>  MdePkg/Include/Ppi/BootInRecoveryMode.h | 9 ++++++++-
>  MdePkg/MdePkg.dec                       | 3 +++
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/MdePkg/Include/Ppi/BootInRecoveryMode.h
> b/MdePkg/Include/Ppi/BootInRecoveryMode.h
> index ae40744d9b..71b0ca8586 100644
> --- a/MdePkg/Include/Ppi/BootInRecoveryMode.h
> +++ b/MdePkg/Include/Ppi/BootInRecoveryMode.h
> @@ -1,10 +1,10 @@
>  /** @file
>    This PPI is installed by the platform PEIM to designate that a recovery boot
>    is in progress.
> 
> -  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>    @par Revision Reference:
>    This PPI is introduced in PI Version 1.0.
> 
> @@ -19,6 +19,13 @@
>    }
> 
> 
>  extern EFI_GUID gEfiPeiBootInRecoveryModePpiGuid;
> 
> +#define EFI_PEI_BOOT_IN_CAPSULE_ON_DISK_MODE_PPI \
> +  { \
> +    0xb08a11e4, 0xe2b7, 0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf,
> 0xd1 } \
> +  }
> +
> +extern EFI_GUID gEfiPeiBootInCapsuleOnDiskModePpiGuid;
> +

Hello all,

One question, the above PPI will be added in the next PI spec, right?
Since I cannot find this definition within the PI 1.7 spec.

Best Regards,
Hao Wu

>  #endif
> diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
> index 6c563375ee..ec02b8c7c7 100644
> --- a/MdePkg/MdePkg.dec
> +++ b/MdePkg/MdePkg.dec
> @@ -790,10 +790,13 @@
>    gEfiPeiMemoryDiscoveredPpiGuid = {0xf894643d, 0xc449, 0x42d1, {0x8e,
> 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } }
> 
>    ## Include/Ppi/BootInRecoveryMode.h
>    gEfiPeiBootInRecoveryModePpiGuid = { 0x17ee496a, 0xd8e4, 0x4b9a, {0x94,
> 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } }
> 
> +  ## Include/Ppi/BootInRecoveryMode.h
> +  gEfiPeiBootInCapsuleOnDiskModePpiGuid = { 0xb08a11e4, 0xe2b7, 0x4b75,
> { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } }
> +
>    ## Include/Ppi/EndOfPeiPhase.h
>    gEfiEndOfPeiSignalPpiGuid = {0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80,
> 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } }
> 
>    ## Include/Ppi/Reset.h
>    gEfiPeiResetPpiGuid = { 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78, 0xc6,
> 0xf4, 0xfe, 0x71, 0x2f } }
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition.
  2019-06-05 15:41 ` [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition Xu, Wei6
@ 2019-06-12  7:48   ` Wu, Hao A
  2019-06-12  8:43     ` Xu, Wei6
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-12  7:48 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J, Zhang, Chao B

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk
> related definition.
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> This patch will add Capsule On Disk related definition, including
> GUID, PPI and PCDs:
> The Capsule On Disk Name GUID indicates the capsule is to store
> Capsule On Disk file names.
> The Pei Capsule On Disk PPI provides service to retrieve capsules
> from Capsule On Disk temp relocation file on mass storage devices
> and create capsule hob for these capsules.
> PcdCapsuleOnDiskSupport is used to enable/disable Capsule On Disk.
> PcdCapsuleInRamSupport is used to enabble/disable Capsule In Ram.

enabble -> enable

May I know the reason that PcdCapsuleOnDiskSupport is listed under section
'[PcdsFixedAtBuild, PcdsPatchableInModule]' while PcdCapsuleInRamSupport
is listed under
'[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]'?

Best Regards,
Hao Wu

> PcdCoDRelocationFileName specifies the Capsule On Disk temp
> relocation file name.
> PcdCodRelocationDevPath specifies platform specific device to store
> Capsule On Disk tem relocation file.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
>  MdeModulePkg/Include/Ppi/CapsuleOnDisk.h | 48
> ++++++++++++++++++++++++++++++++
>  MdeModulePkg/MdeModulePkg.dec            | 43
> ++++++++++++++++++++++++++++
>  MdeModulePkg/MdeModulePkg.uni            | 32 +++++++++++++++++++++
>  3 files changed, 123 insertions(+)
>  create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> 
> diff --git a/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> b/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> new file mode 100644
> index 0000000000..28be6e42be
> --- /dev/null
> +++ b/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> @@ -0,0 +1,48 @@
> +/** @file
> +  This file declares Capsule On Disk PPI.  This PPI is used to find and load the
> +  capsule on files that are relocated into a temp file under rootdir.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef __PEI_CAPSULE_ON_DISK_PPI_H__
> +#define __PEI_CAPSULE_ON_DISK_PPI_H__
> +
> +#define EFI_PEI_CAPSULE_ON_DISK_PPI_GUID \
> +  { \
> +    0x71a9ea61, 0x5a35, 0x4a5d, {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67,
> 0xe0 } \
> +  }
> +
> +typedef struct _EFI_PEI_CAPSULE_ON_DISK_PPI
> EFI_PEI_CAPSULE_ON_DISK_PPI;
> +
> +/**
> +  Loads a DXE capsule from some media into memory and updates the HOB
> table
> +  with the DXE firmware volume information.
> +
> +  @param  PeiServices   General-purpose services that are available to every
> PEIM.
> +  @param  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
> +
> +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> +  @retval EFI_DEVICE_ERROR   A device error occurred.
> +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_PEI_LOAD_CAPSULE_ON_DISK)(
> +  IN EFI_PEI_SERVICES             **PeiServices,
> +  IN EFI_PEI_CAPSULE_ON_DISK_PPI  *This
> +  );
> +
> +///
> +///  Finds and loads the recovery files.
> +///
> +struct _EFI_PEI_CAPSULE_ON_DISK_PPI {
> +  EFI_PEI_LOAD_CAPSULE_ON_DISK LoadCapsuleOnDisk;  ///< Loads a DXE
> binary capsule into memory.
> +};
> +
> +extern EFI_GUID gEdkiiPeiCapsuleOnDiskPpiGuid;
> +
> +#endif
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index 6cba729982..d80b728313 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -394,10 +394,13 @@
>    gEdkiiS3SmmInitDoneGuid = { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 0x71,
> 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } }
> 
>    ## Include/Guid/S3StorageDeviceInitList.h
>    gS3StorageDeviceInitListGuid = { 0x310e9b8c, 0xcf90, 0x421e, { 0x8e, 0x9b,
> 0x9e, 0xef, 0xb6, 0x17, 0xc8, 0xef } }
> 
> +  ## GUID indicates the capsule is to store Capsule On Disk file names.
> +  gEdkiiCapsuleOnDiskNameGuid = { 0x98c80a4f, 0xe16b, 0x4d11, { 0x93,
> 0x9a, 0xab, 0xe5, 0x61, 0x26, 0x3, 0x30 } }
> +
>  [Ppis]
>    ## Include/Ppi/AtaController.h
>    gPeiAtaControllerPpiGuid       = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a,
> 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
> 
>    ## Include/Ppi/UsbHostController.h
> @@ -464,10 +467,13 @@
>    gEdkiiPeiAtaPassThruPpiGuid               = { 0xa16473fd, 0xd474, 0x4c89, { 0xae,
> 0xc7, 0x90, 0xb8, 0x3c, 0x73, 0x86, 0x9  } }
> 
>    ## Include/Ppi/Debug.h
>    gEdkiiDebugPpiGuid                        = { 0x999e699c, 0xb013, 0x475e, { 0xb1,
> 0x7b, 0xf3, 0xa8, 0xae, 0x5c, 0x48, 0x75 } }
> 
> +  ## Include/Ppi/CapsuleOnDisk.h
> +  gEdkiiPeiCapsuleOnDiskPpiGuid             =  {0x71a9ea61, 0x5a35, 0x4a5d,
> {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67, 0xe0}}
> +
>  [Protocols]
>    ## Load File protocol provides capability to load and unload EFI image into
> memory and execute it.
>    #  Include/Protocol/LoadPe32Image.h
>    #  This protocol is deprecated. Native EDKII module should NOT use this
> protocol to load/unload image.
>    #  If developer need implement such functionality, they should use
> BasePeCoffLib.
> @@ -1473,10 +1479,26 @@
> 
>    ## Indicates the allowable maximum number of Reset Filters, Reset
> Notifications or Reset Handlers in PEI phase.
>    # @Prompt Maximum Number of PEI Reset Filters, Reset Notifications or
> Reset Handlers.
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaximumPeiResetNotifies|0x10|UI
> NT32|0x0000010A
> 
> +  ## Capsule On Disk is to deliver capsules via files on Mass Storage
> device.<BR><BR>
> +  #  This PCD indicates if the Capsule On Disk is supported.<BR>
> +  #   TRUE  - Capsule On Disk is supported.<BR>
> +  #   FALSE - Capsule On Disk is not supported.<BR>
> +  #  If platform does not use this feature, this PCD should be set to
> FALSE.<BR><BR>
> +  #  Two sulotions to deliver Capsule On Disk:<BR>
> +  #    a) If PcdCapsuleInRamSupport = TRUE, Load Capsule On Disk image out
> of TCB, and reuse
> +  #       Capsule In Ram to deliver capsule.<BR>
> +  #    b) If PcdCapsuleInRamSupport = FALSE, Relocate Capsule On Disk image
> to RootDir out
> +  #       of TCB, and reuse FatPei to load capsules from external storage.<BR>
> +  #  Note:<BR>
> +  #    If Both Capsule In Ram and Capsule On Disk are provisioned at the same
> time, the Capsule
> +  #  On Disk will be bypassed.
> +  # @Prompt Enable Capsule On Disk support.
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOO
> LEAN|0x0000002d
> +
>  [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
>    ## This PCD defines the Console output row. The default value is 25
> according to UEFI spec.
>    #  This PCD could be set to 0 then console output would be at max column
> and max row.
>    # @Prompt Console output row.
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|25|UINT32|0x4000000
> 6
> @@ -1932,10 +1954,17 @@
>    #  The file name must be the 8.3 format.
>    #  The PCD data must be in UNICODE format.
>    # @Prompt Recover file name in PEI phase
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"|
> VOID*|0x30001045
> 
> +  ## This is Capsule Temp Relocation file name in PEI phase.
> +  #  The file must be in the root directory.
> +  #  The file name must be the 8.3 format.
> +  #  The PCD data must be in UNICODE format.
> +  # @Prompt Capsule On Disk Temp Relocation file name in PEI phase
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName|L"TempCo
> d.tmp"|VOID*|0x30001048
> +
>    ## This PCD hold a list GUIDs for the ImageTypeId to indicate the
>    #  FMP capsule is a system FMP.
>    # @Prompt A list of system FMP ImageTypeId GUIDs
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGu
> id|{0x0}|VOID*|0x30001046
> 
> @@ -1943,10 +1972,24 @@
>    #  enabled on AMD processors supporting the Secure Encrypted
> Virtualization (SEV) feature.
>    #  This mask should be applied when creating 1:1 virtual to physical mapping
> tables.
>    # @Prompt The address mask when memory encryption is enabled.
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrM
> ask|0x0|UINT64|0x30001047
> 
> +  ## Capsule In Ram is to use memory to deliver the capsules that will be
> processed after system
> +  #  reset.<BR><BR>
> +  #  This PCD indicates if the Capsule In Ram is supported.<BR>
> +  #   TRUE  - Capsule In Ram is supported.<BR>
> +  #   FALSE - Capsule In Ram is not supported.
> +  # @Prompt Enable Capsule In Ram support.
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport|TRUE|BOOL
> EAN|0x0000002e
> +
> +  ## Full device path of plaform specific device to store Capsule On Disk
> temp relocation file.<BR>
> +  #  If this PCD is set, Capsule On Disk temp relocation file will be stored in
> the device specified
> +  #  by this PCD, instead of the EFI System Partition that stores capsule image
> file.
> +  # @Prompt Capsule On Disk relocation device path.
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath|{0xFF}|VOI
> D*|0x0000002f
> +
>  [PcdsPatchableInModule]
>    ## Specify memory size with page number for PEI code when
>    #  Loading Module at Fixed Address feature is enabled.
>    #  The value will be set by the build tool.
>    # @Prompt LMFA PEI code page number.
> diff --git a/MdeModulePkg/MdeModulePkg.uni
> b/MdeModulePkg/MdeModulePkg.uni
> index ed8ac9eadc..85c6beae0d 100644
> --- a/MdeModulePkg/MdeModulePkg.uni
> +++ b/MdeModulePkg/MdeModulePkg.uni
> @@ -1064,10 +1064,17 @@
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdRecoveryFileName_HELP
> #language en-US "This is recover file name in PEI phase.\n"
>                                                                                       "The file must be in the root
> directory.\n"
>                                                                                       "The file name must be the 8.3
> format.\n"
>                                                                                       "The PCD data must be in
> UNICODE format."
> 
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_PRO
> MPT  #language en-US "Capsule On Disk Temp Relocation file name in PEI
> phase"
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_HELP
> #language en-US "This is Capsule Temp Relocation file name in PEI phase.\n"
> +                                                                                          "The file must be in the root
> directory.\n"
> +                                                                                          "The file name must be the 8.3
> format.\n"
> +                                                                                          "The PCD data must be in
> UNICODE format."
> +
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTyp
> eIdGuid_PROMPT  #language en-US "A list of system FMP ImageTypeId
> GUIDs"
> 
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTyp
> eIdGuid_HELP  #language en-US "This PCD hold a list GUIDs for the
> ImageTypeId to indicate the\n"
>                                                                                                      "FMP capsule is a system
> FMP."
> 
> @@ -1129,10 +1136,35 @@
> 
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPteMemoryEncryptionAddres
> sOrMask_HELP  #language en-US "This PCD holds the address mask for page
> table entries when memory encryption is\n"
>                                                                                                       "enabled on AMD
> processors supporting the Secure Encrypted Virtualization (SEV) feature.\n"
>                                                                                                       "This mask should be
> applied when creating 1:1 virtual to physical mapping tables."
> 
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_PRO
> MPT  #language en-US "Enable Capsule On Disk support"
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_HELP
> #language en-US   "Capsule On Disk is to deliver capsules via files on Mass
> Storage device.<BR><BR>"
> +                                                                                           "This PCD indicates if the
> Capsule On Disk is supported.<BR>"
> +                                                                                           " TRUE  - Capsule On Disk is
> supported.<BR>"
> +                                                                                           " FALSE - Capsule On Disk is not
> supported.<BR>"
> +                                                                                           "If platform does not use this
> feature, this PCD should be set to FALSE.<BR><BR>"
> +                                                                                           "Two sulotions to deliver
> Capsule On Disk:<BR>"
> +                                                                                           " a) If
> PcdCapsuleInRamSupport = TRUE, Load Capsule On Disk image out of TCB,
> and reuse Capsule In Ram to deliver capsule.<BR>"
> +                                                                                           " b) If
> PcdCapsuleInRamSupport = FALSE, Relocate Capsule On Disk image to
> RootDir out of TCB, and reuse FatPei to load capsules from external
> storage.<BR>"
> +                                                                                           "Note:<BR>"
> +                                                                                           "If Both Capsule In Ram and
> Capsule On Disk are provisioned at the same time, the Capsule On Disk will
> be bypassed."
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROM
> PT  #language en-US "Enable Capsule In Ram support"
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP
> #language en-US   "Capsule In Ram is to use memory to deliver the capsules
> that will be processed after system reset.<BR><BR>"
> +                                                                                          "This PCD indicates if the
> Capsule In Ram is supported.<BR>"
> +                                                                                          " TRUE  - Capsule In Ram is
> supported.<BR>"
> +                                                                                          " FALSE - Capsule In Ram is not
> supported."
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_PRO
> MPT  #language en-US "Capsule On Disk relacation device path."
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_HELP
> #language en-US   "Full device path of plaform specific device to store
> Capsule On Disk temp relocation file.<BR>"
> +                                                                                           "If this PCD is set, Capsule On
> Disk temp relocation file will be stored in the device specified by this PCD,
> instead of the EFI System Partition that stores capsule image file."
> +
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionProperty
> Mask_PROMPT  #language en-US "Enable NULL pointer detection"
> 
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionProperty
> Mask_HELP    #language en-US "Mask to control the NULL address detection
> in code for different phases.\n"
>                                                                                                         " If enabled, accessing
> NULL address in UEFI or SMM code can be caught.\n\n"
>                                                                                                         "   BIT0    - Enable NULL
> pointer detection for UEFI.\n"
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
  2019-06-05 15:41 ` [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM Xu, Wei6
@ 2019-06-12  7:49   ` Wu, Hao A
  2019-06-19  8:40     ` Xu, Wei6
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-12  7:49 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J, Zhang, Chao B

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> CapsuleOnDiskLoadPei PEIM.
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> This module provides PPI to load Capsule On Disk temp relocation file
> from Root Directory file system, retrieve the capsules from the temp
> file and create capsule hobs for these capsules.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
>  MdeModulePkg/MdeModulePkg.dsc                      |   4 +
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    | 442
> +++++++++++++++++++++
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |  64 +++
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |  15 +
>  .../CapsuleOnDiskLoadPeiExtra.uni                  |  14 +
>  5 files changed, 539 insertions(+)
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> f
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.u
> ni
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiEx
> tra.uni

Since this a new module, could you help to follow the recommendation in
https://edk2.groups.io/g/devel/message/39655?p=,,,20,0,0,0::Created,,UefiDebugLibStdErr,20,2,0,31318888

to add/update 'static' (lower case) for global variables/functions whose
scope is limited within a single file?

> 
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc
> index 995fd805e1..615edddbcc 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -197,10 +197,13 @@
>    gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
> 
> +[PcdsDynamicExDefault]
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
> +
>  [Components]
>    MdeModulePkg/Application/HelloWorld/HelloWorld.inf
>    MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
>    MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
> 
> @@ -315,10 +318,11 @@
> 
> NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMainte
> nanceManagerUiLib.inf
>    }
> 
> MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManager
> Dxe.inf
> 
> MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.i
> nf
>    MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
> +
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> f
>    MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
>    MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
>    MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> 
> MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleD
> xe.inf
> 
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDx
> e.inf
> diff --git
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> c
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> c
> new file mode 100644
> index 0000000000..40d25f3d3b
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> c
> @@ -0,0 +1,442 @@
> +/** @file
> +  Recovery module.
> +
> +  Caution: This module requires additional review when modified.
> +  This module will have external input - Capsule-on-Disk Temp Relocation
> image.
> +  This external input must be validated carefully to avoid security issue like
> +  buffer overflow, integer overflow.
> +
> +  RetrieveRelocatedCapsule() will receive untrusted input and do basic
> validation.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +//
> +// The package level header files this module uses
> +//
> +#include <Uefi.h>
> +#include <PiPei.h>
> +
> +//
> +// The protocols, PPI and GUID defintions for this module
> +//
> +#include <Ppi/MasterBootMode.h>
> +#include <Ppi/FirmwareVolumeInfo.h>
> +#include <Ppi/ReadOnlyVariable2.h>
> +#include <Ppi/Capsule.h>
> +#include <Ppi/CapsuleOnDisk.h>
> +#include <Ppi/DeviceRecoveryModule.h>
> +
> +#include <Guid/FirmwareFileSystem2.h>
> +//
> +// The Library classes this module consumes
> +//
> +#include <Library/DebugLib.h>
> +#include <Library/PeimEntryPoint.h>
> +#include <Library/PeiServicesLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/CapsuleLib.h>
> +#include <Library/ReportStatusCodeLib.h>
> +
> +/**
> +  Loads a DXE capsule from some media into memory and updates the HOB
> table
> +  with the DXE firmware volume information.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> every PEIM.
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> instance.
> +
> +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> +  @retval EFI_DEVICE_ERROR   A device error occurred.
> +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LoadCapsuleOnDisk (
> +  IN EFI_PEI_SERVICES              **PeiServices,
> +  IN EFI_PEI_CAPSULE_ON_DISK_PPI   *This
> +  );
> +
> +EFI_PEI_CAPSULE_ON_DISK_PPI mCapsuleOnDiskPpi = {
> +  LoadCapsuleOnDisk
> +};
> +
> +EFI_PEI_PPI_DESCRIPTOR mCapsuleOnDiskPpiList = {
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEdkiiPeiCapsuleOnDiskPpiGuid,
> +  &mCapsuleOnDiskPpi
> +};
> +
> +/**
> +  Determine if capsule comes from memory by checking Capsule PPI.
> +
> +  @param[in]  PeiServices General purpose services available to every PEIM.
> +
> +  @retval TRUE   Capsule comes from memory.
> +  @retval FALSE  No capsule comes from memory.
> +
> +**/
> +STATIC
> +BOOLEAN
> +CheckCapsuleFromRam (
> +  IN CONST EFI_PEI_SERVICES          **PeiServices
> +  )
> +{
> +  EFI_STATUS              Status;
> +  PEI_CAPSULE_PPI         *Capsule;
> +
> +  Status = PeiServicesLocatePpi (
> +             &gPeiCapsulePpiGuid,


Suggest to use gEfiPeiCapsulePpiGuid here.
gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.


> +             0,
> +             NULL,
> +             (VOID **) &Capsule
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    Status = Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES
> **)PeiServices);
> +    if (!EFI_ERROR(Status)) {
> +      return TRUE;
> +    }
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +  Determine if it is a Capsule On Disk mode.
> +
> +  @retval TRUE         Capsule On Disk mode.
> +  @retval FALSE        Not capsule On Disk mode.
> +
> +**/
> +BOOLEAN
> +IsCapsuleOnDiskMode (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UINTN                           Size;
> +  EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
> +  BOOLEAN                         CodRelocInfo;
> +
> +  Status = PeiServicesLocatePpi (
> +             &gEfiPeiReadOnlyVariable2PpiGuid,
> +             0,
> +             NULL,
> +             (VOID **) &PPIVariableServices
> +             );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Size = sizeof (BOOLEAN);
> +  Status = PPIVariableServices->GetVariable (
> +                                  PPIVariableServices,
> +                                  COD_RELOCATION_INFO_VAR_NAME,
> +                                  &gEfiCapsuleVendorGuid,
> +                                  NULL,
> +                                  &Size,
> +                                  &CodRelocInfo
> +                                  );
> +
> +  if (EFI_ERROR (Status) || Size != sizeof(BOOLEAN) || CodRelocInfo != TRUE)


For 'CodRelocInfo != TRUE', variable of BOOLEAN type can be directly used
in the 'if' statement without comparing with 'TRUE' or 'FALSE'.


> {
> +    DEBUG (( DEBUG_ERROR, "Error Get CodRelocationInfo variable %r!\n",
> Status));
> +    return FALSE;
> +  }
> +
> +  return TRUE;
> +}
> +
> +/**
> +  Gets capsule images from relocated capsule buffer.
> +  Create Capsule hob for each Capsule.
> +
> +  Caution: This function may receive untrusted input.
> +  Capsule-on-Disk Temp Relocation image is external input, so this function
> +  will validate Capsule-on-Disk Temp Relocation image to make sure the
> content
> +  is read within the buffer.
> +
> +  @param[in]  RelocCapsuleBuf        Buffer pointer to the relocated capsule.
> +  @param[in]  RelocCapsuleTotalSize  Total size of the relocated capsule.
> +
> +  @retval EFI_SUCCESS     Succeed to get capsules and create hob.
> +  @retval Others          Fail to get capsules and create hob.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RetrieveRelocatedCapsule (
> +  IN UINT8                *RelocCapsuleBuf,
> +  IN UINTN                RelocCapsuleTotalSize
> +  )
> +{
> +  EFI_STATUS               Status;
> +  UINTN                    Index;
> +  UINT8                    *CapsuleDataBufEnd;
> +  UINT8                    *CapsulePtr;
> +  UINT32                   CapsuleSize;
> +  UINT64                   TotalImageSize;
> +  UINTN                    CapsuleNum;
> +
> +  CapsuleNum = 0;
> +
> +  //
> +  // Temp file contains at least 2 capsule (including 1 capsule name capsule)
> & 1 UINT64
> +  //
> +  if (RelocCapsuleTotalSize < sizeof(UINT64) + sizeof(EFI_CAPSULE_HEADER)
> * 2) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CopyMem(&TotalImageSize, RelocCapsuleBuf, sizeof(UINT64));
> +
> +  DEBUG ((DEBUG_INFO, "ProcessRelocatedCapsule CapsuleBuf %x
> TotalCapSize %lx\n",
> +                      RelocCapsuleBuf, TotalImageSize));
> +
> +  RelocCapsuleBuf += sizeof(UINT64);
> +
> +  //
> +  // TempCaspule file length check
> +  //
> +  if (MAX_ADDRESS - TotalImageSize <= sizeof(UINT64) ||
> +      (UINT64)RelocCapsuleTotalSize != TotalImageSize + sizeof(UINT64) ||
> +      (UINTN)(MAX_ADDRESS -
> (PHYSICAL_ADDRESS)(UINTN)RelocCapsuleBuf) <= TotalImageSize) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CapsuleDataBufEnd = RelocCapsuleBuf + TotalImageSize;
> +
> +  //
> +  // TempCapsule file integrity check over Capsule Header to ensure no data
> corruption in NV Var & Relocation storage
> +  //
> +  CapsulePtr = RelocCapsuleBuf;
> +
> +  while (CapsulePtr < CapsuleDataBufEnd) {
> +    if ((CapsuleDataBufEnd - CapsulePtr) < sizeof(EFI_CAPSULE_HEADER) ||
> +        ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize <
> sizeof(EFI_CAPSULE_HEADER) ||
> +        (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)CapsulePtr) <
> ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize
> +        ) {
> +      break;
> +    }
> +    CapsulePtr += ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize;
> +    CapsuleNum ++;
> +  }
> +
> +  if (CapsulePtr != CapsuleDataBufEnd) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Capsule count must be less than PcdCapsuleMax, avoid building too
> many CvHobs to occupy all the free space in HobList.
> +  //
> +  if (CapsuleNum > PcdGet16 (PcdCapsuleMax)) {
> +    Status = EFI_INVALID_PARAMETER;
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Re-iterate the capsule buffer to create Capsule hob & Capsule Name Str
> Hob for each Capsule saved in relocated capsule file
> +  //
> +  CapsulePtr = RelocCapsuleBuf;
> +  Index      = 0;
> +  while (CapsulePtr < CapsuleDataBufEnd) {
> +    CapsuleSize = ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize;
> +    BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsulePtr, CapsuleSize);
> +
> +    DEBUG((DEBUG_INFO, "Capsule saved in address %x size %x\n",
> CapsulePtr, CapsuleSize));
> +
> +    CapsulePtr += CapsuleSize;
> +    Index++;
> +  }
> +
> +EXIT:
> +
> +  return Status;
> +}
> +
> +/**
> +  Recovery module entrypoint
> +
> +  @param[in] FileHandle   Handle of the file being invoked.
> +  @param[in] PeiServices  Describes the list of possible PEI Services.
> +
> +  @return EFI_SUCCESS Recovery module is initialized.
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeCapsuleOnDiskLoad (
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINTN       BootMode;
> +  UINTN       FileNameSize;
> +
> +  BootMode = GetBootModeHob();
> +  ASSERT(BootMode == BOOT_ON_FLASH_UPDATE);
> +
> +  //
> +  // If there are capsules provisioned in memory, quit.
> +  // Only one capsule resource is accept, CapsuleOnRam's priority is higher
> than CapsuleOnDisk.
> +  //
> +  if (CheckCapsuleFromRam(PeiServices)) {
> +    DEBUG((DEBUG_ERROR, "Capsule On Memory Detected! Quit.\n"));
> +    return EFI_ABORTED;
> +  }
> +
> +  DEBUG_CODE (
> +   VOID *CapsuleOnDiskModePpi;
> +
> +  if (!IsCapsuleOnDiskMode()){
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Check Capsule On Disk Relocation flag. If exists, load capsule & create
> Capsule Hob
> +  //
> +  Status = PeiServicesLocatePpi (
> +             &gEfiPeiBootInCapsuleOnDiskModePpiGuid,
> +             0,
> +             NULL,
> +             (VOID **)&CapsuleOnDiskModePpi
> +             );
> +    if (EFI_ERROR(Status)) {
> +      DEBUG((DEBUG_ERROR, "Locate CapsuleOnDiskModePpi error %x\n",
> Status));
> +      return Status;
> +    }
> +  );
> +
> +  Status = (**PeiServices).InstallPpi (PeiServices, &mCapsuleOnDiskPpiList);


Minor one, suggest to directly use PeiServicesInstallPpi().


> +  ASSERT_EFI_ERROR (Status);
> +
> +  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);
> +  Status = PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *)
> PcdGetPtr(PcdCoDRelocationFileName));


Buffer for 'PcdRecoveryFileName' may not be big enough to hold the content
in 'PcdCoDRelocationFileName'.

I think there might be a chance for the above PcdSetPtrS() call to fail.


> +  ASSERT_EFI_ERROR (Status);
> +
> +  return Status;
> +}
> +
> +/**
> +  Loads a DXE capsule from some media into memory and updates the HOB
> table
> +  with the DXE firmware volume information.
> +
> +  @param[in]  PeiServices   General-purpose services that are available to
> every PEIM.
> +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> instance.
> +
> +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> +  @retval EFI_DEVICE_ERROR   A device error occurred.
> +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LoadCapsuleOnDisk (
> +  IN EFI_PEI_SERVICES                     **PeiServices,
> +  IN EFI_PEI_CAPSULE_ON_DISK_PPI          *This
> +  )
> +{
> +  EFI_STATUS                          Status;
> +  EFI_PEI_DEVICE_RECOVERY_MODULE_PPI  *DeviceRecoveryPpi;
> +  UINTN                               NumberRecoveryCapsules;
> +  UINTN                               Instance;
> +  UINTN                               CapsuleInstance;
> +  UINTN                               CapsuleSize;
> +  EFI_GUID                            CapsuleType;
> +  VOID                                *CapsuleBuffer;
> +
> +  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Load Capsule On Disk Entry\n"));
> +
> +  for (Instance = 0; ; Instance++) {
> +    Status = PeiServicesLocatePpi (
> +               &gEfiPeiDeviceRecoveryModulePpiGuid,
> +               Instance,
> +               NULL,
> +               (VOID **)&DeviceRecoveryPpi
> +               );
> +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LocateRecoveryPpi (%d) -
>  %r\n", Instance, Status));
> +    if (EFI_ERROR (Status)) {
> +      if (Instance == 0) {
> +        REPORT_STATUS_CODE (
> +          EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> +          (EFI_SOFTWARE_PEI_MODULE |
> EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
> +          );
> +      }
> +      break;
> +    }
> +    NumberRecoveryCapsules = 0;
> +    Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
> +                                  (EFI_PEI_SERVICES **)PeiServices,
> +                                  DeviceRecoveryPpi,
> +                                  &NumberRecoveryCapsules
> +                                  );
> +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules,
> Status));
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    for (CapsuleInstance = 1; CapsuleInstance <= NumberRecoveryCapsules;
> CapsuleInstance++) {
> +      CapsuleSize = 0;
> +      Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
> +                                    (EFI_PEI_SERVICES **)PeiServices,
> +                                    DeviceRecoveryPpi,
> +                                    CapsuleInstance,
> +                                    &CapsuleSize,
> +                                    &CapsuleType
> +                                    );
> +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - GetRecoveryCapsuleInfo
> (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
> +      if (EFI_ERROR (Status)) {
> +        break;
> +      }
> +
> +      //
> +      // Allocate the memory so that it gets preserved into DXE.
> +      // Capsule is special because it may need to populate to system table
> +      //
> +      CapsuleBuffer = AllocateRuntimePages (EFI_SIZE_TO_PAGES
> (CapsuleSize));
> +
> +      if (CapsuleBuffer == NULL) {
> +        DEBUG ((DEBUG_ERROR, "LoadCapsuleOnDisk - AllocateRuntimePages
> fail\n"));
> +        continue;
> +      }
> +
> +      Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
> +                                    (EFI_PEI_SERVICES **)PeiServices,
> +                                    DeviceRecoveryPpi,
> +                                    CapsuleInstance,
> +                                    CapsuleBuffer
> +                                    );
> +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LoadRecoveryCapsule
> (%d) - %r\n", CapsuleInstance, Status));
> +      if (EFI_ERROR (Status)) {
> +        FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
> +        break;
> +      }
> +
> +      //
> +      // Capsule Update Mode, Split relocated Capsule buffer into different
> capsule vehical hobs.
> +      //
> +      Status = RetrieveRelocatedCapsule(CapsuleBuffer, CapsuleSize);
> +
> +      break;
> +    }
> +
> +    if (EFI_ERROR (Status)) {
> +      REPORT_STATUS_CODE (
> +        EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> +        (EFI_SOFTWARE_PEI_MODULE |
> EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
> +        );
> +    }
> +
> +    return Status;
> +  }
> +
> +  //
> +  // Any attack against GPT, Relocation Info Variable or temp relocation file
> will result in no Capsule HOB and return EFI_NOT_FOUND.
> +  // After flow to DXE phase. since no capsule hob is detected. Platform will
> clear Info flag and force restart.
> +  // No volunerability will be exposed
> +  //
> +
> +  return EFI_NOT_FOUND;
> +}
> diff --git
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> inf
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> inf
> new file mode 100644
> index 0000000000..4af07440b7
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> inf
> @@ -0,0 +1,64 @@
> +## @file
> +# Load Capsule on Disk module.
> +#
> +# Load Capsule On Disk from Root Directory file system. Create CV hob
> +# based on temporary Capsule On Disk file.
> +#
> +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = CapsuleOnDiskLoadPei
> +  MODULE_UNI_FILE                = CapsuleOnDiskLoadPei.uni
> +  FILE_GUID                      = 8ADEDF9E-2EC8-40fb-AE56-B76D90225D2D
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = InitializeCapsuleOnDiskLoad
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources]
> +  CapsuleOnDiskLoadPei.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  PeimEntryPoint
> +  DebugLib
> +  HobLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
> +  ReportStatusCodeLib
> +
> +[Ppis]
> +  gEdkiiPeiCapsuleOnDiskPpiGuid           ## PRODUCES
> +  gEfiPeiReadOnlyVariable2PpiGuid         ## CONSUMES
> +  gEfiPeiBootInCapsuleOnDiskModePpiGuid   ## SOMETIMES_CONSUMES
> +  gEfiPeiDeviceRecoveryModulePpiGuid      ## CONSUMES
> +  gPeiCapsulePpiGuid                      ## CONSUMES


Suggest to use gEfiPeiCapsulePpiGuid here.
gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.


> +
> +[Guids]
> +  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ## Variable
> L"CodRelocationInfo"
> +
> +[Pcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName
> ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax                            ##
> CONSUMES
> +
> +[PcdEx]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName                      ##
> PRODUCES
> +
> +[depex]


Minor comment:
[depex] -> [Depex]

Best Regards,
Hao Wu


> +  gEfiPeiBootInCapsuleOnD
iskModePpiGuid
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  CapsuleOnDiskLoadPeiExtra.uni
> diff --git
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> uni
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> uni
> new file mode 100644
> index 0000000000..c3eae6a5c2
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> uni
> @@ -0,0 +1,15 @@
> +// /** @file
> +// Caspule On Disk Load module.
> +//
> +// Load Capsule On Disk and build CV hob.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "Caspule On Disk
> Load module."
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Load Capsule
> On Disk and build CV hob."
> diff --git
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> Extra.uni
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> Extra.uni
> new file mode 100644
> index 0000000000..81034f6294
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> Extra.uni
> @@ -0,0 +1,14 @@
> +// /** @file
> +// CapsuleOnDiskLoadPei Localized Strings and Content
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"CapsuleOnDiskLoad PEI Driver"
> +
> +
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  2019-06-05 15:42 ` [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature Xu, Wei6
@ 2019-06-12  7:49   ` Wu, Hao A
  2019-06-19  0:41     ` Zhang, Chao B
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-12  7:49 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J, Zhang, Chao B

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe:
> Introduce PCD to control this feature.
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> Introduce PcdCapsuleInRamSupport to turn on/off Capsule In Ram feature.
> Platform could choose to drop CapsulePei/CapsuleX64 and not to support
> Capsule In Ram.


For this patch, it only affects UpdateCapsule(). Do we need to update the
behavior for QueryCapsuleCapabilities() as well?

Best Regards,
Hao Wu


> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf |  1
> +
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c      | 10
> +++++++++-
>  2 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> index 338577e293..9da450722b 100644
> ---
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> @@ -88,10 +88,11 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> CONSUMES
> 
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ##
> SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ##
> SOMETIMES_CONSUMES # Populate Image requires reset support.
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ##
> CONSUMES
> 
>  [Pcd.X64]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize
> ## SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ##
> SOMETIMES_CONSUMES
> 
> diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> index aaf819c4c6..53a1af44e2 100644
> --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> @@ -2,11 +2,11 @@
>    Capsule Runtime Driver produces two UEFI capsule runtime services.
>    (UpdateCapsule, QueryCapsuleCapabilities)
>    It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>    the capsule runtime services are ready.
> 
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #include "CapsuleService.h"
> @@ -69,10 +69,18 @@ UpdateCapsule (
>    BOOLEAN                   NeedReset;
>    BOOLEAN                   InitiateReset;
>    CHAR16                    CapsuleVarName[30];
>    CHAR16                    *TempVarName;
> 
> +  //
> +  // Check if platform support Capsule In RAM or not.
> +  // Platform could choose to drop CapsulePei/CapsuleX64 and do not
> support Capsule In RAM.
> +  //
> +  if (!PcdGetBool(PcdCapsuleInRamSupport)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
>    //
>    // Capsule Count can't be less than one.
>    //
>    if (CapsuleCount < 1) {
>      return EFI_INVALID_PARAMETER;
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule On Disk.
  2019-06-05 15:42 ` [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule On Disk Xu, Wei6
@ 2019-06-12  7:49   ` Wu, Hao A
  0 siblings, 0 replies; 33+ messages in thread
From: Wu, Hao A @ 2019-06-12  7:49 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J, Zhang, Chao B

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule
> On Disk.
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> If Capsule On Disk mode, call Capsule On Disk Load PPI to load
> capsules. When it fails, still goes to Firmware Update boot path.
> BDS will clear corresponding indicator and reboot later on.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.h   |  3 ++-
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 20 ++++++++++--------
>  MdeModulePkg/Core/DxeIplPeim/DxeLoad.c  | 37
> ++++++++++++++++++++++++++++++++-
>  3 files changed, 49 insertions(+), 11 deletions(-)
> 
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> index 063fefb414..90b5b5b211 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h
> @@ -1,10 +1,10 @@
>  /** @file
>    Master header file for DxeIpl PEIM. All source files in this module should
>    include this file for common definitions.
> 
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #ifndef __PEI_DXEIPL_H__
> @@ -19,10 +19,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <Ppi/FirmwareVolumeInfo.h>
>  #include <Ppi/GuidedSectionExtraction.h>
>  #include <Ppi/LoadFile.h>
>  #include <Ppi/S3Resume2.h>
>  #include <Ppi/RecoveryModule.h>
> +#include <Ppi/CapsuleOnDisk.h>
>  #include <Ppi/VectorHandoffInfo.h>
> 
>  #include <Guid/MemoryTypeInformation.h>
>  #include <Guid/MemoryAllocationHob.h>
>  #include <Guid/FirmwareFileSystem2.h>
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> index 62bb3f3077..ff036d8688 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> @@ -3,11 +3,11 @@
>  #
>  #  This module produces a special PPI named the DXE Initial Program Load
> (IPL)
>  #  PPI to discover and dispatch the DXE Foundation and components that are
>  #  needed to run the DXE Foundation.
>  #
> -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  #  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
>  #
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
>  ##
> @@ -74,21 +74,23 @@
> 
>  [LibraryClasses.ARM, LibraryClasses.AARCH64]
>    ArmMmuLib
> 
>  [Ppis]
> -  gEfiDxeIplPpiGuid                 ## PRODUCES
> -  gEfiPeiDecompressPpiGuid          ## PRODUCES
> -  gEfiEndOfPeiSignalPpiGuid         ## SOMETIMES_PRODUCES # Not produced
> on S3 boot path
> -  gEfiPeiReadOnlyVariable2PpiGuid   ## SOMETIMES_CONSUMES
> -  gEfiPeiLoadFilePpiGuid            ## SOMETIMES_CONSUMES
> -  gEfiPeiS3Resume2PpiGuid           ## SOMETIMES_CONSUMES # Consumed
> on S3 boot path
> -  gEfiPeiRecoveryModulePpiGuid      ## SOMETIMES_CONSUMES #
> Consumed on recovery boot path
> +  gEfiDxeIplPpiGuid                      ## PRODUCES
> +  gEfiPeiDecompressPpiGuid               ## PRODUCES
> +  gEfiEndOfPeiSignalPpiGuid              ## SOMETIMES_PRODUCES # Not
> produced on S3 boot path
> +  gEfiPeiReadOnlyVariable2PpiGuid        ## SOMETIMES_CONSUMES
> +  gEfiPeiLoadFilePpiGuid                 ## SOMETIMES_CONSUMES
> +  gEfiPeiS3Resume2PpiGuid                ## SOMETIMES_CONSUMES #
> Consumed on S3 boot path
> +  gEfiPeiRecoveryModulePpiGuid           ## SOMETIMES_CONSUMES #
> Consumed on recovery boot path
>    ## SOMETIMES_CONSUMES
>    ## UNDEFINED # HOB
>    gEfiVectorHandoffInfoPpiGuid
> -  gEfiPeiMemoryDiscoveredPpiGuid    ## SOMETIMES_CONSUMES
> +  gEfiPeiMemoryDiscoveredPpiGuid         ## SOMETIMES_CONSUMES
> +  gEfiPeiBootInCapsuleOnDiskModePpiGuid  ## SOMETIMES_CONSUMES
> +  gEdkiiPeiCapsuleOnDiskPpiGuid          ## SOMETIMES_CONSUMES #
> Consumed on firmware update boot path
> 
>  [Guids]
>    ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation"
>    ## SOMETIMES_PRODUCES ## HOB
>    gEfiMemoryTypeInformationGuid
> diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> index c6e5b83309..9dc2d4485f 100644
> --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
> @@ -1,11 +1,11 @@
>  /** @file
>    Last PEIM.
>    Responsibility of this module is to load the DXE Core from a Firmware
> Volume.
> 
>  Copyright (c) 2016 HP Development Company, L.P.
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #include "DxeIpl.h"
> @@ -263,17 +263,38 @@ DxeLoadCore (
>    UINTN                                     Instance;
>    UINT32                                    AuthenticationState;
>    UINTN                                     DataSize;
>    EFI_PEI_S3_RESUME2_PPI                    *S3Resume;
>    EFI_PEI_RECOVERY_MODULE_PPI               *PeiRecovery;
> +  EFI_PEI_CAPSULE_ON_DISK_PPI               *PeiCapsuleOnDisk;
>    EFI_MEMORY_TYPE_INFORMATION
> MemoryData[EfiMaxMemoryType + 1];
> +  VOID                                      *CapsuleOnDiskModePpi;
> +  BOOLEAN                                   IsCapsuleOnDiskMode;
> +
> +  IsCapsuleOnDiskMode = FALSE;
> 
>    //
>    // if in S3 Resume, restore configure
>    //
>    BootMode = GetBootModeHob ();
> 
> +  //
> +  // If Capsule On Disk mode, call storage stack to read Capsule Relocation
> file
> +  // IoMmmu is highly recommmended to enable before reading
> +  //
> +  if (BootMode == BOOT_ON_FLASH_UPDATE) {
> +    Status = PeiServicesLocatePpi (
> +               &gEfiPeiBootInCapsuleOnDiskModePpiGuid,
> +               0,
> +               NULL,
> +               &CapsuleOnDiskModePpi
> +               );
> +    if (!EFI_ERROR(Status)) {
> +      IsCapsuleOnDiskMode = TRUE;
> +    }
> +  }
> +


Suggest to merge the above logic with the below 

  else if (IsCapsuleOnDiskMode) {...}

chunk of codes together.

In such case, the logic seems a bit cleaner and 'IsCapsuleOnDiskMode' can
also be dropped.

Best Regards,
Hao Wu


>    if (BootMode == BOOT_ON_S3_RESUME) {
>      Status = PeiServicesLocatePpi (
>                 &gEfiPeiS3Resume2PpiGuid,
>                 0,
>                 NULL,
> @@ -328,10 +349,24 @@ DxeLoadCore (
>      }
>      REPORT_STATUS_CODE (EFI_PROGRESS_CODE,
> (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));
>      //
>      // Now should have a HOB with the DXE core
>      //
> +  } else if (IsCapsuleOnDiskMode) {
> +    Status = PeiServicesLocatePpi (
> +               &gEdkiiPeiCapsuleOnDiskPpiGuid,
> +               0,
> +               NULL,
> +               (VOID **) &PeiCapsuleOnDisk
> +               );
> +
> +    //
> +    // Whether failed, still goes to Firmware Update boot path. BDS will clear
> corresponding indicator and reboot later on
> +    //
> +    if (!EFI_ERROR (Status)) {
> +      Status = PeiCapsuleOnDisk->LoadCapsuleOnDisk (PeiServices,
> PeiCapsuleOnDisk);
> +    }
>    }
> 
>    if (GetFirstGuidHob ((CONST EFI_GUID
> *)&gEfiMemoryTypeInformationGuid) == NULL) {
>      //
>      // Don't build GuidHob if GuidHob has been installed.
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.
  2019-06-05 15:42 ` [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib Xu, Wei6
@ 2019-06-12  7:49   ` Wu, Hao A
  2019-06-19  7:55     ` Xu, Wei6
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-12  7:49 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J, Zhang, Chao B

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk
> APIs into CapsuleLib.


Not directly related with this patch, I saw many function declarations
within .C file for this library. Could you help to propose another series
to add header files to address this (Maybe like the case in
MdeModulePkg/Universal/Variable/RuntimeDxe to handle multi-phases).


Some general level comments:

I saw some of the new functions whose scope is limited within a single
file have been decorated with keyword 'STATIC'. Could you help to make it
consistent for all the newly added global variables/functions? Also, could
you help to use keyword 'static' (lower case) instead?


> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> CoDCheckCapsuleOnDiskFlag() is to check if CapsuleOnDisk flag in
> "OsIndications" Variable is enabled. It is used to indicate whether
> capsule on disk is provisioned in normal boot path.
> 
> CoDClearCapsuleOnDiskFlag() is to to clear CapsuleOnDisk flags,
> including "OsIndications" and "BootNext" variable.
> 
> CoDRelocateCapsule() is to relocate the capsules from EFI system
> partition. Depends on PcdCapsuleInRamSupport, there are two solutions
> to relocate the capsule on disk images:
> When Capsule In Ram is supported, the Capsule On Disk images are
> relocated into memory, and call UpdateCapsule() service to deliver
> the capsules.
> When Capsule In Ram is not supported, the Capsule On Disk images are
> relocated into a temp file which will be stored in root directory on
> a platform specific storage device. CapsuleOnDiskLoadPei PEIM will
> retrieve the capsules from the relocation temp file and report
> capsule hobs for them.
> 
> CoDRemoveTempFile() is to remove the relocation temp file in the next
> boot after capsules are processed.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
>  MdeModulePkg/Include/Library/CapsuleLib.h          |   94 +-
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       | 1983
> ++++++++++++++++++++
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |   63 +
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |   56 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |   21 +-
>  .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |  121 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |   67 +-
>  .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |    3 +-
>  .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |   85 +-
>  9 files changed, 2466 insertions(+), 27 deletions(-)
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> 
> diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h
> b/MdeModulePkg/Include/Library/CapsuleLib.h
> index 1fc2fba3a2..f3cb17cbf9 100644
> --- a/MdeModulePkg/Include/Library/CapsuleLib.h
> +++ b/MdeModulePkg/Include/Library/CapsuleLib.h
> @@ -1,17 +1,37 @@
>  /** @file
> 
>    This library class defines a set of interfaces for how to process capsule
> image updates.
> 
> -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #ifndef __CAPSULE_LIB_H__
>  #define __CAPSULE_LIB_H__
> 
> +#include <Guid/FileInfo.h>
> +
> +
> +typedef struct {
> +  //
> +  // image address.
> +  //
> +  VOID             *ImageAddress;
> +  //
> +  // The file info of the image comes from.
> +  //  if FileInfo == NULL. means image does not come from file
> +  //
> +  EFI_FILE_INFO    *FileInfo;
> +} IMAGE_INFO;


Will this 'IMAGE_INFO' structure (FileInfo.h include as well) be used by
the consumer of CapsuleLib? For this series, this one is only used within
DxeCapsuleLibFmp (implementation of CapsuleLib).

If it is only used internally, I suggest to move the definition into
MdeModulePkg\Library\DxeCapsuleLibFmp\CapsuleOnDisk.h.


> +
> +//
> +// BOOLEAN Variable to save the total size of all Capsule On Disk during
> relocation
> +//


The above description comment seems not matching the usage of the variable
perfectly. Looks to me the variable is used to reflect whether the system
is in the capsule on disk state rather than the size information.


> +#define COD_RELOCATION_INFO_VAR_NAME   L"CodRelocationInfo"
> +
>  /**
>    The firmware checks whether the capsule image is supported
>    by the CapsuleGuid in CapsuleHeader or if there is other specific
> information in
>    the capsule image.
> 
> @@ -79,6 +99,78 @@ EFI_STATUS
>  EFIAPI
>  ProcessCapsules (
>    VOID
>    );
> 
> +/**
> +  This routine is called to check if CapsuleOnDisk flag in OsIndications
> Variable
> +  is enabled.
> +
> +  @retval TRUE     Flag is enabled
> +  @retval FALSE    Flag is not enabled
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +CoDCheckCapsuleOnDiskFlag(
> +  VOID
> +  );
> +
> +
> +/**
> +  This routine is called to clear CapsuleOnDisk flags including OsIndications
> and BootNext variable
> +
> +  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDClearCapsuleOnDiskFlag(
> +  VOID
> +  );
> +
> +/**
> +  Relocate Capsule on Disk from EFI system partition.
> +
> +  Two solution to deliver Capsule On Disk:
> +  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On
> Disk to memory and call UpdateCapsule().
> +  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On
> Disk to a platform-specific NV storage
> +  device with BlockIo protocol.
> +
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  Side Effects:
> +    Capsule Delivery Supported Flag in OsIndication variable and BootNext
> variable will be cleared.
> +    Solution B: Content corruption. Block IO write directly touches low level
> write. Orignal partitions, file
> +  systems of the relocation device will be corrupted.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.


For me, it would be better to explicitly mention the behavior for
'MaxRetry' with the value 0. Judging from the implementation, 0 means no
retry.

Similar case for API CoDRemoveTempFile() as well.

> +
> +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.


sucessfully -> successfully
Please help to update this typo in library instances as well.


> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDRelocateCapsule(
> +  UINTN     MaxRetry
> +  );
> +
> +/**
> +  Remove the temp file from the root of EFI System Partition.
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +
> +  @retval EFI_SUCCESS   Remove the temp file successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDRemoveTempFile (
> +  UINTN    MaxRetry
> +  );
> +
>  #endif
> diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
> new file mode 100644
> index 0000000000..5f1edbbbae
> --- /dev/null
> +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
> @@ -0,0 +1,1983 @@
> +/** @file
> +  The implementation supports Capusle on Disk.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "CapsuleOnDisk.h"
> +
> +/**
> +  Return if this capsule is a capsule name capsule, based upon
> CapsuleHeader.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  It is a capsule name capsule.
> +  @retval FALSE It is not a capsule name capsule.
> +**/
> +BOOLEAN
> +IsCapsuleNameCapsule (
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  );
> +
> +/**
> +  Check the integrity of the capsule name capsule.
> +  If the capsule is vaild, return the physical address of each capsule name
> string.
> +
> +  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule
> name capsule.
> +  @param[out] CapsuleNameNum  Number of capsule name.
> +
> +  @retval NULL                Capsule name capsule is not valid.
> +  @retval CapsuleNameBuf      Array of capsule name physical address.
> +
> +**/
> +EFI_PHYSICAL_ADDRESS *
> +ValidateCapsuleNameCapsuleIntegrity (
> +  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,
> +  OUT UINTN                         *CapsuleNameNum
> +  )
> +{
> +  UINT8                    *CapsuleNamePtr;
> +  UINT8                    *CapsuleNameBufStart;
> +  UINT8                    *CapsuleNameBufEnd;
> +  UINTN                    Index;
> +  UINTN                    StringSize;
> +  EFI_PHYSICAL_ADDRESS     *CapsuleNameBuf;
> +
> +  if (!IsCapsuleNameCapsule (CapsuleHeader)) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Total string size must be even.
> +  //
> +  if (((CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize) &
> BIT0) != 0) {
> +    return NULL;
> +  }
> +
> +  *CapsuleNameNum = 0;
> +  Index = 0;
> +  CapsuleNameBufStart = (UINT8 *) CapsuleHeader + CapsuleHeader-
> >HeaderSize;
> +
> +  //
> +  // If strings are not aligned on a 16-bit boundary, reallocate memory for it.
> +  //
> +  if (((UINTN) CapsuleNameBufStart & BIT0) != 0) {
> +    CapsuleNameBufStart = AllocateCopyPool (CapsuleHeader-
> >CapsuleImageSize - CapsuleHeader->HeaderSize, CapsuleNameBufStart);
> +  }
> +
> +  CapsuleNameBufEnd = CapsuleNameBufStart + CapsuleHeader-
> >CapsuleImageSize - CapsuleHeader->HeaderSize;
> +
> +  CapsuleNamePtr = CapsuleNameBufStart;
> +  while (CapsuleNamePtr < CapsuleNameBufEnd) {
> +    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd
> - CapsuleNamePtr)/sizeof(CHAR16));
> +    CapsuleNamePtr += StringSize;
> +    (*CapsuleNameNum) ++;
> +  }
> +
> +  //
> +  // Integrity check.
> +  //
> +  if (CapsuleNamePtr != CapsuleNameBufEnd) {
> +    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize) {
> +      FreePool (CapsuleNameBufStart);
> +    }
> +    return NULL;
> +  }
> +
> +  CapsuleNameBuf = AllocatePool (*CapsuleNameNum * sizeof
> (EFI_PHYSICAL_ADDRESS));
> +  if (CapsuleNameBuf == NULL) {
> +    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader-
> >HeaderSize) {
> +      FreePool (CapsuleNameBufStart);
> +    }
> +    return NULL;
> +  }
> +
> +  CapsuleNamePtr = CapsuleNameBufStart;
> +  while (CapsuleNamePtr < CapsuleNameBufEnd) {
> +    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd
> - CapsuleNamePtr)/sizeof(CHAR16));
> +    CapsuleNameBuf[Index] = (EFI_PHYSICAL_ADDRESS)(UINTN)
> CapsuleNamePtr;
> +    CapsuleNamePtr += StringSize;
> +    Index ++;
> +  }
> +
> +  return CapsuleNameBuf;
> +}
> +
> +/**
> +  This routine is called to upper case given unicode string.
> +
> +  @param[in]   Str              String to upper case
> +
> +  @retval upper cased string after process
> +
> +**/
> +STATIC
> +CHAR16 *
> +UpperCaseString (
> +  IN CHAR16 *Str
> +  )
> +{
> +  CHAR16  *Cptr;
> +
> +  for (Cptr = Str; *Cptr; Cptr++) {
> +    if (L'a' <= *Cptr && *Cptr <= L'z') {
> +      *Cptr = *Cptr - L'a' + L'A';
> +    }
> +  }
> +
> +  return Str;
> +}
> +
> +/**
> +  This routine is used to return substring before period '.' or '\0'
> +  Caller should respsonsible of substr space allocation & free
> +
> +  @param[in]   Str              String to check
> +  @param[out]  SubStr           First part of string before period or '\0'
> +  @param[out]  SubStrLen        Length of first part of string
> +
> +**/
> +STATIC
> +VOID
> +GetSubStringBeforePeriod (
> +  IN  CHAR16 *Str,
> +  OUT CHAR16 *SubStr,
> +  OUT UINTN  *SubStrLen
> +  )
> +{
> +  UINTN Index;
> +  for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {
> +    SubStr[Index] = Str[Index];
> +  }
> +
> +  SubStr[Index] = L'\0';
> +  *SubStrLen = Index;
> +}
> +
> +/**
> +  This routine pad the string in tail with input character.
> +
> +  @param[in]   StrBuf            Str buffer to be padded, should be enough room
> for
> +  @param[in]   PadLen            Expected padding length
> +  @param[in]   Character         Character used to pad
> +
> +**/
> +STATIC
> +VOID
> +PadStrInTail (
> +  IN CHAR16   *StrBuf,
> +  IN UINTN    PadLen,
> +  IN CHAR16   Character
> +  )
> +{
> +  UINTN Index;
> +
> +  for (Index = 0; StrBuf[Index] != L'\0'; Index++);
> +
> +  while(PadLen != 0) {
> +    StrBuf[Index] = Character;
> +    Index++;
> +    PadLen--;
> +  }
> +
> +  StrBuf[Index] = L'\0';
> +}
> +
> +/**
> +  This routine find the offset of the last period '.' of string. If No period exists
> +  function FileNameExtension is set to L'\0'
> +
> +  @param[in]  FileName           File name to split between last period
> +  @param[out] FileNameFirst      First FileName before last period
> +  @param[out] FileNameExtension  FileName after last period
> +
> +**/
> +STATIC
> +VOID
> +SplitFileNameExtension (
> +  IN CHAR16   *FileName,
> +  OUT CHAR16  *FileNameFirst,
> +  OUT CHAR16  *FileNameExtension
> +  )
> +{
> +  UINTN Index;
> +  UINTN StringLen;
> +
> +  StringLen = StrnLenS(FileName, MAX_FILE_NAME_SIZE);
> +  for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--);
> +
> +  //
> +  // No period exists. No FileName Extension
> +  //
> +  if (Index == 0 && FileName[Index] != L'.') {
> +    FileNameExtension[0] = L'\0';
> +    Index = StringLen;
> +  } else {
> +    StrCpyS(FileNameExtension, MAX_FILE_NAME_SIZE,
> &FileName[Index+1]);
> +  }
> +
> +  //
> +  // Copy First file name
> +  //
> +  StrnCpyS(FileNameFirst, MAX_FILE_NAME_SIZE, FileName, Index);
> +  FileNameFirst[Index] = L'\0';
> +}
> +
> +/**
> +  This routine is called to get all boot options in the order determnined by:
> +    1. "OptionBuf"
> +    2. "BootOrder"
> +
> +  @param[out] OptionBuf           BootList buffer to all boot options returned
> +  @param[out] OptionCount         BootList count of all boot options returned
> +
> +  @retval EFI_SUCCESS             There is no error when processing capsule
> +
> +**/
> +EFI_STATUS
> +GetBootOptionInOrder(
> +  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf,
> +  OUT UINTN                        *OptionCount
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  UINTN                        DataSize;
> +  UINT16                       BootNext;
> +  CHAR16                       BootOptionName[20];
> +  EFI_BOOT_MANAGER_LOAD_OPTION *BootOrderOptionBuf;
> +  UINTN                        BootOrderCount;
> +  EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry;
> +  UINTN                        BootNextCount;
> +  EFI_BOOT_MANAGER_LOAD_OPTION *TempBuf;
> +
> +  BootOrderOptionBuf  = NULL;
> +  TempBuf             = NULL;
> +  BootNextCount       = 0;
> +  BootOrderCount      = 0;
> +  *OptionBuf          = NULL;
> +  *OptionCount        = 0;
> +
> +  //
> +  // First Get BootOption from "BootNext"
> +  //
> +  DataSize = sizeof(BootNext);
> +  Status = gRT->GetVariable (
> +                  EFI_BOOT_NEXT_VARIABLE_NAME,
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *)&BootNext
> +                  );
> +  //
> +  // BootNext variable is a single UINT16
> +  //
> +  if (!EFI_ERROR(Status) && DataSize == sizeof(UINT16)) {
> +    //
> +    // Add the boot next boot option
> +    //
> +    UnicodeSPrint (BootOptionName, sizeof (BootOptionName),
> L"Boot%04x", BootNext);
> +    ZeroMem(&BootNextOptionEntry,
> sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
> +    Status = EfiBootManagerVariableToLoadOption (BootOptionName,
> &BootNextOptionEntry);
> +
> +    if (!EFI_ERROR(Status)) {
> +      BootNextCount = 1;
> +    }
> +  }
> +
> +  //
> +  // Second get BootOption from "BootOrder"
> +  //
> +  BootOrderOptionBuf = EfiBootManagerGetLoadOptions
> (&BootOrderCount, LoadOptionTypeBoot);
> +  if (BootNextCount == 0 && BootOrderCount == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // At least one BootOption is found
> +  //
> +  TempBuf = AllocatePool(sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) *
> (BootNextCount + BootOrderCount));
> +  if (TempBuf != NULL) {
> +    if (BootNextCount == 1) {
> +      CopyMem(TempBuf, &BootNextOptionEntry,
> sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
> +    }
> +
> +    if (BootOrderCount > 0) {
> +      CopyMem(TempBuf + BootNextCount, BootOrderOptionBuf,
> sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * BootOrderCount);
> +    }
> +
> +    *OptionBuf   = TempBuf;
> +    *OptionCount = BootNextCount + BootOrderCount;
> +    Status = EFI_SUCCESS;
> +  } else {
> +    Status = EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  FreePool(BootOrderOptionBuf);
> +
> +  return Status;
> +}
> +
> +/**
> +  This routine is called to get boot option by OptionNumber.
> +
> +  @param[in] Number               The OptionNumber of boot option
> +  @param[out] OptionBuf           BootList buffer to all boot options returned
> +
> +  @retval EFI_SUCCESS             There is no error when getting boot option
> +
> +**/
> +EFI_STATUS
> +GetBootOptionByNumber(
> +  IN  UINT16                       Number,
> +  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  CHAR16                        BootOptionName[20];
> +  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
> +
> +  UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x",
> Number);
> +  ZeroMem (&BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
> +  Status = EfiBootManagerVariableToLoadOption (BootOptionName,
> &BootOption);
> +
> +  if (!EFI_ERROR (Status)) {
> +    *OptionBuf = AllocatePool (sizeof
> (EFI_BOOT_MANAGER_LOAD_OPTION));
> +    CopyMem (*OptionBuf, &BootOption, sizeof
> (EFI_BOOT_MANAGER_LOAD_OPTION));
> +    return EFI_SUCCESS;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get Active EFI System Partition within GPT based on device path.
> +
> +  @param[in] DevicePath    Device path to find a active EFI System Partition
> +  @param[out] FsHandle     BootList points to all boot options returned
> +
> +  @retval EFI_SUCCESS      Active EFI System Partition is succesfully found
> +  @retval EFI_NOT_FOUND    No Active EFI System Partition is found
> +
> +**/
> +EFI_STATUS
> +GetEfiSysPartitionFromDevPath(
> +  IN EFI_DEVICE_PATH_PROTOCOL         *DevicePath,
> +  OUT EFI_HANDLE                      *FsHandle
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
> +  HARDDRIVE_DEVICE_PATH           *Hd;
> +  EFI_HANDLE                      Handle;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
> +
> +  //
> +  // Check if the device path contains GPT node
> +  //
> +  TempDevicePath = DevicePath;
> +  while (!IsDevicePathEnd (TempDevicePath)) {
> +    if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
> +       (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP)) {
> +      Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
> +      if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
> +        break;
> +      }
> +    }
> +    TempDevicePath = NextDevicePathNode (TempDevicePath);
> +  }
> +
> +  if (!IsDevicePathEnd (TempDevicePath)) {
> +    //
> +    // Search for EFI system partition protocol on full device path in Boot
> Option
> +    //
> +    Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid,
> &DevicePath, &Handle);
> +
> +    //
> +    // Search for simple file system on this handler
> +    //
> +    if (!EFI_ERROR(Status)) {
> +      Status = gBS->HandleProtocol(Handle,
> &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
> +      if (!EFI_ERROR(Status)) {
> +        *FsHandle = Handle;
> +        return EFI_SUCCESS;
> +      }
> +    }
> +  }
> +
> +  return EFI_NOT_FOUND;
> +}
> +
> +/**
> +  This routine is called to get Simple File System protocol on the first EFI
> system partition found in
> +  active boot option. The boot option list is detemined in order by
> +    1. "BootNext"
> +    2. "BootOrder"
> +
> +  @param[in]       MaxRetry           Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                      device like USB can get enumerated.
> +  @param[in, out]  LoadOptionNumber   On input, specify the boot option to
> get EFI system partition.
> +                                      On output, return the OptionNumber of the boot option
> where EFI
> +                                      system partition is got from.
> +  @param[out]      FsFsHandle         Simple File System Protocol found on first
> active EFI system partition
> +
> +  @retval EFI_SUCCESS     Simple File System protocol found for EFI system
> partition
> +  @retval EFI_NOT_FOUND   No Simple File System protocol found for EFI
> system partition
> +
> +**/
> +EFI_STATUS
> +GetEfiSysPartitionFromActiveBootOption(
> +  IN UINTN                             MaxRetry,
> +  IN OUT UINT16                        **LoadOptionNumber,
> +  OUT EFI_HANDLE                       *FsHandle
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuf;
> +  UINTN                        BootOptionNum;
> +  UINTN                        Index;
> +  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL     *CurFullPath;
> +  EFI_DEVICE_PATH_PROTOCOL     *PreFullPath;
> +
> +  *FsHandle = NULL;
> +
> +  if (*LoadOptionNumber != NULL) {
> +    BootOptionNum = 1;
> +    Status = GetBootOptionByNumber(**LoadOptionNumber,
> &BootOptionBuf);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "GetBootOptionByIndex Failed %x! No
> BootOption available for connection\n", Status));
> +      return Status;
> +    }
> +  } else {
> +    Status = GetBootOptionInOrder(&BootOptionBuf, &BootOptionNum);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "GetBootOptionInOrder Failed %x! No
> BootOption available for connection\n", Status));
> +      return Status;
> +    }
> +  }
> +
> +  //
> +  // Search BootOptionList to check if it is an active boot option with EFI
> system partition
> +  //  1. Connect device path
> +  //  2. expend short/plug in devicepath
> +  //  3. LoadImage
> +  //
> +  for (Index = 0; Index < BootOptionNum; Index++) {
> +    //
> +    // Get the boot option from the link list
> +    //
> +    DevicePath  = BootOptionBuf[Index].FilePath;
> +
> +    //
> +    // Skip inactive or legacy boot options
> +    //
> +    if ((BootOptionBuf[Index].Attributes & LOAD_OPTION_ACTIVE) == 0 ||
> +        DevicePathType (DevicePath) == BBS_DEVICE_PATH) {
> +      continue;
> +    }
> +
> +    DEBUG_CODE (
> +      CHAR16 *DevicePathStr;
> +
> +      DevicePathStr = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
> +      if (DevicePathStr != NULL){
> +        DEBUG((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr));
> +        FreePool(DevicePathStr);
> +      } else {
> +        DEBUG((DEBUG_INFO, "DevicePathToStr failed\n"));
> +      }
> +    );
> +
> +    CurFullPath = NULL;
> +    //
> +    // Try every full device Path generated from bootoption
> +    //
> +    do {
> +      PreFullPath = CurFullPath;
> +      CurFullPath =
> EfiBootManagerGetNextLoadOptionDevicePath(DevicePath, CurFullPath);
> +
> +      if (PreFullPath != NULL) {
> +        FreePool (PreFullPath);
> +      }
> +
> +      if (CurFullPath == NULL) {
> +        //
> +        // No Active EFI system partition is found in BootOption device path
> +        //
> +        Status = EFI_NOT_FOUND;
> +        break;
> +      }
> +
> +      DEBUG_CODE (
> +        CHAR16 *DevicePathStr1;
> +
> +        DevicePathStr1 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);
> +        if (DevicePathStr1 != NULL){
> +          DEBUG((DEBUG_INFO, "Full device path %s\n", DevicePathStr1));
> +          FreePool(DevicePathStr1);
> +        }
> +      );
> +
> +      //
> +      // Make sure the boot option device path connected.
> +      // Only handle first device in boot option. Other optional device paths
> are described as OSV specific
> +      // FullDevice could contain extra directory & file info. So don't check
> connection status here.
> +      //
> +      EfiBootManagerConnectDevicePath (CurFullPath, NULL);
> +      Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);
> +
> +      //
> +      // Some relocation device like USB need more time to get enumerated
> +      //
> +      while (EFI_ERROR(Status) && MaxRetry > 0) {
> +        EfiBootManagerConnectDevicePath(CurFullPath, NULL);
> +
> +        //
> +        // Search for EFI system partition protocol on full device path in Boot
> Option
> +        //
> +        Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);
> +        if (!EFI_ERROR(Status)) {
> +          break;
> +        }
> +        DEBUG((DEBUG_ERROR, "GetEfiSysPartitionFromDevPath Loop %x\n",
> Status));
> +        //
> +        // Stall 100ms if connection failed to ensure USB stack is ready
> +        //
> +        gBS->Stall(100000);
> +        MaxRetry --;
> +      }
> +    } while(EFI_ERROR(Status));
> +
> +    //
> +    // Find a qualified Simple File System
> +    //
> +    if (!EFI_ERROR(Status)) {
> +      break;
> +    }
> +
> +  }
> +
> +  //
> +  // Return the OptionNumber of the boot option where EFI system
> partition is got from
> +  //
> +  if (*LoadOptionNumber == NULL) {
> +    *LoadOptionNumber = AllocateCopyPool (sizeof(UINT16), (UINT16 *)
> &BootOptionBuf[Index].OptionNumber);
> +  }
> +
> +  //
> +  // No qualified EFI system partition found
> +  //
> +  if (*FsHandle == NULL) {
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +  DEBUG_CODE (
> +    CHAR16 *DevicePathStr2;
> +    if (*FsHandle != NULL) {
> +      DevicePathStr2 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);
> +      if (DevicePathStr2 != NULL){
> +        DEBUG((DEBUG_INFO, "Found Active EFI System Partion on %s\n",
> DevicePathStr2));
> +        FreePool(DevicePathStr2);
> +      }
> +    } else {
> +      DEBUG((DEBUG_INFO, "Failed to found Active EFI System Partion\n"));
> +    }
> +  );
> +
> +  if (CurFullPath != NULL) {
> +    FreePool(CurFullPath);
> +  }
> +
> +  //
> +  // Free BootOption Buffer
> +  //
> +  for (Index = 0; Index < BootOptionNum; Index++) {
> +    if (BootOptionBuf[Index].Description != NULL) {
> +      FreePool(BootOptionBuf[Index].Description);
> +    }
> +
> +    if (BootOptionBuf[Index].FilePath != NULL) {
> +      FreePool(BootOptionBuf[Index].FilePath);
> +    }
> +
> +    if (BootOptionBuf[Index].OptionalData != NULL) {
> +      FreePool(BootOptionBuf[Index].OptionalData);
> +    }
> +  }
> +
> +  FreePool(BootOptionBuf);
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  This routine is called to get all file infos with in a given dir & with given file
> attribute, the file info is listed in
> +  alphabetical order described in UEFI spec.
> +
> +  @param[in]  Dir                 Directory file handler
> +  @param[in]  FileAttr            Attribute of file to be red from directory
> +  @param[out] FileInfoList        File images info list red from directory
> +  @param[out] FileNum             File images number red from directory
> +
> +  @retval EFI_SUCCESS             File FileInfo list in the given
> +
> +**/
> +EFI_STATUS
> +GetFileInfoListInAlphabetFromDir(
> +  IN EFI_FILE_HANDLE  Dir,
> +  IN UINT64           FileAttr,
> +  OUT LIST_ENTRY      *FileInfoList,
> +  OUT UINTN           *FileNum
> +  )
> +{
> +  EFI_STATUS        Status;
> +  FILE_INFO_ENTRY   *NewFileInfoEntry;
> +  FILE_INFO_ENTRY   *TempFileInfoEntry;
> +  EFI_FILE_INFO     *FileInfo;
> +  CHAR16            *NewFileName;
> +  CHAR16            *ListedFileName;
> +  CHAR16            *NewFileNameExtension;
> +  CHAR16            *ListedFileNameExtension;
> +  CHAR16            *TempNewSubStr;
> +  CHAR16            *TempListedSubStr;
> +  LIST_ENTRY        *Link;
> +  BOOLEAN           NoFile;
> +  UINTN             FileCount;
> +  UINTN             IndexNew;
> +  UINTN             IndexListed;
> +  UINTN             NewSubStrLen;
> +  UINTN             ListedSubStrLen;
> +  INTN              SubStrCmpResult;
> +
> +  Status                  = EFI_SUCCESS;
> +  NewFileName             = NULL;
> +  ListedFileName          = NULL;
> +  NewFileNameExtension    = NULL;
> +  ListedFileNameExtension = NULL;
> +  TempNewSubStr           = NULL;
> +  TempListedSubStr        = NULL;
> +  NoFile                  = FALSE;
> +  FileCount               = 0;
> +
> +  InitializeListHead(FileInfoList);
> +
> +  TempNewSubStr           = (CHAR16 *)
> AllocateZeroPool(MAX_FILE_NAME_SIZE);
> +  TempListedSubStr        = (CHAR16 *)
> AllocateZeroPool(MAX_FILE_NAME_SIZE);
> +
> +  if (TempNewSubStr == NULL || TempListedSubStr == NULL ) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +
> +  for ( Status = FileHandleFindFirstFile(Dir, &FileInfo)
> +      ; !EFI_ERROR(Status) && !NoFile
> +      ; Status = FileHandleFindNextFile(Dir, FileInfo, &NoFile)
> +     ){
> +
> +    //
> +    // Skip file with mismatching File attribute
> +    //
> +    if ((FileInfo->Attribute & (FileAttr)) == 0) {
> +      continue;
> +    }
> +
> +    NewFileInfoEntry = NULL;
> +    NewFileInfoEntry =
> (FILE_INFO_ENTRY*)AllocateZeroPool(sizeof(FILE_INFO_ENTRY));
> +    if (NewFileInfoEntry == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +    NewFileInfoEntry->Signature = FILE_INFO_SIGNATURE;
> +    NewFileInfoEntry->FileInfo  = AllocateCopyPool((UINTN) FileInfo->Size,
> FileInfo);
> +    if (NewFileInfoEntry->FileInfo == NULL) {
> +      FreePool(NewFileInfoEntry);
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    NewFileInfoEntry->FileNameFirstPart  = (CHAR16 *)
> AllocateZeroPool(MAX_FILE_NAME_SIZE);
> +    if (NewFileInfoEntry->FileNameFirstPart == NULL) {
> +      FreePool(NewFileInfoEntry->FileInfo);
> +      FreePool(NewFileInfoEntry);
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +    NewFileInfoEntry->FileNameSecondPart = (CHAR16 *)
> AllocateZeroPool(MAX_FILE_NAME_SIZE);
> +    if (NewFileInfoEntry->FileNameSecondPart == NULL) {
> +      FreePool(NewFileInfoEntry->FileInfo);
> +      FreePool(NewFileInfoEntry->FileNameFirstPart);
> +      FreePool(NewFileInfoEntry);
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto EXIT;
> +    }
> +
> +    //
> +    // Splitter the whole New file name into 2 parts between the last period
> L'.' into NewFileName NewFileExtension
> +    // If no period in the whole file name. NewFileExtension is set to L'\0'
> +    //
> +    NewFileName          = NewFileInfoEntry->FileNameFirstPart;
> +    NewFileNameExtension = NewFileInfoEntry->FileNameSecondPart;
> +    SplitFileNameExtension(FileInfo->FileName, NewFileName,
> NewFileNameExtension);
> +    UpperCaseString(NewFileName);
> +    UpperCaseString(NewFileNameExtension);
> +
> +    //
> +    // Insert capsule file in alphabetical ordered list
> +    //
> +    for (Link = FileInfoList->ForwardLink; Link != FileInfoList; Link = Link-
> >ForwardLink) {
> +      //
> +      // Get the FileInfo from the link list
> +      //
> +      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> FILE_INFO_SIGNATURE);
> +      ListedFileName          = TempFileInfoEntry->FileNameFirstPart;
> +      ListedFileNameExtension = TempFileInfoEntry->FileNameSecondPart;
> +
> +      //
> +      // Follow rule in UEFI spec 8.5.5 to compare file name
> +      //
> +      IndexListed = 0;
> +      IndexNew    = 0;
> +      while (TRUE){
> +        //
> +        // First compare each substrings in NewFileName & ListedFileName
> between periods
> +        //
> +        GetSubStringBeforePeriod(&NewFileName[IndexNew],
> TempNewSubStr, &NewSubStrLen);
> +        GetSubStringBeforePeriod(&ListedFileName[IndexListed],
> TempListedSubStr, &ListedSubStrLen);
> +        if (NewSubStrLen > ListedSubStrLen) {
> +          //
> +          // Substr in NewFileName is longer. Pad tail with SPACE
> +          //
> +          PadStrInTail(TempListedSubStr, NewSubStrLen - ListedSubStrLen, L' ');
> +        } else if (NewSubStrLen < ListedSubStrLen){
> +          //
> +          // Substr in ListedFileName is longer. Pad tail with SPACE
> +          //
> +          PadStrInTail(TempNewSubStr, ListedSubStrLen - NewSubStrLen, L' ');
> +        }
> +
> +        SubStrCmpResult = StrnCmp(TempNewSubStr, TempListedSubStr,
> MAX_FILE_NAME_LEN);
> +        if (SubStrCmpResult != 0) {
> +          break;
> +        }
> +
> +        //
> +        // Move to skip this substring
> +        //
> +        IndexNew    += NewSubStrLen;
> +        IndexListed += ListedSubStrLen;
> +        //
> +        // Reach File First Name end
> +        //
> +        if (NewFileName[IndexNew] == L'\0' || ListedFileName[IndexListed] ==
> L'\0') {
> +          break;
> +        }
> +
> +        //
> +        // Skip the period L'.'
> +        //
> +        IndexNew++;
> +        IndexListed++;
> +      }
> +
> +      if (SubStrCmpResult < 0) {
> +        //
> +        // NewFileName is smaller. Find the right place to insert New file
> +        //
> +        break;
> +      } else if (SubStrCmpResult == 0) {
> +        //
> +        // 2 cases whole NewFileName is smaller than ListedFileName
> +        //   1. if NewFileName == ListedFileName. Continue to compare
> FileNameExtension
> +        //   2. if NewFileName is shorter than ListedFileName
> +        //
> +        if (NewFileName[IndexNew] == L'\0') {
> +          if (ListedFileName[IndexListed] != L'\0' ||
> (StrnCmp(NewFileNameExtension, ListedFileNameExtension,
> MAX_FILE_NAME_LEN) < 0)) {
> +            break;
> +          }
> +        }
> +      }
> +
> +      //
> +      // Other case, ListedFileName is smaller. Continue to compare the next
> file in the list
> +      //
> +    }
> +
> +    //
> +    // If Find an entry in the list whose name is bigger than new FileInfo in
> alphabet order
> +    //    Insert it before this entry
> +    // else
> +    //    Insert at the tail of this list (Link = FileInfoList)
> +    //
> +    InsertTailList(Link, &NewFileInfoEntry->Link);
> +
> +    FileCount++;
> +  }
> +
> +  *FileNum = FileCount;
> +
> +EXIT:
> +
> +  if (TempNewSubStr != NULL) {
> +    FreePool(TempNewSubStr);
> +  }
> +
> +  if (TempListedSubStr != NULL) {
> +    FreePool(TempListedSubStr);
> +  }
> +
> +  if (EFI_ERROR(Status)) {
> +    while(!IsListEmpty(FileInfoList)) {
> +      Link = FileInfoList->ForwardLink;
> +      RemoveEntryList(Link);
> +
> +      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> FILE_INFO_SIGNATURE);
> +
> +      FreePool(TempFileInfoEntry->FileInfo);
> +      FreePool(TempFileInfoEntry->FileNameFirstPart);
> +      FreePool(TempFileInfoEntry->FileNameSecondPart);
> +      FreePool(TempFileInfoEntry);
> +    }
> +    *FileNum = 0;
> +  }
> +
> +  return Status;
> +}
> +
> +
> +/**
> +  This routine is called to get all qualified image from file from an given
> directory
> +  in alphabetic order. All the file image is copied to allocated boottime
> memory.
> +  Caller should free these memory
> +
> +  @param[in]  Dir            Directory file handler
> +  @param[in]  FileAttr       Attribute of file to be red from directory
> +  @param[out] FilePtr        File images Info buffer red from directory
> +  @param[out] FileNum        File images number red from directory
> +
> +  @retval EFI_SUCCESS  Succeed to get all capsules in alphabetic order.
> +
> +**/
> +EFI_STATUS
> +GetFileImageInAlphabetFromDir(
> +  IN EFI_FILE_HANDLE   Dir,
> +  IN UINT64            FileAttr,
> +  OUT IMAGE_INFO       **FilePtr,
> +  OUT UINTN            *FileNum
> +  )
> +{
> +  EFI_STATUS            Status;
> +  LIST_ENTRY            *Link;
> +  EFI_FILE_HANDLE       FileHandle;
> +  FILE_INFO_ENTRY       *FileInfoEntry;
> +  EFI_FILE_INFO         *FileInfo;
> +  UINTN                 FileCount;
> +  IMAGE_INFO            *TempFilePtrBuf;
> +  UINTN                 Size;
> +  LIST_ENTRY            FileInfoList;
> +
> +  FileHandle       = NULL;
> +  FileCount        = 0;
> +  TempFilePtrBuf   = NULL;
> +  *FilePtr         = NULL;
> +
> +  //
> +  // Get file list in Dir in alphabetical order
> +  //
> +  Status = GetFileInfoListInAlphabetFromDir(
> +             Dir,
> +             FileAttr,
> +             &FileInfoList,
> +             &FileCount
> +             );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n"));
> +    goto EXIT;
> +  }
> +
> +  if (FileCount == 0) {
> +    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));
> +    Status = EFI_NOT_FOUND;
> +    goto EXIT;
> +  }
> +
> +  TempFilePtrBuf = (IMAGE_INFO *)AllocateZeroPool(sizeof(IMAGE_INFO)
> * FileCount);
> +  if (TempFilePtrBuf == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Read all files from FileInfoList to BS memory
> +  //
> +  FileCount = 0;
> +  for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link-
> >ForwardLink) {
> +    //
> +    // Get FileInfo from the link list
> +    //
> +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
> +    FileInfo      = FileInfoEntry->FileInfo;
> +
> +    Status = Dir->Open(
> +                    Dir,
> +                    &FileHandle,
> +                    FileInfo->FileName,
> +                    EFI_FILE_MODE_READ,
> +                    0
> +                    );
> +    if (EFI_ERROR(Status)){
> +      continue;
> +    }
> +
> +    Size = (UINTN)FileInfo->FileSize;
> +    TempFilePtrBuf[FileCount].ImageAddress = AllocateZeroPool(Size);
> +    if (TempFilePtrBuf[FileCount].ImageAddress == NULL) {
> +      DEBUG((DEBUG_ERROR, "Fail to allocate memory for capsule. Stop
> processing the rest.\n"));
> +      break;
> +    }
> +
> +    Status = FileHandle->Read(
> +                           FileHandle,
> +                           &Size,
> +                           TempFilePtrBuf[FileCount].ImageAddress
> +                           );
> +
> +    FileHandle->Close(FileHandle);
> +
> +    //
> +    // Skip read error file
> +    //
> +    if (EFI_ERROR(Status) || Size != (UINTN)FileInfo->FileSize) {
> +      //
> +      // Remove this error file info accordingly
> +      // & move Link to BackLink
> +      //
> +      Link = RemoveEntryList(Link);
> +      Link = Link->BackLink;
> +
> +      FreePool(FileInfoEntry->FileInfo);
> +      FreePool(FileInfoEntry->FileNameFirstPart);
> +      FreePool(FileInfoEntry->FileNameSecondPart);
> +      FreePool(FileInfoEntry);
> +
> +      FreePool(TempFilePtrBuf[FileCount].ImageAddress);
> +      TempFilePtrBuf[FileCount].ImageAddress = NULL;
> +      TempFilePtrBuf[FileCount].FileInfo     = NULL;
> +
> +      continue;
> +    }
> +    TempFilePtrBuf[FileCount].FileInfo = FileInfo;
> +    FileCount++;
> +  }
> +
> +  DEBUG_CODE (
> +    for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link-
> >ForwardLink) {
> +      FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
> +      FileInfo      = FileInfoEntry->FileInfo;
> +      DEBUG((DEBUG_INFO, "Successfully read capsule file %s from disk.\n",
> FileInfo->FileName));
> +    }
> +  );
> +
> +EXIT:
> +
> +  *FilePtr = TempFilePtrBuf;
> +  *FileNum = FileCount;
> +
> +  //
> +  // FileInfo will be freed by Calller
> +  //
> +  while(!IsListEmpty(&FileInfoList)) {
> +    Link = FileInfoList.ForwardLink;
> +    RemoveEntryList(Link);
> +
> +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
> +
> +    FreePool(FileInfoEntry->FileNameFirstPart);
> +    FreePool(FileInfoEntry->FileNameSecondPart);
> +    FreePool(FileInfoEntry);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This routine is called to remove all qualified image from file from an given
> directory.
> +
> +  @param[in] Dir                  Directory file handler
> +  @param[in] FileAttr             Attribute of files to be deleted
> +
> +  @retval EFI_SUCCESS  Succeed to remove all files from an given directory.
> +
> +**/
> +EFI_STATUS
> +RemoveFileFromDir(
> +  IN EFI_FILE_HANDLE   Dir,
> +  IN UINT64            FileAttr
> +  )
> +{
> +  EFI_STATUS        Status;
> +  LIST_ENTRY        *Link;
> +  LIST_ENTRY        FileInfoList;
> +  EFI_FILE_HANDLE   FileHandle;
> +  FILE_INFO_ENTRY   *FileInfoEntry;
> +  EFI_FILE_INFO     *FileInfo;
> +  UINTN             FileCount;
> +
> +  FileHandle = NULL;
> +
> +  //
> +  // Get file list in Dir in alphabetical order
> +  //
> +  Status = GetFileInfoListInAlphabetFromDir(
> +             Dir,
> +             FileAttr,
> +             &FileInfoList,
> +             &FileCount
> +             );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n"));
> +    goto EXIT;
> +  }
> +
> +  if (FileCount == 0) {
> +    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));
> +    Status = EFI_NOT_FOUND;
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Delete all files with given attribute in Dir
> +  //
> +  for (Link = FileInfoList.ForwardLink; Link != &(FileInfoList); Link = Link-
> >ForwardLink) {
> +    //
> +    // Get FileInfo from the link list
> +    //
> +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
> +    FileInfo      = FileInfoEntry->FileInfo;
> +
> +    Status = Dir->Open(
> +                    Dir,
> +                    &FileHandle,
> +                    FileInfo->FileName,
> +                    EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
> +                    0
> +                    );
> +    if (EFI_ERROR(Status)){
> +      continue;
> +    }
> +
> +    Status = FileHandle->Delete(FileHandle);
> +  }
> +
> +EXIT:
> +
> +  while(!IsListEmpty(&FileInfoList)) {
> +    Link = FileInfoList.ForwardLink;
> +    RemoveEntryList(Link);
> +
> +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE);
> +
> +    FreePool(FileInfoEntry->FileInfo);
> +    FreePool(FileInfoEntry);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This routine is called to get all caspules from file. The capsule file image is
> +  copied to BS memory. Caller is responsible to free them.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +  @param[out]   CapsulePtr           Copied Capsule file Image Info buffer
> +  @param[out]   CapsuleNum           CapsuleNumber
> +  @param[out]   FsHandle             File system handle
> +  @param[out]   LoadOptionNumber     OptionNumber of boot option
> +
> +  @retval EFI_SUCCESS  Succeed to get all capsules.
> +
> +**/
> +EFI_STATUS
> +EFIAPI


Please help to remove the keyword 'EFIAPI' for internal function.


> +GetAllCapsuleOnDisk(
> +  IN  UINTN                            MaxRetry,
> +  OUT IMAGE_INFO                       **CapsulePtr,
> +  OUT UINTN                            *CapsuleNum,
> +  OUT EFI_HANDLE                       *FsHandle,
> +  OUT UINT16                            *LoadOptionNumber
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  FileDir;
> +  UINT16                           *TempOptionNumber;
> +
> +  Fs               = NULL;
> +  RootDir          = NULL;
> +  FileDir          = NULL;
> +  TempOptionNumber = NULL;
> +  *CapsuleNum      = 0;
> +
> +  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry,
> &TempOptionNumber, FsHandle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Status = gBS->HandleProtocol(*FsHandle,
> &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &FileDir,
> +                      EFI_CAPSULE_FILE_DIRECTORY,
> +                      EFI_FILE_MODE_READ,
> +                      0
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_ERROR, "CodLibGetAllCapsuleOnDisk fail to open
> RootDir!\n"));
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Only Load files with EFI_FILE_SYSTEM or EFI_FILE_ARCHIVE attribute
> +  // ignore EFI_FILE_READ_ONLY, EFI_FILE_HIDDEN, EFI_FILE_RESERVED,
> EFI_FILE_DIRECTORY
> +  //
> +  Status = GetFileImageInAlphabetFromDir(
> +             FileDir,
> +             EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE,
> +             CapsulePtr,
> +             CapsuleNum
> +             );
> +  DEBUG((DEBUG_INFO, "GetFileImageInAlphabetFromDir status %x\n",
> Status));
> +
> +  //
> +  // Always remove file to avoid deadloop in capsule process
> +  //
> +  Status = RemoveFileFromDir(FileDir, EFI_FILE_SYSTEM |
> EFI_FILE_ARCHIVE);
> +  DEBUG((DEBUG_INFO, "RemoveFileFromDir status %x\n", Status));
> +
> +  if (LoadOptionNumber != NULL) {
> +    *LoadOptionNumber = *TempOptionNumber;
> +  }
> +
> +EXIT:
> +
> +  if (FileDir != NULL) {
> +    FileDir->Close (FileDir);
> +  }
> +
> +  if (RootDir != NULL) {
> +    RootDir->Close (RootDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Build Gather list for a list of capsule images.
> +
> +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> +  @param[in]  CapsuleSize      An array of UINTN to capsule images size
> +  @param[in]  CapsuleNum       The count of capsule images
> +  @param[out] BlockDescriptors The block descriptors for the capsule
> images
> +
> +  @retval EFI_SUCCESS The block descriptors for the capsule images are
> constructed.
> +
> +**/
> +EFI_STATUS
> +BuildGatherList (
> +  IN VOID                          **CapsuleBuffer,
> +  IN UINTN                         *CapsuleSize,
> +  IN UINTN                         CapsuleNum,
> +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> +  UINTN                         Index;
> +
> +  BlockDescriptors1      = NULL;
> +  BlockDescriptorPre     = NULL;
> +  BlockDescriptorsHeader = NULL;
> +
> +  for (Index = 0; Index < CapsuleNum; Index++) {
> +    //
> +    // Allocate memory for the descriptors.
> +    //
> +    BlockDescriptors1  = AllocateZeroPool (2 * sizeof
> (EFI_CAPSULE_BLOCK_DESCRIPTOR));
> +    if (BlockDescriptors1 == NULL) {
> +      DEBUG ((DEBUG_ERROR, "BuildGatherList: failed to allocate memory for
> descriptors\n"));
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ERREXIT;
> +    } else {
> +      DEBUG ((DEBUG_INFO, "BuildGatherList: creating capsule descriptors at
> 0x%X\n", (UINTN) BlockDescriptors1));
> +    }
> +
> +    //
> +    // Record descirptor header
> +    //
> +    if (Index == 0) {
> +      BlockDescriptorsHeader = BlockDescriptors1;
> +    }
> +
> +    if (BlockDescriptorPre != NULL) {
> +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN)
> BlockDescriptors1;
> +      BlockDescriptorPre->Length = 0;
> +    }
> +
> +    BlockDescriptors1->Union.DataBlock = (UINTN) CapsuleBuffer[Index];
> +    BlockDescriptors1->Length = CapsuleSize[Index];
> +
> +    BlockDescriptorPre = BlockDescriptors1 + 1;
> +    BlockDescriptors1 = NULL;
> +  }
> +
> +  //
> +  // Null-terminate.
> +  //
> +  if (BlockDescriptorPre != NULL) {
> +    BlockDescriptorPre->Union.ContinuationPointer = (UINTN)NULL;
> +    BlockDescriptorPre->Length = 0;
> +    *BlockDescriptors = BlockDescriptorsHeader;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ERREXIT:
> +  if (BlockDescriptors1 != NULL) {
> +    FreePool (BlockDescriptors1);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This routine is called to check if CapsuleOnDisk flag in OsIndications
> Variable
> +  is enabled.
> +
> +  @retval TRUE     Flag is enabled
> +  @retval FALSE    Flag is not enabled
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +CoDCheckCapsuleOnDiskFlag(
> +  VOID
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINT64                OsIndication;
> +  UINTN                 DataSize;
> +
> +  //
> +  // Check File Capsule Delivery Supported Flag in OsIndication variable
> +  //
> +  OsIndication = 0;
> +  DataSize     = sizeof(UINT64);
> +  Status = gRT->GetVariable (
> +                  EFI_OS_INDICATIONS_VARIABLE_NAME,
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  &OsIndication
> +                  );
> +  if (!EFI_ERROR(Status) &&
> +      (OsIndication &
> EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0) {
> +    return TRUE;
> +  }
> +
> +  return FALSE;
> +}
> +
> +
> +/**
> +  This routine is called to clear CapsuleOnDisk flags including OsIndications
> and BootNext variable.
> +
> +  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDClearCapsuleOnDiskFlag(
> +  VOID
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINT64                OsIndication;
> +  UINTN                 DataSize;
> +
> +  //
> +  // Reset File Capsule Delivery Supported Flag in OsIndication variable
> +  //
> +  OsIndication = 0;
> +  DataSize = sizeof(UINT64);
> +  Status = gRT->GetVariable (
> +                  EFI_OS_INDICATIONS_VARIABLE_NAME,
> +                  &gEfiGlobalVariableGuid,
> +                  NULL,
> +                  &DataSize,
> +                  &OsIndication
> +                  );
> +  if (EFI_ERROR(Status) ||
> +      (OsIndication &
> EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) == 0) {
> +    return Status;
> +  }
> +
> +  OsIndication &=
> ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
> +  Status = gRT->SetVariable (
> +                  EFI_OS_INDICATIONS_VARIABLE_NAME,
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS |
> EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
> +                  sizeof(UINT64),
> +                  &OsIndication
> +                  );
> +  ASSERT(!EFI_ERROR(Status));
> +
> +  //
> +  // Delete BootNext variable. Capsule Process may reset system, so can't
> rely on Bds to clear this variable
> +  //
> +  Status = gRT->SetVariable (
> +                  EFI_BOOT_NEXT_VARIABLE_NAME,
> +                  &gEfiGlobalVariableGuid,
> +                  0,
> +                  0,
> +                  NULL
> +                  );
> +  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This routine is called to clear Capsule On Disk Relocation flag
> +  The flag is the total size of capsules being relocated. It is saved
> +  in CapsuleOnDisk Relocation Info varible in form of UINT64
> +
> +  @param[out] CapsuleRelocInfo  The value of "CapsuleRelocInfo" variable
> +
> +  @retval EFI_SUCCESS   Capsule Relocation flag is cleared
> +
> +**/
> +EFI_STATUS
> +CoDCheckCapsuleRelocationInfo(
> +  OUT BOOLEAN *CapsuleRelocInfo
> +  )


I do not see the above function being used internally/externally.
Please help to check and remove it.


> +{
> +  EFI_STATUS  Status;
> +  UINTN       DataSize;
> +
> +  DataSize = sizeof(BOOLEAN);
> +
> +  Status= gRT->GetVariable (
> +                 COD_RELOCATION_INFO_VAR_NAME,
> +                 &gEfiCapsuleVendorGuid,
> +                 NULL,
> +                 &DataSize,
> +                 CapsuleRelocInfo
> +                 );
> +
> +  if (DataSize != sizeof(BOOLEAN)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  This routine is called to clear CapsuleOnDisk Relocation Info variable.
> +  Total Capsule On Disk length is recorded in this variable
> +
> +  @retval EFI_SUCCESS   Capsule On Disk flags are cleared
> +
> +**/
> +EFI_STATUS
> +CoDClearCapsuleRelocationInfo(
> +  VOID
> +  )
> +{
> +  return gRT->SetVariable (
> +                COD_RELOCATION_INFO_VAR_NAME,
> +                &gEfiCapsuleVendorGuid,
> +                0,
> +                0,
> +                NULL
> +                );
> +}
> +
> +/**
> +  Relocate Capsule on Disk from EFI system partition to a platform-specific
> NV storage device
> +  with BlockIo protocol. Relocation device path, identified by
> PcdCodRelocationDevPath, must
> +  be a full device path.
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  Side Effects:
> +    Content corruption. Block IO write directly touches low level write. Orignal
> partitions, file systems
> +    of the relocation device will be corrupted.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +
> +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated to
> the platform-specific device.
> +
> +**/
> +EFI_STATUS
> +EFIAPI


Please help to remove 'EFIAPI' for this internal function.


> +RelocateCapsuleToDisk(
> +  UINTN     MaxRetry
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UINTN                           CapsuleOnDiskNum;
> +  UINTN                           Index;
> +  UINTN                           DataSize;
> +  UINT64                          TotalImageSize;
> +  UINT64                          TotalImageNameSize;
> +  IMAGE_INFO                      *CapsuleOnDiskBuf;
> +  EFI_HANDLE                      Handle;
> +  EFI_HANDLE                      TempHandle;
> +  EFI_HANDLE                      *HandleBuffer;
> +  UINTN                           NumberOfHandles;
> +  EFI_BLOCK_IO_PROTOCOL           *BlockIo;
> +  UINT8                           *CapsuleDataBuf;
> +  UINT8                           *CapsulePtr;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
> +  EFI_FILE_HANDLE                 RootDir;
> +  EFI_FILE_HANDLE                 TempCodFile;
> +  UINT64                          TempCodFileSize;
> +  EFI_DEVICE_PATH                 *TempDevicePath;
> +  BOOLEAN                         RelocationInfo;
> +  UINT16                          LoadOptionNumber;
> +  EFI_CAPSULE_HEADER              FileNameCapsuleHeader;
> +
> +  RootDir          = NULL;
> +  TempCodFile      = NULL;
> +  HandleBuffer     = NULL;
> +  CapsuleDataBuf   = NULL;
> +  CapsuleOnDiskBuf = NULL;
> +  NumberOfHandles  = 0;
> +
> +  DEBUG ((DEBUG_INFO, "CapsuleOnDisk RelocateCapsule Enter\n"));
> +
> +  //
> +  // 1. Load all Capsule On Disks in to memory
> +  //
> +  Status = GetAllCapsuleOnDisk(MaxRetry, &CapsuleOnDiskBuf,
> &CapsuleOnDiskNum, &Handle, &LoadOptionNumber);
> +  if (EFI_ERROR(Status) || CapsuleOnDiskNum == 0) {
> +    DEBUG ((DEBUG_INFO, "RelocateCapsule: GetAllCapsuleOnDisk Status -
> 0x%x\n", Status));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // 2. Connect platform special dev path or Use EFI System Partition as
> relocation device
> +  //
> +  if (PcdGetSize(PcdCodRelocationDevPath) >
> sizeof(EFI_DEVICE_PATH_PROTOCOL)) {


Do we need a validity check for the device path specified by
'PcdCodRelocationDevPath'? Since it is from external input (by configuring
the PCD).

Also, should we consider an error when the above 'if' statement is not met?

For the implementation in the patch, when:
if (PcdGetSize(PcdCodRelocationDevPath) > sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
evaluates to false, 'Handle' will still carry the value for the device where
the capsules are placed. And then, the function may continue to write content
on this media device. I think this should not happen, right?


> +    Status = EfiBootManagerConnectDevicePath ((EFI_DEVICE_PATH
> *)PcdGetPtr(PcdCodRelocationDevPath), &TempHandle);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "RelocateCapsule:
> EfiBootManagerConnectDevicePath Status - 0x%x\n", Status));
> +      goto EXIT;
> +    }
> +
> +    //
> +    // Connect all the child handle. Partition & FAT drivers are allowed in this
> case
> +    //
> +    gBS->ConnectController (TempHandle, NULL, NULL, TRUE);
> +    Status = gBS->LocateHandleBuffer(
> +                    ByProtocol,
> +                    &gEfiSimpleFileSystemProtocolGuid,
> +                    NULL,
> +                    &NumberOfHandles,
> +                    &HandleBuffer
> +                    );
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((DEBUG_ERROR, "RelocateCapsule: LocateHandleBuffer Status -
> 0x%x\n", Status));
> +      goto EXIT;
> +    }
> +
> +    //
> +    // Find first Simple File System Handle which can match
> PcdCodRelocationDevPath
> +    //
> +    for (Index = 0; Index < NumberOfHandles; Index++) {
> +      Status = gBS->HandleProtocol(HandleBuffer[Index],
> &gEfiDevicePathProtocolGuid, (VOID **)&TempDevicePath);
> +      if (EFI_ERROR(Status)) {
> +        continue;
> +      }
> +
> +      DataSize = GetDevicePathSize((EFI_DEVICE_PATH
> *)PcdGetPtr(PcdCodRelocationDevPath)) - sizeof(EFI_DEVICE_PATH);
> +      if (0 == CompareMem((EFI_DEVICE_PATH
> *)PcdGetPtr(PcdCodRelocationDevPath), TempDevicePath, DataSize)) {
> +        Handle = HandleBuffer[Index];
> +        break;
> +      }
> +    }
> +
> +    FreePool(HandleBuffer);
> +
> +    if (Index == NumberOfHandles) {
> +      DEBUG ((DEBUG_ERROR, "RelocateCapsule: No simple file system
> protocol found.\n"));
> +      Status = EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  Status = gBS->HandleProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID
> **)&BlockIo);
> +  if (EFI_ERROR(Status) || BlockIo->Media->ReadOnly) {
> +    DEBUG((DEBUG_ERROR, "Fail to find Capsule on Disk relocation BlockIo
> device or device is ReadOnly!\n"));
> +    return Status;
> +  }
> +
> +  Status = gBS->HandleProtocol(Handle, &gEfiSimpleFileSystemProtocolGuid,
> (VOID **)&Fs);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Check if device used to relocate Capsule On Disk is big enough
> +  //
> +  TotalImageSize     = 0;
> +  TotalImageNameSize = 0;
> +  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
> +    //
> +    // Overflow check
> +    //
> +    if (MAX_ADDRESS - (UINTN)TotalImageSize <=
> CapsuleOnDiskBuf[Index].FileInfo->FileSize) {
> +      return EFI_INVALID_PARAMETER;


Will memory leak happen in this error handling?


> +    }
> +
> +    if (MAX_ADDRESS - (UINTN)TotalImageNameSize <=
> StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName)) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    TotalImageSize     += CapsuleOnDiskBuf[Index].FileInfo->FileSize;
> +    TotalImageNameSize += StrSize(CapsuleOnDiskBuf[Index].FileInfo-
> >FileName);
> +    DEBUG((DEBUG_INFO, "RelocateCapsule: %x
> Size %x\n",CapsuleOnDiskBuf[Index].FileInfo->FileName,
> CapsuleOnDiskBuf[Index].FileInfo->FileSize));
> +  }
> +
> +  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageSize %x\n",
> TotalImageSize));
> +  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageNameSize %x\n",
> TotalImageNameSize));
> +
> +  if (MAX_ADDRESS - (UINTN)TotalImageNameSize <= sizeof(UINT64) * 2 ||
> +      MAX_ADDRESS - (UINTN)TotalImageSize <=
> (UINTN)TotalImageNameSize + sizeof(UINT64) * 2) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TempCodFileSize = sizeof(UINT64) + TotalImageSize +
> sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;
> +
> +  //
> +  // Check if CapsuleTotalSize. There could be reminder, so use LastBlock
> number directly
> +  //
> +  if (DivU64x32(TempCodFileSize, BlockIo->Media->BlockSize) > BlockIo-
> >Media->LastBlock) {
> +    DEBUG((DEBUG_ERROR, "RelocateCapsule: Relocation device isn't big
> enough to hold all Capsule on Disk!\n"));
> +    DEBUG((DEBUG_ERROR, "TotalImageSize = %x\n", TotalImageSize));
> +    DEBUG((DEBUG_ERROR, "TotalImageNameSize = %x\n",
> TotalImageNameSize));
> +    DEBUG((DEBUG_ERROR, "RelocationDev BlockSize = %x LastBlock = %x\n",
> BlockIo->Media->BlockSize, BlockIo->Media->LastBlock));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +
> +  CapsuleDataBuf = AllocatePool((UINTN) TempCodFileSize);
> +  if (CapsuleDataBuf == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +
> +  //
> +  // First UINT64 reserved for total image size, including capsule name
> capsule.
> +  //
> +  *(UINT64 *) CapsuleDataBuf = TotalImageSize +
> sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;
> +
> +  //
> +  // Line up all the Capsule on Disk and write to relocation disk at one time. It
> could save some time in disk write
> +  //
> +  for (Index = 0, CapsulePtr = CapsuleDataBuf + sizeof(UINT64); Index <
> CapsuleOnDiskNum; Index++) {
> +    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].ImageAddress, (UINTN)
> CapsuleOnDiskBuf[Index].FileInfo->FileSize);
> +    CapsulePtr += CapsuleOnDiskBuf[Index].FileInfo->FileSize;
> +  }
> +
> +  //
> +  // Line the capsule header for capsule name capsule.
> +  //
> +  CopyGuid(&FileNameCapsuleHeader.CapsuleGuid,
> &gEdkiiCapsuleOnDiskNameGuid);
> +  FileNameCapsuleHeader.CapsuleImageSize = (UINT32)
> TotalImageNameSize + sizeof(EFI_CAPSULE_HEADER);
> +  FileNameCapsuleHeader.Flags            =
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  FileNameCapsuleHeader.HeaderSize       = sizeof(EFI_CAPSULE_HEADER);
> +  CopyMem(CapsulePtr, &FileNameCapsuleHeader,
> FileNameCapsuleHeader.HeaderSize);
> +  CapsulePtr += FileNameCapsuleHeader.HeaderSize;
> +
> +  //
> +  // Line up all the Capsule file names.
> +  //
> +  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
> +    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].FileInfo->FileName,
> StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName));
> +    CapsulePtr += StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName);
> +  }
> +
> +  //
> +  // 5. Flash all Capsules on Disk to TempCoD.tmp under RootDir
> +  //
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_ERROR, "RelocateCapsule: OpenVolume error. %x\n",
> Status));
> +    goto EXIT;
> +  }
> +
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &TempCodFile,
> +                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
> +                      0
> +                      );
> +  if (!EFI_ERROR(Status)) {
> +    //
> +    // Error handling code to prevent malicious code to hold this file to block
> capsule on disk
> +    //
> +    TempCodFile->Delete(TempCodFile);
> +  }
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &TempCodFile,
> +                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> EFI_FILE_MODE_CREATE,
> +                      0
> +                      );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_ERROR, "RelocateCapsule: Open TemCoD.tmp
> error. %x\n", Status));
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Always write at the begining of TempCap file
> +  //
> +  DataSize = (UINTN) TempCodFileSize;
> +  Status = TempCodFile->Write(
> +                          TempCodFile,
> +                          &DataSize,
> +                          CapsuleDataBuf
> +                          );
> +  if (EFI_ERROR(Status)) {
> +    DEBUG((DEBUG_ERROR, "RelocateCapsule: Write TemCoD.tmp
> error. %x\n", Status));
> +    goto EXIT;
> +  }
> +
> +  if (DataSize != TempCodFileSize) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto EXIT;
> +  }
> +
> +  //
> +  // Save Capsule On Disk relocation info to "CodRelocationInfo" Var
> +  // It is used in next reboot by TCB
> +  //
> +  RelocationInfo = TRUE;
> +  Status = gRT->SetVariable(
> +                   COD_RELOCATION_INFO_VAR_NAME,
> +                   &gEfiCapsuleVendorGuid,
> +                   EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                   sizeof (BOOLEAN),
> +                   &RelocationInfo
> +                   );
> +  //
> +  // Save the LoadOptionNumber of the boot option, where the capsule is
> relocated,
> +  // into "CodRelocationLoadOption" var. It is used in next reboot after
> capsule is
> +  // updated out of TCB to remove the TempCoDFile.
> +  //
> +  Status = gRT->SetVariable(
> +                   COD_RELOCATION_LOAD_OPTION_VAR_NAME,
> +                   &gEfiCapsuleVendorGuid,
> +                   EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                   sizeof (UINT16),
> +                   &LoadOptionNumber
> +                   );
> +
> +EXIT:
> +
> +  if (CapsuleDataBuf != NULL) {
> +    FreePool(CapsuleDataBuf);
> +  }
> +
> +  if (CapsuleOnDiskBuf != NULL) {
> +    //
> +    // Free resources allocated by CodLibGetAllCapsuleOnDisk
> +    //
> +    for (Index = 0; Index < CapsuleOnDiskNum; Index++ ) {
> +      FreePool(CapsuleOnDiskBuf[Index].ImageAddress);
> +      FreePool(CapsuleOnDiskBuf[Index].FileInfo);
> +    }
> +    FreePool(CapsuleOnDiskBuf);
> +  }
> +
> +  if (TempCodFile != NULL) {
> +    if (EFI_ERROR(Status)) {
> +      TempCodFile->Delete (TempCodFile);
> +    } else {
> +      TempCodFile->Close (TempCodFile);
> +    }
> +  }
> +
> +  if (RootDir != NULL) {
> +    RootDir->Close (RootDir);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  For the platforms that support Capsule In Ram, reuse the Capsule In Ram
> to deliver capsule.
> +  Relocate Capsule On Disk to memory and call UpdateCapsule().
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +
> +  @retval EFI_SUCCESS   Deliver capsule through Capsule In Ram successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI

Please help to remove 'EFIAPI' for this internal function.


> +RelocateCapsuleToRam (
> +  UINTN    MaxRetry
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  UINTN                         CapsuleOnDiskNum;
> +  IMAGE_INFO                    *CapsuleOnDiskBuf;
> +  EFI_HANDLE                    Handle;
> +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> +  VOID                          **CapsuleBuffer;
> +  UINTN                         *CapsuleSize;
> +  EFI_CAPSULE_HEADER            *FileNameCapsule;
> +  UINTN                         Index;
> +  UINT8                         *StringBuf;
> +  UINTN                         StringSize;
> +  UINTN                         TotalStringSize;
> +
> +  CapsuleOnDiskBuf = NULL;
> +  BlockDescriptors = NULL;
> +  CapsuleBuffer    = NULL;
> +  CapsuleSize      = NULL;
> +  FileNameCapsule  = NULL;
> +  TotalStringSize  = 0;
> +
> +  //
> +  // 1. Load all Capsule On Disks into memory
> +  //
> +  Status = GetAllCapsuleOnDisk (MaxRetry, &CapsuleOnDiskBuf,
> &CapsuleOnDiskNum, &Handle, NULL);
> +  if (EFI_ERROR (Status) || CapsuleOnDiskNum == 0) {
> +    DEBUG ((DEBUG_ERROR, "GetAllCapsuleOnDisk Status - 0x%x\n",
> Status));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // 2. Add a capsule for Capsule file name strings
> +  //
> +  CapsuleBuffer = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof (VOID
> *));
> +  if (CapsuleBuffer == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  CapsuleSize = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof
> (UINTN));
> +  if (CapsuleSize == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));
> +    return EFI_OUT_OF_RESOURCES;


Potential memory leaks in some error handling paths, please help to
address them.


> +  }
> +
> +  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
> +    CapsuleBuffer[Index] = (VOID *)(UINTN)
> CapsuleOnDiskBuf[Index].ImageAddress;
> +    CapsuleSize[Index] = (UINTN) CapsuleOnDiskBuf[Index].FileInfo->FileSize;
> +    TotalStringSize += StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName);
> +  }
> +
> +  FileNameCapsule = AllocateZeroPool (sizeof (EFI_CAPSULE_HEADER) +
> TotalStringSize);
> +  if (FileNameCapsule == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for name capsule.\n"));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  FileNameCapsule->CapsuleImageSize = (UINT32) (sizeof
> (EFI_CAPSULE_HEADER) + TotalStringSize);
> +  FileNameCapsule->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +  FileNameCapsule->HeaderSize = sizeof (EFI_CAPSULE_HEADER);
> +  CopyGuid (&(FileNameCapsule->CapsuleGuid),
> &gEdkiiCapsuleOnDiskNameGuid);
> +
> +  StringBuf = (UINT8 *)FileNameCapsule + FileNameCapsule->HeaderSize;
> +  for (Index = 0; Index < CapsuleOnDiskNum; Index ++) {
> +    StringSize = StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName);
> +    CopyMem (StringBuf, CapsuleOnDiskBuf[Index].FileInfo->FileName,
> StringSize);
> +    StringBuf += StringSize;
> +  }
> +
> +  CapsuleBuffer[CapsuleOnDiskNum] = FileNameCapsule;
> +  CapsuleSize[CapsuleOnDiskNum] = TotalStringSize + sizeof
> (EFI_CAPSULE_HEADER);
> +
> +  //
> +  // 3. Build Gather list for the capsules
> +  //
> +  Status = BuildGatherList (CapsuleBuffer, CapsuleSize, CapsuleOnDiskNum
> + 1, &BlockDescriptors);
> +  if (EFI_ERROR (Status) || BlockDescriptors == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // 4. Call UpdateCapsule() service
> +  //
> +  Status = gRT->UpdateCapsule((EFI_CAPSULE_HEADER **) CapsuleBuffer,
> CapsuleOnDiskNum + 1, (UINTN) BlockDescriptors);
> +
> +  return Status;
> +}
> +
> +/**
> +  Relocate Capsule on Disk from EFI system partition.
> +
> +  Two solution to deliver Capsule On Disk:
> +  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On
> Disk to memory and call UpdateCapsule().
> +  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On
> Disk to a platform-specific NV storage
> +  device with BlockIo protocol.
> +
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  Side Effects:
> +    Capsule Delivery Supported Flag in OsIndication variable and BootNext
> variable will be cleared.
> +    Solution B: Content corruption. Block IO write directly touches low level
> write. Orignal partitions, file
> +  systems of the relocation device will be corrupted.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +
> +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDRelocateCapsule(
> +  UINTN     MaxRetry
> +  )
> +{
> +  if (!PcdGetBool (PcdCapsuleOnDiskSupport)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Clear CapsuleOnDisk Flag firstly.
> +  //
> +  CoDClearCapsuleOnDiskFlag ();
> +
> +  //
> +  // If Capsule In Ram is supported, delivery capsules through memory
> +  //
> +  if (PcdGetBool (PcdCapsuleInRamSupport)) {
> +    DEBUG ((DEBUG_INFO, "Capsule In Ram is supported, call gRT-
> >UpdateCapsule().\n"));
> +    return RelocateCapsuleToRam (MaxRetry);
> +  } else {
> +    DEBUG ((DEBUG_INFO, "Reallcoate all Capsule on Disks to %s in
> RootDir.\n", (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName)));
> +    return RelocateCapsuleToDisk (MaxRetry);
> +  }
> +}
> +
> +/**
> +  Remove the temp file from the root of EFI System Partition.
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +
> +  @retval EFI_SUCCESS   Remove the temp file successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDRemoveTempFile (
> +  UINTN    MaxRetry
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINTN                            DataSize;
> +  UINT16                           *LoadOptionNumber;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> +  EFI_HANDLE                       FsHandle;
> +  EFI_FILE_HANDLE                  RootDir;
> +  EFI_FILE_HANDLE                  TempCodFile;
> +
> +  RootDir     = NULL;
> +  TempCodFile = NULL;
> +
> +  LoadOptionNumber = AllocatePool (sizeof(UINT16));
> +  DataSize = sizeof(UINT16);
> +
> +  //
> +  // Check if capsule files are relocated
> +  //
> +  Status = gRT->GetVariable (
> +                  COD_RELOCATION_LOAD_OPTION_VAR_NAME,
> +                  &gEfiCapsuleVendorGuid,
> +                  NULL,
> +                  &DataSize,
> +                  (VOID *)LoadOptionNumber
> +                  );
> +  if (EFI_ERROR(Status) || DataSize != sizeof(UINT16)) {
> +    return Status;


Please handle possible memory leak in error handlings for this function.


> +  }
> +
> +  //
> +  // Get the EFI file system from the boot option where the capsules are
> relocated
> +  //
> +  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry,
> &LoadOptionNumber, &FsHandle);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Status = gBS->HandleProtocol(FsHandle,
> &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Status = Fs->OpenVolume(Fs, &RootDir);
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Delete the TempCoDFile
> +  //
> +  Status = RootDir->Open(
> +                      RootDir,
> +                      &TempCodFile,
> +                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
> +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
> +                      0
> +                      );
> +  if (!EFI_ERROR(Status)) {
> +    TempCodFile->Delete(TempCodFile);
> +  }
> +
> +  if (RootDir != NULL) {
> +    RootDir->Close(RootDir);
> +  }
> +
> +  //
> +  // Clear "CoDRelocationLoadOption" variable
> +  //
> +  Status = gRT->SetVariable (
> +             COD_RELOCATION_LOAD_OPTION_VAR_NAME,
> +             &gEfiCapsuleVendorGuid,
> +             0,
> +             0,
> +             NULL
> +             );
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> new file mode 100644
> index 0000000000..064dc791b8
> --- /dev/null
> +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> @@ -0,0 +1,63 @@
> +/** @file
> +  Defines several datastructures used by Capsule On Disk feature.
> +  They are mainly used for FAT files.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _CAPSULES_ON_DISK_H_
> +#define _CAPSULES_ON_DISK_H_
> +
> +#include <Uefi.h>
> +#include <Pi/PiMultiPhase.h>
> +
> +#include <Library/UefiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiRuntimeLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/FileHandleLib.h>
> +#include <Library/CapsuleLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootManagerLib.h>
> +
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/DiskIo.h>
> +#include <Protocol/BlockIo.h>
> +
> +#include <Guid/CapsuleVendor.h>
> +#include <Guid/GlobalVariable.h>
> +
> +//
> +// This data structure is the part of FILE_INFO_ENTRY
> +//
> +#define FILE_INFO_SIGNATURE SIGNATURE_32 ('F', 'L', 'I', 'F')
> +
> +//
> +// LoadOptionNumber of the boot option where the capsules is relocated.
> +//
> +#define COD_RELOCATION_LOAD_OPTION_VAR_NAME
> L"CodRelocationLoadOption"
> +
> +typedef struct {
> +  UINTN           Signature;
> +  LIST_ENTRY      Link;                  ///  Linked list members.
> +  EFI_FILE_INFO   *FileInfo;             ///  Pointer to the FileInfo struct for this
> file or NULL.
> +  CHAR16          *FileNameFirstPart;    ///  Text to the left of right-most period
> in the file name. String is capitialized
> +  CHAR16          *FileNameSecondPart;   ///  Text to the right of right-most
> period in the file name.String is capitialized. Maybe NULL
> +} FILE_INFO_ENTRY;
> +
> +//
> +// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for
> bytes)
> +//
> +#define MAX_FILE_NAME_SIZE   522
> +#define MAX_FILE_NAME_LEN    (MAX_FILE_NAME_SIZE / sizeof(CHAR16))
> +
> +#define MAX_FILE_INFO_LEN    (OFFSET_OF(EFI_FILE_INFO, FileName) +
> MAX_FILE_NAME_LEN)
> +
> +#endif // _CAPSULES_ON_DISK_H_
> diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> index f38ab69e38..4254cc8270 100644
> --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> @@ -8,11 +8,11 @@
> 
>    SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),
>    ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input
> and
>    performs basic validation.
> 
> -  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #include <PiDxe.h>
> @@ -88,11 +88,12 @@ EFI_STATUS
>  RecordFmpCapsuleStatusVariable (
>    IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
>    IN EFI_STATUS                                    CapsuleStatus,
>    IN UINTN                                         PayloadIndex,
>    IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> *ImageHeader,
> -  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath OPTIONAL
> +  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath, OPTIONAL
> +  IN CHAR16                                        *CapFileName    OPTIONAL


Please help to update the function description comments for adding a new
parameter.

Also, the implementations of this function in file DxeCapsuleReportLib.c &
DxeCapsuleReportLibNull.c are with different interface definitions. Could
you help to double confirm on this?


>    );
> 
>  /**
>    Function indicate the current completion progress of the firmware
>    update. Platform may override with own specific progress function.
> @@ -107,10 +108,26 @@ EFI_STATUS
>  EFIAPI
>  UpdateImageProgress (
>    IN UINTN  Completion
>    );
> 
> +/**
> +  Return if this capsule is a capsule name capsule, based upon
> CapsuleHeader.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  It is a capsule name capsule.
> +  @retval FALSE It is not a capsule name capsule.
> +**/
> +BOOLEAN
> +IsCapsuleNameCapsule (
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  )
> +{
> +  return CompareGuid (&CapsuleHeader->CapsuleGuid,
> &gEdkiiCapsuleOnDiskNameGuid);
> +}
> +
>  /**
>    Return if this CapsuleGuid is a FMP capsule GUID or not.
> 
>    @param[in] CapsuleGuid A pointer to EFI_GUID
> 
> @@ -1032,23 +1049,25 @@ StartFmpImage (
>  }
> 
>  /**
>    Record FMP capsule status.
> 
> -  @param[in]  Handle        A FMP handle.
> +  @param[in] Handle         A FMP handle.
>    @param[in] CapsuleHeader  The capsule image header
>    @param[in] CapsuleStatus  The capsule process stauts
>    @param[in] PayloadIndex   FMP payload index
>    @param[in] ImageHeader    FMP image header
> +  @param[in] CapFileName    Capsule file name
>  **/
>  VOID
>  RecordFmpCapsuleStatus (
>    IN EFI_HANDLE                                    Handle,  OPTIONAL
>    IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
>    IN EFI_STATUS                                    CapsuleStatus,
>    IN UINTN                                         PayloadIndex,
> -  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> *ImageHeader
> +  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> *ImageHeader,
> +  IN CHAR16                                        *CapFileName   OPTIONAL
>    )
>  {
>    EFI_STATUS                                    Status;
>    EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath;
>    UINT32                                        FmpImageInfoDescriptorVer;
> @@ -1068,11 +1087,12 @@ RecordFmpCapsuleStatus (
>    RecordFmpCapsuleStatusVariable (
>      CapsuleHeader,
>      CapsuleStatus,
>      PayloadIndex,
>      ImageHeader,
> -    FmpDevicePath
> +    FmpDevicePath,
> +    CapFileName
>      );
> 
>    //
>    // Update corresponding ESRT entry LastAttemp Status
>    //
> @@ -1113,10 +1133,11 @@ RecordFmpCapsuleStatus (
>    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
> 
>    This function need support nested FMP capsule.
> 
>    @param[in]  CapsuleHeader         Points to a capsule header.
> +  @param[in]  CapFileName           Capsule file name.
>    @param[out] ResetRequired         Indicates whether reset is required or not.
> 
>    @retval EFI_SUCESS            Process Capsule Image successfully.
>    @retval EFI_UNSUPPORTED       Capsule image is not supported by the
> firmware.
>    @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
> @@ -1124,10 +1145,11 @@ RecordFmpCapsuleStatus (
>    @retval EFI_NOT_READY         No FMP protocol to handle this FMP capsule.
>  **/
>  EFI_STATUS
>  ProcessFmpCapsuleImage (
>    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN CHAR16              *CapFileName,  OPTIONAL
>    OUT BOOLEAN            *ResetRequired OPTIONAL
>    )
>  {
>    EFI_STATUS                                    Status;
>    EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
> *FmpCapsuleHeader;
> @@ -1143,11 +1165,11 @@ ProcessFmpCapsuleImage (
>    UINTN                                         Index2;
>    BOOLEAN                                       NotReady;
>    BOOLEAN                                       Abort;
> 
>    if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
> -    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
> *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);
> +    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
> *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName,
> ResetRequired);
>    }
> 
>    NotReady = FALSE;
>    Abort = FALSE;
> 
> @@ -1225,11 +1247,12 @@ ProcessFmpCapsuleImage (
>        RecordFmpCapsuleStatus (
>          NULL,
>          CapsuleHeader,
>          EFI_NOT_READY,
>          Index - FmpCapsuleHeader->EmbeddedDriverCount,
> -        ImageHeader
> +        ImageHeader,
> +        CapFileName
>          );
>        continue;
>      }
> 
>      for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
> @@ -1237,11 +1260,12 @@ ProcessFmpCapsuleImage (
>          RecordFmpCapsuleStatus (
>            HandleBuffer[Index2],
>            CapsuleHeader,
>            EFI_ABORTED,
>            Index - FmpCapsuleHeader->EmbeddedDriverCount,
> -          ImageHeader
> +          ImageHeader,
> +          CapFileName
>            );
>          continue;
>        }
> 
>        Status = SetFmpImageData (
> @@ -1260,11 +1284,12 @@ ProcessFmpCapsuleImage (
>        RecordFmpCapsuleStatus (
>          HandleBuffer[Index2],
>          CapsuleHeader,
>          Status,
>          Index - FmpCapsuleHeader->EmbeddedDriverCount,
> -        ImageHeader
> +        ImageHeader,
> +        CapFileName
>          );
>      }
>      if (HandleBuffer != NULL) {
>        FreePool(HandleBuffer);
>      }
> @@ -1412,10 +1437,17 @@ SupportCapsuleImage (
>    //
>    if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader-
> >CapsuleGuid)) {
>      return EFI_SUCCESS;
>    }
> 
> +  //
> +  // Check capsule file name capsule
> +  //
> +  if (IsCapsuleNameCapsule(CapsuleHeader)) {
> +    return EFI_SUCCESS;
> +  }
> +
>    if (IsFmpCapsule(CapsuleHeader)) {
>      //
>      // Fake capsule header is valid case in QueryCapsuleCpapbilities().
>      //
>      if (CapsuleHeader->HeaderSize == CapsuleHeader->CapsuleImageSize) {
> @@ -1434,10 +1466,11 @@ SupportCapsuleImage (
>    The firmware implements to process the capsule image.
> 
>    Caution: This function may receive untrusted input.
> 
>    @param[in]  CapsuleHeader         Points to a capsule header.
> +  @param[in]  CapFileName           Capsule file name.
>    @param[out] ResetRequired         Indicates whether reset is required or not.
> 
>    @retval EFI_SUCESS            Process Capsule Image successfully.
>    @retval EFI_UNSUPPORTED       Capsule image is not supported by the
> firmware.
>    @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
> @@ -1445,10 +1478,11 @@ SupportCapsuleImage (
>  **/
>  EFI_STATUS
>  EFIAPI
>  ProcessThisCapsuleImage (
>    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN CHAR16              *CapFileName,  OPTIONAL
>    OUT BOOLEAN            *ResetRequired OPTIONAL
>    )
>  {
>    EFI_STATUS                   Status;
> 
> @@ -1482,11 +1516,11 @@ ProcessThisCapsuleImage (
> 
>      //
>      // Process EFI FMP Capsule
>      //
>      DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
> -    Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);
> +    Status = ProcessFmpCapsuleImage(CapsuleHeader, CapFileName,
> ResetRequired);
>      DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
> 
>      return Status;
>    }
> 
> @@ -1509,11 +1543,11 @@ EFI_STATUS
>  EFIAPI
>  ProcessCapsuleImage (
>    IN EFI_CAPSULE_HEADER  *CapsuleHeader
>    )
>  {
> -  return ProcessThisCapsuleImage (CapsuleHeader, NULL);
> +  return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL);
>  }
> 
>  /**
>    Callback function executed when the EndOfDxe event group is signaled.
> 
> diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> index 14c3d19bc3..05de4299fb 100644
> --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> @@ -1,11 +1,11 @@
>  ## @file
>  #  Capsule library instance for DXE_DRIVER.
>  #
>  #  Capsule library instance for DXE_DRIVER module types.
>  #
> -#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
>  ##
> 
>  [Defines]
> @@ -27,10 +27,12 @@
> 
>  [Sources]
>    DxeCapsuleLib.c
>    DxeCapsuleProcessLib.c
>    DxeCapsuleReportLib.c
> +  CapsuleOnDisk.c
> +  CapsuleOnDisk.h
> 
>  [Packages]
>    MdePkg/MdePkg.dec
>    MdeModulePkg/MdeModulePkg.dec
> 
> @@ -45,10 +47,12 @@
>    ReportStatusCodeLib
>    PrintLib
>    HobLib
>    BmpSupportLib
>    DisplayUpdateProgressLib
> +  FileHandleLib
> +  UefiBootManagerLib
> 
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax                               ##
> CONSUMES
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcess
> Flag      ## CONSUMES
> 
> @@ -57,23 +61,38 @@
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsules
> End      ## CONSUMES
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmwa
> re        ## CONSUMES
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwar
> eSuccess   ## CONSUMES
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwar
> eFailed    ## CONSUMES
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSyste
> m         ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport
> ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport
> ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath
> ## SOMETIMES_CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName
> ## CONSUMES
> 
>  [Protocols]
>    gEsrtManagementProtocolGuid                   ## CONSUMES
>    gEfiFirmwareManagementProtocolGuid            ## CONSUMES
>    gEdkiiVariableLockProtocolGuid                ## SOMETIMES_CONSUMES
>    gEdkiiFirmwareManagementProgressProtocolGuid  ##
> SOMETIMES_CONSUMES
> +  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
> +  gEfiBlockIoProtocolGuid                       ## CONSUMES
> +  gEfiDiskIoProtocolGuid                        ## CONSUMES
> 
>  [Guids]
>    gEfiFmpCapsuleGuid                      ## SOMETIMES_CONSUMES ## GUID
>    gWindowsUxCapsuleGuid                   ## SOMETIMES_CONSUMES ## GUID
>    ## SOMETIMES_CONSUMES ## Variable:L"CapsuleMax"
>    ## SOMETIMES_PRODUCES ## Variable:L"CapsuleMax"
>    gEfiCapsuleReportGuid
>    gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> Variable:L"CapsuleUpdateData"
>    gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
> +  gEfiPartTypeSystemPartGuid              ## SOMETIMES_CONSUMES
> +  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> Variable:L"CodRelocationInfo"
> +  ## SOMETIMES_CONSUMES ## Variable:L"OsIndications"
> +  ## SOMETIMES_PRODUCES ## Variable:L"OsIndications"
> +  ## SOMETIMES_CONSUMES ## Variable:L"BootNext"
> +  ## SOMETIMES_PRODUCES ## Variable:L"BootNext"
> +  gEfiGlobalVariableGuid
> +  gEdkiiCapsuleOnDiskNameGuid             ## SOMETIMES_CONSUMES ##
> GUID
> 
>  [Depex]
>    gEfiVariableWriteArchProtocolGuid
> diff --git
> a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> index 5e2d2b87a8..e07dd7986e 100644
> --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> @@ -7,11 +7,11 @@
>    buffer overflow, integer overflow.
> 
>    ProcessCapsules(), ProcessTheseCapsules() will receive untrusted
>    input and do basic validation.
> 
> -  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #include <PiDxe.h>
> @@ -90,14 +90,45 @@ BOOLEAN
>  IsValidCapsuleHeader (
>    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
>    IN UINT64              CapsuleSize
>    );
> 
> +/**
> +  Return if this capsule is a capsule name capsule, based upon
> CapsuleHeader.
> +
> +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> +
> +  @retval TRUE  It is a capsule name capsule.
> +  @retval FALSE It is not a capsule name capsule.
> +**/
> +BOOLEAN
> +IsCapsuleNameCapsule (
> +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> +  );
> +
> +/**
> +  Check the integrity of the capsule name capsule.
> +  If the capsule is vaild, return the physical address of each capsule name
> string.
> +
> +  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule
> name capsule.
> +  @param[out] CapsuleNameNum  Number of capsule name.
> +
> +  @retval NULL                Capsule name capsule is not valid.
> +  @retval CapsuleNameBuf      Array of capsule name physical address.
> +
> +**/
> +EFI_PHYSICAL_ADDRESS *
> +ValidateCapsuleNameCapsuleIntegrity (
> +  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,
> +  OUT UINTN                         *CapsuleNameNum
> +  );
> +
>  extern BOOLEAN                   mDxeCapsuleLibEndOfDxe;
>  BOOLEAN                          mNeedReset = FALSE;
> 
>  VOID                        **mCapsulePtr;
> +CHAR16                      **mCapsuleNamePtr;
>  EFI_STATUS                  *mCapsuleStatusArray;
>  UINT32                      mCapsuleTotalNumber;
> 
>  /**
>    The firmware implements to process the capsule image.
> @@ -114,10 +145,11 @@ UINT32                      mCapsuleTotalNumber;
>  **/
>  EFI_STATUS
>  EFIAPI
>  ProcessThisCapsuleImage (
>    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> +  IN CHAR16              *CapFileName,  OPTIONAL
>    OUT BOOLEAN            *ResetRequired OPTIONAL
>    );
> 
>  /**
>    Function indicate the current completion progress of the firmware
> @@ -183,20 +215,36 @@ InitCapsulePtr (
>    VOID
>    )
>  {
>    EFI_PEI_HOB_POINTERS        HobPointer;
>    UINTN                       Index;
> +  UINTN                       Index2;
> +  UINTN                       Index3;
> +  UINTN                       CapsuleNameNumber;
> +  UINTN                       CapsuleNameTotalNumber;
> +  UINTN                       CapsuleNameCapsuleTotalNumber;
> +  VOID                        **CapsuleNameCapsulePtr;
> +  EFI_PHYSICAL_ADDRESS        *CapsuleNameAddress;
> +
> +  CapsuleNameNumber             = 0;
> +  CapsuleNameTotalNumber        = 0;
> +  CapsuleNameCapsuleTotalNumber = 0;
> +  CapsuleNameCapsulePtr         = NULL;
> 
>    //
>    // Find all capsule images from hob
>    //
>    HobPointer.Raw = GetHobList ();
>    while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE,
> HobPointer.Raw)) != NULL) {
>      if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule-
> >BaseAddress, HobPointer.Capsule->Length)) {
>        HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this
> hob as invalid
>      } else {
> -      mCapsuleTotalNumber++;
> +      if (IsCapsuleNameCapsule((VOID *)(UINTN)HobPointer.Capsule-
> >BaseAddress)) {
> +        CapsuleNameCapsuleTotalNumber++;
> +      } else {
> +        mCapsuleTotalNumber++;
> +      }
>      }
>      HobPointer.Raw = GET_NEXT_HOB (HobPointer);
>    }
> 
>    DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n",
> mCapsuleTotalNumber));
> @@ -222,19 +270,76 @@ InitCapsulePtr (
>      mCapsuleTotalNumber = 0;
>      return ;
>    }
>    SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) *
> mCapsuleTotalNumber, EFI_NOT_READY);
> 
> +  if (CapsuleNameCapsuleTotalNumber != 0) {
> +    CapsuleNameCapsulePtr =  (VOID **) AllocateZeroPool (sizeof (VOID *) *
> CapsuleNameCapsuleTotalNumber);
> +    if (CapsuleNameCapsulePtr == NULL) {
> +      DEBUG ((DEBUG_ERROR, "Allocate CapsuleNameCapsulePtr fail!\n"));
> +      FreePool (mCapsulePtr);
> +      FreePool (mCapsuleStatusArray);
> +      mCapsulePtr         = NULL;
> +      mCapsuleStatusArray = NULL;
> +      mCapsuleTotalNumber = 0;
> +      return ;
> +    }
> +  }
> +
>    //
>    // Find all capsule images from hob
>    //
>    HobPointer.Raw = GetHobList ();
> -  Index = 0;
> +  Index  = 0;
> +  Index2 = 0;
>    while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE,
> HobPointer.Raw)) != NULL) {
> -    mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule-
> >BaseAddress;
> +    if (!IsCapsuleNameCapsule ((VOID *) (UINTN) HobPointer.Capsule-
> >BaseAddress)) {
> +      mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule-
> >BaseAddress;
> +    } else {
> +      CapsuleNameCapsulePtr [Index2++] = (VOID *) (UINTN)
> HobPointer.Capsule->BaseAddress;
> +    }
>      HobPointer.Raw = GET_NEXT_HOB (HobPointer);
>    }
> +
> +  //
> +  // Find Capsule On Disk Names
> +  //
> +  for (Index = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {
> +    CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity
> (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
> +    if (CapsuleNameAddress != NULL ) {
> +      CapsuleNameTotalNumber += CapsuleNameNumber;
> +    }
> +  }
> +
> +  if (CapsuleNameTotalNumber == mCapsuleTotalNumber) {
> +    mCapsuleNamePtr = (CHAR16 **) AllocateZeroPool (sizeof (CHAR16 *) *
> mCapsuleTotalNumber);
> +    if (mCapsuleNamePtr == NULL) {
> +      DEBUG ((DEBUG_ERROR, "Allocate mCapsuleNamePtr fail!\n"));
> +      FreePool (mCapsulePtr);
> +      FreePool (mCapsuleStatusArray);
> +      FreePool (CapsuleNameCapsulePtr);
> +      mCapsulePtr         = NULL;
> +      mCapsuleStatusArray = NULL;
> +      mCapsuleTotalNumber = 0;
> +      return ;
> +    }
> +
> +    for (Index = 0, Index3 = 0; Index < CapsuleNameCapsuleTotalNumber;
> Index ++) {
> +      CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity
> (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
> +      if (CapsuleNameAddress != NULL ) {
> +        for (Index2 = 0; Index2 < CapsuleNameNumber; Index2 ++) {
> +          mCapsuleNamePtr[Index3 ++] = (CHAR16 *)(UINTN)
> CapsuleNameAddress[Index2];
> +        }
> +      }
> +    }
> +  } else {
> +    mCapsuleNamePtr = NULL;
> +  }
> +
> +  if (CapsuleNameCapsulePtr != NULL) {
> +    FreePool (CapsuleNameCapsulePtr);
> +  }
>  }
> 
>  /**
>    This function returns if all capsule images are processed.
> 
> @@ -394,10 +499,11 @@ ProcessTheseCapsules (
>    EFI_CAPSULE_HEADER          *CapsuleHeader;
>    UINT32                      Index;
>    ESRT_MANAGEMENT_PROTOCOL    *EsrtManagement;
>    UINT16                      EmbeddedDriverCount;
>    BOOLEAN                     ResetRequired;
> +  CHAR16                      *CapsuleName;
> 
>    REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE |
> PcdGet32(PcdStatusCodeSubClassCapsule) |
> PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));
> 
>    if (FirstRound) {
>      InitCapsulePtr ();
> @@ -406,10 +512,11 @@ ProcessTheseCapsules (
>    if (mCapsuleTotalNumber == 0) {
>      //
>      // We didn't find a hob, so had no errors.
>      //
>      DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update
> boot mode.\n"));
> +    mNeedReset = TRUE;


According to the API description of ProcessCapsules():

'''
If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.
'''

After the above change (I assume mCapsuleTotalNumber == 0 means no Capsule
Hob), a system reset will be triggered. May I know the purpose for such
change?

Best Regards,
Hao Wu


>      return EFI_SUCCESS;
>    }
> 
>    if (AreAllImagesProcessed ()) {
>      return EFI_SUCCESS;
> @@ -428,14 +535,15 @@ ProcessTheseCapsules (
>    //
>    // If Windows UX capsule exist, process it first
>    //
>    for (Index = 0; Index < mCapsuleTotalNumber; Index++) {
>      CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
> +    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL :
> mCapsuleNamePtr[Index];
>      if (CompareGuid (&CapsuleHeader->CapsuleGuid,
> &gWindowsUxCapsuleGuid)) {
>        DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n",
> CapsuleHeader));
>        DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));
> -      Status = ProcessThisCapsuleImage (CapsuleHeader, NULL);
> +      Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName,
> NULL);
>        mCapsuleStatusArray [Index] = EFI_SUCCESS;
>        DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n", Status));
>        break;
>      }
>    }
> @@ -449,10 +557,11 @@ ProcessTheseCapsules (
>      if (mCapsuleStatusArray [Index] != EFI_NOT_READY) {
>        // already processed
>        continue;
>      }
>      CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
> +    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL :
> mCapsuleNamePtr[Index];
>      if (!CompareGuid (&CapsuleHeader->CapsuleGuid,
> &gWindowsUxCapsuleGuid)) {
>        //
>        // Call capsule library to process capsule image.
>        //
>        EmbeddedDriverCount = 0;
> @@ -469,11 +578,11 @@ ProcessTheseCapsules (
>        }
> 
>        if ((!FirstRound) || (EmbeddedDriverCount == 0)) {
>          DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n",
> CapsuleHeader));
>          ResetRequired = FALSE;
> -        Status = ProcessThisCapsuleImage (CapsuleHeader, &ResetRequired);
> +        Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName,
> &ResetRequired);
>          mCapsuleStatusArray [Index] = Status;
>          DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status));
> 
>          if (Status != EFI_NOT_READY) {
>            if (EFI_ERROR(Status)) {
> diff --git
> a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> index 6ad766d65a..0ec5f20676 100644
> --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> @@ -1,9 +1,9 @@
>  /** @file
>    DXE capsule report related function.
> 
> -  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> 
>  #include <PiDxe.h>
> @@ -27,10 +27,22 @@
>  #include <Library/DevicePathLib.h>
>  #include <Library/CapsuleLib.h>
> 
>  #include <IndustryStandard/WindowsUxCapsule.h>
> 
> +/**
> +  This routine is called to clear CapsuleOnDisk Relocation Info variable.
> +  Total Capsule On Disk length is recorded in this variable
> +
> +  @retval EFI_SUCCESS   Capsule On Disk flags are cleared
> +
> +**/
> +EFI_STATUS
> +CoDClearCapsuleRelocationInfo(
> +  VOID
> +  );
> +
>  /**
>    Get current capsule last variable index.
> 
>    @return Current capsule last variable index.
>    @retval -1  No current capsule last variable.
> @@ -172,44 +184,55 @@ RecordCapsuleStatusVariable (
>    @param[in] CapsuleHeader  The capsule image header
>    @param[in] CapsuleStatus  The capsule process stauts
>    @param[in] PayloadIndex   FMP payload index
>    @param[in] ImageHeader    FMP image header
>    @param[in] FmpDevicePath  DevicePath associated with the FMP producer
> +  @param[in] CapFileName    Capsule file name
> 
>    @retval EFI_SUCCESS          The capsule status variable is recorded.
>    @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status
> variable.
>  **/
>  EFI_STATUS
>  RecordFmpCapsuleStatusVariable (
>    IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
>    IN EFI_STATUS                                    CapsuleStatus,
>    IN UINTN                                         PayloadIndex,
>    IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> *ImageHeader,
> -  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath OPTIONAL
> +  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath, OPTIONAL
> +  IN CHAR16                                        *CapFileName    OPTIONAL
>    )
>  {
>    EFI_CAPSULE_RESULT_VARIABLE_HEADER  *CapsuleResultVariableHeader;
>    EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultVariableFmp;
>    EFI_STATUS                          Status;
>    UINT8                               *CapsuleResultVariable;
>    UINTN                               CapsuleResultVariableSize;
>    CHAR16                              *DevicePathStr;
>    UINTN                               DevicePathStrSize;
> +  UINTN                               CapFileNameSize;
> +
> +  DevicePathStr   = NULL;
> +  CapFileNameSize = sizeof(CHAR16);
> 
> -  DevicePathStr = NULL;
>    if (FmpDevicePath != NULL) {
>      DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE);
>    }
>    if (DevicePathStr != NULL) {
>      DevicePathStrSize = StrSize(DevicePathStr);
>    } else {
>      DevicePathStrSize = sizeof(CHAR16);
>    }
> +
> +  if (CapFileName != NULL) {
> +    CapFileNameSize = StrSize(CapFileName);
> +  }
> +
>    //
> -  // Allocate zero CHAR16 for CapsuleFileName.
> +  // Allocate room for CapsuleFileName.
>    //
> -  CapsuleResultVariableSize =
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) +
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) +
> DevicePathStrSize;
> +  CapsuleResultVariableSize =
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) +
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize +
> DevicePathStrSize;
> +
>    CapsuleResultVariable     = AllocateZeroPool (CapsuleResultVariableSize);
>    if (CapsuleResultVariable == NULL) {
>      return EFI_OUT_OF_RESOURCES;
>    }
>    CapsuleResultVariableHeader = (VOID *)CapsuleResultVariable;
> @@ -223,12 +246,17 @@ RecordFmpCapsuleStatusVariable (
>    CapsuleResultVariableFmp = (VOID *)(CapsuleResultVariable +
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER));
>    CapsuleResultVariableFmp->Version = 0x1;
>    CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;
>    CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader-
> >UpdateImageIndex;
>    CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId,
> &ImageHeader->UpdateImageTypeId);
> +
> +  if (CapFileName != NULL) {
> +    CopyMem((UINT8 *)CapsuleResultVariableFmp +
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName,
> CapFileNameSize);
> +  }
> +
>    if (DevicePathStr != NULL) {
> -    CopyMem ((UINT8 *)CapsuleResultVariableFmp +
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16),
> DevicePathStr, DevicePathStrSize);
> +    CopyMem ((UINT8 *)CapsuleResultVariableFmp +
> sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize,
> DevicePathStr, DevicePathStrSize);
>      FreePool (DevicePathStr);
>      DevicePathStr = NULL;
>    }
> 
>    Status = EFI_SUCCESS;
> @@ -398,10 +426,35 @@ InitCapsuleUpdateVariable (
>      }
>      Index++;
>    }
>  }
> 
> +/**
> +  Initialize capsule relocation info variable.
> +**/
> +VOID
> +InitCapsuleRelocationInfo (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
> +
> +  CoDClearCapsuleRelocationInfo();
> +
> +  //
> +  // Unlock Capsule On Disk relocation Info variable only when Capsule On
> Disk flag is enabled
> +  //
> +  if (!CoDCheckCapsuleOnDiskFlag()) {
> +    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL,
> (VOID **) &VariableLock);
> +    if (!EFI_ERROR (Status)) {
> +      Status = VariableLock->RequestToLock (VariableLock,
> COD_RELOCATION_INFO_VAR_NAME, &gEfiCapsuleVendorGuid);
> +      ASSERT_EFI_ERROR (Status);
> +    }
> +  }
> +}
> +
>  /**
>    Initialize capsule related variables.
>  **/
>  VOID
>  InitCapsuleVariable (
> @@ -409,10 +462,12 @@ InitCapsuleVariable (
>    )
>  {
>    InitCapsuleUpdateVariable();
>    InitCapsuleMaxVariable();
>    InitCapsuleLastVariable();
> +  InitCapsuleRelocationInfo();
> +
>    //
>    // No need to clear L"Capsule####", because OS/APP should refer
> L"CapsuleLast"
>    // to check status and delete them.
>    //
>  }
> diff --git
> a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> index 2c93e68700..bf56f4623f 100644
> --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> +++
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> @@ -1,11 +1,11 @@
>  ## @file
>  #  Capsule library instance for DXE_RUNTIME_DRIVER.
>  #
>  #  Capsule library instance for DXE_RUNTIME_DRIVER module types.
>  #
> -#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
>  ##
> 
>  [Defines]
> @@ -66,8 +66,9 @@
>    gEfiCapsuleReportGuid
>    gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> Variable:L"CapsuleUpdateData"
>    gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
>    gEfiEventReadyToBootGuid                ## CONSUMES ## Event
>    gEfiEventVirtualAddressChangeGuid       ## CONSUMES ## Event
> +  gEdkiiCapsuleOnDiskNameGuid             ## SOMETIMES_CONSUMES ##
> GUID
> 
>  [Depex]
>    gEfiVariableWriteArchProtocolGuid
> diff --git a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> index 06a1abe16b..39e37cffcd 100644
> --- a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> +++ b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> @@ -1,9 +1,9 @@
>  /** @file
>    Null Dxe Capsule Library instance does nothing and returns unsupport
> status.
> 
> -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
>  #include <Uefi.h>
>  #include <Library/CapsuleLib.h>
> @@ -83,5 +83,88 @@ ProcessCapsules (
>    )
>  {
>    return EFI_UNSUPPORTED;
>  }
> 
> +
> +/**
> +  This routine is called to check if CapsuleOnDisk flag in OsIndications
> Variable
> +  is enabled.
> +
> +  @retval TRUE     Flag is enabled
> +  @retval FALSE    Flag is not enabled
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +CoDCheckCapsuleOnDiskFlag(
> +  VOID
> +  )
> +{
> +  return FALSE;
> +}
> +
> +/**
> +  This routine is called to clear CapsuleOnDisk flags including OsIndications
> and BootNext variable.
> +
> +  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDClearCapsuleOnDiskFlag(
> +  VOID
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Relocate Capsule on Disk from EFI system partition.
> +
> +  Two solution to deliver Capsule On Disk:
> +  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On
> Disk to memory and call UpdateCapsule().
> +  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On
> Disk to a platform-specific NV storage
> +  device with BlockIo protocol.
> +
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  Side Effects:
> +    Capsule Delivery Supported Flag in OsIndication variable and BootNext
> variable will be cleared.
> +    Solution B: Content corruption. Block IO write directly touches low level
> write. Orignal partitions, file
> +  systems of the relocation device will be corrupted.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +
> +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDRelocateCapsule(
> +  UINTN     MaxRetry
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Remove the temp file from the root of EFI System Partition.
> +  Device enumeration like USB costs time, user can input MaxRetry to tell
> function to retry.
> +  Function will stall 100ms between each retry.
> +
> +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms between
> each connection try to ensure
> +                                     devices like USB can get enumerated.
> +
> +  @retval EFI_SUCCESS   Remove the temp file successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +CoDRemoveTempFile (
> +  UINTN    MaxRetry
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
  2019-06-12  7:47 ` Wu, Hao A
@ 2019-06-12  8:13   ` Zhang, Chao B
  0 siblings, 0 replies; 33+ messages in thread
From: Zhang, Chao B @ 2019-06-12  8:13 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io, Xu, Wei6
  Cc: Wang, Jian J, Kinney, Michael D, Gao, Liming

[-- Attachment #1: Type: text/plain, Size: 5125 bytes --]

HI Hao:
  I don't have extra comments for the whole patch

From: Wu, Hao A
Sent: Wednesday, June 12, 2019 3:48 PM
To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>
Subject: RE: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.

Hello Chao,

Do you have any comment/feedback on this series?

One comment with regard to the series below:

> -----Original Message-----
> From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> [mailto:devel@edk2.groups.io] On Behalf Of
> Xu, Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> Cc: Wang, Jian J; Wu, Hao A; Kinney, Michael D; Gao, Liming; Zhang, Chao B
> Subject: [edk2-devel][Patch v2 0/7] Implement Capsule On Disk.
>
> V2:
> Fix Ecc check failure.
>
> V1:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
>
> This patch set implements Capsule On Disk.
> Depends on whether platform supports Capsule-In-Ram, Capsule On Disk
> feature is composed of 2 solutions:
> Solution A): Load capsules out of TCB, rely on UpdateCapsule() runtime
> service to deliver Capsule-On-Disk.
> Solution B): Relocate capsules into a temp file which will be stored in root
> directory on a platform specific storage device.
> Leverage existing storage stack in PEI to load all capsule on disk images and
> create capsule hobs for the capsules.
> This solution has bigger TCB, but can work without Capsule-In-RAM support.
>
>
> Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
> Cc: Michael D Kinney <michael.d.kinney@intel.com<mailto:michael.d.kinney@intel.com>>
> Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
> Cc: Chao B Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
>
> xuwei6 (7):
>   MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
>   MdeModulePkg: Add Capsule On Disk related definition.
>   MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
>   MdeModulePkg/BdsDxe: Support Capsule On Disk.
>   MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
>   MdeModulePkg/DxeIpl: Support Capsule On Disk.
>   MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.


Please re-order the sequence of the patches.
I found that the below patch:
MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.

depends on some definitions added in patch (last one):
MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.

Best Regards,
Hao Wu


>
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.h              |    3 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf            |   20 +-
>  MdeModulePkg/Core/DxeIplPeim/DxeLoad.c             |   37 +-
>  MdeModulePkg/Include/Library/CapsuleLib.h          |   94 +-
>  MdeModulePkg/Include/Ppi/CapsuleOnDisk.h           |   48 +
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       | 1983
> ++++++++++++++++++++
>  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |   63 +
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |   56 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |   21 +-
>  .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |  121 +-
>  .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |   67 +-
>  .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |    3 +-
>  .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |   85 +-
>  MdeModulePkg/MdeModulePkg.dec                      |   43 +
>  MdeModulePkg/MdeModulePkg.dsc                      |    4 +
>  MdeModulePkg/MdeModulePkg.uni                      |   32 +
>  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf           |    3 +-
>  MdeModulePkg/Universal/BdsDxe/BdsEntry.c           |    6 +-
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    |  442 +++++
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |   64 +
>  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |   15 +
>  .../CapsuleOnDiskLoadPeiExtra.uni                  |   14 +
>  .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf        |    1 +
>  .../Universal/CapsuleRuntimeDxe/CapsuleService.c   |   10 +-
>  MdePkg/Include/Ppi/BootInRecoveryMode.h            |    9 +-
>  MdePkg/MdePkg.dec                                  |    3 +
>  26 files changed, 3205 insertions(+), 42 deletions(-)
>  create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
>  create mode 100644
> MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.i
> nf
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.u
> ni
>  create mode 100644
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiE
> xtra.uni
>
> --
> 2.16.2.windows.1
>
>
> 

[-- Attachment #2: Type: text/html, Size: 16328 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition.
  2019-06-12  7:48   ` Wu, Hao A
@ 2019-06-12  8:28     ` Liming Gao
  0 siblings, 0 replies; 33+ messages in thread
From: Liming Gao @ 2019-06-12  8:28 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io, Xu, Wei6
  Cc: Kinney, Michael D, Zhang, Chao B

Wei:

>-----Original Message-----
>From: Wu, Hao A
>Sent: Wednesday, June 12, 2019 3:48 PM
>To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
>Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Gao, Liming
><liming.gao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
>Subject: RE: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In
>CapsuleOnDisk Mode Ppi definition.
>
>> -----Original Message-----
>> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
>Xu,
>> Wei6
>> Sent: Wednesday, June 05, 2019 11:42 PM
>> To: devel@edk2.groups.io
>> Cc: Kinney, Michael D; Gao, Liming; Zhang, Chao B; Xu, Wei6
>> Subject: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk
>> Mode Ppi definition.
>>
>> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
>>
>> This PPI indicates current boot mode is capsule on disk mode.
>>
>> Cc: Michael D Kinney <michael.d.kinney@intel.com>
>> Cc: Liming Gao <liming.gao@intel.com>
>> Cc: Chao B Zhang <chao.b.zhang@intel.com>
>> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
>> ---
>>  MdePkg/Include/Ppi/BootInRecoveryMode.h | 9 ++++++++-
>>  MdePkg/MdePkg.dec                       | 3 +++
>>  2 files changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/MdePkg/Include/Ppi/BootInRecoveryMode.h
>> b/MdePkg/Include/Ppi/BootInRecoveryMode.h
>> index ae40744d9b..71b0ca8586 100644
>> --- a/MdePkg/Include/Ppi/BootInRecoveryMode.h
>> +++ b/MdePkg/Include/Ppi/BootInRecoveryMode.h
>> @@ -1,10 +1,10 @@
>>  /** @file
>>    This PPI is installed by the platform PEIM to designate that a recovery boot
>>    is in progress.
>>
>> -  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
>> +  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>>    SPDX-License-Identifier: BSD-2-Clause-Patent
>>
>>    @par Revision Reference:
>>    This PPI is introduced in PI Version 1.0.
>>
>> @@ -19,6 +19,13 @@
>>    }
>>
>>
>>  extern EFI_GUID gEfiPeiBootInRecoveryModePpiGuid;
>>
>> +#define EFI_PEI_BOOT_IN_CAPSULE_ON_DISK_MODE_PPI \
>> +  { \
>> +    0xb08a11e4, 0xe2b7, 0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf,
>> 0xd1 } \
>> +  }
>> +
>> +extern EFI_GUID gEfiPeiBootInCapsuleOnDiskModePpiGuid;
>> +
>
>Hello all,
>
>One question, the above PPI will be added in the next PI spec, right?
>Since I cannot find this definition within the PI 1.7 spec.
>

If this is not defined in PI spec, it belongs to edk2 implementation related PPI. 
For this feature, I suggest to add It into MdeModulePkg with Edkii prefix. 

>Best Regards,
>Hao Wu
>
>>  #endif
>> diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
>> index 6c563375ee..ec02b8c7c7 100644
>> --- a/MdePkg/MdePkg.dec
>> +++ b/MdePkg/MdePkg.dec
>> @@ -790,10 +790,13 @@
>>    gEfiPeiMemoryDiscoveredPpiGuid = {0xf894643d, 0xc449, 0x42d1, {0x8e,
>> 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } }
>>
>>    ## Include/Ppi/BootInRecoveryMode.h
>>    gEfiPeiBootInRecoveryModePpiGuid = { 0x17ee496a, 0xd8e4, 0x4b9a,
>{0x94,
>> 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } }
>>
>> +  ## Include/Ppi/BootInRecoveryMode.h
>> +  gEfiPeiBootInCapsuleOnDiskModePpiGuid = { 0xb08a11e4, 0xe2b7,
>0x4b75,
>> { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } }
>> +
>>    ## Include/Ppi/EndOfPeiPhase.h
>>    gEfiEndOfPeiSignalPpiGuid = {0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80,
>> 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } }
>>
>>    ## Include/Ppi/Reset.h
>>    gEfiPeiResetPpiGuid = { 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78,
>0xc6,
>> 0xf4, 0xfe, 0x71, 0x2f } }
>> --
>> 2.16.2.windows.1
>>
>>
>> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition.
  2019-06-12  7:48   ` Wu, Hao A
@ 2019-06-12  8:43     ` Xu, Wei6
  0 siblings, 0 replies; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-12  8:43 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io; +Cc: Wang, Jian J, Zhang, Chao B

Hi Hao,

Thanks a lot for the comments. It comes from the feedback of SDL review. 
The PcdCapsuleOnDiskSupport only has type of '[PcdsFixedAtBuild, PcdsPatchableInModule]', so that Capsule On Disk feature can be configured by platform during build time, to ensure the feature will be permanently removed.

BR,
Wei
-----Original Message-----
From: Wu, Hao A 
Sent: Wednesday, June 12, 2019 3:48 PM
To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition.

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of 
> Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk 
> related definition.
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> 
> This patch will add Capsule On Disk related definition, including 
> GUID, PPI and PCDs:
> The Capsule On Disk Name GUID indicates the capsule is to store 
> Capsule On Disk file names.
> The Pei Capsule On Disk PPI provides service to retrieve capsules from 
> Capsule On Disk temp relocation file on mass storage devices and 
> create capsule hob for these capsules.
> PcdCapsuleOnDiskSupport is used to enable/disable Capsule On Disk.
> PcdCapsuleInRamSupport is used to enabble/disable Capsule In Ram.

enabble -> enable

May I know the reason that PcdCapsuleOnDiskSupport is listed under section '[PcdsFixedAtBuild, PcdsPatchableInModule]' while PcdCapsuleInRamSupport is listed under '[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]'?

Best Regards,
Hao Wu

> PcdCoDRelocationFileName specifies the Capsule On Disk temp relocation 
> file name.
> PcdCodRelocationDevPath specifies platform specific device to store 
> Capsule On Disk tem relocation file.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Chao B Zhang <chao.b.zhang@intel.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
>  MdeModulePkg/Include/Ppi/CapsuleOnDisk.h | 48
> ++++++++++++++++++++++++++++++++
>  MdeModulePkg/MdeModulePkg.dec            | 43
> ++++++++++++++++++++++++++++
>  MdeModulePkg/MdeModulePkg.uni            | 32 +++++++++++++++++++++
>  3 files changed, 123 insertions(+)
>  create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> 
> diff --git a/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> b/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> new file mode 100644
> index 0000000000..28be6e42be
> --- /dev/null
> +++ b/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h
> @@ -0,0 +1,48 @@
> +/** @file
> +  This file declares Capsule On Disk PPI.  This PPI is used to find 
> +and load the
> +  capsule on files that are relocated into a temp file under rootdir.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef __PEI_CAPSULE_ON_DISK_PPI_H__ #define 
> +__PEI_CAPSULE_ON_DISK_PPI_H__
> +
> +#define EFI_PEI_CAPSULE_ON_DISK_PPI_GUID \
> +  { \
> +    0x71a9ea61, 0x5a35, 0x4a5d, {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 
> +0x67,
> 0xe0 } \
> +  }
> +
> +typedef struct _EFI_PEI_CAPSULE_ON_DISK_PPI
> EFI_PEI_CAPSULE_ON_DISK_PPI;
> +
> +/**
> +  Loads a DXE capsule from some media into memory and updates the HOB
> table
> +  with the DXE firmware volume information.
> +
> +  @param  PeiServices   General-purpose services that are available to every
> PEIM.
> +  @param  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance.
> +
> +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> +  @retval EFI_DEVICE_ERROR   A device error occurred.
> +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_PEI_LOAD_CAPSULE_ON_DISK)(
> +  IN EFI_PEI_SERVICES             **PeiServices,
> +  IN EFI_PEI_CAPSULE_ON_DISK_PPI  *This
> +  );
> +
> +///
> +///  Finds and loads the recovery files.
> +///
> +struct _EFI_PEI_CAPSULE_ON_DISK_PPI {
> +  EFI_PEI_LOAD_CAPSULE_ON_DISK LoadCapsuleOnDisk;  ///< Loads a DXE
> binary capsule into memory.
> +};
> +
> +extern EFI_GUID gEdkiiPeiCapsuleOnDiskPpiGuid;
> +
> +#endif
> diff --git a/MdeModulePkg/MdeModulePkg.dec 
> b/MdeModulePkg/MdeModulePkg.dec index 6cba729982..d80b728313 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -394,10 +394,13 @@
>    gEdkiiS3SmmInitDoneGuid = { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 
> 0x71, 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } }
> 
>    ## Include/Guid/S3StorageDeviceInitList.h
>    gS3StorageDeviceInitListGuid = { 0x310e9b8c, 0xcf90, 0x421e, { 
> 0x8e, 0x9b, 0x9e, 0xef, 0xb6, 0x17, 0xc8, 0xef } }
> 
> +  ## GUID indicates the capsule is to store Capsule On Disk file names.
> +  gEdkiiCapsuleOnDiskNameGuid = { 0x98c80a4f, 0xe16b, 0x4d11, { 0x93,
> 0x9a, 0xab, 0xe5, 0x61, 0x26, 0x3, 0x30 } }
> +
>  [Ppis]
>    ## Include/Ppi/AtaController.h
>    gPeiAtaControllerPpiGuid       = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a,
> 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
> 
>    ## Include/Ppi/UsbHostController.h
> @@ -464,10 +467,13 @@
>    gEdkiiPeiAtaPassThruPpiGuid               = { 0xa16473fd, 0xd474, 0x4c89, { 0xae,
> 0xc7, 0x90, 0xb8, 0x3c, 0x73, 0x86, 0x9  } }
> 
>    ## Include/Ppi/Debug.h
>    gEdkiiDebugPpiGuid                        = { 0x999e699c, 0xb013, 0x475e, { 0xb1,
> 0x7b, 0xf3, 0xa8, 0xae, 0x5c, 0x48, 0x75 } }
> 
> +  ## Include/Ppi/CapsuleOnDisk.h
> +  gEdkiiPeiCapsuleOnDiskPpiGuid             =  {0x71a9ea61, 0x5a35, 0x4a5d,
> {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67, 0xe0}}
> +
>  [Protocols]
>    ## Load File protocol provides capability to load and unload EFI 
> image into memory and execute it.
>    #  Include/Protocol/LoadPe32Image.h
>    #  This protocol is deprecated. Native EDKII module should NOT use 
> this protocol to load/unload image.
>    #  If developer need implement such functionality, they should use 
> BasePeCoffLib.
> @@ -1473,10 +1479,26 @@
> 
>    ## Indicates the allowable maximum number of Reset Filters, Reset 
> Notifications or Reset Handlers in PEI phase.
>    # @Prompt Maximum Number of PEI Reset Filters, Reset Notifications 
> or Reset Handlers.
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaximumPeiResetNotifies|0x10|UI
> NT32|0x0000010A
> 
> +  ## Capsule On Disk is to deliver capsules via files on Mass Storage
> device.<BR><BR>
> +  #  This PCD indicates if the Capsule On Disk is supported.<BR>
> +  #   TRUE  - Capsule On Disk is supported.<BR>
> +  #   FALSE - Capsule On Disk is not supported.<BR>
> +  #  If platform does not use this feature, this PCD should be set to
> FALSE.<BR><BR>
> +  #  Two sulotions to deliver Capsule On Disk:<BR>
> +  #    a) If PcdCapsuleInRamSupport = TRUE, Load Capsule On Disk image out
> of TCB, and reuse
> +  #       Capsule In Ram to deliver capsule.<BR>
> +  #    b) If PcdCapsuleInRamSupport = FALSE, Relocate Capsule On Disk image
> to RootDir out
> +  #       of TCB, and reuse FatPei to load capsules from external storage.<BR>
> +  #  Note:<BR>
> +  #    If Both Capsule In Ram and Capsule On Disk are provisioned at the same
> time, the Capsule
> +  #  On Disk will be bypassed.
> +  # @Prompt Enable Capsule On Disk support.
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOO
> LEAN|0x0000002d
> +
>  [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
>    ## This PCD defines the Console output row. The default value is 25 
> according to UEFI spec.
>    #  This PCD could be set to 0 then console output would be at max 
> column and max row.
>    # @Prompt Console output row.
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|25|UINT32|0x4000000
> 6
> @@ -1932,10 +1954,17 @@
>    #  The file name must be the 8.3 format.
>    #  The PCD data must be in UNICODE format.
>    # @Prompt Recover file name in PEI phase
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"|
> VOID*|0x30001045
> 
> +  ## This is Capsule Temp Relocation file name in PEI phase.
> +  #  The file must be in the root directory.
> +  #  The file name must be the 8.3 format.
> +  #  The PCD data must be in UNICODE format.
> +  # @Prompt Capsule On Disk Temp Relocation file name in PEI phase
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName|L"TempCo
> d.tmp"|VOID*|0x30001048
> +
>    ## This PCD hold a list GUIDs for the ImageTypeId to indicate the
>    #  FMP capsule is a system FMP.
>    # @Prompt A list of system FMP ImageTypeId GUIDs
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGu
> id|{0x0}|VOID*|0x30001046
> 
> @@ -1943,10 +1972,24 @@
>    #  enabled on AMD processors supporting the Secure Encrypted 
> Virtualization (SEV) feature.
>    #  This mask should be applied when creating 1:1 virtual to 
> physical mapping tables.
>    # @Prompt The address mask when memory encryption is enabled.
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrM
> ask|0x0|UINT64|0x30001047
> 
> +  ## Capsule In Ram is to use memory to deliver the capsules that 
> + will be
> processed after system
> +  #  reset.<BR><BR>
> +  #  This PCD indicates if the Capsule In Ram is supported.<BR>
> +  #   TRUE  - Capsule In Ram is supported.<BR>
> +  #   FALSE - Capsule In Ram is not supported.
> +  # @Prompt Enable Capsule In Ram support.
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport|TRUE|BOOL
> EAN|0x0000002e
> +
> +  ## Full device path of plaform specific device to store Capsule On 
> + Disk
> temp relocation file.<BR>
> +  #  If this PCD is set, Capsule On Disk temp relocation file will be 
> + stored in
> the device specified
> +  #  by this PCD, instead of the EFI System Partition that stores 
> + capsule image
> file.
> +  # @Prompt Capsule On Disk relocation device path.
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath|{0xFF}|VOI
> D*|0x0000002f
> +
>  [PcdsPatchableInModule]
>    ## Specify memory size with page number for PEI code when
>    #  Loading Module at Fixed Address feature is enabled.
>    #  The value will be set by the build tool.
>    # @Prompt LMFA PEI code page number.
> diff --git a/MdeModulePkg/MdeModulePkg.uni 
> b/MdeModulePkg/MdeModulePkg.uni index ed8ac9eadc..85c6beae0d 100644
> --- a/MdeModulePkg/MdeModulePkg.uni
> +++ b/MdeModulePkg/MdeModulePkg.uni
> @@ -1064,10 +1064,17 @@
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdRecoveryFileName_HELP
> #language en-US "This is recover file name in PEI phase.\n"
>                                                                                       
> "The file must be in the root directory.\n"
>                                                                                       
> "The file name must be the 8.3 format.\n"
>                                                                                       
> "The PCD data must be in UNICODE format."
> 
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_PRO
> MPT  #language en-US "Capsule On Disk Temp Relocation file name in PEI 
> phase"
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_HELP
> #language en-US "This is Capsule Temp Relocation file name in PEI phase.\n"
> +                                                                       
> + "The file must be in the root
> directory.\n"
> +                                                                       
> + "The file name must be the 8.3
> format.\n"
> +                                                                       
> + "The PCD data must be in
> UNICODE format."
> +
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTyp
> eIdGuid_PROMPT  #language en-US "A list of system FMP ImageTypeId 
> GUIDs"
> 
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTyp
> eIdGuid_HELP  #language en-US "This PCD hold a list GUIDs for the 
> ImageTypeId to indicate the\n"
>                                                                         
> "FMP capsule is a system FMP."
> 
> @@ -1129,10 +1136,35 @@
> 
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPteMemoryEncryptionAddres
> sOrMask_HELP  #language en-US "This PCD holds the address mask for 
> page table entries when memory encryption is\n"
>                                                                                                       
> "enabled on AMD processors supporting the Secure Encrypted Virtualization (SEV) feature.\n"
>                                                                                                       
> "This mask should be applied when creating 1:1 virtual to physical mapping tables."
> 
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_PRO
> MPT  #language en-US "Enable Capsule On Disk support"
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_HELP
> #language en-US   "Capsule On Disk is to deliver capsules via files on Mass
> Storage device.<BR><BR>"
> +                                                                                           
> + "This PCD indicates if the
> Capsule On Disk is supported.<BR>"
> +                                                                                           
> + " TRUE  - Capsule On Disk is
> supported.<BR>"
> +                                                                                           
> + " FALSE - Capsule On Disk is not
> supported.<BR>"
> +                                                                                           
> + "If platform does not use this
> feature, this PCD should be set to FALSE.<BR><BR>"
> +                                                                                           
> + "Two sulotions to deliver
> Capsule On Disk:<BR>"
> +                                                                                           
> + " a) If
> PcdCapsuleInRamSupport = TRUE, Load Capsule On Disk image out of TCB, 
> and reuse Capsule In Ram to deliver capsule.<BR>"
> +                                                                                           
> + " b) If
> PcdCapsuleInRamSupport = FALSE, Relocate Capsule On Disk image to 
> RootDir out of TCB, and reuse FatPei to load capsules from external 
> storage.<BR>"
> +                                                                                           "Note:<BR>"
> +                                                                                           
> + "If Both Capsule In Ram and
> Capsule On Disk are provisioned at the same time, the Capsule On Disk 
> will be bypassed."
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROM
> PT  #language en-US "Enable Capsule In Ram support"
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP
> #language en-US   "Capsule In Ram is to use memory to deliver the capsules
> that will be processed after system reset.<BR><BR>"
> +                                                                       
> + "This PCD indicates if the
> Capsule In Ram is supported.<BR>"
> +                                                                       
> + " TRUE  - Capsule In Ram is
> supported.<BR>"
> +                                                                       
> + " FALSE - Capsule In Ram is not
> supported."
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_PRO
> MPT  #language en-US "Capsule On Disk relacation device path."
> +
> +#string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_HELP
> #language en-US   "Full device path of plaform specific device to store
> Capsule On Disk temp relocation file.<BR>"
> +                                                                                           
> + "If this PCD is set, Capsule On
> Disk temp relocation file will be stored in the device specified by 
> this PCD, instead of the EFI System Partition that stores capsule image file."
> +
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionProperty
> Mask_PROMPT  #language en-US "Enable NULL pointer detection"
> 
>  #string
> STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionProperty
> Mask_HELP    #language en-US "Mask to control the NULL address detection
> in code for different phases.\n"
>                                                                                                         
> " If enabled, accessing NULL address in UEFI or SMM code can be caught.\n\n"
>                                                                                                         "   BIT0    - Enable NULL
> pointer detection for UEFI.\n"
> --
> 2.16.2.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  2019-06-12  7:49   ` Wu, Hao A
@ 2019-06-19  0:41     ` Zhang, Chao B
  2019-06-19  0:59       ` Wu, Hao A
  0 siblings, 1 reply; 33+ messages in thread
From: Zhang, Chao B @ 2019-06-19  0:41 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J

[-- Attachment #1: Type: text/plain, Size: 4285 bytes --]

Hi Hao:
  I think blocking UpdateCapsule interface is enough for Capsule in RAM.  QueryCapsuleCapabilities can still be used to test capsules before delivering by different sources.

From: Wu, Hao A
Sent: Wednesday, June 12, 2019 3:49 PM
To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

> -----Original Message-----
> From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe:
> Introduce PCD to control this feature.
>
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
>
> Introduce PcdCapsuleInRamSupport to turn on/off Capsule In Ram feature.
> Platform could choose to drop CapsulePei/CapsuleX64 and not to support
> Capsule In Ram.


For this patch, it only affects UpdateCapsule(). Do we need to update the
behavior for QueryCapsuleCapabilities() as well?

Best Regards,
Hao Wu


>
> Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
> Cc: Chao B Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com<mailto:wei6.xu@intel.com>>
> ---
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf |  1
> +
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c      | 10
> +++++++++-
>  2 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> index 338577e293..9da450722b 100644
> ---
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> @@ -88,10 +88,11 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> CONSUMES
>
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ##
> SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ##
> SOMETIMES_CONSUMES # Populate Image requires reset support.
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ##
> CONSUMES
>
>  [Pcd.X64]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize
> ## SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ##
> SOMETIMES_CONSUMES
>
> diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> index aaf819c4c6..53a1af44e2 100644
> --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> @@ -2,11 +2,11 @@
>    Capsule Runtime Driver produces two UEFI capsule runtime services.
>    (UpdateCapsule, QueryCapsuleCapabilities)
>    It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>    the capsule runtime services are ready.
>
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
>
>  **/
>
>  #include "CapsuleService.h"
> @@ -69,10 +69,18 @@ UpdateCapsule (
>    BOOLEAN                   NeedReset;
>    BOOLEAN                   InitiateReset;
>    CHAR16                    CapsuleVarName[30];
>    CHAR16                    *TempVarName;
>
> +  //
> +  // Check if platform support Capsule In RAM or not.
> +  // Platform could choose to drop CapsulePei/CapsuleX64 and do not
> support Capsule In RAM.
> +  //
> +  if (!PcdGetBool(PcdCapsuleInRamSupport)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
>    //
>    // Capsule Count can't be less than one.
>    //
>    if (CapsuleCount < 1) {
>      return EFI_INVALID_PARAMETER;
> --
> 2.16.2.windows.1
>
>
> 

[-- Attachment #2: Type: text/html, Size: 14228 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  2019-06-19  0:41     ` Zhang, Chao B
@ 2019-06-19  0:59       ` Wu, Hao A
  2019-06-19  1:13         ` Zhang, Chao B
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-19  0:59 UTC (permalink / raw)
  To: Zhang, Chao B, devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J

[-- Attachment #1: Type: text/plain, Size: 5030 bytes --]

From: Zhang, Chao B
Sent: Wednesday, June 19, 2019 8:42 AM
To: Wu, Hao A; devel@edk2.groups.io; Xu, Wei6
Cc: Wang, Jian J
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

Hi Hao:
  I think blocking UpdateCapsule interface is enough for Capsule in RAM.  QueryCapsuleCapabilities can still be used to test capsules before delivering by different sources.

Hello Chao,

I am okay with the usage update for the function.

But I think we need to update the comments for the QueryCapsuleCapabilities()
function within this driver and the 'EFI_QUERY_CAPSULE_CAPABILITIES' service for
EFI_RUNTIME_SERVICES to reflect the fact that even QueryCapsuleCapabilities()
returns without error, the capsule may still be unsupported by UpdateCapsule():

/**
  Returns if the capsule can be supported via UpdateCapsule().

  ...

**/

Best Regards,
Hao Wu


From: Wu, Hao A
Sent: Wednesday, June 12, 2019 3:49 PM
To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

> -----Original Message-----
> From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe:
> Introduce PCD to control this feature.
>
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
>
> Introduce PcdCapsuleInRamSupport to turn on/off Capsule In Ram feature.
> Platform could choose to drop CapsulePei/CapsuleX64 and not to support
> Capsule In Ram.


For this patch, it only affects UpdateCapsule(). Do we need to update the
behavior for QueryCapsuleCapabilities() as well?

Best Regards,
Hao Wu


>
> Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
> Cc: Chao B Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com<mailto:wei6.xu@intel.com>>
> ---
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf |  1
> +
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c      | 10
> +++++++++-
>  2 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> index 338577e293..9da450722b 100644
> ---
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> @@ -88,10 +88,11 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> CONSUMES
>
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ##
> SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ##
> SOMETIMES_CONSUMES # Populate Image requires reset support.
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ##
> CONSUMES
>
>  [Pcd.X64]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize
> ## SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ##
> SOMETIMES_CONSUMES
>
> diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> index aaf819c4c6..53a1af44e2 100644
> --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> @@ -2,11 +2,11 @@
>    Capsule Runtime Driver produces two UEFI capsule runtime services.
>    (UpdateCapsule, QueryCapsuleCapabilities)
>    It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>    the capsule runtime services are ready.
>
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
>
>  **/
>
>  #include "CapsuleService.h"
> @@ -69,10 +69,18 @@ UpdateCapsule (
>    BOOLEAN                   NeedReset;
>    BOOLEAN                   InitiateReset;
>    CHAR16                    CapsuleVarName[30];
>    CHAR16                    *TempVarName;
>
> +  //
> +  // Check if platform support Capsule In RAM or not.
> +  // Platform could choose to drop CapsulePei/CapsuleX64 and do not
> support Capsule In RAM.
> +  //
> +  if (!PcdGetBool(PcdCapsuleInRamSupport)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
>    //
>    // Capsule Count can't be less than one.
>    //
>    if (CapsuleCount < 1) {
>      return EFI_INVALID_PARAMETER;
> --
> 2.16.2.windows.1
>
>
> 

[-- Attachment #2: Type: text/html, Size: 39452 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  2019-06-19  0:59       ` Wu, Hao A
@ 2019-06-19  1:13         ` Zhang, Chao B
  2019-06-19  2:22           ` Wu, Hao A
  0 siblings, 1 reply; 33+ messages in thread
From: Zhang, Chao B @ 2019-06-19  1:13 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J

[-- Attachment #1: Type: text/plain, Size: 5561 bytes --]

Hi Hao:
   OK that is a good point. We will follow up to clean this. Tks

From: Wu, Hao A
Sent: Wednesday, June 19, 2019 9:00 AM
To: Zhang, Chao B <chao.b.zhang@intel.com>; devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

From: Zhang, Chao B
Sent: Wednesday, June 19, 2019 8:42 AM
To: Wu, Hao A; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Xu, Wei6
Cc: Wang, Jian J
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

Hi Hao:
  I think blocking UpdateCapsule interface is enough for Capsule in RAM.  QueryCapsuleCapabilities can still be used to test capsules before delivering by different sources.

Hello Chao,

I am okay with the usage update for the function.

But I think we need to update the comments for the QueryCapsuleCapabilities()
function within this driver and the 'EFI_QUERY_CAPSULE_CAPABILITIES' service for
EFI_RUNTIME_SERVICES to reflect the fact that even QueryCapsuleCapabilities()
returns without error, the capsule may still be unsupported by UpdateCapsule():

/**
  Returns if the capsule can be supported via UpdateCapsule().

  ...

**/

Best Regards,
Hao Wu


From: Wu, Hao A
Sent: Wednesday, June 12, 2019 3:49 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Xu, Wei6 <wei6.xu@intel.com<mailto:wei6.xu@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

> -----Original Message-----
> From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe:
> Introduce PCD to control this feature.
>
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
>
> Introduce PcdCapsuleInRamSupport to turn on/off Capsule In Ram feature.
> Platform could choose to drop CapsulePei/CapsuleX64 and not to support
> Capsule In Ram.


For this patch, it only affects UpdateCapsule(). Do we need to update the
behavior for QueryCapsuleCapabilities() as well?

Best Regards,
Hao Wu


>
> Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
> Cc: Chao B Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com<mailto:wei6.xu@intel.com>>
> ---
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf |  1
> +
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c      | 10
> +++++++++-
>  2 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> index 338577e293..9da450722b 100644
> ---
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> @@ -88,10 +88,11 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> CONSUMES
>
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ##
> SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ##
> SOMETIMES_CONSUMES # Populate Image requires reset support.
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ##
> CONSUMES
>
>  [Pcd.X64]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize
> ## SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ##
> SOMETIMES_CONSUMES
>
> diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> index aaf819c4c6..53a1af44e2 100644
> --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> @@ -2,11 +2,11 @@
>    Capsule Runtime Driver produces two UEFI capsule runtime services.
>    (UpdateCapsule, QueryCapsuleCapabilities)
>    It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>    the capsule runtime services are ready.
>
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
>
>  **/
>
>  #include "CapsuleService.h"
> @@ -69,10 +69,18 @@ UpdateCapsule (
>    BOOLEAN                   NeedReset;
>    BOOLEAN                   InitiateReset;
>    CHAR16                    CapsuleVarName[30];
>    CHAR16                    *TempVarName;
>
> +  //
> +  // Check if platform support Capsule In RAM or not.
> +  // Platform could choose to drop CapsulePei/CapsuleX64 and do not
> support Capsule In RAM.
> +  //
> +  if (!PcdGetBool(PcdCapsuleInRamSupport)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
>    //
>    // Capsule Count can't be less than one.
>    //
>    if (CapsuleCount < 1) {
>      return EFI_INVALID_PARAMETER;
> --
> 2.16.2.windows.1
>
>
> 

[-- Attachment #2: Type: text/html, Size: 19795 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.
  2019-06-19  1:13         ` Zhang, Chao B
@ 2019-06-19  2:22           ` Wu, Hao A
  0 siblings, 0 replies; 33+ messages in thread
From: Wu, Hao A @ 2019-06-19  2:22 UTC (permalink / raw)
  To: Zhang, Chao B, devel@edk2.groups.io, Xu, Wei6; +Cc: Wang, Jian J

[-- Attachment #1: Type: text/plain, Size: 6077 bytes --]

From: Zhang, Chao B
Sent: Wednesday, June 19, 2019 9:13 AM
To: Wu, Hao A; devel@edk2.groups.io; Xu, Wei6
Cc: Wang, Jian J
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

Hi Hao:
   OK that is a good point. We will follow up to clean this. Tks


Hello Chao,

I am not sure if the update still applies to the UEFI spec with regard to
the description for the QueryCapsuleCapabilities service of EFI_RUNTIME_SERVICES.

  IMO, I think it is fine, but it would be better to double confirm.

Best Regards,
Hao Wu


From: Wu, Hao A
Sent: Wednesday, June 19, 2019 9:00 AM
To: Zhang, Chao B <chao.b.zhang@intel.com>; devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

From: Zhang, Chao B
Sent: Wednesday, June 19, 2019 8:42 AM
To: Wu, Hao A; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Xu, Wei6
Cc: Wang, Jian J
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

Hi Hao:
  I think blocking UpdateCapsule interface is enough for Capsule in RAM.  QueryCapsuleCapabilities can still be used to test capsules before delivering by different sources.

Hello Chao,

I am okay with the usage update for the function.

But I think we need to update the comments for the QueryCapsuleCapabilities()
function within this driver and the 'EFI_QUERY_CAPSULE_CAPABILITIES' service for
EFI_RUNTIME_SERVICES to reflect the fact that even QueryCapsuleCapabilities()
returns without error, the capsule may still be unsupported by UpdateCapsule():

/**
  Returns if the capsule can be supported via UpdateCapsule().

  ...

**/

Best Regards,
Hao Wu


From: Wu, Hao A
Sent: Wednesday, June 12, 2019 3:49 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Xu, Wei6 <wei6.xu@intel.com<mailto:wei6.xu@intel.com>>
Cc: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
Subject: RE: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature.

> -----Original Message-----
> From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> [mailto:devel@edk2.groups.io] On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 05, 2019 11:42 PM
> To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
> Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> Subject: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe:
> Introduce PCD to control this feature.
>
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
>
> Introduce PcdCapsuleInRamSupport to turn on/off Capsule In Ram feature.
> Platform could choose to drop CapsulePei/CapsuleX64 and not to support
> Capsule In Ram.


For this patch, it only affects UpdateCapsule(). Do we need to update the
behavior for QueryCapsuleCapabilities() as well?

Best Regards,
Hao Wu


>
> Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
> Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
> Cc: Chao B Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com<mailto:wei6.xu@intel.com>>
> ---
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf |  1
> +
>  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c      | 10
> +++++++++-
>  2 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> index 338577e293..9da450722b 100644
> ---
> a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> @@ -88,10 +88,11 @@
>    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ##
> CONSUMES
>
>  [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ##
> SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ##
> SOMETIMES_CONSUMES # Populate Image requires reset support.
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ##
> CONSUMES
>
>  [Pcd.X64]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize
> ## SOMETIMES_CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ##
> SOMETIMES_CONSUMES
>
> diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> index aaf819c4c6..53a1af44e2 100644
> --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
> @@ -2,11 +2,11 @@
>    Capsule Runtime Driver produces two UEFI capsule runtime services.
>    (UpdateCapsule, QueryCapsuleCapabilities)
>    It installs the Capsule Architectural Protocol defined in PI1.0a to signify
>    the capsule runtime services are ready.
>
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
>
>  **/
>
>  #include "CapsuleService.h"
> @@ -69,10 +69,18 @@ UpdateCapsule (
>    BOOLEAN                   NeedReset;
>    BOOLEAN                   InitiateReset;
>    CHAR16                    CapsuleVarName[30];
>    CHAR16                    *TempVarName;
>
> +  //
> +  // Check if platform support Capsule In RAM or not.
> +  // Platform could choose to drop CapsulePei/CapsuleX64 and do not
> support Capsule In RAM.
> +  //
> +  if (!PcdGetBool(PcdCapsuleInRamSupport)) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
>    //
>    // Capsule Count can't be less than one.
>    //
>    if (CapsuleCount < 1) {
>      return EFI_INVALID_PARAMETER;
> --
> 2.16.2.windows.1
>
>
> 

[-- Attachment #2: Type: text/html, Size: 43679 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.
  2019-06-12  7:49   ` Wu, Hao A
@ 2019-06-19  7:55     ` Xu, Wei6
  2019-06-19  8:16       ` Wu, Hao A
  0 siblings, 1 reply; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-19  7:55 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io; +Cc: Wang, Jian J, Zhang, Chao B

Thanks a lot for the comments. 
Please find my answer bellow.


> -----Original Message-----
> From: Wu, Hao A
> Sent: Wednesday, June 12, 2019 3:50 PM
> To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: RE: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On
> Disk APIs into CapsuleLib.
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Xu,
> > Wei6
> > Sent: Wednesday, June 05, 2019 11:42 PM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> > Subject: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk
> > APIs into CapsuleLib.
> 
> 
> Not directly related with this patch, I saw many function declarations
> within .C file for this library. Could you help to propose another series
> to add header files to address this (Maybe like the case in
> MdeModulePkg/Universal/Variable/RuntimeDxe to handle multi-phases).
> 

Sure, I will work on it after this patch is done.

> 
> Some general level comments:
> 
> I saw some of the new functions whose scope is limited within a single
> file have been decorated with keyword 'STATIC'. Could you help to make it
> consistent for all the newly added global variables/functions? Also, could
> you help to use keyword 'static' (lower case) instead?
> 

I will update all 'STATIC' to 'static'.

> 
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> >
> > CoDCheckCapsuleOnDiskFlag() is to check if CapsuleOnDisk flag in
> > "OsIndications" Variable is enabled. It is used to indicate whether
> > capsule on disk is provisioned in normal boot path.
> >
> > CoDClearCapsuleOnDiskFlag() is to to clear CapsuleOnDisk flags,
> > including "OsIndications" and "BootNext" variable.
> >
> > CoDRelocateCapsule() is to relocate the capsules from EFI system
> > partition. Depends on PcdCapsuleInRamSupport, there are two solutions
> > to relocate the capsule on disk images:
> > When Capsule In Ram is supported, the Capsule On Disk images are
> > relocated into memory, and call UpdateCapsule() service to deliver
> > the capsules.
> > When Capsule In Ram is not supported, the Capsule On Disk images are
> > relocated into a temp file which will be stored in root directory on
> > a platform specific storage device. CapsuleOnDiskLoadPei PEIM will
> > retrieve the capsules from the relocation temp file and report
> > capsule hobs for them.
> >
> > CoDRemoveTempFile() is to remove the relocation temp file in the next
> > boot after capsules are processed.
> >
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Chao B Zhang <chao.b.zhang@intel.com>
> > Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> > ---
> >  MdeModulePkg/Include/Library/CapsuleLib.h          |   94 +-
> >  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c       | 1983
> > ++++++++++++++++++++
> >  .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h       |   63 +
> >  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c       |   56 +-
> >  .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf     |   21 +-
> >  .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c        |  121 +-
> >  .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c |   67 +-
> >  .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf      |    3 +-
> >  .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c  |   85 +-
> >  9 files changed, 2466 insertions(+), 27 deletions(-)
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
> >  create mode 100644
> > MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> >
> > diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h
> > b/MdeModulePkg/Include/Library/CapsuleLib.h
> > index 1fc2fba3a2..f3cb17cbf9 100644
> > --- a/MdeModulePkg/Include/Library/CapsuleLib.h
> > +++ b/MdeModulePkg/Include/Library/CapsuleLib.h
> > @@ -1,17 +1,37 @@
> >  /** @file
> >
> >    This library class defines a set of interfaces for how to process capsule
> > image updates.
> >
> > -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
> >  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> >
> >  #ifndef __CAPSULE_LIB_H__
> >  #define __CAPSULE_LIB_H__
> >
> > +#include <Guid/FileInfo.h>
> > +
> > +
> > +typedef struct {
> > +  //
> > +  // image address.
> > +  //
> > +  VOID             *ImageAddress;
> > +  //
> > +  // The file info of the image comes from.
> > +  //  if FileInfo == NULL. means image does not come from file
> > +  //
> > +  EFI_FILE_INFO    *FileInfo;
> > +} IMAGE_INFO;
> 
> 
> Will this 'IMAGE_INFO' structure (FileInfo.h include as well) be used by
> the consumer of CapsuleLib? For this series, this one is only used within
> DxeCapsuleLibFmp (implementation of CapsuleLib).
> 
> If it is only used internally, I suggest to move the definition into
> MdeModulePkg\Library\DxeCapsuleLibFmp\CapsuleOnDisk.h.
> 
> 
> > +
> > +//
> > +// BOOLEAN Variable to save the total size of all Capsule On Disk during
> > relocation
> > +//
> 
> 
> The above description comment seems not matching the usage of the
> variable
> perfectly. Looks to me the variable is used to reflect whether the system
> is in the capsule on disk state rather than the size information.
> 
> 
> > +#define COD_RELOCATION_INFO_VAR_NAME   L"CodRelocationInfo"
> > +
> >  /**
> >    The firmware checks whether the capsule image is supported
> >    by the CapsuleGuid in CapsuleHeader or if there is other specific
> > information in
> >    the capsule image.
> >
> > @@ -79,6 +99,78 @@ EFI_STATUS
> >  EFIAPI
> >  ProcessCapsules (
> >    VOID
> >    );
> >
> > +/**
> > +  This routine is called to check if CapsuleOnDisk flag in OsIndications
> > Variable
> > +  is enabled.
> > +
> > +  @retval TRUE     Flag is enabled
> > +  @retval FALSE    Flag is not enabled
> > +
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +CoDCheckCapsuleOnDiskFlag(
> > +  VOID
> > +  );
> > +
> > +
> > +/**
> > +  This routine is called to clear CapsuleOnDisk flags including OsIndications
> > and BootNext variable
> > +
> > +  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDClearCapsuleOnDiskFlag(
> > +  VOID
> > +  );
> > +
> > +/**
> > +  Relocate Capsule on Disk from EFI system partition.
> > +
> > +  Two solution to deliver Capsule On Disk:
> > +  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On
> > Disk to memory and call UpdateCapsule().
> > +  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On
> > Disk to a platform-specific NV storage
> > +  device with BlockIo protocol.
> > +
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  Side Effects:
> > +    Capsule Delivery Supported Flag in OsIndication variable and BootNext
> > variable will be cleared.
> > +    Solution B: Content corruption. Block IO write directly touches low level
> > write. Orignal partitions, file
> > +  systems of the relocation device will be corrupted.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> 
> 
> For me, it would be better to explicitly mention the behavior for
> 'MaxRetry' with the value 0. Judging from the implementation, 0 means no
> retry.
> 
> Similar case for API CoDRemoveTempFile() as well.
> 
> > +
> > +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
> 
> 
> sucessfully -> successfully
> Please help to update this typo in library instances as well.
> 
> 
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDRelocateCapsule(
> > +  UINTN     MaxRetry
> > +  );
> > +
> > +/**
> > +  Remove the temp file from the root of EFI System Partition.
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +
> > +  @retval EFI_SUCCESS   Remove the temp file successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDRemoveTempFile (
> > +  UINTN    MaxRetry
> > +  );
> > +
> >  #endif
> > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
> > new file mode 100644
> > index 0000000000..5f1edbbbae
> > --- /dev/null
> > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c
> > @@ -0,0 +1,1983 @@
> > +/** @file
> > +  The implementation supports Capusle on Disk.
> > +
> > +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "CapsuleOnDisk.h"
> > +
> > +/**
> > +  Return if this capsule is a capsule name capsule, based upon
> > CapsuleHeader.
> > +
> > +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> > +
> > +  @retval TRUE  It is a capsule name capsule.
> > +  @retval FALSE It is not a capsule name capsule.
> > +**/
> > +BOOLEAN
> > +IsCapsuleNameCapsule (
> > +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> > +  );
> > +
> > +/**
> > +  Check the integrity of the capsule name capsule.
> > +  If the capsule is vaild, return the physical address of each capsule name
> > string.
> > +
> > +  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule
> > name capsule.
> > +  @param[out] CapsuleNameNum  Number of capsule name.
> > +
> > +  @retval NULL                Capsule name capsule is not valid.
> > +  @retval CapsuleNameBuf      Array of capsule name physical address.
> > +
> > +**/
> > +EFI_PHYSICAL_ADDRESS *
> > +ValidateCapsuleNameCapsuleIntegrity (
> > +  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,
> > +  OUT UINTN                         *CapsuleNameNum
> > +  )
> > +{
> > +  UINT8                    *CapsuleNamePtr;
> > +  UINT8                    *CapsuleNameBufStart;
> > +  UINT8                    *CapsuleNameBufEnd;
> > +  UINTN                    Index;
> > +  UINTN                    StringSize;
> > +  EFI_PHYSICAL_ADDRESS     *CapsuleNameBuf;
> > +
> > +  if (!IsCapsuleNameCapsule (CapsuleHeader)) {
> > +    return NULL;
> > +  }
> > +
> > +  //
> > +  // Total string size must be even.
> > +  //
> > +  if (((CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize)
> &
> > BIT0) != 0) {
> > +    return NULL;
> > +  }
> > +
> > +  *CapsuleNameNum = 0;
> > +  Index = 0;
> > +  CapsuleNameBufStart = (UINT8 *) CapsuleHeader + CapsuleHeader-
> > >HeaderSize;
> > +
> > +  //
> > +  // If strings are not aligned on a 16-bit boundary, reallocate memory for it.
> > +  //
> > +  if (((UINTN) CapsuleNameBufStart & BIT0) != 0) {
> > +    CapsuleNameBufStart = AllocateCopyPool (CapsuleHeader-
> > >CapsuleImageSize - CapsuleHeader->HeaderSize, CapsuleNameBufStart);
> > +  }
> > +
> > +  CapsuleNameBufEnd = CapsuleNameBufStart + CapsuleHeader-
> > >CapsuleImageSize - CapsuleHeader->HeaderSize;
> > +
> > +  CapsuleNamePtr = CapsuleNameBufStart;
> > +  while (CapsuleNamePtr < CapsuleNameBufEnd) {
> > +    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr,
> (CapsuleNameBufEnd
> > - CapsuleNamePtr)/sizeof(CHAR16));
> > +    CapsuleNamePtr += StringSize;
> > +    (*CapsuleNameNum) ++;
> > +  }
> > +
> > +  //
> > +  // Integrity check.
> > +  //
> > +  if (CapsuleNamePtr != CapsuleNameBufEnd) {
> > +    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader-
> > >HeaderSize) {
> > +      FreePool (CapsuleNameBufStart);
> > +    }
> > +    return NULL;
> > +  }
> > +
> > +  CapsuleNameBuf = AllocatePool (*CapsuleNameNum * sizeof
> > (EFI_PHYSICAL_ADDRESS));
> > +  if (CapsuleNameBuf == NULL) {
> > +    if (CapsuleNameBufStart != (UINT8 *)CapsuleHeader + CapsuleHeader-
> > >HeaderSize) {
> > +      FreePool (CapsuleNameBufStart);
> > +    }
> > +    return NULL;
> > +  }
> > +
> > +  CapsuleNamePtr = CapsuleNameBufStart;
> > +  while (CapsuleNamePtr < CapsuleNameBufEnd) {
> > +    StringSize= StrnSizeS ((CHAR16 *) CapsuleNamePtr,
> (CapsuleNameBufEnd
> > - CapsuleNamePtr)/sizeof(CHAR16));
> > +    CapsuleNameBuf[Index] = (EFI_PHYSICAL_ADDRESS)(UINTN)
> > CapsuleNamePtr;
> > +    CapsuleNamePtr += StringSize;
> > +    Index ++;
> > +  }
> > +
> > +  return CapsuleNameBuf;
> > +}
> > +
> > +/**
> > +  This routine is called to upper case given unicode string.
> > +
> > +  @param[in]   Str              String to upper case
> > +
> > +  @retval upper cased string after process
> > +
> > +**/
> > +STATIC
> > +CHAR16 *
> > +UpperCaseString (
> > +  IN CHAR16 *Str
> > +  )
> > +{
> > +  CHAR16  *Cptr;
> > +
> > +  for (Cptr = Str; *Cptr; Cptr++) {
> > +    if (L'a' <= *Cptr && *Cptr <= L'z') {
> > +      *Cptr = *Cptr - L'a' + L'A';
> > +    }
> > +  }
> > +
> > +  return Str;
> > +}
> > +
> > +/**
> > +  This routine is used to return substring before period '.' or '\0'
> > +  Caller should respsonsible of substr space allocation & free
> > +
> > +  @param[in]   Str              String to check
> > +  @param[out]  SubStr           First part of string before period or '\0'
> > +  @param[out]  SubStrLen        Length of first part of string
> > +
> > +**/
> > +STATIC
> > +VOID
> > +GetSubStringBeforePeriod (
> > +  IN  CHAR16 *Str,
> > +  OUT CHAR16 *SubStr,
> > +  OUT UINTN  *SubStrLen
> > +  )
> > +{
> > +  UINTN Index;
> > +  for (Index = 0; Str[Index] != L'.' && Str[Index] != L'\0'; Index++) {
> > +    SubStr[Index] = Str[Index];
> > +  }
> > +
> > +  SubStr[Index] = L'\0';
> > +  *SubStrLen = Index;
> > +}
> > +
> > +/**
> > +  This routine pad the string in tail with input character.
> > +
> > +  @param[in]   StrBuf            Str buffer to be padded, should be enough
> room
> > for
> > +  @param[in]   PadLen            Expected padding length
> > +  @param[in]   Character         Character used to pad
> > +
> > +**/
> > +STATIC
> > +VOID
> > +PadStrInTail (
> > +  IN CHAR16   *StrBuf,
> > +  IN UINTN    PadLen,
> > +  IN CHAR16   Character
> > +  )
> > +{
> > +  UINTN Index;
> > +
> > +  for (Index = 0; StrBuf[Index] != L'\0'; Index++);
> > +
> > +  while(PadLen != 0) {
> > +    StrBuf[Index] = Character;
> > +    Index++;
> > +    PadLen--;
> > +  }
> > +
> > +  StrBuf[Index] = L'\0';
> > +}
> > +
> > +/**
> > +  This routine find the offset of the last period '.' of string. If No period
> exists
> > +  function FileNameExtension is set to L'\0'
> > +
> > +  @param[in]  FileName           File name to split between last period
> > +  @param[out] FileNameFirst      First FileName before last period
> > +  @param[out] FileNameExtension  FileName after last period
> > +
> > +**/
> > +STATIC
> > +VOID
> > +SplitFileNameExtension (
> > +  IN CHAR16   *FileName,
> > +  OUT CHAR16  *FileNameFirst,
> > +  OUT CHAR16  *FileNameExtension
> > +  )
> > +{
> > +  UINTN Index;
> > +  UINTN StringLen;
> > +
> > +  StringLen = StrnLenS(FileName, MAX_FILE_NAME_SIZE);
> > +  for (Index = StringLen; Index > 0 && FileName[Index] != L'.'; Index--);
> > +
> > +  //
> > +  // No period exists. No FileName Extension
> > +  //
> > +  if (Index == 0 && FileName[Index] != L'.') {
> > +    FileNameExtension[0] = L'\0';
> > +    Index = StringLen;
> > +  } else {
> > +    StrCpyS(FileNameExtension, MAX_FILE_NAME_SIZE,
> > &FileName[Index+1]);
> > +  }
> > +
> > +  //
> > +  // Copy First file name
> > +  //
> > +  StrnCpyS(FileNameFirst, MAX_FILE_NAME_SIZE, FileName, Index);
> > +  FileNameFirst[Index] = L'\0';
> > +}
> > +
> > +/**
> > +  This routine is called to get all boot options in the order determnined by:
> > +    1. "OptionBuf"
> > +    2. "BootOrder"
> > +
> > +  @param[out] OptionBuf           BootList buffer to all boot options returned
> > +  @param[out] OptionCount         BootList count of all boot options
> returned
> > +
> > +  @retval EFI_SUCCESS             There is no error when processing capsule
> > +
> > +**/
> > +EFI_STATUS
> > +GetBootOptionInOrder(
> > +  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf,
> > +  OUT UINTN                        *OptionCount
> > +  )
> > +{
> > +  EFI_STATUS                   Status;
> > +  UINTN                        DataSize;
> > +  UINT16                       BootNext;
> > +  CHAR16                       BootOptionName[20];
> > +  EFI_BOOT_MANAGER_LOAD_OPTION *BootOrderOptionBuf;
> > +  UINTN                        BootOrderCount;
> > +  EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry;
> > +  UINTN                        BootNextCount;
> > +  EFI_BOOT_MANAGER_LOAD_OPTION *TempBuf;
> > +
> > +  BootOrderOptionBuf  = NULL;
> > +  TempBuf             = NULL;
> > +  BootNextCount       = 0;
> > +  BootOrderCount      = 0;
> > +  *OptionBuf          = NULL;
> > +  *OptionCount        = 0;
> > +
> > +  //
> > +  // First Get BootOption from "BootNext"
> > +  //
> > +  DataSize = sizeof(BootNext);
> > +  Status = gRT->GetVariable (
> > +                  EFI_BOOT_NEXT_VARIABLE_NAME,
> > +                  &gEfiGlobalVariableGuid,
> > +                  NULL,
> > +                  &DataSize,
> > +                  (VOID *)&BootNext
> > +                  );
> > +  //
> > +  // BootNext variable is a single UINT16
> > +  //
> > +  if (!EFI_ERROR(Status) && DataSize == sizeof(UINT16)) {
> > +    //
> > +    // Add the boot next boot option
> > +    //
> > +    UnicodeSPrint (BootOptionName, sizeof (BootOptionName),
> > L"Boot%04x", BootNext);
> > +    ZeroMem(&BootNextOptionEntry,
> > sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
> > +    Status = EfiBootManagerVariableToLoadOption (BootOptionName,
> > &BootNextOptionEntry);
> > +
> > +    if (!EFI_ERROR(Status)) {
> > +      BootNextCount = 1;
> > +    }
> > +  }
> > +
> > +  //
> > +  // Second get BootOption from "BootOrder"
> > +  //
> > +  BootOrderOptionBuf = EfiBootManagerGetLoadOptions
> > (&BootOrderCount, LoadOptionTypeBoot);
> > +  if (BootNextCount == 0 && BootOrderCount == 0) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  //
> > +  // At least one BootOption is found
> > +  //
> > +  TempBuf = AllocatePool(sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) *
> > (BootNextCount + BootOrderCount));
> > +  if (TempBuf != NULL) {
> > +    if (BootNextCount == 1) {
> > +      CopyMem(TempBuf, &BootNextOptionEntry,
> > sizeof(EFI_BOOT_MANAGER_LOAD_OPTION));
> > +    }
> > +
> > +    if (BootOrderCount > 0) {
> > +      CopyMem(TempBuf + BootNextCount, BootOrderOptionBuf,
> > sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * BootOrderCount);
> > +    }
> > +
> > +    *OptionBuf   = TempBuf;
> > +    *OptionCount = BootNextCount + BootOrderCount;
> > +    Status = EFI_SUCCESS;
> > +  } else {
> > +    Status = EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  FreePool(BootOrderOptionBuf);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  This routine is called to get boot option by OptionNumber.
> > +
> > +  @param[in] Number               The OptionNumber of boot option
> > +  @param[out] OptionBuf           BootList buffer to all boot options returned
> > +
> > +  @retval EFI_SUCCESS             There is no error when getting boot option
> > +
> > +**/
> > +EFI_STATUS
> > +GetBootOptionByNumber(
> > +  IN  UINT16                       Number,
> > +  OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf
> > +  )
> > +{
> > +  EFI_STATUS                    Status;
> > +  CHAR16                        BootOptionName[20];
> > +  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
> > +
> > +  UnicodeSPrint (BootOptionName, sizeof (BootOptionName),
> L"Boot%04x",
> > Number);
> > +  ZeroMem (&BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION));
> > +  Status = EfiBootManagerVariableToLoadOption (BootOptionName,
> > &BootOption);
> > +
> > +  if (!EFI_ERROR (Status)) {
> > +    *OptionBuf = AllocatePool (sizeof
> > (EFI_BOOT_MANAGER_LOAD_OPTION));
> > +    CopyMem (*OptionBuf, &BootOption, sizeof
> > (EFI_BOOT_MANAGER_LOAD_OPTION));
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Get Active EFI System Partition within GPT based on device path.
> > +
> > +  @param[in] DevicePath    Device path to find a active EFI System Partition
> > +  @param[out] FsHandle     BootList points to all boot options returned
> > +
> > +  @retval EFI_SUCCESS      Active EFI System Partition is succesfully found
> > +  @retval EFI_NOT_FOUND    No Active EFI System Partition is found
> > +
> > +**/
> > +EFI_STATUS
> > +GetEfiSysPartitionFromDevPath(
> > +  IN EFI_DEVICE_PATH_PROTOCOL         *DevicePath,
> > +  OUT EFI_HANDLE                      *FsHandle
> > +  )
> > +{
> > +  EFI_STATUS                      Status;
> > +  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
> > +  HARDDRIVE_DEVICE_PATH           *Hd;
> > +  EFI_HANDLE                      Handle;
> > +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
> > +
> > +  //
> > +  // Check if the device path contains GPT node
> > +  //
> > +  TempDevicePath = DevicePath;
> > +  while (!IsDevicePathEnd (TempDevicePath)) {
> > +    if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
> > +       (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP))
> {
> > +      Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
> > +      if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
> > +        break;
> > +      }
> > +    }
> > +    TempDevicePath = NextDevicePathNode (TempDevicePath);
> > +  }
> > +
> > +  if (!IsDevicePathEnd (TempDevicePath)) {
> > +    //
> > +    // Search for EFI system partition protocol on full device path in Boot
> > Option
> > +    //
> > +    Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid,
> > &DevicePath, &Handle);
> > +
> > +    //
> > +    // Search for simple file system on this handler
> > +    //
> > +    if (!EFI_ERROR(Status)) {
> > +      Status = gBS->HandleProtocol(Handle,
> > &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
> > +      if (!EFI_ERROR(Status)) {
> > +        *FsHandle = Handle;
> > +        return EFI_SUCCESS;
> > +      }
> > +    }
> > +  }
> > +
> > +  return EFI_NOT_FOUND;
> > +}
> > +
> > +/**
> > +  This routine is called to get Simple File System protocol on the first EFI
> > system partition found in
> > +  active boot option. The boot option list is detemined in order by
> > +    1. "BootNext"
> > +    2. "BootOrder"
> > +
> > +  @param[in]       MaxRetry           Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                      device like USB can get enumerated.
> > +  @param[in, out]  LoadOptionNumber   On input, specify the boot option
> to
> > get EFI system partition.
> > +                                      On output, return the OptionNumber of the boot
> option
> > where EFI
> > +                                      system partition is got from.
> > +  @param[out]      FsFsHandle         Simple File System Protocol found on
> first
> > active EFI system partition
> > +
> > +  @retval EFI_SUCCESS     Simple File System protocol found for EFI system
> > partition
> > +  @retval EFI_NOT_FOUND   No Simple File System protocol found for EFI
> > system partition
> > +
> > +**/
> > +EFI_STATUS
> > +GetEfiSysPartitionFromActiveBootOption(
> > +  IN UINTN                             MaxRetry,
> > +  IN OUT UINT16                        **LoadOptionNumber,
> > +  OUT EFI_HANDLE                       *FsHandle
> > +  )
> > +{
> > +  EFI_STATUS                   Status;
> > +  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuf;
> > +  UINTN                        BootOptionNum;
> > +  UINTN                        Index;
> > +  EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
> > +  EFI_DEVICE_PATH_PROTOCOL     *CurFullPath;
> > +  EFI_DEVICE_PATH_PROTOCOL     *PreFullPath;
> > +
> > +  *FsHandle = NULL;
> > +
> > +  if (*LoadOptionNumber != NULL) {
> > +    BootOptionNum = 1;
> > +    Status = GetBootOptionByNumber(**LoadOptionNumber,
> > &BootOptionBuf);
> > +    if (EFI_ERROR(Status)) {
> > +      DEBUG ((DEBUG_ERROR, "GetBootOptionByIndex Failed %x! No
> > BootOption available for connection\n", Status));
> > +      return Status;
> > +    }
> > +  } else {
> > +    Status = GetBootOptionInOrder(&BootOptionBuf, &BootOptionNum);
> > +    if (EFI_ERROR(Status)) {
> > +      DEBUG ((DEBUG_ERROR, "GetBootOptionInOrder Failed %x! No
> > BootOption available for connection\n", Status));
> > +      return Status;
> > +    }
> > +  }
> > +
> > +  //
> > +  // Search BootOptionList to check if it is an active boot option with EFI
> > system partition
> > +  //  1. Connect device path
> > +  //  2. expend short/plug in devicepath
> > +  //  3. LoadImage
> > +  //
> > +  for (Index = 0; Index < BootOptionNum; Index++) {
> > +    //
> > +    // Get the boot option from the link list
> > +    //
> > +    DevicePath  = BootOptionBuf[Index].FilePath;
> > +
> > +    //
> > +    // Skip inactive or legacy boot options
> > +    //
> > +    if ((BootOptionBuf[Index].Attributes & LOAD_OPTION_ACTIVE) == 0 ||
> > +        DevicePathType (DevicePath) == BBS_DEVICE_PATH) {
> > +      continue;
> > +    }
> > +
> > +    DEBUG_CODE (
> > +      CHAR16 *DevicePathStr;
> > +
> > +      DevicePathStr = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
> > +      if (DevicePathStr != NULL){
> > +        DEBUG((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr));
> > +        FreePool(DevicePathStr);
> > +      } else {
> > +        DEBUG((DEBUG_INFO, "DevicePathToStr failed\n"));
> > +      }
> > +    );
> > +
> > +    CurFullPath = NULL;
> > +    //
> > +    // Try every full device Path generated from bootoption
> > +    //
> > +    do {
> > +      PreFullPath = CurFullPath;
> > +      CurFullPath =
> > EfiBootManagerGetNextLoadOptionDevicePath(DevicePath, CurFullPath);
> > +
> > +      if (PreFullPath != NULL) {
> > +        FreePool (PreFullPath);
> > +      }
> > +
> > +      if (CurFullPath == NULL) {
> > +        //
> > +        // No Active EFI system partition is found in BootOption device path
> > +        //
> > +        Status = EFI_NOT_FOUND;
> > +        break;
> > +      }
> > +
> > +      DEBUG_CODE (
> > +        CHAR16 *DevicePathStr1;
> > +
> > +        DevicePathStr1 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);
> > +        if (DevicePathStr1 != NULL){
> > +          DEBUG((DEBUG_INFO, "Full device path %s\n", DevicePathStr1));
> > +          FreePool(DevicePathStr1);
> > +        }
> > +      );
> > +
> > +      //
> > +      // Make sure the boot option device path connected.
> > +      // Only handle first device in boot option. Other optional device paths
> > are described as OSV specific
> > +      // FullDevice could contain extra directory & file info. So don't check
> > connection status here.
> > +      //
> > +      EfiBootManagerConnectDevicePath (CurFullPath, NULL);
> > +      Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);
> > +
> > +      //
> > +      // Some relocation device like USB need more time to get enumerated
> > +      //
> > +      while (EFI_ERROR(Status) && MaxRetry > 0) {
> > +        EfiBootManagerConnectDevicePath(CurFullPath, NULL);
> > +
> > +        //
> > +        // Search for EFI system partition protocol on full device path in Boot
> > Option
> > +        //
> > +        Status = GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle);
> > +        if (!EFI_ERROR(Status)) {
> > +          break;
> > +        }
> > +        DEBUG((DEBUG_ERROR, "GetEfiSysPartitionFromDevPath
> Loop %x\n",
> > Status));
> > +        //
> > +        // Stall 100ms if connection failed to ensure USB stack is ready
> > +        //
> > +        gBS->Stall(100000);
> > +        MaxRetry --;
> > +      }
> > +    } while(EFI_ERROR(Status));
> > +
> > +    //
> > +    // Find a qualified Simple File System
> > +    //
> > +    if (!EFI_ERROR(Status)) {
> > +      break;
> > +    }
> > +
> > +  }
> > +
> > +  //
> > +  // Return the OptionNumber of the boot option where EFI system
> > partition is got from
> > +  //
> > +  if (*LoadOptionNumber == NULL) {
> > +    *LoadOptionNumber = AllocateCopyPool (sizeof(UINT16), (UINT16 *)
> > &BootOptionBuf[Index].OptionNumber);
> > +  }
> > +
> > +  //
> > +  // No qualified EFI system partition found
> > +  //
> > +  if (*FsHandle == NULL) {
> > +    Status = EFI_NOT_FOUND;
> > +  }
> > +
> > +  DEBUG_CODE (
> > +    CHAR16 *DevicePathStr2;
> > +    if (*FsHandle != NULL) {
> > +      DevicePathStr2 = ConvertDevicePathToText(CurFullPath, TRUE, TRUE);
> > +      if (DevicePathStr2 != NULL){
> > +        DEBUG((DEBUG_INFO, "Found Active EFI System Partion on %s\n",
> > DevicePathStr2));
> > +        FreePool(DevicePathStr2);
> > +      }
> > +    } else {
> > +      DEBUG((DEBUG_INFO, "Failed to found Active EFI System Partion\n"));
> > +    }
> > +  );
> > +
> > +  if (CurFullPath != NULL) {
> > +    FreePool(CurFullPath);
> > +  }
> > +
> > +  //
> > +  // Free BootOption Buffer
> > +  //
> > +  for (Index = 0; Index < BootOptionNum; Index++) {
> > +    if (BootOptionBuf[Index].Description != NULL) {
> > +      FreePool(BootOptionBuf[Index].Description);
> > +    }
> > +
> > +    if (BootOptionBuf[Index].FilePath != NULL) {
> > +      FreePool(BootOptionBuf[Index].FilePath);
> > +    }
> > +
> > +    if (BootOptionBuf[Index].OptionalData != NULL) {
> > +      FreePool(BootOptionBuf[Index].OptionalData);
> > +    }
> > +  }
> > +
> > +  FreePool(BootOptionBuf);
> > +
> > +  return Status;
> > +}
> > +
> > +
> > +/**
> > +  This routine is called to get all file infos with in a given dir & with given file
> > attribute, the file info is listed in
> > +  alphabetical order described in UEFI spec.
> > +
> > +  @param[in]  Dir                 Directory file handler
> > +  @param[in]  FileAttr            Attribute of file to be red from directory
> > +  @param[out] FileInfoList        File images info list red from directory
> > +  @param[out] FileNum             File images number red from directory
> > +
> > +  @retval EFI_SUCCESS             File FileInfo list in the given
> > +
> > +**/
> > +EFI_STATUS
> > +GetFileInfoListInAlphabetFromDir(
> > +  IN EFI_FILE_HANDLE  Dir,
> > +  IN UINT64           FileAttr,
> > +  OUT LIST_ENTRY      *FileInfoList,
> > +  OUT UINTN           *FileNum
> > +  )
> > +{
> > +  EFI_STATUS        Status;
> > +  FILE_INFO_ENTRY   *NewFileInfoEntry;
> > +  FILE_INFO_ENTRY   *TempFileInfoEntry;
> > +  EFI_FILE_INFO     *FileInfo;
> > +  CHAR16            *NewFileName;
> > +  CHAR16            *ListedFileName;
> > +  CHAR16            *NewFileNameExtension;
> > +  CHAR16            *ListedFileNameExtension;
> > +  CHAR16            *TempNewSubStr;
> > +  CHAR16            *TempListedSubStr;
> > +  LIST_ENTRY        *Link;
> > +  BOOLEAN           NoFile;
> > +  UINTN             FileCount;
> > +  UINTN             IndexNew;
> > +  UINTN             IndexListed;
> > +  UINTN             NewSubStrLen;
> > +  UINTN             ListedSubStrLen;
> > +  INTN              SubStrCmpResult;
> > +
> > +  Status                  = EFI_SUCCESS;
> > +  NewFileName             = NULL;
> > +  ListedFileName          = NULL;
> > +  NewFileNameExtension    = NULL;
> > +  ListedFileNameExtension = NULL;
> > +  TempNewSubStr           = NULL;
> > +  TempListedSubStr        = NULL;
> > +  NoFile                  = FALSE;
> > +  FileCount               = 0;
> > +
> > +  InitializeListHead(FileInfoList);
> > +
> > +  TempNewSubStr           = (CHAR16 *)
> > AllocateZeroPool(MAX_FILE_NAME_SIZE);
> > +  TempListedSubStr        = (CHAR16 *)
> > AllocateZeroPool(MAX_FILE_NAME_SIZE);
> > +
> > +  if (TempNewSubStr == NULL || TempListedSubStr == NULL ) {
> > +    Status = EFI_OUT_OF_RESOURCES;
> > +    goto EXIT;
> > +  }
> > +
> > +  for ( Status = FileHandleFindFirstFile(Dir, &FileInfo)
> > +      ; !EFI_ERROR(Status) && !NoFile
> > +      ; Status = FileHandleFindNextFile(Dir, FileInfo, &NoFile)
> > +     ){
> > +
> > +    //
> > +    // Skip file with mismatching File attribute
> > +    //
> > +    if ((FileInfo->Attribute & (FileAttr)) == 0) {
> > +      continue;
> > +    }
> > +
> > +    NewFileInfoEntry = NULL;
> > +    NewFileInfoEntry =
> > (FILE_INFO_ENTRY*)AllocateZeroPool(sizeof(FILE_INFO_ENTRY));
> > +    if (NewFileInfoEntry == NULL) {
> > +      Status = EFI_OUT_OF_RESOURCES;
> > +      goto EXIT;
> > +    }
> > +    NewFileInfoEntry->Signature = FILE_INFO_SIGNATURE;
> > +    NewFileInfoEntry->FileInfo  = AllocateCopyPool((UINTN) FileInfo->Size,
> > FileInfo);
> > +    if (NewFileInfoEntry->FileInfo == NULL) {
> > +      FreePool(NewFileInfoEntry);
> > +      Status = EFI_OUT_OF_RESOURCES;
> > +      goto EXIT;
> > +    }
> > +
> > +    NewFileInfoEntry->FileNameFirstPart  = (CHAR16 *)
> > AllocateZeroPool(MAX_FILE_NAME_SIZE);
> > +    if (NewFileInfoEntry->FileNameFirstPart == NULL) {
> > +      FreePool(NewFileInfoEntry->FileInfo);
> > +      FreePool(NewFileInfoEntry);
> > +      Status = EFI_OUT_OF_RESOURCES;
> > +      goto EXIT;
> > +    }
> > +    NewFileInfoEntry->FileNameSecondPart = (CHAR16 *)
> > AllocateZeroPool(MAX_FILE_NAME_SIZE);
> > +    if (NewFileInfoEntry->FileNameSecondPart == NULL) {
> > +      FreePool(NewFileInfoEntry->FileInfo);
> > +      FreePool(NewFileInfoEntry->FileNameFirstPart);
> > +      FreePool(NewFileInfoEntry);
> > +      Status = EFI_OUT_OF_RESOURCES;
> > +      goto EXIT;
> > +    }
> > +
> > +    //
> > +    // Splitter the whole New file name into 2 parts between the last period
> > L'.' into NewFileName NewFileExtension
> > +    // If no period in the whole file name. NewFileExtension is set to L'\0'
> > +    //
> > +    NewFileName          = NewFileInfoEntry->FileNameFirstPart;
> > +    NewFileNameExtension = NewFileInfoEntry->FileNameSecondPart;
> > +    SplitFileNameExtension(FileInfo->FileName, NewFileName,
> > NewFileNameExtension);
> > +    UpperCaseString(NewFileName);
> > +    UpperCaseString(NewFileNameExtension);
> > +
> > +    //
> > +    // Insert capsule file in alphabetical ordered list
> > +    //
> > +    for (Link = FileInfoList->ForwardLink; Link != FileInfoList; Link = Link-
> > >ForwardLink) {
> > +      //
> > +      // Get the FileInfo from the link list
> > +      //
> > +      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> > FILE_INFO_SIGNATURE);
> > +      ListedFileName          = TempFileInfoEntry->FileNameFirstPart;
> > +      ListedFileNameExtension = TempFileInfoEntry->FileNameSecondPart;
> > +
> > +      //
> > +      // Follow rule in UEFI spec 8.5.5 to compare file name
> > +      //
> > +      IndexListed = 0;
> > +      IndexNew    = 0;
> > +      while (TRUE){
> > +        //
> > +        // First compare each substrings in NewFileName & ListedFileName
> > between periods
> > +        //
> > +        GetSubStringBeforePeriod(&NewFileName[IndexNew],
> > TempNewSubStr, &NewSubStrLen);
> > +        GetSubStringBeforePeriod(&ListedFileName[IndexListed],
> > TempListedSubStr, &ListedSubStrLen);
> > +        if (NewSubStrLen > ListedSubStrLen) {
> > +          //
> > +          // Substr in NewFileName is longer. Pad tail with SPACE
> > +          //
> > +          PadStrInTail(TempListedSubStr, NewSubStrLen - ListedSubStrLen, L'
> ');
> > +        } else if (NewSubStrLen < ListedSubStrLen){
> > +          //
> > +          // Substr in ListedFileName is longer. Pad tail with SPACE
> > +          //
> > +          PadStrInTail(TempNewSubStr, ListedSubStrLen - NewSubStrLen, L' ');
> > +        }
> > +
> > +        SubStrCmpResult = StrnCmp(TempNewSubStr, TempListedSubStr,
> > MAX_FILE_NAME_LEN);
> > +        if (SubStrCmpResult != 0) {
> > +          break;
> > +        }
> > +
> > +        //
> > +        // Move to skip this substring
> > +        //
> > +        IndexNew    += NewSubStrLen;
> > +        IndexListed += ListedSubStrLen;
> > +        //
> > +        // Reach File First Name end
> > +        //
> > +        if (NewFileName[IndexNew] == L'\0' || ListedFileName[IndexListed]
> ==
> > L'\0') {
> > +          break;
> > +        }
> > +
> > +        //
> > +        // Skip the period L'.'
> > +        //
> > +        IndexNew++;
> > +        IndexListed++;
> > +      }
> > +
> > +      if (SubStrCmpResult < 0) {
> > +        //
> > +        // NewFileName is smaller. Find the right place to insert New file
> > +        //
> > +        break;
> > +      } else if (SubStrCmpResult == 0) {
> > +        //
> > +        // 2 cases whole NewFileName is smaller than ListedFileName
> > +        //   1. if NewFileName == ListedFileName. Continue to compare
> > FileNameExtension
> > +        //   2. if NewFileName is shorter than ListedFileName
> > +        //
> > +        if (NewFileName[IndexNew] == L'\0') {
> > +          if (ListedFileName[IndexListed] != L'\0' ||
> > (StrnCmp(NewFileNameExtension, ListedFileNameExtension,
> > MAX_FILE_NAME_LEN) < 0)) {
> > +            break;
> > +          }
> > +        }
> > +      }
> > +
> > +      //
> > +      // Other case, ListedFileName is smaller. Continue to compare the next
> > file in the list
> > +      //
> > +    }
> > +
> > +    //
> > +    // If Find an entry in the list whose name is bigger than new FileInfo in
> > alphabet order
> > +    //    Insert it before this entry
> > +    // else
> > +    //    Insert at the tail of this list (Link = FileInfoList)
> > +    //
> > +    InsertTailList(Link, &NewFileInfoEntry->Link);
> > +
> > +    FileCount++;
> > +  }
> > +
> > +  *FileNum = FileCount;
> > +
> > +EXIT:
> > +
> > +  if (TempNewSubStr != NULL) {
> > +    FreePool(TempNewSubStr);
> > +  }
> > +
> > +  if (TempListedSubStr != NULL) {
> > +    FreePool(TempListedSubStr);
> > +  }
> > +
> > +  if (EFI_ERROR(Status)) {
> > +    while(!IsListEmpty(FileInfoList)) {
> > +      Link = FileInfoList->ForwardLink;
> > +      RemoveEntryList(Link);
> > +
> > +      TempFileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> > FILE_INFO_SIGNATURE);
> > +
> > +      FreePool(TempFileInfoEntry->FileInfo);
> > +      FreePool(TempFileInfoEntry->FileNameFirstPart);
> > +      FreePool(TempFileInfoEntry->FileNameSecondPart);
> > +      FreePool(TempFileInfoEntry);
> > +    }
> > +    *FileNum = 0;
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +
> > +/**
> > +  This routine is called to get all qualified image from file from an given
> > directory
> > +  in alphabetic order. All the file image is copied to allocated boottime
> > memory.
> > +  Caller should free these memory
> > +
> > +  @param[in]  Dir            Directory file handler
> > +  @param[in]  FileAttr       Attribute of file to be red from directory
> > +  @param[out] FilePtr        File images Info buffer red from directory
> > +  @param[out] FileNum        File images number red from directory
> > +
> > +  @retval EFI_SUCCESS  Succeed to get all capsules in alphabetic order.
> > +
> > +**/
> > +EFI_STATUS
> > +GetFileImageInAlphabetFromDir(
> > +  IN EFI_FILE_HANDLE   Dir,
> > +  IN UINT64            FileAttr,
> > +  OUT IMAGE_INFO       **FilePtr,
> > +  OUT UINTN            *FileNum
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  LIST_ENTRY            *Link;
> > +  EFI_FILE_HANDLE       FileHandle;
> > +  FILE_INFO_ENTRY       *FileInfoEntry;
> > +  EFI_FILE_INFO         *FileInfo;
> > +  UINTN                 FileCount;
> > +  IMAGE_INFO            *TempFilePtrBuf;
> > +  UINTN                 Size;
> > +  LIST_ENTRY            FileInfoList;
> > +
> > +  FileHandle       = NULL;
> > +  FileCount        = 0;
> > +  TempFilePtrBuf   = NULL;
> > +  *FilePtr         = NULL;
> > +
> > +  //
> > +  // Get file list in Dir in alphabetical order
> > +  //
> > +  Status = GetFileInfoListInAlphabetFromDir(
> > +             Dir,
> > +             FileAttr,
> > +             &FileInfoList,
> > +             &FileCount
> > +             );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir
> Failed!\n"));
> > +    goto EXIT;
> > +  }
> > +
> > +  if (FileCount == 0) {
> > +    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));
> > +    Status = EFI_NOT_FOUND;
> > +    goto EXIT;
> > +  }
> > +
> > +  TempFilePtrBuf = (IMAGE_INFO *)AllocateZeroPool(sizeof(IMAGE_INFO)
> > * FileCount);
> > +  if (TempFilePtrBuf == NULL) {
> > +    Status = EFI_OUT_OF_RESOURCES;
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // Read all files from FileInfoList to BS memory
> > +  //
> > +  FileCount = 0;
> > +  for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link-
> > >ForwardLink) {
> > +    //
> > +    // Get FileInfo from the link list
> > +    //
> > +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> FILE_INFO_SIGNATURE);
> > +    FileInfo      = FileInfoEntry->FileInfo;
> > +
> > +    Status = Dir->Open(
> > +                    Dir,
> > +                    &FileHandle,
> > +                    FileInfo->FileName,
> > +                    EFI_FILE_MODE_READ,
> > +                    0
> > +                    );
> > +    if (EFI_ERROR(Status)){
> > +      continue;
> > +    }
> > +
> > +    Size = (UINTN)FileInfo->FileSize;
> > +    TempFilePtrBuf[FileCount].ImageAddress = AllocateZeroPool(Size);
> > +    if (TempFilePtrBuf[FileCount].ImageAddress == NULL) {
> > +      DEBUG((DEBUG_ERROR, "Fail to allocate memory for capsule. Stop
> > processing the rest.\n"));
> > +      break;
> > +    }
> > +
> > +    Status = FileHandle->Read(
> > +                           FileHandle,
> > +                           &Size,
> > +                           TempFilePtrBuf[FileCount].ImageAddress
> > +                           );
> > +
> > +    FileHandle->Close(FileHandle);
> > +
> > +    //
> > +    // Skip read error file
> > +    //
> > +    if (EFI_ERROR(Status) || Size != (UINTN)FileInfo->FileSize) {
> > +      //
> > +      // Remove this error file info accordingly
> > +      // & move Link to BackLink
> > +      //
> > +      Link = RemoveEntryList(Link);
> > +      Link = Link->BackLink;
> > +
> > +      FreePool(FileInfoEntry->FileInfo);
> > +      FreePool(FileInfoEntry->FileNameFirstPart);
> > +      FreePool(FileInfoEntry->FileNameSecondPart);
> > +      FreePool(FileInfoEntry);
> > +
> > +      FreePool(TempFilePtrBuf[FileCount].ImageAddress);
> > +      TempFilePtrBuf[FileCount].ImageAddress = NULL;
> > +      TempFilePtrBuf[FileCount].FileInfo     = NULL;
> > +
> > +      continue;
> > +    }
> > +    TempFilePtrBuf[FileCount].FileInfo = FileInfo;
> > +    FileCount++;
> > +  }
> > +
> > +  DEBUG_CODE (
> > +    for (Link = FileInfoList.ForwardLink; Link != &FileInfoList; Link = Link-
> > >ForwardLink) {
> > +      FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> FILE_INFO_SIGNATURE);
> > +      FileInfo      = FileInfoEntry->FileInfo;
> > +      DEBUG((DEBUG_INFO, "Successfully read capsule file %s from disk.\n",
> > FileInfo->FileName));
> > +    }
> > +  );
> > +
> > +EXIT:
> > +
> > +  *FilePtr = TempFilePtrBuf;
> > +  *FileNum = FileCount;
> > +
> > +  //
> > +  // FileInfo will be freed by Calller
> > +  //
> > +  while(!IsListEmpty(&FileInfoList)) {
> > +    Link = FileInfoList.ForwardLink;
> > +    RemoveEntryList(Link);
> > +
> > +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> FILE_INFO_SIGNATURE);
> > +
> > +    FreePool(FileInfoEntry->FileNameFirstPart);
> > +    FreePool(FileInfoEntry->FileNameSecondPart);
> > +    FreePool(FileInfoEntry);
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  This routine is called to remove all qualified image from file from an given
> > directory.
> > +
> > +  @param[in] Dir                  Directory file handler
> > +  @param[in] FileAttr             Attribute of files to be deleted
> > +
> > +  @retval EFI_SUCCESS  Succeed to remove all files from an given directory.
> > +
> > +**/
> > +EFI_STATUS
> > +RemoveFileFromDir(
> > +  IN EFI_FILE_HANDLE   Dir,
> > +  IN UINT64            FileAttr
> > +  )
> > +{
> > +  EFI_STATUS        Status;
> > +  LIST_ENTRY        *Link;
> > +  LIST_ENTRY        FileInfoList;
> > +  EFI_FILE_HANDLE   FileHandle;
> > +  FILE_INFO_ENTRY   *FileInfoEntry;
> > +  EFI_FILE_INFO     *FileInfo;
> > +  UINTN             FileCount;
> > +
> > +  FileHandle = NULL;
> > +
> > +  //
> > +  // Get file list in Dir in alphabetical order
> > +  //
> > +  Status = GetFileInfoListInAlphabetFromDir(
> > +             Dir,
> > +             FileAttr,
> > +             &FileInfoList,
> > +             &FileCount
> > +             );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir
> Failed!\n"));
> > +    goto EXIT;
> > +  }
> > +
> > +  if (FileCount == 0) {
> > +    DEBUG ((DEBUG_ERROR, "No file found in Dir!\n"));
> > +    Status = EFI_NOT_FOUND;
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // Delete all files with given attribute in Dir
> > +  //
> > +  for (Link = FileInfoList.ForwardLink; Link != &(FileInfoList); Link = Link-
> > >ForwardLink) {
> > +    //
> > +    // Get FileInfo from the link list
> > +    //
> > +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> FILE_INFO_SIGNATURE);
> > +    FileInfo      = FileInfoEntry->FileInfo;
> > +
> > +    Status = Dir->Open(
> > +                    Dir,
> > +                    &FileHandle,
> > +                    FileInfo->FileName,
> > +                    EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
> > +                    0
> > +                    );
> > +    if (EFI_ERROR(Status)){
> > +      continue;
> > +    }
> > +
> > +    Status = FileHandle->Delete(FileHandle);
> > +  }
> > +
> > +EXIT:
> > +
> > +  while(!IsListEmpty(&FileInfoList)) {
> > +    Link = FileInfoList.ForwardLink;
> > +    RemoveEntryList(Link);
> > +
> > +    FileInfoEntry = CR (Link, FILE_INFO_ENTRY, Link,
> FILE_INFO_SIGNATURE);
> > +
> > +    FreePool(FileInfoEntry->FileInfo);
> > +    FreePool(FileInfoEntry);
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  This routine is called to get all caspules from file. The capsule file image is
> > +  copied to BS memory. Caller is responsible to free them.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +  @param[out]   CapsulePtr           Copied Capsule file Image Info buffer
> > +  @param[out]   CapsuleNum           CapsuleNumber
> > +  @param[out]   FsHandle             File system handle
> > +  @param[out]   LoadOptionNumber     OptionNumber of boot option
> > +
> > +  @retval EFI_SUCCESS  Succeed to get all capsules.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> 
> 
> Please help to remove the keyword 'EFIAPI' for internal function.
> 
> 
> > +GetAllCapsuleOnDisk(
> > +  IN  UINTN                            MaxRetry,
> > +  OUT IMAGE_INFO                       **CapsulePtr,
> > +  OUT UINTN                            *CapsuleNum,
> > +  OUT EFI_HANDLE                       *FsHandle,
> > +  OUT UINT16                            *LoadOptionNumber
> > +  )
> > +{
> > +  EFI_STATUS                       Status;
> > +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> > +  EFI_FILE_HANDLE                  RootDir;
> > +  EFI_FILE_HANDLE                  FileDir;
> > +  UINT16                           *TempOptionNumber;
> > +
> > +  Fs               = NULL;
> > +  RootDir          = NULL;
> > +  FileDir          = NULL;
> > +  TempOptionNumber = NULL;
> > +  *CapsuleNum      = 0;
> > +
> > +  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry,
> > &TempOptionNumber, FsHandle);
> > +  if (EFI_ERROR(Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = gBS->HandleProtocol(*FsHandle,
> > &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
> > +  if (EFI_ERROR(Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = Fs->OpenVolume(Fs, &RootDir);
> > +  if (EFI_ERROR(Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = RootDir->Open(
> > +                      RootDir,
> > +                      &FileDir,
> > +                      EFI_CAPSULE_FILE_DIRECTORY,
> > +                      EFI_FILE_MODE_READ,
> > +                      0
> > +                      );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG((DEBUG_ERROR, "CodLibGetAllCapsuleOnDisk fail to open
> > RootDir!\n"));
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // Only Load files with EFI_FILE_SYSTEM or EFI_FILE_ARCHIVE attribute
> > +  // ignore EFI_FILE_READ_ONLY, EFI_FILE_HIDDEN, EFI_FILE_RESERVED,
> > EFI_FILE_DIRECTORY
> > +  //
> > +  Status = GetFileImageInAlphabetFromDir(
> > +             FileDir,
> > +             EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE,
> > +             CapsulePtr,
> > +             CapsuleNum
> > +             );
> > +  DEBUG((DEBUG_INFO, "GetFileImageInAlphabetFromDir status %x\n",
> > Status));
> > +
> > +  //
> > +  // Always remove file to avoid deadloop in capsule process
> > +  //
> > +  Status = RemoveFileFromDir(FileDir, EFI_FILE_SYSTEM |
> > EFI_FILE_ARCHIVE);
> > +  DEBUG((DEBUG_INFO, "RemoveFileFromDir status %x\n", Status));
> > +
> > +  if (LoadOptionNumber != NULL) {
> > +    *LoadOptionNumber = *TempOptionNumber;
> > +  }
> > +
> > +EXIT:
> > +
> > +  if (FileDir != NULL) {
> > +    FileDir->Close (FileDir);
> > +  }
> > +
> > +  if (RootDir != NULL) {
> > +    RootDir->Close (RootDir);
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Build Gather list for a list of capsule images.
> > +
> > +  @param[in]  CapsuleBuffer    An array of pointer to capsule images
> > +  @param[in]  CapsuleSize      An array of UINTN to capsule images size
> > +  @param[in]  CapsuleNum       The count of capsule images
> > +  @param[out] BlockDescriptors The block descriptors for the capsule
> > images
> > +
> > +  @retval EFI_SUCCESS The block descriptors for the capsule images are
> > constructed.
> > +
> > +**/
> > +EFI_STATUS
> > +BuildGatherList (
> > +  IN VOID                          **CapsuleBuffer,
> > +  IN UINTN                         *CapsuleSize,
> > +  IN UINTN                         CapsuleNum,
> > +  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
> > +  )
> > +{
> > +  EFI_STATUS                    Status;
> > +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
> > +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
> > +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
> > +  UINTN                         Index;
> > +
> > +  BlockDescriptors1      = NULL;
> > +  BlockDescriptorPre     = NULL;
> > +  BlockDescriptorsHeader = NULL;
> > +
> > +  for (Index = 0; Index < CapsuleNum; Index++) {
> > +    //
> > +    // Allocate memory for the descriptors.
> > +    //
> > +    BlockDescriptors1  = AllocateZeroPool (2 * sizeof
> > (EFI_CAPSULE_BLOCK_DESCRIPTOR));
> > +    if (BlockDescriptors1 == NULL) {
> > +      DEBUG ((DEBUG_ERROR, "BuildGatherList: failed to allocate memory
> for
> > descriptors\n"));
> > +      Status = EFI_OUT_OF_RESOURCES;
> > +      goto ERREXIT;
> > +    } else {
> > +      DEBUG ((DEBUG_INFO, "BuildGatherList: creating capsule descriptors
> at
> > 0x%X\n", (UINTN) BlockDescriptors1));
> > +    }
> > +
> > +    //
> > +    // Record descirptor header
> > +    //
> > +    if (Index == 0) {
> > +      BlockDescriptorsHeader = BlockDescriptors1;
> > +    }
> > +
> > +    if (BlockDescriptorPre != NULL) {
> > +      BlockDescriptorPre->Union.ContinuationPointer = (UINTN)
> > BlockDescriptors1;
> > +      BlockDescriptorPre->Length = 0;
> > +    }
> > +
> > +    BlockDescriptors1->Union.DataBlock = (UINTN) CapsuleBuffer[Index];
> > +    BlockDescriptors1->Length = CapsuleSize[Index];
> > +
> > +    BlockDescriptorPre = BlockDescriptors1 + 1;
> > +    BlockDescriptors1 = NULL;
> > +  }
> > +
> > +  //
> > +  // Null-terminate.
> > +  //
> > +  if (BlockDescriptorPre != NULL) {
> > +    BlockDescriptorPre->Union.ContinuationPointer = (UINTN)NULL;
> > +    BlockDescriptorPre->Length = 0;
> > +    *BlockDescriptors = BlockDescriptorsHeader;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +
> > +ERREXIT:
> > +  if (BlockDescriptors1 != NULL) {
> > +    FreePool (BlockDescriptors1);
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  This routine is called to check if CapsuleOnDisk flag in OsIndications
> > Variable
> > +  is enabled.
> > +
> > +  @retval TRUE     Flag is enabled
> > +  @retval FALSE    Flag is not enabled
> > +
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +CoDCheckCapsuleOnDiskFlag(
> > +  VOID
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  UINT64                OsIndication;
> > +  UINTN                 DataSize;
> > +
> > +  //
> > +  // Check File Capsule Delivery Supported Flag in OsIndication variable
> > +  //
> > +  OsIndication = 0;
> > +  DataSize     = sizeof(UINT64);
> > +  Status = gRT->GetVariable (
> > +                  EFI_OS_INDICATIONS_VARIABLE_NAME,
> > +                  &gEfiGlobalVariableGuid,
> > +                  NULL,
> > +                  &DataSize,
> > +                  &OsIndication
> > +                  );
> > +  if (!EFI_ERROR(Status) &&
> > +      (OsIndication &
> > EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0) {
> > +    return TRUE;
> > +  }
> > +
> > +  return FALSE;
> > +}
> > +
> > +
> > +/**
> > +  This routine is called to clear CapsuleOnDisk flags including OsIndications
> > and BootNext variable.
> > +
> > +  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDClearCapsuleOnDiskFlag(
> > +  VOID
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  UINT64                OsIndication;
> > +  UINTN                 DataSize;
> > +
> > +  //
> > +  // Reset File Capsule Delivery Supported Flag in OsIndication variable
> > +  //
> > +  OsIndication = 0;
> > +  DataSize = sizeof(UINT64);
> > +  Status = gRT->GetVariable (
> > +                  EFI_OS_INDICATIONS_VARIABLE_NAME,
> > +                  &gEfiGlobalVariableGuid,
> > +                  NULL,
> > +                  &DataSize,
> > +                  &OsIndication
> > +                  );
> > +  if (EFI_ERROR(Status) ||
> > +      (OsIndication &
> > EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) == 0) {
> > +    return Status;
> > +  }
> > +
> > +  OsIndication &=
> > ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
> > +  Status = gRT->SetVariable (
> > +                  EFI_OS_INDICATIONS_VARIABLE_NAME,
> > +                  &gEfiGlobalVariableGuid,
> > +                  EFI_VARIABLE_BOOTSERVICE_ACCESS |
> > EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
> > +                  sizeof(UINT64),
> > +                  &OsIndication
> > +                  );
> > +  ASSERT(!EFI_ERROR(Status));
> > +
> > +  //
> > +  // Delete BootNext variable. Capsule Process may reset system, so can't
> > rely on Bds to clear this variable
> > +  //
> > +  Status = gRT->SetVariable (
> > +                  EFI_BOOT_NEXT_VARIABLE_NAME,
> > +                  &gEfiGlobalVariableGuid,
> > +                  0,
> > +                  0,
> > +                  NULL
> > +                  );
> > +  ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_FOUND);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  This routine is called to clear Capsule On Disk Relocation flag
> > +  The flag is the total size of capsules being relocated. It is saved
> > +  in CapsuleOnDisk Relocation Info varible in form of UINT64
> > +
> > +  @param[out] CapsuleRelocInfo  The value of "CapsuleRelocInfo" variable
> > +
> > +  @retval EFI_SUCCESS   Capsule Relocation flag is cleared
> > +
> > +**/
> > +EFI_STATUS
> > +CoDCheckCapsuleRelocationInfo(
> > +  OUT BOOLEAN *CapsuleRelocInfo
> > +  )
> 
> 
> I do not see the above function being used internally/externally.
> Please help to check and remove it.
> 
> 
> > +{
> > +  EFI_STATUS  Status;
> > +  UINTN       DataSize;
> > +
> > +  DataSize = sizeof(BOOLEAN);
> > +
> > +  Status= gRT->GetVariable (
> > +                 COD_RELOCATION_INFO_VAR_NAME,
> > +                 &gEfiCapsuleVendorGuid,
> > +                 NULL,
> > +                 &DataSize,
> > +                 CapsuleRelocInfo
> > +                 );
> > +
> > +  if (DataSize != sizeof(BOOLEAN)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  This routine is called to clear CapsuleOnDisk Relocation Info variable.
> > +  Total Capsule On Disk length is recorded in this variable
> > +
> > +  @retval EFI_SUCCESS   Capsule On Disk flags are cleared
> > +
> > +**/
> > +EFI_STATUS
> > +CoDClearCapsuleRelocationInfo(
> > +  VOID
> > +  )
> > +{
> > +  return gRT->SetVariable (
> > +                COD_RELOCATION_INFO_VAR_NAME,
> > +                &gEfiCapsuleVendorGuid,
> > +                0,
> > +                0,
> > +                NULL
> > +                );
> > +}
> > +
> > +/**
> > +  Relocate Capsule on Disk from EFI system partition to a platform-specific
> > NV storage device
> > +  with BlockIo protocol. Relocation device path, identified by
> > PcdCodRelocationDevPath, must
> > +  be a full device path.
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  Side Effects:
> > +    Content corruption. Block IO write directly touches low level write.
> Orignal
> > partitions, file systems
> > +    of the relocation device will be corrupted.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +
> > +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated
> to
> > the platform-specific device.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> 
> 
> Please help to remove 'EFIAPI' for this internal function.
> 
> 
> > +RelocateCapsuleToDisk(
> > +  UINTN     MaxRetry
> > +  )
> > +{
> > +  EFI_STATUS                      Status;
> > +  UINTN                           CapsuleOnDiskNum;
> > +  UINTN                           Index;
> > +  UINTN                           DataSize;
> > +  UINT64                          TotalImageSize;
> > +  UINT64                          TotalImageNameSize;
> > +  IMAGE_INFO                      *CapsuleOnDiskBuf;
> > +  EFI_HANDLE                      Handle;
> > +  EFI_HANDLE                      TempHandle;
> > +  EFI_HANDLE                      *HandleBuffer;
> > +  UINTN                           NumberOfHandles;
> > +  EFI_BLOCK_IO_PROTOCOL           *BlockIo;
> > +  UINT8                           *CapsuleDataBuf;
> > +  UINT8                           *CapsulePtr;
> > +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
> > +  EFI_FILE_HANDLE                 RootDir;
> > +  EFI_FILE_HANDLE                 TempCodFile;
> > +  UINT64                          TempCodFileSize;
> > +  EFI_DEVICE_PATH                 *TempDevicePath;
> > +  BOOLEAN                         RelocationInfo;
> > +  UINT16                          LoadOptionNumber;
> > +  EFI_CAPSULE_HEADER              FileNameCapsuleHeader;
> > +
> > +  RootDir          = NULL;
> > +  TempCodFile      = NULL;
> > +  HandleBuffer     = NULL;
> > +  CapsuleDataBuf   = NULL;
> > +  CapsuleOnDiskBuf = NULL;
> > +  NumberOfHandles  = 0;
> > +
> > +  DEBUG ((DEBUG_INFO, "CapsuleOnDisk RelocateCapsule Enter\n"));
> > +
> > +  //
> > +  // 1. Load all Capsule On Disks in to memory
> > +  //
> > +  Status = GetAllCapsuleOnDisk(MaxRetry, &CapsuleOnDiskBuf,
> > &CapsuleOnDiskNum, &Handle, &LoadOptionNumber);
> > +  if (EFI_ERROR(Status) || CapsuleOnDiskNum == 0) {
> > +    DEBUG ((DEBUG_INFO, "RelocateCapsule: GetAllCapsuleOnDisk Status -
> > 0x%x\n", Status));
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  //
> > +  // 2. Connect platform special dev path or Use EFI System Partition as
> > relocation device
> > +  //
> > +  if (PcdGetSize(PcdCodRelocationDevPath) >
> > sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
> 
> 
> Do we need a validity check for the device path specified by
> 'PcdCodRelocationDevPath'? Since it is from external input (by configuring
> the PCD).
> 
> Also, should we consider an error when the above 'if' statement is not met?
> 
> For the implementation in the patch, when:
> if (PcdGetSize(PcdCodRelocationDevPath) >
> sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
> evaluates to false, 'Handle' will still carry the value for the device where
> the capsules are placed. And then, the function may continue to write
> content
> on this media device. I think this should not happen, right?
> 


No,  that's how it is designed.
PcdCodRelocationDevPath is used by platform to specify a device to store temp Cod relocation file. 
If this PCD is not available, it means that platform doesn't have a requirement to store the file to a specific place.
Then save the file to the device where the capsules are placed.


> 
> > +    Status = EfiBootManagerConnectDevicePath ((EFI_DEVICE_PATH
> > *)PcdGetPtr(PcdCodRelocationDevPath), &TempHandle);
> > +    if (EFI_ERROR(Status)) {
> > +      DEBUG ((DEBUG_ERROR, "RelocateCapsule:
> > EfiBootManagerConnectDevicePath Status - 0x%x\n", Status));
> > +      goto EXIT;
> > +    }
> > +
> > +    //
> > +    // Connect all the child handle. Partition & FAT drivers are allowed in this
> > case
> > +    //
> > +    gBS->ConnectController (TempHandle, NULL, NULL, TRUE);
> > +    Status = gBS->LocateHandleBuffer(
> > +                    ByProtocol,
> > +                    &gEfiSimpleFileSystemProtocolGuid,
> > +                    NULL,
> > +                    &NumberOfHandles,
> > +                    &HandleBuffer
> > +                    );
> > +    if (EFI_ERROR(Status)) {
> > +      DEBUG ((DEBUG_ERROR, "RelocateCapsule: LocateHandleBuffer
> Status -
> > 0x%x\n", Status));
> > +      goto EXIT;
> > +    }
> > +
> > +    //
> > +    // Find first Simple File System Handle which can match
> > PcdCodRelocationDevPath
> > +    //
> > +    for (Index = 0; Index < NumberOfHandles; Index++) {
> > +      Status = gBS->HandleProtocol(HandleBuffer[Index],
> > &gEfiDevicePathProtocolGuid, (VOID **)&TempDevicePath);
> > +      if (EFI_ERROR(Status)) {
> > +        continue;
> > +      }
> > +
> > +      DataSize = GetDevicePathSize((EFI_DEVICE_PATH
> > *)PcdGetPtr(PcdCodRelocationDevPath)) - sizeof(EFI_DEVICE_PATH);
> > +      if (0 == CompareMem((EFI_DEVICE_PATH
> > *)PcdGetPtr(PcdCodRelocationDevPath), TempDevicePath, DataSize)) {
> > +        Handle = HandleBuffer[Index];
> > +        break;
> > +      }
> > +    }
> > +
> > +    FreePool(HandleBuffer);
> > +
> > +    if (Index == NumberOfHandles) {
> > +      DEBUG ((DEBUG_ERROR, "RelocateCapsule: No simple file system
> > protocol found.\n"));
> > +      Status = EFI_NOT_FOUND;
> > +    }
> > +  }
> > +
> > +  Status = gBS->HandleProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID
> > **)&BlockIo);
> > +  if (EFI_ERROR(Status) || BlockIo->Media->ReadOnly) {
> > +    DEBUG((DEBUG_ERROR, "Fail to find Capsule on Disk relocation BlockIo
> > device or device is ReadOnly!\n"));
> > +    return Status;
> > +  }
> > +
> > +  Status = gBS->HandleProtocol(Handle,
> &gEfiSimpleFileSystemProtocolGuid,
> > (VOID **)&Fs);
> > +  if (EFI_ERROR(Status)) {
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // Check if device used to relocate Capsule On Disk is big enough
> > +  //
> > +  TotalImageSize     = 0;
> > +  TotalImageNameSize = 0;
> > +  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
> > +    //
> > +    // Overflow check
> > +    //
> > +    if (MAX_ADDRESS - (UINTN)TotalImageSize <=
> > CapsuleOnDiskBuf[Index].FileInfo->FileSize) {
> > +      return EFI_INVALID_PARAMETER;
> 
> 
> Will memory leak happen in this error handling?
> 
> 
> > +    }
> > +
> > +    if (MAX_ADDRESS - (UINTN)TotalImageNameSize <=
> > StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName)) {
> > +      return EFI_INVALID_PARAMETER;
> > +    }
> > +
> > +    TotalImageSize     += CapsuleOnDiskBuf[Index].FileInfo->FileSize;
> > +    TotalImageNameSize += StrSize(CapsuleOnDiskBuf[Index].FileInfo-
> > >FileName);
> > +    DEBUG((DEBUG_INFO, "RelocateCapsule: %x
> > Size %x\n",CapsuleOnDiskBuf[Index].FileInfo->FileName,
> > CapsuleOnDiskBuf[Index].FileInfo->FileSize));
> > +  }
> > +
> > +  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageSize %x\n",
> > TotalImageSize));
> > +  DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageNameSize %x\n",
> > TotalImageNameSize));
> > +
> > +  if (MAX_ADDRESS - (UINTN)TotalImageNameSize <= sizeof(UINT64) * 2
> ||
> > +      MAX_ADDRESS - (UINTN)TotalImageSize <=
> > (UINTN)TotalImageNameSize + sizeof(UINT64) * 2) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  TempCodFileSize = sizeof(UINT64) + TotalImageSize +
> > sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;
> > +
> > +  //
> > +  // Check if CapsuleTotalSize. There could be reminder, so use LastBlock
> > number directly
> > +  //
> > +  if (DivU64x32(TempCodFileSize, BlockIo->Media->BlockSize) > BlockIo-
> > >Media->LastBlock) {
> > +    DEBUG((DEBUG_ERROR, "RelocateCapsule: Relocation device isn't big
> > enough to hold all Capsule on Disk!\n"));
> > +    DEBUG((DEBUG_ERROR, "TotalImageSize = %x\n", TotalImageSize));
> > +    DEBUG((DEBUG_ERROR, "TotalImageNameSize = %x\n",
> > TotalImageNameSize));
> > +    DEBUG((DEBUG_ERROR, "RelocationDev BlockSize = %x LastBlock
> = %x\n",
> > BlockIo->Media->BlockSize, BlockIo->Media->LastBlock));
> > +    Status = EFI_OUT_OF_RESOURCES;
> > +    goto EXIT;
> > +  }
> > +
> > +  CapsuleDataBuf = AllocatePool((UINTN) TempCodFileSize);
> > +  if (CapsuleDataBuf == NULL) {
> > +    Status = EFI_OUT_OF_RESOURCES;
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // First UINT64 reserved for total image size, including capsule name
> > capsule.
> > +  //
> > +  *(UINT64 *) CapsuleDataBuf = TotalImageSize +
> > sizeof(EFI_CAPSULE_HEADER) + TotalImageNameSize;
> > +
> > +  //
> > +  // Line up all the Capsule on Disk and write to relocation disk at one time.
> It
> > could save some time in disk write
> > +  //
> > +  for (Index = 0, CapsulePtr = CapsuleDataBuf + sizeof(UINT64); Index <
> > CapsuleOnDiskNum; Index++) {
> > +    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].ImageAddress,
> (UINTN)
> > CapsuleOnDiskBuf[Index].FileInfo->FileSize);
> > +    CapsulePtr += CapsuleOnDiskBuf[Index].FileInfo->FileSize;
> > +  }
> > +
> > +  //
> > +  // Line the capsule header for capsule name capsule.
> > +  //
> > +  CopyGuid(&FileNameCapsuleHeader.CapsuleGuid,
> > &gEdkiiCapsuleOnDiskNameGuid);
> > +  FileNameCapsuleHeader.CapsuleImageSize = (UINT32)
> > TotalImageNameSize + sizeof(EFI_CAPSULE_HEADER);
> > +  FileNameCapsuleHeader.Flags            =
> > CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> > +  FileNameCapsuleHeader.HeaderSize       = sizeof(EFI_CAPSULE_HEADER);
> > +  CopyMem(CapsulePtr, &FileNameCapsuleHeader,
> > FileNameCapsuleHeader.HeaderSize);
> > +  CapsulePtr += FileNameCapsuleHeader.HeaderSize;
> > +
> > +  //
> > +  // Line up all the Capsule file names.
> > +  //
> > +  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
> > +    CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].FileInfo->FileName,
> > StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName));
> > +    CapsulePtr += StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName);
> > +  }
> > +
> > +  //
> > +  // 5. Flash all Capsules on Disk to TempCoD.tmp under RootDir
> > +  //
> > +  Status = Fs->OpenVolume(Fs, &RootDir);
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG((DEBUG_ERROR, "RelocateCapsule: OpenVolume error. %x\n",
> > Status));
> > +    goto EXIT;
> > +  }
> > +
> > +  Status = RootDir->Open(
> > +                      RootDir,
> > +                      &TempCodFile,
> > +                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
> > +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
> > +                      0
> > +                      );
> > +  if (!EFI_ERROR(Status)) {
> > +    //
> > +    // Error handling code to prevent malicious code to hold this file to block
> > capsule on disk
> > +    //
> > +    TempCodFile->Delete(TempCodFile);
> > +  }
> > +  Status = RootDir->Open(
> > +                      RootDir,
> > +                      &TempCodFile,
> > +                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
> > +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
> > EFI_FILE_MODE_CREATE,
> > +                      0
> > +                      );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG((DEBUG_ERROR, "RelocateCapsule: Open TemCoD.tmp
> > error. %x\n", Status));
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // Always write at the begining of TempCap file
> > +  //
> > +  DataSize = (UINTN) TempCodFileSize;
> > +  Status = TempCodFile->Write(
> > +                          TempCodFile,
> > +                          &DataSize,
> > +                          CapsuleDataBuf
> > +                          );
> > +  if (EFI_ERROR(Status)) {
> > +    DEBUG((DEBUG_ERROR, "RelocateCapsule: Write TemCoD.tmp
> > error. %x\n", Status));
> > +    goto EXIT;
> > +  }
> > +
> > +  if (DataSize != TempCodFileSize) {
> > +    Status = EFI_DEVICE_ERROR;
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // Save Capsule On Disk relocation info to "CodRelocationInfo" Var
> > +  // It is used in next reboot by TCB
> > +  //
> > +  RelocationInfo = TRUE;
> > +  Status = gRT->SetVariable(
> > +                   COD_RELOCATION_INFO_VAR_NAME,
> > +                   &gEfiCapsuleVendorGuid,
> > +                   EFI_VARIABLE_NON_VOLATILE |
> > EFI_VARIABLE_BOOTSERVICE_ACCESS,
> > +                   sizeof (BOOLEAN),
> > +                   &RelocationInfo
> > +                   );
> > +  //
> > +  // Save the LoadOptionNumber of the boot option, where the capsule is
> > relocated,
> > +  // into "CodRelocationLoadOption" var. It is used in next reboot after
> > capsule is
> > +  // updated out of TCB to remove the TempCoDFile.
> > +  //
> > +  Status = gRT->SetVariable(
> > +                   COD_RELOCATION_LOAD_OPTION_VAR_NAME,
> > +                   &gEfiCapsuleVendorGuid,
> > +                   EFI_VARIABLE_NON_VOLATILE |
> > EFI_VARIABLE_BOOTSERVICE_ACCESS,
> > +                   sizeof (UINT16),
> > +                   &LoadOptionNumber
> > +                   );
> > +
> > +EXIT:
> > +
> > +  if (CapsuleDataBuf != NULL) {
> > +    FreePool(CapsuleDataBuf);
> > +  }
> > +
> > +  if (CapsuleOnDiskBuf != NULL) {
> > +    //
> > +    // Free resources allocated by CodLibGetAllCapsuleOnDisk
> > +    //
> > +    for (Index = 0; Index < CapsuleOnDiskNum; Index++ ) {
> > +      FreePool(CapsuleOnDiskBuf[Index].ImageAddress);
> > +      FreePool(CapsuleOnDiskBuf[Index].FileInfo);
> > +    }
> > +    FreePool(CapsuleOnDiskBuf);
> > +  }
> > +
> > +  if (TempCodFile != NULL) {
> > +    if (EFI_ERROR(Status)) {
> > +      TempCodFile->Delete (TempCodFile);
> > +    } else {
> > +      TempCodFile->Close (TempCodFile);
> > +    }
> > +  }
> > +
> > +  if (RootDir != NULL) {
> > +    RootDir->Close (RootDir);
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  For the platforms that support Capsule In Ram, reuse the Capsule In Ram
> > to deliver capsule.
> > +  Relocate Capsule On Disk to memory and call UpdateCapsule().
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +
> > +  @retval EFI_SUCCESS   Deliver capsule through Capsule In Ram
> successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> 
> Please help to remove 'EFIAPI' for this internal function.
> 
> 
> > +RelocateCapsuleToRam (
> > +  UINTN    MaxRetry
> > +  )
> > +{
> > +  EFI_STATUS                    Status;
> > +  UINTN                         CapsuleOnDiskNum;
> > +  IMAGE_INFO                    *CapsuleOnDiskBuf;
> > +  EFI_HANDLE                    Handle;
> > +  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors;
> > +  VOID                          **CapsuleBuffer;
> > +  UINTN                         *CapsuleSize;
> > +  EFI_CAPSULE_HEADER            *FileNameCapsule;
> > +  UINTN                         Index;
> > +  UINT8                         *StringBuf;
> > +  UINTN                         StringSize;
> > +  UINTN                         TotalStringSize;
> > +
> > +  CapsuleOnDiskBuf = NULL;
> > +  BlockDescriptors = NULL;
> > +  CapsuleBuffer    = NULL;
> > +  CapsuleSize      = NULL;
> > +  FileNameCapsule  = NULL;
> > +  TotalStringSize  = 0;
> > +
> > +  //
> > +  // 1. Load all Capsule On Disks into memory
> > +  //
> > +  Status = GetAllCapsuleOnDisk (MaxRetry, &CapsuleOnDiskBuf,
> > &CapsuleOnDiskNum, &Handle, NULL);
> > +  if (EFI_ERROR (Status) || CapsuleOnDiskNum == 0) {
> > +    DEBUG ((DEBUG_ERROR, "GetAllCapsuleOnDisk Status - 0x%x\n",
> > Status));
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  //
> > +  // 2. Add a capsule for Capsule file name strings
> > +  //
> > +  CapsuleBuffer = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof
> (VOID
> > *));
> > +  if (CapsuleBuffer == NULL) {
> > +    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  CapsuleSize = AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof
> > (UINTN));
> > +  if (CapsuleSize == NULL) {
> > +    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n"));
> > +    return EFI_OUT_OF_RESOURCES;
> 
> 
> Potential memory leaks in some error handling paths, please help to
> address them.
> 
> 
> > +  }
> > +
> > +  for (Index = 0; Index < CapsuleOnDiskNum; Index++) {
> > +    CapsuleBuffer[Index] = (VOID *)(UINTN)
> > CapsuleOnDiskBuf[Index].ImageAddress;
> > +    CapsuleSize[Index] = (UINTN) CapsuleOnDiskBuf[Index].FileInfo-
> >FileSize;
> > +    TotalStringSize += StrSize (CapsuleOnDiskBuf[Index].FileInfo-
> >FileName);
> > +  }
> > +
> > +  FileNameCapsule = AllocateZeroPool (sizeof (EFI_CAPSULE_HEADER) +
> > TotalStringSize);
> > +  if (FileNameCapsule == NULL) {
> > +    DEBUG ((DEBUG_ERROR, "Fail to allocate memory for name
> capsule.\n"));
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  FileNameCapsule->CapsuleImageSize = (UINT32) (sizeof
> > (EFI_CAPSULE_HEADER) + TotalStringSize);
> > +  FileNameCapsule->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> > +  FileNameCapsule->HeaderSize = sizeof (EFI_CAPSULE_HEADER);
> > +  CopyGuid (&(FileNameCapsule->CapsuleGuid),
> > &gEdkiiCapsuleOnDiskNameGuid);
> > +
> > +  StringBuf = (UINT8 *)FileNameCapsule + FileNameCapsule->HeaderSize;
> > +  for (Index = 0; Index < CapsuleOnDiskNum; Index ++) {
> > +    StringSize = StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName);
> > +    CopyMem (StringBuf, CapsuleOnDiskBuf[Index].FileInfo->FileName,
> > StringSize);
> > +    StringBuf += StringSize;
> > +  }
> > +
> > +  CapsuleBuffer[CapsuleOnDiskNum] = FileNameCapsule;
> > +  CapsuleSize[CapsuleOnDiskNum] = TotalStringSize + sizeof
> > (EFI_CAPSULE_HEADER);
> > +
> > +  //
> > +  // 3. Build Gather list for the capsules
> > +  //
> > +  Status = BuildGatherList (CapsuleBuffer, CapsuleSize,
> CapsuleOnDiskNum
> > + 1, &BlockDescriptors);
> > +  if (EFI_ERROR (Status) || BlockDescriptors == NULL) {
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  //
> > +  // 4. Call UpdateCapsule() service
> > +  //
> > +  Status = gRT->UpdateCapsule((EFI_CAPSULE_HEADER **) CapsuleBuffer,
> > CapsuleOnDiskNum + 1, (UINTN) BlockDescriptors);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Relocate Capsule on Disk from EFI system partition.
> > +
> > +  Two solution to deliver Capsule On Disk:
> > +  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On
> > Disk to memory and call UpdateCapsule().
> > +  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On
> > Disk to a platform-specific NV storage
> > +  device with BlockIo protocol.
> > +
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  Side Effects:
> > +    Capsule Delivery Supported Flag in OsIndication variable and BootNext
> > variable will be cleared.
> > +    Solution B: Content corruption. Block IO write directly touches low level
> > write. Orignal partitions, file
> > +  systems of the relocation device will be corrupted.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +
> > +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDRelocateCapsule(
> > +  UINTN     MaxRetry
> > +  )
> > +{
> > +  if (!PcdGetBool (PcdCapsuleOnDiskSupport)) {
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  //
> > +  // Clear CapsuleOnDisk Flag firstly.
> > +  //
> > +  CoDClearCapsuleOnDiskFlag ();
> > +
> > +  //
> > +  // If Capsule In Ram is supported, delivery capsules through memory
> > +  //
> > +  if (PcdGetBool (PcdCapsuleInRamSupport)) {
> > +    DEBUG ((DEBUG_INFO, "Capsule In Ram is supported, call gRT-
> > >UpdateCapsule().\n"));
> > +    return RelocateCapsuleToRam (MaxRetry);
> > +  } else {
> > +    DEBUG ((DEBUG_INFO, "Reallcoate all Capsule on Disks to %s in
> > RootDir.\n", (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName)));
> > +    return RelocateCapsuleToDisk (MaxRetry);
> > +  }
> > +}
> > +
> > +/**
> > +  Remove the temp file from the root of EFI System Partition.
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +
> > +  @retval EFI_SUCCESS   Remove the temp file successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDRemoveTempFile (
> > +  UINTN    MaxRetry
> > +  )
> > +{
> > +  EFI_STATUS                       Status;
> > +  UINTN                            DataSize;
> > +  UINT16                           *LoadOptionNumber;
> > +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
> > +  EFI_HANDLE                       FsHandle;
> > +  EFI_FILE_HANDLE                  RootDir;
> > +  EFI_FILE_HANDLE                  TempCodFile;
> > +
> > +  RootDir     = NULL;
> > +  TempCodFile = NULL;
> > +
> > +  LoadOptionNumber = AllocatePool (sizeof(UINT16));
> > +  DataSize = sizeof(UINT16);
> > +
> > +  //
> > +  // Check if capsule files are relocated
> > +  //
> > +  Status = gRT->GetVariable (
> > +                  COD_RELOCATION_LOAD_OPTION_VAR_NAME,
> > +                  &gEfiCapsuleVendorGuid,
> > +                  NULL,
> > +                  &DataSize,
> > +                  (VOID *)LoadOptionNumber
> > +                  );
> > +  if (EFI_ERROR(Status) || DataSize != sizeof(UINT16)) {
> > +    return Status;
> 
> 
> Please handle possible memory leak in error handlings for this function.
> 
> 
> > +  }
> > +
> > +  //
> > +  // Get the EFI file system from the boot option where the capsules are
> > relocated
> > +  //
> > +  Status = GetEfiSysPartitionFromActiveBootOption(MaxRetry,
> > &LoadOptionNumber, &FsHandle);
> > +  if (EFI_ERROR(Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = gBS->HandleProtocol(FsHandle,
> > &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
> > +  if (EFI_ERROR(Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = Fs->OpenVolume(Fs, &RootDir);
> > +  if (EFI_ERROR(Status)) {
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // Delete the TempCoDFile
> > +  //
> > +  Status = RootDir->Open(
> > +                      RootDir,
> > +                      &TempCodFile,
> > +                      (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName),
> > +                      EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
> > +                      0
> > +                      );
> > +  if (!EFI_ERROR(Status)) {
> > +    TempCodFile->Delete(TempCodFile);
> > +  }
> > +
> > +  if (RootDir != NULL) {
> > +    RootDir->Close(RootDir);
> > +  }
> > +
> > +  //
> > +  // Clear "CoDRelocationLoadOption" variable
> > +  //
> > +  Status = gRT->SetVariable (
> > +             COD_RELOCATION_LOAD_OPTION_VAR_NAME,
> > +             &gEfiCapsuleVendorGuid,
> > +             0,
> > +             0,
> > +             NULL
> > +             );
> > +
> > +  return EFI_SUCCESS;
> > +}
> > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> > new file mode 100644
> > index 0000000000..064dc791b8
> > --- /dev/null
> > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h
> > @@ -0,0 +1,63 @@
> > +/** @file
> > +  Defines several datastructures used by Capsule On Disk feature.
> > +  They are mainly used for FAT files.
> > +
> > +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef _CAPSULES_ON_DISK_H_
> > +#define _CAPSULES_ON_DISK_H_
> > +
> > +#include <Uefi.h>
> > +#include <Pi/PiMultiPhase.h>
> > +
> > +#include <Library/UefiLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/BaseLib.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +#include <Library/UefiRuntimeServicesTableLib.h>
> > +#include <Library/UefiRuntimeLib.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/MemoryAllocationLib.h>
> > +#include <Library/FileHandleLib.h>
> > +#include <Library/CapsuleLib.h>
> > +#include <Library/DevicePathLib.h>
> > +#include <Library/PrintLib.h>
> > +#include <Library/UefiBootManagerLib.h>
> > +
> > +#include <Protocol/SimpleFileSystem.h>
> > +#include <Protocol/DiskIo.h>
> > +#include <Protocol/BlockIo.h>
> > +
> > +#include <Guid/CapsuleVendor.h>
> > +#include <Guid/GlobalVariable.h>
> > +
> > +//
> > +// This data structure is the part of FILE_INFO_ENTRY
> > +//
> > +#define FILE_INFO_SIGNATURE SIGNATURE_32 ('F', 'L', 'I', 'F')
> > +
> > +//
> > +// LoadOptionNumber of the boot option where the capsules is relocated.
> > +//
> > +#define COD_RELOCATION_LOAD_OPTION_VAR_NAME
> > L"CodRelocationLoadOption"
> > +
> > +typedef struct {
> > +  UINTN           Signature;
> > +  LIST_ENTRY      Link;                  ///  Linked list members.
> > +  EFI_FILE_INFO   *FileInfo;             ///  Pointer to the FileInfo struct for this
> > file or NULL.
> > +  CHAR16          *FileNameFirstPart;    ///  Text to the left of right-most
> period
> > in the file name. String is capitialized
> > +  CHAR16          *FileNameSecondPart;   ///  Text to the right of right-most
> > period in the file name.String is capitialized. Maybe NULL
> > +} FILE_INFO_ENTRY;
> > +
> > +//
> > +// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for
> > bytes)
> > +//
> > +#define MAX_FILE_NAME_SIZE   522
> > +#define MAX_FILE_NAME_LEN    (MAX_FILE_NAME_SIZE /
> sizeof(CHAR16))
> > +
> > +#define MAX_FILE_INFO_LEN    (OFFSET_OF(EFI_FILE_INFO, FileName) +
> > MAX_FILE_NAME_LEN)
> > +
> > +#endif // _CAPSULES_ON_DISK_H_
> > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > index f38ab69e38..4254cc8270 100644
> > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
> > @@ -8,11 +8,11 @@
> >
> >    SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),
> >    ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted
> input
> > and
> >    performs basic validation.
> >
> > -  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> >
> >  #include <PiDxe.h>
> > @@ -88,11 +88,12 @@ EFI_STATUS
> >  RecordFmpCapsuleStatusVariable (
> >    IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
> >    IN EFI_STATUS                                    CapsuleStatus,
> >    IN UINTN                                         PayloadIndex,
> >    IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> > *ImageHeader,
> > -  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath OPTIONAL
> > +  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath, OPTIONAL
> > +  IN CHAR16                                        *CapFileName    OPTIONAL
> 
> 
> Please help to update the function description comments for adding a new
> parameter.
> 
> Also, the implementations of this function in file DxeCapsuleReportLib.c &
> DxeCapsuleReportLibNull.c are with different interface definitions. Could
> you help to double confirm on this?
> 

It is a mistake, will fix it.


> 
> >    );
> >
> >  /**
> >    Function indicate the current completion progress of the firmware
> >    update. Platform may override with own specific progress function.
> > @@ -107,10 +108,26 @@ EFI_STATUS
> >  EFIAPI
> >  UpdateImageProgress (
> >    IN UINTN  Completion
> >    );
> >
> > +/**
> > +  Return if this capsule is a capsule name capsule, based upon
> > CapsuleHeader.
> > +
> > +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> > +
> > +  @retval TRUE  It is a capsule name capsule.
> > +  @retval FALSE It is not a capsule name capsule.
> > +**/
> > +BOOLEAN
> > +IsCapsuleNameCapsule (
> > +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> > +  )
> > +{
> > +  return CompareGuid (&CapsuleHeader->CapsuleGuid,
> > &gEdkiiCapsuleOnDiskNameGuid);
> > +}
> > +
> >  /**
> >    Return if this CapsuleGuid is a FMP capsule GUID or not.
> >
> >    @param[in] CapsuleGuid A pointer to EFI_GUID
> >
> > @@ -1032,23 +1049,25 @@ StartFmpImage (
> >  }
> >
> >  /**
> >    Record FMP capsule status.
> >
> > -  @param[in]  Handle        A FMP handle.
> > +  @param[in] Handle         A FMP handle.
> >    @param[in] CapsuleHeader  The capsule image header
> >    @param[in] CapsuleStatus  The capsule process stauts
> >    @param[in] PayloadIndex   FMP payload index
> >    @param[in] ImageHeader    FMP image header
> > +  @param[in] CapFileName    Capsule file name
> >  **/
> >  VOID
> >  RecordFmpCapsuleStatus (
> >    IN EFI_HANDLE                                    Handle,  OPTIONAL
> >    IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
> >    IN EFI_STATUS                                    CapsuleStatus,
> >    IN UINTN                                         PayloadIndex,
> > -  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> > *ImageHeader
> > +  IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> > *ImageHeader,
> > +  IN CHAR16                                        *CapFileName   OPTIONAL
> >    )
> >  {
> >    EFI_STATUS                                    Status;
> >    EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath;
> >    UINT32                                        FmpImageInfoDescriptorVer;
> > @@ -1068,11 +1087,12 @@ RecordFmpCapsuleStatus (
> >    RecordFmpCapsuleStatusVariable (
> >      CapsuleHeader,
> >      CapsuleStatus,
> >      PayloadIndex,
> >      ImageHeader,
> > -    FmpDevicePath
> > +    FmpDevicePath,
> > +    CapFileName
> >      );
> >
> >    //
> >    // Update corresponding ESRT entry LastAttemp Status
> >    //
> > @@ -1113,10 +1133,11 @@ RecordFmpCapsuleStatus (
> >    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
> >
> >    This function need support nested FMP capsule.
> >
> >    @param[in]  CapsuleHeader         Points to a capsule header.
> > +  @param[in]  CapFileName           Capsule file name.
> >    @param[out] ResetRequired         Indicates whether reset is required or
> not.
> >
> >    @retval EFI_SUCESS            Process Capsule Image successfully.
> >    @retval EFI_UNSUPPORTED       Capsule image is not supported by the
> > firmware.
> >    @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
> > @@ -1124,10 +1145,11 @@ RecordFmpCapsuleStatus (
> >    @retval EFI_NOT_READY         No FMP protocol to handle this FMP capsule.
> >  **/
> >  EFI_STATUS
> >  ProcessFmpCapsuleImage (
> >    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> > +  IN CHAR16              *CapFileName,  OPTIONAL
> >    OUT BOOLEAN            *ResetRequired OPTIONAL
> >    )
> >  {
> >    EFI_STATUS                                    Status;
> >    EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
> > *FmpCapsuleHeader;
> > @@ -1143,11 +1165,11 @@ ProcessFmpCapsuleImage (
> >    UINTN                                         Index2;
> >    BOOLEAN                                       NotReady;
> >    BOOLEAN                                       Abort;
> >
> >    if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
> > -    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
> > *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);
> > +    return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER
> > *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName,
> > ResetRequired);
> >    }
> >
> >    NotReady = FALSE;
> >    Abort = FALSE;
> >
> > @@ -1225,11 +1247,12 @@ ProcessFmpCapsuleImage (
> >        RecordFmpCapsuleStatus (
> >          NULL,
> >          CapsuleHeader,
> >          EFI_NOT_READY,
> >          Index - FmpCapsuleHeader->EmbeddedDriverCount,
> > -        ImageHeader
> > +        ImageHeader,
> > +        CapFileName
> >          );
> >        continue;
> >      }
> >
> >      for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
> > @@ -1237,11 +1260,12 @@ ProcessFmpCapsuleImage (
> >          RecordFmpCapsuleStatus (
> >            HandleBuffer[Index2],
> >            CapsuleHeader,
> >            EFI_ABORTED,
> >            Index - FmpCapsuleHeader->EmbeddedDriverCount,
> > -          ImageHeader
> > +          ImageHeader,
> > +          CapFileName
> >            );
> >          continue;
> >        }
> >
> >        Status = SetFmpImageData (
> > @@ -1260,11 +1284,12 @@ ProcessFmpCapsuleImage (
> >        RecordFmpCapsuleStatus (
> >          HandleBuffer[Index2],
> >          CapsuleHeader,
> >          Status,
> >          Index - FmpCapsuleHeader->EmbeddedDriverCount,
> > -        ImageHeader
> > +        ImageHeader,
> > +        CapFileName
> >          );
> >      }
> >      if (HandleBuffer != NULL) {
> >        FreePool(HandleBuffer);
> >      }
> > @@ -1412,10 +1437,17 @@ SupportCapsuleImage (
> >    //
> >    if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader-
> > >CapsuleGuid)) {
> >      return EFI_SUCCESS;
> >    }
> >
> > +  //
> > +  // Check capsule file name capsule
> > +  //
> > +  if (IsCapsuleNameCapsule(CapsuleHeader)) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> >    if (IsFmpCapsule(CapsuleHeader)) {
> >      //
> >      // Fake capsule header is valid case in QueryCapsuleCpapbilities().
> >      //
> >      if (CapsuleHeader->HeaderSize == CapsuleHeader->CapsuleImageSize) {
> > @@ -1434,10 +1466,11 @@ SupportCapsuleImage (
> >    The firmware implements to process the capsule image.
> >
> >    Caution: This function may receive untrusted input.
> >
> >    @param[in]  CapsuleHeader         Points to a capsule header.
> > +  @param[in]  CapFileName           Capsule file name.
> >    @param[out] ResetRequired         Indicates whether reset is required or
> not.
> >
> >    @retval EFI_SUCESS            Process Capsule Image successfully.
> >    @retval EFI_UNSUPPORTED       Capsule image is not supported by the
> > firmware.
> >    @retval EFI_VOLUME_CORRUPTED  FV volume in the capsule is corrupted.
> > @@ -1445,10 +1478,11 @@ SupportCapsuleImage (
> >  **/
> >  EFI_STATUS
> >  EFIAPI
> >  ProcessThisCapsuleImage (
> >    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> > +  IN CHAR16              *CapFileName,  OPTIONAL
> >    OUT BOOLEAN            *ResetRequired OPTIONAL
> >    )
> >  {
> >    EFI_STATUS                   Status;
> >
> > @@ -1482,11 +1516,11 @@ ProcessThisCapsuleImage (
> >
> >      //
> >      // Process EFI FMP Capsule
> >      //
> >      DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
> > -    Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);
> > +    Status = ProcessFmpCapsuleImage(CapsuleHeader, CapFileName,
> > ResetRequired);
> >      DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
> >
> >      return Status;
> >    }
> >
> > @@ -1509,11 +1543,11 @@ EFI_STATUS
> >  EFIAPI
> >  ProcessCapsuleImage (
> >    IN EFI_CAPSULE_HEADER  *CapsuleHeader
> >    )
> >  {
> > -  return ProcessThisCapsuleImage (CapsuleHeader, NULL);
> > +  return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL);
> >  }
> >
> >  /**
> >    Callback function executed when the EndOfDxe event group is signaled.
> >
> > diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> > index 14c3d19bc3..05de4299fb 100644
> > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
> > @@ -1,11 +1,11 @@
> >  ## @file
> >  #  Capsule library instance for DXE_DRIVER.
> >  #
> >  #  Capsule library instance for DXE_DRIVER module types.
> >  #
> > -#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >  #
> >  ##
> >
> >  [Defines]
> > @@ -27,10 +27,12 @@
> >
> >  [Sources]
> >    DxeCapsuleLib.c
> >    DxeCapsuleProcessLib.c
> >    DxeCapsuleReportLib.c
> > +  CapsuleOnDisk.c
> > +  CapsuleOnDisk.h
> >
> >  [Packages]
> >    MdePkg/MdePkg.dec
> >    MdeModulePkg/MdeModulePkg.dec
> >
> > @@ -45,10 +47,12 @@
> >    ReportStatusCodeLib
> >    PrintLib
> >    HobLib
> >    BmpSupportLib
> >    DisplayUpdateProgressLib
> > +  FileHandleLib
> > +  UefiBootManagerLib
> >
> >  [Pcd]
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax                               ##
> > CONSUMES
> >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcess
> > Flag      ## CONSUMES
> >
> > @@ -57,23 +61,38 @@
> >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsules
> > End      ## CONSUMES
> >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmwa
> > re        ## CONSUMES
> >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwar
> > eSuccess   ## CONSUMES
> >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwar
> > eFailed    ## CONSUMES
> >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSyste
> > m         ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport
> > ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport
> > ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath
> > ## SOMETIMES_CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName
> > ## CONSUMES
> >
> >  [Protocols]
> >    gEsrtManagementProtocolGuid                   ## CONSUMES
> >    gEfiFirmwareManagementProtocolGuid            ## CONSUMES
> >    gEdkiiVariableLockProtocolGuid                ## SOMETIMES_CONSUMES
> >    gEdkiiFirmwareManagementProgressProtocolGuid  ##
> > SOMETIMES_CONSUMES
> > +  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
> > +  gEfiBlockIoProtocolGuid                       ## CONSUMES
> > +  gEfiDiskIoProtocolGuid                        ## CONSUMES
> >
> >  [Guids]
> >    gEfiFmpCapsuleGuid                      ## SOMETIMES_CONSUMES ## GUID
> >    gWindowsUxCapsuleGuid                   ## SOMETIMES_CONSUMES ## GUID
> >    ## SOMETIMES_CONSUMES ## Variable:L"CapsuleMax"
> >    ## SOMETIMES_PRODUCES ## Variable:L"CapsuleMax"
> >    gEfiCapsuleReportGuid
> >    gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> > Variable:L"CapsuleUpdateData"
> >    gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
> > +  gEfiPartTypeSystemPartGuid              ## SOMETIMES_CONSUMES
> > +  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> > Variable:L"CodRelocationInfo"
> > +  ## SOMETIMES_CONSUMES ## Variable:L"OsIndications"
> > +  ## SOMETIMES_PRODUCES ## Variable:L"OsIndications"
> > +  ## SOMETIMES_CONSUMES ## Variable:L"BootNext"
> > +  ## SOMETIMES_PRODUCES ## Variable:L"BootNext"
> > +  gEfiGlobalVariableGuid
> > +  gEdkiiCapsuleOnDiskNameGuid             ## SOMETIMES_CONSUMES ##
> > GUID
> >
> >  [Depex]
> >    gEfiVariableWriteArchProtocolGuid
> > diff --git
> > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> > index 5e2d2b87a8..e07dd7986e 100644
> > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> > +++
> b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
> > @@ -7,11 +7,11 @@
> >    buffer overflow, integer overflow.
> >
> >    ProcessCapsules(), ProcessTheseCapsules() will receive untrusted
> >    input and do basic validation.
> >
> > -  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> >
> >  #include <PiDxe.h>
> > @@ -90,14 +90,45 @@ BOOLEAN
> >  IsValidCapsuleHeader (
> >    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> >    IN UINT64              CapsuleSize
> >    );
> >
> > +/**
> > +  Return if this capsule is a capsule name capsule, based upon
> > CapsuleHeader.
> > +
> > +  @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
> > +
> > +  @retval TRUE  It is a capsule name capsule.
> > +  @retval FALSE It is not a capsule name capsule.
> > +**/
> > +BOOLEAN
> > +IsCapsuleNameCapsule (
> > +  IN EFI_CAPSULE_HEADER         *CapsuleHeader
> > +  );
> > +
> > +/**
> > +  Check the integrity of the capsule name capsule.
> > +  If the capsule is vaild, return the physical address of each capsule name
> > string.
> > +
> > +  @param[in]  CapsuleHeader   Pointer to the capsule header of a capsule
> > name capsule.
> > +  @param[out] CapsuleNameNum  Number of capsule name.
> > +
> > +  @retval NULL                Capsule name capsule is not valid.
> > +  @retval CapsuleNameBuf      Array of capsule name physical address.
> > +
> > +**/
> > +EFI_PHYSICAL_ADDRESS *
> > +ValidateCapsuleNameCapsuleIntegrity (
> > +  IN  EFI_CAPSULE_HEADER            *CapsuleHeader,
> > +  OUT UINTN                         *CapsuleNameNum
> > +  );
> > +
> >  extern BOOLEAN                   mDxeCapsuleLibEndOfDxe;
> >  BOOLEAN                          mNeedReset = FALSE;
> >
> >  VOID                        **mCapsulePtr;
> > +CHAR16                      **mCapsuleNamePtr;
> >  EFI_STATUS                  *mCapsuleStatusArray;
> >  UINT32                      mCapsuleTotalNumber;
> >
> >  /**
> >    The firmware implements to process the capsule image.
> > @@ -114,10 +145,11 @@ UINT32                      mCapsuleTotalNumber;
> >  **/
> >  EFI_STATUS
> >  EFIAPI
> >  ProcessThisCapsuleImage (
> >    IN EFI_CAPSULE_HEADER  *CapsuleHeader,
> > +  IN CHAR16              *CapFileName,  OPTIONAL
> >    OUT BOOLEAN            *ResetRequired OPTIONAL
> >    );
> >
> >  /**
> >    Function indicate the current completion progress of the firmware
> > @@ -183,20 +215,36 @@ InitCapsulePtr (
> >    VOID
> >    )
> >  {
> >    EFI_PEI_HOB_POINTERS        HobPointer;
> >    UINTN                       Index;
> > +  UINTN                       Index2;
> > +  UINTN                       Index3;
> > +  UINTN                       CapsuleNameNumber;
> > +  UINTN                       CapsuleNameTotalNumber;
> > +  UINTN                       CapsuleNameCapsuleTotalNumber;
> > +  VOID                        **CapsuleNameCapsulePtr;
> > +  EFI_PHYSICAL_ADDRESS        *CapsuleNameAddress;
> > +
> > +  CapsuleNameNumber             = 0;
> > +  CapsuleNameTotalNumber        = 0;
> > +  CapsuleNameCapsuleTotalNumber = 0;
> > +  CapsuleNameCapsulePtr         = NULL;
> >
> >    //
> >    // Find all capsule images from hob
> >    //
> >    HobPointer.Raw = GetHobList ();
> >    while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE,
> > HobPointer.Raw)) != NULL) {
> >      if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule-
> > >BaseAddress, HobPointer.Capsule->Length)) {
> >        HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this
> > hob as invalid
> >      } else {
> > -      mCapsuleTotalNumber++;
> > +      if (IsCapsuleNameCapsule((VOID *)(UINTN)HobPointer.Capsule-
> > >BaseAddress)) {
> > +        CapsuleNameCapsuleTotalNumber++;
> > +      } else {
> > +        mCapsuleTotalNumber++;
> > +      }
> >      }
> >      HobPointer.Raw = GET_NEXT_HOB (HobPointer);
> >    }
> >
> >    DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n",
> > mCapsuleTotalNumber));
> > @@ -222,19 +270,76 @@ InitCapsulePtr (
> >      mCapsuleTotalNumber = 0;
> >      return ;
> >    }
> >    SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) *
> > mCapsuleTotalNumber, EFI_NOT_READY);
> >
> > +  if (CapsuleNameCapsuleTotalNumber != 0) {
> > +    CapsuleNameCapsulePtr =  (VOID **) AllocateZeroPool (sizeof (VOID *)
> *
> > CapsuleNameCapsuleTotalNumber);
> > +    if (CapsuleNameCapsulePtr == NULL) {
> > +      DEBUG ((DEBUG_ERROR, "Allocate CapsuleNameCapsulePtr fail!\n"));
> > +      FreePool (mCapsulePtr);
> > +      FreePool (mCapsuleStatusArray);
> > +      mCapsulePtr         = NULL;
> > +      mCapsuleStatusArray = NULL;
> > +      mCapsuleTotalNumber = 0;
> > +      return ;
> > +    }
> > +  }
> > +
> >    //
> >    // Find all capsule images from hob
> >    //
> >    HobPointer.Raw = GetHobList ();
> > -  Index = 0;
> > +  Index  = 0;
> > +  Index2 = 0;
> >    while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE,
> > HobPointer.Raw)) != NULL) {
> > -    mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule-
> > >BaseAddress;
> > +    if (!IsCapsuleNameCapsule ((VOID *) (UINTN) HobPointer.Capsule-
> > >BaseAddress)) {
> > +      mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule-
> > >BaseAddress;
> > +    } else {
> > +      CapsuleNameCapsulePtr [Index2++] = (VOID *) (UINTN)
> > HobPointer.Capsule->BaseAddress;
> > +    }
> >      HobPointer.Raw = GET_NEXT_HOB (HobPointer);
> >    }
> > +
> > +  //
> > +  // Find Capsule On Disk Names
> > +  //
> > +  for (Index = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {
> > +    CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity
> > (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
> > +    if (CapsuleNameAddress != NULL ) {
> > +      CapsuleNameTotalNumber += CapsuleNameNumber;
> > +    }
> > +  }
> > +
> > +  if (CapsuleNameTotalNumber == mCapsuleTotalNumber) {
> > +    mCapsuleNamePtr = (CHAR16 **) AllocateZeroPool (sizeof (CHAR16 *)
> *
> > mCapsuleTotalNumber);
> > +    if (mCapsuleNamePtr == NULL) {
> > +      DEBUG ((DEBUG_ERROR, "Allocate mCapsuleNamePtr fail!\n"));
> > +      FreePool (mCapsulePtr);
> > +      FreePool (mCapsuleStatusArray);
> > +      FreePool (CapsuleNameCapsulePtr);
> > +      mCapsulePtr         = NULL;
> > +      mCapsuleStatusArray = NULL;
> > +      mCapsuleTotalNumber = 0;
> > +      return ;
> > +    }
> > +
> > +    for (Index = 0, Index3 = 0; Index < CapsuleNameCapsuleTotalNumber;
> > Index ++) {
> > +      CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity
> > (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
> > +      if (CapsuleNameAddress != NULL ) {
> > +        for (Index2 = 0; Index2 < CapsuleNameNumber; Index2 ++) {
> > +          mCapsuleNamePtr[Index3 ++] = (CHAR16 *)(UINTN)
> > CapsuleNameAddress[Index2];
> > +        }
> > +      }
> > +    }
> > +  } else {
> > +    mCapsuleNamePtr = NULL;
> > +  }
> > +
> > +  if (CapsuleNameCapsulePtr != NULL) {
> > +    FreePool (CapsuleNameCapsulePtr);
> > +  }
> >  }
> >
> >  /**
> >    This function returns if all capsule images are processed.
> >
> > @@ -394,10 +499,11 @@ ProcessTheseCapsules (
> >    EFI_CAPSULE_HEADER          *CapsuleHeader;
> >    UINT32                      Index;
> >    ESRT_MANAGEMENT_PROTOCOL    *EsrtManagement;
> >    UINT16                      EmbeddedDriverCount;
> >    BOOLEAN                     ResetRequired;
> > +  CHAR16                      *CapsuleName;
> >
> >    REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE |
> > PcdGet32(PcdStatusCodeSubClassCapsule) |
> > PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));
> >
> >    if (FirstRound) {
> >      InitCapsulePtr ();
> > @@ -406,10 +512,11 @@ ProcessTheseCapsules (
> >    if (mCapsuleTotalNumber == 0) {
> >      //
> >      // We didn't find a hob, so had no errors.
> >      //
> >      DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule
> update
> > boot mode.\n"));
> > +    mNeedReset = TRUE;
> 
> 
> According to the API description of ProcessCapsules():
> 
> '''
> If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.
> '''
> 
> After the above change (I assume mCapsuleTotalNumber == 0 means no
> Capsule
> Hob), a system reset will be triggered. May I know the purpose for such
> change?
> 

For Capsule On Disk, no capsule hob means the Cod temp relocations file is corrupted, which also means current boot is insecure.
Then force reset to re-apply normal boot platform secure policy.
I will update the description. Do you have comments for it?


BR,
Wei Xu



> Best Regards,
> Hao Wu
> 
> 
> >      return EFI_SUCCESS;
> >    }
> >
> >    if (AreAllImagesProcessed ()) {
> >      return EFI_SUCCESS;
> > @@ -428,14 +535,15 @@ ProcessTheseCapsules (
> >    //
> >    // If Windows UX capsule exist, process it first
> >    //
> >    for (Index = 0; Index < mCapsuleTotalNumber; Index++) {
> >      CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
> > +    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL :
> > mCapsuleNamePtr[Index];
> >      if (CompareGuid (&CapsuleHeader->CapsuleGuid,
> > &gWindowsUxCapsuleGuid)) {
> >        DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n",
> > CapsuleHeader));
> >        DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));
> > -      Status = ProcessThisCapsuleImage (CapsuleHeader, NULL);
> > +      Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName,
> > NULL);
> >        mCapsuleStatusArray [Index] = EFI_SUCCESS;
> >        DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n",
> Status));
> >        break;
> >      }
> >    }
> > @@ -449,10 +557,11 @@ ProcessTheseCapsules (
> >      if (mCapsuleStatusArray [Index] != EFI_NOT_READY) {
> >        // already processed
> >        continue;
> >      }
> >      CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
> > +    CapsuleName = (mCapsuleNamePtr == NULL) ? NULL :
> > mCapsuleNamePtr[Index];
> >      if (!CompareGuid (&CapsuleHeader->CapsuleGuid,
> > &gWindowsUxCapsuleGuid)) {
> >        //
> >        // Call capsule library to process capsule image.
> >        //
> >        EmbeddedDriverCount = 0;
> > @@ -469,11 +578,11 @@ ProcessTheseCapsules (
> >        }
> >
> >        if ((!FirstRound) || (EmbeddedDriverCount == 0)) {
> >          DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n",
> > CapsuleHeader));
> >          ResetRequired = FALSE;
> > -        Status = ProcessThisCapsuleImage (CapsuleHeader, &ResetRequired);
> > +        Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName,
> > &ResetRequired);
> >          mCapsuleStatusArray [Index] = Status;
> >          DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status));
> >
> >          if (Status != EFI_NOT_READY) {
> >            if (EFI_ERROR(Status)) {
> > diff --git
> > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> > index 6ad766d65a..0ec5f20676 100644
> > --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> > +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c
> > @@ -1,9 +1,9 @@
> >  /** @file
> >    DXE capsule report related function.
> >
> > -  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
> > +  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> >
> >  #include <PiDxe.h>
> > @@ -27,10 +27,22 @@
> >  #include <Library/DevicePathLib.h>
> >  #include <Library/CapsuleLib.h>
> >
> >  #include <IndustryStandard/WindowsUxCapsule.h>
> >
> > +/**
> > +  This routine is called to clear CapsuleOnDisk Relocation Info variable.
> > +  Total Capsule On Disk length is recorded in this variable
> > +
> > +  @retval EFI_SUCCESS   Capsule On Disk flags are cleared
> > +
> > +**/
> > +EFI_STATUS
> > +CoDClearCapsuleRelocationInfo(
> > +  VOID
> > +  );
> > +
> >  /**
> >    Get current capsule last variable index.
> >
> >    @return Current capsule last variable index.
> >    @retval -1  No current capsule last variable.
> > @@ -172,44 +184,55 @@ RecordCapsuleStatusVariable (
> >    @param[in] CapsuleHeader  The capsule image header
> >    @param[in] CapsuleStatus  The capsule process stauts
> >    @param[in] PayloadIndex   FMP payload index
> >    @param[in] ImageHeader    FMP image header
> >    @param[in] FmpDevicePath  DevicePath associated with the FMP
> producer
> > +  @param[in] CapFileName    Capsule file name
> >
> >    @retval EFI_SUCCESS          The capsule status variable is recorded.
> >    @retval EFI_OUT_OF_RESOURCES No resource to record the capsule
> status
> > variable.
> >  **/
> >  EFI_STATUS
> >  RecordFmpCapsuleStatusVariable (
> >    IN EFI_CAPSULE_HEADER                            *CapsuleHeader,
> >    IN EFI_STATUS                                    CapsuleStatus,
> >    IN UINTN                                         PayloadIndex,
> >    IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
> > *ImageHeader,
> > -  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath OPTIONAL
> > +  IN EFI_DEVICE_PATH_PROTOCOL                      *FmpDevicePath, OPTIONAL
> > +  IN CHAR16                                        *CapFileName    OPTIONAL
> >    )
> >  {
> >    EFI_CAPSULE_RESULT_VARIABLE_HEADER
> *CapsuleResultVariableHeader;
> >    EFI_CAPSULE_RESULT_VARIABLE_FMP     *CapsuleResultVariableFmp;
> >    EFI_STATUS                          Status;
> >    UINT8                               *CapsuleResultVariable;
> >    UINTN                               CapsuleResultVariableSize;
> >    CHAR16                              *DevicePathStr;
> >    UINTN                               DevicePathStrSize;
> > +  UINTN                               CapFileNameSize;
> > +
> > +  DevicePathStr   = NULL;
> > +  CapFileNameSize = sizeof(CHAR16);
> >
> > -  DevicePathStr = NULL;
> >    if (FmpDevicePath != NULL) {
> >      DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE,
> FALSE);
> >    }
> >    if (DevicePathStr != NULL) {
> >      DevicePathStrSize = StrSize(DevicePathStr);
> >    } else {
> >      DevicePathStrSize = sizeof(CHAR16);
> >    }
> > +
> > +  if (CapFileName != NULL) {
> > +    CapFileNameSize = StrSize(CapFileName);
> > +  }
> > +
> >    //
> > -  // Allocate zero CHAR16 for CapsuleFileName.
> > +  // Allocate room for CapsuleFileName.
> >    //
> > -  CapsuleResultVariableSize =
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) +
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) +
> > DevicePathStrSize;
> > +  CapsuleResultVariableSize =
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) +
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize +
> > DevicePathStrSize;
> > +
> >    CapsuleResultVariable     = AllocateZeroPool (CapsuleResultVariableSize);
> >    if (CapsuleResultVariable == NULL) {
> >      return EFI_OUT_OF_RESOURCES;
> >    }
> >    CapsuleResultVariableHeader = (VOID *)CapsuleResultVariable;
> > @@ -223,12 +246,17 @@ RecordFmpCapsuleStatusVariable (
> >    CapsuleResultVariableFmp = (VOID *)(CapsuleResultVariable +
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER));
> >    CapsuleResultVariableFmp->Version = 0x1;
> >    CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;
> >    CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader-
> > >UpdateImageIndex;
> >    CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId,
> > &ImageHeader->UpdateImageTypeId);
> > +
> > +  if (CapFileName != NULL) {
> > +    CopyMem((UINT8 *)CapsuleResultVariableFmp +
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName,
> > CapFileNameSize);
> > +  }
> > +
> >    if (DevicePathStr != NULL) {
> > -    CopyMem ((UINT8 *)CapsuleResultVariableFmp +
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16),
> > DevicePathStr, DevicePathStrSize);
> > +    CopyMem ((UINT8 *)CapsuleResultVariableFmp +
> > sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize,
> > DevicePathStr, DevicePathStrSize);
> >      FreePool (DevicePathStr);
> >      DevicePathStr = NULL;
> >    }
> >
> >    Status = EFI_SUCCESS;
> > @@ -398,10 +426,35 @@ InitCapsuleUpdateVariable (
> >      }
> >      Index++;
> >    }
> >  }
> >
> > +/**
> > +  Initialize capsule relocation info variable.
> > +**/
> > +VOID
> > +InitCapsuleRelocationInfo (
> > +  VOID
> > +  )
> > +{
> > +  EFI_STATUS                   Status;
> > +  EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
> > +
> > +  CoDClearCapsuleRelocationInfo();
> > +
> > +  //
> > +  // Unlock Capsule On Disk relocation Info variable only when Capsule On
> > Disk flag is enabled
> > +  //
> > +  if (!CoDCheckCapsuleOnDiskFlag()) {
> > +    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL,
> > (VOID **) &VariableLock);
> > +    if (!EFI_ERROR (Status)) {
> > +      Status = VariableLock->RequestToLock (VariableLock,
> > COD_RELOCATION_INFO_VAR_NAME, &gEfiCapsuleVendorGuid);
> > +      ASSERT_EFI_ERROR (Status);
> > +    }
> > +  }
> > +}
> > +
> >  /**
> >    Initialize capsule related variables.
> >  **/
> >  VOID
> >  InitCapsuleVariable (
> > @@ -409,10 +462,12 @@ InitCapsuleVariable (
> >    )
> >  {
> >    InitCapsuleUpdateVariable();
> >    InitCapsuleMaxVariable();
> >    InitCapsuleLastVariable();
> > +  InitCapsuleRelocationInfo();
> > +
> >    //
> >    // No need to clear L"Capsule####", because OS/APP should refer
> > L"CapsuleLast"
> >    // to check status and delete them.
> >    //
> >  }
> > diff --git
> > a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > index 2c93e68700..bf56f4623f 100644
> > ---
> a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > +++
> > b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
> > @@ -1,11 +1,11 @@
> >  ## @file
> >  #  Capsule library instance for DXE_RUNTIME_DRIVER.
> >  #
> >  #  Capsule library instance for DXE_RUNTIME_DRIVER module types.
> >  #
> > -#  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
> > +#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >  #
> >  ##
> >
> >  [Defines]
> > @@ -66,8 +66,9 @@
> >    gEfiCapsuleReportGuid
> >    gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> > Variable:L"CapsuleUpdateData"
> >    gEfiEndOfDxeEventGroupGuid              ## CONSUMES ## Event
> >    gEfiEventReadyToBootGuid                ## CONSUMES ## Event
> >    gEfiEventVirtualAddressChangeGuid       ## CONSUMES ## Event
> > +  gEdkiiCapsuleOnDiskNameGuid             ## SOMETIMES_CONSUMES ##
> > GUID
> >
> >  [Depex]
> >    gEfiVariableWriteArchProtocolGuid
> > diff --git a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> > b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> > index 06a1abe16b..39e37cffcd 100644
> > --- a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> > +++ b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c
> > @@ -1,9 +1,9 @@
> >  /** @file
> >    Null Dxe Capsule Library instance does nothing and returns unsupport
> > status.
> >
> > -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
> >  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  **/
> >  #include <Uefi.h>
> >  #include <Library/CapsuleLib.h>
> > @@ -83,5 +83,88 @@ ProcessCapsules (
> >    )
> >  {
> >    return EFI_UNSUPPORTED;
> >  }
> >
> > +
> > +/**
> > +  This routine is called to check if CapsuleOnDisk flag in OsIndications
> > Variable
> > +  is enabled.
> > +
> > +  @retval TRUE     Flag is enabled
> > +  @retval FALSE    Flag is not enabled
> > +
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +CoDCheckCapsuleOnDiskFlag(
> > +  VOID
> > +  )
> > +{
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  This routine is called to clear CapsuleOnDisk flags including OsIndications
> > and BootNext variable.
> > +
> > +  @retval EFI_SUCCESS   All Capsule On Disk flags are cleared
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDClearCapsuleOnDiskFlag(
> > +  VOID
> > +  )
> > +{
> > +  return EFI_UNSUPPORTED;
> > +}
> > +
> > +/**
> > +  Relocate Capsule on Disk from EFI system partition.
> > +
> > +  Two solution to deliver Capsule On Disk:
> > +  Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On
> > Disk to memory and call UpdateCapsule().
> > +  Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On
> > Disk to a platform-specific NV storage
> > +  device with BlockIo protocol.
> > +
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  Side Effects:
> > +    Capsule Delivery Supported Flag in OsIndication variable and BootNext
> > variable will be cleared.
> > +    Solution B: Content corruption. Block IO write directly touches low level
> > write. Orignal partitions, file
> > +  systems of the relocation device will be corrupted.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +
> > +  @retval EFI_SUCCESS   Capsule on Disk images are sucessfully relocated.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDRelocateCapsule(
> > +  UINTN     MaxRetry
> > +  )
> > +{
> > +  return EFI_UNSUPPORTED;
> > +}
> > +
> > +/**
> > +  Remove the temp file from the root of EFI System Partition.
> > +  Device enumeration like USB costs time, user can input MaxRetry to tell
> > function to retry.
> > +  Function will stall 100ms between each retry.
> > +
> > +  @param[in]    MaxRetry             Max Connection Retry. Stall 100ms
> between
> > each connection try to ensure
> > +                                     devices like USB can get enumerated.
> > +
> > +  @retval EFI_SUCCESS   Remove the temp file successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +CoDRemoveTempFile (
> > +  UINTN    MaxRetry
> > +  )
> > +{
> > +  return EFI_UNSUPPORTED;
> > +}
> > --
> > 2.16.2.windows.1
> >
> >
> > 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.
  2019-06-19  7:55     ` Xu, Wei6
@ 2019-06-19  8:16       ` Wu, Hao A
  2019-06-19  8:19         ` Wu, Hao A
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-19  8:16 UTC (permalink / raw)
  To: Xu, Wei6, devel@edk2.groups.io; +Cc: Wang, Jian J, Zhang, Chao B

> 
> No,  that's how it is designed.
> PcdCodRelocationDevPath is used by platform to specify a device to store
> temp Cod relocation file.
> If this PCD is not available, it means that platform doesn't have a requirement
> to store the file to a specific place.
> Then save the file to the device where the capsules are placed.
> 

Got it.
I suggest to add comments to explicitly mention this in the codes.

> 
> For Capsule On Disk, no capsule hob means the Cod temp relocations file is
> corrupted, which also means current boot is insecure.
> Then force reset to re-apply normal boot platform secure policy.
> I will update the description. Do you have comments for it?
>

If the behavior change of the 'ProcessCapsules' API is covered during
design review process, then updating the comments is good to me.

Best Regards,
Hao Wu

> 
> BR,
> Wei Xu

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.
  2019-06-19  8:16       ` Wu, Hao A
@ 2019-06-19  8:19         ` Wu, Hao A
  2019-06-19  8:23           ` Xu, Wei6
  0 siblings, 1 reply; 33+ messages in thread
From: Wu, Hao A @ 2019-06-19  8:19 UTC (permalink / raw)
  To: devel@edk2.groups.io, Wu, Hao A, Xu, Wei6; +Cc: Wang, Jian J, Zhang, Chao B

Forgot to mention, please help to handle other comments in the first reply
to the patch. Thanks in advance.

Best Regards,
Hao Wu


> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Wu, Hao A
> Sent: Wednesday, June 19, 2019 4:17 PM
> To: Xu, Wei6; devel@edk2.groups.io
> Cc: Wang, Jian J; Zhang, Chao B
> Subject: Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On
> Disk APIs into CapsuleLib.
> 
> >
> > No,  that's how it is designed.
> > PcdCodRelocationDevPath is used by platform to specify a device to store
> > temp Cod relocation file.
> > If this PCD is not available, it means that platform doesn't have a
> requirement
> > to store the file to a specific place.
> > Then save the file to the device where the capsules are placed.
> >
> 
> Got it.
> I suggest to add comments to explicitly mention this in the codes.
> 
> >
> > For Capsule On Disk, no capsule hob means the Cod temp relocations file is
> > corrupted, which also means current boot is insecure.
> > Then force reset to re-apply normal boot platform secure policy.
> > I will update the description. Do you have comments for it?
> >
> 
> If the behavior change of the 'ProcessCapsules' API is covered during
> design review process, then updating the comments is good to me.
> 
> Best Regards,
> Hao Wu
> 
> >
> > BR,
> > Wei Xu
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.
  2019-06-19  8:19         ` Wu, Hao A
@ 2019-06-19  8:23           ` Xu, Wei6
  0 siblings, 0 replies; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-19  8:23 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io; +Cc: Wang, Jian J, Zhang, Chao B

Thank you very much.
Of course, I will follow up all the other comments.

BR,
Wei
> -----Original Message-----
> From: Wu, Hao A
> Sent: Wednesday, June 19, 2019 4:20 PM
> To: devel@edk2.groups.io; Wu, Hao A <hao.a.wu@intel.com>; Xu, Wei6
> <wei6.xu@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: RE: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On
> Disk APIs into CapsuleLib.
> 
> Forgot to mention, please help to handle other comments in the first reply to
> the patch. Thanks in advance.
> 
> Best Regards,
> Hao Wu
> 
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> > Wu, Hao A
> > Sent: Wednesday, June 19, 2019 4:17 PM
> > To: Xu, Wei6; devel@edk2.groups.io
> > Cc: Wang, Jian J; Zhang, Chao B
> > Subject: Re: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On
> > Disk APIs into CapsuleLib.
> >
> > >
> > > No,  that's how it is designed.
> > > PcdCodRelocationDevPath is used by platform to specify a device to
> > > store temp Cod relocation file.
> > > If this PCD is not available, it means that platform doesn't have a
> > requirement
> > > to store the file to a specific place.
> > > Then save the file to the device where the capsules are placed.
> > >
> >
> > Got it.
> > I suggest to add comments to explicitly mention this in the codes.
> >
> > >
> > > For Capsule On Disk, no capsule hob means the Cod temp relocations
> > > file is corrupted, which also means current boot is insecure.
> > > Then force reset to re-apply normal boot platform secure policy.
> > > I will update the description. Do you have comments for it?
> > >
> >
> > If the behavior change of the 'ProcessCapsules' API is covered during
> > design review process, then updating the comments is good to me.
> >
> > Best Regards,
> > Hao Wu
> >
> > >
> > > BR,
> > > Wei Xu
> >
> > 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
  2019-06-12  7:49   ` Wu, Hao A
@ 2019-06-19  8:40     ` Xu, Wei6
  2019-06-19  8:59       ` Ni, Ray
  0 siblings, 1 reply; 33+ messages in thread
From: Xu, Wei6 @ 2019-06-19  8:40 UTC (permalink / raw)
  To: Wu, Hao A, devel@edk2.groups.io; +Cc: Wang, Jian J, Zhang, Chao B

> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);  Status =
> > + PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *)
> > PcdGetPtr(PcdCoDRelocationFileName));
> 
> 
> Buffer for 'PcdRecoveryFileName' may not be big enough to hold the content
> in 'PcdCoDRelocationFileName'.
> 
> I think there might be a chance for the above PcdSetPtrS() call to fail.
>


Thanks a lot for the comments.
Yes, 'PcdRecoveryFileName' should be larger than 'PcdCoDRelocationFileName'.
I think no need to update the code, since these two PCDs are fixed during build time.
I will update the description of 'PcdCoDRelocationFileName' to mention: it must be smaller than 'PcdRecoveryFileName', otherwise failure may occur.

Do you have comments about it?
Thanks again.


BR,
Wei

> -----Original Message-----
> From: Wu, Hao A
> Sent: Wednesday, June 12, 2019 3:49 PM
> To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: RE: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> CapsuleOnDiskLoadPei PEIM.
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> > Xu,
> > Wei6
> > Sent: Wednesday, June 05, 2019 11:42 PM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> > Subject: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> > CapsuleOnDiskLoadPei PEIM.
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> >
> > This module provides PPI to load Capsule On Disk temp relocation file
> > from Root Directory file system, retrieve the capsules from the temp
> > file and create capsule hobs for these capsules.
> >
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Chao B Zhang <chao.b.zhang@intel.com>
> > Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> > ---
> >  MdeModulePkg/MdeModulePkg.dsc                      |   4 +
> >  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    | 442
> > +++++++++++++++++++++
> >  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |  64 +++
> > .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |  15 +
> >  .../CapsuleOnDiskLoadPeiExtra.uni                  |  14 +
> >  5 files changed, 539 insertions(+)
> >  create mode 100644
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
> >  create mode 100644
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> > f
> >  create mode 100644
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.u
> > ni
> >  create mode 100644
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiEx
> > tra.uni
> 
> Since this a new module, could you help to follow the recommendation in
> https://edk2.groups.io/g/devel/message/39655?p=,,,20,0,0,0::Created,,Uefi
> DebugLibStdErr,20,2,0,31318888
> 
> to add/update 'static' (lower case) for global variables/functions whose
> scope is limited within a single file?
> 
> >
> > diff --git a/MdeModulePkg/MdeModulePkg.dsc
> > b/MdeModulePkg/MdeModulePkg.dsc index 995fd805e1..615edddbcc
> 100644
> > --- a/MdeModulePkg/MdeModulePkg.dsc
> > +++ b/MdeModulePkg/MdeModulePkg.dsc
> > @@ -197,10 +197,13 @@
> >    gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
> >
> > +[PcdsDynamicExDefault]
> > +
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
> > +
> >  [Components]
> >    MdeModulePkg/Application/HelloWorld/HelloWorld.inf
> >    MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
> >    MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
> >
> > @@ -315,10 +318,11 @@
> >
> >
> NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMainte
> > nanceManagerUiLib.inf
> >    }
> >
> >
> MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManager
> > Dxe.inf
> >
> >
> MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.i
> > nf
> >    MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
> > +
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> > f
> >    MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> >
> MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
> >    MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> >
> >
> MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleD
> > xe.inf
> >
> >
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDx
> > e.inf
> > diff --git
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > c
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > c
> > new file mode 100644
> > index 0000000000..40d25f3d3b
> > --- /dev/null
> > +++
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > c
> > @@ -0,0 +1,442 @@
> > +/** @file
> > +  Recovery module.
> > +
> > +  Caution: This module requires additional review when modified.
> > +  This module will have external input - Capsule-on-Disk Temp
> > + Relocation
> > image.
> > +  This external input must be validated carefully to avoid security
> > + issue like  buffer overflow, integer overflow.
> > +
> > +  RetrieveRelocatedCapsule() will receive untrusted input and do
> > + basic
> > validation.
> > +
> > +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +//
> > +// The package level header files this module uses // #include
> > +<Uefi.h> #include <PiPei.h>
> > +
> > +//
> > +// The protocols, PPI and GUID defintions for this module // #include
> > +<Ppi/MasterBootMode.h> #include <Ppi/FirmwareVolumeInfo.h>
> #include
> > +<Ppi/ReadOnlyVariable2.h> #include <Ppi/Capsule.h> #include
> > +<Ppi/CapsuleOnDisk.h> #include <Ppi/DeviceRecoveryModule.h>
> > +
> > +#include <Guid/FirmwareFileSystem2.h> // // The Library classes this
> > +module consumes // #include <Library/DebugLib.h> #include
> > +<Library/PeimEntryPoint.h> #include <Library/PeiServicesLib.h>
> > +#include <Library/HobLib.h> #include <Library/BaseMemoryLib.h>
> > +#include <Library/MemoryAllocationLib.h> #include <Library/PcdLib.h>
> > +#include <Library/CapsuleLib.h> #include
> > +<Library/ReportStatusCodeLib.h>
> > +
> > +/**
> > +  Loads a DXE capsule from some media into memory and updates the
> HOB
> > table
> > +  with the DXE firmware volume information.
> > +
> > +  @param[in]  PeiServices   General-purpose services that are available to
> > every PEIM.
> > +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> > instance.
> > +
> > +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> > +  @retval EFI_DEVICE_ERROR   A device error occurred.
> > +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +LoadCapsuleOnDisk (
> > +  IN EFI_PEI_SERVICES              **PeiServices,
> > +  IN EFI_PEI_CAPSULE_ON_DISK_PPI   *This
> > +  );
> > +
> > +EFI_PEI_CAPSULE_ON_DISK_PPI mCapsuleOnDiskPpi = {
> > +  LoadCapsuleOnDisk
> > +};
> > +
> > +EFI_PEI_PPI_DESCRIPTOR mCapsuleOnDiskPpiList = {
> > +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > +  &gEdkiiPeiCapsuleOnDiskPpiGuid,
> > +  &mCapsuleOnDiskPpi
> > +};
> > +
> > +/**
> > +  Determine if capsule comes from memory by checking Capsule PPI.
> > +
> > +  @param[in]  PeiServices General purpose services available to every
> PEIM.
> > +
> > +  @retval TRUE   Capsule comes from memory.
> > +  @retval FALSE  No capsule comes from memory.
> > +
> > +**/
> > +STATIC
> > +BOOLEAN
> > +CheckCapsuleFromRam (
> > +  IN CONST EFI_PEI_SERVICES          **PeiServices
> > +  )
> > +{
> > +  EFI_STATUS              Status;
> > +  PEI_CAPSULE_PPI         *Capsule;
> > +
> > +  Status = PeiServicesLocatePpi (
> > +             &gPeiCapsulePpiGuid,
> 
> 
> Suggest to use gEfiPeiCapsulePpiGuid here.
> gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.
> 
> 
> > +             0,
> > +             NULL,
> > +             (VOID **) &Capsule
> > +             );
> > +  if (!EFI_ERROR(Status)) {
> > +    Status = Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES
> > **)PeiServices);
> > +    if (!EFI_ERROR(Status)) {
> > +      return TRUE;
> > +    }
> > +  }
> > +
> > +  return FALSE;
> > +}
> > +
> > +/**
> > +  Determine if it is a Capsule On Disk mode.
> > +
> > +  @retval TRUE         Capsule On Disk mode.
> > +  @retval FALSE        Not capsule On Disk mode.
> > +
> > +**/
> > +BOOLEAN
> > +IsCapsuleOnDiskMode (
> > +  VOID
> > +  )
> > +{
> > +  EFI_STATUS                      Status;
> > +  UINTN                           Size;
> > +  EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
> > +  BOOLEAN                         CodRelocInfo;
> > +
> > +  Status = PeiServicesLocatePpi (
> > +             &gEfiPeiReadOnlyVariable2PpiGuid,
> > +             0,
> > +             NULL,
> > +             (VOID **) &PPIVariableServices
> > +             );
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  Size = sizeof (BOOLEAN);
> > +  Status = PPIVariableServices->GetVariable (
> > +                                  PPIVariableServices,
> > +                                  COD_RELOCATION_INFO_VAR_NAME,
> > +                                  &gEfiCapsuleVendorGuid,
> > +                                  NULL,
> > +                                  &Size,
> > +                                  &CodRelocInfo
> > +                                  );
> > +
> > +  if (EFI_ERROR (Status) || Size != sizeof(BOOLEAN) || CodRelocInfo
> > + != TRUE)
> 
> 
> For 'CodRelocInfo != TRUE', variable of BOOLEAN type can be directly used in
> the 'if' statement without comparing with 'TRUE' or 'FALSE'.
> 
> 
> > {
> > +    DEBUG (( DEBUG_ERROR, "Error Get CodRelocationInfo variable
> > + %r!\n",
> > Status));
> > +    return FALSE;
> > +  }
> > +
> > +  return TRUE;
> > +}
> > +
> > +/**
> > +  Gets capsule images from relocated capsule buffer.
> > +  Create Capsule hob for each Capsule.
> > +
> > +  Caution: This function may receive untrusted input.
> > +  Capsule-on-Disk Temp Relocation image is external input, so this
> > + function  will validate Capsule-on-Disk Temp Relocation image to
> > + make sure the
> > content
> > +  is read within the buffer.
> > +
> > +  @param[in]  RelocCapsuleBuf        Buffer pointer to the relocated capsule.
> > +  @param[in]  RelocCapsuleTotalSize  Total size of the relocated capsule.
> > +
> > +  @retval EFI_SUCCESS     Succeed to get capsules and create hob.
> > +  @retval Others          Fail to get capsules and create hob.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +RetrieveRelocatedCapsule (
> > +  IN UINT8                *RelocCapsuleBuf,
> > +  IN UINTN                RelocCapsuleTotalSize
> > +  )
> > +{
> > +  EFI_STATUS               Status;
> > +  UINTN                    Index;
> > +  UINT8                    *CapsuleDataBufEnd;
> > +  UINT8                    *CapsulePtr;
> > +  UINT32                   CapsuleSize;
> > +  UINT64                   TotalImageSize;
> > +  UINTN                    CapsuleNum;
> > +
> > +  CapsuleNum = 0;
> > +
> > +  //
> > +  // Temp file contains at least 2 capsule (including 1 capsule name
> > + capsule)
> > & 1 UINT64
> > +  //
> > +  if (RelocCapsuleTotalSize < sizeof(UINT64) +
> > + sizeof(EFI_CAPSULE_HEADER)
> > * 2) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  CopyMem(&TotalImageSize, RelocCapsuleBuf, sizeof(UINT64));
> > +
> > +  DEBUG ((DEBUG_INFO, "ProcessRelocatedCapsule CapsuleBuf %x
> > TotalCapSize %lx\n",
> > +                      RelocCapsuleBuf, TotalImageSize));
> > +
> > +  RelocCapsuleBuf += sizeof(UINT64);
> > +
> > +  //
> > +  // TempCaspule file length check
> > +  //
> > +  if (MAX_ADDRESS - TotalImageSize <= sizeof(UINT64) ||
> > +      (UINT64)RelocCapsuleTotalSize != TotalImageSize + sizeof(UINT64) ||
> > +      (UINTN)(MAX_ADDRESS -
> > (PHYSICAL_ADDRESS)(UINTN)RelocCapsuleBuf) <= TotalImageSize) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  CapsuleDataBufEnd = RelocCapsuleBuf + TotalImageSize;
> > +
> > +  //
> > +  // TempCapsule file integrity check over Capsule Header to ensure
> > + no data
> > corruption in NV Var & Relocation storage
> > +  //
> > +  CapsulePtr = RelocCapsuleBuf;
> > +
> > +  while (CapsulePtr < CapsuleDataBufEnd) {
> > +    if ((CapsuleDataBufEnd - CapsulePtr) < sizeof(EFI_CAPSULE_HEADER) ||
> > +        ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize <
> > sizeof(EFI_CAPSULE_HEADER) ||
> > +        (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)CapsulePtr) <
> > ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize
> > +        ) {
> > +      break;
> > +    }
> > +    CapsulePtr += ((EFI_CAPSULE_HEADER *)CapsulePtr)-
> >CapsuleImageSize;
> > +    CapsuleNum ++;
> > +  }
> > +
> > +  if (CapsulePtr != CapsuleDataBufEnd) {
> > +    Status = EFI_INVALID_PARAMETER;
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // Capsule count must be less than PcdCapsuleMax, avoid building
> > + too
> > many CvHobs to occupy all the free space in HobList.
> > +  //
> > +  if (CapsuleNum > PcdGet16 (PcdCapsuleMax)) {
> > +    Status = EFI_INVALID_PARAMETER;
> > +    goto EXIT;
> > +  }
> > +
> > +  //
> > +  // Re-iterate the capsule buffer to create Capsule hob & Capsule
> > + Name Str
> > Hob for each Capsule saved in relocated capsule file
> > +  //
> > +  CapsulePtr = RelocCapsuleBuf;
> > +  Index      = 0;
> > +  while (CapsulePtr < CapsuleDataBufEnd) {
> > +    CapsuleSize = ((EFI_CAPSULE_HEADER *)CapsulePtr)-
> >CapsuleImageSize;
> > +    BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsulePtr,
> > + CapsuleSize);
> > +
> > +    DEBUG((DEBUG_INFO, "Capsule saved in address %x size %x\n",
> > CapsulePtr, CapsuleSize));
> > +
> > +    CapsulePtr += CapsuleSize;
> > +    Index++;
> > +  }
> > +
> > +EXIT:
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Recovery module entrypoint
> > +
> > +  @param[in] FileHandle   Handle of the file being invoked.
> > +  @param[in] PeiServices  Describes the list of possible PEI Services.
> > +
> > +  @return EFI_SUCCESS Recovery module is initialized.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +InitializeCapsuleOnDiskLoad (
> > +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> > +  IN CONST EFI_PEI_SERVICES     **PeiServices
> > +  )
> > +{
> > +  EFI_STATUS  Status;
> > +  UINTN       BootMode;
> > +  UINTN       FileNameSize;
> > +
> > +  BootMode = GetBootModeHob();
> > +  ASSERT(BootMode == BOOT_ON_FLASH_UPDATE);
> > +
> > +  //
> > +  // If there are capsules provisioned in memory, quit.
> > +  // Only one capsule resource is accept, CapsuleOnRam's priority is
> > + higher
> > than CapsuleOnDisk.
> > +  //
> > +  if (CheckCapsuleFromRam(PeiServices)) {
> > +    DEBUG((DEBUG_ERROR, "Capsule On Memory Detected! Quit.\n"));
> > +    return EFI_ABORTED;
> > +  }
> > +
> > +  DEBUG_CODE (
> > +   VOID *CapsuleOnDiskModePpi;
> > +
> > +  if (!IsCapsuleOnDiskMode()){
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  //
> > +  // Check Capsule On Disk Relocation flag. If exists, load capsule &
> > + create
> > Capsule Hob
> > +  //
> > +  Status = PeiServicesLocatePpi (
> > +             &gEfiPeiBootInCapsuleOnDiskModePpiGuid,
> > +             0,
> > +             NULL,
> > +             (VOID **)&CapsuleOnDiskModePpi
> > +             );
> > +    if (EFI_ERROR(Status)) {
> > +      DEBUG((DEBUG_ERROR, "Locate CapsuleOnDiskModePpi error %x\n",
> > Status));
> > +      return Status;
> > +    }
> > +  );
> > +
> > +  Status = (**PeiServices).InstallPpi (PeiServices,
> > + &mCapsuleOnDiskPpiList);
> 
> 
> Minor one, suggest to directly use PeiServicesInstallPpi().
> 
> 
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);  Status =
> > + PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *)
> > PcdGetPtr(PcdCoDRelocationFileName));
> 
> 
> Buffer for 'PcdRecoveryFileName' may not be big enough to hold the content
> in 'PcdCoDRelocationFileName'.
> 
> I think there might be a chance for the above PcdSetPtrS() call to fail.
> 
> 
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Loads a DXE capsule from some media into memory and updates the
> HOB
> > table
> > +  with the DXE firmware volume information.
> > +
> > +  @param[in]  PeiServices   General-purpose services that are available to
> > every PEIM.
> > +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> > instance.
> > +
> > +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> > +  @retval EFI_DEVICE_ERROR   A device error occurred.
> > +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +LoadCapsuleOnDisk (
> > +  IN EFI_PEI_SERVICES                     **PeiServices,
> > +  IN EFI_PEI_CAPSULE_ON_DISK_PPI          *This
> > +  )
> > +{
> > +  EFI_STATUS                          Status;
> > +  EFI_PEI_DEVICE_RECOVERY_MODULE_PPI  *DeviceRecoveryPpi;
> > +  UINTN                               NumberRecoveryCapsules;
> > +  UINTN                               Instance;
> > +  UINTN                               CapsuleInstance;
> > +  UINTN                               CapsuleSize;
> > +  EFI_GUID                            CapsuleType;
> > +  VOID                                *CapsuleBuffer;
> > +
> > +  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Load Capsule On Disk
> Entry\n"));
> > +
> > +  for (Instance = 0; ; Instance++) {
> > +    Status = PeiServicesLocatePpi (
> > +               &gEfiPeiDeviceRecoveryModulePpiGuid,
> > +               Instance,
> > +               NULL,
> > +               (VOID **)&DeviceRecoveryPpi
> > +               );
> > +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LocateRecoveryPpi (%d)
> -
> >  %r\n", Instance, Status));
> > +    if (EFI_ERROR (Status)) {
> > +      if (Instance == 0) {
> > +        REPORT_STATUS_CODE (
> > +          EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> > +          (EFI_SOFTWARE_PEI_MODULE |
> > EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
> > +          );
> > +      }
> > +      break;
> > +    }
> > +    NumberRecoveryCapsules = 0;
> > +    Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
> > +                                  (EFI_PEI_SERVICES **)PeiServices,
> > +                                  DeviceRecoveryPpi,
> > +                                  &NumberRecoveryCapsules
> > +                                  );
> > +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> > GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules,
> > Status));
> > +    if (EFI_ERROR (Status)) {
> > +      continue;
> > +    }
> > +
> > +    for (CapsuleInstance = 1; CapsuleInstance <=
> > + NumberRecoveryCapsules;
> > CapsuleInstance++) {
> > +      CapsuleSize = 0;
> > +      Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
> > +                                    (EFI_PEI_SERVICES **)PeiServices,
> > +                                    DeviceRecoveryPpi,
> > +                                    CapsuleInstance,
> > +                                    &CapsuleSize,
> > +                                    &CapsuleType
> > +                                    );
> > +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> GetRecoveryCapsuleInfo
> > (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
> > +      if (EFI_ERROR (Status)) {
> > +        break;
> > +      }
> > +
> > +      //
> > +      // Allocate the memory so that it gets preserved into DXE.
> > +      // Capsule is special because it may need to populate to system table
> > +      //
> > +      CapsuleBuffer = AllocateRuntimePages (EFI_SIZE_TO_PAGES
> > (CapsuleSize));
> > +
> > +      if (CapsuleBuffer == NULL) {
> > +        DEBUG ((DEBUG_ERROR, "LoadCapsuleOnDisk -
> > + AllocateRuntimePages
> > fail\n"));
> > +        continue;
> > +      }
> > +
> > +      Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
> > +                                    (EFI_PEI_SERVICES **)PeiServices,
> > +                                    DeviceRecoveryPpi,
> > +                                    CapsuleInstance,
> > +                                    CapsuleBuffer
> > +                                    );
> > +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LoadRecoveryCapsule
> > (%d) - %r\n", CapsuleInstance, Status));
> > +      if (EFI_ERROR (Status)) {
> > +        FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
> > +        break;
> > +      }
> > +
> > +      //
> > +      // Capsule Update Mode, Split relocated Capsule buffer into
> > + different
> > capsule vehical hobs.
> > +      //
> > +      Status = RetrieveRelocatedCapsule(CapsuleBuffer, CapsuleSize);
> > +
> > +      break;
> > +    }
> > +
> > +    if (EFI_ERROR (Status)) {
> > +      REPORT_STATUS_CODE (
> > +        EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> > +        (EFI_SOFTWARE_PEI_MODULE |
> > EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
> > +        );
> > +    }
> > +
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // Any attack against GPT, Relocation Info Variable or temp
> > + relocation file
> > will result in no Capsule HOB and return EFI_NOT_FOUND.
> > +  // After flow to DXE phase. since no capsule hob is detected.
> > + Platform will
> > clear Info flag and force restart.
> > +  // No volunerability will be exposed  //
> > +
> > +  return EFI_NOT_FOUND;
> > +}
> > diff --git
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > inf
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > inf
> > new file mode 100644
> > index 0000000000..4af07440b7
> > --- /dev/null
> > +++
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > inf
> > @@ -0,0 +1,64 @@
> > +## @file
> > +# Load Capsule on Disk module.
> > +#
> > +# Load Capsule On Disk from Root Directory file system. Create CV hob
> > +# based on temporary Capsule On Disk file.
> > +#
> > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> # #
> > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = CapsuleOnDiskLoadPei
> > +  MODULE_UNI_FILE                = CapsuleOnDiskLoadPei.uni
> > +  FILE_GUID                      = 8ADEDF9E-2EC8-40fb-AE56-B76D90225D2D
> > +  MODULE_TYPE                    = PEIM
> > +  VERSION_STRING                 = 1.0
> > +  ENTRY_POINT                    = InitializeCapsuleOnDiskLoad
> > +
> > +#
> > +# The following information is for reference only and not required by
> > +the
> > build tools.
> > +#
> > +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> > +#
> > +
> > +[Sources]
> > +  CapsuleOnDiskLoadPei.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +
> > +[LibraryClasses]
> > +  PeimEntryPoint
> > +  DebugLib
> > +  HobLib
> > +  BaseMemoryLib
> > +  MemoryAllocationLib
> > +  ReportStatusCodeLib
> > +
> > +[Ppis]
> > +  gEdkiiPeiCapsuleOnDiskPpiGuid           ## PRODUCES
> > +  gEfiPeiReadOnlyVariable2PpiGuid         ## CONSUMES
> > +  gEfiPeiBootInCapsuleOnDiskModePpiGuid   ## SOMETIMES_CONSUMES
> > +  gEfiPeiDeviceRecoveryModulePpiGuid      ## CONSUMES
> > +  gPeiCapsulePpiGuid                      ## CONSUMES
> 
> 
> Suggest to use gEfiPeiCapsulePpiGuid here.
> gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.
> 
> 
> > +
> > +[Guids]
> > +  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> Variable
> > L"CodRelocationInfo"
> > +
> > +[Pcd]
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName
> > ## CONSUMES
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax                            ##
> > CONSUMES
> > +
> > +[PcdEx]
> > +  gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName
> ##
> > PRODUCES
> > +
> > +[depex]
> 
> 
> Minor comment:
> [depex] -> [Depex]
> 
> Best Regards,
> Hao Wu
> 
> 
> > +  gEfiPeiBootInCapsuleOnD
> iskModePpiGuid
> > +
> > +[UserExtensions.TianoCore."ExtraFiles"]
> > +  CapsuleOnDiskLoadPeiExtra.uni
> > diff --git
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > uni
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > uni
> > new file mode 100644
> > index 0000000000..c3eae6a5c2
> > --- /dev/null
> > +++
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > uni
> > @@ -0,0 +1,15 @@
> > +// /** @file
> > +// Caspule On Disk Load module.
> > +//
> > +// Load Capsule On Disk and build CV hob.
> > +//
> > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> //
> > +// SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > +
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US "Caspule On Disk
> > Load module."
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "Load Capsule
> > On Disk and build CV hob."
> > diff --git
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > Extra.uni
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > Extra.uni
> > new file mode 100644
> > index 0000000000..81034f6294
> > --- /dev/null
> > +++
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > Extra.uni
> > @@ -0,0 +1,14 @@
> > +// /** @file
> > +// CapsuleOnDiskLoadPei Localized Strings and Content // // Copyright
> > +(c) 2019, Intel Corporation. All rights reserved.<BR> // //
> > +SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > +
> > +#string STR_PROPERTIES_MODULE_NAME
> > +#language en-US
> > +"CapsuleOnDiskLoad PEI Driver"
> > +
> > +
> > --
> > 2.16.2.windows.1
> >
> >
> > 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
  2019-06-19  8:40     ` Xu, Wei6
@ 2019-06-19  8:59       ` Ni, Ray
  2019-06-20  0:59         ` Wu, Hao A
  0 siblings, 1 reply; 33+ messages in thread
From: Ni, Ray @ 2019-06-19  8:59 UTC (permalink / raw)
  To: devel@edk2.groups.io, Xu, Wei6, Wu, Hao A; +Cc: Wang, Jian J, Zhang, Chao B

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Xu,
> Wei6
> Sent: Wednesday, June 19, 2019 4:41 PM
> To: Wu, Hao A <hao.a.wu@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: Re: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> CapsuleOnDiskLoadPei PEIM.
> 
> > > +  ASSERT_EFI_ERROR (Status);
> > > +
> > > +  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);  Status =
> > > + PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *)
> > > PcdGetPtr(PcdCoDRelocationFileName));
> >
> >
> > Buffer for 'PcdRecoveryFileName' may not be big enough to hold the
> > content in 'PcdCoDRelocationFileName'.
> >
> > I think there might be a chance for the above PcdSetPtrS() call to fail.
> >
> 
> 
> Thanks a lot for the comments.
> Yes, 'PcdRecoveryFileName' should be larger than
> 'PcdCoDRelocationFileName'.
> I think no need to update the code, since these two PCDs are fixed during
> build time.
> I will update the description of 'PcdCoDRelocationFileName' to mention: it
> must be smaller than 'PcdRecoveryFileName', otherwise failure may occur.

But your code doesn't check the status of PcdSetPtrS().

> 
> Do you have comments about it?
> Thanks again.
> 
> 
> BR,
> Wei
> 
> > -----Original Message-----
> > From: Wu, Hao A
> > Sent: Wednesday, June 12, 2019 3:49 PM
> > To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B
> > <chao.b.zhang@intel.com>
> > Subject: RE: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> > CapsuleOnDiskLoadPei PEIM.
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf
> > > Of Xu,
> > > Wei6
> > > Sent: Wednesday, June 05, 2019 11:42 PM
> > > To: devel@edk2.groups.io
> > > Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> > > Subject: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> > > CapsuleOnDiskLoadPei PEIM.
> > >
> > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> > >
> > > This module provides PPI to load Capsule On Disk temp relocation
> > > file from Root Directory file system, retrieve the capsules from the
> > > temp file and create capsule hobs for these capsules.
> > >
> > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > Cc: Hao A Wu <hao.a.wu@intel.com>
> > > Cc: Chao B Zhang <chao.b.zhang@intel.com>
> > > Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> > > ---
> > >  MdeModulePkg/MdeModulePkg.dsc                      |   4 +
> > >  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    | 442
> > > +++++++++++++++++++++
> > >  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |  64 +++
> > > .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |  15 +
> > >  .../CapsuleOnDiskLoadPeiExtra.uni                  |  14 +
> > >  5 files changed, 539 insertions(+)
> > >  create mode 100644
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
> > >  create mode 100644
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> > > f
> > >  create mode 100644
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.u
> > > ni
> > >  create mode 100644
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiEx
> > > tra.uni
> >
> > Since this a new module, could you help to follow the recommendation
> > in
> > https://edk2.groups.io/g/devel/message/39655?p=,,,20,0,0,0::Created,,U
> > efi
> > DebugLibStdErr,20,2,0,31318888
> >
> > to add/update 'static' (lower case) for global variables/functions
> > whose scope is limited within a single file?
> >
> > >
> > > diff --git a/MdeModulePkg/MdeModulePkg.dsc
> > > b/MdeModulePkg/MdeModulePkg.dsc index 995fd805e1..615edddbcc
> > 100644
> > > --- a/MdeModulePkg/MdeModulePkg.dsc
> > > +++ b/MdeModulePkg/MdeModulePkg.dsc
> > > @@ -197,10 +197,13 @@
> > >    gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
> > >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
> > >    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
> > >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
> > >
> > > +[PcdsDynamicExDefault]
> > > +
> > >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
> > > +
> > >  [Components]
> > >    MdeModulePkg/Application/HelloWorld/HelloWorld.inf
> > >    MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
> > >
> MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
> > >
> > > @@ -315,10 +318,11 @@
> > >
> > >
> >
> NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMainte
> > > nanceManagerUiLib.inf
> > >    }
> > >
> > >
> >
> MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManager
> > > Dxe.inf
> > >
> > >
> >
> MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.i
> > > nf
> > >    MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
> > > +
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> > > f
> > >
> MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> > >
> > MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
> > >    MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> > >
> > >
> >
> MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleD
> > > xe.inf
> > >
> > >
> >
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDx
> > > e.inf
> > > diff --git
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > c
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > c
> > > new file mode 100644
> > > index 0000000000..40d25f3d3b
> > > --- /dev/null
> > > +++
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > c
> > > @@ -0,0 +1,442 @@
> > > +/** @file
> > > +  Recovery module.
> > > +
> > > +  Caution: This module requires additional review when modified.
> > > +  This module will have external input - Capsule-on-Disk Temp
> > > + Relocation
> > > image.
> > > +  This external input must be validated carefully to avoid security
> > > + issue like  buffer overflow, integer overflow.
> > > +
> > > +  RetrieveRelocatedCapsule() will receive untrusted input and do
> > > + basic
> > > validation.
> > > +
> > > +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > +
> > > +**/
> > > +
> > > +//
> > > +// The package level header files this module uses // #include
> > > +<Uefi.h> #include <PiPei.h>
> > > +
> > > +//
> > > +// The protocols, PPI and GUID defintions for this module //
> > > +#include <Ppi/MasterBootMode.h> #include
> <Ppi/FirmwareVolumeInfo.h>
> > #include
> > > +<Ppi/ReadOnlyVariable2.h> #include <Ppi/Capsule.h> #include
> > > +<Ppi/CapsuleOnDisk.h> #include <Ppi/DeviceRecoveryModule.h>
> > > +
> > > +#include <Guid/FirmwareFileSystem2.h> // // The Library classes
> > > +this module consumes // #include <Library/DebugLib.h> #include
> > > +<Library/PeimEntryPoint.h> #include <Library/PeiServicesLib.h>
> > > +#include <Library/HobLib.h> #include <Library/BaseMemoryLib.h>
> > > +#include <Library/MemoryAllocationLib.h> #include
> > > +<Library/PcdLib.h> #include <Library/CapsuleLib.h> #include
> > > +<Library/ReportStatusCodeLib.h>
> > > +
> > > +/**
> > > +  Loads a DXE capsule from some media into memory and updates the
> > HOB
> > > table
> > > +  with the DXE firmware volume information.
> > > +
> > > +  @param[in]  PeiServices   General-purpose services that are available
> to
> > > every PEIM.
> > > +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> > > instance.
> > > +
> > > +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> > > +  @retval EFI_DEVICE_ERROR   A device error occurred.
> > > +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +LoadCapsuleOnDisk (
> > > +  IN EFI_PEI_SERVICES              **PeiServices,
> > > +  IN EFI_PEI_CAPSULE_ON_DISK_PPI   *This
> > > +  );
> > > +
> > > +EFI_PEI_CAPSULE_ON_DISK_PPI mCapsuleOnDiskPpi = {
> > > +  LoadCapsuleOnDisk
> > > +};
> > > +
> > > +EFI_PEI_PPI_DESCRIPTOR mCapsuleOnDiskPpiList = {
> > > +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> > > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > > +  &gEdkiiPeiCapsuleOnDiskPpiGuid,
> > > +  &mCapsuleOnDiskPpi
> > > +};
> > > +
> > > +/**
> > > +  Determine if capsule comes from memory by checking Capsule PPI.
> > > +
> > > +  @param[in]  PeiServices General purpose services available to
> > > + every
> > PEIM.
> > > +
> > > +  @retval TRUE   Capsule comes from memory.
> > > +  @retval FALSE  No capsule comes from memory.
> > > +
> > > +**/
> > > +STATIC
> > > +BOOLEAN
> > > +CheckCapsuleFromRam (
> > > +  IN CONST EFI_PEI_SERVICES          **PeiServices
> > > +  )
> > > +{
> > > +  EFI_STATUS              Status;
> > > +  PEI_CAPSULE_PPI         *Capsule;
> > > +
> > > +  Status = PeiServicesLocatePpi (
> > > +             &gPeiCapsulePpiGuid,
> >
> >
> > Suggest to use gEfiPeiCapsulePpiGuid here.
> > gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.
> >
> >
> > > +             0,
> > > +             NULL,
> > > +             (VOID **) &Capsule
> > > +             );
> > > +  if (!EFI_ERROR(Status)) {
> > > +    Status = Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES
> > > **)PeiServices);
> > > +    if (!EFI_ERROR(Status)) {
> > > +      return TRUE;
> > > +    }
> > > +  }
> > > +
> > > +  return FALSE;
> > > +}
> > > +
> > > +/**
> > > +  Determine if it is a Capsule On Disk mode.
> > > +
> > > +  @retval TRUE         Capsule On Disk mode.
> > > +  @retval FALSE        Not capsule On Disk mode.
> > > +
> > > +**/
> > > +BOOLEAN
> > > +IsCapsuleOnDiskMode (
> > > +  VOID
> > > +  )
> > > +{
> > > +  EFI_STATUS                      Status;
> > > +  UINTN                           Size;
> > > +  EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
> > > +  BOOLEAN                         CodRelocInfo;
> > > +
> > > +  Status = PeiServicesLocatePpi (
> > > +             &gEfiPeiReadOnlyVariable2PpiGuid,
> > > +             0,
> > > +             NULL,
> > > +             (VOID **) &PPIVariableServices
> > > +             );
> > > +  ASSERT_EFI_ERROR (Status);
> > > +
> > > +  Size = sizeof (BOOLEAN);
> > > +  Status = PPIVariableServices->GetVariable (
> > > +                                  PPIVariableServices,
> > > +                                  COD_RELOCATION_INFO_VAR_NAME,
> > > +                                  &gEfiCapsuleVendorGuid,
> > > +                                  NULL,
> > > +                                  &Size,
> > > +                                  &CodRelocInfo
> > > +                                  );
> > > +
> > > +  if (EFI_ERROR (Status) || Size != sizeof(BOOLEAN) || CodRelocInfo
> > > + != TRUE)
> >
> >
> > For 'CodRelocInfo != TRUE', variable of BOOLEAN type can be directly
> > used in the 'if' statement without comparing with 'TRUE' or 'FALSE'.
> >
> >
> > > {
> > > +    DEBUG (( DEBUG_ERROR, "Error Get CodRelocationInfo variable
> > > + %r!\n",
> > > Status));
> > > +    return FALSE;
> > > +  }
> > > +
> > > +  return TRUE;
> > > +}
> > > +
> > > +/**
> > > +  Gets capsule images from relocated capsule buffer.
> > > +  Create Capsule hob for each Capsule.
> > > +
> > > +  Caution: This function may receive untrusted input.
> > > +  Capsule-on-Disk Temp Relocation image is external input, so this
> > > + function  will validate Capsule-on-Disk Temp Relocation image to
> > > + make sure the
> > > content
> > > +  is read within the buffer.
> > > +
> > > +  @param[in]  RelocCapsuleBuf        Buffer pointer to the relocated
> capsule.
> > > +  @param[in]  RelocCapsuleTotalSize  Total size of the relocated capsule.
> > > +
> > > +  @retval EFI_SUCCESS     Succeed to get capsules and create hob.
> > > +  @retval Others          Fail to get capsules and create hob.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +RetrieveRelocatedCapsule (
> > > +  IN UINT8                *RelocCapsuleBuf,
> > > +  IN UINTN                RelocCapsuleTotalSize
> > > +  )
> > > +{
> > > +  EFI_STATUS               Status;
> > > +  UINTN                    Index;
> > > +  UINT8                    *CapsuleDataBufEnd;
> > > +  UINT8                    *CapsulePtr;
> > > +  UINT32                   CapsuleSize;
> > > +  UINT64                   TotalImageSize;
> > > +  UINTN                    CapsuleNum;
> > > +
> > > +  CapsuleNum = 0;
> > > +
> > > +  //
> > > +  // Temp file contains at least 2 capsule (including 1 capsule
> > > + name
> > > + capsule)
> > > & 1 UINT64
> > > +  //
> > > +  if (RelocCapsuleTotalSize < sizeof(UINT64) +
> > > + sizeof(EFI_CAPSULE_HEADER)
> > > * 2) {
> > > +    return EFI_INVALID_PARAMETER;
> > > +  }
> > > +
> > > +  CopyMem(&TotalImageSize, RelocCapsuleBuf, sizeof(UINT64));
> > > +
> > > +  DEBUG ((DEBUG_INFO, "ProcessRelocatedCapsule CapsuleBuf %x
> > > TotalCapSize %lx\n",
> > > +                      RelocCapsuleBuf, TotalImageSize));
> > > +
> > > +  RelocCapsuleBuf += sizeof(UINT64);
> > > +
> > > +  //
> > > +  // TempCaspule file length check
> > > +  //
> > > +  if (MAX_ADDRESS - TotalImageSize <= sizeof(UINT64) ||
> > > +      (UINT64)RelocCapsuleTotalSize != TotalImageSize + sizeof(UINT64)
> ||
> > > +      (UINTN)(MAX_ADDRESS -
> > > (PHYSICAL_ADDRESS)(UINTN)RelocCapsuleBuf) <= TotalImageSize) {
> > > +    return EFI_INVALID_PARAMETER;
> > > +  }
> > > +
> > > +  CapsuleDataBufEnd = RelocCapsuleBuf + TotalImageSize;
> > > +
> > > +  //
> > > +  // TempCapsule file integrity check over Capsule Header to ensure
> > > + no data
> > > corruption in NV Var & Relocation storage
> > > +  //
> > > +  CapsulePtr = RelocCapsuleBuf;
> > > +
> > > +  while (CapsulePtr < CapsuleDataBufEnd) {
> > > +    if ((CapsuleDataBufEnd - CapsulePtr) < sizeof(EFI_CAPSULE_HEADER)
> ||
> > > +        ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize <
> > > sizeof(EFI_CAPSULE_HEADER) ||
> > > +        (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)CapsulePtr)
> > > + <
> > > ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize
> > > +        ) {
> > > +      break;
> > > +    }
> > > +    CapsulePtr += ((EFI_CAPSULE_HEADER *)CapsulePtr)-
> > >CapsuleImageSize;
> > > +    CapsuleNum ++;
> > > +  }
> > > +
> > > +  if (CapsulePtr != CapsuleDataBufEnd) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    goto EXIT;
> > > +  }
> > > +
> > > +  //
> > > +  // Capsule count must be less than PcdCapsuleMax, avoid building
> > > + too
> > > many CvHobs to occupy all the free space in HobList.
> > > +  //
> > > +  if (CapsuleNum > PcdGet16 (PcdCapsuleMax)) {
> > > +    Status = EFI_INVALID_PARAMETER;
> > > +    goto EXIT;
> > > +  }
> > > +
> > > +  //
> > > +  // Re-iterate the capsule buffer to create Capsule hob & Capsule
> > > + Name Str
> > > Hob for each Capsule saved in relocated capsule file
> > > +  //
> > > +  CapsulePtr = RelocCapsuleBuf;
> > > +  Index      = 0;
> > > +  while (CapsulePtr < CapsuleDataBufEnd) {
> > > +    CapsuleSize = ((EFI_CAPSULE_HEADER *)CapsulePtr)-
> > >CapsuleImageSize;
> > > +    BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsulePtr,
> > > + CapsuleSize);
> > > +
> > > +    DEBUG((DEBUG_INFO, "Capsule saved in address %x size %x\n",
> > > CapsulePtr, CapsuleSize));
> > > +
> > > +    CapsulePtr += CapsuleSize;
> > > +    Index++;
> > > +  }
> > > +
> > > +EXIT:
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Recovery module entrypoint
> > > +
> > > +  @param[in] FileHandle   Handle of the file being invoked.
> > > +  @param[in] PeiServices  Describes the list of possible PEI Services.
> > > +
> > > +  @return EFI_SUCCESS Recovery module is initialized.
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +InitializeCapsuleOnDiskLoad (
> > > +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> > > +  IN CONST EFI_PEI_SERVICES     **PeiServices
> > > +  )
> > > +{
> > > +  EFI_STATUS  Status;
> > > +  UINTN       BootMode;
> > > +  UINTN       FileNameSize;
> > > +
> > > +  BootMode = GetBootModeHob();
> > > +  ASSERT(BootMode == BOOT_ON_FLASH_UPDATE);
> > > +
> > > +  //
> > > +  // If there are capsules provisioned in memory, quit.
> > > +  // Only one capsule resource is accept, CapsuleOnRam's priority
> > > + is higher
> > > than CapsuleOnDisk.
> > > +  //
> > > +  if (CheckCapsuleFromRam(PeiServices)) {
> > > +    DEBUG((DEBUG_ERROR, "Capsule On Memory Detected! Quit.\n"));
> > > +    return EFI_ABORTED;
> > > +  }
> > > +
> > > +  DEBUG_CODE (
> > > +   VOID *CapsuleOnDiskModePpi;
> > > +
> > > +  if (!IsCapsuleOnDiskMode()){
> > > +    return EFI_NOT_FOUND;
> > > +  }
> > > +
> > > +  //
> > > +  // Check Capsule On Disk Relocation flag. If exists, load capsule
> > > + & create
> > > Capsule Hob
> > > +  //
> > > +  Status = PeiServicesLocatePpi (
> > > +             &gEfiPeiBootInCapsuleOnDiskModePpiGuid,
> > > +             0,
> > > +             NULL,
> > > +             (VOID **)&CapsuleOnDiskModePpi
> > > +             );
> > > +    if (EFI_ERROR(Status)) {
> > > +      DEBUG((DEBUG_ERROR, "Locate CapsuleOnDiskModePpi
> error %x\n",
> > > Status));
> > > +      return Status;
> > > +    }
> > > +  );
> > > +
> > > +  Status = (**PeiServices).InstallPpi (PeiServices,
> > > + &mCapsuleOnDiskPpiList);
> >
> >
> > Minor one, suggest to directly use PeiServicesInstallPpi().
> >
> >
> > > +  ASSERT_EFI_ERROR (Status);
> > > +
> > > +  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);  Status =
> > > + PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *)
> > > PcdGetPtr(PcdCoDRelocationFileName));
> >
> >
> > Buffer for 'PcdRecoveryFileName' may not be big enough to hold the
> > content in 'PcdCoDRelocationFileName'.
> >
> > I think there might be a chance for the above PcdSetPtrS() call to fail.
> >
> >
> > > +  ASSERT_EFI_ERROR (Status);
> > > +
> > > +  return Status;
> > > +}
> > > +
> > > +/**
> > > +  Loads a DXE capsule from some media into memory and updates the
> > HOB
> > > table
> > > +  with the DXE firmware volume information.
> > > +
> > > +  @param[in]  PeiServices   General-purpose services that are available
> to
> > > every PEIM.
> > > +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> > > instance.
> > > +
> > > +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> > > +  @retval EFI_DEVICE_ERROR   A device error occurred.
> > > +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> > > +
> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +LoadCapsuleOnDisk (
> > > +  IN EFI_PEI_SERVICES                     **PeiServices,
> > > +  IN EFI_PEI_CAPSULE_ON_DISK_PPI          *This
> > > +  )
> > > +{
> > > +  EFI_STATUS                          Status;
> > > +  EFI_PEI_DEVICE_RECOVERY_MODULE_PPI  *DeviceRecoveryPpi;
> > > +  UINTN                               NumberRecoveryCapsules;
> > > +  UINTN                               Instance;
> > > +  UINTN                               CapsuleInstance;
> > > +  UINTN                               CapsuleSize;
> > > +  EFI_GUID                            CapsuleType;
> > > +  VOID                                *CapsuleBuffer;
> > > +
> > > +  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Load Capsule On Disk
> > Entry\n"));
> > > +
> > > +  for (Instance = 0; ; Instance++) {
> > > +    Status = PeiServicesLocatePpi (
> > > +               &gEfiPeiDeviceRecoveryModulePpiGuid,
> > > +               Instance,
> > > +               NULL,
> > > +               (VOID **)&DeviceRecoveryPpi
> > > +               );
> > > +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LocateRecoveryPpi (%d)
> > -
> > >  %r\n", Instance, Status));
> > > +    if (EFI_ERROR (Status)) {
> > > +      if (Instance == 0) {
> > > +        REPORT_STATUS_CODE (
> > > +          EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> > > +          (EFI_SOFTWARE_PEI_MODULE |
> > > EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
> > > +          );
> > > +      }
> > > +      break;
> > > +    }
> > > +    NumberRecoveryCapsules = 0;
> > > +    Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
> > > +                                  (EFI_PEI_SERVICES **)PeiServices,
> > > +                                  DeviceRecoveryPpi,
> > > +                                  &NumberRecoveryCapsules
> > > +                                  );
> > > +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> > > GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules,
> > > Status));
> > > +    if (EFI_ERROR (Status)) {
> > > +      continue;
> > > +    }
> > > +
> > > +    for (CapsuleInstance = 1; CapsuleInstance <=
> > > + NumberRecoveryCapsules;
> > > CapsuleInstance++) {
> > > +      CapsuleSize = 0;
> > > +      Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
> > > +                                    (EFI_PEI_SERVICES **)PeiServices,
> > > +                                    DeviceRecoveryPpi,
> > > +                                    CapsuleInstance,
> > > +                                    &CapsuleSize,
> > > +                                    &CapsuleType
> > > +                                    );
> > > +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> > GetRecoveryCapsuleInfo
> > > (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
> > > +      if (EFI_ERROR (Status)) {
> > > +        break;
> > > +      }
> > > +
> > > +      //
> > > +      // Allocate the memory so that it gets preserved into DXE.
> > > +      // Capsule is special because it may need to populate to system table
> > > +      //
> > > +      CapsuleBuffer = AllocateRuntimePages (EFI_SIZE_TO_PAGES
> > > (CapsuleSize));
> > > +
> > > +      if (CapsuleBuffer == NULL) {
> > > +        DEBUG ((DEBUG_ERROR, "LoadCapsuleOnDisk -
> > > + AllocateRuntimePages
> > > fail\n"));
> > > +        continue;
> > > +      }
> > > +
> > > +      Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
> > > +                                    (EFI_PEI_SERVICES **)PeiServices,
> > > +                                    DeviceRecoveryPpi,
> > > +                                    CapsuleInstance,
> > > +                                    CapsuleBuffer
> > > +                                    );
> > > +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LoadRecoveryCapsule
> > > (%d) - %r\n", CapsuleInstance, Status));
> > > +      if (EFI_ERROR (Status)) {
> > > +        FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
> > > +        break;
> > > +      }
> > > +
> > > +      //
> > > +      // Capsule Update Mode, Split relocated Capsule buffer into
> > > + different
> > > capsule vehical hobs.
> > > +      //
> > > +      Status = RetrieveRelocatedCapsule(CapsuleBuffer,
> > > + CapsuleSize);
> > > +
> > > +      break;
> > > +    }
> > > +
> > > +    if (EFI_ERROR (Status)) {
> > > +      REPORT_STATUS_CODE (
> > > +        EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> > > +        (EFI_SOFTWARE_PEI_MODULE |
> > > EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
> > > +        );
> > > +    }
> > > +
> > > +    return Status;
> > > +  }
> > > +
> > > +  //
> > > +  // Any attack against GPT, Relocation Info Variable or temp
> > > + relocation file
> > > will result in no Capsule HOB and return EFI_NOT_FOUND.
> > > +  // After flow to DXE phase. since no capsule hob is detected.
> > > + Platform will
> > > clear Info flag and force restart.
> > > +  // No volunerability will be exposed  //
> > > +
> > > +  return EFI_NOT_FOUND;
> > > +}
> > > diff --git
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > inf
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > inf
> > > new file mode 100644
> > > index 0000000000..4af07440b7
> > > --- /dev/null
> > > +++
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > inf
> > > @@ -0,0 +1,64 @@
> > > +## @file
> > > +# Load Capsule on Disk module.
> > > +#
> > > +# Load Capsule On Disk from Root Directory file system. Create CV
> > > +hob # based on temporary Capsule On Disk file.
> > > +#
> > > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > > +#
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > +
> > > +[Defines]
> > > +  INF_VERSION                    = 0x00010005
> > > +  BASE_NAME                      = CapsuleOnDiskLoadPei
> > > +  MODULE_UNI_FILE                = CapsuleOnDiskLoadPei.uni
> > > +  FILE_GUID                      = 8ADEDF9E-2EC8-40fb-AE56-B76D90225D2D
> > > +  MODULE_TYPE                    = PEIM
> > > +  VERSION_STRING                 = 1.0
> > > +  ENTRY_POINT                    = InitializeCapsuleOnDiskLoad
> > > +
> > > +#
> > > +# The following information is for reference only and not required
> > > +by the
> > > build tools.
> > > +#
> > > +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> > > +#
> > > +
> > > +[Sources]
> > > +  CapsuleOnDiskLoadPei.c
> > > +
> > > +[Packages]
> > > +  MdePkg/MdePkg.dec
> > > +  MdeModulePkg/MdeModulePkg.dec
> > > +
> > > +[LibraryClasses]
> > > +  PeimEntryPoint
> > > +  DebugLib
> > > +  HobLib
> > > +  BaseMemoryLib
> > > +  MemoryAllocationLib
> > > +  ReportStatusCodeLib
> > > +
> > > +[Ppis]
> > > +  gEdkiiPeiCapsuleOnDiskPpiGuid           ## PRODUCES
> > > +  gEfiPeiReadOnlyVariable2PpiGuid         ## CONSUMES
> > > +  gEfiPeiBootInCapsuleOnDiskModePpiGuid   ##
> SOMETIMES_CONSUMES
> > > +  gEfiPeiDeviceRecoveryModulePpiGuid      ## CONSUMES
> > > +  gPeiCapsulePpiGuid                      ## CONSUMES
> >
> >
> > Suggest to use gEfiPeiCapsulePpiGuid here.
> > gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.
> >
> >
> > > +
> > > +[Guids]
> > > +  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> > Variable
> > > L"CodRelocationInfo"
> > > +
> > > +[Pcd]
> > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName
> > > ## CONSUMES
> > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax                            ##
> > > CONSUMES
> > > +
> > > +[PcdEx]
> > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName
> > ##
> > > PRODUCES
> > > +
> > > +[depex]
> >
> >
> > Minor comment:
> > [depex] -> [Depex]
> >
> > Best Regards,
> > Hao Wu
> >
> >
> > > +  gEfiPeiBootInCapsuleOnD
> > iskModePpiGuid
> > > +
> > > +[UserExtensions.TianoCore."ExtraFiles"]
> > > +  CapsuleOnDiskLoadPeiExtra.uni
> > > diff --git
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > uni
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > uni
> > > new file mode 100644
> > > index 0000000000..c3eae6a5c2
> > > --- /dev/null
> > > +++
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > uni
> > > @@ -0,0 +1,15 @@
> > > +// /** @file
> > > +// Caspule On Disk Load module.
> > > +//
> > > +// Load Capsule On Disk and build CV hob.
> > > +//
> > > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > +// // SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > +
> > > +
> > > +#string STR_MODULE_ABSTRACT             #language en-US "Caspule On
> Disk
> > > Load module."
> > > +
> > > +#string STR_MODULE_DESCRIPTION          #language en-US "Load
> Capsule
> > > On Disk and build CV hob."
> > > diff --git
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > > Extra.uni
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > > Extra.uni
> > > new file mode 100644
> > > index 0000000000..81034f6294
> > > --- /dev/null
> > > +++
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > > Extra.uni
> > > @@ -0,0 +1,14 @@
> > > +// /** @file
> > > +// CapsuleOnDiskLoadPei Localized Strings and Content // //
> > > +Copyright
> > > +(c) 2019, Intel Corporation. All rights reserved.<BR> // //
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > +
> > > +#string STR_PROPERTIES_MODULE_NAME
> > > +#language en-US
> > > +"CapsuleOnDiskLoad PEI Driver"
> > > +
> > > +
> > > --
> > > 2.16.2.windows.1
> > >
> > >
> > >
> 
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM.
  2019-06-19  8:59       ` Ni, Ray
@ 2019-06-20  0:59         ` Wu, Hao A
  0 siblings, 0 replies; 33+ messages in thread
From: Wu, Hao A @ 2019-06-20  0:59 UTC (permalink / raw)
  To: Xu, Wei6, Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Zhang, Chao B

> -----Original Message-----
> From: Ni, Ray
> Sent: Wednesday, June 19, 2019 5:00 PM
> To: devel@edk2.groups.io; Xu, Wei6; Wu, Hao A
> Cc: Wang, Jian J; Zhang, Chao B
> Subject: RE: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> CapsuleOnDiskLoadPei PEIM.
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Xu,
> > Wei6
> > Sent: Wednesday, June 19, 2019 4:41 PM
> > To: Wu, Hao A <hao.a.wu@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B
> > <chao.b.zhang@intel.com>
> > Subject: Re: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> > CapsuleOnDiskLoadPei PEIM.
> >
> > > > +  ASSERT_EFI_ERROR (Status);
> > > > +
> > > > +  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);  Status =
> > > > + PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *)
> > > > PcdGetPtr(PcdCoDRelocationFileName));
> > >
> > >
> > > Buffer for 'PcdRecoveryFileName' may not be big enough to hold the
> > > content in 'PcdCoDRelocationFileName'.
> > >
> > > I think there might be a chance for the above PcdSetPtrS() call to fail.
> > >
> >
> >
> > Thanks a lot for the comments.
> > Yes, 'PcdRecoveryFileName' should be larger than
> > 'PcdCoDRelocationFileName'.
> > I think no need to update the code, since these two PCDs are fixed during
> > build time.
> > I will update the description of 'PcdCoDRelocationFileName' to mention: it
> > must be smaller than 'PcdRecoveryFileName', otherwise failure may occur.
> 
> But your code doesn't check the status of PcdSetPtrS().


Please help to add check to the return status of PcdSetPtrS() and also add
description comments for 'PcdCoDRelocationFileName' to mention its impact
to 'PcdRecoveryFileName' together with the limitation.

Best Regards,
Hao Wu


> 
> >
> > Do you have comments about it?
> > Thanks again.
> >
> >
> > BR,
> > Wei
> >
> > > -----Original Message-----
> > > From: Wu, Hao A
> > > Sent: Wednesday, June 12, 2019 3:49 PM
> > > To: devel@edk2.groups.io; Xu, Wei6 <wei6.xu@intel.com>
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Zhang, Chao B
> > > <chao.b.zhang@intel.com>
> > > Subject: RE: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> > > CapsuleOnDiskLoadPei PEIM.
> > >
> > > > -----Original Message-----
> > > > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf
> > > > Of Xu,
> > > > Wei6
> > > > Sent: Wednesday, June 05, 2019 11:42 PM
> > > > To: devel@edk2.groups.io
> > > > Cc: Wang, Jian J; Wu, Hao A; Zhang, Chao B; Xu, Wei6
> > > > Subject: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add
> > > > CapsuleOnDiskLoadPei PEIM.
> > > >
> > > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1852
> > > >
> > > > This module provides PPI to load Capsule On Disk temp relocation
> > > > file from Root Directory file system, retrieve the capsules from the
> > > > temp file and create capsule hobs for these capsules.
> > > >
> > > > Cc: Jian J Wang <jian.j.wang@intel.com>
> > > > Cc: Hao A Wu <hao.a.wu@intel.com>
> > > > Cc: Chao B Zhang <chao.b.zhang@intel.com>
> > > > Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> > > > ---
> > > >  MdeModulePkg/MdeModulePkg.dsc                      |   4 +
> > > >  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c    | 442
> > > > +++++++++++++++++++++
> > > >  .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf  |  64 +++
> > > > .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni  |  15 +
> > > >  .../CapsuleOnDiskLoadPeiExtra.uni                  |  14 +
> > > >  5 files changed, 539 insertions(+)
> > > >  create mode 100644
> > > >
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
> > > >  create mode 100644
> > > >
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> > > > f
> > > >  create mode 100644
> > > >
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.u
> > > > ni
> > > >  create mode 100644
> > > >
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiEx
> > > > tra.uni
> > >
> > > Since this a new module, could you help to follow the recommendation
> > > in
> > >
> https://edk2.groups.io/g/devel/message/39655?p=,,,20,0,0,0::Created,,U
> > > efi
> > > DebugLibStdErr,20,2,0,31318888
> > >
> > > to add/update 'static' (lower case) for global variables/functions
> > > whose scope is limited within a single file?
> > >
> > > >
> > > > diff --git a/MdeModulePkg/MdeModulePkg.dsc
> > > > b/MdeModulePkg/MdeModulePkg.dsc index 995fd805e1..615edddbcc
> > > 100644
> > > > --- a/MdeModulePkg/MdeModulePkg.dsc
> > > > +++ b/MdeModulePkg/MdeModulePkg.dsc
> > > > @@ -197,10 +197,13 @@
> > > >
> gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
> > > >
> > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0
> > > >
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0
> > > >
> > >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28
> > > >
> > > > +[PcdsDynamicExDefault]
> > > > +
> > > >
> > >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
> > > > +
> > > >  [Components]
> > > >    MdeModulePkg/Application/HelloWorld/HelloWorld.inf
> > > >    MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
> > > >
> > MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
> > > >
> > > > @@ -315,10 +318,11 @@
> > > >
> > > >
> > >
> >
> NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMainte
> > > > nanceManagerUiLib.inf
> > > >    }
> > > >
> > > >
> > >
> >
> MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManager
> > > > Dxe.inf
> > > >
> > > >
> > >
> >
> MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.i
> > > > nf
> > > >    MdeModulePkg/Universal/CapsulePei/CapsulePei.inf
> > > > +
> > > >
> > >
> >
> MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.in
> > > > f
> > > >
> > MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> > > >
> > >
> MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
> > > >
> MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
> > > >
> > > >
> > >
> >
> MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleD
> > > > xe.inf
> > > >
> > > >
> > >
> >
> MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDx
> > > > e.inf
> > > > diff --git
> > > >
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > c
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > c
> > > > new file mode 100644
> > > > index 0000000000..40d25f3d3b
> > > > --- /dev/null
> > > > +++
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > c
> > > > @@ -0,0 +1,442 @@
> > > > +/** @file
> > > > +  Recovery module.
> > > > +
> > > > +  Caution: This module requires additional review when modified.
> > > > +  This module will have external input - Capsule-on-Disk Temp
> > > > + Relocation
> > > > image.
> > > > +  This external input must be validated carefully to avoid security
> > > > + issue like  buffer overflow, integer overflow.
> > > > +
> > > > +  RetrieveRelocatedCapsule() will receive untrusted input and do
> > > > + basic
> > > > validation.
> > > > +
> > > > +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > +
> > > > +**/
> > > > +
> > > > +//
> > > > +// The package level header files this module uses // #include
> > > > +<Uefi.h> #include <PiPei.h>
> > > > +
> > > > +//
> > > > +// The protocols, PPI and GUID defintions for this module //
> > > > +#include <Ppi/MasterBootMode.h> #include
> > <Ppi/FirmwareVolumeInfo.h>
> > > #include
> > > > +<Ppi/ReadOnlyVariable2.h> #include <Ppi/Capsule.h> #include
> > > > +<Ppi/CapsuleOnDisk.h> #include <Ppi/DeviceRecoveryModule.h>
> > > > +
> > > > +#include <Guid/FirmwareFileSystem2.h> // // The Library classes
> > > > +this module consumes // #include <Library/DebugLib.h> #include
> > > > +<Library/PeimEntryPoint.h> #include <Library/PeiServicesLib.h>
> > > > +#include <Library/HobLib.h> #include <Library/BaseMemoryLib.h>
> > > > +#include <Library/MemoryAllocationLib.h> #include
> > > > +<Library/PcdLib.h> #include <Library/CapsuleLib.h> #include
> > > > +<Library/ReportStatusCodeLib.h>
> > > > +
> > > > +/**
> > > > +  Loads a DXE capsule from some media into memory and updates the
> > > HOB
> > > > table
> > > > +  with the DXE firmware volume information.
> > > > +
> > > > +  @param[in]  PeiServices   General-purpose services that are available
> > to
> > > > every PEIM.
> > > > +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> > > > instance.
> > > > +
> > > > +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> > > > +  @retval EFI_DEVICE_ERROR   A device error occurred.
> > > > +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> > > > +
> > > > +**/
> > > > +EFI_STATUS
> > > > +EFIAPI
> > > > +LoadCapsuleOnDisk (
> > > > +  IN EFI_PEI_SERVICES              **PeiServices,
> > > > +  IN EFI_PEI_CAPSULE_ON_DISK_PPI   *This
> > > > +  );
> > > > +
> > > > +EFI_PEI_CAPSULE_ON_DISK_PPI mCapsuleOnDiskPpi = {
> > > > +  LoadCapsuleOnDisk
> > > > +};
> > > > +
> > > > +EFI_PEI_PPI_DESCRIPTOR mCapsuleOnDiskPpiList = {
> > > > +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> > > > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> > > > +  &gEdkiiPeiCapsuleOnDiskPpiGuid,
> > > > +  &mCapsuleOnDiskPpi
> > > > +};
> > > > +
> > > > +/**
> > > > +  Determine if capsule comes from memory by checking Capsule PPI.
> > > > +
> > > > +  @param[in]  PeiServices General purpose services available to
> > > > + every
> > > PEIM.
> > > > +
> > > > +  @retval TRUE   Capsule comes from memory.
> > > > +  @retval FALSE  No capsule comes from memory.
> > > > +
> > > > +**/
> > > > +STATIC
> > > > +BOOLEAN
> > > > +CheckCapsuleFromRam (
> > > > +  IN CONST EFI_PEI_SERVICES          **PeiServices
> > > > +  )
> > > > +{
> > > > +  EFI_STATUS              Status;
> > > > +  PEI_CAPSULE_PPI         *Capsule;
> > > > +
> > > > +  Status = PeiServicesLocatePpi (
> > > > +             &gPeiCapsulePpiGuid,
> > >
> > >
> > > Suggest to use gEfiPeiCapsulePpiGuid here.
> > > gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.
> > >
> > >
> > > > +             0,
> > > > +             NULL,
> > > > +             (VOID **) &Capsule
> > > > +             );
> > > > +  if (!EFI_ERROR(Status)) {
> > > > +    Status = Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES
> > > > **)PeiServices);
> > > > +    if (!EFI_ERROR(Status)) {
> > > > +      return TRUE;
> > > > +    }
> > > > +  }
> > > > +
> > > > +  return FALSE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Determine if it is a Capsule On Disk mode.
> > > > +
> > > > +  @retval TRUE         Capsule On Disk mode.
> > > > +  @retval FALSE        Not capsule On Disk mode.
> > > > +
> > > > +**/
> > > > +BOOLEAN
> > > > +IsCapsuleOnDiskMode (
> > > > +  VOID
> > > > +  )
> > > > +{
> > > > +  EFI_STATUS                      Status;
> > > > +  UINTN                           Size;
> > > > +  EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices;
> > > > +  BOOLEAN                         CodRelocInfo;
> > > > +
> > > > +  Status = PeiServicesLocatePpi (
> > > > +             &gEfiPeiReadOnlyVariable2PpiGuid,
> > > > +             0,
> > > > +             NULL,
> > > > +             (VOID **) &PPIVariableServices
> > > > +             );
> > > > +  ASSERT_EFI_ERROR (Status);
> > > > +
> > > > +  Size = sizeof (BOOLEAN);
> > > > +  Status = PPIVariableServices->GetVariable (
> > > > +                                  PPIVariableServices,
> > > > +                                  COD_RELOCATION_INFO_VAR_NAME,
> > > > +                                  &gEfiCapsuleVendorGuid,
> > > > +                                  NULL,
> > > > +                                  &Size,
> > > > +                                  &CodRelocInfo
> > > > +                                  );
> > > > +
> > > > +  if (EFI_ERROR (Status) || Size != sizeof(BOOLEAN) || CodRelocInfo
> > > > + != TRUE)
> > >
> > >
> > > For 'CodRelocInfo != TRUE', variable of BOOLEAN type can be directly
> > > used in the 'if' statement without comparing with 'TRUE' or 'FALSE'.
> > >
> > >
> > > > {
> > > > +    DEBUG (( DEBUG_ERROR, "Error Get CodRelocationInfo variable
> > > > + %r!\n",
> > > > Status));
> > > > +    return FALSE;
> > > > +  }
> > > > +
> > > > +  return TRUE;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Gets capsule images from relocated capsule buffer.
> > > > +  Create Capsule hob for each Capsule.
> > > > +
> > > > +  Caution: This function may receive untrusted input.
> > > > +  Capsule-on-Disk Temp Relocation image is external input, so this
> > > > + function  will validate Capsule-on-Disk Temp Relocation image to
> > > > + make sure the
> > > > content
> > > > +  is read within the buffer.
> > > > +
> > > > +  @param[in]  RelocCapsuleBuf        Buffer pointer to the relocated
> > capsule.
> > > > +  @param[in]  RelocCapsuleTotalSize  Total size of the relocated
> capsule.
> > > > +
> > > > +  @retval EFI_SUCCESS     Succeed to get capsules and create hob.
> > > > +  @retval Others          Fail to get capsules and create hob.
> > > > +
> > > > +**/
> > > > +EFI_STATUS
> > > > +EFIAPI
> > > > +RetrieveRelocatedCapsule (
> > > > +  IN UINT8                *RelocCapsuleBuf,
> > > > +  IN UINTN                RelocCapsuleTotalSize
> > > > +  )
> > > > +{
> > > > +  EFI_STATUS               Status;
> > > > +  UINTN                    Index;
> > > > +  UINT8                    *CapsuleDataBufEnd;
> > > > +  UINT8                    *CapsulePtr;
> > > > +  UINT32                   CapsuleSize;
> > > > +  UINT64                   TotalImageSize;
> > > > +  UINTN                    CapsuleNum;
> > > > +
> > > > +  CapsuleNum = 0;
> > > > +
> > > > +  //
> > > > +  // Temp file contains at least 2 capsule (including 1 capsule
> > > > + name
> > > > + capsule)
> > > > & 1 UINT64
> > > > +  //
> > > > +  if (RelocCapsuleTotalSize < sizeof(UINT64) +
> > > > + sizeof(EFI_CAPSULE_HEADER)
> > > > * 2) {
> > > > +    return EFI_INVALID_PARAMETER;
> > > > +  }
> > > > +
> > > > +  CopyMem(&TotalImageSize, RelocCapsuleBuf, sizeof(UINT64));
> > > > +
> > > > +  DEBUG ((DEBUG_INFO, "ProcessRelocatedCapsule CapsuleBuf %x
> > > > TotalCapSize %lx\n",
> > > > +                      RelocCapsuleBuf, TotalImageSize));
> > > > +
> > > > +  RelocCapsuleBuf += sizeof(UINT64);
> > > > +
> > > > +  //
> > > > +  // TempCaspule file length check
> > > > +  //
> > > > +  if (MAX_ADDRESS - TotalImageSize <= sizeof(UINT64) ||
> > > > +      (UINT64)RelocCapsuleTotalSize != TotalImageSize + sizeof(UINT64)
> > ||
> > > > +      (UINTN)(MAX_ADDRESS -
> > > > (PHYSICAL_ADDRESS)(UINTN)RelocCapsuleBuf) <= TotalImageSize) {
> > > > +    return EFI_INVALID_PARAMETER;
> > > > +  }
> > > > +
> > > > +  CapsuleDataBufEnd = RelocCapsuleBuf + TotalImageSize;
> > > > +
> > > > +  //
> > > > +  // TempCapsule file integrity check over Capsule Header to ensure
> > > > + no data
> > > > corruption in NV Var & Relocation storage
> > > > +  //
> > > > +  CapsulePtr = RelocCapsuleBuf;
> > > > +
> > > > +  while (CapsulePtr < CapsuleDataBufEnd) {
> > > > +    if ((CapsuleDataBufEnd - CapsulePtr) < sizeof(EFI_CAPSULE_HEADER)
> > ||
> > > > +        ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize <
> > > > sizeof(EFI_CAPSULE_HEADER) ||
> > > > +        (UINTN)(MAX_ADDRESS -
> (PHYSICAL_ADDRESS)(UINTN)CapsulePtr)
> > > > + <
> > > > ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize
> > > > +        ) {
> > > > +      break;
> > > > +    }
> > > > +    CapsulePtr += ((EFI_CAPSULE_HEADER *)CapsulePtr)-
> > > >CapsuleImageSize;
> > > > +    CapsuleNum ++;
> > > > +  }
> > > > +
> > > > +  if (CapsulePtr != CapsuleDataBufEnd) {
> > > > +    Status = EFI_INVALID_PARAMETER;
> > > > +    goto EXIT;
> > > > +  }
> > > > +
> > > > +  //
> > > > +  // Capsule count must be less than PcdCapsuleMax, avoid building
> > > > + too
> > > > many CvHobs to occupy all the free space in HobList.
> > > > +  //
> > > > +  if (CapsuleNum > PcdGet16 (PcdCapsuleMax)) {
> > > > +    Status = EFI_INVALID_PARAMETER;
> > > > +    goto EXIT;
> > > > +  }
> > > > +
> > > > +  //
> > > > +  // Re-iterate the capsule buffer to create Capsule hob & Capsule
> > > > + Name Str
> > > > Hob for each Capsule saved in relocated capsule file
> > > > +  //
> > > > +  CapsulePtr = RelocCapsuleBuf;
> > > > +  Index      = 0;
> > > > +  while (CapsulePtr < CapsuleDataBufEnd) {
> > > > +    CapsuleSize = ((EFI_CAPSULE_HEADER *)CapsulePtr)-
> > > >CapsuleImageSize;
> > > > +    BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsulePtr,
> > > > + CapsuleSize);
> > > > +
> > > > +    DEBUG((DEBUG_INFO, "Capsule saved in address %x size %x\n",
> > > > CapsulePtr, CapsuleSize));
> > > > +
> > > > +    CapsulePtr += CapsuleSize;
> > > > +    Index++;
> > > > +  }
> > > > +
> > > > +EXIT:
> > > > +
> > > > +  return Status;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Recovery module entrypoint
> > > > +
> > > > +  @param[in] FileHandle   Handle of the file being invoked.
> > > > +  @param[in] PeiServices  Describes the list of possible PEI Services.
> > > > +
> > > > +  @return EFI_SUCCESS Recovery module is initialized.
> > > > +**/
> > > > +EFI_STATUS
> > > > +EFIAPI
> > > > +InitializeCapsuleOnDiskLoad (
> > > > +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> > > > +  IN CONST EFI_PEI_SERVICES     **PeiServices
> > > > +  )
> > > > +{
> > > > +  EFI_STATUS  Status;
> > > > +  UINTN       BootMode;
> > > > +  UINTN       FileNameSize;
> > > > +
> > > > +  BootMode = GetBootModeHob();
> > > > +  ASSERT(BootMode == BOOT_ON_FLASH_UPDATE);
> > > > +
> > > > +  //
> > > > +  // If there are capsules provisioned in memory, quit.
> > > > +  // Only one capsule resource is accept, CapsuleOnRam's priority
> > > > + is higher
> > > > than CapsuleOnDisk.
> > > > +  //
> > > > +  if (CheckCapsuleFromRam(PeiServices)) {
> > > > +    DEBUG((DEBUG_ERROR, "Capsule On Memory Detected! Quit.\n"));
> > > > +    return EFI_ABORTED;
> > > > +  }
> > > > +
> > > > +  DEBUG_CODE (
> > > > +   VOID *CapsuleOnDiskModePpi;
> > > > +
> > > > +  if (!IsCapsuleOnDiskMode()){
> > > > +    return EFI_NOT_FOUND;
> > > > +  }
> > > > +
> > > > +  //
> > > > +  // Check Capsule On Disk Relocation flag. If exists, load capsule
> > > > + & create
> > > > Capsule Hob
> > > > +  //
> > > > +  Status = PeiServicesLocatePpi (
> > > > +             &gEfiPeiBootInCapsuleOnDiskModePpiGuid,
> > > > +             0,
> > > > +             NULL,
> > > > +             (VOID **)&CapsuleOnDiskModePpi
> > > > +             );
> > > > +    if (EFI_ERROR(Status)) {
> > > > +      DEBUG((DEBUG_ERROR, "Locate CapsuleOnDiskModePpi
> > error %x\n",
> > > > Status));
> > > > +      return Status;
> > > > +    }
> > > > +  );
> > > > +
> > > > +  Status = (**PeiServices).InstallPpi (PeiServices,
> > > > + &mCapsuleOnDiskPpiList);
> > >
> > >
> > > Minor one, suggest to directly use PeiServicesInstallPpi().
> > >
> > >
> > > > +  ASSERT_EFI_ERROR (Status);
> > > > +
> > > > +  FileNameSize = PcdGetSize (PcdCoDRelocationFileName);  Status =
> > > > + PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *)
> > > > PcdGetPtr(PcdCoDRelocationFileName));
> > >
> > >
> > > Buffer for 'PcdRecoveryFileName' may not be big enough to hold the
> > > content in 'PcdCoDRelocationFileName'.
> > >
> > > I think there might be a chance for the above PcdSetPtrS() call to fail.
> > >
> > >
> > > > +  ASSERT_EFI_ERROR (Status);
> > > > +
> > > > +  return Status;
> > > > +}
> > > > +
> > > > +/**
> > > > +  Loads a DXE capsule from some media into memory and updates the
> > > HOB
> > > > table
> > > > +  with the DXE firmware volume information.
> > > > +
> > > > +  @param[in]  PeiServices   General-purpose services that are available
> > to
> > > > every PEIM.
> > > > +  @param[in]  This          Indicates the EFI_PEI_RECOVERY_MODULE_PPI
> > > > instance.
> > > > +
> > > > +  @retval EFI_SUCCESS        The capsule was loaded correctly.
> > > > +  @retval EFI_DEVICE_ERROR   A device error occurred.
> > > > +  @retval EFI_NOT_FOUND      A recovery DXE capsule cannot be found.
> > > > +
> > > > +**/
> > > > +EFI_STATUS
> > > > +EFIAPI
> > > > +LoadCapsuleOnDisk (
> > > > +  IN EFI_PEI_SERVICES                     **PeiServices,
> > > > +  IN EFI_PEI_CAPSULE_ON_DISK_PPI          *This
> > > > +  )
> > > > +{
> > > > +  EFI_STATUS                          Status;
> > > > +  EFI_PEI_DEVICE_RECOVERY_MODULE_PPI  *DeviceRecoveryPpi;
> > > > +  UINTN                               NumberRecoveryCapsules;
> > > > +  UINTN                               Instance;
> > > > +  UINTN                               CapsuleInstance;
> > > > +  UINTN                               CapsuleSize;
> > > > +  EFI_GUID                            CapsuleType;
> > > > +  VOID                                *CapsuleBuffer;
> > > > +
> > > > +  DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Load Capsule On Disk
> > > Entry\n"));
> > > > +
> > > > +  for (Instance = 0; ; Instance++) {
> > > > +    Status = PeiServicesLocatePpi (
> > > > +               &gEfiPeiDeviceRecoveryModulePpiGuid,
> > > > +               Instance,
> > > > +               NULL,
> > > > +               (VOID **)&DeviceRecoveryPpi
> > > > +               );
> > > > +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LocateRecoveryPpi
> (%d)
> > > -
> > > >  %r\n", Instance, Status));
> > > > +    if (EFI_ERROR (Status)) {
> > > > +      if (Instance == 0) {
> > > > +        REPORT_STATUS_CODE (
> > > > +          EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> > > > +          (EFI_SOFTWARE_PEI_MODULE |
> > > > EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
> > > > +          );
> > > > +      }
> > > > +      break;
> > > > +    }
> > > > +    NumberRecoveryCapsules = 0;
> > > > +    Status = DeviceRecoveryPpi->GetNumberRecoveryCapsules (
> > > > +                                  (EFI_PEI_SERVICES **)PeiServices,
> > > > +                                  DeviceRecoveryPpi,
> > > > +                                  &NumberRecoveryCapsules
> > > > +                                  );
> > > > +    DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> > > > GetNumberRecoveryCapsules (%d) - %r\n", NumberRecoveryCapsules,
> > > > Status));
> > > > +    if (EFI_ERROR (Status)) {
> > > > +      continue;
> > > > +    }
> > > > +
> > > > +    for (CapsuleInstance = 1; CapsuleInstance <=
> > > > + NumberRecoveryCapsules;
> > > > CapsuleInstance++) {
> > > > +      CapsuleSize = 0;
> > > > +      Status = DeviceRecoveryPpi->GetRecoveryCapsuleInfo (
> > > > +                                    (EFI_PEI_SERVICES **)PeiServices,
> > > > +                                    DeviceRecoveryPpi,
> > > > +                                    CapsuleInstance,
> > > > +                                    &CapsuleSize,
> > > > +                                    &CapsuleType
> > > > +                                    );
> > > > +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> > > GetRecoveryCapsuleInfo
> > > > (%d - %x) - %r\n", CapsuleInstance, CapsuleSize, Status));
> > > > +      if (EFI_ERROR (Status)) {
> > > > +        break;
> > > > +      }
> > > > +
> > > > +      //
> > > > +      // Allocate the memory so that it gets preserved into DXE.
> > > > +      // Capsule is special because it may need to populate to system
> table
> > > > +      //
> > > > +      CapsuleBuffer = AllocateRuntimePages (EFI_SIZE_TO_PAGES
> > > > (CapsuleSize));
> > > > +
> > > > +      if (CapsuleBuffer == NULL) {
> > > > +        DEBUG ((DEBUG_ERROR, "LoadCapsuleOnDisk -
> > > > + AllocateRuntimePages
> > > > fail\n"));
> > > > +        continue;
> > > > +      }
> > > > +
> > > > +      Status = DeviceRecoveryPpi->LoadRecoveryCapsule (
> > > > +                                    (EFI_PEI_SERVICES **)PeiServices,
> > > > +                                    DeviceRecoveryPpi,
> > > > +                                    CapsuleInstance,
> > > > +                                    CapsuleBuffer
> > > > +                                    );
> > > > +      DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk -
> LoadRecoveryCapsule
> > > > (%d) - %r\n", CapsuleInstance, Status));
> > > > +      if (EFI_ERROR (Status)) {
> > > > +        FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize));
> > > > +        break;
> > > > +      }
> > > > +
> > > > +      //
> > > > +      // Capsule Update Mode, Split relocated Capsule buffer into
> > > > + different
> > > > capsule vehical hobs.
> > > > +      //
> > > > +      Status = RetrieveRelocatedCapsule(CapsuleBuffer,
> > > > + CapsuleSize);
> > > > +
> > > > +      break;
> > > > +    }
> > > > +
> > > > +    if (EFI_ERROR (Status)) {
> > > > +      REPORT_STATUS_CODE (
> > > > +        EFI_ERROR_CODE | EFI_ERROR_MAJOR,
> > > > +        (EFI_SOFTWARE_PEI_MODULE |
> > > > EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
> > > > +        );
> > > > +    }
> > > > +
> > > > +    return Status;
> > > > +  }
> > > > +
> > > > +  //
> > > > +  // Any attack against GPT, Relocation Info Variable or temp
> > > > + relocation file
> > > > will result in no Capsule HOB and return EFI_NOT_FOUND.
> > > > +  // After flow to DXE phase. since no capsule hob is detected.
> > > > + Platform will
> > > > clear Info flag and force restart.
> > > > +  // No volunerability will be exposed  //
> > > > +
> > > > +  return EFI_NOT_FOUND;
> > > > +}
> > > > diff --git
> > > >
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > inf
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > inf
> > > > new file mode 100644
> > > > index 0000000000..4af07440b7
> > > > --- /dev/null
> > > > +++
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > inf
> > > > @@ -0,0 +1,64 @@
> > > > +## @file
> > > > +# Load Capsule on Disk module.
> > > > +#
> > > > +# Load Capsule On Disk from Root Directory file system. Create CV
> > > > +hob # based on temporary Capsule On Disk file.
> > > > +#
> > > > +# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> #
> > > > +#
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> > > > +
> > > > +[Defines]
> > > > +  INF_VERSION                    = 0x00010005
> > > > +  BASE_NAME                      = CapsuleOnDiskLoadPei
> > > > +  MODULE_UNI_FILE                = CapsuleOnDiskLoadPei.uni
> > > > +  FILE_GUID                      = 8ADEDF9E-2EC8-40fb-AE56-B76D90225D2D
> > > > +  MODULE_TYPE                    = PEIM
> > > > +  VERSION_STRING                 = 1.0
> > > > +  ENTRY_POINT                    = InitializeCapsuleOnDiskLoad
> > > > +
> > > > +#
> > > > +# The following information is for reference only and not required
> > > > +by the
> > > > build tools.
> > > > +#
> > > > +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> > > > +#
> > > > +
> > > > +[Sources]
> > > > +  CapsuleOnDiskLoadPei.c
> > > > +
> > > > +[Packages]
> > > > +  MdePkg/MdePkg.dec
> > > > +  MdeModulePkg/MdeModulePkg.dec
> > > > +
> > > > +[LibraryClasses]
> > > > +  PeimEntryPoint
> > > > +  DebugLib
> > > > +  HobLib
> > > > +  BaseMemoryLib
> > > > +  MemoryAllocationLib
> > > > +  ReportStatusCodeLib
> > > > +
> > > > +[Ppis]
> > > > +  gEdkiiPeiCapsuleOnDiskPpiGuid           ## PRODUCES
> > > > +  gEfiPeiReadOnlyVariable2PpiGuid         ## CONSUMES
> > > > +  gEfiPeiBootInCapsuleOnDiskModePpiGuid   ##
> > SOMETIMES_CONSUMES
> > > > +  gEfiPeiDeviceRecoveryModulePpiGuid      ## CONSUMES
> > > > +  gPeiCapsulePpiGuid                      ## CONSUMES
> > >
> > >
> > > Suggest to use gEfiPeiCapsulePpiGuid here.
> > > gPeiCapsulePpiGuid is kept for compatibility before PI Version 1.4.
> > >
> > >
> > > > +
> > > > +[Guids]
> > > > +  gEfiCapsuleVendorGuid                   ## SOMETIMES_CONSUMES ##
> > > Variable
> > > > L"CodRelocationInfo"
> > > > +
> > > > +[Pcd]
> > > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName
> > > > ## CONSUMES
> > > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax
> ##
> > > > CONSUMES
> > > > +
> > > > +[PcdEx]
> > > > +  gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName
> > > ##
> > > > PRODUCES
> > > > +
> > > > +[depex]
> > >
> > >
> > > Minor comment:
> > > [depex] -> [Depex]
> > >
> > > Best Regards,
> > > Hao Wu
> > >
> > >
> > > > +  gEfiPeiBootInCapsuleOnD
> > > iskModePpiGuid
> > > > +
> > > > +[UserExtensions.TianoCore."ExtraFiles"]
> > > > +  CapsuleOnDiskLoadPeiExtra.uni
> > > > diff --git
> > > >
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > uni
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > uni
> > > > new file mode 100644
> > > > index 0000000000..c3eae6a5c2
> > > > --- /dev/null
> > > > +++
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.
> > > > uni
> > > > @@ -0,0 +1,15 @@
> > > > +// /** @file
> > > > +// Caspule On Disk Load module.
> > > > +//
> > > > +// Load Capsule On Disk and build CV hob.
> > > > +//
> > > > +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> > > > +// // SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > > +
> > > > +
> > > > +#string STR_MODULE_ABSTRACT             #language en-US "Caspule On
> > Disk
> > > > Load module."
> > > > +
> > > > +#string STR_MODULE_DESCRIPTION          #language en-US "Load
> > Capsule
> > > > On Disk and build CV hob."
> > > > diff --git
> > > >
> > >
> >
> a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > > > Extra.uni
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > > > Extra.uni
> > > > new file mode 100644
> > > > index 0000000000..81034f6294
> > > > --- /dev/null
> > > > +++
> > > >
> > >
> >
> b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei
> > > > Extra.uni
> > > > @@ -0,0 +1,14 @@
> > > > +// /** @file
> > > > +// CapsuleOnDiskLoadPei Localized Strings and Content // //
> > > > +Copyright
> > > > +(c) 2019, Intel Corporation. All rights reserved.<BR> // //
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent // // **/
> > > > +
> > > > +#string STR_PROPERTIES_MODULE_NAME
> > > > +#language en-US
> > > > +"CapsuleOnDiskLoad PEI Driver"
> > > > +
> > > > +
> > > > --
> > > > 2.16.2.windows.1
> > > >
> > > >
> > > >
> >
> >
> > 


^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2019-06-20  0:59 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-05 15:41 [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Xu, Wei6
2019-06-05 15:41 ` [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition Xu, Wei6
2019-06-05 21:42   ` Felix Polyudov
2019-06-12  7:48   ` Wu, Hao A
2019-06-12  8:28     ` Liming Gao
2019-06-05 15:41 ` [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition Xu, Wei6
2019-06-12  7:48   ` Wu, Hao A
2019-06-12  8:43     ` Xu, Wei6
2019-06-05 15:41 ` [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM Xu, Wei6
2019-06-12  7:49   ` Wu, Hao A
2019-06-19  8:40     ` Xu, Wei6
2019-06-19  8:59       ` Ni, Ray
2019-06-20  0:59         ` Wu, Hao A
2019-06-05 15:42 ` [edk2-devel][Patch v2 4/7] MdeModulePkg/BdsDxe: Support Capsule On Disk Xu, Wei6
2019-06-05 15:42 ` [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature Xu, Wei6
2019-06-12  7:49   ` Wu, Hao A
2019-06-19  0:41     ` Zhang, Chao B
2019-06-19  0:59       ` Wu, Hao A
2019-06-19  1:13         ` Zhang, Chao B
2019-06-19  2:22           ` Wu, Hao A
2019-06-05 15:42 ` [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule On Disk Xu, Wei6
2019-06-12  7:49   ` Wu, Hao A
2019-06-05 15:42 ` [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib Xu, Wei6
2019-06-12  7:49   ` Wu, Hao A
2019-06-19  7:55     ` Xu, Wei6
2019-06-19  8:16       ` Wu, Hao A
2019-06-19  8:19         ` Wu, Hao A
2019-06-19  8:23           ` Xu, Wei6
2019-06-05 21:53 ` [edk2-devel][Patch v2 0/7] Implement Capsule On Disk Felix Polyudov
2019-06-05 22:36   ` Michael D Kinney
2019-06-06  1:23     ` Zhang, Chao B
2019-06-12  7:47 ` Wu, Hao A
2019-06-12  8:13   ` Zhang, Chao B

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox